@ebay/muse-layout-antd 1.3.3 → 1.3.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.
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
# Plugin Integration Guide: @ebay/muse-layout-antd
|
|
2
|
+
|
|
3
|
+
**Generated**: 2026-03-28
|
|
4
|
+
**Plugin Type**: normal
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. Plugin Purpose & Overview
|
|
9
|
+
|
|
10
|
+
### Purpose
|
|
11
|
+
Provides a complete application layout system for MUSE apps with customizable header, sidebar navigation, and main content areas using Ant Design components.
|
|
12
|
+
|
|
13
|
+
### Key Features
|
|
14
|
+
- **Responsive Layout Management**: Provides a main layout component (`MainLayout`) with configurable header and sidebar
|
|
15
|
+
- **Extensible Header**: Supports customizable header with logo, title, navigation items, and user menu
|
|
16
|
+
- **Flexible Sidebar**: Offers multiple sidebar modes (drawer, collapsable, collapsed, fixed, none) with menu navigation
|
|
17
|
+
- **Layout Providers**: Supports wrapping the entire layout with custom React context providers
|
|
18
|
+
- **Theme Support**: Integrates with dark/light theme switching via `muse-lib-antd`
|
|
19
|
+
- **Sub-App Support**: Handles visibility of header/sidebar when running as a sub-application
|
|
20
|
+
- **Redux Integration**: Manages sidebar collapse state and layout updates through Redux
|
|
21
|
+
|
|
22
|
+
### Use Cases
|
|
23
|
+
- Building consistent application layouts across MUSE apps
|
|
24
|
+
- Providing navigation structure with header and sidebar menus
|
|
25
|
+
- Supporting both standalone apps and micro-frontend sub-apps
|
|
26
|
+
- Enabling plugins to contribute navigation items and layout providers
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 2. Extension Points Exposed
|
|
31
|
+
|
|
32
|
+
This plugin exposes extension points that allow other plugins to customize and extend the application layout.
|
|
33
|
+
|
|
34
|
+
### 2.1 `museLayout.header.getConfig`
|
|
35
|
+
|
|
36
|
+
**Type**: Direct (returns configuration object)
|
|
37
|
+
|
|
38
|
+
**Purpose**: Allows plugins to configure the header appearance and behavior.
|
|
39
|
+
|
|
40
|
+
**Signature**:
|
|
41
|
+
```typescript
|
|
42
|
+
() => HeaderConfig
|
|
43
|
+
|
|
44
|
+
interface HeaderConfig {
|
|
45
|
+
backgroundColor?: string;
|
|
46
|
+
icon?: ReactNode;
|
|
47
|
+
title?: string;
|
|
48
|
+
noUserMenu?: boolean;
|
|
49
|
+
themeSwitcher?: boolean;
|
|
50
|
+
subTitle?: string;
|
|
51
|
+
mode?: 'none' | 'show-in-sub-app' | undefined;
|
|
52
|
+
[key: string]: any;
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Usage**:
|
|
57
|
+
```javascript
|
|
58
|
+
plugin.register({
|
|
59
|
+
name: 'my-plugin',
|
|
60
|
+
museLayout: {
|
|
61
|
+
header: {
|
|
62
|
+
getConfig: () => ({
|
|
63
|
+
backgroundColor: '#1890ff',
|
|
64
|
+
icon: '/path/to/icon.png',
|
|
65
|
+
title: 'My App',
|
|
66
|
+
subTitle: 'Application subtitle',
|
|
67
|
+
themeSwitcher: true,
|
|
68
|
+
noUserMenu: false
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**File Reference**: `src/ext-points.d.ts:3-11`, `src/features/home/Header.jsx:210-216`
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
### 2.2 `museLayout.header.getItems`
|
|
80
|
+
|
|
81
|
+
**Type**: Direct (returns header item(s))
|
|
82
|
+
|
|
83
|
+
**Purpose**: Allows plugins to add navigation items, buttons, or menus to the application header.
|
|
84
|
+
|
|
85
|
+
**Signature**:
|
|
86
|
+
```typescript
|
|
87
|
+
() => HeaderItem | HeaderItem[]
|
|
88
|
+
|
|
89
|
+
interface HeaderItem {
|
|
90
|
+
position?: 'left' | 'center' | 'right';
|
|
91
|
+
order?: number;
|
|
92
|
+
key: string;
|
|
93
|
+
label?: string;
|
|
94
|
+
link?: string;
|
|
95
|
+
linkTarget?: string;
|
|
96
|
+
onClick?: Function;
|
|
97
|
+
icon?: ReactNode;
|
|
98
|
+
type?: 'menu' | string;
|
|
99
|
+
className?: string;
|
|
100
|
+
menuMeta?: Record<string, any>;
|
|
101
|
+
render?: () => ReactNode;
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Usage**:
|
|
106
|
+
```javascript
|
|
107
|
+
plugin.register({
|
|
108
|
+
name: 'my-plugin',
|
|
109
|
+
museLayout: {
|
|
110
|
+
header: {
|
|
111
|
+
getItems: () => [
|
|
112
|
+
{
|
|
113
|
+
key: 'settings',
|
|
114
|
+
icon: 'SettingOutlined',
|
|
115
|
+
position: 'right',
|
|
116
|
+
order: 50,
|
|
117
|
+
link: '/settings'
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
key: 'help-menu',
|
|
121
|
+
type: 'menu',
|
|
122
|
+
position: 'right',
|
|
123
|
+
order: 100,
|
|
124
|
+
menuMeta: {
|
|
125
|
+
trigger: { label: 'Help' },
|
|
126
|
+
items: [
|
|
127
|
+
{ key: 'docs', label: 'Documentation' },
|
|
128
|
+
{ key: 'support', label: 'Support' }
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**File Reference**: `src/ext-points.d.ts:13-31`, `src/features/home/Header.jsx:235`
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
### 2.3 `museLayout.header.processItems`
|
|
143
|
+
|
|
144
|
+
**Type**: Lifecycle (processes header items before rendering)
|
|
145
|
+
|
|
146
|
+
**Purpose**: Allows plugins to modify, filter, or transform the complete list of header items after they have been collected from all plugins.
|
|
147
|
+
|
|
148
|
+
**Signature**:
|
|
149
|
+
```typescript
|
|
150
|
+
(items: HeaderItem[]) => void
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**Usage**:
|
|
154
|
+
```javascript
|
|
155
|
+
plugin.register({
|
|
156
|
+
name: 'my-plugin',
|
|
157
|
+
museLayout: {
|
|
158
|
+
header: {
|
|
159
|
+
processItems: (items) => {
|
|
160
|
+
// Example: Remove specific items
|
|
161
|
+
const index = items.findIndex(item => item.key === 'unwanted-item');
|
|
162
|
+
if (index !== -1) items.splice(index, 1);
|
|
163
|
+
|
|
164
|
+
// Example: Modify items
|
|
165
|
+
items.forEach(item => {
|
|
166
|
+
if (item.key === 'special') {
|
|
167
|
+
item.className = 'highlighted';
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**File Reference**: `src/ext-points.d.ts:27-30`, `src/features/home/Header.jsx:267`
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
### 2.4 `museLayout.sider.getConfig`
|
|
181
|
+
|
|
182
|
+
**Type**: Direct (returns configuration object)
|
|
183
|
+
|
|
184
|
+
**Purpose**: Allows plugins to configure the sidebar appearance and behavior.
|
|
185
|
+
|
|
186
|
+
**Signature**:
|
|
187
|
+
```typescript
|
|
188
|
+
() => SiderConfig
|
|
189
|
+
|
|
190
|
+
interface SiderConfig {
|
|
191
|
+
mode?: 'fixed' | 'drawer' | 'collapsable' | 'collapsed' | 'none';
|
|
192
|
+
siderDefaultCollapsed?: boolean;
|
|
193
|
+
homeMenu?: boolean;
|
|
194
|
+
theme?: 'dark' | 'light' | 'custom';
|
|
195
|
+
width?: number;
|
|
196
|
+
menuProps?: Record<string, any>;
|
|
197
|
+
[key: string]: any;
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Usage**:
|
|
202
|
+
```javascript
|
|
203
|
+
plugin.register({
|
|
204
|
+
name: 'my-plugin',
|
|
205
|
+
museLayout: {
|
|
206
|
+
sider: {
|
|
207
|
+
getConfig: () => ({
|
|
208
|
+
mode: 'collapsable',
|
|
209
|
+
siderDefaultCollapsed: false,
|
|
210
|
+
homeMenu: true,
|
|
211
|
+
theme: 'dark',
|
|
212
|
+
width: 280
|
|
213
|
+
})
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**File Reference**: `src/ext-points.d.ts:33-41`, `src/features/home/Sider.jsx:10-14`
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
### 2.5 `museLayout.sider.getItems`
|
|
224
|
+
|
|
225
|
+
**Type**: Direct (returns sidebar menu item(s))
|
|
226
|
+
|
|
227
|
+
**Purpose**: Allows plugins to add navigation menu items to the application sidebar.
|
|
228
|
+
|
|
229
|
+
**Signature**:
|
|
230
|
+
```typescript
|
|
231
|
+
() => SiderItem | SiderItem[]
|
|
232
|
+
|
|
233
|
+
interface SiderItem {
|
|
234
|
+
key: string;
|
|
235
|
+
icon?: ReactNode;
|
|
236
|
+
link?: string;
|
|
237
|
+
label: ReactNode;
|
|
238
|
+
order?: number;
|
|
239
|
+
children?: SiderItem[];
|
|
240
|
+
parent?: string;
|
|
241
|
+
type?: 'group' | string;
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Usage**:
|
|
246
|
+
```javascript
|
|
247
|
+
plugin.register({
|
|
248
|
+
name: 'my-plugin',
|
|
249
|
+
museLayout: {
|
|
250
|
+
sider: {
|
|
251
|
+
getItems: () => [
|
|
252
|
+
{
|
|
253
|
+
key: 'dashboard',
|
|
254
|
+
icon: 'DashboardOutlined',
|
|
255
|
+
label: 'Dashboard',
|
|
256
|
+
order: 10,
|
|
257
|
+
children: [
|
|
258
|
+
{ key: 'overview', label: 'Overview', link: '/dashboard' },
|
|
259
|
+
{ key: 'analytics', label: 'Analytics', link: '/dashboard/analytics' }
|
|
260
|
+
]
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
key: 'settings',
|
|
264
|
+
icon: 'SettingOutlined',
|
|
265
|
+
label: 'Settings',
|
|
266
|
+
link: '/settings',
|
|
267
|
+
order: 100
|
|
268
|
+
}
|
|
269
|
+
]
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
**File Reference**: `src/ext-points.d.ts:43-54`, `src/features/home/Sider.jsx:87`
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
### 2.6 `museLayout.sider` (nested menu items via MetaMenu)
|
|
280
|
+
|
|
281
|
+
**Type**: Nested extension point pattern (via `baseExtPoint="museLayout.sider"`)
|
|
282
|
+
|
|
283
|
+
**Purpose**: The sidebar uses `MetaMenu` component which automatically creates nested extension points for each menu item, allowing plugins to add sub-items to existing menus.
|
|
284
|
+
|
|
285
|
+
**Pattern**: For a menu item with `key: 'myMenu'`, other plugins can contribute to `museLayout.sider.myMenu.getItems`
|
|
286
|
+
|
|
287
|
+
**File Reference**: `src/features/home/Sider.jsx:87`
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
### 2.7 `museLayout.header.{itemKey}` (nested menu items via MetaMenu)
|
|
292
|
+
|
|
293
|
+
**Type**: Nested extension point pattern (via `baseExtPoint`)
|
|
294
|
+
|
|
295
|
+
**Purpose**: Header items of type 'menu' automatically create nested extension points allowing plugins to add items to those menus.
|
|
296
|
+
|
|
297
|
+
**Pattern**: For a header menu item with `key: 'helpMenu'`, other plugins can contribute to `museLayout.header.helpMenu.getItems`
|
|
298
|
+
|
|
299
|
+
**File Reference**: `src/features/home/HeaderItem.jsx:47`
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
### 2.8 `museLayout.providers`
|
|
304
|
+
|
|
305
|
+
**Type**: Array extension (via `extendArray`)
|
|
306
|
+
|
|
307
|
+
**Purpose**: Allows plugins to wrap the entire layout with React context providers (e.g., for modals, notifications, or global state).
|
|
308
|
+
|
|
309
|
+
**Signature**:
|
|
310
|
+
```typescript
|
|
311
|
+
{
|
|
312
|
+
order?: number;
|
|
313
|
+
key: string;
|
|
314
|
+
provider?: React.ComponentType<{children: React.ReactNode}>;
|
|
315
|
+
props?: Record<string, any>;
|
|
316
|
+
renderProvider?: (children: React.ReactNode) => React.ReactNode;
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
**Usage**:
|
|
321
|
+
```javascript
|
|
322
|
+
import { NiceModal } from '@ebay/nice-modal-react';
|
|
323
|
+
|
|
324
|
+
plugin.register({
|
|
325
|
+
name: 'my-plugin',
|
|
326
|
+
museLayout: {
|
|
327
|
+
providers: {
|
|
328
|
+
getItems: () => ({
|
|
329
|
+
order: 40,
|
|
330
|
+
key: 'nice-modal',
|
|
331
|
+
provider: NiceModal.Provider,
|
|
332
|
+
props: { /* provider props */ }
|
|
333
|
+
})
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
// Alternative using renderProvider
|
|
339
|
+
plugin.register({
|
|
340
|
+
name: 'my-plugin',
|
|
341
|
+
museLayout: {
|
|
342
|
+
providers: {
|
|
343
|
+
getItems: () => ({
|
|
344
|
+
order: 50,
|
|
345
|
+
key: 'custom-provider',
|
|
346
|
+
renderProvider: (children) => (
|
|
347
|
+
<MyCustomProvider>
|
|
348
|
+
{children}
|
|
349
|
+
</MyCustomProvider>
|
|
350
|
+
)
|
|
351
|
+
})
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
**File Reference**: `src/features/home/MainLayout.jsx:178`, `src/features/home/MainLayout.jsx:167-201`
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
361
|
+
## 3. Extension Points Contributed
|
|
362
|
+
|
|
363
|
+
This plugin implements extension points from other MUSE plugins to integrate with the ecosystem.
|
|
364
|
+
|
|
365
|
+
### 3.1 Contributions to `home` extension point
|
|
366
|
+
|
|
367
|
+
#### 3.1.1 `home.mainLayout`
|
|
368
|
+
|
|
369
|
+
**Source Plugin**: Core routing system (expected by MUSE framework)
|
|
370
|
+
|
|
371
|
+
**Purpose**: Provides the main layout component that wraps all application routes.
|
|
372
|
+
|
|
373
|
+
**Implementation**: Exports the `MainLayout` React component that renders header, sidebar, and page content.
|
|
374
|
+
|
|
375
|
+
**File Reference**: `src/ext/home.js:4`
|
|
376
|
+
|
|
377
|
+
**Why**: This allows the MUSE framework to use this plugin's layout as the application shell that wraps all page content.
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
### 3.2 Contributions via `route` property
|
|
382
|
+
|
|
383
|
+
#### 3.2.1 `route`
|
|
384
|
+
|
|
385
|
+
**Source Plugin**: MUSE routing system (standard plugin property)
|
|
386
|
+
|
|
387
|
+
**Purpose**: Registers route configuration for the plugin's own pages.
|
|
388
|
+
|
|
389
|
+
**Implementation**: Provides a route configuration object for the `/plugin-muse-layout/home` path.
|
|
390
|
+
|
|
391
|
+
**File Reference**: `src/index.js:11`, `src/common/routeConfig.js`
|
|
392
|
+
|
|
393
|
+
**Why**: Standard MUSE plugin pattern to register routes, though this plugin's routes are primarily for internal structure rather than user-facing pages.
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
### 3.3 Contributions via `reducer` property
|
|
398
|
+
|
|
399
|
+
#### 3.3.1 `reducer`
|
|
400
|
+
|
|
401
|
+
**Source Plugin**: MUSE Redux integration (standard plugin property)
|
|
402
|
+
|
|
403
|
+
**Purpose**: Registers Redux reducer to manage layout state (sidebar collapse, layout updates).
|
|
404
|
+
|
|
405
|
+
**Implementation**: Provides a Redux reducer that handles:
|
|
406
|
+
- `MUSE_LAYOUT$HOME_SET_SIDER_COLLAPSED` - Toggle sidebar collapse state
|
|
407
|
+
- `MUSE_LAYOUT$HOME_SET_LAYOUT_CONFIG` - Update layout configuration
|
|
408
|
+
- `MUSE_LAYOUT$HOME_UPDATE_MUSE_LAYOUT` - Force layout re-render
|
|
409
|
+
|
|
410
|
+
**File Reference**: `src/index.js:12`, `src/common/rootReducer.js`
|
|
411
|
+
|
|
412
|
+
**Why**: Manages global layout state that needs to be accessible across the application and persist during navigation.
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
### 3.4 Demo Extension Points (from ext/museLayout.js)
|
|
417
|
+
|
|
418
|
+
**Note**: The file `src/ext/museLayout.js` contains example/demo implementations of this plugin's own extension points. These are for demonstration purposes in the MUSE demo app.
|
|
419
|
+
|
|
420
|
+
#### 3.4.1 `museLayout.header.getConfig` (demo)
|
|
421
|
+
**Purpose**: Demo configuration showing header with Muse branding
|
|
422
|
+
**File Reference**: `src/ext/museLayout.js:4-12`
|
|
423
|
+
|
|
424
|
+
#### 3.4.2 `museLayout.header.userAvatar.getItems` (demo)
|
|
425
|
+
**Purpose**: Demo showing how to add items to user avatar menu
|
|
426
|
+
**File Reference**: `src/ext/museLayout.js:13-21`
|
|
427
|
+
|
|
428
|
+
#### 3.4.3 `museLayout.header.getItems` (demo)
|
|
429
|
+
**Purpose**: Demo showing various header items (menus, icons, center items)
|
|
430
|
+
**File Reference**: `src/ext/museLayout.js:22-73`
|
|
431
|
+
|
|
432
|
+
#### 3.4.4 `museLayout.sider.getConfig` (demo)
|
|
433
|
+
**Purpose**: Demo configuration showing drawer mode sidebar
|
|
434
|
+
**File Reference**: `src/ext/museLayout.js:75-81`
|
|
435
|
+
|
|
436
|
+
#### 3.4.5 `museLayout.sider.getItems` (demo)
|
|
437
|
+
**Purpose**: Demo showing comprehensive sidebar menu structure with nested items, groups, and various component examples
|
|
438
|
+
**File Reference**: `src/ext/museLayout.js:82-349`
|
|
439
|
+
|
|
440
|
+
**Why**: These demo implementations serve as living examples for developers learning how to extend the layout plugin. They are currently commented out in `src/ext/index.js:1` (not active by default).
|
|
441
|
+
|
|
442
|
+
---
|
|
443
|
+
|
|
444
|
+
## 4. Exported Functionality
|
|
445
|
+
|
|
446
|
+
This plugin exports functionality for other plugins to use programmatically.
|
|
447
|
+
|
|
448
|
+
### 4.1 `updateMuseLayout`
|
|
449
|
+
|
|
450
|
+
**Type**: Function export
|
|
451
|
+
|
|
452
|
+
**Purpose**: Forces the layout to re-render by dispatching a Redux action. Useful when plugins dynamically change layout configuration and need to trigger an immediate update.
|
|
453
|
+
|
|
454
|
+
**Signature**:
|
|
455
|
+
```typescript
|
|
456
|
+
() => void
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
**Usage**:
|
|
460
|
+
```javascript
|
|
461
|
+
const layoutPlugin = plugin.getPlugin('@ebay/muse-layout-antd');
|
|
462
|
+
layoutPlugin.exports.updateMuseLayout();
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
**File Reference**: `src/index.js:13`, `src/features/home/updateMuseLayout.js`
|
|
466
|
+
|
|
467
|
+
**Why**: When plugins dynamically modify layout configuration (e.g., changing header items based on runtime conditions), they need a way to notify the layout to re-collect contributions and re-render. This function triggers that update.
|
|
468
|
+
|
|
469
|
+
**Common Use Cases**:
|
|
470
|
+
- After dynamically adding/removing navigation items
|
|
471
|
+
- After changing user permissions that affect visible menus
|
|
472
|
+
- After configuration changes that affect layout appearance
|
|
473
|
+
|
|
474
|
+
---
|
|
475
|
+
|
|
476
|
+
## 5. Integration Examples
|
|
477
|
+
|
|
478
|
+
**CRITICAL**: Extension points are **nested object properties**, NOT string paths!
|
|
479
|
+
|
|
480
|
+
### Example 1: Adding Navigation to Header and Sidebar (CORRECT Syntax)
|
|
481
|
+
|
|
482
|
+
```javascript
|
|
483
|
+
// ✅ CORRECT - nested object properties
|
|
484
|
+
plugin.register({
|
|
485
|
+
name: '@my/plugin',
|
|
486
|
+
museLayout: {
|
|
487
|
+
header: {
|
|
488
|
+
getItems: () => ({
|
|
489
|
+
key: 'my-tool',
|
|
490
|
+
icon: 'ToolOutlined',
|
|
491
|
+
label: 'My Tool',
|
|
492
|
+
position: 'right',
|
|
493
|
+
link: '/my-tool'
|
|
494
|
+
})
|
|
495
|
+
},
|
|
496
|
+
sider: {
|
|
497
|
+
getItems: () => ({
|
|
498
|
+
key: 'my-section',
|
|
499
|
+
icon: 'AppstoreOutlined',
|
|
500
|
+
label: 'My Section',
|
|
501
|
+
order: 50,
|
|
502
|
+
children: [
|
|
503
|
+
{ key: 'page1', label: 'Page 1', link: '/my/page1' },
|
|
504
|
+
{ key: 'page2', label: 'Page 2', link: '/my/page2' }
|
|
505
|
+
]
|
|
506
|
+
})
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
// ❌ INCORRECT - DO NOT use string paths
|
|
512
|
+
plugin.register({
|
|
513
|
+
name: '@my/plugin',
|
|
514
|
+
'museLayout.header.getItems': () => ({ /* ... */ }), // WRONG!
|
|
515
|
+
'museLayout.sider.getItems': () => ({ /* ... */ }) // WRONG!
|
|
516
|
+
});
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### Example 2: Customizing Layout Configuration
|
|
520
|
+
|
|
521
|
+
```javascript
|
|
522
|
+
plugin.register({
|
|
523
|
+
name: '@my/plugin',
|
|
524
|
+
museLayout: {
|
|
525
|
+
header: {
|
|
526
|
+
getConfig: () => ({
|
|
527
|
+
backgroundColor: '#722ed1',
|
|
528
|
+
title: 'My Custom App',
|
|
529
|
+
subTitle: 'Powered by MUSE',
|
|
530
|
+
icon: '/assets/logo.png',
|
|
531
|
+
noUserMenu: false,
|
|
532
|
+
themeSwitcher: true
|
|
533
|
+
})
|
|
534
|
+
},
|
|
535
|
+
sider: {
|
|
536
|
+
getConfig: () => ({
|
|
537
|
+
mode: 'collapsable',
|
|
538
|
+
siderDefaultCollapsed: true,
|
|
539
|
+
theme: 'dark',
|
|
540
|
+
width: 280,
|
|
541
|
+
homeMenu: true
|
|
542
|
+
})
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
});
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
### Example 3: Adding Layout Providers
|
|
549
|
+
|
|
550
|
+
```javascript
|
|
551
|
+
import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
|
|
552
|
+
|
|
553
|
+
const queryClient = new QueryClient();
|
|
554
|
+
|
|
555
|
+
plugin.register({
|
|
556
|
+
name: '@my/plugin',
|
|
557
|
+
museLayout: {
|
|
558
|
+
providers: {
|
|
559
|
+
getItems: () => ({
|
|
560
|
+
order: 30,
|
|
561
|
+
key: 'react-query',
|
|
562
|
+
provider: QueryClientProvider,
|
|
563
|
+
props: { client: queryClient }
|
|
564
|
+
})
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
});
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
### Example 4: Processing Header Items
|
|
571
|
+
|
|
572
|
+
```javascript
|
|
573
|
+
plugin.register({
|
|
574
|
+
name: '@my/plugin',
|
|
575
|
+
museLayout: {
|
|
576
|
+
header: {
|
|
577
|
+
processItems: (items) => {
|
|
578
|
+
// Add a badge to specific items
|
|
579
|
+
items.forEach(item => {
|
|
580
|
+
if (item.key === 'notifications') {
|
|
581
|
+
item.badge = { count: 5 };
|
|
582
|
+
}
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
// Remove items based on permissions
|
|
586
|
+
const userPermissions = window.MUSE_GLOBAL.getUser().permissions;
|
|
587
|
+
if (!userPermissions.includes('admin')) {
|
|
588
|
+
const adminIndex = items.findIndex(item => item.key === 'admin-panel');
|
|
589
|
+
if (adminIndex !== -1) items.splice(adminIndex, 1);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
### Example 5: Using Exported Functions
|
|
598
|
+
|
|
599
|
+
```javascript
|
|
600
|
+
// Get the layout plugin
|
|
601
|
+
const layoutPlugin = plugin.getPlugin('@ebay/muse-layout-antd');
|
|
602
|
+
|
|
603
|
+
// Trigger layout update after dynamic changes
|
|
604
|
+
function updateMyMenuItems() {
|
|
605
|
+
// Your logic to modify menu items...
|
|
606
|
+
|
|
607
|
+
// Force layout to re-render with new items
|
|
608
|
+
layoutPlugin.exports.updateMuseLayout();
|
|
609
|
+
}
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
### Example 6: Adding Items to Existing Header Menus
|
|
613
|
+
|
|
614
|
+
```javascript
|
|
615
|
+
// Assuming another plugin created a 'help' menu in the header
|
|
616
|
+
plugin.register({
|
|
617
|
+
name: '@my/plugin',
|
|
618
|
+
museLayout: {
|
|
619
|
+
header: {
|
|
620
|
+
help: { // This matches the 'key' of the parent menu item
|
|
621
|
+
getItems: () => [
|
|
622
|
+
{
|
|
623
|
+
key: 'my-docs',
|
|
624
|
+
label: 'My Plugin Docs',
|
|
625
|
+
link: '/docs/my-plugin'
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
key: 'my-tutorial',
|
|
629
|
+
label: 'Tutorial',
|
|
630
|
+
onClick: () => window.open('/tutorial')
|
|
631
|
+
}
|
|
632
|
+
]
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
});
|
|
637
|
+
```
|
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
"content": {
|
|
3
3
|
"@ebay/muse-lib-react@1.3.2": [
|
|
4
4
|
"js-plugin@1.1.0/plugin.js",
|
|
5
|
-
"redux@4.2.1/es/redux.js",
|
|
6
5
|
"@ebay/muse-lib-react@1.3.2/src/common/store.js",
|
|
6
|
+
"redux@4.2.1/es/redux.js",
|
|
7
7
|
"react@18.2.0/index.js",
|
|
8
8
|
"react-redux@8.1.2/es/index.js",
|
|
9
9
|
"lodash@4.17.21/lodash.js",
|
|
10
10
|
"react@18.2.0/jsx-dev-runtime.js",
|
|
11
|
-
"
|
|
12
|
-
"
|
|
11
|
+
"@ebay/muse-lib-react@1.3.2/src/utils.js",
|
|
12
|
+
"react-router-dom@6.15.0/dist/index.js"
|
|
13
13
|
],
|
|
14
14
|
"@ebay/muse-lib-antd@1.3.2": [
|
|
15
|
-
"@
|
|
15
|
+
"@ebay/muse-lib-antd@1.3.2/src/features/common/index.js",
|
|
16
16
|
"antd@5.19.0/es/index.js",
|
|
17
|
-
"@
|
|
17
|
+
"@ant-design/icons@5.3.7/es/index.js"
|
|
18
18
|
]
|
|
19
19
|
}
|
|
20
20
|
}
|
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
"react-redux@8.1.2/es/index.js",
|
|
9
9
|
"lodash@4.17.21/lodash.js",
|
|
10
10
|
"react@18.2.0/jsx-runtime.js",
|
|
11
|
-
"
|
|
12
|
-
"
|
|
11
|
+
"@ebay/muse-lib-react@1.3.2/src/utils.js",
|
|
12
|
+
"react-router-dom@6.15.0/dist/index.js"
|
|
13
13
|
],
|
|
14
14
|
"@ebay/muse-lib-antd@1.3.2": [
|
|
15
|
-
"antd@
|
|
15
|
+
"@ebay/muse-lib-antd@1.3.2/src/features/common/index.js",
|
|
16
16
|
"@ant-design/icons@5.3.7/es/index.js",
|
|
17
|
-
"
|
|
17
|
+
"antd@5.19.0/es/index.js"
|
|
18
18
|
]
|
|
19
19
|
}
|
|
20
20
|
}
|
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
"content": {
|
|
3
3
|
"@ebay/muse-lib-react@1.3.2": [
|
|
4
4
|
"js-plugin@1.1.0/plugin.js",
|
|
5
|
-
"@ebay/muse-lib-react@1.3.2/src/common/store.js",
|
|
6
5
|
"redux@4.2.1/es/redux.js",
|
|
6
|
+
"@ebay/muse-lib-react@1.3.2/src/common/store.js",
|
|
7
7
|
"react@18.2.0/index.js",
|
|
8
8
|
"react-redux@8.1.2/es/index.js",
|
|
9
9
|
"lodash@4.17.21/lodash.js",
|
|
10
10
|
"react@18.2.0/jsx-runtime.js",
|
|
11
|
-
"
|
|
12
|
-
"
|
|
11
|
+
"react-router-dom@6.15.0/dist/index.js",
|
|
12
|
+
"@ebay/muse-lib-react@1.3.2/src/utils.js"
|
|
13
13
|
],
|
|
14
14
|
"@ebay/muse-lib-antd@1.3.2": [
|
|
15
|
-
"@ant-design/icons@5.3.7/es/index.js",
|
|
16
15
|
"@ebay/muse-lib-antd@1.3.2/src/features/common/index.js",
|
|
16
|
+
"@ant-design/icons@5.3.7/es/index.js",
|
|
17
17
|
"antd@5.19.0/es/index.js"
|
|
18
18
|
]
|
|
19
19
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ebay/muse-layout-antd",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.5",
|
|
4
4
|
"repository": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"muse": {
|
|
@@ -67,6 +67,7 @@
|
|
|
67
67
|
"build:test": "cross-env MUSE_TEST_BUILD=true NODE_ENV=production vite build --mode e2e-test",
|
|
68
68
|
"gen-muse-doc": "typedoc",
|
|
69
69
|
"test": "vitest",
|
|
70
|
-
"test:coverage": "vitest run --coverage"
|
|
70
|
+
"test:coverage": "vitest run --coverage",
|
|
71
|
+
"postbuild": "cp MUSE_README.md ./build"
|
|
71
72
|
}
|
|
72
73
|
}
|