@ebay/muse-lib-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,971 @@
1
+ # Plugin Integration Guide: @ebay/muse-lib-antd
2
+
3
+ **Generated**: 2026-03-28
4
+ **Plugin Type**: lib
5
+
6
+ ---
7
+
8
+ ## Table of Contents
9
+
10
+ 1. [Plugin Purpose & Overview](#1-plugin-purpose--overview)
11
+ 2. [Extension Points Exposed](#2-extension-points-exposed)
12
+ 3. [Extension Points Contributed](#3-extension-points-contributed)
13
+ 4. [Exported Functionality](#4-exported-functionality)
14
+ 5. [Integration Examples](#5-integration-examples)
15
+
16
+ ---
17
+
18
+ ## 1. Plugin Purpose & Overview
19
+
20
+ ### What This Plugin Does
21
+
22
+ `@ebay/muse-lib-antd` is a library plugin that provides Ant Design (antd) UI components and utilities to MUSE applications. It serves as a shared UI framework layer, preventing code duplication by providing a single instance of Ant Design that all consuming plugins can use.
23
+
24
+ ### Key Features
25
+
26
+ - **Ant Design Components**: Provides the complete Ant Design 5.x component library as shared modules
27
+ - **Reusable UI Components**: Offers custom-built components like MetaMenu, DropdownMenu, ErrorBox, CodeViewer, and more
28
+ - **Form Utilities**: Provides extensible form and array utilities via `extendFormMeta()` and `extendArray()`
29
+ - **Nice Form Integration**: Pre-configured Nice Form React with Ant Design adapter and custom widgets
30
+ - **Dark Mode Support**: Built-in dark mode theme switching with Redux state management
31
+ - **React Router Integration**: Provides route configuration and React Router setup
32
+ - **Redux State Management**: Includes Redux reducer for common state (dark mode, etc.)
33
+ - **Config Provider Wrapper**: Extensible Ant Design ConfigProvider with theme management
34
+
35
+ ### Plugin Type: lib
36
+
37
+ As a **lib plugin**, this plugin loads before normal plugins and provides shared modules to avoid duplicating dependencies. Other plugins that depend on Ant Design or React will consume these modules from this plugin rather than bundling their own copies, reducing bundle size and ensuring version consistency.
38
+
39
+ ---
40
+
41
+ ## 2. Extension Points Exposed
42
+
43
+ This plugin exposes the following extension points that OTHER plugins can implement to extend its functionality.
44
+
45
+ ### Summary
46
+
47
+ - **Total Extension Points**: 7 base patterns (expandable to unlimited via parameter-based extension points)
48
+ - **Categories**: Form Extensions, Array Extensions, Menu Extensions, ConfigProvider Extensions
49
+
50
+ ### Extension Point Patterns
51
+
52
+ This plugin uses **parameter-based extension points**, where the extension point name is passed as a parameter to utility functions. This allows unlimited extensibility without hardcoding specific extension point names.
53
+
54
+ #### Form Extension Pattern (via `extendFormMeta`)
55
+
56
+ **Base Extension Point**: `${extBase}.*` (where `extBase` is provided by caller)
57
+
58
+ When a plugin calls `extendFormMeta(meta, extBase, ...args)`, other plugins can implement these extension points:
59
+
60
+ ##### `${extBase}.preProcessMeta`
61
+
62
+ - **Purpose**: Hook to modify form metadata before fields are added
63
+ - **When Invoked**: Called at the start of `extendFormMeta()`, before any field processing
64
+ - **Context Parameters**:
65
+ - `...args`: Variable arguments passed through from the caller
66
+ - **Expected Return**: `void` (modifies arguments in place)
67
+ - **Use Case Example**: Initialize form state, add validators, or set up form-level configuration
68
+ - **File Reference**: src/utils.js:12
69
+
70
+ ##### `${extBase}.getFields`
71
+
72
+ - **Purpose**: Allows plugins to contribute additional fields to the form
73
+ - **When Invoked**: Called during form metadata construction to gather field definitions
74
+ - **Context Parameters**:
75
+ - `...args`: Variable arguments passed through from the caller (typically includes form context, record data, etc.)
76
+ - **Expected Return**: `Array<FieldDefinition>` - Array of Nice Form field definitions
77
+ - **Use Case Example**: Add custom fields to app creation form, plugin info form, or any extensible form
78
+ - **File Reference**: src/utils.js:13
79
+
80
+ ##### `${extBase}.processMeta`
81
+
82
+ - **Purpose**: Hook to modify the complete form metadata after fields are added
83
+ - **When Invoked**: Called after all fields are collected but before post-processing
84
+ - **Context Parameters**:
85
+ - `...args`: Variable arguments passed through from the caller
86
+ - **Expected Return**: `void` (modifies metadata in place)
87
+ - **Use Case Example**: Reorder fields, add field dependencies, modify field properties based on other fields
88
+ - **File Reference**: src/utils.js:15
89
+
90
+ ##### `${extBase}.postProcessMeta`
91
+
92
+ - **Purpose**: Final hook to modify form metadata after all processing
93
+ - **When Invoked**: Called after all other form processing is complete
94
+ - **Context Parameters**:
95
+ - `...args`: Variable arguments passed through from the caller
96
+ - **Expected Return**: `void` (modifies metadata in place)
97
+ - **Use Case Example**: Apply final validation rules, add computed fields, or finalize form layout
98
+ - **File Reference**: src/utils.js:16
99
+
100
+ ##### `${extBase}.getWatchingFields`
101
+
102
+ - **Purpose**: Allows plugins to define fields that should be watched for changes
103
+ - **When Invoked**: Called during form metadata construction to gather watching field configurations
104
+ - **Context Parameters**:
105
+ - `...args`: Variable arguments passed through from the caller
106
+ - **Expected Return**: `Array<WatchingFieldConfig>` - Array of watching field configurations for Nice Form
107
+ - **Use Case Example**: Define field dependencies where one field's value affects another's visibility or validation
108
+ - **File Reference**: src/utils.js:20
109
+
110
+ #### Array Extension Pattern (via `extendArray`)
111
+
112
+ **Base Extension Point**: `${extBase}.*` (where `extBase` and `extName` are provided by caller)
113
+
114
+ When a plugin calls `extendArray(arr, extName, extBase, ...args)`, other plugins can implement these extension points:
115
+
116
+ ##### `${extBase}.preProcess${CapitalizedExtName}`
117
+
118
+ - **Purpose**: Hook to process array before items are added
119
+ - **When Invoked**: Called at the start of `extendArray()`, before collecting items
120
+ - **Context Parameters**:
121
+ - `...args`: Variable arguments passed through from the caller
122
+ - **Expected Return**: `void` (modifies arguments in place)
123
+ - **Use Case Example**: Initialize array context, set up filters
124
+ - **File Reference**: src/utils.js:38
125
+
126
+ ##### `${extBase}.get${CapitalizedExtName}`
127
+
128
+ - **Purpose**: Allows plugins to contribute items to the array
129
+ - **When Invoked**: Called during array construction to gather items
130
+ - **Context Parameters**:
131
+ - `...args`: Variable arguments passed through from the caller
132
+ - **Expected Return**: `Array<any>` - Array of items to add
133
+ - **Use Case Example**: Add table columns, menu items, action buttons, tabs, etc.
134
+ - **File Reference**: src/utils.js:39
135
+
136
+ ##### `${extBase}.process${CapitalizedExtName}`
137
+
138
+ - **Purpose**: Hook to modify array after items are collected
139
+ - **When Invoked**: Called after all items are gathered but before post-processing
140
+ - **Context Parameters**:
141
+ - `...args`: Variable arguments passed through from the caller
142
+ - **Expected Return**: `void` (modifies array in place)
143
+ - **Use Case Example**: Filter, reorder, or transform items
144
+ - **File Reference**: src/utils.js:41
145
+
146
+ ##### `${extBase}.postProcess${CapitalizedExtName}`
147
+
148
+ - **Purpose**: Final hook to modify array after all processing
149
+ - **When Invoked**: Called after all other processing is complete
150
+ - **Context Parameters**:
151
+ - `...args`: Variable arguments passed through from the caller
152
+ - **Expected Return**: `void` (modifies array in place)
153
+ - **Use Case Example**: Apply final transformations, add computed items
154
+ - **File Reference**: src/utils.js:42
155
+
156
+ #### MetaMenu Extension Pattern
157
+
158
+ **Base Extension Point**: `${baseExtPoint}.*` (where `baseExtPoint` is provided via props)
159
+
160
+ ##### `${baseExtPoint}.getItems`
161
+
162
+ - **Purpose**: Allows plugins to contribute menu items to a MetaMenu component
163
+ - **When Invoked**: Called when MetaMenu renders, if `baseExtPoint` prop is provided
164
+ - **Context Parameters**:
165
+ - `meta`: Object - The menu metadata object containing configuration
166
+ - **Expected Return**: `Array<MetaMenuItem>` - Array of menu item definitions
167
+ - **Use Case Example**: Add custom menu items to application sidebar, header menu, or dropdown menus
168
+ - **File Reference**: src/features/common/MetaMenu.js:23
169
+
170
+ ##### `${baseExtPoint}.processItems`
171
+
172
+ - **Purpose**: Hook to modify all menu items after they're collected and normalized
173
+ - **When Invoked**: Called after all items (from meta and extensions) are collected, normalized, and have parent-child relationships resolved
174
+ - **Context Parameters**:
175
+ - `meta`: Object - The menu metadata object
176
+ - `newItems`: Array - The normalized array of menu items
177
+ - `itemByKey`: Object - Map of menu items keyed by their key property
178
+ - **Expected Return**: `void` (modifies items in place)
179
+ - **Use Case Example**: Reorder items, hide items based on permissions, add badges or notifications
180
+ - **File Reference**: src/features/common/MetaMenu.js:57
181
+
182
+ #### DropdownMenu Extension Pattern
183
+
184
+ **Extension Point**: Custom (passed via `extPoint` prop)
185
+
186
+ When a DropdownMenu component is rendered with an `extPoint` prop, it invokes that extension point:
187
+
188
+ ##### Custom Extension Point (via `extPoint` prop)
189
+
190
+ - **Purpose**: Allows plugins to modify dropdown menu items dynamically
191
+ - **When Invoked**: Called during DropdownMenu rendering, before items are processed
192
+ - **Context Parameters**:
193
+ - `items`: Array - The menu items array to modify
194
+ - `...extPointParams`: Variable arguments passed via the `extPointParams` prop
195
+ - **Expected Return**: `void` (modifies items array in place)
196
+ - **Use Case Example**: Add context-specific actions to record dropdown menus, filter items based on permissions
197
+ - **File Reference**: src/features/common/DropdownMenu.js:38
198
+
199
+ #### ConfigProvider Extension
200
+
201
+ ##### `museLibAntd.configProvider.processProps`
202
+
203
+ - **Purpose**: Allows plugins to modify Ant Design ConfigProvider props (e.g., theme tokens, component defaults)
204
+ - **When Invoked**: Called when ConfigProviderWrapper renders, before passing props to Ant Design's ConfigProvider
205
+ - **Context Parameters**:
206
+ - `configProps`: Object - The ConfigProvider props object with structure `{ theme: { algorithm: ... } }`
207
+ - **Expected Return**: `void` (modifies configProps in place)
208
+ - **Use Case Example**: Customize theme tokens (borderRadius, colors), add locale configuration, set component-level defaults
209
+ - **File Reference**: src/features/common/ConfigProviderWrapper.js:16
210
+
211
+ ### Usage Example
212
+
213
+ **CRITICAL**: Extension points are **nested object properties**, NOT string paths!
214
+
215
+ ```javascript
216
+ // Example: Extending a form via extendFormMeta
217
+ // ✅ CORRECT - nested object properties
218
+ plugin.register({
219
+ name: 'my-custom-plugin',
220
+ am: {
221
+ createAppForm: {
222
+ getFields: (context) => {
223
+ return [
224
+ {
225
+ key: 'customField',
226
+ label: 'Custom Field',
227
+ widget: 'input',
228
+ order: 100,
229
+ }
230
+ ];
231
+ },
232
+ processMeta: (context) => {
233
+ // Modify form metadata after fields are added
234
+ context.meta.fields.forEach(field => {
235
+ if (field.key === 'appName') {
236
+ field.required = true;
237
+ }
238
+ });
239
+ }
240
+ }
241
+ }
242
+ });
243
+
244
+ // Example: Customizing Ant Design theme
245
+ // ✅ CORRECT - nested object properties
246
+ plugin.register({
247
+ name: 'my-theme-plugin',
248
+ museLibAntd: {
249
+ configProvider: {
250
+ processProps: (configProps) => {
251
+ configProps.theme.token = {
252
+ colorPrimary: '#00b96b',
253
+ borderRadius: 2,
254
+ };
255
+ }
256
+ }
257
+ }
258
+ });
259
+
260
+ // Example: Adding items to a MetaMenu
261
+ // ✅ CORRECT - nested object properties
262
+ plugin.register({
263
+ name: 'my-menu-plugin',
264
+ museLayout: {
265
+ siderMenu: {
266
+ getItems: (meta) => {
267
+ return [
268
+ {
269
+ key: 'custom-item',
270
+ label: 'Custom Menu Item',
271
+ icon: 'star',
272
+ link: '/custom-page',
273
+ order: 50,
274
+ }
275
+ ];
276
+ }
277
+ }
278
+ }
279
+ });
280
+ ```
281
+
282
+ ---
283
+
284
+ ## 3. Extension Points Contributed
285
+
286
+ This plugin implements the following extension points from OTHER plugins to integrate with the MUSE ecosystem.
287
+
288
+ ### Summary
289
+
290
+ - **Total Contributions**: 3
291
+ - **Host Plugins**: @ebay/muse-lib-react
292
+
293
+ ### By Host Plugin
294
+
295
+ #### Contributes to: @ebay/muse-lib-react
296
+
297
+ ##### `route`
298
+
299
+ - **Invoked By**: @ebay/muse-lib-react routing system
300
+ - **What This Plugin Provides**: Route configuration for `/plugin-muse-antd` path with common feature routes
301
+ - **Why Needed**: Registers the plugin's route structure so it can be accessed via React Router
302
+ - **File Reference**: src/index.js:17, src/common/routeConfig.js:1-16
303
+
304
+ ##### `root.getProviders`
305
+
306
+ - **Invoked By**: @ebay/muse-lib-react root component provider chain
307
+ - **What This Plugin Provides**: Ant Design ConfigProviderWrapper with dark mode support
308
+ - **Why Needed**: Wraps the app with Ant Design's ConfigProvider to enable theming, localization, and component configuration. Sets order to 35 to ensure it wraps most other providers.
309
+ - **File Reference**: src/index.js:18-26, src/features/common/ConfigProviderWrapper.js:1-18
310
+
311
+ ##### `reducer`
312
+
313
+ - **Invoked By**: @ebay/muse-lib-react Redux store configuration
314
+ - **What This Plugin Provides**: Redux reducer managing common state (currently dark mode preference)
315
+ - **Why Needed**: Manages shared state for dark mode theme switching and persists preference to localStorage
316
+ - **File Reference**: src/index.js:27, src/common/rootReducer.js:1-14
317
+
318
+ ---
319
+
320
+ ## 4. Exported Functionality
321
+
322
+ This plugin exports the following functionality for use by other plugins.
323
+
324
+ **Access via**: `plugin.getPlugin('@ebay/muse-lib-antd').exports`
325
+
326
+ ### Library Modules (Shared Dependencies)
327
+
328
+ As a **lib plugin**, this plugin's primary export is the complete set of Ant Design and icon modules, which are automatically shared with consuming plugins via MUSE's module federation system:
329
+
330
+ #### Default Export Object
331
+
332
+ ```javascript
333
+ {
334
+ antd, // Complete Ant Design 5.x library (all components)
335
+ icons, // @ant-design/icons (all Ant Design icons)
336
+ utils, // This plugin's utility functions
337
+ }
338
+ ```
339
+
340
+ - **`antd`**: Complete Ant Design 5.19.0 component library
341
+ - **Access**: Other plugins import from 'antd' and it resolves to this shared instance
342
+ - **Why Exported**: Prevents duplicate Ant Design bundles across plugins, ensures version consistency
343
+ - **Components Include**: Button, Table, Form, Modal, Drawer, Menu, Layout, Input, Select, DatePicker, etc. (100+ components)
344
+
345
+ - **`icons`**: Complete @ant-design/icons 5.3.7 icon library
346
+ - **Access**: Other plugins import from '@ant-design/icons' and it resolves to this shared instance
347
+ - **Why Exported**: Prevents duplicate icon bundles, ensures consistent icon versions
348
+ - **Icons Include**: All Ant Design icons (outlined, filled, two-tone)
349
+
350
+ - **`utils`**: Utility functions for extensibility
351
+ - **Access**: Import from '@ebay/muse-lib-antd/src/utils'
352
+ - **Why Exported**: Provides helpers for making forms and arrays extensible via extension points
353
+
354
+ ### Components (from src/features/common)
355
+
356
+ The following custom components are exported via standard ES6 exports (not via plugin.exports):
357
+
358
+ #### UI Components
359
+
360
+ - **`MetaMenu`**: Metadata-driven menu component with extension point support
361
+ - **Purpose**: Render Ant Design menus from declarative configuration with plugin extensibility
362
+ - **Props**: `meta` (menu config), `baseExtPoint` (extension point base), `autoSort` (auto-sort items)
363
+ - **Use Cases**: Sidebar menus, header menus, dropdown menus with plugin-contributed items
364
+ - **File Reference**: src/features/common/MetaMenu.js:1-165
365
+
366
+ - **`DropdownMenu`**: Dropdown menu with actions and extension point support
367
+ - **Purpose**: Render dropdown menus with highlighted actions and extension points
368
+ - **Props**: `items`, `triggerNode`, `extPoint`, `extPointParams`, `size`
369
+ - **Use Cases**: Record action menus, context menus
370
+ - **File Reference**: src/features/common/DropdownMenu.js:1-93
371
+
372
+ - **`ErrorBox`**: Error display component with retry functionality
373
+ - **Purpose**: Display errors with stack traces, retry buttons, and customizable messaging
374
+ - **Props**: `title`, `content`, `error`, `onRetry`, `showStack`, `btnSize`
375
+ - **Use Cases**: Error boundaries, API error display, validation errors
376
+ - **File Reference**: src/features/common/ErrorBox.js
377
+
378
+ - **`ErrorBoundary`**: React error boundary component
379
+ - **Purpose**: Catch React rendering errors and display fallback UI
380
+ - **Props**: `message`, `children`
381
+ - **Use Cases**: Wrap components to prevent entire app crashes
382
+ - **File Reference**: src/features/common/ErrorBoundary.js
383
+
384
+ - **`GlobalLoading`**: Full-page or container loading indicator
385
+ - **Purpose**: Display loading spinner overlays
386
+ - **Props**: `full` (boolean for full-page mode)
387
+ - **Use Cases**: Page transitions, async data loading
388
+ - **File Reference**: src/features/common/GlobalLoading.js
389
+
390
+ - **`GlobalErrorBox`**: Modal error display
391
+ - **Purpose**: Display errors in modal dialogs
392
+ - **Props**: `title`, `error`, `onOk`, `okText`, `onClose`
393
+ - **Use Cases**: Critical errors, API failures that need user acknowledgment
394
+ - **File Reference**: src/features/common/GlobalErrorBox.js
395
+
396
+ - **`CodeViewer`**: Syntax-highlighted code display
397
+ - **Purpose**: Display formatted code with syntax highlighting and copy functionality
398
+ - **Props**: `code`, `language`, `theme`, `allowCopy`, `title`
399
+ - **Use Cases**: Display JSON, YAML, JavaScript, or other code snippets
400
+ - **File Reference**: src/features/common/CodeViewer.js
401
+
402
+ - **`BlockView`**: Formatted value display component
403
+ - **Purpose**: Display values in a consistent block format, with email link support
404
+ - **Props**: `value`, `openEmail`
405
+ - **Use Cases**: Display field values in view mode, form field previews
406
+ - **File Reference**: src/features/common/BlockView.js
407
+
408
+ - **`DateView`**: Date/time display component
409
+ - **Purpose**: Format and display dates/times with various format options
410
+ - **Props**: `value`, `dateOnly`, `timeOnly`, `dateFormat`, `timeFormat`
411
+ - **Use Cases**: Display timestamps, dates, or times in consistent format
412
+ - **File Reference**: src/features/common/DateView.js
413
+
414
+ - **`Highlighter`**: Text search highlighting component
415
+ - **Purpose**: Highlight search terms within text
416
+ - **Props**: `search`, `text`
417
+ - **Use Cases**: Search results, filtered lists
418
+ - **File Reference**: src/features/common/Highlighter.js
419
+
420
+ - **`Icon`**: Icon wrapper component
421
+ - **Purpose**: Render Ant Design icons with consistent API
422
+ - **Props**: `type`, `className`, `onClick`, `style`
423
+ - **Use Cases**: Consistent icon rendering across app
424
+ - **File Reference**: src/features/common/Icon.js
425
+
426
+ - **`LoadingMask`**: Inline loading indicator
427
+ - **Purpose**: Display loading state for components
428
+ - **Use Cases**: Inline component loading states
429
+ - **File Reference**: src/features/common/LoadingMask.js
430
+
431
+ - **`PageNotFound`**: 404 error page component
432
+ - **Purpose**: Display "page not found" error page
433
+ - **Use Cases**: React Router fallback route
434
+ - **File Reference**: src/features/common/PageNotFound.js
435
+
436
+ - **`RequestStatus`**: Request state management component
437
+ - **Purpose**: Handle loading, error, and success states for async requests
438
+ - **Props**: `pending`, `loading`, `error`, `errorMode`, `loadingMode`, `dismissError`
439
+ - **Use Cases**: Wrap async components to handle loading/error states
440
+ - **File Reference**: src/features/common/RequestStatus.js
441
+
442
+ - **`StatusLabel`**: Status badge component
443
+ - **Purpose**: Display status with colored labels
444
+ - **Props**: `label`, `type` (SUCCESS, FAILURE, PROCESSING, etc.)
445
+ - **Use Cases**: Display plugin status, request status, app status
446
+ - **File Reference**: src/features/common/StatusLabel.js
447
+
448
+ - **`TableBar`**: Table toolbar with search
449
+ - **Purpose**: Provide search bar and actions for tables
450
+ - **Props**: `onSearch`, `search`, `placeholder`, `children`
451
+ - **Use Cases**: Table filtering, bulk actions
452
+ - **File Reference**: src/features/common/TableBar.js
453
+
454
+ - **`TagInput`**: Tag input widget
455
+ - **Purpose**: Input component for entering multiple tags
456
+ - **Props**: `max`, `value`, `onChange`
457
+ - **Use Cases**: Form fields for arrays of strings (tags, labels, keywords)
458
+ - **File Reference**: src/features/common/TagInput.js
459
+
460
+ - **`ConfigProviderWrapper`**: Ant Design ConfigProvider with dark mode
461
+ - **Purpose**: Wrap app with Ant Design theme provider and dark mode support
462
+ - **Props**: `children`
463
+ - **Use Cases**: Root-level provider for Ant Design theming
464
+ - **File Reference**: src/features/common/ConfigProviderWrapper.js
465
+
466
+ ### Utilities (from src/utils.js)
467
+
468
+ - **`extendFormMeta(meta, extBase, ...args)`**: Make Nice Form metadata extensible
469
+ - **Purpose**: Allow plugins to extend form definitions via extension points
470
+ - **Parameters**:
471
+ - `meta`: FormMeta object with `fields` array
472
+ - `extBase`: String - base name for extension points (e.g., 'am.createAppForm')
473
+ - `...args`: Additional arguments passed to extension point handlers
474
+ - **Returns**: `{ watchingFields: Array, meta: FormMeta }`
475
+ - **Extension Points Invoked**:
476
+ - `${extBase}.preProcessMeta`
477
+ - `${extBase}.getFields`
478
+ - `${extBase}.processMeta`
479
+ - `${extBase}.postProcessMeta`
480
+ - `${extBase}.getWatchingFields`
481
+ - **Use Cases**: Create extensible forms in manager UIs where plugins can add custom fields
482
+ - **File Reference**: src/utils.js:11-23
483
+
484
+ - **`extendArray(arr, extName, extBase, ...args)`**: Make arrays extensible
485
+ - **Purpose**: Allow plugins to extend arrays (columns, actions, tabs, etc.) via extension points
486
+ - **Parameters**:
487
+ - `arr`: Array - the array to extend
488
+ - `extName`: String - name of the array type (e.g., 'columns', 'actions')
489
+ - `extBase`: String - base name for extension points (e.g., 'pm.pluginList')
490
+ - `...args`: Additional arguments passed to extension point handlers
491
+ - **Returns**: The modified array
492
+ - **Extension Points Invoked**:
493
+ - `${extBase}.preProcess${CapitalizedExtName}`
494
+ - `${extBase}.get${CapitalizedExtName}`
495
+ - `${extBase}.process${CapitalizedExtName}`
496
+ - `${extBase}.postProcess${CapitalizedExtName}`
497
+ - **Use Cases**: Create extensible table columns, action menus, tabs, etc.
498
+ - **File Reference**: src/utils.js:36-45
499
+
500
+ ### Other Resources
501
+
502
+ - **History Object**: Browser history singleton for programmatic navigation
503
+ - **Access**: Import from '@ebay/muse-lib-antd/src/common/history'
504
+ - **Type**: `BrowserHistory` from history v5
505
+ - **Global Access**: Also available at `window.MUSE_ANTD_HISTORY`
506
+ - **Methods**: `push(path)`, `replace(path)`, `go(n)`, `goBack()`, `goForward()`
507
+ - **Use Cases**: Navigate programmatically without React Router hooks, imperative navigation in non-component code
508
+ - **File Reference**: src/common/history.js:1-6
509
+
510
+ - **Table Configuration**: Default Ant Design table props and utilities
511
+ - **Access**: Import from '@ebay/muse-lib-antd/src/features/common/tableConfig'
512
+ - **Exports**: `defaultProps`, `defaultSorter`, `defaultFilter`
513
+ - **Use Cases**: Consistent table configuration across app
514
+ - **File Reference**: src/features/common/tableConfig.js:1-42
515
+
516
+ - **Redux State**: Dark mode state management
517
+ - **Hook**: `useSetIsDarkMode()` - Returns `{ isDarkMode, setIsDarkMode }`
518
+ - **Action**: `setIsDarkMode(isDarkMode)` - Dispatch action to toggle dark mode
519
+ - **Use Cases**: Theme switching, dark mode preferences
520
+ - **File Reference**: src/features/common/redux/setIsDarkMode.js:1-31
521
+
522
+ - **Modals**: Pre-registered Nice Modal React modals
523
+ - **Modal ID**: `'muse-lib-antd.loading-modal'`
524
+ - **Component**: LoadingModal
525
+ - **Use Cases**: Show loading dialogs via Nice Modal React
526
+ - **File Reference**: src/modals.js:1-4
527
+
528
+ - **Nice Form Widgets**: Custom form widgets registered with Nice Form
529
+ - **Widgets**:
530
+ - `'tag'`: TagInput component
531
+ - `'tag-view'`: BlockView component
532
+ - `'date-view'`: DateView (dateOnly)
533
+ - `'time-view'`: DateView (timeOnly)
534
+ - `'datetime-view'`: DateView (full)
535
+ - **Use Cases**: Use in Nice Form field definitions
536
+ - **File Reference**: src/initNiceForm.jsx:1-16
537
+
538
+ ### Using Exported Functionality
539
+
540
+ ```javascript
541
+ // Accessing shared Ant Design components (automatic via module federation)
542
+ import { Button, Table, Form } from 'antd';
543
+ import { UserOutlined, SearchOutlined } from '@ant-design/icons';
544
+
545
+ // Using custom components
546
+ import {
547
+ MetaMenu,
548
+ DropdownMenu,
549
+ ErrorBox,
550
+ CodeViewer,
551
+ DateView
552
+ } from '@ebay/muse-lib-antd/src/features/common';
553
+
554
+ // Using utilities
555
+ import { extendFormMeta, extendArray } from '@ebay/muse-lib-antd/src/utils';
556
+
557
+ // Example: Make a form extensible
558
+ const meta = {
559
+ fields: [
560
+ { key: 'name', label: 'Name', widget: 'input' }
561
+ ]
562
+ };
563
+
564
+ const { watchingFields, meta: extendedMeta } = extendFormMeta(
565
+ meta,
566
+ 'myPlugin.myForm',
567
+ { context: 'additional data' }
568
+ );
569
+
570
+ // Example: Make a table columns array extensible
571
+ const columns = [
572
+ { key: 'name', title: 'Name', dataIndex: 'name' }
573
+ ];
574
+
575
+ extendArray(columns, 'columns', 'myPlugin.myTable', tableData);
576
+
577
+ // Example: Using dark mode
578
+ import { useSetIsDarkMode } from '@ebay/muse-lib-antd/src/features/common/redux/hooks';
579
+
580
+ function MyComponent() {
581
+ const { isDarkMode, setIsDarkMode } = useSetIsDarkMode();
582
+
583
+ return (
584
+ <button onClick={() => setIsDarkMode(!isDarkMode)}>
585
+ Toggle Theme (current: {isDarkMode ? 'dark' : 'light'})
586
+ </button>
587
+ );
588
+ }
589
+
590
+ // Example: Using MetaMenu
591
+ const menuMeta = {
592
+ items: [
593
+ { key: 'home', label: 'Home', link: '/', icon: 'home' },
594
+ { key: 'settings', label: 'Settings', link: '/settings', icon: 'setting' }
595
+ ],
596
+ autoActive: true,
597
+ mode: 'inline'
598
+ };
599
+
600
+ <MetaMenu
601
+ meta={menuMeta}
602
+ baseExtPoint="myPlugin.siderMenu"
603
+ autoSort={true}
604
+ />
605
+
606
+ // Example: Using history for programmatic navigation
607
+ import history from '@ebay/muse-lib-antd/src/common/history';
608
+
609
+ // Navigate to a different route
610
+ function handleCreateSuccess(newId) {
611
+ history.push(`/items/${newId}`);
612
+ }
613
+
614
+ // Or access via global
615
+ window.MUSE_ANTD_HISTORY.push('/dashboard');
616
+ ```
617
+
618
+ **Note**: As a lib plugin, the primary value is providing shared Ant Design modules. The custom components and utilities are secondary exports that build on top of the shared foundation.
619
+
620
+ ---
621
+
622
+ ## 5. Integration Examples
623
+
624
+ **CRITICAL**: Extension points are **nested object properties**, NOT string paths!
625
+
626
+ ### ✅ CORRECT Syntax
627
+ ```javascript
628
+ plugin.register({
629
+ name: 'my-plugin',
630
+ pluginName: {
631
+ extensionPoint: (context) => {
632
+ // Your implementation
633
+ }
634
+ }
635
+ });
636
+ ```
637
+
638
+ ### ❌ INCORRECT Syntax
639
+ ```javascript
640
+ plugin.register({
641
+ name: 'my-plugin',
642
+ 'pluginName.extensionPoint': (context) => { // WRONG!
643
+ // This will NOT work!
644
+ }
645
+ });
646
+ ```
647
+
648
+ ---
649
+
650
+ ### Example 1: Using Shared Ant Design Components
651
+
652
+ Since `@ebay/muse-lib-antd` is a lib plugin, consuming plugins automatically use its shared Ant Design instance:
653
+
654
+ ```javascript
655
+ // In your plugin - automatically uses shared antd from muse-lib-antd
656
+ import React from 'react';
657
+ import { Button, Table, Form, Modal } from 'antd';
658
+ import { UserOutlined, PlusOutlined } from '@ant-design/icons';
659
+
660
+ export default function MyComponent() {
661
+ return (
662
+ <div>
663
+ <Button type="primary" icon={<PlusOutlined />}>
664
+ Create User
665
+ </Button>
666
+ <Table
667
+ dataSource={data}
668
+ columns={columns}
669
+ />
670
+ </div>
671
+ );
672
+ }
673
+ ```
674
+
675
+ ### Example 2: Extending Forms with Custom Fields
676
+
677
+ ```javascript
678
+ import plugin from 'js-plugin';
679
+
680
+ // ✅ CORRECT - nested object properties
681
+ plugin.register({
682
+ name: 'my-custom-plugin',
683
+
684
+ // Add fields to the create app form
685
+ am: {
686
+ createAppForm: {
687
+ getFields: (context) => {
688
+ return [
689
+ {
690
+ key: 'githubRepo',
691
+ label: 'GitHub Repository',
692
+ widget: 'input',
693
+ placeholder: 'org/repo',
694
+ order: 100,
695
+ required: true,
696
+ },
697
+ {
698
+ key: 'slackChannel',
699
+ label: 'Slack Channel',
700
+ widget: 'input',
701
+ placeholder: '#channel-name',
702
+ order: 101,
703
+ }
704
+ ];
705
+ },
706
+
707
+ // Modify form after all fields are added
708
+ processMeta: (context) => {
709
+ const { meta } = context;
710
+
711
+ // Make appName field required
712
+ const appNameField = meta.fields.find(f => f.key === 'appName');
713
+ if (appNameField) {
714
+ appNameField.required = true;
715
+ appNameField.rules = [
716
+ { required: true, message: 'App name is required' },
717
+ { pattern: /^[a-z][a-z0-9-]*$/, message: 'Must start with letter, use lowercase and hyphens only' }
718
+ ];
719
+ }
720
+ }
721
+ }
722
+ }
723
+ });
724
+ ```
725
+
726
+ ### Example 3: Customizing Ant Design Theme
727
+
728
+ ```javascript
729
+ import plugin from 'js-plugin';
730
+
731
+ // ✅ CORRECT - nested object properties
732
+ plugin.register({
733
+ name: 'my-theme-plugin',
734
+
735
+ museLibAntd: {
736
+ configProvider: {
737
+ processProps: (configProps) => {
738
+ // Customize theme tokens
739
+ configProps.theme.token = {
740
+ colorPrimary: '#1890ff', // Primary color
741
+ colorSuccess: '#52c41a', // Success color
742
+ colorWarning: '#faad14', // Warning color
743
+ colorError: '#f5222d', // Error color
744
+ borderRadius: 4, // Border radius for components
745
+ fontSize: 14, // Base font size
746
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial',
747
+ };
748
+
749
+ // Add component-level configurations
750
+ configProps.button = {
751
+ defaultProps: {
752
+ size: 'middle'
753
+ }
754
+ };
755
+
756
+ // Add locale if needed
757
+ // configProps.locale = enUS;
758
+ }
759
+ }
760
+ }
761
+ });
762
+ ```
763
+
764
+ ### Example 4: Creating Extensible UI with MetaMenu
765
+
766
+ ```javascript
767
+ import React from 'react';
768
+ import { MetaMenu } from '@ebay/muse-lib-antd/src/features/common';
769
+ import plugin from 'js-plugin';
770
+
771
+ // Define base menu
772
+ function MySidebar() {
773
+ const menuMeta = {
774
+ items: [
775
+ {
776
+ key: 'dashboard',
777
+ label: 'Dashboard',
778
+ link: '/dashboard',
779
+ icon: 'dashboard',
780
+ order: 0
781
+ },
782
+ {
783
+ key: 'users',
784
+ label: 'Users',
785
+ link: '/users',
786
+ icon: 'user',
787
+ order: 10
788
+ },
789
+ ],
790
+ mode: 'inline',
791
+ autoActive: true,
792
+ };
793
+
794
+ return (
795
+ <MetaMenu
796
+ meta={menuMeta}
797
+ baseExtPoint="myApp.siderMenu"
798
+ autoSort={true}
799
+ />
800
+ );
801
+ }
802
+
803
+ // Other plugins can extend the menu
804
+ // ✅ CORRECT - nested object properties
805
+ plugin.register({
806
+ name: 'my-extension-plugin',
807
+
808
+ myApp: {
809
+ siderMenu: {
810
+ getItems: (meta) => {
811
+ return [
812
+ {
813
+ key: 'custom-feature',
814
+ label: 'Custom Feature',
815
+ link: '/custom',
816
+ icon: 'star',
817
+ order: 20,
818
+ }
819
+ ];
820
+ },
821
+
822
+ processItems: (meta, items, itemByKey) => {
823
+ // Hide users menu if user doesn't have permission
824
+ const usersItem = itemByKey['users'];
825
+ if (usersItem && !userHasPermission('view_users')) {
826
+ items.splice(items.indexOf(usersItem), 1);
827
+ }
828
+ }
829
+ }
830
+ }
831
+ });
832
+ ```
833
+
834
+ ### Example 5: Using Extensibility Utilities
835
+
836
+ ```javascript
837
+ import React from 'react';
838
+ import { extendFormMeta, extendArray } from '@ebay/muse-lib-antd/src/utils';
839
+ import NiceForm from '@ebay/nice-form-react';
840
+
841
+ function MyForm({ record }) {
842
+ // Create extensible form
843
+ const baseMeta = {
844
+ fields: [
845
+ { key: 'name', label: 'Name', widget: 'input', required: true },
846
+ { key: 'email', label: 'Email', widget: 'input', required: true },
847
+ ]
848
+ };
849
+
850
+ const { meta, watchingFields } = extendFormMeta(
851
+ baseMeta,
852
+ 'myPlugin.userForm',
853
+ { record, mode: 'create' }
854
+ );
855
+
856
+ return <NiceForm meta={meta} />;
857
+ }
858
+
859
+ // Create extensible table columns
860
+ function MyTable({ dataSource }) {
861
+ const columns = [
862
+ { key: 'name', title: 'Name', dataIndex: 'name', sorter: true },
863
+ { key: 'email', title: 'Email', dataIndex: 'email' },
864
+ ];
865
+
866
+ // Allow plugins to add columns
867
+ extendArray(columns, 'columns', 'myPlugin.userTable', { dataSource });
868
+
869
+ return <Table dataSource={dataSource} columns={columns} />;
870
+ }
871
+
872
+ // Other plugins can extend these
873
+ // ✅ CORRECT - nested object properties
874
+ plugin.register({
875
+ name: 'my-extension',
876
+
877
+ myPlugin: {
878
+ userForm: {
879
+ getFields: ({ record, mode }) => {
880
+ if (mode === 'create') {
881
+ return [
882
+ {
883
+ key: 'role',
884
+ label: 'Role',
885
+ widget: 'select',
886
+ options: ['admin', 'user'],
887
+ order: 50
888
+ }
889
+ ];
890
+ }
891
+ return [];
892
+ }
893
+ },
894
+
895
+ userTable: {
896
+ getColumns: ({ dataSource }) => {
897
+ return [
898
+ {
899
+ key: 'role',
900
+ title: 'Role',
901
+ dataIndex: 'role',
902
+ filters: [
903
+ { text: 'Admin', value: 'admin' },
904
+ { text: 'User', value: 'user' }
905
+ ],
906
+ onFilter: (value, record) => record.role === value,
907
+ order: 50
908
+ }
909
+ ];
910
+ }
911
+ }
912
+ }
913
+ });
914
+ ```
915
+
916
+ ### Example 6: Using Custom Components
917
+
918
+ ```javascript
919
+ import React from 'react';
920
+ import {
921
+ ErrorBox,
922
+ CodeViewer,
923
+ DateView,
924
+ Highlighter,
925
+ StatusLabel,
926
+ DropdownMenu
927
+ } from '@ebay/muse-lib-antd/src/features/common';
928
+
929
+ function MyComponent({ data, error, searchTerm }) {
930
+ if (error) {
931
+ return (
932
+ <ErrorBox
933
+ title="Failed to Load Data"
934
+ error={error}
935
+ onRetry={handleRetry}
936
+ showStack={true}
937
+ />
938
+ );
939
+ }
940
+
941
+ return (
942
+ <div>
943
+ {/* Display formatted code */}
944
+ <CodeViewer
945
+ code={JSON.stringify(data, null, 2)}
946
+ language="json"
947
+ theme="dark"
948
+ allowCopy={true}
949
+ />
950
+
951
+ {/* Display dates */}
952
+ <DateView value={data.createdAt} dateOnly />
953
+
954
+ {/* Highlight search terms */}
955
+ <Highlighter text={data.description} search={searchTerm} />
956
+
957
+ {/* Display status */}
958
+ <StatusLabel label={data.status} type="SUCCESS" />
959
+
960
+ {/* Dropdown menu with actions */}
961
+ <DropdownMenu
962
+ items={[
963
+ { key: 'edit', label: 'Edit', icon: 'edit', onClick: handleEdit },
964
+ { key: 'delete', label: 'Delete', icon: 'delete', onClick: handleDelete }
965
+ ]}
966
+ size="small"
967
+ />
968
+ </div>
969
+ );
970
+ }
971
+ ```