@integrativedesigndevelopment/dashboard-core 0.0.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.
- package/README.md +775 -0
- package/dist/actions/pluginActions.d.ts +48 -0
- package/dist/actions/pluginActions.d.ts.map +1 -0
- package/dist/actions/types.d.ts +17 -0
- package/dist/actions/types.d.ts.map +1 -0
- package/dist/components/ActivityProvider/index.d.ts +10 -0
- package/dist/components/ActivityProvider/index.d.ts.map +1 -0
- package/dist/components/CancelActionButton/index.d.ts +11 -0
- package/dist/components/CancelActionButton/index.d.ts.map +1 -0
- package/dist/components/ConfirmActionButton/index.d.ts +12 -0
- package/dist/components/ConfirmActionButton/index.d.ts.map +1 -0
- package/dist/components/ErrorBoundary/index.d.ts +18 -0
- package/dist/components/ErrorBoundary/index.d.ts.map +1 -0
- package/dist/components/IDDLink/index.d.ts +10 -0
- package/dist/components/IDDLink/index.d.ts.map +1 -0
- package/dist/components/IDDLinkInputItem/index.d.ts +18 -0
- package/dist/components/IDDLinkInputItem/index.d.ts.map +1 -0
- package/dist/components/Layout/SimpleLayout.d.ts +8 -0
- package/dist/components/Layout/SimpleLayout.d.ts.map +1 -0
- package/dist/components/Layout/index.d.ts +8 -0
- package/dist/components/Layout/index.d.ts.map +1 -0
- package/dist/components/Password/index.d.ts +15 -0
- package/dist/components/Password/index.d.ts.map +1 -0
- package/dist/components/SimpleButton/index.d.ts +10 -0
- package/dist/components/SimpleButton/index.d.ts.map +1 -0
- package/dist/components/TextInput/index.d.ts +16 -0
- package/dist/components/TextInput/index.d.ts.map +1 -0
- package/dist/components/helpers.d.ts +5 -0
- package/dist/components/helpers.d.ts.map +1 -0
- package/dist/components/index.d.ts +16 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/config/index.d.ts +23 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/hooks/index.d.ts +3 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/useAsyncOperation.d.ts +12 -0
- package/dist/hooks/useAsyncOperation.d.ts.map +1 -0
- package/dist/hooks/useUpdateUser.d.ts +32 -0
- package/dist/hooks/useUpdateUser.d.ts.map +1 -0
- package/dist/hooks/useUserManagement.d.ts +51 -0
- package/dist/hooks/useUserManagement.d.ts.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.js +14 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/metrics/clsMetrics.d.ts +3 -0
- package/dist/metrics/clsMetrics.d.ts.map +1 -0
- package/dist/metrics/fcpMetrics.d.ts +3 -0
- package/dist/metrics/fcpMetrics.d.ts.map +1 -0
- package/dist/metrics/fidMetrics.d.ts +3 -0
- package/dist/metrics/fidMetrics.d.ts.map +1 -0
- package/dist/metrics/index.d.ts +3 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/lcpMetrics.d.ts +3 -0
- package/dist/metrics/lcpMetrics.d.ts.map +1 -0
- package/dist/metrics/ttfbMetrics.d.ts +3 -0
- package/dist/metrics/ttfbMetrics.d.ts.map +1 -0
- package/dist/plugin-system/DashboardProvider.d.ts +14 -0
- package/dist/plugin-system/DashboardProvider.d.ts.map +1 -0
- package/dist/plugin-system/PluginManager.d.ts +9 -0
- package/dist/plugin-system/PluginManager.d.ts.map +1 -0
- package/dist/plugin-system/core/Dashboard/Icon.d.ts +6 -0
- package/dist/plugin-system/core/Dashboard/Icon.d.ts.map +1 -0
- package/dist/plugin-system/core/Dashboard/index.d.ts +4 -0
- package/dist/plugin-system/core/Dashboard/index.d.ts.map +1 -0
- package/dist/plugin-system/core/Dashboard/tab0.d.ts +8 -0
- package/dist/plugin-system/core/Dashboard/tab0.d.ts.map +1 -0
- package/dist/plugin-system/core/Dashboard/views/DashboardView/index.d.ts +3 -0
- package/dist/plugin-system/core/Dashboard/views/DashboardView/index.d.ts.map +1 -0
- package/dist/plugin-system/index.d.ts +6 -0
- package/dist/plugin-system/index.d.ts.map +1 -0
- package/dist/plugin-system/plugin_manifest.d.ts +2 -0
- package/dist/plugin-system/plugin_manifest.d.ts.map +1 -0
- package/dist/plugin-system/types.d.ts +76 -0
- package/dist/plugin-system/types.d.ts.map +1 -0
- package/dist/services/errorServices.d.ts +37 -0
- package/dist/services/errorServices.d.ts.map +1 -0
- package/dist/types/index.d.ts +66 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/utils/array-safety.d.ts +32 -0
- package/dist/utils/array-safety.d.ts.map +1 -0
- package/dist/utils/fromReq.d.ts +3 -0
- package/dist/utils/fromReq.d.ts.map +1 -0
- package/dist/utils/helpers.d.ts +27 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,775 @@
|
|
|
1
|
+
# @integrativedesigndevelopment/dashboard-core
|
|
2
|
+
|
|
3
|
+
The foundational package for IDD Dashboard providing core components, plugin system, state management, and essential utilities.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@integrativedesigndevelopment/dashboard-core)
|
|
6
|
+
|
|
7
|
+
## 🚀 Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @integrativedesigndevelopment/dashboard-core
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```jsx
|
|
14
|
+
import {
|
|
15
|
+
DashboardProvider,
|
|
16
|
+
SimpleButton,
|
|
17
|
+
} from '@integrativedesigndevelopment/dashboard-core';
|
|
18
|
+
|
|
19
|
+
function App() {
|
|
20
|
+
return (
|
|
21
|
+
<DashboardProvider>
|
|
22
|
+
<SimpleButton onClick={() => alert('Hello!')}>Click me</SimpleButton>
|
|
23
|
+
</DashboardProvider>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 📦 What's Included
|
|
29
|
+
|
|
30
|
+
### Core Components
|
|
31
|
+
|
|
32
|
+
- **SimpleButton** - Styled button component
|
|
33
|
+
- **DashboardProvider** - Global state provider
|
|
34
|
+
- **ErrorBoundary** - Error handling wrapper
|
|
35
|
+
|
|
36
|
+
### Plugin System
|
|
37
|
+
|
|
38
|
+
- **PluginManager** - Plugin lifecycle management
|
|
39
|
+
- **get_all_plugins** - Plugin discovery utility
|
|
40
|
+
- **useDashboard** - Dashboard context hook
|
|
41
|
+
|
|
42
|
+
### State Management
|
|
43
|
+
|
|
44
|
+
- **Actions** - Redux actions for plugins and notifications
|
|
45
|
+
- **Hooks** - Custom React hooks for common operations
|
|
46
|
+
|
|
47
|
+
### Utilities
|
|
48
|
+
|
|
49
|
+
- **Array Safety** - Safe array operations
|
|
50
|
+
- **Helpers** - Common utility functions
|
|
51
|
+
- **Metrics** - Performance tracking utilities
|
|
52
|
+
|
|
53
|
+
### Services
|
|
54
|
+
|
|
55
|
+
- **Error Services** - Centralized error handling
|
|
56
|
+
|
|
57
|
+
## 🔧 Installation
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# npm
|
|
61
|
+
npm install @integrativedesigndevelopment/dashboard-core
|
|
62
|
+
|
|
63
|
+
# yarn
|
|
64
|
+
yarn add @integrativedesigndevelopment/dashboard-core
|
|
65
|
+
|
|
66
|
+
# pnpm
|
|
67
|
+
pnpm add @integrativedesigndevelopment/dashboard-core
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Peer Dependencies
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npm install react@^18.0.0 react-dom@^18.0.0
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## 📖 API Reference
|
|
77
|
+
|
|
78
|
+
### DashboardProvider
|
|
79
|
+
|
|
80
|
+
The main provider component that wraps your entire dashboard application.
|
|
81
|
+
|
|
82
|
+
```jsx
|
|
83
|
+
import { DashboardProvider } from '@integrativedesigndevelopment/dashboard-core';
|
|
84
|
+
|
|
85
|
+
function App() {
|
|
86
|
+
return (
|
|
87
|
+
<DashboardProvider
|
|
88
|
+
config={{
|
|
89
|
+
theme: 'light',
|
|
90
|
+
plugins: ['Dashboard', 'Content'],
|
|
91
|
+
apiEndpoint: '/api',
|
|
92
|
+
}}
|
|
93
|
+
initialState={{
|
|
94
|
+
user: null,
|
|
95
|
+
notifications: [],
|
|
96
|
+
}}>
|
|
97
|
+
<YourDashboard />
|
|
98
|
+
</DashboardProvider>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Props:**
|
|
104
|
+
|
|
105
|
+
- `config?: DashboardConfig` - Dashboard configuration
|
|
106
|
+
- `initialState?: Partial<DashboardState>` - Initial Redux state
|
|
107
|
+
- `children: React.ReactNode` - Child components
|
|
108
|
+
|
|
109
|
+
### useDashboard Hook
|
|
110
|
+
|
|
111
|
+
Access dashboard state and utilities throughout your app.
|
|
112
|
+
|
|
113
|
+
```jsx
|
|
114
|
+
import { useDashboard } from '@integrativedesigndevelopment/dashboard-core';
|
|
115
|
+
|
|
116
|
+
function MyComponent() {
|
|
117
|
+
const {
|
|
118
|
+
state, // Current dashboard state
|
|
119
|
+
dispatch, // Redux dispatch function
|
|
120
|
+
plugins, // Available plugins
|
|
121
|
+
config, // Dashboard configuration
|
|
122
|
+
notifications, // Current notifications
|
|
123
|
+
} = useDashboard();
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<div>
|
|
127
|
+
<h1>Active Plugins: {plugins.length}</h1>
|
|
128
|
+
<p>Notifications: {notifications.length}</p>
|
|
129
|
+
</div>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### PluginManager
|
|
135
|
+
|
|
136
|
+
Manages plugin lifecycle and registration.
|
|
137
|
+
|
|
138
|
+
```jsx
|
|
139
|
+
import { PluginManager } from '@integrativedesigndevelopment/dashboard-core';
|
|
140
|
+
|
|
141
|
+
const pluginManager = new PluginManager({
|
|
142
|
+
plugins: [MyPlugin, AnotherPlugin],
|
|
143
|
+
config: {
|
|
144
|
+
autoLoad: true,
|
|
145
|
+
enableHotReload: true,
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Register a new plugin
|
|
150
|
+
pluginManager.register(NewPlugin);
|
|
151
|
+
|
|
152
|
+
// Get all active plugins
|
|
153
|
+
const activePlugins = pluginManager.getActivePlugins();
|
|
154
|
+
|
|
155
|
+
// Unregister a plugin
|
|
156
|
+
pluginManager.unregister('plugin-id');
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### SimpleButton
|
|
160
|
+
|
|
161
|
+
A styled button component following IDD design system.
|
|
162
|
+
|
|
163
|
+
```jsx
|
|
164
|
+
import { SimpleButton } from '@integrativedesigndevelopment/dashboard-core';
|
|
165
|
+
|
|
166
|
+
function MyComponent() {
|
|
167
|
+
return (
|
|
168
|
+
<SimpleButton
|
|
169
|
+
variant="primary"
|
|
170
|
+
size="medium"
|
|
171
|
+
disabled={false}
|
|
172
|
+
loading={false}
|
|
173
|
+
onClick={() => console.log('Clicked!')}
|
|
174
|
+
className="custom-class">
|
|
175
|
+
Click Me
|
|
176
|
+
</SimpleButton>
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Props:**
|
|
182
|
+
|
|
183
|
+
- `variant?: 'primary' | 'secondary' | 'danger' | 'ghost'` - Button style variant
|
|
184
|
+
- `size?: 'small' | 'medium' | 'large'` - Button size
|
|
185
|
+
- `disabled?: boolean` - Disabled state
|
|
186
|
+
- `loading?: boolean` - Loading state with spinner
|
|
187
|
+
- `onClick?: () => void` - Click handler
|
|
188
|
+
- `className?: string` - Additional CSS classes
|
|
189
|
+
- `children: React.ReactNode` - Button content
|
|
190
|
+
|
|
191
|
+
## 🔌 Plugin System
|
|
192
|
+
|
|
193
|
+
### Creating a Plugin
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
import { IDDPlugin } from '@integrativedesigndevelopment/dashboard-core';
|
|
197
|
+
|
|
198
|
+
const MyPlugin: IDDPlugin = {
|
|
199
|
+
id: 'my-plugin',
|
|
200
|
+
name: 'My Plugin',
|
|
201
|
+
version: '0.0.1',
|
|
202
|
+
order: 10,
|
|
203
|
+
tabs: [
|
|
204
|
+
{
|
|
205
|
+
id: 'main',
|
|
206
|
+
name: 'Main',
|
|
207
|
+
content: <MyPluginContent />,
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
dashboardWidget: <MyWidget />,
|
|
211
|
+
settings: [
|
|
212
|
+
{
|
|
213
|
+
key: 'enabled',
|
|
214
|
+
label: 'Enable Plugin',
|
|
215
|
+
type: 'toggle',
|
|
216
|
+
defaultValue: true,
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
onLoad: () => console.log('Plugin loaded'),
|
|
220
|
+
onUnload: () => console.log('Plugin unloaded'),
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
export default MyPlugin;
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Plugin Interface
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
interface IDDPlugin {
|
|
230
|
+
id: string; // Unique plugin identifier
|
|
231
|
+
name: string; // Display name
|
|
232
|
+
version?: string; // Plugin version
|
|
233
|
+
order?: number; // Sidebar order (lower = higher)
|
|
234
|
+
icon?: React.ComponentType; // Custom icon component
|
|
235
|
+
tabs?: IDDPluginTab[]; // Plugin tabs
|
|
236
|
+
dashboardWidget?: React.ReactNode; // Dashboard widget
|
|
237
|
+
settings?: IDDPluginSetting[]; // Plugin settings
|
|
238
|
+
notifications?: IDDPluginNotification[]; // Plugin notifications
|
|
239
|
+
exports?: IDDPluginExport[]; // Exportable data
|
|
240
|
+
onLoad?: () => void; // Load callback
|
|
241
|
+
onUnload?: () => void; // Unload callback
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Plugin Discovery
|
|
246
|
+
|
|
247
|
+
```jsx
|
|
248
|
+
import { get_all_plugins } from '@integrativedesigndevelopment/dashboard-core';
|
|
249
|
+
|
|
250
|
+
// Get all available plugins
|
|
251
|
+
const plugins = get_all_plugins();
|
|
252
|
+
|
|
253
|
+
// Filter plugins by criteria
|
|
254
|
+
const activePlugins = plugins.filter((plugin) => plugin.enabled);
|
|
255
|
+
|
|
256
|
+
// Get plugin by ID
|
|
257
|
+
const specificPlugin = plugins.find((plugin) => plugin.id === 'my-plugin');
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## 🎯 State Management
|
|
261
|
+
|
|
262
|
+
### Actions
|
|
263
|
+
|
|
264
|
+
```jsx
|
|
265
|
+
import { ActionTypes } from '@integrativedesigndevelopment/dashboard-core';
|
|
266
|
+
|
|
267
|
+
// Plugin actions
|
|
268
|
+
dispatch({
|
|
269
|
+
type: ActionTypes.LOAD_PLUGIN,
|
|
270
|
+
payload: { pluginId: 'my-plugin' },
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
dispatch({
|
|
274
|
+
type: ActionTypes.UNLOAD_PLUGIN,
|
|
275
|
+
payload: { pluginId: 'my-plugin' },
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// Notification actions
|
|
279
|
+
dispatch({
|
|
280
|
+
type: ActionTypes.ADD_NOTIFICATION,
|
|
281
|
+
payload: {
|
|
282
|
+
id: 'notif-1',
|
|
283
|
+
title: 'Success',
|
|
284
|
+
message: 'Operation completed',
|
|
285
|
+
type: 'success',
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Custom Hooks
|
|
291
|
+
|
|
292
|
+
```jsx
|
|
293
|
+
import {
|
|
294
|
+
useAsyncOperation,
|
|
295
|
+
useDeleteUsers,
|
|
296
|
+
useGetUsers,
|
|
297
|
+
useUpdateUser,
|
|
298
|
+
} from '@integrativedesigndevelopment/dashboard-core';
|
|
299
|
+
|
|
300
|
+
function UserManagement() {
|
|
301
|
+
// Async operation with loading state
|
|
302
|
+
const { execute, loading, error } = useAsyncOperation(async (userId) => {
|
|
303
|
+
return await api.deleteUser(userId);
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
// User management hooks
|
|
307
|
+
const { users, loading: usersLoading } = useGetUsers();
|
|
308
|
+
const { updateUser } = useUpdateUser();
|
|
309
|
+
const { deleteUser } = useDeleteUsers();
|
|
310
|
+
|
|
311
|
+
return (
|
|
312
|
+
<div>
|
|
313
|
+
{usersLoading ? (
|
|
314
|
+
<div>Loading users...</div>
|
|
315
|
+
) : (
|
|
316
|
+
users.map((user) => (
|
|
317
|
+
<div key={user.id}>
|
|
318
|
+
<span>{user.name}</span>
|
|
319
|
+
<button onClick={() => updateUser(user.id, { active: false })}>
|
|
320
|
+
Deactivate
|
|
321
|
+
</button>
|
|
322
|
+
<button onClick={() => deleteUser(user.id)}>Delete</button>
|
|
323
|
+
</div>
|
|
324
|
+
))
|
|
325
|
+
)}
|
|
326
|
+
</div>
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## 📊 Metrics System
|
|
332
|
+
|
|
333
|
+
### Performance Tracking
|
|
334
|
+
|
|
335
|
+
```jsx
|
|
336
|
+
import {
|
|
337
|
+
trackCLS,
|
|
338
|
+
trackFCP,
|
|
339
|
+
trackFID,
|
|
340
|
+
trackLCP,
|
|
341
|
+
trackTTFB,
|
|
342
|
+
} from '@integrativedesigndevelopment/dashboard-core';
|
|
343
|
+
|
|
344
|
+
// Track Core Web Vitals
|
|
345
|
+
trackCLS((metric) => {
|
|
346
|
+
console.log('Cumulative Layout Shift:', metric);
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
trackFCP((metric) => {
|
|
350
|
+
console.log('First Contentful Paint:', metric);
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
trackFID((metric) => {
|
|
354
|
+
console.log('First Input Delay:', metric);
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
trackLCP((metric) => {
|
|
358
|
+
console.log('Largest Contentful Paint:', metric);
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
trackTTFB((metric) => {
|
|
362
|
+
console.log('Time to First Byte:', metric);
|
|
363
|
+
});
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Custom Metrics
|
|
367
|
+
|
|
368
|
+
```jsx
|
|
369
|
+
import { trackCustomMetric } from '@integrativedesigndevelopment/dashboard-core';
|
|
370
|
+
|
|
371
|
+
// Track custom events
|
|
372
|
+
trackCustomMetric('plugin-load-time', {
|
|
373
|
+
pluginId: 'my-plugin',
|
|
374
|
+
loadTime: performance.now() - startTime,
|
|
375
|
+
timestamp: Date.now(),
|
|
376
|
+
});
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## 🛠 Utilities
|
|
380
|
+
|
|
381
|
+
### Array Safety
|
|
382
|
+
|
|
383
|
+
```jsx
|
|
384
|
+
import {
|
|
385
|
+
safeArray,
|
|
386
|
+
safeMap,
|
|
387
|
+
safeFilter,
|
|
388
|
+
} from '@integrativedesigndevelopment/dashboard-core';
|
|
389
|
+
|
|
390
|
+
// Safe array operations that handle null/undefined
|
|
391
|
+
const items = safeArray(possiblyNullArray);
|
|
392
|
+
const mapped = safeMap(items, (item) => item.name);
|
|
393
|
+
const filtered = safeFilter(items, (item) => item.active);
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Helpers
|
|
397
|
+
|
|
398
|
+
```jsx
|
|
399
|
+
import {
|
|
400
|
+
debounce,
|
|
401
|
+
throttle,
|
|
402
|
+
deepMerge,
|
|
403
|
+
formatDate,
|
|
404
|
+
generateId,
|
|
405
|
+
} from '@integrativedesigndevelopment/dashboard-core';
|
|
406
|
+
|
|
407
|
+
// Debounce function calls
|
|
408
|
+
const debouncedSearch = debounce((query) => {
|
|
409
|
+
performSearch(query);
|
|
410
|
+
}, 300);
|
|
411
|
+
|
|
412
|
+
// Throttle function calls
|
|
413
|
+
const throttledScroll = throttle(() => {
|
|
414
|
+
handleScroll();
|
|
415
|
+
}, 100);
|
|
416
|
+
|
|
417
|
+
// Deep merge objects
|
|
418
|
+
const merged = deepMerge(defaultConfig, userConfig);
|
|
419
|
+
|
|
420
|
+
// Format dates
|
|
421
|
+
const formatted = formatDate(new Date(), 'YYYY-MM-DD');
|
|
422
|
+
|
|
423
|
+
// Generate unique IDs
|
|
424
|
+
const id = generateId();
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
## 🔧 Configuration
|
|
428
|
+
|
|
429
|
+
### Dashboard Config
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
interface DashboardConfig {
|
|
433
|
+
theme?: 'light' | 'dark' | 'auto';
|
|
434
|
+
plugins?: string[];
|
|
435
|
+
apiEndpoint?: string;
|
|
436
|
+
features?: {
|
|
437
|
+
notifications?: boolean;
|
|
438
|
+
metrics?: boolean;
|
|
439
|
+
errorBoundary?: boolean;
|
|
440
|
+
};
|
|
441
|
+
ui?: {
|
|
442
|
+
sidebar?: {
|
|
443
|
+
collapsible?: boolean;
|
|
444
|
+
defaultCollapsed?: boolean;
|
|
445
|
+
};
|
|
446
|
+
header?: {
|
|
447
|
+
showLogo?: boolean;
|
|
448
|
+
showUserMenu?: boolean;
|
|
449
|
+
};
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
### Environment Configuration
|
|
455
|
+
|
|
456
|
+
```jsx
|
|
457
|
+
// Configure based on environment
|
|
458
|
+
const config = {
|
|
459
|
+
apiEndpoint:
|
|
460
|
+
process.env.NODE_ENV === 'production'
|
|
461
|
+
? 'https://api.example.com'
|
|
462
|
+
: 'http://localhost:3001',
|
|
463
|
+
features: {
|
|
464
|
+
metrics: process.env.NODE_ENV === 'production',
|
|
465
|
+
errorBoundary: true,
|
|
466
|
+
},
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
<DashboardProvider config={config}>
|
|
470
|
+
<App />
|
|
471
|
+
</DashboardProvider>;
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
## 🧪 Testing
|
|
475
|
+
|
|
476
|
+
### Component Testing
|
|
477
|
+
|
|
478
|
+
```jsx
|
|
479
|
+
import { render, screen } from '@testing-library/react';
|
|
480
|
+
import {
|
|
481
|
+
DashboardProvider,
|
|
482
|
+
SimpleButton,
|
|
483
|
+
} from '@integrativedesigndevelopment/dashboard-core';
|
|
484
|
+
|
|
485
|
+
function renderWithProvider(component, config = {}) {
|
|
486
|
+
return render(
|
|
487
|
+
<DashboardProvider config={config}>{component}</DashboardProvider>
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
test('SimpleButton renders correctly', () => {
|
|
492
|
+
renderWithProvider(
|
|
493
|
+
<SimpleButton onClick={jest.fn()}>Test Button</SimpleButton>
|
|
494
|
+
);
|
|
495
|
+
|
|
496
|
+
expect(screen.getByRole('button')).toHaveTextContent('Test Button');
|
|
497
|
+
});
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
### Plugin Testing
|
|
501
|
+
|
|
502
|
+
```jsx
|
|
503
|
+
import { PluginManager } from '@integrativedesigndevelopment/dashboard-core';
|
|
504
|
+
|
|
505
|
+
test('plugin manager registers plugins correctly', () => {
|
|
506
|
+
const manager = new PluginManager();
|
|
507
|
+
const mockPlugin = {
|
|
508
|
+
id: 'test-plugin',
|
|
509
|
+
name: 'Test Plugin',
|
|
510
|
+
tabs: [],
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
manager.register(mockPlugin);
|
|
514
|
+
|
|
515
|
+
expect(manager.getPlugin('test-plugin')).toBe(mockPlugin);
|
|
516
|
+
});
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
## 🎨 Styling
|
|
520
|
+
|
|
521
|
+
### CSS Classes
|
|
522
|
+
|
|
523
|
+
```css
|
|
524
|
+
/* Core component styles */
|
|
525
|
+
.idd-button {
|
|
526
|
+
@apply px-4 py-2 rounded-md font-medium transition-colors;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
.idd-button-primary {
|
|
530
|
+
@apply bg-idd-primary text-white hover:bg-idd-primary-dark;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
.idd-button-secondary {
|
|
534
|
+
@apply bg-gray-200 text-gray-900 hover:bg-gray-300;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
.idd-dashboard-container {
|
|
538
|
+
@apply min-h-screen bg-gray-50;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
.idd-sidebar {
|
|
542
|
+
@apply w-64 bg-white shadow-lg;
|
|
543
|
+
}
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
### Theme Customization
|
|
547
|
+
|
|
548
|
+
```jsx
|
|
549
|
+
const customTheme = {
|
|
550
|
+
colors: {
|
|
551
|
+
primary: '#ad0000',
|
|
552
|
+
secondary: '#f5f5f5',
|
|
553
|
+
accent: '#0066cc',
|
|
554
|
+
},
|
|
555
|
+
spacing: {
|
|
556
|
+
sidebar: '16rem',
|
|
557
|
+
header: '4rem',
|
|
558
|
+
},
|
|
559
|
+
borderRadius: {
|
|
560
|
+
default: '0.5rem',
|
|
561
|
+
large: '1rem',
|
|
562
|
+
},
|
|
563
|
+
};
|
|
564
|
+
|
|
565
|
+
<DashboardProvider config={{ theme: customTheme }}>
|
|
566
|
+
<App />
|
|
567
|
+
</DashboardProvider>;
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
## 🔄 Migration Guide
|
|
571
|
+
|
|
572
|
+
### From v0.0.1 to v1.0.0
|
|
573
|
+
|
|
574
|
+
```jsx
|
|
575
|
+
// Before
|
|
576
|
+
import { Dashboard } from '@integrativedesigndevelopment/dashboard-core';
|
|
577
|
+
|
|
578
|
+
// After
|
|
579
|
+
import { DashboardProvider } from '@integrativedesigndevelopment/dashboard-core';
|
|
580
|
+
|
|
581
|
+
// Before
|
|
582
|
+
<Dashboard plugins={plugins} />
|
|
583
|
+
|
|
584
|
+
// After
|
|
585
|
+
<DashboardProvider config={{ plugins: ['plugin-1', 'plugin-2'] }}>
|
|
586
|
+
<YourApp />
|
|
587
|
+
</DashboardProvider>
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
## 🐛 Troubleshooting
|
|
591
|
+
|
|
592
|
+
### Common Issues
|
|
593
|
+
|
|
594
|
+
**Plugin not loading**
|
|
595
|
+
|
|
596
|
+
```jsx
|
|
597
|
+
// Check plugin registration
|
|
598
|
+
const plugins = get_all_plugins();
|
|
599
|
+
console.log(
|
|
600
|
+
'Available plugins:',
|
|
601
|
+
plugins.map((p) => p.id)
|
|
602
|
+
);
|
|
603
|
+
|
|
604
|
+
// Verify plugin structure
|
|
605
|
+
const plugin = plugins.find((p) => p.id === 'my-plugin');
|
|
606
|
+
console.log('Plugin structure:', plugin);
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
**State not updating**
|
|
610
|
+
|
|
611
|
+
```jsx
|
|
612
|
+
// Ensure DashboardProvider wraps your app
|
|
613
|
+
<DashboardProvider>
|
|
614
|
+
<App />
|
|
615
|
+
</DashboardProvider>;
|
|
616
|
+
|
|
617
|
+
// Use the hook correctly
|
|
618
|
+
const { state, dispatch } = useDashboard();
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
**TypeScript errors**
|
|
622
|
+
|
|
623
|
+
```typescript
|
|
624
|
+
// Extend plugin interface for custom properties
|
|
625
|
+
declare module '@integrativedesigndevelopment/dashboard-core' {
|
|
626
|
+
interface IDDPlugin {
|
|
627
|
+
customProperty?: string;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
## 📝 Examples
|
|
633
|
+
|
|
634
|
+
### Complete Dashboard Setup
|
|
635
|
+
|
|
636
|
+
```jsx
|
|
637
|
+
import React from 'react';
|
|
638
|
+
import {
|
|
639
|
+
DashboardProvider,
|
|
640
|
+
SimpleButton,
|
|
641
|
+
useDashboard,
|
|
642
|
+
} from '@integrativedesigndevelopment/dashboard-core';
|
|
643
|
+
|
|
644
|
+
const dashboardConfig = {
|
|
645
|
+
theme: 'light',
|
|
646
|
+
plugins: ['Dashboard', 'Content'],
|
|
647
|
+
features: {
|
|
648
|
+
notifications: true,
|
|
649
|
+
metrics: true,
|
|
650
|
+
},
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
function Dashboard() {
|
|
654
|
+
const { plugins, notifications } = useDashboard();
|
|
655
|
+
|
|
656
|
+
return (
|
|
657
|
+
<div className="idd-dashboard-container">
|
|
658
|
+
<header className="bg-white shadow p-4">
|
|
659
|
+
<h1>My Dashboard</h1>
|
|
660
|
+
<span>{notifications.length} notifications</span>
|
|
661
|
+
</header>
|
|
662
|
+
|
|
663
|
+
<main className="flex">
|
|
664
|
+
<aside className="idd-sidebar p-4">
|
|
665
|
+
<h2>Plugins</h2>
|
|
666
|
+
{plugins.map((plugin) => (
|
|
667
|
+
<div key={plugin.id} className="mb-2">
|
|
668
|
+
<SimpleButton variant="ghost" size="small">
|
|
669
|
+
{plugin.name}
|
|
670
|
+
</SimpleButton>
|
|
671
|
+
</div>
|
|
672
|
+
))}
|
|
673
|
+
</aside>
|
|
674
|
+
|
|
675
|
+
<div className="flex-1 p-6">{/* Main content */}</div>
|
|
676
|
+
</main>
|
|
677
|
+
</div>
|
|
678
|
+
);
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
function App() {
|
|
682
|
+
return (
|
|
683
|
+
<DashboardProvider config={dashboardConfig}>
|
|
684
|
+
<Dashboard />
|
|
685
|
+
</DashboardProvider>
|
|
686
|
+
);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
export default App;
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
### Custom Plugin with Metrics
|
|
693
|
+
|
|
694
|
+
```jsx
|
|
695
|
+
import React, { useEffect } from 'react';
|
|
696
|
+
import {
|
|
697
|
+
IDDPlugin,
|
|
698
|
+
trackCustomMetric,
|
|
699
|
+
useDashboard,
|
|
700
|
+
} from '@integrativedesigndevelopment/dashboard-core';
|
|
701
|
+
|
|
702
|
+
function AnalyticsContent() {
|
|
703
|
+
const { state } = useDashboard();
|
|
704
|
+
|
|
705
|
+
useEffect(() => {
|
|
706
|
+
// Track plugin usage
|
|
707
|
+
trackCustomMetric('analytics-plugin-view', {
|
|
708
|
+
timestamp: Date.now(),
|
|
709
|
+
userId: state.user?.id,
|
|
710
|
+
});
|
|
711
|
+
}, [state.user]);
|
|
712
|
+
|
|
713
|
+
return (
|
|
714
|
+
<div className="p-6">
|
|
715
|
+
<h2>Analytics Dashboard</h2>
|
|
716
|
+
<div className="grid grid-cols-2 gap-4 mt-4">
|
|
717
|
+
<div className="bg-white p-4 rounded shadow">
|
|
718
|
+
<h3>Page Views</h3>
|
|
719
|
+
<p className="text-2xl font-bold">1,234</p>
|
|
720
|
+
</div>
|
|
721
|
+
<div className="bg-white p-4 rounded shadow">
|
|
722
|
+
<h3>Users</h3>
|
|
723
|
+
<p className="text-2xl font-bold">567</p>
|
|
724
|
+
</div>
|
|
725
|
+
</div>
|
|
726
|
+
</div>
|
|
727
|
+
);
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
const AnalyticsPlugin: IDDPlugin = {
|
|
731
|
+
id: 'analytics',
|
|
732
|
+
name: 'Analytics',
|
|
733
|
+
order: 5,
|
|
734
|
+
tabs: [
|
|
735
|
+
{
|
|
736
|
+
id: 'overview',
|
|
737
|
+
name: 'Overview',
|
|
738
|
+
content: <AnalyticsContent />,
|
|
739
|
+
},
|
|
740
|
+
],
|
|
741
|
+
settings: [
|
|
742
|
+
{
|
|
743
|
+
key: 'trackingEnabled',
|
|
744
|
+
label: 'Enable Tracking',
|
|
745
|
+
type: 'toggle',
|
|
746
|
+
defaultValue: true,
|
|
747
|
+
},
|
|
748
|
+
],
|
|
749
|
+
};
|
|
750
|
+
|
|
751
|
+
export default AnalyticsPlugin;
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
## 🤝 Contributing
|
|
755
|
+
|
|
756
|
+
1. Fork the repository
|
|
757
|
+
2. Create a feature branch: `git checkout -b feature/core-improvement`
|
|
758
|
+
3. Make your changes
|
|
759
|
+
4. Add tests for new functionality
|
|
760
|
+
5. Run tests: `npm test`
|
|
761
|
+
6. Submit a pull request
|
|
762
|
+
|
|
763
|
+
## 📄 License
|
|
764
|
+
|
|
765
|
+
MIT License - see [LICENSE](../../LICENSE) file for details.
|
|
766
|
+
|
|
767
|
+
## 🔗 Related Packages
|
|
768
|
+
|
|
769
|
+
- [@integrativedesigndevelopment/dashboard-auth](../dashboard-auth) - Authentication system
|
|
770
|
+
- [@integrativedesigndevelopment/dashboard-nav](../dashboard-nav) - Navigation components
|
|
771
|
+
- [@integrativedesigndevelopment/dashboard-icons](../dashboard-icons) - Icon library
|
|
772
|
+
|
|
773
|
+
---
|
|
774
|
+
|
|
775
|
+
**Need help?** Check out our [documentation](../../docs) or [open an issue](https://dev.azure.com/IntegrativeDesignDevelopment/IDD/_workitems).
|