@topconsultnpm/sdkui-react 6.20.0-dev1.2 → 6.20.0-dev1.4
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/lib/components/base/TMAccordion.js +2 -2
- package/lib/components/features/documents/TMDcmtForm.js +3 -6
- package/lib/components/features/search/TMSearchResult.js +3 -4
- package/lib/components/features/search/TMViewHistoryDcmt.js +1 -1
- package/lib/components/index.d.ts +1 -0
- package/lib/components/index.js +1 -0
- package/package.json +10 -10
- package/lib/components/NewComponents/ContextMenu/TMContextMenu.d.ts +0 -4
- package/lib/components/NewComponents/ContextMenu/TMContextMenu.js +0 -187
- package/lib/components/NewComponents/ContextMenu/hooks.d.ts +0 -11
- package/lib/components/NewComponents/ContextMenu/hooks.js +0 -48
- package/lib/components/NewComponents/ContextMenu/index.d.ts +0 -2
- package/lib/components/NewComponents/ContextMenu/index.js +0 -1
- package/lib/components/NewComponents/ContextMenu/styles.d.ts +0 -27
- package/lib/components/NewComponents/ContextMenu/styles.js +0 -308
- package/lib/components/NewComponents/ContextMenu/types.d.ts +0 -26
- package/lib/components/NewComponents/ContextMenu/types.js +0 -1
- package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.d.ts +0 -4
- package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +0 -370
- package/lib/components/NewComponents/FloatingMenuBar/index.d.ts +0 -2
- package/lib/components/NewComponents/FloatingMenuBar/index.js +0 -2
- package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +0 -38
- package/lib/components/NewComponents/FloatingMenuBar/styles.js +0 -267
- package/lib/components/NewComponents/FloatingMenuBar/types.d.ts +0 -30
- package/lib/components/NewComponents/FloatingMenuBar/types.js +0 -1
- package/lib/components/NewComponents/Notification/Notification.d.ts +0 -4
- package/lib/components/NewComponents/Notification/Notification.js +0 -60
- package/lib/components/NewComponents/Notification/NotificationContainer.d.ts +0 -8
- package/lib/components/NewComponents/Notification/NotificationContainer.js +0 -33
- package/lib/components/NewComponents/Notification/index.d.ts +0 -2
- package/lib/components/NewComponents/Notification/index.js +0 -2
- package/lib/components/NewComponents/Notification/styles.d.ts +0 -21
- package/lib/components/NewComponents/Notification/styles.js +0 -180
- package/lib/components/NewComponents/Notification/types.d.ts +0 -18
- package/lib/components/NewComponents/Notification/types.js +0 -1
|
@@ -47,12 +47,12 @@ const StyledGroupTemplate = styled.div `
|
|
|
47
47
|
&::after {
|
|
48
48
|
content: '';
|
|
49
49
|
display: block;
|
|
50
|
-
width:
|
|
50
|
+
width: calc(100% - 35px);
|
|
51
51
|
margin: 0 auto;
|
|
52
52
|
border-bottom: 1px solid #00A99D;
|
|
53
53
|
margin-top: 8px;
|
|
54
54
|
position: absolute;
|
|
55
|
-
left:
|
|
55
|
+
left: 35px;
|
|
56
56
|
bottom: 0;
|
|
57
57
|
}
|
|
58
58
|
`;
|
|
@@ -237,8 +237,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
|
|
|
237
237
|
// Imposta il layout e customButtonsLayout immediatamente
|
|
238
238
|
setLayout(resLayout);
|
|
239
239
|
if (layoutMode === LayoutModes.Update && customButtonsLayoutResult) {
|
|
240
|
-
|
|
241
|
-
//setCustomButtonsLayout(customButtonsLayoutResult);
|
|
240
|
+
setCustomButtonsLayout(customButtonsLayoutResult);
|
|
242
241
|
}
|
|
243
242
|
// Carica DTD e metadata
|
|
244
243
|
let dtd = await DcmtTypeListCacheService.GetWithNotGrantedAsync(TID, DID, getMetadataResult);
|
|
@@ -680,13 +679,11 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
|
|
|
680
679
|
text: customButton.title || 'Bottone personalizzato',
|
|
681
680
|
onClick: () => setCustomButton(customButton)
|
|
682
681
|
}));
|
|
683
|
-
//disabilitato per ora
|
|
684
|
-
/*
|
|
685
682
|
items.push({
|
|
686
|
-
icon: svgToString(
|
|
683
|
+
icon: svgToString(_jsx(IconCheck, {})),
|
|
687
684
|
text: SDKUI_Localizator.CustomButtons,
|
|
688
685
|
items: customButtonsItems
|
|
689
|
-
}
|
|
686
|
+
});
|
|
690
687
|
}
|
|
691
688
|
return items;
|
|
692
689
|
}, [
|
|
@@ -374,8 +374,7 @@ const TMSearchResult = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, a
|
|
|
374
374
|
e.items = e.items || [];
|
|
375
375
|
const menuItems = getCommandsMenuItems(isMobile, fromDTD, allUsers, selectedItems, focusedItem, context, showFloatingBar, workingGroupContext, showSearch, setShowFloatingBar, openFormHandler, openSharedArchiveHandler, showSharedDcmtsHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, refreshSelectionDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, openConfirmAttachmentsDialog, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler, openExportForm, handleToggleSearch, handleSignApprove, openSignSettingsForm, handleCheckOutOperationCallback, showCheckoutInformationFormCallback, viewHistoryCallback, openWGsCopyMoveForm, openCommentFormCallback, openEditPdf, openAddDocumentForm, passToArchiveCallback, archiveMasterDocuments, archiveDetailDocuments, currentTIDHasMasterRelations, currentTIDHasDetailRelations, canArchiveMasterRelation, canArchiveDetailRelation, pairManyToMany, hasManyToManyRelation);
|
|
376
376
|
e.items.push(...menuItems);
|
|
377
|
-
|
|
378
|
-
//e.items.push(customButtonMenuItems());
|
|
377
|
+
e.items.push(customButtonMenuItems());
|
|
379
378
|
}
|
|
380
379
|
};
|
|
381
380
|
const handleCheckOutOperationCallback = async (checkout) => {
|
|
@@ -618,7 +617,7 @@ const TMSearchResult = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, a
|
|
|
618
617
|
}
|
|
619
618
|
};
|
|
620
619
|
const searchResutlToolbar = _jsxs(_Fragment, { children: [(dcmtsReturned != dcmtsFound) && _jsx("p", { style: { backgroundColor: `white`, color: TMColors.primaryColor, textAlign: 'center', padding: '1px 4px', borderRadius: '3px', display: 'flex' }, children: `${dcmtsReturned}/${dcmtsFound} restituiti` }), context === SearchResultContext.FAVORITES_AND_RECENTS &&
|
|
621
|
-
_jsx("div", { style: { display: 'flex', alignItems: 'center', gap: '5px' }, children: _jsx(TMButton, { btnStyle: 'icon', icon: _jsx(IconDelete, { color: 'white' }), caption: "Rimuovi da " + (selectedSearchResult?.category === "Favorites" ? '"Preferiti"' : '"Recenti"'), disabled: getSelectedDcmtsOrFocused(selectedItems, focusedItem).length <= 0, onClick: removeDcmtFromFavsOrRecents }) }), _jsx(TMButton, { btnStyle: 'icon', icon: _jsx(IconRefresh, { color: 'white' }), caption: SDKUI_Localizator.Refresh, onClick: onRefreshSearchAsync }), _jsx(IconMenuVertical, { id: `commands-header-${id}`, color: 'white', cursor: 'pointer' }), _jsx(TMCommandsContextMenu, { target: `#commands-header-${id}`, showEvent: "click", menuItems: getCommandsMenuItems(isMobile, fromDTD, allUsers, selectedItems, focusedItem, context, showFloatingBar, workingGroupContext, showSearch, setShowFloatingBar, openFormHandler, openSharedArchiveHandler, showSharedDcmtsHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, refreshSelectionDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, openConfirmAttachmentsDialog, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler, openExportForm, handleToggleSearch, handleSignApprove, openSignSettingsForm, handleCheckOutOperationCallback, showCheckoutInformationFormCallback, viewHistoryCallback, openWGsCopyMoveForm, openCommentFormCallback, openEditPdf, openAddDocumentForm, passToArchiveCallback, archiveMasterDocuments, archiveDetailDocuments, currentTIDHasMasterRelations, currentTIDHasDetailRelations, canArchiveMasterRelation, canArchiveDetailRelation, pairManyToMany, hasManyToManyRelation)
|
|
620
|
+
_jsx("div", { style: { display: 'flex', alignItems: 'center', gap: '5px' }, children: _jsx(TMButton, { btnStyle: 'icon', icon: _jsx(IconDelete, { color: 'white' }), caption: "Rimuovi da " + (selectedSearchResult?.category === "Favorites" ? '"Preferiti"' : '"Recenti"'), disabled: getSelectedDcmtsOrFocused(selectedItems, focusedItem).length <= 0, onClick: removeDcmtFromFavsOrRecents }) }), _jsx(TMButton, { btnStyle: 'icon', icon: _jsx(IconRefresh, { color: 'white' }), caption: SDKUI_Localizator.Refresh, onClick: onRefreshSearchAsync }), _jsx(IconMenuVertical, { id: `commands-header-${id}`, color: 'white', cursor: 'pointer' }), _jsx(TMCommandsContextMenu, { target: `#commands-header-${id}`, showEvent: "click", menuItems: getCommandsMenuItems(isMobile, fromDTD, allUsers, selectedItems, focusedItem, context, showFloatingBar, workingGroupContext, showSearch, setShowFloatingBar, openFormHandler, openSharedArchiveHandler, showSharedDcmtsHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, refreshSelectionDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, openConfirmAttachmentsDialog, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler, openExportForm, handleToggleSearch, handleSignApprove, openSignSettingsForm, handleCheckOutOperationCallback, showCheckoutInformationFormCallback, viewHistoryCallback, openWGsCopyMoveForm, openCommentFormCallback, openEditPdf, openAddDocumentForm, passToArchiveCallback, archiveMasterDocuments, archiveDetailDocuments, currentTIDHasMasterRelations, currentTIDHasDetailRelations, canArchiveMasterRelation, canArchiveDetailRelation, pairManyToMany, hasManyToManyRelation).concat([customButtonMenuItems()]) })] });
|
|
622
621
|
const handleAddItem = (tid, did) => {
|
|
623
622
|
let newItem = { TID: tid ?? 0, DID: did ?? 0 };
|
|
624
623
|
setSecondaryMasterDcmts((prevItems) => [...prevItems, newItem]);
|
|
@@ -653,7 +652,7 @@ const TMSearchResult = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, a
|
|
|
653
652
|
_jsx(TMLayoutItem, { children: _jsx(TMSearchResultSelector, { searchResults: currentSearchResults, disableAccordionIfSingleCategory: disableAccordionIfSingleCategory, selectedTID: selectedSearchResultTID, selectedSearchResult: selectedSearchResult, autoSelectFirst: !isMobile || currentSearchResults.length === 1, onSelectionChanged: onSearchResultSelectionChanged }) })
|
|
654
653
|
:
|
|
655
654
|
_jsx(_Fragment, {}), _jsxs(TMLayoutItem, { children: [_jsx(TMSearchResultGrid, { showSearch: showSearch, fromDTD: fromDTD, allUsers: allUsers, inputFocusedItem: focusedItem, inputSelectedItems: selectedItems, searchResult: searchResults.length > 1 ? selectedSearchResult : searchResults[0], lastUpdateSearchTime: lastUpdateSearchTime, openInOffice: openInOffice, onDblClick: () => openFormHandler(LayoutModes.Update), onContextMenuPreparing: onContextMenuPreparing, onSelectionChanged: (items) => { setSelectedItems(items); }, onVisibleItemChanged: setVisibleItems, onFocusedItemChanged: setFocusedItem, onDownloadDcmtsAsync: async (inputDcmts, downloadType, downloadMode, _y, confirmAttachments) => await downloadDcmtsAsync(inputDcmts, downloadType, downloadMode, onFileOpened, confirmAttachments), showExportForm: showExportForm, onCloseExportForm: onCloseExportForm }), allowFloatingBar && showFloatingBar && deviceType !== DeviceType.MOBILE &&
|
|
656
|
-
_jsxs(TMFloatingToolbar, { backgroundColor: TMColors.primaryColor, initialLeft: '10px', initialTop: 'calc(100% - 75px)', children: [fromDTD?.perm?.canRetrieveFile === AccessLevels.Yes && _jsx(TMButton, { btnStyle: 'icon', caption: "Download file", disabled: fromDTD?.perm?.canRetrieveFile !== AccessLevels.Yes || !focusedItem?.DID, icon: _jsx(IconDownload, { color: 'white' }), onClick: () => { downloadDcmtsAsync(getSelectedDcmtsOrFocused(selectedItems, focusedItem), DownloadTypes.Dcmt, "download"); } }), allowRelations && _jsx(TMButton, { btnStyle: 'icon', disabled: !currentTIDHasDetailRelations || !focusedItem?.DID, icon: _jsx(IconDetailDcmts, { color: 'white' }), caption: SDKUI_Localizator.DcmtsDetail, onClick: () => setIsOpenDetails(true) }), allowRelations && _jsx(TMButton, { btnStyle: 'icon', disabled: !currentTIDHasMasterRelations || !focusedItem?.DID, icon: _jsx(IconDetailDcmts, { color: 'white', transform: 'scale(-1, 1)' }), caption: SDKUI_Localizator.DcmtsMaster, onClick: () => setIsOpenMaster(true) }), _jsx(IconMenuVertical, { id: `commands-floating-${id}`, color: 'white', cursor: 'pointer' }), _jsx(TMCommandsContextMenu, { target: `#commands-floating-${id}`, showEvent: "click", menuItems: getCommandsMenuItems(isMobile, fromDTD, allUsers, selectedItems, focusedItem, context, showFloatingBar, workingGroupContext, showSearch, setShowFloatingBar, openFormHandler, openSharedArchiveHandler, showSharedDcmtsHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, refreshSelectionDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, openConfirmAttachmentsDialog, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler, openExportForm, handleToggleSearch, handleSignApprove, openSignSettingsForm, handleCheckOutOperationCallback, showCheckoutInformationFormCallback, viewHistoryCallback, openWGsCopyMoveForm, openCommentFormCallback, openEditPdf, openAddDocumentForm, passToArchiveCallback, archiveMasterDocuments, archiveDetailDocuments, currentTIDHasMasterRelations, currentTIDHasDetailRelations, canArchiveMasterRelation, canArchiveDetailRelation, pairManyToMany, hasManyToManyRelation)
|
|
655
|
+
_jsxs(TMFloatingToolbar, { backgroundColor: TMColors.primaryColor, initialLeft: '10px', initialTop: 'calc(100% - 75px)', children: [fromDTD?.perm?.canRetrieveFile === AccessLevels.Yes && _jsx(TMButton, { btnStyle: 'icon', caption: "Download file", disabled: fromDTD?.perm?.canRetrieveFile !== AccessLevels.Yes || !focusedItem?.DID, icon: _jsx(IconDownload, { color: 'white' }), onClick: () => { downloadDcmtsAsync(getSelectedDcmtsOrFocused(selectedItems, focusedItem), DownloadTypes.Dcmt, "download"); } }), allowRelations && _jsx(TMButton, { btnStyle: 'icon', disabled: !currentTIDHasDetailRelations || !focusedItem?.DID, icon: _jsx(IconDetailDcmts, { color: 'white' }), caption: SDKUI_Localizator.DcmtsDetail, onClick: () => setIsOpenDetails(true) }), allowRelations && _jsx(TMButton, { btnStyle: 'icon', disabled: !currentTIDHasMasterRelations || !focusedItem?.DID, icon: _jsx(IconDetailDcmts, { color: 'white', transform: 'scale(-1, 1)' }), caption: SDKUI_Localizator.DcmtsMaster, onClick: () => setIsOpenMaster(true) }), _jsx(IconMenuVertical, { id: `commands-floating-${id}`, color: 'white', cursor: 'pointer' }), _jsx(TMCommandsContextMenu, { target: `#commands-floating-${id}`, showEvent: "click", menuItems: getCommandsMenuItems(isMobile, fromDTD, allUsers, selectedItems, focusedItem, context, showFloatingBar, workingGroupContext, showSearch, setShowFloatingBar, openFormHandler, openSharedArchiveHandler, showSharedDcmtsHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, refreshSelectionDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, openConfirmAttachmentsDialog, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler, openExportForm, handleToggleSearch, handleSignApprove, openSignSettingsForm, handleCheckOutOperationCallback, showCheckoutInformationFormCallback, viewHistoryCallback, openWGsCopyMoveForm, openCommentFormCallback, openEditPdf, openAddDocumentForm, passToArchiveCallback, archiveMasterDocuments, archiveDetailDocuments, currentTIDHasMasterRelations, currentTIDHasDetailRelations, canArchiveMasterRelation, canArchiveDetailRelation, pairManyToMany, hasManyToManyRelation).concat([customButtonMenuItems()]) })] })] })] }), showApprovePopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: onWFOperationCompleted, selectedItems: getSelectedDcmtsOrFocused(selectedItems, focusedItem), isReject: 0, onClose: () => setShowApprovePopup(false) }), showRejectPopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: onWFOperationCompleted, selectedItems: getSelectedDcmtsOrFocused(selectedItems, focusedItem), isReject: 1, onClose: () => setShowRejectPopup(false) }), showReAssignPopup && _jsx(WorkFlowReAssignPopUp, { deviceType: deviceType, onCompleted: onWFOperationCompleted, selectedItems: getSelectedDcmtsOrFocused(selectedItems, focusedItem), onClose: () => setShowReAssignPopup(false) }), showMoreInfoPopup && _jsx(WorkFlowMoreInfoPopUp, { TID: focusedItem?.TID, DID: focusedItem?.DID, deviceType: deviceType, onCompleted: onWFOperationCompleted, onClose: () => setShowMoreInfoPopup(false) }), isOpenBatchUpdate && _jsx(TMBatchUpdateForm, { isModal: true, titleModal: `${SDKUI_Localizator.BatchUpdate} (${getSelectionDcmtInfo().length} documenti selezionati)`, inputDcmts: getSelectionDcmtInfo(), TID: focusedItem ? focusedItem?.TID : selectedItems[0]?.TID, DID: focusedItem ? focusedItem?.DID : selectedItems[0]?.DID, onBack: () => {
|
|
657
656
|
setIsOpenBatchUpdate(false);
|
|
658
657
|
}, onSavedCallbackAsync: async () => {
|
|
659
658
|
setIsOpenBatchUpdate(false);
|
|
@@ -140,7 +140,7 @@ const TMViewHistoryDcmt = (props) => {
|
|
|
140
140
|
await downloadDcmtsAsync(files, DownloadTypes.Dcmt, "download");
|
|
141
141
|
};
|
|
142
142
|
const deleteFilesCallback = () => {
|
|
143
|
-
if (!
|
|
143
|
+
if (!focusedRowKey)
|
|
144
144
|
return;
|
|
145
145
|
const currentDcmt = dcmtHistory.find(dcmt => dcmt.id === focusedRowKey);
|
|
146
146
|
if (currentDcmt && currentDcmt.id) {
|
|
@@ -25,6 +25,7 @@ export { default as TMTooltip } from './base/TMTooltip';
|
|
|
25
25
|
export { default as TMVilViewer } from './base/TMVilViewer';
|
|
26
26
|
export { default as TMUserAvatar } from './base/TMUserAvatar';
|
|
27
27
|
export { default as TMFloatingToolbar } from './base/TMFloatingToolbar';
|
|
28
|
+
export { default as TMAccordion } from './base/TMAccordion';
|
|
28
29
|
export { default as TMDropDown } from './editors/TMDropDown';
|
|
29
30
|
export { default as TMTreeDropDown } from './editors/TMTreeDropDown';
|
|
30
31
|
export { default as TMSummary } from './editors/TMSummary';
|
package/lib/components/index.js
CHANGED
|
@@ -26,6 +26,7 @@ export { default as TMTooltip } from './base/TMTooltip';
|
|
|
26
26
|
export { default as TMVilViewer } from './base/TMVilViewer';
|
|
27
27
|
export { default as TMUserAvatar } from './base/TMUserAvatar';
|
|
28
28
|
export { default as TMFloatingToolbar } from './base/TMFloatingToolbar';
|
|
29
|
+
export { default as TMAccordion } from './base/TMAccordion';
|
|
29
30
|
//editors
|
|
30
31
|
export { default as TMDropDown } from './editors/TMDropDown';
|
|
31
32
|
export { default as TMTreeDropDown } from './editors/TMTreeDropDown';
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topconsultnpm/sdkui-react",
|
|
3
|
-
"version": "6.20.0-dev1.
|
|
3
|
+
"version": "6.20.0-dev1.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"test": "echo \"Error: no test specified\"
|
|
6
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
7
7
|
"clean": "powershell Remove-Item lib/ -recurse",
|
|
8
8
|
"copy-files": "copyfiles -u 1 src/assets/*.* src/assets/ImageLibrary/*.* src/assets/thumbnails/*.* src/assets/IconsS4t/*.* src/assets/Metadata/*.* src/css/tm-sdkui.css lib/",
|
|
9
|
-
"tm-build": "npm run clean
|
|
9
|
+
"tm-build": "npm run clean && tsc && npm run copy-files",
|
|
10
10
|
"tm-watch": "tsc -w",
|
|
11
11
|
"tm-publish": "npm publish --tag latest",
|
|
12
12
|
"storybook": "storybook dev -p 6006",
|
|
@@ -39,16 +39,16 @@
|
|
|
39
39
|
"lib"
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"
|
|
43
|
-
"htmlparser2": "^10.0.0",
|
|
42
|
+
"@topconsultnpm/sdk-ts": "6.20.0-dev1.1",
|
|
44
43
|
"buffer": "^6.0.3",
|
|
45
|
-
"@topconsultnpm/sdk-ts": "^6.20.0-dev1.1",
|
|
46
|
-
"exceljs": "^4.4.0",
|
|
47
44
|
"devextreme": "25.1.7",
|
|
48
|
-
"
|
|
49
|
-
"
|
|
45
|
+
"devextreme-react": "25.1.7",
|
|
46
|
+
"exceljs": "^4.4.0",
|
|
47
|
+
"htmlparser2": "^10.0.0",
|
|
48
|
+
"react-router-dom": "^6.15.0",
|
|
49
|
+
"styled-components": "^6.1.1"
|
|
50
50
|
},
|
|
51
51
|
"overrides": {
|
|
52
52
|
"esbuild": "^0.25.0"
|
|
53
53
|
}
|
|
54
|
-
}
|
|
54
|
+
}
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useState, useRef, useEffect } from 'react';
|
|
3
|
-
import * as S from './styles';
|
|
4
|
-
import { useIsMobile, useMenuPosition } from './hooks';
|
|
5
|
-
const TMContextMenu = ({ items, trigger = 'right', children }) => {
|
|
6
|
-
const [menuState, setMenuState] = useState({
|
|
7
|
-
visible: false,
|
|
8
|
-
position: { x: 0, y: 0 },
|
|
9
|
-
submenuStack: [items],
|
|
10
|
-
parentNames: [],
|
|
11
|
-
});
|
|
12
|
-
const [hoveredSubmenus, setHoveredSubmenus] = useState([]);
|
|
13
|
-
const isMobile = useIsMobile();
|
|
14
|
-
const menuRef = useRef(null);
|
|
15
|
-
const triggerRef = useRef(null);
|
|
16
|
-
const submenuTimeoutRef = useRef(null);
|
|
17
|
-
const { openLeft, openUp } = useMenuPosition(menuRef, menuState.position);
|
|
18
|
-
const handleClose = () => {
|
|
19
|
-
setMenuState(prev => ({
|
|
20
|
-
...prev,
|
|
21
|
-
visible: false,
|
|
22
|
-
submenuStack: [items],
|
|
23
|
-
parentNames: [],
|
|
24
|
-
}));
|
|
25
|
-
setHoveredSubmenus([]);
|
|
26
|
-
};
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
if (!menuState.visible)
|
|
29
|
-
return;
|
|
30
|
-
const handleClickOutside = (event) => {
|
|
31
|
-
const target = event.target;
|
|
32
|
-
// Check if click is inside main menu
|
|
33
|
-
if (menuRef.current?.contains(target)) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
// Check if click is inside any submenu
|
|
37
|
-
const submenus = document.querySelectorAll('[data-submenu="true"]');
|
|
38
|
-
for (const submenu of Array.from(submenus)) {
|
|
39
|
-
if (submenu.contains(target)) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
// Click is outside all menus, close them
|
|
44
|
-
handleClose();
|
|
45
|
-
};
|
|
46
|
-
document.addEventListener('mousedown', handleClickOutside);
|
|
47
|
-
document.addEventListener('touchstart', handleClickOutside);
|
|
48
|
-
return () => {
|
|
49
|
-
document.removeEventListener('mousedown', handleClickOutside);
|
|
50
|
-
document.removeEventListener('touchstart', handleClickOutside);
|
|
51
|
-
};
|
|
52
|
-
}, [menuState.visible]);
|
|
53
|
-
const handleContextMenu = (e) => {
|
|
54
|
-
if (trigger === 'right') {
|
|
55
|
-
e.preventDefault();
|
|
56
|
-
setMenuState({
|
|
57
|
-
visible: true,
|
|
58
|
-
position: { x: e.clientX, y: e.clientY },
|
|
59
|
-
submenuStack: [items],
|
|
60
|
-
parentNames: [],
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
const handleClick = (e) => {
|
|
65
|
-
if (trigger === 'left') {
|
|
66
|
-
e.preventDefault();
|
|
67
|
-
setMenuState({
|
|
68
|
-
visible: true,
|
|
69
|
-
position: { x: e.clientX, y: e.clientY },
|
|
70
|
-
submenuStack: [items],
|
|
71
|
-
parentNames: [],
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
const handleItemClick = (item) => {
|
|
76
|
-
if (item.disabled)
|
|
77
|
-
return;
|
|
78
|
-
// Always execute onClick if present
|
|
79
|
-
if (item.onClick) {
|
|
80
|
-
item.onClick();
|
|
81
|
-
}
|
|
82
|
-
if (item.submenu && item.submenu.length > 0) {
|
|
83
|
-
if (isMobile) {
|
|
84
|
-
// Mobile: Push submenu to stack
|
|
85
|
-
setMenuState(prev => ({
|
|
86
|
-
...prev,
|
|
87
|
-
submenuStack: [...prev.submenuStack, item.submenu],
|
|
88
|
-
parentNames: [...prev.parentNames, item.name],
|
|
89
|
-
}));
|
|
90
|
-
}
|
|
91
|
-
// Desktop: Submenus are handled by hover, don't close menu
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
// No submenu: close menu after executing action
|
|
95
|
-
handleClose();
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
const handleBack = () => {
|
|
99
|
-
setMenuState(prev => ({
|
|
100
|
-
...prev,
|
|
101
|
-
submenuStack: prev.submenuStack.slice(0, -1),
|
|
102
|
-
parentNames: prev.parentNames.slice(0, -1),
|
|
103
|
-
}));
|
|
104
|
-
};
|
|
105
|
-
const handleMouseEnter = (item, event, depth = 0) => {
|
|
106
|
-
if (isMobile || !item.submenu || item.submenu.length === 0)
|
|
107
|
-
return;
|
|
108
|
-
if (submenuTimeoutRef.current) {
|
|
109
|
-
clearTimeout(submenuTimeoutRef.current);
|
|
110
|
-
submenuTimeoutRef.current = null;
|
|
111
|
-
}
|
|
112
|
-
const rect = event.currentTarget.getBoundingClientRect();
|
|
113
|
-
// Calculate if submenu should open upward based on available space
|
|
114
|
-
// Estimate submenu height: ~35px per item (accounting for smaller padding) + container padding
|
|
115
|
-
const estimatedSubmenuHeight = (item.submenu.length * 35) + 8;
|
|
116
|
-
const spaceBelow = window.innerHeight - rect.top;
|
|
117
|
-
const spaceAbove = rect.bottom;
|
|
118
|
-
// Open upward only if there's not enough space below AND there's more space above
|
|
119
|
-
const shouldOpenUp = spaceBelow < estimatedSubmenuHeight && spaceAbove > spaceBelow;
|
|
120
|
-
// Remove all submenus at this depth and deeper
|
|
121
|
-
setHoveredSubmenus(prev => {
|
|
122
|
-
const filtered = prev.filter(sub => sub.depth < depth);
|
|
123
|
-
if (!item.submenu)
|
|
124
|
-
return filtered;
|
|
125
|
-
return [
|
|
126
|
-
...filtered,
|
|
127
|
-
{
|
|
128
|
-
items: item.submenu,
|
|
129
|
-
parentRect: rect,
|
|
130
|
-
depth: depth,
|
|
131
|
-
openUp: shouldOpenUp,
|
|
132
|
-
}
|
|
133
|
-
];
|
|
134
|
-
});
|
|
135
|
-
};
|
|
136
|
-
const handleMouseLeave = (depth = 0) => {
|
|
137
|
-
if (isMobile)
|
|
138
|
-
return;
|
|
139
|
-
if (submenuTimeoutRef.current) {
|
|
140
|
-
clearTimeout(submenuTimeoutRef.current);
|
|
141
|
-
}
|
|
142
|
-
const targetDepth = depth;
|
|
143
|
-
submenuTimeoutRef.current = setTimeout(() => {
|
|
144
|
-
setHoveredSubmenus(prev => prev.filter(sub => sub.depth < targetDepth));
|
|
145
|
-
}, 300);
|
|
146
|
-
};
|
|
147
|
-
const handleSubmenuMouseEnter = () => {
|
|
148
|
-
if (submenuTimeoutRef.current) {
|
|
149
|
-
clearTimeout(submenuTimeoutRef.current);
|
|
150
|
-
submenuTimeoutRef.current = null;
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
useEffect(() => {
|
|
154
|
-
return () => {
|
|
155
|
-
if (submenuTimeoutRef.current) {
|
|
156
|
-
clearTimeout(submenuTimeoutRef.current);
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
|
-
}, []);
|
|
160
|
-
const renderMenuItems = (menuItems, depth = 0) => {
|
|
161
|
-
return menuItems
|
|
162
|
-
.filter(item => item.visible !== false)
|
|
163
|
-
.map((item, idx) => {
|
|
164
|
-
const itemKey = `${item.name}-${idx}`.replaceAll(/\s+/g, '-');
|
|
165
|
-
const handleClick = (e) => {
|
|
166
|
-
if (item.disabled)
|
|
167
|
-
return;
|
|
168
|
-
e.stopPropagation();
|
|
169
|
-
handleItemClick(item);
|
|
170
|
-
};
|
|
171
|
-
const handleRightIconClick = (e) => {
|
|
172
|
-
e.stopPropagation();
|
|
173
|
-
// if (item.disabled) return;
|
|
174
|
-
item.onRightIconClick?.();
|
|
175
|
-
};
|
|
176
|
-
return (_jsxs(S.MenuItem, { "$disabled": item.disabled, "$hasSubmenu": !!item.submenu && item.submenu.length > 0, "$beginGroup": item.beginGroup, onMouseDown: handleClick, onMouseEnter: (e) => !isMobile && handleMouseEnter(item, e, depth + 1), onMouseLeave: () => !isMobile && handleMouseLeave(depth + 1), children: [_jsxs(S.MenuItemContent, { children: [item.icon && _jsx(S.IconWrapper, { children: item.icon }), _jsx(S.MenuItemName, { children: item.name })] }), item.rightIcon && item.onRightIconClick && (_jsx(S.RightIconButton, { onClick: handleRightIconClick, onMouseDown: (e) => e.stopPropagation(), "aria-label": `Action for ${item.name}`, children: item.rightIcon })), item.submenu && item.submenu.length > 0 && (_jsx(S.SubmenuIndicator, { "$isMobile": isMobile, children: isMobile ? '›' : '▸' }))] }, itemKey));
|
|
177
|
-
});
|
|
178
|
-
};
|
|
179
|
-
const currentMenu = menuState.submenuStack.at(-1) || items;
|
|
180
|
-
const currentParentName = menuState.parentNames.at(-1) || '';
|
|
181
|
-
return (_jsxs(_Fragment, { children: [_jsx("div", { ref: triggerRef, onContextMenu: handleContextMenu, onClick: handleClick, onKeyDown: (e) => {
|
|
182
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
183
|
-
handleClick(e);
|
|
184
|
-
}
|
|
185
|
-
}, role: "button", tabIndex: 0, style: { display: 'inline-block' }, children: children }), menuState.visible && (_jsxs(_Fragment, { children: [_jsx(S.Overlay, { onClick: handleClose }), _jsxs(S.MenuContainer, { ref: menuRef, "$x": menuState.position.x, "$y": menuState.position.y, "$openLeft": openLeft, "$openUp": openUp, children: [isMobile && menuState.parentNames.length > 0 && (_jsxs(S.MobileMenuHeader, { children: [_jsx(S.BackButton, { onClick: handleBack, "aria-label": "Go back", children: "\u2190" }), _jsx(S.HeaderTitle, { children: currentParentName })] })), renderMenuItems(currentMenu, 0)] }), !isMobile && hoveredSubmenus.map((submenu, idx) => (_jsx(S.Submenu, { "$parentRect": submenu.parentRect, "$openUp": submenu.openUp, "data-submenu": "true", onMouseEnter: handleSubmenuMouseEnter, onMouseLeave: () => handleMouseLeave(submenu.depth), children: renderMenuItems(submenu.items, submenu.depth) }, `submenu-${submenu.depth}-${idx}`)))] }))] }));
|
|
186
|
-
};
|
|
187
|
-
export default TMContextMenu;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export declare const useIsMobile: () => boolean;
|
|
2
|
-
export declare const useClickOutside: (callback: () => void) => import("react").RefObject<HTMLDivElement>;
|
|
3
|
-
interface Position {
|
|
4
|
-
x: number;
|
|
5
|
-
y: number;
|
|
6
|
-
}
|
|
7
|
-
export declare const useMenuPosition: (menuRef: React.RefObject<HTMLDivElement | null>, position: Position) => {
|
|
8
|
-
openLeft: boolean;
|
|
9
|
-
openUp: boolean;
|
|
10
|
-
};
|
|
11
|
-
export {};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect, useRef } from 'react';
|
|
2
|
-
export const useIsMobile = () => {
|
|
3
|
-
const [isMobile, setIsMobile] = useState(false);
|
|
4
|
-
useEffect(() => {
|
|
5
|
-
const checkMobile = () => {
|
|
6
|
-
const mobile = globalThis.innerWidth <= 768 || 'ontouchstart' in globalThis;
|
|
7
|
-
setIsMobile(mobile);
|
|
8
|
-
};
|
|
9
|
-
checkMobile();
|
|
10
|
-
window.addEventListener('resize', checkMobile);
|
|
11
|
-
return () => window.removeEventListener('resize', checkMobile);
|
|
12
|
-
}, []);
|
|
13
|
-
return isMobile;
|
|
14
|
-
};
|
|
15
|
-
export const useClickOutside = (callback) => {
|
|
16
|
-
const ref = useRef(null);
|
|
17
|
-
useEffect(() => {
|
|
18
|
-
const handleClick = (event) => {
|
|
19
|
-
if (ref.current && !ref.current.contains(event.target)) {
|
|
20
|
-
callback();
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
document.addEventListener('mousedown', handleClick);
|
|
24
|
-
document.addEventListener('touchstart', handleClick);
|
|
25
|
-
return () => {
|
|
26
|
-
document.removeEventListener('mousedown', handleClick);
|
|
27
|
-
document.removeEventListener('touchstart', handleClick);
|
|
28
|
-
};
|
|
29
|
-
}, [callback]);
|
|
30
|
-
return ref;
|
|
31
|
-
};
|
|
32
|
-
export const useMenuPosition = (menuRef, position) => {
|
|
33
|
-
const [adjustedPosition, setAdjustedPosition] = useState({ openLeft: false, openUp: false });
|
|
34
|
-
useEffect(() => {
|
|
35
|
-
if (!menuRef.current)
|
|
36
|
-
return;
|
|
37
|
-
const menuRect = menuRef.current.getBoundingClientRect();
|
|
38
|
-
const viewportWidth = window.innerWidth;
|
|
39
|
-
const viewportHeight = window.innerHeight;
|
|
40
|
-
const spaceRight = viewportWidth - position.x;
|
|
41
|
-
const spaceBottom = viewportHeight - position.y;
|
|
42
|
-
setAdjustedPosition({
|
|
43
|
-
openLeft: spaceRight < menuRect.width + 20,
|
|
44
|
-
openUp: spaceBottom < menuRect.height + 20,
|
|
45
|
-
});
|
|
46
|
-
}, [position, menuRef]);
|
|
47
|
-
return adjustedPosition;
|
|
48
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as ContextMenu } from './TMContextMenu';
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
export declare const MenuContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
2
|
-
$x: number;
|
|
3
|
-
$y: number;
|
|
4
|
-
$openLeft: boolean;
|
|
5
|
-
$openUp: boolean;
|
|
6
|
-
}>> & string;
|
|
7
|
-
export declare const MenuItem: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
8
|
-
$disabled?: boolean;
|
|
9
|
-
$hasSubmenu?: boolean;
|
|
10
|
-
$beginGroup?: boolean;
|
|
11
|
-
}>> & string;
|
|
12
|
-
export declare const MenuItemContent: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
13
|
-
export declare const IconWrapper: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>> & string;
|
|
14
|
-
export declare const MenuItemName: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>> & string;
|
|
15
|
-
export declare const RightIconButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
|
|
16
|
-
export declare const SubmenuIndicator: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, {
|
|
17
|
-
$isMobile?: boolean;
|
|
18
|
-
}>> & string;
|
|
19
|
-
export declare const Submenu: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
20
|
-
$parentRect: DOMRect;
|
|
21
|
-
$openUp?: boolean;
|
|
22
|
-
}>> & string;
|
|
23
|
-
export declare const MobileMenuHeader: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
24
|
-
export declare const BackButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
|
|
25
|
-
export declare const HeaderTitle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>, never>> & string;
|
|
26
|
-
export declare const MenuDivider: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
27
|
-
export declare const Overlay: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|