@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.
@@ -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, { useTMContextMenu } from './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) => { setIsFocused(true); };
31
- let [coords, show] = useTMContextMenu(contRef);
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
- isSelected: key === orderedBy,
239
- onItemClick: () => { setOrderedBy(key); setShowOrderOptions(false); },
246
+ onClick: () => { setOrderedBy(key); setShowOrderOptions(false); setOrderMenuVisible(false); },
240
247
  icon: _jsx(IconColumns, { fontSize: 16 }),
241
- text: _jsxs("div", { style: { display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 10 }, children: [key, " ", key === orderedBy && _jsx(IconApply, { fontSize: 14, color: 'gray' })] })
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
- onItemClick: () => setLocalShowSearch(!localShowSearch),
332
- text: localShowSearch ? SDKUI_Localizator.HideSearch : SDKUI_Localizator.ShowSearch
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
- onItemClick: () => setLocalShowId(!localShowId),
340
- text: localShowId ? SDKUI_Localizator.ID_Hide : SDKUI_Localizator.ID_Show,
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
- onItemClick: () => setShowOrderMenu(!showOrderMenu),
349
- text: showOrderMenu ? 'Nascondi menu di ordinamento' : 'Mostra menu di ordinamento'
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: [(show && contextMenuItems.length > 0) && _jsx(TMContextMenu, { coords: coords, items: contextMenuItems }), showOrderOptions &&
356
- _jsx(TMContextMenu, { items: orderMenuItems(), coords: { x: orderRef.current?.getBoundingClientRect().left, y: orderRef.current?.getBoundingClientRect().top - (searchKeys.length * 30) - 10 } }), header && _jsx("div", { style: { width: '100%', height: '40px', backgroundColor: headerBackGroundColor ?? `${customColor}30`, marginBottom: '3px', display: 'flex', alignItems: 'center' }, children: header }), localShowSearch &&
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, { useContextMenu } from '../base/TMContextMenuOLD';
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
- // Populate the formula menu items whenever the `formulaItems` prop changes
73
- useEffect(() => {
74
- if (formulaItems && formulaItems.length > 0) {
75
- let menuItems = [];
76
- for (const formula of formulaItems) {
77
- menuItems.push({ text: formula });
78
- }
79
- setFormulaMenuItems(menuItems);
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
- return _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)
157
- onBlur?.(currentValue); }, onChange: (e) => { setCurrentValue(e.target.value); onValueChanged?.(e); }, onContextMenu: (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(), formulaItems.length > 0 && clicked && (_jsx(TMContextMenu, { menuData: formulaMenuItems, top: points.y, left: points.x, onMenuItemClick: (formula) => insertText(formula) })), _jsx(TMVilViewer, { vil: validationItems })] });
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: showToppyForApprove && !showApprovePopup && !showRejectPopup && !showReAssignPopup && !showMoreInfoPopup && !openS4TViewer && !showTodoDcmtForm, content: _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: '10px' }, children: _jsx(WorkFlowOperationButtons, { deviceType: deviceType, onApprove: () => {
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';
@@ -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,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react",
3
- "version": "6.20.0-dev1.93",
3
+ "version": "6.20.0-dev1.95",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -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;