@topconsultnpm/sdkui-react 6.20.0-dev1.93 → 6.20.0-dev1.95
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/TMListView.js +33 -15
- package/lib/components/editors/TMTextArea.js +18 -30
- package/lib/components/features/search/TMSearch.d.ts +1 -0
- package/lib/components/features/search/TMSearch.js +2 -2
- package/lib/components/features/search/TMSearchResult.d.ts +1 -0
- package/lib/components/features/search/TMSearchResult.js +19 -3
- package/lib/components/index.d.ts +0 -2
- package/lib/components/index.js +0 -2
- package/package.json +1 -1
- package/lib/components/base/TMContextMenu.d.ts +0 -25
- package/lib/components/base/TMContextMenu.js +0 -109
- package/lib/components/base/TMContextMenuOLD.d.ts +0 -26
- package/lib/components/base/TMContextMenuOLD.js +0 -56
- package/lib/components/base/TMFloatingToolbar.d.ts +0 -9
- package/lib/components/base/TMFloatingToolbar.js +0 -101
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import styled from 'styled-components';
|
|
4
4
|
import { ObjectClasses } from '@topconsultnpm/sdk-ts';
|
|
5
|
-
import TMContextMenu
|
|
5
|
+
import TMContextMenu from '../NewComponents/ContextMenu/TMContextMenu';
|
|
6
6
|
import { IconApply, IconCloseCircle, IconColumns, IconDown, IconHide, IconShow, IconUp, IconVisible } from '../../helper/TMIcons';
|
|
7
7
|
import { TMSearchBar } from '../sidebar/TMHeader';
|
|
8
8
|
import TMTooltip from './TMTooltip';
|
|
@@ -26,9 +26,17 @@ const TMListView = ({ customGroupingHeaders, headerBackGroundColor, header, show
|
|
|
26
26
|
const [isFocused, setIsFocused] = useState(false);
|
|
27
27
|
const [showOrderMenu, setShowOrderMenu] = useState(false);
|
|
28
28
|
const [showOrderOptions, setShowOrderOptions] = useState(false);
|
|
29
|
+
const [contextMenuVisible, setContextMenuVisible] = useState(false);
|
|
30
|
+
const [contextMenuPosition, setContextMenuPosition] = useState({ x: 0, y: 0 });
|
|
31
|
+
const [orderMenuVisible, setOrderMenuVisible] = useState(false);
|
|
32
|
+
const [orderMenuPosition, setOrderMenuPosition] = useState({ x: 0, y: 0 });
|
|
29
33
|
useEffect(() => { setCurrentDataSource(dataSource); }, [dataSource]);
|
|
30
|
-
const openContextMenu = (e) => {
|
|
31
|
-
|
|
34
|
+
const openContextMenu = (e) => {
|
|
35
|
+
e.preventDefault();
|
|
36
|
+
setIsFocused(true);
|
|
37
|
+
setContextMenuVisible(true);
|
|
38
|
+
setContextMenuPosition({ x: e.clientX, y: e.clientY });
|
|
39
|
+
};
|
|
32
40
|
useEffect(() => { if (orderBy) {
|
|
33
41
|
setOrderedBy(orderBy);
|
|
34
42
|
} }, [orderBy]);
|
|
@@ -235,10 +243,10 @@ const TMListView = ({ customGroupingHeaders, headerBackGroundColor, header, show
|
|
|
235
243
|
for (let key of searchKeys) {
|
|
236
244
|
arr.push({
|
|
237
245
|
disabled: !localShowId && key === exprKey,
|
|
238
|
-
|
|
239
|
-
onItemClick: () => { setOrderedBy(key); setShowOrderOptions(false); },
|
|
246
|
+
onClick: () => { setOrderedBy(key); setShowOrderOptions(false); setOrderMenuVisible(false); },
|
|
240
247
|
icon: _jsx(IconColumns, { fontSize: 16 }),
|
|
241
|
-
|
|
248
|
+
name: key,
|
|
249
|
+
rightIcon: key === orderedBy ? _jsx(IconApply, { fontSize: 14, color: 'gray' }) : undefined
|
|
242
250
|
});
|
|
243
251
|
}
|
|
244
252
|
}
|
|
@@ -328,16 +336,16 @@ const TMListView = ({ customGroupingHeaders, headerBackGroundColor, header, show
|
|
|
328
336
|
if (showSearch === undefined) {
|
|
329
337
|
items.push({
|
|
330
338
|
icon: localShowSearch ? _jsx(IconHide, { fontSize: 16 }) : _jsx(IconShow, { fontSize: 16 }),
|
|
331
|
-
|
|
332
|
-
|
|
339
|
+
onClick: () => setLocalShowSearch(!localShowSearch),
|
|
340
|
+
name: localShowSearch ? SDKUI_Localizator.HideSearch : SDKUI_Localizator.ShowSearch
|
|
333
341
|
});
|
|
334
342
|
}
|
|
335
343
|
// Add ID menu item only if showId prop is undefined
|
|
336
344
|
if (showId === undefined) {
|
|
337
345
|
items.push({
|
|
338
346
|
icon: localShowId ? _jsx(IconHide, { fontSize: 16 }) : _jsx(IconShow, { fontSize: 16 }),
|
|
339
|
-
|
|
340
|
-
|
|
347
|
+
onClick: () => setLocalShowId(!localShowId),
|
|
348
|
+
name: localShowId ? SDKUI_Localizator.ID_Hide : SDKUI_Localizator.ID_Show,
|
|
341
349
|
});
|
|
342
350
|
}
|
|
343
351
|
// Add order menu item only if grouping length is zero
|
|
@@ -345,21 +353,31 @@ const TMListView = ({ customGroupingHeaders, headerBackGroundColor, header, show
|
|
|
345
353
|
items.push({
|
|
346
354
|
icon: showOrderMenu ? _jsx(IconHide, { fontSize: 16 }) : _jsx(IconShow, { fontSize: 16 }),
|
|
347
355
|
disabled: searchKeys.length === 0,
|
|
348
|
-
|
|
349
|
-
|
|
356
|
+
onClick: () => setShowOrderMenu(!showOrderMenu),
|
|
357
|
+
name: showOrderMenu ? 'Nascondi menu di ordinamento' : 'Mostra menu di ordinamento'
|
|
350
358
|
});
|
|
351
359
|
}
|
|
352
360
|
return items;
|
|
353
361
|
};
|
|
354
362
|
const contextMenuItems = generateContextMenuItems(localShowSearch, localShowId, showOrderMenu, grouping, searchKeys);
|
|
355
|
-
return (_jsxs(StyledListViewContainer, { ref: contRef, onContextMenu: openContextMenu, children: [
|
|
356
|
-
|
|
363
|
+
return (_jsxs(StyledListViewContainer, { ref: contRef, onContextMenu: openContextMenu, children: [contextMenuItems.length > 0 && (_jsx(TMContextMenu, { items: contextMenuItems, externalControl: {
|
|
364
|
+
visible: contextMenuVisible,
|
|
365
|
+
position: contextMenuPosition,
|
|
366
|
+
onClose: () => setContextMenuVisible(false)
|
|
367
|
+
} })), showOrderOptions && orderRef.current && (_jsx(TMContextMenu, { items: orderMenuItems(), externalControl: {
|
|
368
|
+
visible: orderMenuVisible || showOrderOptions,
|
|
369
|
+
position: {
|
|
370
|
+
x: orderRef.current.getBoundingClientRect().left,
|
|
371
|
+
y: orderRef.current.getBoundingClientRect().top - (searchKeys.length * 30) - 10
|
|
372
|
+
},
|
|
373
|
+
onClose: () => { setOrderMenuVisible(false); setShowOrderOptions(false); }
|
|
374
|
+
} })), header && _jsx("div", { style: { width: '100%', height: '40px', backgroundColor: headerBackGroundColor ?? `${customColor}30`, marginBottom: '3px', display: 'flex', alignItems: 'center' }, children: header }), localShowSearch &&
|
|
357
375
|
_jsx(StyledSearchContainer, { children: _jsxs(StyledSearchContainer, { children: [_jsx(TMSearchBar, { marginLeft: '0px', maxWidth: '300px', searchValue: searchValue, onSearchValueChanged: (e) => setSearchValue(e) }), _jsx(TMTooltip, { content: 'Nascondi ricerca', children: _jsx(IconCloseCircle, { style: { cursor: 'pointer' }, color: 'red', fontSize: 14, onClick: () => { setSearchValue(''); setLocalShowSearch(false); } }) })] }) }), _jsx("div", { ref: listRef, onClick: () => setIsFocused(true), style: { width: '100%', overflow: 'auto', height: listHeight() }, children: currentDataSource.length > 0 ?
|
|
358
376
|
grouping.length === 0 ? memoList : groupedMemoList :
|
|
359
377
|
searchValue.length > 0 ? _jsx("div", { style: { width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }, children: "No data found" }) :
|
|
360
378
|
_jsx("div", { style: { width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }, children: "No data" }) }), (searchValue.length > 0 || showOrderMenu) &&
|
|
361
379
|
_jsxs(StyledListViewFooter, { "$bgColor": `${customColor}20`, children: [showOrderMenu &&
|
|
362
|
-
_jsxs("div", { style: { width: 'max-content', display: 'flex', alignItems: 'center', gap: 5 }, children: [_jsx("div", { style: { width: 'max-content' }, children: "Ordinato per" }), _jsx("div", { ref: orderRef, onClick: () => { setShowOrderOptions(!showOrderOptions); }, style: { cursor: 'pointer', fontWeight: 'bold' }, children: orderedBy.length > 0 ? orderedBy : 'Nulla' }), orderedBy.length > 0 && _jsxs(TMTooltip, { content: orderDir ? 'ASC' : 'DESC', children: [" ", orderDir ? _jsx(IconUp, { style: { cursor: 'pointer' }, onClick: () => setOrderDir(false), fontSize: 14 }) : _jsx(IconDown, { style: { cursor: 'pointer' }, onClick: () => setOrderDir(true), fontSize: 14 }), " "] }), _jsx(TMTooltip, { content: 'Annulla ordinamento', children: _jsx(IconCloseCircle, { style: { cursor: 'pointer' }, color: 'red', fontSize: 14, onClick: () => { setOrderedBy(''); setShowOrderMenu(false); setShowOrderOptions(false); } }) })] }), searchValue.length > 0 && _jsxs("div", { style: { display: 'flex', alignItems: 'center', width: '100%', justifyContent: 'flex-end', gap: 5 }, children: [_jsx(TMTooltip, { content: 'Visibili', children: _jsx(IconVisible, { fontSize: 14 }) }), currentDataSource.length] })] })] }));
|
|
380
|
+
_jsxs("div", { style: { width: 'max-content', display: 'flex', alignItems: 'center', gap: 5 }, children: [_jsx("div", { style: { width: 'max-content' }, children: "Ordinato per" }), _jsx("div", { ref: orderRef, onClick: () => { setShowOrderOptions(!showOrderOptions); setOrderMenuVisible(!orderMenuVisible); }, style: { cursor: 'pointer', fontWeight: 'bold' }, children: orderedBy.length > 0 ? orderedBy : 'Nulla' }), orderedBy.length > 0 && _jsxs(TMTooltip, { content: orderDir ? 'ASC' : 'DESC', children: [" ", orderDir ? _jsx(IconUp, { style: { cursor: 'pointer' }, onClick: () => setOrderDir(false), fontSize: 14 }) : _jsx(IconDown, { style: { cursor: 'pointer' }, onClick: () => setOrderDir(true), fontSize: 14 }), " "] }), _jsx(TMTooltip, { content: 'Annulla ordinamento', children: _jsx(IconCloseCircle, { style: { cursor: 'pointer' }, color: 'red', fontSize: 14, onClick: () => { setOrderedBy(''); setShowOrderMenu(false); setShowOrderOptions(false); } }) })] }), searchValue.length > 0 && _jsxs("div", { style: { display: 'flex', alignItems: 'center', width: '100%', justifyContent: 'flex-end', gap: 5 }, children: [_jsx(TMTooltip, { content: 'Visibili', children: _jsx(IconVisible, { fontSize: 14 }) }), currentDataSource.length] })] })] }));
|
|
363
381
|
};
|
|
364
382
|
export default TMListView;
|
|
365
383
|
export const CustomListViewHeader = (props) => {
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { useState, useEffect, useRef } from 'react';
|
|
3
3
|
import { StyledEditorContainer, StyledEditorIcon, StyledEditorLabel, StyledTextareaEditor } from './TMEditorStyled';
|
|
4
4
|
import { FontSize, TMColors } from '../../utils/theme';
|
|
5
|
-
import TMContextMenu
|
|
5
|
+
import TMContextMenu from '../NewComponents/ContextMenu/TMContextMenu';
|
|
6
6
|
import { TMExceptionBoxManager } from '../base/TMPopUp';
|
|
7
7
|
import TMLayoutContainer, { TMLayoutItem } from '../base/TMLayout';
|
|
8
8
|
import TMVilViewer from '../base/TMVilViewer';
|
|
@@ -35,14 +35,10 @@ const TMTextArea = (props) => {
|
|
|
35
35
|
const [isFocused, setIsFocused] = useState(false);
|
|
36
36
|
// Stores the current value of the textarea
|
|
37
37
|
const [currentValue, setCurrentValue] = useState(value);
|
|
38
|
-
// Stores the items for the context menu
|
|
39
|
-
const [formulaMenuItems, setFormulaMenuItems] = useState([]);
|
|
40
38
|
// Stores the calculated number of rows for the textarea
|
|
41
39
|
const [calculatedRows, setCalculatedRows] = useState(rows ?? 1);
|
|
42
40
|
//Show chooserForm formulaItems
|
|
43
41
|
const [showFormulaItemsChooser, setShowFormulaItemsChooser] = useState(false);
|
|
44
|
-
// Manages the state for the custom context menu
|
|
45
|
-
const { clicked, setClicked, points, setPoints } = useContextMenu();
|
|
46
42
|
const deviceType = useDeviceType();
|
|
47
43
|
// Attach a `ResizeObserver` to the textarea to monitor changes in width: dynamically updates rows based on textarea content and width
|
|
48
44
|
useEffect(() => {
|
|
@@ -69,16 +65,15 @@ const TMTextArea = (props) => {
|
|
|
69
65
|
setCalculatedRows(newRowCount);
|
|
70
66
|
}
|
|
71
67
|
}, [currentValue, autoCalculateRows]);
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
if (formulaItems
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}, [formulaItems]);
|
|
68
|
+
// Build context menu items for formulas
|
|
69
|
+
const getFormulaMenuItems = () => {
|
|
70
|
+
if (!formulaItems || formulaItems.length === 0)
|
|
71
|
+
return [];
|
|
72
|
+
return formulaItems.map(formula => ({
|
|
73
|
+
name: formula,
|
|
74
|
+
onClick: () => insertText(formula)
|
|
75
|
+
}));
|
|
76
|
+
};
|
|
82
77
|
function getFormulaDataSorce() {
|
|
83
78
|
let fiarray = [];
|
|
84
79
|
if (!formulaItems)
|
|
@@ -153,20 +148,8 @@ const TMTextArea = (props) => {
|
|
|
153
148
|
};
|
|
154
149
|
// Renders the textarea
|
|
155
150
|
const renderTextArea = () => {
|
|
156
|
-
|
|
157
|
-
onBlur?.(currentValue); }, onChange: (e) => { setCurrentValue(e.target.value); onValueChanged?.(e); },
|
|
158
|
-
if (formulaItems.length <= 0)
|
|
159
|
-
return;
|
|
160
|
-
// prevent default right click behavior
|
|
161
|
-
e.preventDefault();
|
|
162
|
-
// set our click state to true when a user right clicks
|
|
163
|
-
setClicked(true);
|
|
164
|
-
const bounds = e.currentTarget.getBoundingClientRect();
|
|
165
|
-
const x = e.clientX - bounds.left;
|
|
166
|
-
const y = e.clientY - bounds.top;
|
|
167
|
-
// set the x and y coordinates of our users right click
|
|
168
|
-
setPoints({ x, y });
|
|
169
|
-
}, "$isMobile": deviceType === DeviceType.MOBILE, "$maxHeight": maxHeight, "$disabled": disabled, "$vil": validationItems, "$isModified": isModifiedWhen, "$fontSize": fontSize, "$width": width, "$resize": resize }), _jsxs("div", { style: { display: 'flex', flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'center', position: 'absolute', right: '6px', top: calculatedRows === 1 ? (label.length > 0 ? '20px' : '7px') : (label.length > 0 ? '22px' : '7px'), pointerEvents: disabled ? 'none' : 'auto', opacity: disabled ? 0.4 : 1 }, children: [formulaItems.length > 0 &&
|
|
151
|
+
const textareaElement = _jsxs(_Fragment, { children: [_jsx(StyledTextareaEditor, { ref: inputRef, autoFocus: autoFocus, readOnly: readOnly, disabled: disabled, value: currentValue, placeholder: placeHolder, rows: calculatedRows, maxLength: maxLength, spellCheck: false, onFocus: () => setIsFocused(true), onBlur: (e) => { setIsFocused(false); if (currentValue != value)
|
|
152
|
+
onBlur?.(currentValue); }, onChange: (e) => { setCurrentValue(e.target.value); onValueChanged?.(e); }, "$isMobile": deviceType === DeviceType.MOBILE, "$maxHeight": maxHeight, "$disabled": disabled, "$vil": validationItems, "$isModified": isModifiedWhen, "$fontSize": fontSize, "$width": width, "$resize": resize }), _jsxs("div", { style: { display: 'flex', flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'center', position: 'absolute', right: '6px', top: calculatedRows === 1 ? (label.length > 0 ? '20px' : '7px') : (label.length > 0 ? '22px' : '7px'), pointerEvents: disabled ? 'none' : 'auto', opacity: disabled ? 0.4 : 1 }, children: [formulaItems.length > 0 &&
|
|
170
153
|
_jsx(StyledTextAreaEditorButton, { onClick: () => {
|
|
171
154
|
setShowFormulaItemsChooser(true);
|
|
172
155
|
}, children: _jsx(IconDataList, {}) }), showClearButton && currentValue &&
|
|
@@ -178,7 +161,12 @@ const TMTextArea = (props) => {
|
|
|
178
161
|
onBlur?.(undefined);
|
|
179
162
|
}, children: _jsx(IconClearButton, {}) }), buttons.map((buttonItem, index) => {
|
|
180
163
|
return (_jsx(StyledTextAreaEditorButton, { onClick: buttonItem.onClick, children: _jsx(TMTooltip, { content: buttonItem.text, children: buttonItem.icon }) }, buttonItem.text));
|
|
181
|
-
})] }), openFormulaItemsChooser(),
|
|
164
|
+
})] }), openFormulaItemsChooser(), _jsx(TMVilViewer, { vil: validationItems })] });
|
|
165
|
+
// Wrap with context menu if formula items exist
|
|
166
|
+
if (formulaItems.length > 0) {
|
|
167
|
+
return (_jsx(TMContextMenu, { items: getFormulaMenuItems(), trigger: "right", children: textareaElement }));
|
|
168
|
+
}
|
|
169
|
+
return textareaElement;
|
|
182
170
|
};
|
|
183
171
|
// Layout for the textarea with a left-aligned label
|
|
184
172
|
const renderedLeftLabelTextArea = () => {
|
|
@@ -23,6 +23,7 @@ interface ITMSearchProps {
|
|
|
23
23
|
onFileOpened?: (dcmtFile: File | undefined) => void;
|
|
24
24
|
onTaskCreateRequest?: (taskContext: TaskContext, onTaskCreated?: (task?: TaskDescriptor) => void) => void;
|
|
25
25
|
openWGsCopyMoveForm?: (mode: "copyToWgDraft" | "copyToWgArchivedDoc", dcmtTypeDescriptor: DcmtTypeDescriptor, documents: Array<DcmtInfo>) => void;
|
|
26
|
+
editPdfForm?: boolean;
|
|
26
27
|
openEditPdf?: (documents: Array<DcmtInfo>) => void;
|
|
27
28
|
openS4TViewer?: boolean;
|
|
28
29
|
onOpenS4TViewerRequest?: (dcmtInfo: Array<DcmtInfo>, onRefreshSearchAsync?: (() => Promise<void>)) => void;
|
|
@@ -19,7 +19,7 @@ var TMSearchViews;
|
|
|
19
19
|
TMSearchViews[TMSearchViews["Search"] = 0] = "Search";
|
|
20
20
|
TMSearchViews[TMSearchViews["Result"] = 1] = "Result";
|
|
21
21
|
})(TMSearchViews || (TMSearchViews = {}));
|
|
22
|
-
const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, openInOffice, isVisible, inputTID, inputSqdID, inputMids, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, floatingActionConfig, onFileOpened, onRefreshAfterAddDcmtToFavs, onTaskCreateRequest, openWGsCopyMoveForm, openEditPdf, openS4TViewer, onOpenS4TViewerRequest, showTodoDcmtForm, passToArchiveCallback, onCurrentTIDChangedCallback, onlyShowSearchQueryPanel, onReferenceClick }) => {
|
|
22
|
+
const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, openInOffice, isVisible, inputTID, inputSqdID, inputMids, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, floatingActionConfig, onFileOpened, onRefreshAfterAddDcmtToFavs, onTaskCreateRequest, openWGsCopyMoveForm, openEditPdf, editPdfForm = false, openS4TViewer, onOpenS4TViewerRequest, showTodoDcmtForm, passToArchiveCallback, onCurrentTIDChangedCallback, onlyShowSearchQueryPanel, onReferenceClick }) => {
|
|
23
23
|
const [allSQDs, setAllSQDs] = useState([]);
|
|
24
24
|
const [filteredByTIDSQDs, setFilteredByTIDSQDs] = useState([]);
|
|
25
25
|
const [currentSQD, setCurrentSQD] = useState();
|
|
@@ -254,7 +254,7 @@ const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTask
|
|
|
254
254
|
toolbarOptions: { icon: _jsx(IconSavedQuery, { fontSize: 24 }), visible: true, orderNumber: 4, isActive: allInitialPanelVisibility['TMSavedQuerySelector'] }
|
|
255
255
|
}
|
|
256
256
|
], [tmTreeSelectorElement, showSearchResults, tmRecentsManagerElement, tmSearchQueryPanelElement, tmSavedQuerySelectorElement, fromDTD, mruTIDs]);
|
|
257
|
-
return (_jsxs(_Fragment, { children: [showSearchResults ? _jsx(StyledMultiViewPanel, { "$isVisible": currentSearchView === TMSearchViews.Search, children: _jsx(TMPanelManagerWithPersistenceProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'TMRecentsManager', isPersistenceEnabled: !isMobile ? hasSavedLayout() : false, persistPanelStates: !isMobile ? (state) => persistPanelStates(state) : undefined, persistedPanelStates: getPersistedPanelStates(), children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true, minPanelSizePx: !isMobile ? 250 : 150 }) }) }) : tmSearchQueryPanelElement, showSearchResults && _jsx(TMSearchResult, { isVisible: isVisible && currentSearchView === TMSearchViews.Result, context: SearchResultContext.METADATA_SEARCH, searchResults: searchResult, floatingActionConfig: floatingActionConfig, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, openInOffice: openInOffice, onRefreshSearchAsync: onRefreshSearchAsync, onClose: () => { onlyShowSearchQueryPanel ? setShowSearchResults(false) : setCurrentSearchView(TMSearchViews.Search); }, onFileOpened: onFileOpened, onTaskCreateRequest: onTaskCreateRequest, openWGsCopyMoveForm: openWGsCopyMoveForm, openEditPdf: openEditPdf, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, passToArchiveCallback: passToArchiveCallback, onSelectedTIDChanged: onCurrentTIDChangedCallback, showTodoDcmtForm: showTodoDcmtForm, onReferenceClick: onReferenceClick, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers })] }));
|
|
257
|
+
return (_jsxs(_Fragment, { children: [showSearchResults ? _jsx(StyledMultiViewPanel, { "$isVisible": currentSearchView === TMSearchViews.Search, children: _jsx(TMPanelManagerWithPersistenceProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'TMRecentsManager', isPersistenceEnabled: !isMobile ? hasSavedLayout() : false, persistPanelStates: !isMobile ? (state) => persistPanelStates(state) : undefined, persistedPanelStates: getPersistedPanelStates(), children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true, minPanelSizePx: !isMobile ? 250 : 150 }) }) }) : tmSearchQueryPanelElement, showSearchResults && _jsx(TMSearchResult, { isVisible: isVisible && currentSearchView === TMSearchViews.Result, context: SearchResultContext.METADATA_SEARCH, searchResults: searchResult, floatingActionConfig: floatingActionConfig, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, openInOffice: openInOffice, onRefreshSearchAsync: onRefreshSearchAsync, onClose: () => { onlyShowSearchQueryPanel ? setShowSearchResults(false) : setCurrentSearchView(TMSearchViews.Search); }, onFileOpened: onFileOpened, onTaskCreateRequest: onTaskCreateRequest, openWGsCopyMoveForm: openWGsCopyMoveForm, editPdfForm: editPdfForm, openEditPdf: openEditPdf, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, passToArchiveCallback: passToArchiveCallback, onSelectedTIDChanged: onCurrentTIDChangedCallback, showTodoDcmtForm: showTodoDcmtForm, onReferenceClick: onReferenceClick, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers })] }));
|
|
258
258
|
};
|
|
259
259
|
export default TMSearch;
|
|
260
260
|
const TMTreeSelectorWrapper = ({ isMobile, onSelectedTIDChanged }) => {
|
|
@@ -37,6 +37,7 @@ interface ITMSearchResultProps {
|
|
|
37
37
|
onFileOpened?: (blob: File | undefined) => void;
|
|
38
38
|
onTaskCreateRequest?: (taskContext: TaskContext, onTaskCreated?: (task?: TaskDescriptor) => void) => void;
|
|
39
39
|
openWGsCopyMoveForm?: (mode: "copyToWgDraft" | "copyToWgArchivedDoc", dcmtTypeDescriptor: DcmtTypeDescriptor, documents: Array<DcmtInfo>) => void;
|
|
40
|
+
editPdfForm?: boolean;
|
|
40
41
|
openEditPdf?: (documents: Array<DcmtInfo>) => void;
|
|
41
42
|
openCommentFormCallback?: (documents: Array<DcmtInfo>) => void;
|
|
42
43
|
openAddDocumentForm?: () => void;
|
|
@@ -67,7 +67,7 @@ const orderByName = (array) => {
|
|
|
67
67
|
return 1;
|
|
68
68
|
} return 0; });
|
|
69
69
|
};
|
|
70
|
-
const TMSearchResult = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, context = SearchResultContext.METADATA_SEARCH, isVisible = true, allowRelations = true, openDcmtFormAsModal = false, searchResults = [], showSearchResultSidebar = true, showSelector = false, groupId, title, isClosable = false, allowFloatingBar = true, showToolbarHeader = true, showBackButton = true, selectedSearchResultTID, workingGroupContext = undefined, disableAccordionIfSingleCategory = false, floatingActionConfig, openInOffice, onRefreshAfterAddDcmtToFavs, onRefreshSearchAsync, onSelectedTIDChanged, onWFOperationCompleted, onClose, onFileOpened, onTaskCreateRequest, openWGsCopyMoveForm, openEditPdf, openCommentFormCallback, openAddDocumentForm, openS4TViewer = false, onOpenS4TViewerRequest, passToArchiveCallback, showTodoDcmtForm = false, onReferenceClick, }) => {
|
|
70
|
+
const TMSearchResult = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, context = SearchResultContext.METADATA_SEARCH, isVisible = true, allowRelations = true, openDcmtFormAsModal = false, searchResults = [], showSearchResultSidebar = true, showSelector = false, groupId, title, isClosable = false, allowFloatingBar = true, showToolbarHeader = true, showBackButton = true, selectedSearchResultTID, workingGroupContext = undefined, disableAccordionIfSingleCategory = false, floatingActionConfig, openInOffice, onRefreshAfterAddDcmtToFavs, onRefreshSearchAsync, onSelectedTIDChanged, onWFOperationCompleted, onClose, onFileOpened, onTaskCreateRequest, openWGsCopyMoveForm, editPdfForm = false, openEditPdf, openCommentFormCallback, openAddDocumentForm, openS4TViewer = false, onOpenS4TViewerRequest, passToArchiveCallback, showTodoDcmtForm = false, onReferenceClick, }) => {
|
|
71
71
|
const [id, setID] = useState('');
|
|
72
72
|
const [showApprovePopup, setShowApprovePopup] = useState(false);
|
|
73
73
|
const [showRejectPopup, setShowRejectPopup] = useState(false);
|
|
@@ -576,6 +576,21 @@ const TMSearchResult = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, a
|
|
|
576
576
|
const showToppyForApprove = useMemo(() => {
|
|
577
577
|
return Boolean(isVisible && fromDTD && isApprovalWorkflowView(fromDTD) && !isOpenDcmtForm && !isOpenDetails && !isOpenMaster);
|
|
578
578
|
}, [isVisible, fromDTD, isOpenDcmtForm, isOpenDetails, isOpenMaster]);
|
|
579
|
+
/**
|
|
580
|
+
* TMToppyDraggableHelpCenter viene nascosto quando è aperto qualsiasi altro popup o modale che potrebbe
|
|
581
|
+
* interferire con l'interazione dell'utente (approvazione, rifiuto, riassegnazione, info aggiuntive,
|
|
582
|
+
* modifica PDF, visualizzatore S4T, form todo documento).
|
|
583
|
+
*/
|
|
584
|
+
const isToppyHelpCenterVisible = useMemo(() => {
|
|
585
|
+
return Boolean(showToppyForApprove
|
|
586
|
+
&& !showApprovePopup
|
|
587
|
+
&& !showRejectPopup
|
|
588
|
+
&& !showReAssignPopup
|
|
589
|
+
&& !showMoreInfoPopup
|
|
590
|
+
&& !editPdfForm
|
|
591
|
+
&& !openS4TViewer
|
|
592
|
+
&& !showTodoDcmtForm);
|
|
593
|
+
}, [showToppyForApprove, showApprovePopup, showRejectPopup, showReAssignPopup, showMoreInfoPopup, editPdfForm, openS4TViewer, showTodoDcmtForm]);
|
|
579
594
|
const floatingMenuItems = useMemo(() => {
|
|
580
595
|
const baseMenuItems = 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, handleCheckInOperationCallback, showCheckoutInformationFormCallback, showHistoryCallback, copyCheckoutPathToClipboardOperationCallback, openWGsCopyMoveForm, openCommentFormCallback, openEditPdf, openAddDocumentForm, passToArchiveCallback, archiveMasterDocuments, archiveDetailDocuments, currentTIDHasMasterRelations, currentTIDHasDetailRelations, canArchiveMasterRelation, canArchiveDetailRelation, pairManyToMany, hasManyToManyRelation);
|
|
581
596
|
const customButtons = customButtonMenuItems();
|
|
@@ -601,7 +616,7 @@ const TMSearchResult = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, a
|
|
|
601
616
|
setIsOpenBatchUpdate(false);
|
|
602
617
|
setIsModifiedBatchUpdate(false);
|
|
603
618
|
await refreshSelectionDataRowsAsync();
|
|
604
|
-
}, onStatusChanged: (isModified) => { setIsModifiedBatchUpdate(isModified); } }), _jsx(TMToppyDraggableHelpCenter, { usePortal: true, isVisible:
|
|
619
|
+
}, onStatusChanged: (isModified) => { setIsModifiedBatchUpdate(isModified); } }), _jsx(TMToppyDraggableHelpCenter, { usePortal: true, isVisible: isToppyHelpCenterVisible, content: _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: '10px' }, children: _jsx(WorkFlowOperationButtons, { deviceType: deviceType, onApprove: () => {
|
|
605
620
|
setShowApprovePopup(true);
|
|
606
621
|
}, onSignApprove: () => {
|
|
607
622
|
handleSignApprove();
|
|
@@ -644,7 +659,7 @@ const TMSearchResult = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, a
|
|
|
644
659
|
TMSpinner.hide();
|
|
645
660
|
}
|
|
646
661
|
}, onClose: () => setShowManyToManyChooser(false), manageUseLocalizedName: false }), showPairDcmtsModal &&
|
|
647
|
-
_jsx(TMModal, { title: (isPairingManyToMany ? "Abbina" : "Disabbina") + " documenti", onClose: () => setShowPairDcmtsModal(false), width: isMobile ? '90%' : '50%', height: isMobile ? '90%' : '70%', children: _jsx(TMSearchResult, { searchResults: pairedSearchResults, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, onRefreshSearchAsync: onRefreshSearchAsync, onFileOpened: onFileOpened, onTaskCreateRequest: onTaskCreateRequest, openWGsCopyMoveForm: openWGsCopyMoveForm, openEditPdf: openEditPdf, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, passToArchiveCallback: passToArchiveCallback, showTodoDcmtForm: showTodoDcmtForm, allowFloatingBar: false, floatingActionConfig: pairFloatingActionConfig, showBackButton: false, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }) }), showPairSearchModal &&
|
|
662
|
+
_jsx(TMModal, { title: (isPairingManyToMany ? "Abbina" : "Disabbina") + " documenti", onClose: () => setShowPairDcmtsModal(false), width: isMobile ? '90%' : '50%', height: isMobile ? '90%' : '70%', children: _jsx(TMSearchResult, { searchResults: pairedSearchResults, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, onRefreshSearchAsync: onRefreshSearchAsync, onFileOpened: onFileOpened, onTaskCreateRequest: onTaskCreateRequest, openWGsCopyMoveForm: openWGsCopyMoveForm, editPdfForm: editPdfForm, openEditPdf: openEditPdf, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, passToArchiveCallback: passToArchiveCallback, showTodoDcmtForm: showTodoDcmtForm, allowFloatingBar: false, floatingActionConfig: pairFloatingActionConfig, showBackButton: false, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }) }), showPairSearchModal &&
|
|
648
663
|
_jsx(TMModal, { title: "Ricerca documenti", onClose: () => setShowPairSearchModal(false), width: isMobile ? '90%' : '50%', height: isMobile ? '90%' : '70%', children: _jsx(TMSearch, { onlyShowSearchQueryPanel: true, inputTID: pairSearchModalTargetTID, inputMids: pairSearchModalInputMids, floatingActionConfig: pairSearchModalFloatingActionConfig, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }) }), isOpenSharedArchive && _jsx(TMModal, { title: "Archiviazione condivisa", onClose: () => {
|
|
649
664
|
setIsOpenSharedArchive(false);
|
|
650
665
|
}, width: isMobile ? '90%' : '60%', height: isMobile ? '90%' : '80%', children: _jsx(TMArchive, { inputDID: focusedItem?.DID, inputTID: focusedItem?.TID, inputMids: currentMetadataValues.filter(md => md.mid && md.mid > 100).map(md => ({ mid: md.mid, value: md.value ?? '' })), isSharedArchive: true, inputFile: sharedDcmtFile, onSavedAsyncCallback: async (tid, did) => {
|
|
@@ -708,6 +723,7 @@ const TMSearchResult = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, a
|
|
|
708
723
|
onRefreshSearchAsync,
|
|
709
724
|
handleNavigateToWGs,
|
|
710
725
|
handleNavigateToDossiers,
|
|
726
|
+
editPdfForm
|
|
711
727
|
]);
|
|
712
728
|
const tmBlog = useMemo(() => _jsx(TMDcmtBlog, { tid: focusedItem?.TID, did: focusedItem?.DID, fetchBlogDataTrigger: refreshBlogTrigger, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }), [focusedItem, allTasks, refreshBlogTrigger, handleNavigateToWGs, handleNavigateToDossiers]);
|
|
713
729
|
const tmSysMetadata = useMemo(() => _jsx(TMMetadataValues, { layoutMode: LayoutModes.Update, openChooserBySingleClick: true, TID: focusedItem?.TID, isReadOnly: true, deviceType: deviceType, metadataValues: currentMetadataValues.filter(o => (o.mid != undefined && o.mid <= 100)), metadataValuesOrig: currentMetadataValues.filter(o => (o.mid != undefined && o.mid <= 100)), validationItems: [] }), [focusedItem, currentMetadataValues, deviceType]);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { default as ShowAlert } from './base/TMAlert';
|
|
2
2
|
export { default as TMButton } from './base/TMButton';
|
|
3
3
|
export { default as TMClosableList } from './base/TMClosableList';
|
|
4
|
-
export * from './base/TMContextMenu';
|
|
5
4
|
export { default as TMDropDownMenu } from './base/TMDropDownMenu';
|
|
6
5
|
export * from './base/TMListView';
|
|
7
6
|
export { default as TMList } from './base/TMList';
|
|
@@ -25,7 +24,6 @@ export { default as TMToggleButton } from './base/TMToggleButton';
|
|
|
25
24
|
export { default as TMTooltip } from './base/TMTooltip';
|
|
26
25
|
export { default as TMVilViewer } from './base/TMVilViewer';
|
|
27
26
|
export { default as TMUserAvatar } from './base/TMUserAvatar';
|
|
28
|
-
export { default as TMFloatingToolbar } from './base/TMFloatingToolbar';
|
|
29
27
|
export { default as TMDropDown } from './editors/TMDropDown';
|
|
30
28
|
export { default as TMTreeDropDown } from './editors/TMTreeDropDown';
|
|
31
29
|
export { default as TMSummary } from './editors/TMSummary';
|
package/lib/components/index.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
export { default as ShowAlert } from './base/TMAlert';
|
|
3
3
|
export { default as TMButton } from './base/TMButton';
|
|
4
4
|
export { default as TMClosableList } from './base/TMClosableList';
|
|
5
|
-
export * from './base/TMContextMenu';
|
|
6
5
|
export { default as TMDropDownMenu } from './base/TMDropDownMenu';
|
|
7
6
|
export * from './base/TMListView';
|
|
8
7
|
export { default as TMList } from './base/TMList';
|
|
@@ -26,7 +25,6 @@ export { default as TMToggleButton } from './base/TMToggleButton';
|
|
|
26
25
|
export { default as TMTooltip } from './base/TMTooltip';
|
|
27
26
|
export { default as TMVilViewer } from './base/TMVilViewer';
|
|
28
27
|
export { default as TMUserAvatar } from './base/TMUserAvatar';
|
|
29
|
-
export { default as TMFloatingToolbar } from './base/TMFloatingToolbar';
|
|
30
28
|
//editors
|
|
31
29
|
export { default as TMDropDown } from './editors/TMDropDown';
|
|
32
30
|
export { default as TMTreeDropDown } from './editors/TMTreeDropDown';
|
package/package.json
CHANGED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import React, { ReactNode } from 'react';
|
|
2
|
-
export interface ITMContextMenuItemProps {
|
|
3
|
-
icon?: ReactNode;
|
|
4
|
-
text?: any;
|
|
5
|
-
items?: ITMContextMenuItemProps[];
|
|
6
|
-
disabled?: boolean;
|
|
7
|
-
isSelected?: boolean;
|
|
8
|
-
id?: string;
|
|
9
|
-
onItemClick?: () => void;
|
|
10
|
-
onItemMouseOver?: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
|
|
11
|
-
}
|
|
12
|
-
export interface ITMContextMenuProps {
|
|
13
|
-
items?: ITMContextMenuItemProps[];
|
|
14
|
-
coords?: {
|
|
15
|
-
x: number;
|
|
16
|
-
y: number;
|
|
17
|
-
};
|
|
18
|
-
subMenuDir?: 'left' | 'right';
|
|
19
|
-
}
|
|
20
|
-
declare const TMContextMenu: ({ items, coords, subMenuDir, }: ITMContextMenuProps) => import("react/jsx-runtime").JSX.Element;
|
|
21
|
-
export declare const useTMContextMenu: (ref: React.RefObject<HTMLElement>) => (boolean | {
|
|
22
|
-
x: number;
|
|
23
|
-
y: number;
|
|
24
|
-
})[];
|
|
25
|
-
export default TMContextMenu;
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useRef, useState } from 'react';
|
|
3
|
-
import styled from 'styled-components';
|
|
4
|
-
import { IconRight } from '../../helper/TMIcons';
|
|
5
|
-
const StyledContextMenuContainer = styled.div `
|
|
6
|
-
display: flex; flex-direction: column; align-items: flex-start; justify-content: flex-start; z-index: 300; position: fixed; top: ${props => `${props.$top}px`}; left: ${props => `${props.$left}px`}; right: ${props => `${props.$right}px`}; bottom: ${props => `${props.$bottom}px`}; width: max-content; height: max-content; background-color: white; box-shadow: 1px 1px 2px #00000040;
|
|
7
|
-
`;
|
|
8
|
-
const StyledContextMenuItem = styled.div `
|
|
9
|
-
cursor: ${props => !props.$disabled ? 'pointer' : 'default'}; display: flex; align-items: center; gap: 5px; transition: ease 100ms; padding: 5px; background-color: ${props => props.$isSelected && '#e9e9e9'}; width: 100%; height: 100%; color: ${props => props.$disabled && '#d0d0d0'}; &:hover { background-color: ${props => !props.$disabled && '#e9e9e9'} ; }
|
|
10
|
-
`;
|
|
11
|
-
const TMContextMenu = ({ items = [], coords = { x: 0, y: 0 }, subMenuDir = 'right', }) => {
|
|
12
|
-
// Coordinates for sub-menus
|
|
13
|
-
const [subMenuCoords, setSubMenuCoords] = useState({ x: 0, y: 0 });
|
|
14
|
-
// Track which item is currently hovered
|
|
15
|
-
const [hoveredItem, setHoveredItem] = useState(null);
|
|
16
|
-
// Size of the menu
|
|
17
|
-
const [menuSize, setMenuSize] = useState({ x: 0, y: 0 });
|
|
18
|
-
// Current direction for submenus
|
|
19
|
-
const [currentSubMenuDir, setCurrentSubMenuDir] = useState(subMenuDir);
|
|
20
|
-
// Reference to the context menu DOM element
|
|
21
|
-
const contextMenuRef = useRef(null);
|
|
22
|
-
// Uupdate submenu direction based on incoming props
|
|
23
|
-
useEffect(() => setCurrentSubMenuDir(subMenuDir), [subMenuDir]);
|
|
24
|
-
// Calculate the size of the context menu and adjust submenu direction
|
|
25
|
-
// Run this effect only once when the component mounts
|
|
26
|
-
useEffect(() => {
|
|
27
|
-
if (contextMenuRef.current) {
|
|
28
|
-
setMenuSize({
|
|
29
|
-
x: contextMenuRef.current.getBoundingClientRect().width || 0,
|
|
30
|
-
y: contextMenuRef.current.getBoundingClientRect().height || 0,
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
}, []);
|
|
34
|
-
useEffect(() => {
|
|
35
|
-
// This effect checks the width on resize
|
|
36
|
-
const handleResize = () => {
|
|
37
|
-
if (window.innerWidth <= coords.x + menuSize.x) {
|
|
38
|
-
// Change direction to left if menu goes beyond right edge
|
|
39
|
-
setCurrentSubMenuDir('left');
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
42
|
-
// Default to right if there's space
|
|
43
|
-
setCurrentSubMenuDir('right');
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
// Attach event listener
|
|
47
|
-
window.addEventListener('resize', handleResize);
|
|
48
|
-
handleResize(); // Call it initially to set the direction
|
|
49
|
-
// Clean up the event listener on unmount
|
|
50
|
-
return () => {
|
|
51
|
-
window.removeEventListener('resize', handleResize);
|
|
52
|
-
};
|
|
53
|
-
}, [coords, menuSize.x]); // Only watch coords and the width of menuSize
|
|
54
|
-
// Handle mouse over event on items to potentially show submenus
|
|
55
|
-
const onItemMouseOver = (item, index) => {
|
|
56
|
-
if (!item.disabled && item.items && item.items.length > 0) {
|
|
57
|
-
setHoveredItem(index);
|
|
58
|
-
const boundingRect = contextMenuRef.current?.getBoundingClientRect();
|
|
59
|
-
if (boundingRect) {
|
|
60
|
-
// Calculate the sub-menu position based on the current item position
|
|
61
|
-
const subMenuX = currentSubMenuDir === 'right' ? boundingRect.right : boundingRect.left - menuSize.x;
|
|
62
|
-
const subMenuY = boundingRect.top + index * 30; // Adjust Y coordinate to match item
|
|
63
|
-
setSubMenuCoords({ x: subMenuX, y: subMenuY });
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
// Clear hover state if the item has no sub-menu
|
|
68
|
-
setHoveredItem(null); // If no submenu, clear hover state
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
return (_jsx(StyledContextMenuContainer, { ref: contextMenuRef, "$left": currentSubMenuDir === 'right' ? coords.x : 'none', "$top": window.innerHeight > coords.y + menuSize.y ? coords.y : 'none', "$right": currentSubMenuDir === 'left' ? window.innerWidth - coords.x : 'none', "$bottom": window.innerHeight <= coords.y + menuSize.y ? window.innerHeight - coords.y : 'none', children: items.map((item, index) => (_jsxs("div", { style: { width: '100%' }, children: [_jsxs(StyledContextMenuItem, { id: item.id, onMouseOver: () => onItemMouseOver(item, index), onMouseEnter: () => onItemMouseOver(item, index), "$isSelected": item.isSelected, "$disabled": item.disabled, onClick: () => !item.disabled && item.onItemClick && item.onItemClick(), children: [_jsx("div", { style: { transform: 'translateY(3px)' }, children: item.icon }), _jsx("div", { style: { width: '100%' }, children: item.items && item.items.length > 0 ? (_jsxs("div", { style: {
|
|
72
|
-
width: '100%',
|
|
73
|
-
display: 'flex',
|
|
74
|
-
alignItems: 'center',
|
|
75
|
-
gap: 5,
|
|
76
|
-
justifyContent: 'space-between',
|
|
77
|
-
}, children: [item.text, " ", _jsx(IconRight, { style: { transform: 'translateY(1px)' }, fontSize: 10 })] })) : (_jsx("div", { style: { width: '100%' }, children: item.text })) })] }), item.items && item.items.length > 0 && hoveredItem === index && (_jsx(TMContextMenu, { subMenuDir: currentSubMenuDir, coords: subMenuCoords, items: item.items }))] }, index))) }));
|
|
78
|
-
};
|
|
79
|
-
export const useTMContextMenu = (ref) => {
|
|
80
|
-
// Coordinates for the context menu
|
|
81
|
-
const [coords, setCoords] = useState({ x: 0, y: 0 });
|
|
82
|
-
// State to control visibility of the context menu
|
|
83
|
-
const [showContextMenu, setShowContexMenu] = useState(false);
|
|
84
|
-
// Effect to hide context menu when clicking outside of the referenced element
|
|
85
|
-
useEffect(() => {
|
|
86
|
-
const menu = ref.current;
|
|
87
|
-
const deSelectAll = (e) => { if (menu && !menu.contains(e.target)) {
|
|
88
|
-
setShowContexMenu(false);
|
|
89
|
-
} };
|
|
90
|
-
window.addEventListener('contextmenu', deSelectAll);
|
|
91
|
-
return () => { window.removeEventListener('contextmenu', deSelectAll); };
|
|
92
|
-
}, []);
|
|
93
|
-
// Effect to hide context menu on left-click anywhere
|
|
94
|
-
useEffect(() => {
|
|
95
|
-
const handleClick = () => { setShowContexMenu(false); };
|
|
96
|
-
window.addEventListener("click", handleClick);
|
|
97
|
-
return () => { window.removeEventListener("click", handleClick); };
|
|
98
|
-
}, []);
|
|
99
|
-
// Effect to show context menu on right-click and prevent default context menu
|
|
100
|
-
useEffect(() => {
|
|
101
|
-
let menu = ref.current;
|
|
102
|
-
if (menu) {
|
|
103
|
-
menu?.addEventListener('contextmenu', (e) => { e.preventDefault(); setShowContexMenu(true); setCoords({ x: e.pageX, y: e.pageY }); });
|
|
104
|
-
}
|
|
105
|
-
return () => menu?.removeEventListener('contextmenu', (e) => { setCoords({ x: e.pageX, y: e.pageY }); });
|
|
106
|
-
}, [ref]);
|
|
107
|
-
return [coords, showContextMenu];
|
|
108
|
-
};
|
|
109
|
-
export default TMContextMenu;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
export declare const useContextMenu: () => {
|
|
3
|
-
clicked: boolean;
|
|
4
|
-
setClicked: React.Dispatch<React.SetStateAction<boolean>>;
|
|
5
|
-
points: {
|
|
6
|
-
x: number;
|
|
7
|
-
y: number;
|
|
8
|
-
};
|
|
9
|
-
setPoints: React.Dispatch<React.SetStateAction<{
|
|
10
|
-
x: number;
|
|
11
|
-
y: number;
|
|
12
|
-
}>>;
|
|
13
|
-
};
|
|
14
|
-
export declare const Container: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
15
|
-
$top: number;
|
|
16
|
-
$left: number;
|
|
17
|
-
}>> & string;
|
|
18
|
-
export declare const MenuOption: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
19
|
-
interface ITMContextMenu {
|
|
20
|
-
menuData: any[];
|
|
21
|
-
onMenuItemClick?: (item: string) => void;
|
|
22
|
-
top: number;
|
|
23
|
-
left: number;
|
|
24
|
-
}
|
|
25
|
-
declare const TMContextMenuOLD: React.FunctionComponent<ITMContextMenu>;
|
|
26
|
-
export default TMContextMenuOLD;
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useState } from 'react';
|
|
3
|
-
import styled from 'styled-components';
|
|
4
|
-
import { Colors, FontSize } from '../../utils/theme';
|
|
5
|
-
// #region Hook useContextMenu
|
|
6
|
-
export const useContextMenu = () => {
|
|
7
|
-
// boolean value to determine if the user has right clicked
|
|
8
|
-
const [clicked, setClicked] = useState(false);
|
|
9
|
-
// allows us to track the x,y coordinates of the users right click
|
|
10
|
-
const [points, setPoints] = useState({ x: 0, y: 0 });
|
|
11
|
-
useEffect(() => {
|
|
12
|
-
// reset clicked to false on user click
|
|
13
|
-
const handleClick = () => {
|
|
14
|
-
setClicked(false);
|
|
15
|
-
};
|
|
16
|
-
// add listener for user click
|
|
17
|
-
document.addEventListener("click", handleClick);
|
|
18
|
-
// clean up listener function to avoid memory leaks
|
|
19
|
-
return () => {
|
|
20
|
-
document.removeEventListener("click", handleClick);
|
|
21
|
-
};
|
|
22
|
-
}, []);
|
|
23
|
-
return { clicked, setClicked, points, setPoints };
|
|
24
|
-
};
|
|
25
|
-
// #endregion
|
|
26
|
-
export const Container = styled.div `
|
|
27
|
-
position: absolute;
|
|
28
|
-
padding: 5px 5px;
|
|
29
|
-
background-color: white;
|
|
30
|
-
width: max-content;
|
|
31
|
-
height: max-content;
|
|
32
|
-
border-radius: 2px;
|
|
33
|
-
display: flex;
|
|
34
|
-
flex-direction: column;
|
|
35
|
-
justify-content: flex-start;
|
|
36
|
-
align-items: center;
|
|
37
|
-
box-shadow: 2px 2px 10px #00000030;
|
|
38
|
-
z-index: 2;
|
|
39
|
-
top: ${(props) => props.$top || 0}px;
|
|
40
|
-
left: ${(props) => props.$left || 0}px;
|
|
41
|
-
`;
|
|
42
|
-
export const MenuOption = styled.div `
|
|
43
|
-
width: 100%;
|
|
44
|
-
height: 20px;
|
|
45
|
-
padding: 3px;
|
|
46
|
-
cursor: pointer;
|
|
47
|
-
font-size: ${FontSize.defaultFontSize};
|
|
48
|
-
|
|
49
|
-
&:hover {
|
|
50
|
-
color: ${Colors.primary};
|
|
51
|
-
}
|
|
52
|
-
`;
|
|
53
|
-
const TMContextMenuOLD = ({ menuData, top, left, onMenuItemClick }) => {
|
|
54
|
-
return (_jsx(_Fragment, { children: _jsx(Container, { "$top": top, "$left": left, children: menuData.map((item, index) => (_jsx(MenuOption, { onClick: (e) => onMenuItemClick?.(e.target.innerText), children: item.text }, index))) }) }));
|
|
55
|
-
};
|
|
56
|
-
export default TMContextMenuOLD;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
interface ITMFloatingToolbarProps {
|
|
3
|
-
children: React.ReactNode;
|
|
4
|
-
backgroundColor: string | undefined;
|
|
5
|
-
initialLeft?: string;
|
|
6
|
-
initialTop?: string;
|
|
7
|
-
}
|
|
8
|
-
declare const TMFloatingToolbar: ({ children, backgroundColor, initialLeft, initialTop }: ITMFloatingToolbarProps) => import("react/jsx-runtime").JSX.Element;
|
|
9
|
-
export default TMFloatingToolbar;
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useRef } from 'react';
|
|
3
|
-
import styled from 'styled-components';
|
|
4
|
-
import { IconDraggabledots } from '../../helper/TMIcons';
|
|
5
|
-
const StyledFloatingToolbarContainer = styled.div `
|
|
6
|
-
position: absolute;
|
|
7
|
-
width: max-content;
|
|
8
|
-
height: max-content;
|
|
9
|
-
display: flex;
|
|
10
|
-
flex-direction: row;
|
|
11
|
-
background-color: ${props => `${props.$backgroundColor}a6`};
|
|
12
|
-
left: calc(50% - 90px);
|
|
13
|
-
top: calc(100% - 40px);
|
|
14
|
-
border-radius: 8px;
|
|
15
|
-
z-index: 10;
|
|
16
|
-
&:hover {
|
|
17
|
-
background: ${props => props.$backgroundColor};
|
|
18
|
-
}
|
|
19
|
-
`;
|
|
20
|
-
const StyledFloatingToolbarDraggable = styled.div `
|
|
21
|
-
display: flex;
|
|
22
|
-
align-items: center;
|
|
23
|
-
justify-content: center;
|
|
24
|
-
width: 25px;
|
|
25
|
-
height: 100%;
|
|
26
|
-
background-color: ${props => `${props.$backgroundColor}FF`};
|
|
27
|
-
border-top-left-radius: 8px;
|
|
28
|
-
border-bottom-left-radius: 8px;
|
|
29
|
-
padding: 10px 0px 10px 0px;
|
|
30
|
-
&:hover {
|
|
31
|
-
cursor: grab;
|
|
32
|
-
}
|
|
33
|
-
`;
|
|
34
|
-
const StyledFloatingToolbar = styled.div `
|
|
35
|
-
width: max-content;
|
|
36
|
-
display: flex;
|
|
37
|
-
flex-direction: row;
|
|
38
|
-
padding: 10px 10px 10px 20px;
|
|
39
|
-
gap: 8px;
|
|
40
|
-
border-radius: 8px;
|
|
41
|
-
`;
|
|
42
|
-
const TMFloatingToolbar = ({ children, backgroundColor, initialLeft, initialTop }) => {
|
|
43
|
-
const boxRef = useRef(null);
|
|
44
|
-
const boxDraggableRef = useRef(null);
|
|
45
|
-
const isClicked = useRef(false);
|
|
46
|
-
const coords = useRef({
|
|
47
|
-
startX: 0,
|
|
48
|
-
startY: 0,
|
|
49
|
-
lastX: 0,
|
|
50
|
-
lastY: 0
|
|
51
|
-
});
|
|
52
|
-
useEffect(() => {
|
|
53
|
-
if (!boxRef.current)
|
|
54
|
-
return;
|
|
55
|
-
if (!boxDraggableRef.current)
|
|
56
|
-
return;
|
|
57
|
-
let container = boxRef.current?.parentElement;
|
|
58
|
-
if (!container)
|
|
59
|
-
return;
|
|
60
|
-
const box = boxRef.current;
|
|
61
|
-
box.style.top = initialTop ?? `0px`;
|
|
62
|
-
box.style.left = initialLeft ?? `0px`;
|
|
63
|
-
const onMouseDown = (e) => {
|
|
64
|
-
isClicked.current = true;
|
|
65
|
-
coords.current.startX = e.clientX;
|
|
66
|
-
coords.current.startY = e.clientY;
|
|
67
|
-
coords.current.lastX = box.offsetLeft;
|
|
68
|
-
coords.current.lastY = box.offsetTop;
|
|
69
|
-
};
|
|
70
|
-
const onMouseUp = (e) => {
|
|
71
|
-
isClicked.current = false;
|
|
72
|
-
coords.current.lastX = box.offsetLeft;
|
|
73
|
-
coords.current.lastY = box.offsetTop;
|
|
74
|
-
};
|
|
75
|
-
const onMouseMove = (e) => {
|
|
76
|
-
if (!isClicked.current)
|
|
77
|
-
return;
|
|
78
|
-
const nextX = e.clientX - coords.current.startX + coords.current.lastX;
|
|
79
|
-
const nextY = e.clientY - coords.current.startY + coords.current.lastY;
|
|
80
|
-
const screenWidth = container.getBoundingClientRect().width;
|
|
81
|
-
const screenHeight = container.getBoundingClientRect().height;
|
|
82
|
-
const boundedX = Math.max(0, Math.min(screenWidth - box.getBoundingClientRect().width, nextX));
|
|
83
|
-
const boundedY = Math.max(0, Math.min(screenHeight - box.getBoundingClientRect().height, nextY));
|
|
84
|
-
box.style.top = `${boundedY}px`;
|
|
85
|
-
box.style.left = `${boundedX}px`;
|
|
86
|
-
};
|
|
87
|
-
boxDraggableRef.current?.addEventListener('mousedown', onMouseDown);
|
|
88
|
-
window.addEventListener('mouseup', onMouseUp);
|
|
89
|
-
window.addEventListener('mousemove', onMouseMove);
|
|
90
|
-
window.addEventListener('mouseleave', onMouseUp);
|
|
91
|
-
const cleanup = () => {
|
|
92
|
-
boxDraggableRef.current?.removeEventListener('mousedown', onMouseDown);
|
|
93
|
-
window.removeEventListener('mouseup', onMouseUp);
|
|
94
|
-
window.removeEventListener('mousemove', onMouseMove);
|
|
95
|
-
window.removeEventListener('mouseleave', onMouseUp);
|
|
96
|
-
};
|
|
97
|
-
return cleanup;
|
|
98
|
-
}, [initialLeft, initialTop]);
|
|
99
|
-
return (_jsxs(StyledFloatingToolbarContainer, { ref: boxRef, "$backgroundColor": backgroundColor, children: [_jsx(StyledFloatingToolbarDraggable, { ref: boxDraggableRef, "$backgroundColor": backgroundColor, children: _jsx(IconDraggabledots, { color: 'white' }) }), _jsx(StyledFloatingToolbar, { "$backgroundColor": backgroundColor, children: children })] }));
|
|
100
|
-
};
|
|
101
|
-
export default TMFloatingToolbar;
|