@syuttechnologies/layout 1.0.1 → 1.0.21
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 +536 -0
- package/dist/components/ChangePasswordModal.d.ts.map +1 -1
- package/dist/components/ChangePasswordModal.js +22 -11
- package/dist/components/EnterpriseLayout.d.ts.map +1 -1
- package/dist/components/EnterpriseLayout.js +21 -6
- package/dist/components/ui/ActionMenu/ActionMenu.d.ts +52 -0
- package/dist/components/ui/ActionMenu/ActionMenu.d.ts.map +1 -0
- package/dist/components/ui/ActionMenu/ActionMenu.js +116 -0
- package/dist/components/ui/ActionMenu/index.d.ts +3 -0
- package/dist/components/ui/ActionMenu/index.d.ts.map +1 -0
- package/dist/components/ui/ActionMenu/index.js +2 -0
- package/dist/components/ui/ModuleHeader/ModuleHeader.d.ts +90 -0
- package/dist/components/ui/ModuleHeader/ModuleHeader.d.ts.map +1 -0
- package/dist/components/ui/ModuleHeader/ModuleHeader.js +433 -0
- package/dist/components/ui/ModuleHeader/index.d.ts +3 -0
- package/dist/components/ui/ModuleHeader/index.d.ts.map +1 -0
- package/dist/components/ui/ModuleHeader/index.js +1 -0
- package/dist/components/ui/SyutGrid/SyutGrid.d.ts +74 -0
- package/dist/components/ui/SyutGrid/SyutGrid.d.ts.map +1 -0
- package/dist/components/ui/SyutGrid/SyutGrid.js +306 -0
- package/dist/components/ui/SyutGrid/index.d.ts +3 -0
- package/dist/components/ui/SyutGrid/index.d.ts.map +1 -0
- package/dist/components/ui/SyutGrid/index.js +2 -0
- package/dist/components/ui/SyutSelect/SyutSelectUnified.d.ts +128 -0
- package/dist/components/ui/SyutSelect/SyutSelectUnified.d.ts.map +1 -0
- package/dist/components/ui/SyutSelect/SyutSelectUnified.js +679 -0
- package/dist/components/ui/SyutSelect/index.d.ts +3 -0
- package/dist/components/ui/SyutSelect/index.d.ts.map +1 -0
- package/dist/components/ui/SyutSelect/index.js +2 -0
- package/dist/icon-collection/icon-systems.d.ts +89 -0
- package/dist/icon-collection/icon-systems.d.ts.map +1 -0
- package/dist/icon-collection/icon-systems.js +70 -0
- package/dist/icon-collection/index.d.ts +4 -0
- package/dist/icon-collection/index.d.ts.map +1 -0
- package/dist/icon-collection/index.js +8 -0
- package/dist/index.d.ts +12 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -1
- package/package.json +9 -4
- package/src/components/ChangePasswordModal.tsx +26 -14
- package/src/components/EnterpriseLayout.tsx +23 -8
- package/src/components/ui/ActionMenu/ActionMenu.tsx +222 -0
- package/src/components/ui/ActionMenu/index.ts +2 -0
- package/src/components/ui/ModuleHeader/ModuleHeader.tsx +722 -0
- package/src/components/ui/ModuleHeader/index.ts +9 -0
- package/src/components/ui/SyutGrid/SyutGrid.tsx +483 -0
- package/src/components/ui/SyutGrid/index.ts +2 -0
- package/src/components/ui/SyutSelect/SyutSelectUnified.tsx +1115 -0
- package/src/components/ui/SyutSelect/index.ts +3 -0
- package/src/icon-collection/icon-systems.tsx +464 -0
- package/src/icon-collection/index.ts +13 -0
- package/src/index.ts +47 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -110,7 +110,6 @@ export const EnterpriseLayout = ({ config, componentRegistry, children, router =
|
|
|
110
110
|
setDynamicNavigation(parsedNavigation);
|
|
111
111
|
// Update expanded sections for the new navigation
|
|
112
112
|
setExpandedSections(new Set(parsedNavigation.map((n) => n.section)));
|
|
113
|
-
setExpandedOverviewSections(new Set(parsedNavigation.filter((sec) => sec.section !== "Dashboard").map((sec) => sec.section)));
|
|
114
113
|
}
|
|
115
114
|
}
|
|
116
115
|
catch (error) {
|
|
@@ -142,10 +141,25 @@ export const EnterpriseLayout = ({ config, componentRegistry, children, router =
|
|
|
142
141
|
}
|
|
143
142
|
}
|
|
144
143
|
}, []);
|
|
144
|
+
// Sync dynamicModules when config.modules prop changes (if no localStorage override)
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
const storedModules = localStorage.getItem('MODULES_CONFIG');
|
|
147
|
+
if (!storedModules && config.modules) {
|
|
148
|
+
setDynamicModules(config.modules);
|
|
149
|
+
}
|
|
150
|
+
}, [config.modules]);
|
|
151
|
+
// Sync dynamicNavigation when config.navigation prop changes (if no localStorage override)
|
|
152
|
+
useEffect(() => {
|
|
153
|
+
const storedNavigation = localStorage.getItem('NAVIGATION_MENU');
|
|
154
|
+
if (!storedNavigation && config.navigation) {
|
|
155
|
+
setDynamicNavigation(config.navigation);
|
|
156
|
+
setExpandedSections(new Set(config.navigation.map((n) => n.section)));
|
|
157
|
+
}
|
|
158
|
+
}, [config.navigation]);
|
|
145
159
|
// User preference for auto-collapse (configurable)
|
|
146
160
|
const [autoCollapseEnabled, setAutoCollapseEnabled] = useState(config.layout.autoCollapseSidebar);
|
|
147
161
|
// Overview tab section management
|
|
148
|
-
const [expandedOverviewSections, setExpandedOverviewSections] = useState(new Set(
|
|
162
|
+
const [expandedOverviewSections, setExpandedOverviewSections] = useState(new Set());
|
|
149
163
|
// React 18 Concurrent Features
|
|
150
164
|
const [isPending, startTransition] = useTransition();
|
|
151
165
|
const deferredActiveTab = useDeferredValue(activeTab);
|
|
@@ -994,7 +1008,7 @@ export const EnterpriseLayout = ({ config, componentRegistry, children, router =
|
|
|
994
1008
|
|
|
995
1009
|
.tab-content-area {
|
|
996
1010
|
flex: 1;
|
|
997
|
-
overflow:
|
|
1011
|
+
overflow: auto;
|
|
998
1012
|
width: 100%;
|
|
999
1013
|
height: 100%;
|
|
1000
1014
|
min-height: 0;
|
|
@@ -1006,7 +1020,7 @@ export const EnterpriseLayout = ({ config, componentRegistry, children, router =
|
|
|
1006
1020
|
display: none;
|
|
1007
1021
|
width: 100%;
|
|
1008
1022
|
height: 100%;
|
|
1009
|
-
overflow:
|
|
1023
|
+
overflow: auto;
|
|
1010
1024
|
box-sizing: border-box;
|
|
1011
1025
|
}
|
|
1012
1026
|
|
|
@@ -1292,6 +1306,7 @@ export const EnterpriseLayout = ({ config, componentRegistry, children, router =
|
|
|
1292
1306
|
cursor: pointer;
|
|
1293
1307
|
transition: all 0.3s ease;
|
|
1294
1308
|
flex-shrink: 0;
|
|
1309
|
+
z-index: 10002;
|
|
1295
1310
|
}
|
|
1296
1311
|
|
|
1297
1312
|
.persona-control:hover {
|
|
@@ -1332,7 +1347,7 @@ export const EnterpriseLayout = ({ config, componentRegistry, children, router =
|
|
|
1332
1347
|
border-radius: 1rem;
|
|
1333
1348
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
|
1334
1349
|
padding: 1rem;
|
|
1335
|
-
z-index:
|
|
1350
|
+
z-index: 10001;
|
|
1336
1351
|
margin-top: 0.5rem;
|
|
1337
1352
|
opacity: 0;
|
|
1338
1353
|
visibility: hidden;
|
|
@@ -2616,7 +2631,7 @@ export const EnterpriseLayout = ({ config, componentRegistry, children, router =
|
|
|
2616
2631
|
}, children: "Tabs" }), _jsx("button", { className: `view-mode-btn ${!tabModeEnabled ? "active" : ""}`, onClick: (e) => {
|
|
2617
2632
|
e.stopPropagation();
|
|
2618
2633
|
startTransition(() => setTabModeEnabled(false));
|
|
2619
|
-
}, children: "Single" })] })] }), _jsxs("div", { className: "persona-control-item", children: [_jsxs("div", { className: "persona-control-label", children: [_jsx(IconSystem.settings, {}), "Dark Mode
|
|
2634
|
+
}, children: "Single" })] })] }), _jsxs("div", { className: "persona-control-item", children: [_jsxs("div", { className: "persona-control-label", children: [_jsx(IconSystem.settings, {}), "Dark Mode-7"] }), _jsx("div", { className: `theme-switch ${darkMode ? "active" : ""}`, onClick: (e) => {
|
|
2620
2635
|
e.stopPropagation();
|
|
2621
2636
|
toggleTheme();
|
|
2622
2637
|
}, children: _jsx("div", { className: "theme-switch-handle" }) })] }), _jsxs("div", { className: "persona-control-item", children: [_jsxs("div", { className: "persona-control-label", children: [_jsx(IconSystem.footer, {}), "Show Footer"] }), _jsx("div", { className: `theme-switch ${footerVisible ? "active" : ""}`, onClick: (e) => {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
export interface ActionMenuItem<T = any> {
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
icon?: ReactNode;
|
|
6
|
+
onClick: (() => void) | ((row: T) => void);
|
|
7
|
+
variant?: 'default' | 'danger';
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
isVisible?: (row: T) => boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface ProcessedActionMenuItem {
|
|
12
|
+
id: string;
|
|
13
|
+
label: string;
|
|
14
|
+
icon?: ReactNode;
|
|
15
|
+
onClick: () => void;
|
|
16
|
+
variant?: 'default' | 'danger';
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface ActionMenuProps {
|
|
20
|
+
/** Unique identifier for the menu */
|
|
21
|
+
id?: string;
|
|
22
|
+
/** Array of menu items to display - accepts both processed and raw items */
|
|
23
|
+
items: ProcessedActionMenuItem[] | ActionMenuItem[];
|
|
24
|
+
/** Custom trigger button content */
|
|
25
|
+
triggerContent?: ReactNode;
|
|
26
|
+
/** Additional class name for the trigger button */
|
|
27
|
+
triggerClassName?: string;
|
|
28
|
+
/** Menu position preference */
|
|
29
|
+
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
30
|
+
/** Callback when menu opens/closes */
|
|
31
|
+
onOpenChange?: (isOpen: boolean) => void;
|
|
32
|
+
/** Disabled state */
|
|
33
|
+
disabled?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* ActionMenu - A reusable dropdown menu component that uses React Portal
|
|
37
|
+
* to render outside of parent containers, avoiding overflow clipping issues.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```tsx
|
|
41
|
+
* <ActionMenu
|
|
42
|
+
* items={[
|
|
43
|
+
* { id: 'view', label: 'View', icon: <EyeIcon />, onClick: () => handleView() },
|
|
44
|
+
* { id: 'edit', label: 'Edit', icon: <EditIcon />, onClick: () => handleEdit() },
|
|
45
|
+
* { id: 'delete', label: 'Delete', icon: <TrashIcon />, onClick: () => handleDelete(), variant: 'danger' },
|
|
46
|
+
* ]}
|
|
47
|
+
* />
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare const ActionMenu: React.FC<ActionMenuProps>;
|
|
51
|
+
export default ActionMenu;
|
|
52
|
+
//# sourceMappingURL=ActionMenu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ActionMenu.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/ActionMenu/ActionMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAoB,SAAS,EAAE,MAAM,OAAO,CAAC;AAQ3D,MAAM,WAAW,cAAc,CAAC,CAAC,GAAG,GAAG;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,CAAC;IAC3C,OAAO,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC;CACjC;AAGD,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,qCAAqC;IACrC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,4EAA4E;IAC5E,KAAK,EAAE,uBAAuB,EAAE,GAAG,cAAc,EAAE,CAAC;IACpD,oCAAoC;IACpC,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,mDAAmD;IACnD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,cAAc,GAAG,aAAa,GAAG,WAAW,GAAG,UAAU,CAAC;IACrE,sCAAsC;IACtC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAMD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA0JhD,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import React, { useState, useRef } from 'react';
|
|
3
|
+
import { createPortal } from 'react-dom';
|
|
4
|
+
import IconSystem from '../../../icon-collection/icon-systems';
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// COMPONENT
|
|
7
|
+
// ============================================================================
|
|
8
|
+
/**
|
|
9
|
+
* ActionMenu - A reusable dropdown menu component that uses React Portal
|
|
10
|
+
* to render outside of parent containers, avoiding overflow clipping issues.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* <ActionMenu
|
|
15
|
+
* items={[
|
|
16
|
+
* { id: 'view', label: 'View', icon: <EyeIcon />, onClick: () => handleView() },
|
|
17
|
+
* { id: 'edit', label: 'Edit', icon: <EditIcon />, onClick: () => handleEdit() },
|
|
18
|
+
* { id: 'delete', label: 'Delete', icon: <TrashIcon />, onClick: () => handleDelete(), variant: 'danger' },
|
|
19
|
+
* ]}
|
|
20
|
+
* />
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export const ActionMenu = ({ id, items, triggerContent, triggerClassName = '', position = 'bottom-right', onOpenChange, disabled = false, }) => {
|
|
24
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
25
|
+
const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 });
|
|
26
|
+
const triggerRef = useRef(null);
|
|
27
|
+
const calculatePosition = () => {
|
|
28
|
+
if (!triggerRef.current)
|
|
29
|
+
return;
|
|
30
|
+
const rect = triggerRef.current.getBoundingClientRect();
|
|
31
|
+
const menuHeight = 200; // Approximate menu height
|
|
32
|
+
const menuWidth = 180; // Approximate menu width
|
|
33
|
+
const viewportHeight = window.innerHeight;
|
|
34
|
+
const viewportWidth = window.innerWidth;
|
|
35
|
+
const spaceBelow = viewportHeight - rect.bottom;
|
|
36
|
+
const spaceRight = viewportWidth - rect.right;
|
|
37
|
+
let top;
|
|
38
|
+
let left;
|
|
39
|
+
// Determine vertical position
|
|
40
|
+
const shouldOpenUpward = position.startsWith('top') || spaceBelow < menuHeight;
|
|
41
|
+
if (shouldOpenUpward) {
|
|
42
|
+
top = rect.top - menuHeight - 4;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
top = rect.bottom + 4;
|
|
46
|
+
}
|
|
47
|
+
// Determine horizontal position
|
|
48
|
+
const shouldOpenLeft = position.endsWith('left') || spaceRight < menuWidth;
|
|
49
|
+
if (shouldOpenLeft) {
|
|
50
|
+
left = Math.max(8, rect.left);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
left = Math.max(8, rect.right - menuWidth);
|
|
54
|
+
}
|
|
55
|
+
// Ensure menu stays within viewport
|
|
56
|
+
top = Math.max(8, Math.min(top, viewportHeight - menuHeight - 8));
|
|
57
|
+
left = Math.max(8, Math.min(left, viewportWidth - menuWidth - 8));
|
|
58
|
+
setMenuPosition({ top, left });
|
|
59
|
+
};
|
|
60
|
+
const openMenu = () => {
|
|
61
|
+
if (disabled)
|
|
62
|
+
return;
|
|
63
|
+
calculatePosition();
|
|
64
|
+
setIsOpen(true);
|
|
65
|
+
onOpenChange?.(true);
|
|
66
|
+
};
|
|
67
|
+
const closeMenu = () => {
|
|
68
|
+
setIsOpen(false);
|
|
69
|
+
onOpenChange?.(false);
|
|
70
|
+
};
|
|
71
|
+
const handleItemClick = (item) => {
|
|
72
|
+
if (item.disabled)
|
|
73
|
+
return;
|
|
74
|
+
// Both processed and raw items should have onClick as () => void when used directly
|
|
75
|
+
item.onClick();
|
|
76
|
+
closeMenu();
|
|
77
|
+
};
|
|
78
|
+
const handleTriggerClick = (e) => {
|
|
79
|
+
e.preventDefault();
|
|
80
|
+
e.stopPropagation();
|
|
81
|
+
if (isOpen) {
|
|
82
|
+
closeMenu();
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
openMenu();
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
return (_jsxs("div", { className: "action-menu-container", id: id, children: [_jsx("button", { ref: triggerRef, className: `action-menu-trigger ${isOpen ? 'active' : ''} ${triggerClassName}`, onClick: handleTriggerClick, type: "button", disabled: disabled, "aria-haspopup": "menu", "aria-expanded": isOpen, children: triggerContent || _jsx(IconSystem.moreVertical, { size: 16 }) }), isOpen && createPortal(_jsxs(_Fragment, { children: [_jsx("div", { onClick: closeMenu, style: {
|
|
89
|
+
position: 'fixed',
|
|
90
|
+
top: 0,
|
|
91
|
+
left: 0,
|
|
92
|
+
right: 0,
|
|
93
|
+
bottom: 0,
|
|
94
|
+
zIndex: 9998,
|
|
95
|
+
background: 'transparent',
|
|
96
|
+
}, "aria-hidden": "true" }), _jsx("div", { role: "menu", onClick: (e) => e.stopPropagation(), style: {
|
|
97
|
+
position: 'fixed',
|
|
98
|
+
top: menuPosition.top,
|
|
99
|
+
left: menuPosition.left,
|
|
100
|
+
zIndex: 9999,
|
|
101
|
+
minWidth: '180px',
|
|
102
|
+
maxHeight: '280px',
|
|
103
|
+
overflowY: 'auto',
|
|
104
|
+
background: 'white',
|
|
105
|
+
border: '2px solid var(--primary)',
|
|
106
|
+
borderRadius: '8px',
|
|
107
|
+
boxShadow: '0 12px 32px rgba(37, 99, 235, 0.2)',
|
|
108
|
+
padding: '0.5rem',
|
|
109
|
+
}, children: items.map((item, index) => {
|
|
110
|
+
// Check if we should add a divider before this item
|
|
111
|
+
const prevItem = items[index - 1];
|
|
112
|
+
const showDivider = prevItem && prevItem.variant !== 'danger' && item.variant === 'danger';
|
|
113
|
+
return (_jsxs(React.Fragment, { children: [showDivider && _jsx("div", { className: "action-menu-divider" }), _jsxs("button", { role: "menuitem", className: `action-menu-item ${item.variant === 'danger' ? 'action-menu-item-danger' : ''}`, onClick: () => handleItemClick(item), disabled: item.disabled, children: [item.icon, _jsx("span", { children: item.label })] })] }, item.id));
|
|
114
|
+
}) })] }), document.body)] }));
|
|
115
|
+
};
|
|
116
|
+
export default ActionMenu;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/ActionMenu/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,KAAK,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACnH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* ============================================================================
|
|
4
|
+
* MODULE HEADER COMPONENT - REUSABLE HEADER FOR ALL MASTER SCREENS
|
|
5
|
+
* ============================================================================
|
|
6
|
+
*
|
|
7
|
+
* A flexible, configurable header component that can be used across all
|
|
8
|
+
* master screens (Service Master, GL Master, Customer Master, etc.)
|
|
9
|
+
*
|
|
10
|
+
* FEATURES:
|
|
11
|
+
* - Configurable title and description
|
|
12
|
+
* - Optional search functionality
|
|
13
|
+
* - Flexible view mode toggles (list, grid, calendar, etc.)
|
|
14
|
+
* - Optional filter button with active count badge
|
|
15
|
+
* - Custom toolbar items slot (for Column Selector, etc.)
|
|
16
|
+
* - Configurable action buttons (Add, Refresh, Export, Delete, etc.)
|
|
17
|
+
* - Responsive design with mobile overflow menu
|
|
18
|
+
* - Type-safe with TypeScript
|
|
19
|
+
* - Easy to extend without modifying base component
|
|
20
|
+
* ============================================================================
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Configuration for an individual action button
|
|
24
|
+
*/
|
|
25
|
+
export interface ActionButton {
|
|
26
|
+
id: string;
|
|
27
|
+
icon: React.ReactNode;
|
|
28
|
+
label: string;
|
|
29
|
+
onClick: () => void;
|
|
30
|
+
tooltip?: string;
|
|
31
|
+
disabled?: boolean;
|
|
32
|
+
variant?: 'primary' | 'secondary' | 'icon' | 'danger';
|
|
33
|
+
visible?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Configuration for view mode options (list, grid, calendar, etc.)
|
|
37
|
+
*/
|
|
38
|
+
export interface ViewModeOption {
|
|
39
|
+
id: string;
|
|
40
|
+
icon: React.ReactNode;
|
|
41
|
+
label: string;
|
|
42
|
+
tooltip?: string;
|
|
43
|
+
disabled?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Configuration for the search bar
|
|
47
|
+
*/
|
|
48
|
+
export interface SearchConfig {
|
|
49
|
+
value: string;
|
|
50
|
+
onChange: (value: string) => void;
|
|
51
|
+
placeholder?: string;
|
|
52
|
+
disabled?: boolean;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Configuration for view mode toggle
|
|
56
|
+
*/
|
|
57
|
+
export interface ViewModeConfig {
|
|
58
|
+
currentMode: string;
|
|
59
|
+
modes: ViewModeOption[];
|
|
60
|
+
onChange: (mode: string) => void;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Configuration for the filter button
|
|
64
|
+
*/
|
|
65
|
+
export interface FilterConfig {
|
|
66
|
+
onClick: () => void;
|
|
67
|
+
isActive?: boolean;
|
|
68
|
+
activeCount?: number;
|
|
69
|
+
badgeCount?: number;
|
|
70
|
+
disabled?: boolean;
|
|
71
|
+
tooltip?: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Main props for the ModuleHeader component
|
|
75
|
+
*/
|
|
76
|
+
export interface ModuleHeaderProps {
|
|
77
|
+
title: string;
|
|
78
|
+
description?: string;
|
|
79
|
+
searchConfig?: SearchConfig;
|
|
80
|
+
viewModeConfig?: ViewModeConfig;
|
|
81
|
+
filterConfig?: FilterConfig;
|
|
82
|
+
customToolbarItems?: React.ReactNode;
|
|
83
|
+
actions?: ActionButton[];
|
|
84
|
+
showActionSeparator?: boolean;
|
|
85
|
+
visible?: boolean;
|
|
86
|
+
className?: string;
|
|
87
|
+
}
|
|
88
|
+
declare const ModuleHeader: React.FC<ModuleHeaderProps>;
|
|
89
|
+
export default ModuleHeader;
|
|
90
|
+
//# sourceMappingURL=ModuleHeader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModuleHeader.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/ModuleHeader/ModuleHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAI3D;;;;;;;;;;;;;;;;;;;GAmBG;AAMH;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,MAAM,GAAG,QAAQ,CAAC;IACtD,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,kBAAkB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACrC,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAuWD,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAqQ7C,CAAC;AAEF,eAAe,YAAY,CAAC"}
|