@hamak/ui-shell 0.5.1
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/README.md +414 -0
- package/dist/api/api/IFeatureManager.d.ts +56 -0
- package/dist/api/api/IFeatureManager.d.ts.map +1 -0
- package/dist/api/api/IFeatureManager.js +5 -0
- package/dist/api/api/ILayoutManager.d.ts +40 -0
- package/dist/api/api/ILayoutManager.d.ts.map +1 -0
- package/dist/api/api/ILayoutManager.js +5 -0
- package/dist/api/api/IRouter.d.ts +40 -0
- package/dist/api/api/IRouter.d.ts.map +1 -0
- package/dist/api/api/IRouter.js +5 -0
- package/dist/api/api/IShell.d.ts +55 -0
- package/dist/api/api/IShell.d.ts.map +1 -0
- package/dist/api/api/IShell.js +5 -0
- package/dist/api/api/IThemeManager.d.ts +36 -0
- package/dist/api/api/IThemeManager.d.ts.map +1 -0
- package/dist/api/api/IThemeManager.js +5 -0
- package/dist/api/api/index.d.ts +10 -0
- package/dist/api/api/index.d.ts.map +1 -0
- package/dist/api/api/index.js +9 -0
- package/dist/api/index.d.ts +11 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +13 -0
- package/dist/api/tokens/index.d.ts +6 -0
- package/dist/api/tokens/index.d.ts.map +1 -0
- package/dist/api/tokens/index.js +5 -0
- package/dist/api/tokens/service-tokens.d.ts +57 -0
- package/dist/api/tokens/service-tokens.d.ts.map +1 -0
- package/dist/api/tokens/service-tokens.js +56 -0
- package/dist/api/types/event-types.d.ts +14 -0
- package/dist/api/types/event-types.d.ts.map +1 -0
- package/dist/api/types/event-types.js +5 -0
- package/dist/api/types/feature-types.d.ts +26 -0
- package/dist/api/types/feature-types.d.ts.map +1 -0
- package/dist/api/types/feature-types.js +26 -0
- package/dist/api/types/index.d.ts +11 -0
- package/dist/api/types/index.d.ts.map +1 -0
- package/dist/api/types/index.js +10 -0
- package/dist/api/types/layout-types.d.ts +29 -0
- package/dist/api/types/layout-types.d.ts.map +1 -0
- package/dist/api/types/layout-types.js +5 -0
- package/dist/api/types/route-types.d.ts +22 -0
- package/dist/api/types/route-types.d.ts.map +1 -0
- package/dist/api/types/route-types.js +5 -0
- package/dist/api/types/shell-context.d.ts +34 -0
- package/dist/api/types/shell-context.d.ts.map +1 -0
- package/dist/api/types/shell-context.js +5 -0
- package/dist/api/types/theme-types.d.ts +13 -0
- package/dist/api/types/theme-types.d.ts.map +1 -0
- package/dist/api/types/theme-types.js +5 -0
- package/dist/impl/core/DefaultFeatureManager.d.ts +24 -0
- package/dist/impl/core/DefaultFeatureManager.d.ts.map +1 -0
- package/dist/impl/core/DefaultFeatureManager.js +90 -0
- package/dist/impl/core/DefaultLayoutManager.d.ts +19 -0
- package/dist/impl/core/DefaultLayoutManager.d.ts.map +1 -0
- package/dist/impl/core/DefaultLayoutManager.js +71 -0
- package/dist/impl/core/DefaultRouter.d.ts +30 -0
- package/dist/impl/core/DefaultRouter.d.ts.map +1 -0
- package/dist/impl/core/DefaultRouter.js +136 -0
- package/dist/impl/core/DefaultShell.d.ts +30 -0
- package/dist/impl/core/DefaultShell.d.ts.map +1 -0
- package/dist/impl/core/DefaultShell.js +187 -0
- package/dist/impl/core/DefaultThemeManager.d.ts +27 -0
- package/dist/impl/core/DefaultThemeManager.d.ts.map +1 -0
- package/dist/impl/core/DefaultThemeManager.js +101 -0
- package/dist/impl/core/index.d.ts +10 -0
- package/dist/impl/core/index.d.ts.map +1 -0
- package/dist/impl/core/index.js +9 -0
- package/dist/impl/index.d.ts +21 -0
- package/dist/impl/index.d.ts.map +1 -0
- package/dist/impl/index.js +41 -0
- package/dist/impl/plugin/ShellPluginFactory.d.ts +11 -0
- package/dist/impl/plugin/ShellPluginFactory.d.ts.map +1 -0
- package/dist/impl/plugin/ShellPluginFactory.js +73 -0
- package/dist/impl/plugin/index.d.ts +6 -0
- package/dist/impl/plugin/index.d.ts.map +1 -0
- package/dist/impl/plugin/index.js +5 -0
- package/dist/impl/providers/CSSVariablesThemeProvider.d.ts +16 -0
- package/dist/impl/providers/CSSVariablesThemeProvider.d.ts.map +1 -0
- package/dist/impl/providers/CSSVariablesThemeProvider.js +64 -0
- package/dist/impl/providers/HashRouterStrategy.d.ts +20 -0
- package/dist/impl/providers/HashRouterStrategy.d.ts.map +1 -0
- package/dist/impl/providers/HashRouterStrategy.js +67 -0
- package/dist/impl/providers/HistoryRouterStrategy.d.ts +21 -0
- package/dist/impl/providers/HistoryRouterStrategy.d.ts.map +1 -0
- package/dist/impl/providers/HistoryRouterStrategy.js +79 -0
- package/dist/impl/providers/LocalStorageProvider.d.ts +13 -0
- package/dist/impl/providers/LocalStorageProvider.d.ts.map +1 -0
- package/dist/impl/providers/LocalStorageProvider.js +50 -0
- package/dist/impl/providers/MemoryStorageProvider.d.ts +14 -0
- package/dist/impl/providers/MemoryStorageProvider.d.ts.map +1 -0
- package/dist/impl/providers/MemoryStorageProvider.js +29 -0
- package/dist/impl/providers/index.d.ts +10 -0
- package/dist/impl/providers/index.d.ts.map +1 -0
- package/dist/impl/providers/index.js +9 -0
- package/dist/impl/utils/index.d.ts +6 -0
- package/dist/impl/utils/index.d.ts.map +1 -0
- package/dist/impl/utils/index.js +5 -0
- package/dist/impl/utils/viewport-utils.d.ts +16 -0
- package/dist/impl/utils/viewport-utils.d.ts.map +1 -0
- package/dist/impl/utils/viewport-utils.js +52 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/spi/guards/NavigationGuard.d.ts +18 -0
- package/dist/spi/guards/NavigationGuard.d.ts.map +1 -0
- package/dist/spi/guards/NavigationGuard.js +5 -0
- package/dist/spi/guards/index.d.ts +6 -0
- package/dist/spi/guards/index.d.ts.map +1 -0
- package/dist/spi/guards/index.js +5 -0
- package/dist/spi/hooks/ShellHooks.d.ts +40 -0
- package/dist/spi/hooks/ShellHooks.d.ts.map +1 -0
- package/dist/spi/hooks/ShellHooks.js +5 -0
- package/dist/spi/hooks/index.d.ts +6 -0
- package/dist/spi/hooks/index.d.ts.map +1 -0
- package/dist/spi/hooks/index.js +5 -0
- package/dist/spi/index.d.ts +18 -0
- package/dist/spi/index.d.ts.map +1 -0
- package/dist/spi/index.js +22 -0
- package/dist/spi/providers/IRouterStrategy.d.ts +35 -0
- package/dist/spi/providers/IRouterStrategy.d.ts.map +1 -0
- package/dist/spi/providers/IRouterStrategy.js +5 -0
- package/dist/spi/providers/IStorageProvider.d.ts +27 -0
- package/dist/spi/providers/IStorageProvider.d.ts.map +1 -0
- package/dist/spi/providers/IStorageProvider.js +5 -0
- package/dist/spi/providers/ITemplateProvider.d.ts +36 -0
- package/dist/spi/providers/ITemplateProvider.d.ts.map +1 -0
- package/dist/spi/providers/ITemplateProvider.js +5 -0
- package/dist/spi/providers/IThemeProvider.d.ts +24 -0
- package/dist/spi/providers/IThemeProvider.d.ts.map +1 -0
- package/dist/spi/providers/IThemeProvider.js +5 -0
- package/dist/spi/providers/index.d.ts +9 -0
- package/dist/spi/providers/index.d.ts.map +1 -0
- package/dist/spi/providers/index.js +8 -0
- package/dist/spi/slots/LayoutSlotProvider.d.ts +31 -0
- package/dist/spi/slots/LayoutSlotProvider.d.ts.map +1 -0
- package/dist/spi/slots/LayoutSlotProvider.js +5 -0
- package/dist/spi/slots/TemplateSlot.d.ts +34 -0
- package/dist/spi/slots/TemplateSlot.d.ts.map +1 -0
- package/dist/spi/slots/TemplateSlot.js +5 -0
- package/dist/spi/slots/index.d.ts +7 -0
- package/dist/spi/slots/index.d.ts.map +1 -0
- package/dist/spi/slots/index.js +6 -0
- package/package.json +67 -0
package/README.md
ADDED
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
# UI Shell
|
|
2
|
+
|
|
3
|
+
A comprehensive application shell framework providing theme management, feature flags, routing, and layout orchestration for microkernel-based applications.
|
|
4
|
+
|
|
5
|
+
## Package Structure
|
|
6
|
+
|
|
7
|
+
This is a monorepo package containing four sub-packages following the API-SPI-IMPL pattern:
|
|
8
|
+
|
|
9
|
+
- **[@hamak/ui-shell-api](./ui-shell-api)** - Type definitions, interfaces, and service tokens
|
|
10
|
+
- **[@hamak/ui-shell-spi](./ui-shell-spi)** - Service Provider Interfaces for extensibility
|
|
11
|
+
- **[@hamak/ui-shell-impl](./ui-shell-impl)** - Concrete implementations of all services
|
|
12
|
+
- **[@hamak/ui-shell-templates](./ui-shell-templates)** - React templates, components, and hooks
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
16
|
+
### Theme Management
|
|
17
|
+
- **Dynamic theme switching** between light, dark, and system modes
|
|
18
|
+
- **LocalStorage persistence** for user preferences
|
|
19
|
+
- **System preference detection** with automatic fallback
|
|
20
|
+
- **Custom CSS variables** support
|
|
21
|
+
- **Event-driven** theme change notifications
|
|
22
|
+
|
|
23
|
+
### Feature Configuration
|
|
24
|
+
- **Feature flags** for enabling/disabling functionality
|
|
25
|
+
- **Type-safe** feature access with generic types
|
|
26
|
+
- **Subscribe to feature changes** with fine-grained listeners
|
|
27
|
+
- **Bulk feature updates** for configuration management
|
|
28
|
+
- Includes **common feature definitions** for quick setup
|
|
29
|
+
|
|
30
|
+
### Router Integration
|
|
31
|
+
- **Lazy loading** support for route components
|
|
32
|
+
- **Navigation guards** for route protection
|
|
33
|
+
- **History and hash modes** for different deployment scenarios
|
|
34
|
+
- **Route metadata** for custom data attachment
|
|
35
|
+
- **Event-driven** navigation updates
|
|
36
|
+
|
|
37
|
+
### Layout Management
|
|
38
|
+
- **Slot-based layout system** with priority ordering
|
|
39
|
+
- **Responsive breakpoints** (xs, sm, md, lg, xl, 2xl)
|
|
40
|
+
- **Viewport utilities** for responsive behavior
|
|
41
|
+
- **CSS Grid layouts** with pre-built templates
|
|
42
|
+
- **Touch detection** and device pixel ratio utilities
|
|
43
|
+
|
|
44
|
+
### Microkernel Integration
|
|
45
|
+
- **Plugin module** for seamless microkernel integration
|
|
46
|
+
- **Dependency injection** tokens for all services
|
|
47
|
+
- **Command registration** for shell operations
|
|
48
|
+
- **Event forwarding** to microkernel hooks
|
|
49
|
+
- **Service providers** for easy consumption
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Install the packages you need
|
|
55
|
+
bun add @hamak/ui-shell-api @hamak/ui-shell-impl @hamak/ui-shell-templates
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Usage
|
|
59
|
+
|
|
60
|
+
### Basic Shell Setup
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import { createShellPlugin } from '@hamak/ui-shell-impl';
|
|
64
|
+
|
|
65
|
+
const shellPlugin = createShellPlugin({
|
|
66
|
+
theme: {
|
|
67
|
+
mode: 'system', // 'light' | 'dark' | 'system'
|
|
68
|
+
cssVariables: {
|
|
69
|
+
'--primary-color': '#007bff',
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
features: {
|
|
73
|
+
'ui.sidebar': true,
|
|
74
|
+
'experimental.ssr': false,
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Register with your microkernel
|
|
79
|
+
kernel.registerPlugin(shellPlugin);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Theme Management
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { SHELL_TOKEN } from '@hamak/ui-shell-api';
|
|
86
|
+
import type { IShell } from '@hamak/ui-shell-api';
|
|
87
|
+
|
|
88
|
+
// In your plugin or component
|
|
89
|
+
const shell = context.resolve<IShell>(SHELL_TOKEN);
|
|
90
|
+
const themeManager = shell.getThemeManager();
|
|
91
|
+
|
|
92
|
+
// Set theme
|
|
93
|
+
themeManager.setTheme('dark');
|
|
94
|
+
|
|
95
|
+
// Toggle theme
|
|
96
|
+
themeManager.toggleTheme();
|
|
97
|
+
|
|
98
|
+
// Subscribe to changes
|
|
99
|
+
themeManager.subscribe((theme) => {
|
|
100
|
+
console.log('Theme changed to:', theme);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Get resolved theme (converts 'system' to actual theme)
|
|
104
|
+
const resolvedTheme = themeManager.getResolvedTheme(); // 'light' | 'dark'
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Feature Flags
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
const featureManager = shell.getFeatureManager();
|
|
111
|
+
|
|
112
|
+
// Check if enabled
|
|
113
|
+
if (featureManager.isEnabled('ui.sidebar')) {
|
|
114
|
+
// Show sidebar
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Get feature value
|
|
118
|
+
const pollingInterval = featureManager.get('performance.polling', 5000);
|
|
119
|
+
|
|
120
|
+
// Toggle feature
|
|
121
|
+
featureManager.toggle('experimental.ssr');
|
|
122
|
+
|
|
123
|
+
// Subscribe to changes
|
|
124
|
+
featureManager.subscribe('ui.sidebar', (enabled) => {
|
|
125
|
+
console.log('Sidebar:', enabled ? 'enabled' : 'disabled');
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Router Setup
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import { SHELL_TOKEN } from '@hamak/ui-shell-api';
|
|
133
|
+
|
|
134
|
+
const shell = context.resolve(SHELL_TOKEN);
|
|
135
|
+
const router = shell.setupRouter({
|
|
136
|
+
mode: 'history',
|
|
137
|
+
routes: [
|
|
138
|
+
{
|
|
139
|
+
path: '/',
|
|
140
|
+
component: () => import('./pages/Home'),
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
path: '/about',
|
|
144
|
+
component: () => import('./pages/About'),
|
|
145
|
+
meta: { title: 'About Us' },
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
path: '/dashboard',
|
|
149
|
+
component: () => import('./pages/Dashboard'),
|
|
150
|
+
beforeEnter: (to, from) => {
|
|
151
|
+
// Route guard logic
|
|
152
|
+
return isAuthenticated();
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
],
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Navigate
|
|
159
|
+
await router.push('/about');
|
|
160
|
+
|
|
161
|
+
// Subscribe to route changes
|
|
162
|
+
router.subscribe((route) => {
|
|
163
|
+
console.log('Navigated to:', route.path);
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Layout Management
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
import { SHELL_TOKEN } from '@hamak/ui-shell-api';
|
|
171
|
+
|
|
172
|
+
const shell = context.resolve(SHELL_TOKEN);
|
|
173
|
+
const layoutManager = shell.getLayoutManager();
|
|
174
|
+
|
|
175
|
+
// Register slots
|
|
176
|
+
layoutManager.registerSlot({
|
|
177
|
+
id: 'main-nav',
|
|
178
|
+
area: 'header',
|
|
179
|
+
priority: 10,
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// Get slots for an area
|
|
183
|
+
const headerSlots = layoutManager.getSlots('header');
|
|
184
|
+
|
|
185
|
+
// Responsive utilities
|
|
186
|
+
if (ViewportUtils.isMinBreakpoint('md')) {
|
|
187
|
+
// Desktop layout
|
|
188
|
+
} else {
|
|
189
|
+
// Mobile layout
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const currentBreakpoint = ViewportUtils.getCurrentBreakpoint();
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Microkernel Plugin Integration
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
import { createShellPlugin } from '@hamak/ui-shell-impl';
|
|
199
|
+
import { CommonFeatures } from '@hamak/ui-shell-api';
|
|
200
|
+
|
|
201
|
+
export const shellPlugin = createShellPlugin({
|
|
202
|
+
theme: { mode: 'system' },
|
|
203
|
+
features: {
|
|
204
|
+
'ui.sidebar': true,
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// In your plugin
|
|
209
|
+
export function initialize(ctx) {
|
|
210
|
+
// Access shell services
|
|
211
|
+
const shell = ctx.resolve(SHELL_TOKEN);
|
|
212
|
+
|
|
213
|
+
// Subscribe to theme changes
|
|
214
|
+
shell.getThemeManager().subscribe((theme) => {
|
|
215
|
+
console.log('Theme changed:', theme);
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export function activate(ctx) {
|
|
220
|
+
// Access shell services
|
|
221
|
+
const shell = ctx.resolve(SHELL_TOKEN);
|
|
222
|
+
shell.getThemeManager().setTheme('dark');
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Using React Templates
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
import { ShellProvider, DashboardLayout } from '@hamak/ui-shell-templates';
|
|
230
|
+
import { useTheme, useFeatures } from '@hamak/ui-shell-templates/hooks';
|
|
231
|
+
|
|
232
|
+
// Wrap your app with ShellProvider
|
|
233
|
+
function App() {
|
|
234
|
+
return (
|
|
235
|
+
<ShellProvider>
|
|
236
|
+
<DashboardLayout />
|
|
237
|
+
</ShellProvider>
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Use hooks in your components
|
|
242
|
+
function MyComponent() {
|
|
243
|
+
const { theme, setTheme } = useTheme();
|
|
244
|
+
const { isEnabled } = useFeatures();
|
|
245
|
+
|
|
246
|
+
return (
|
|
247
|
+
<div>
|
|
248
|
+
<button onClick={() => setTheme('dark')}>Dark Mode</button>
|
|
249
|
+
{isEnabled('ui.sidebar') && <Sidebar />}
|
|
250
|
+
</div>
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Shell Context
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
import { SHELL_TOKEN } from '@hamak/ui-shell-api';
|
|
259
|
+
|
|
260
|
+
const shell = context.resolve(SHELL_TOKEN);
|
|
261
|
+
const shellContext = shell.getContext();
|
|
262
|
+
|
|
263
|
+
// Access current theme
|
|
264
|
+
console.log('Current theme:', shellContext.theme);
|
|
265
|
+
|
|
266
|
+
// Set theme
|
|
267
|
+
shellContext.setTheme('dark');
|
|
268
|
+
|
|
269
|
+
// Check features
|
|
270
|
+
if (shellContext.isFeatureEnabled('ui.sidebar')) {
|
|
271
|
+
// ...
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Responsive info
|
|
275
|
+
if (shellContext.viewport.isMobile) {
|
|
276
|
+
// Mobile UI
|
|
277
|
+
} else if (shellContext.viewport.isDesktop) {
|
|
278
|
+
// Desktop UI
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Shell Events
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
// Subscribe to events
|
|
286
|
+
shell.on('theme:changed', (event) => {
|
|
287
|
+
console.log('Theme changed:', event.payload);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
shell.on('viewport:resized', (event) => {
|
|
291
|
+
console.log('Viewport:', event.payload.width, 'x', event.payload.height);
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
shell.on('route:changed', (event) => {
|
|
295
|
+
console.log('Navigated to:', event.payload.route.path);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
// Listen to all events
|
|
299
|
+
shell.on('*', (event) => {
|
|
300
|
+
console.log('Event:', event.type, event.payload);
|
|
301
|
+
});
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## API Reference
|
|
305
|
+
|
|
306
|
+
### Shell
|
|
307
|
+
|
|
308
|
+
Main orchestrator for the UI shell.
|
|
309
|
+
|
|
310
|
+
**Methods:**
|
|
311
|
+
- `initialize()` - Initialize the shell
|
|
312
|
+
- `setupRouter(options)` - Setup router with routes
|
|
313
|
+
- `getRouter()` - Get router instance
|
|
314
|
+
- `getThemeManager()` - Get theme manager
|
|
315
|
+
- `getFeatureManager()` - Get feature manager
|
|
316
|
+
- `getContext()` - Get shell context for consumers
|
|
317
|
+
- `on(type, listener)` - Subscribe to events
|
|
318
|
+
- `emit(type, payload)` - Emit events
|
|
319
|
+
- `destroy()` - Clean up resources
|
|
320
|
+
|
|
321
|
+
### ThemeManager
|
|
322
|
+
|
|
323
|
+
Handles theme switching and persistence.
|
|
324
|
+
|
|
325
|
+
**Methods:**
|
|
326
|
+
- `getTheme()` - Get current theme mode
|
|
327
|
+
- `getResolvedTheme()` - Get resolved theme (light/dark)
|
|
328
|
+
- `setTheme(mode)` - Set theme mode
|
|
329
|
+
- `toggleTheme()` - Toggle between light and dark
|
|
330
|
+
- `subscribe(listener)` - Subscribe to changes
|
|
331
|
+
- `setCSSVariables(vars)` - Set custom CSS variables
|
|
332
|
+
|
|
333
|
+
### FeatureManager
|
|
334
|
+
|
|
335
|
+
Manages feature flags and configurations.
|
|
336
|
+
|
|
337
|
+
**Methods:**
|
|
338
|
+
- `isEnabled(key)` - Check if feature is enabled
|
|
339
|
+
- `get(key, defaultValue)` - Get feature value
|
|
340
|
+
- `set(key, value)` - Set feature value
|
|
341
|
+
- `enable(key)` - Enable feature
|
|
342
|
+
- `disable(key)` - Disable feature
|
|
343
|
+
- `toggle(key)` - Toggle feature
|
|
344
|
+
- `subscribe(key, listener)` - Subscribe to feature changes
|
|
345
|
+
|
|
346
|
+
### Router
|
|
347
|
+
|
|
348
|
+
Handles client-side routing with lazy loading.
|
|
349
|
+
|
|
350
|
+
**Methods:**
|
|
351
|
+
- `push(path)` - Navigate to path
|
|
352
|
+
- `replace(path)` - Replace current route
|
|
353
|
+
- `back()` - Go back
|
|
354
|
+
- `forward()` - Go forward
|
|
355
|
+
- `getCurrentRoute()` - Get current route
|
|
356
|
+
- `subscribe(listener)` - Subscribe to route changes
|
|
357
|
+
- `addGuard(guard)` - Add navigation guard
|
|
358
|
+
|
|
359
|
+
### LayoutManager
|
|
360
|
+
|
|
361
|
+
Manages layout slots and areas.
|
|
362
|
+
|
|
363
|
+
**Methods:**
|
|
364
|
+
- `registerSlot(slot)` - Register a layout slot
|
|
365
|
+
- `unregisterSlot(slot)` - Unregister a slot
|
|
366
|
+
- `getSlots(area)` - Get slots for area
|
|
367
|
+
- `getAreas()` - Get all registered areas
|
|
368
|
+
- `hasSlots(area)` - Check if area has slots
|
|
369
|
+
|
|
370
|
+
## Architecture
|
|
371
|
+
|
|
372
|
+
The UI Shell is designed to integrate seamlessly with the microkernel architecture:
|
|
373
|
+
|
|
374
|
+
1. **Core Services**: Theme, Features, Router, Layout
|
|
375
|
+
2. **Plugin Integration**: Provides services via DI tokens
|
|
376
|
+
3. **Event System**: Forwards events to microkernel hooks
|
|
377
|
+
4. **Commands**: Registers shell commands for cross-plugin use
|
|
378
|
+
5. **Context API**: Provides reactive access to shell state
|
|
379
|
+
|
|
380
|
+
## Common Patterns
|
|
381
|
+
|
|
382
|
+
### Responsive Layouts
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
import { useViewport } from '@hamak/ui-shell-templates/hooks';
|
|
386
|
+
|
|
387
|
+
// In React components
|
|
388
|
+
function MyComponent() {
|
|
389
|
+
const { isMobile, isDesktop, breakpoint } = useViewport();
|
|
390
|
+
|
|
391
|
+
return isMobile ? <MobileLayout /> : <DesktopLayout />;
|
|
392
|
+
}
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### Feature Gating
|
|
396
|
+
|
|
397
|
+
```typescript
|
|
398
|
+
import { CommonFeatures } from '@hamak/ui-shell-api';
|
|
399
|
+
import { useFeatures } from '@hamak/ui-shell-templates/hooks';
|
|
400
|
+
|
|
401
|
+
function MyComponent() {
|
|
402
|
+
const { isEnabled } = useFeatures();
|
|
403
|
+
|
|
404
|
+
return (
|
|
405
|
+
<div>
|
|
406
|
+
{isEnabled(CommonFeatures.VOICE_MODE) && <VoiceInput />}
|
|
407
|
+
</div>
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
## License
|
|
413
|
+
|
|
414
|
+
MIT
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature Manager Interface
|
|
3
|
+
* Public API contract for feature flag management
|
|
4
|
+
*/
|
|
5
|
+
import type { FeatureFlags } from '../types';
|
|
6
|
+
export interface IFeatureManager {
|
|
7
|
+
/**
|
|
8
|
+
* Check if a feature is enabled (boolean features)
|
|
9
|
+
*/
|
|
10
|
+
isEnabled(key: string): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Get a feature value with optional default
|
|
13
|
+
*/
|
|
14
|
+
get<T = any>(key: string, defaultValue?: T): T;
|
|
15
|
+
/**
|
|
16
|
+
* Set a feature value
|
|
17
|
+
*/
|
|
18
|
+
set(key: string, value: any): void;
|
|
19
|
+
/**
|
|
20
|
+
* Enable a feature (set to true)
|
|
21
|
+
*/
|
|
22
|
+
enable(key: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* Disable a feature (set to false)
|
|
25
|
+
*/
|
|
26
|
+
disable(key: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* Toggle a boolean feature
|
|
29
|
+
*/
|
|
30
|
+
toggle(key: string): void;
|
|
31
|
+
/**
|
|
32
|
+
* Update multiple features at once
|
|
33
|
+
*/
|
|
34
|
+
update(updates: FeatureFlags): void;
|
|
35
|
+
/**
|
|
36
|
+
* Get all features
|
|
37
|
+
*/
|
|
38
|
+
getAll(): Readonly<FeatureFlags>;
|
|
39
|
+
/**
|
|
40
|
+
* Check if a feature exists
|
|
41
|
+
*/
|
|
42
|
+
has(key: string): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Subscribe to feature changes
|
|
45
|
+
*/
|
|
46
|
+
subscribe(key: string, listener: (value: any) => void): () => void;
|
|
47
|
+
/**
|
|
48
|
+
* Subscribe to all feature changes
|
|
49
|
+
*/
|
|
50
|
+
subscribeAll(listener: (key: string, value: any) => void): () => void;
|
|
51
|
+
/**
|
|
52
|
+
* Clean up resources
|
|
53
|
+
*/
|
|
54
|
+
destroy(): void;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=IFeatureManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IFeatureManager.d.ts","sourceRoot":"","sources":["../../../src/api/api/IFeatureManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAEhC;;OAEG;IACH,GAAG,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAE/C;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI,CAAC;IAEnC;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAE1B;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3B;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAE1B;;OAEG;IACH,MAAM,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;IAEpC;;OAEG;IACH,MAAM,IAAI,QAAQ,CAAC,YAAY,CAAC,CAAC;IAEjC;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAE1B;;OAEG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAEnE;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAEtE;;OAEG;IACH,OAAO,IAAI,IAAI,CAAC;CACjB"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layout Manager Interface
|
|
3
|
+
* Public API contract for layout management
|
|
4
|
+
*/
|
|
5
|
+
import type { LayoutSlot, LayoutArea } from '../types';
|
|
6
|
+
export interface ILayoutManager {
|
|
7
|
+
/**
|
|
8
|
+
* Register a layout slot
|
|
9
|
+
*/
|
|
10
|
+
registerSlot(slot: LayoutSlot): () => void;
|
|
11
|
+
/**
|
|
12
|
+
* Unregister a layout slot
|
|
13
|
+
*/
|
|
14
|
+
unregisterSlot(slot: LayoutSlot): void;
|
|
15
|
+
/**
|
|
16
|
+
* Get all slots for an area
|
|
17
|
+
*/
|
|
18
|
+
getSlots(area: LayoutArea): LayoutSlot[];
|
|
19
|
+
/**
|
|
20
|
+
* Get all registered areas
|
|
21
|
+
*/
|
|
22
|
+
getAreas(): LayoutArea[];
|
|
23
|
+
/**
|
|
24
|
+
* Check if an area has any slots
|
|
25
|
+
*/
|
|
26
|
+
hasSlots(area: LayoutArea): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Subscribe to layout changes
|
|
29
|
+
*/
|
|
30
|
+
subscribe(listener: () => void): () => void;
|
|
31
|
+
/**
|
|
32
|
+
* Clear all slots
|
|
33
|
+
*/
|
|
34
|
+
clear(): void;
|
|
35
|
+
/**
|
|
36
|
+
* Clean up resources
|
|
37
|
+
*/
|
|
38
|
+
destroy(): void;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=ILayoutManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ILayoutManager.d.ts","sourceRoot":"","sources":["../../../src/api/api/ILayoutManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEvD,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,IAAI,CAAC;IAE3C;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IAEvC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,EAAE,CAAC;IAEzC;;OAEG;IACH,QAAQ,IAAI,UAAU,EAAE,CAAC;IAEzB;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC;IAEpC;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IAE5C;;OAEG;IACH,KAAK,IAAI,IAAI,CAAC;IAEd;;OAEG;IACH,OAAO,IAAI,IAAI,CAAC;CACjB"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Router Interface
|
|
3
|
+
* Public API contract for routing
|
|
4
|
+
*/
|
|
5
|
+
import type { RouteConfig } from '../types';
|
|
6
|
+
export interface IRouter {
|
|
7
|
+
/**
|
|
8
|
+
* Navigate to a path
|
|
9
|
+
*/
|
|
10
|
+
push(path: string): Promise<boolean>;
|
|
11
|
+
/**
|
|
12
|
+
* Replace current route
|
|
13
|
+
*/
|
|
14
|
+
replace(path: string): Promise<boolean>;
|
|
15
|
+
/**
|
|
16
|
+
* Go back in history
|
|
17
|
+
*/
|
|
18
|
+
back(): void;
|
|
19
|
+
/**
|
|
20
|
+
* Go forward in history
|
|
21
|
+
*/
|
|
22
|
+
forward(): void;
|
|
23
|
+
/**
|
|
24
|
+
* Get current route
|
|
25
|
+
*/
|
|
26
|
+
getCurrentRoute(): RouteConfig | null;
|
|
27
|
+
/**
|
|
28
|
+
* Subscribe to route changes
|
|
29
|
+
*/
|
|
30
|
+
subscribe(listener: (route: RouteConfig) => void): () => void;
|
|
31
|
+
/**
|
|
32
|
+
* Load a route component (lazy loading)
|
|
33
|
+
*/
|
|
34
|
+
loadRouteComponent(route: RouteConfig): Promise<any>;
|
|
35
|
+
/**
|
|
36
|
+
* Clean up resources
|
|
37
|
+
*/
|
|
38
|
+
destroy(): void;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=IRouter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IRouter.d.ts","sourceRoot":"","sources":["../../../src/api/api/IRouter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,WAAW,OAAO;IACtB;;OAEG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAErC;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAExC;;OAEG;IACH,IAAI,IAAI,IAAI,CAAC;IAEb;;OAEG;IACH,OAAO,IAAI,IAAI,CAAC;IAEhB;;OAEG;IACH,eAAe,IAAI,WAAW,GAAG,IAAI,CAAC;IAEtC;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAE9D;;OAEG;IACH,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAErD;;OAEG;IACH,OAAO,IAAI,IAAI,CAAC;CACjB"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell Interface
|
|
3
|
+
* Public API contract for the UI Shell
|
|
4
|
+
*/
|
|
5
|
+
import type { ShellConfig, ShellContext, ShellEventListener, ShellEventType } from '../types';
|
|
6
|
+
import type { IThemeManager } from './IThemeManager';
|
|
7
|
+
import type { IFeatureManager } from './IFeatureManager';
|
|
8
|
+
import type { IRouter } from './IRouter';
|
|
9
|
+
export interface IShell {
|
|
10
|
+
/**
|
|
11
|
+
* Initialize the shell
|
|
12
|
+
*/
|
|
13
|
+
initialize(): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Get shell context for consumers
|
|
16
|
+
*/
|
|
17
|
+
getContext(): ShellContext;
|
|
18
|
+
/**
|
|
19
|
+
* Get theme manager
|
|
20
|
+
*/
|
|
21
|
+
getThemeManager(): IThemeManager;
|
|
22
|
+
/**
|
|
23
|
+
* Get feature manager
|
|
24
|
+
*/
|
|
25
|
+
getFeatureManager(): IFeatureManager;
|
|
26
|
+
/**
|
|
27
|
+
* Get router instance
|
|
28
|
+
*/
|
|
29
|
+
getRouter(): IRouter | null;
|
|
30
|
+
/**
|
|
31
|
+
* Emit a shell event
|
|
32
|
+
*/
|
|
33
|
+
emit(type: ShellEventType, payload?: any): void;
|
|
34
|
+
/**
|
|
35
|
+
* Subscribe to shell events
|
|
36
|
+
*/
|
|
37
|
+
on(type: ShellEventType | '*', listener: ShellEventListener): () => void;
|
|
38
|
+
/**
|
|
39
|
+
* Unsubscribe from shell events
|
|
40
|
+
*/
|
|
41
|
+
off(type: ShellEventType | '*', listener: ShellEventListener): void;
|
|
42
|
+
/**
|
|
43
|
+
* Check if shell is ready
|
|
44
|
+
*/
|
|
45
|
+
ready(): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Get configuration
|
|
48
|
+
*/
|
|
49
|
+
getConfig(): Readonly<ShellConfig>;
|
|
50
|
+
/**
|
|
51
|
+
* Clean up resources
|
|
52
|
+
*/
|
|
53
|
+
destroy(): void;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=IShell.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IShell.d.ts","sourceRoot":"","sources":["../../../src/api/api/IShell.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC9F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,WAAW,MAAM;IACrB;;OAEG;IACH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B;;OAEG;IACH,UAAU,IAAI,YAAY,CAAC;IAE3B;;OAEG;IACH,eAAe,IAAI,aAAa,CAAC;IAEjC;;OAEG;IACH,iBAAiB,IAAI,eAAe,CAAC;IAErC;;OAEG;IACH,SAAS,IAAI,OAAO,GAAG,IAAI,CAAC;IAE5B;;OAEG;IACH,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;IAEhD;;OAEG;IACH,EAAE,CAAC,IAAI,EAAE,cAAc,GAAG,GAAG,EAAE,QAAQ,EAAE,kBAAkB,GAAG,MAAM,IAAI,CAAC;IAEzE;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,GAAG,EAAE,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAEpE;;OAEG;IACH,KAAK,IAAI,OAAO,CAAC;IAEjB;;OAEG;IACH,SAAS,IAAI,QAAQ,CAAC,WAAW,CAAC,CAAC;IAEnC;;OAEG;IACH,OAAO,IAAI,IAAI,CAAC;CACjB"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Manager Interface
|
|
3
|
+
* Public API contract for theme management
|
|
4
|
+
*/
|
|
5
|
+
import type { ThemeMode } from '../types';
|
|
6
|
+
export interface IThemeManager {
|
|
7
|
+
/**
|
|
8
|
+
* Get the current theme mode
|
|
9
|
+
*/
|
|
10
|
+
getTheme(): ThemeMode;
|
|
11
|
+
/**
|
|
12
|
+
* Get the resolved theme (converts 'system' to actual theme)
|
|
13
|
+
*/
|
|
14
|
+
getResolvedTheme(): 'light' | 'dark';
|
|
15
|
+
/**
|
|
16
|
+
* Set the theme mode
|
|
17
|
+
*/
|
|
18
|
+
setTheme(mode: ThemeMode): void;
|
|
19
|
+
/**
|
|
20
|
+
* Toggle between light and dark themes
|
|
21
|
+
*/
|
|
22
|
+
toggleTheme(): void;
|
|
23
|
+
/**
|
|
24
|
+
* Subscribe to theme changes
|
|
25
|
+
*/
|
|
26
|
+
subscribe(listener: (theme: ThemeMode) => void): () => void;
|
|
27
|
+
/**
|
|
28
|
+
* Apply custom CSS variables
|
|
29
|
+
*/
|
|
30
|
+
setCSSVariables(variables: Record<string, string>): void;
|
|
31
|
+
/**
|
|
32
|
+
* Clean up resources
|
|
33
|
+
*/
|
|
34
|
+
destroy(): void;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=IThemeManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IThemeManager.d.ts","sourceRoot":"","sources":["../../../src/api/api/IThemeManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,QAAQ,IAAI,SAAS,CAAC;IAEtB;;OAEG;IACH,gBAAgB,IAAI,OAAO,GAAG,MAAM,CAAC;IAErC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;IAEhC;;OAEG;IACH,WAAW,IAAI,IAAI,CAAC;IAEpB;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAE5D;;OAEG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IAEzD;;OAEG;IACH,OAAO,IAAI,IAAI,CAAC;CACjB"}
|