@topconsultnpm/sdkui-react 6.20.0-dev1.13 → 6.20.0-dev1.130

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.
Files changed (202) hide show
  1. package/lib/assets/Toppy-help-center.png +0 -0
  2. package/lib/assets/headergradient.svg +87 -0
  3. package/lib/components/NewComponents/ContextMenu/TMContextMenu.js +322 -30
  4. package/lib/components/NewComponents/ContextMenu/hooks.d.ts +8 -1
  5. package/lib/components/NewComponents/ContextMenu/hooks.js +80 -8
  6. package/lib/components/NewComponents/ContextMenu/index.d.ts +3 -0
  7. package/lib/components/NewComponents/ContextMenu/index.js +2 -0
  8. package/lib/components/NewComponents/ContextMenu/styles.d.ts +9 -1
  9. package/lib/components/NewComponents/ContextMenu/styles.js +146 -47
  10. package/lib/components/NewComponents/ContextMenu/types.d.ts +22 -3
  11. package/lib/components/NewComponents/ContextMenu/useLongPress.d.ts +21 -0
  12. package/lib/components/NewComponents/ContextMenu/useLongPress.js +112 -0
  13. package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +620 -125
  14. package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +25 -5
  15. package/lib/components/NewComponents/FloatingMenuBar/styles.js +215 -59
  16. package/lib/components/NewComponents/FloatingMenuBar/types.d.ts +12 -3
  17. package/lib/components/base/TMAccordionNew.js +35 -14
  18. package/lib/components/base/TMButton.js +6 -0
  19. package/lib/components/base/TMClosableList.js +4 -0
  20. package/lib/components/base/TMCustomButton.js +61 -17
  21. package/lib/components/base/TMDataGrid.d.ts +7 -4
  22. package/lib/components/base/TMDataGrid.js +153 -11
  23. package/lib/components/base/TMDropDownMenu.js +21 -18
  24. package/lib/components/base/TMFileManager.d.ts +4 -3
  25. package/lib/components/base/TMFileManager.js +32 -24
  26. package/lib/components/base/TMFileManagerDataGridView.d.ts +3 -2
  27. package/lib/components/base/TMFileManagerDataGridView.js +1 -11
  28. package/lib/components/base/TMFileManagerThumbnailItems.d.ts +7 -1
  29. package/lib/components/base/TMFileManagerThumbnailItems.js +5 -2
  30. package/lib/components/base/TMFileManagerThumbnailsView.d.ts +17 -4
  31. package/lib/components/base/TMFileManagerThumbnailsView.js +18 -6
  32. package/lib/components/base/TMFileManagerUtils.d.ts +0 -12
  33. package/lib/components/base/TMListView.js +33 -15
  34. package/lib/components/base/TMPanel.d.ts +1 -1
  35. package/lib/components/base/TMPanel.js +4 -2
  36. package/lib/components/base/TMPopUp.js +6 -0
  37. package/lib/components/base/TMToolbarCard.js +2 -0
  38. package/lib/components/base/TMTreeView.d.ts +2 -1
  39. package/lib/components/base/TMTreeView.js +33 -26
  40. package/lib/components/choosers/TMDataListItemChooser.d.ts +2 -0
  41. package/lib/components/choosers/TMDataListItemChooser.js +8 -2
  42. package/lib/components/choosers/TMDcmtTypeChooser.d.ts +1 -0
  43. package/lib/components/choosers/TMDcmtTypeChooser.js +11 -3
  44. package/lib/components/choosers/TMDistinctValues.js +2 -2
  45. package/lib/components/choosers/TMDynDataListItemChooser.d.ts +2 -0
  46. package/lib/components/choosers/TMDynDataListItemChooser.js +8 -2
  47. package/lib/components/choosers/TMInvoiceRetrieveFormats.js +1 -1
  48. package/lib/components/choosers/TMMetadataChooser.d.ts +2 -0
  49. package/lib/components/choosers/TMMetadataChooser.js +19 -4
  50. package/lib/components/choosers/TMOrderRetrieveFormats.js +1 -1
  51. package/lib/components/choosers/TMUserChooser.d.ts +2 -5
  52. package/lib/components/choosers/TMUserChooser.js +33 -47
  53. package/lib/components/editors/TMCheckBox.js +2 -0
  54. package/lib/components/editors/TMDateBox.js +18 -9
  55. package/lib/components/editors/TMEditorStyled.js +7 -0
  56. package/lib/components/editors/TMLocalizedTextBox.d.ts +3 -1
  57. package/lib/components/editors/TMLocalizedTextBox.js +16 -14
  58. package/lib/components/editors/TMMetadataEditor.d.ts +1 -0
  59. package/lib/components/editors/TMMetadataEditor.js +4 -4
  60. package/lib/components/editors/TMMetadataTextBox.d.ts +9 -0
  61. package/lib/components/editors/TMMetadataTextBox.js +92 -0
  62. package/lib/components/editors/TMMetadataValues.d.ts +2 -0
  63. package/lib/components/editors/TMMetadataValues.js +26 -8
  64. package/lib/components/editors/TMRadioButton.js +2 -0
  65. package/lib/components/editors/TMTextArea.js +18 -30
  66. package/lib/components/editors/TMTextBox.d.ts +1 -1
  67. package/lib/components/editors/TMTextBox.js +29 -4
  68. package/lib/components/editors/TMTextExpression.js +6 -91
  69. package/lib/components/features/archive/TMArchive.js +2 -2
  70. package/lib/components/features/assistant/TMToppyDraggableHelpCenter.d.ts +15 -0
  71. package/lib/components/features/assistant/TMToppyDraggableHelpCenter.js +462 -0
  72. package/lib/components/features/assistant/TMToppySpeechBubble.d.ts +11 -0
  73. package/lib/components/features/assistant/TMToppySpeechBubble.js +126 -0
  74. package/lib/components/features/documents/TMDcmtBlog.js +1 -1
  75. package/lib/components/features/documents/TMDcmtForm.d.ts +14 -2
  76. package/lib/components/features/documents/TMDcmtForm.js +576 -292
  77. package/lib/components/features/documents/TMDcmtPreview.js +42 -155
  78. package/lib/components/features/documents/TMDcmtTasks.js +9 -9
  79. package/lib/components/features/documents/TMMasterDetailDcmts.js +38 -53
  80. package/lib/components/features/documents/TMRelationViewer.d.ts +1 -1
  81. package/lib/components/features/documents/TMRelationViewer.js +2 -2
  82. package/lib/components/features/search/TMDcmtCheckoutInfoForm.d.ts +8 -0
  83. package/lib/components/features/search/{TMSearchResultCheckoutInfoForm.js → TMDcmtCheckoutInfoForm.js} +2 -2
  84. package/lib/components/features/search/TMSavedQuerySelector.js +72 -67
  85. package/lib/components/features/search/TMSearch.d.ts +3 -0
  86. package/lib/components/features/search/TMSearch.js +50 -11
  87. package/lib/components/features/search/TMSearchQueryEditor.d.ts +1 -0
  88. package/lib/components/features/search/TMSearchQueryEditor.js +10 -10
  89. package/lib/components/features/search/TMSearchQueryPanel.d.ts +1 -0
  90. package/lib/components/features/search/TMSearchQueryPanel.js +40 -25
  91. package/lib/components/features/search/TMSearchResult.d.ts +3 -0
  92. package/lib/components/features/search/TMSearchResult.js +370 -252
  93. package/lib/components/features/search/TMSearchResultsMenuItems.d.ts +3 -3
  94. package/lib/components/features/search/TMSearchResultsMenuItems.js +227 -171
  95. package/lib/components/features/search/TMSignSettingsForm.js +1 -1
  96. package/lib/components/features/search/TMSignatureInfoContent.d.ts +6 -0
  97. package/lib/components/features/search/TMSignatureInfoContent.js +140 -0
  98. package/lib/components/features/search/TMViewHistoryDcmt.js +47 -52
  99. package/lib/components/features/tasks/TMTaskForm.js +75 -25
  100. package/lib/components/features/tasks/TMTasksAgenda.d.ts +3 -1
  101. package/lib/components/features/tasks/TMTasksAgenda.js +48 -9
  102. package/lib/components/features/tasks/TMTasksCalendar.d.ts +2 -0
  103. package/lib/components/features/tasks/TMTasksCalendar.js +19 -7
  104. package/lib/components/features/tasks/TMTasksUtils.d.ts +2 -2
  105. package/lib/components/features/tasks/TMTasksUtils.js +57 -37
  106. package/lib/components/features/tasks/TMTasksView.js +28 -19
  107. package/lib/components/features/workflow/TMWorkflowPopup.d.ts +33 -2
  108. package/lib/components/features/workflow/TMWorkflowPopup.js +140 -34
  109. package/lib/components/features/workflow/diagram/DiagramItemComponent.d.ts +2 -0
  110. package/lib/components/features/workflow/diagram/DiagramItemComponent.js +14 -7
  111. package/lib/components/features/workflow/diagram/DiagramItemForm.js +1 -1
  112. package/lib/components/features/workflow/diagram/RecipientList.js +3 -2
  113. package/lib/components/features/workflow/diagram/WFDiagram.d.ts +4 -0
  114. package/lib/components/features/workflow/diagram/WFDiagram.js +164 -13
  115. package/lib/components/forms/Login/LoginValidatorService.d.ts +2 -0
  116. package/lib/components/forms/Login/LoginValidatorService.js +7 -2
  117. package/lib/components/forms/Login/TMLoginForm.js +35 -7
  118. package/lib/components/forms/TMChooserForm.js +1 -1
  119. package/lib/components/grids/TMBlogsPost.js +56 -31
  120. package/lib/components/grids/TMRecentsManager.js +20 -10
  121. package/lib/components/grids/TMValidationItemsList.js +6 -0
  122. package/lib/components/index.d.ts +6 -3
  123. package/lib/components/index.js +6 -3
  124. package/lib/components/layout/panelManager/TMPanelManagerContext.js +13 -5
  125. package/lib/components/query/TMQueryEditor.d.ts +6 -1
  126. package/lib/components/query/TMQueryEditor.js +105 -101
  127. package/lib/components/settings/SettingsAppearance.d.ts +2 -1
  128. package/lib/components/settings/SettingsAppearance.js +99 -30
  129. package/lib/components/sidebar/TMHeader.js +11 -7
  130. package/lib/components/sidebar/TMSidebar.d.ts +0 -1
  131. package/lib/components/sidebar/TMSidebar.js +16 -44
  132. package/lib/components/sidebar/TMSidebarItem.js +36 -17
  133. package/lib/components/viewers/TMDataListItemViewer.d.ts +2 -1
  134. package/lib/components/viewers/TMDataListItemViewer.js +35 -71
  135. package/lib/components/viewers/TMDataUserIdItemViewer.d.ts +8 -0
  136. package/lib/components/viewers/TMDataUserIdItemViewer.js +39 -0
  137. package/lib/css/tm-sdkui.css +1 -1
  138. package/lib/helper/SDKUI_Globals.d.ts +22 -0
  139. package/lib/helper/SDKUI_Globals.js +10 -1
  140. package/lib/helper/SDKUI_Localizator.d.ts +21 -3
  141. package/lib/helper/SDKUI_Localizator.js +196 -10
  142. package/lib/helper/TMCommandsContextMenu.d.ts +4 -2
  143. package/lib/helper/TMCommandsContextMenu.js +15 -4
  144. package/lib/helper/TMIcons.d.ts +4 -0
  145. package/lib/helper/TMIcons.js +13 -3
  146. package/lib/helper/TMPdfViewer.d.ts +8 -0
  147. package/lib/helper/TMPdfViewer.js +373 -0
  148. package/lib/helper/TMToppyMessage.js +4 -0
  149. package/lib/helper/checkinCheckoutManager.d.ts +31 -1
  150. package/lib/helper/checkinCheckoutManager.js +112 -30
  151. package/lib/helper/devextremeCustomMessages.d.ts +30 -0
  152. package/lib/helper/devextremeCustomMessages.js +30 -0
  153. package/lib/helper/helpers.d.ts +30 -2
  154. package/lib/helper/helpers.js +132 -4
  155. package/lib/helper/index.d.ts +2 -0
  156. package/lib/helper/index.js +2 -0
  157. package/lib/helper/queryHelper.d.ts +2 -2
  158. package/lib/helper/queryHelper.js +80 -24
  159. package/lib/helper/workItemsHelper.d.ts +6 -0
  160. package/lib/helper/workItemsHelper.js +230 -0
  161. package/lib/hooks/useCheckInOutOperations.d.ts +28 -0
  162. package/lib/hooks/useCheckInOutOperations.js +223 -0
  163. package/lib/hooks/useDataListItem.d.ts +12 -0
  164. package/lib/hooks/useDataListItem.js +132 -0
  165. package/lib/hooks/useDataUserIdItem.d.ts +10 -0
  166. package/lib/hooks/useDataUserIdItem.js +96 -0
  167. package/lib/hooks/useFloatingBarPinnedItems.d.ts +11 -0
  168. package/lib/hooks/useFloatingBarPinnedItems.js +54 -0
  169. package/lib/hooks/useMetadataExpression.d.ts +19 -0
  170. package/lib/hooks/useMetadataExpression.js +99 -0
  171. package/lib/hooks/useSettingsFeedback.d.ts +11 -0
  172. package/lib/hooks/useSettingsFeedback.js +38 -0
  173. package/lib/hooks/useWorkflowApprove.d.ts +4 -0
  174. package/lib/hooks/useWorkflowApprove.js +14 -1
  175. package/lib/index.d.ts +1 -0
  176. package/lib/index.js +3 -2
  177. package/lib/services/platform_services.d.ts +3 -3
  178. package/lib/ts/types.d.ts +61 -1
  179. package/lib/utils/theme.d.ts +1 -1
  180. package/lib/utils/theme.js +1 -1
  181. package/package.json +6 -5
  182. package/lib/components/NewComponents/Notification/Notification.d.ts +0 -4
  183. package/lib/components/NewComponents/Notification/Notification.js +0 -60
  184. package/lib/components/NewComponents/Notification/NotificationContainer.d.ts +0 -8
  185. package/lib/components/NewComponents/Notification/NotificationContainer.js +0 -33
  186. package/lib/components/NewComponents/Notification/index.d.ts +0 -2
  187. package/lib/components/NewComponents/Notification/index.js +0 -2
  188. package/lib/components/NewComponents/Notification/styles.d.ts +0 -21
  189. package/lib/components/NewComponents/Notification/styles.js +0 -180
  190. package/lib/components/NewComponents/Notification/types.d.ts +0 -18
  191. package/lib/components/NewComponents/Notification/types.js +0 -1
  192. package/lib/components/base/TMContextMenu.d.ts +0 -25
  193. package/lib/components/base/TMContextMenu.js +0 -109
  194. package/lib/components/base/TMContextMenuOLD.d.ts +0 -26
  195. package/lib/components/base/TMContextMenuOLD.js +0 -56
  196. package/lib/components/base/TMFloatingToolbar.d.ts +0 -9
  197. package/lib/components/base/TMFloatingToolbar.js +0 -101
  198. package/lib/components/features/assistant/ToppyDraggableHelpCenter.d.ts +0 -30
  199. package/lib/components/features/assistant/ToppyDraggableHelpCenter.js +0 -482
  200. package/lib/components/features/assistant/ToppySpeechBubble.d.ts +0 -9
  201. package/lib/components/features/assistant/ToppySpeechBubble.js +0 -117
  202. package/lib/components/features/search/TMSearchResultCheckoutInfoForm.d.ts +0 -8
@@ -0,0 +1,462 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useRef, useState } from 'react';
3
+ import ReactDOM from 'react-dom';
4
+ import styled from 'styled-components';
5
+ import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
6
+ import TMToppySpeechBubble from './TMToppySpeechBubble';
7
+ import ToppyHelpCenterImage from '../../../assets/Toppy-help-center.png';
8
+ import { SDKUI_Localizator } from '../../../helper';
9
+ import { IconWindowMaximize } from '../../../helper/TMIcons';
10
+ // Keyframes per l'animazione pulse sull'immagine quando Toppy è collassato
11
+ const pulseAnimation = `
12
+ @keyframes toppyImagePulse {
13
+ 0% {
14
+ transform: translateY(-2px) scale(1);
15
+ filter: drop-shadow(0 0 0 rgba(59, 130, 246, 0));
16
+ }
17
+ 25% {
18
+ transform: translateY(-2px) scale(1.08);
19
+ filter: drop-shadow(0 0 8px rgba(59, 130, 246, 0.6));
20
+ }
21
+ 50% {
22
+ transform: translateY(-2px) scale(1);
23
+ filter: drop-shadow(0 0 12px rgba(118, 75, 162, 0.5));
24
+ }
25
+ 75% {
26
+ transform: translateY(-2px) scale(1.05);
27
+ filter: drop-shadow(0 0 6px rgba(240, 147, 251, 0.4));
28
+ }
29
+ 100% {
30
+ transform: translateY(-2px) scale(1);
31
+ filter: drop-shadow(0 0 0 rgba(59, 130, 246, 0));
32
+ }
33
+ }
34
+ `;
35
+ const TMToppyButton = styled.div.attrs((props) => ({
36
+ style: {
37
+ // Applica left/top come stili inline per evitare la generazione di troppe classi CSS
38
+ ...(props.$x !== undefined && props.$y !== undefined
39
+ ? {
40
+ left: `${props.$x}px`,
41
+ top: `${props.$y}px`,
42
+ bottom: 'auto',
43
+ right: 'auto',
44
+ }
45
+ : {}),
46
+ // Cursore applicato come stile inline
47
+ cursor: props.$isDragging ? 'grabbing' : 'grab',
48
+ },
49
+ })) `
50
+ ${pulseAnimation}
51
+ display: ${(props) => (props.$isVisible ? 'flex' : 'none')};
52
+ align-items: center;
53
+ justify-content: center;
54
+ position: ${(props) => props.$usePortal ? 'fixed' : 'absolute'};
55
+ /* Posizionamento di default quando non è draggato (x e y non sono definiti) */
56
+ ${(props) => props.$x === undefined || props.$y === undefined ?
57
+ `bottom: 0px;
58
+ ${props.$align === 'left' ? 'left: 10px;' : 'right: 0px;'};` : ''}
59
+ width: ${(props) => props.$isCollapsed ? '56px' : '110px'};
60
+ height: ${(props) => props.$isCollapsed ? '56px' : '110px'};
61
+ max-width: 100%;
62
+ max-height: 100%;
63
+ z-index: 2147483647;
64
+ background-color: ${(props) => props.$isCollapsed ? '#ffffff' : 'transparent'};
65
+ border: ${(props) => props.$isCollapsed ? '3px solid #3b82f6' : 'none'};
66
+ border-radius: ${(props) => props.$isCollapsed ? '50%' : '0'};
67
+ padding: 0;
68
+ outline: none;
69
+ user-select: none;
70
+ -webkit-touch-callout: none;
71
+ -webkit-user-select: none;
72
+ transition: background-color 0.3s ease, border 0.3s ease, border-radius 0.3s ease, box-shadow 0.3s ease, width 0.3s ease, height 0.3s ease;
73
+
74
+ img {
75
+ width: ${(props) => props.$isCollapsed ? '40px' : '110px'};
76
+ height: ${(props) => props.$isCollapsed ? '40px' : '110px'};
77
+ pointer-events: ${(props) => (props.$isMobile ? 'auto' : 'none')};
78
+ transform: ${(props) => props.$isCollapsed ? 'rotate(0deg)' : props.$align === 'left' ? 'rotate(20deg)' : 'rotate(-20deg)'};
79
+ transition: transform 0.3s ease, width 0.3s ease, height 0.3s ease, filter 0.3s ease;
80
+ object-fit: contain;
81
+ ${(props) => props.$isCollapsed && `animation: toppyImagePulse 2.5s ease-in-out infinite;`}
82
+ }
83
+ `;
84
+ /**
85
+ * Pulsante di espansione quando Toppy è minimizzato
86
+ */
87
+ const ExpandButton = styled.button `
88
+ position: absolute;
89
+ top: -8px;
90
+ right: -8px;
91
+ width: 24px;
92
+ height: 24px;
93
+ border-radius: 50%;
94
+ border: 2px solid rgba(255, 255, 255, 0.9);
95
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
96
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4), 0 0 20px rgba(118, 75, 162, 0.2);
97
+ cursor: pointer;
98
+ display: flex;
99
+ align-items: center;
100
+ justify-content: center;
101
+ transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
102
+ z-index: 10001;
103
+ color: white;
104
+ font-size: 14px;
105
+
106
+ &:hover {
107
+ background: linear-gradient(135deg, #764ba2 0%, #f093fb 100%);
108
+ box-shadow: 0 6px 20px rgba(118, 75, 162, 0.6), 0 0 30px rgba(240, 147, 251, 0.4);
109
+ border-color: rgba(255, 255, 255, 1);
110
+ transform: scale(1.1);
111
+ }
112
+
113
+ &:active {
114
+ transform: scale(0.95);
115
+ box-shadow: 0 2px 8px rgba(102, 126, 234, 0.4);
116
+ }
117
+
118
+ &:focus {
119
+ outline: none;
120
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4), 0 0 0 3px rgba(102, 126, 234, 0.2);
121
+ }
122
+ `;
123
+ /**
124
+ * Overlay trasparente per bloccare le interazioni durante il drag
125
+ * Previene problemi di performance con iframe e altri elementi interattivi
126
+ */
127
+ const DragOverlay = styled.div `
128
+ position: fixed;
129
+ top: 0;
130
+ left: 0;
131
+ right: 0;
132
+ bottom: 0;
133
+ z-index: 2147483646;
134
+ cursor: grabbing;
135
+ `;
136
+ const TMToppyDraggableHelpCenter = (props) => {
137
+ const { content, usePortal, align = 'right', isVisible = true, onToppyImageClick } = props;
138
+ // Get the current device type (e.g., mobile, tablet, desktop) using a custom hook.
139
+ const deviceType = useDeviceType();
140
+ // This avoids unnecessary re-renders by only recalculating when deviceType changes.
141
+ const isMobile = useMemo(() => { return deviceType === DeviceType.MOBILE; }, [deviceType]);
142
+ // Ref per il contenitore principale
143
+ const toppyButtonRef = useRef(null);
144
+ // Ref per la speech bubble per calcolare le sue dimensioni
145
+ const bubbleRef = useRef(null);
146
+ // Dimensioni della bubble (aggiornate dinamicamente)
147
+ const bubbleDimensions = useRef({ width: 0, height: 0 });
148
+ // Posizione corrente del componente (null = posizione di default)
149
+ const [position, setPosition] = useState(null);
150
+ // Stato per tracciare se il componente è in fase di trascinamento
151
+ const [isDragging, setIsDragging] = useState(false);
152
+ // Stato per controllare se il componente è collassato o espanso
153
+ const [isCollapsed, setIsCollapsed] = useState(false);
154
+ // Refs per gestire il drag
155
+ const dragStartPos = useRef(null);
156
+ const dragOffset = useRef(null);
157
+ const hasMoved = useRef(false);
158
+ // Ref per tracciare il dragging dell'ExpandButton
159
+ const isExpandButtonDraggingRef = useRef(false);
160
+ const expandButtonMouseDownPosRef = useRef(null);
161
+ // Soglia minima di movimento in pixel per attivare il drag
162
+ const DRAG_THRESHOLD = 5;
163
+ // Calcola le dimensioni della bubble quando il contenuto cambia
164
+ useEffect(() => {
165
+ if (bubbleRef.current) {
166
+ const rect = bubbleRef.current.getBoundingClientRect();
167
+ bubbleDimensions.current = { width: rect.width, height: rect.height };
168
+ }
169
+ }, [content, isCollapsed]);
170
+ // Handler per l'inizio del drag (mouse)
171
+ const handleMouseDown = (e) => {
172
+ if (isMobile)
173
+ return;
174
+ e.preventDefault();
175
+ const rect = toppyButtonRef.current?.getBoundingClientRect();
176
+ if (!rect)
177
+ return;
178
+ // Salva la posizione iniziale del mouse e l'offset rispetto al componente
179
+ dragStartPos.current = { x: e.clientX, y: e.clientY };
180
+ dragOffset.current = {
181
+ x: e.clientX - rect.left,
182
+ y: e.clientY - rect.top,
183
+ };
184
+ hasMoved.current = false;
185
+ // Aggiungi listener globali per il movimento e il rilascio
186
+ document.addEventListener('mousemove', handleDragMove);
187
+ document.addEventListener('mouseup', handleDragEnd);
188
+ };
189
+ // Handler per l'inizio del drag (touch)
190
+ const handleTouchStart = (e) => {
191
+ if (!isMobile)
192
+ return;
193
+ const touch = e.touches[0];
194
+ if (!touch)
195
+ return;
196
+ const rect = toppyButtonRef.current?.getBoundingClientRect();
197
+ if (!rect)
198
+ return;
199
+ // Salva la posizione iniziale del touch e l'offset rispetto al componente
200
+ dragStartPos.current = { x: touch.clientX, y: touch.clientY };
201
+ dragOffset.current = {
202
+ x: touch.clientX - rect.left,
203
+ y: touch.clientY - rect.top,
204
+ };
205
+ hasMoved.current = false;
206
+ // Aggiungi listener globali per il movimento e il rilascio
207
+ document.addEventListener('touchmove', handleDragMove, { passive: false });
208
+ document.addEventListener('touchend', handleDragEnd);
209
+ };
210
+ // Handler unificato per il movimento durante il drag (mouse e touch)
211
+ const handleDragMove = (e) => {
212
+ if (!dragStartPos.current || !dragOffset.current || !toppyButtonRef.current)
213
+ return;
214
+ // Estrae le coordinate dal tipo di evento appropriato
215
+ const clientX = 'touches' in e ? e.touches[0]?.clientX : e.clientX;
216
+ const clientY = 'touches' in e ? e.touches[0]?.clientY : e.clientY;
217
+ if (clientX === undefined || clientY === undefined)
218
+ return;
219
+ // Calcola la distanza dal punto iniziale
220
+ const deltaX = clientX - dragStartPos.current.x;
221
+ const deltaY = clientY - dragStartPos.current.y;
222
+ const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
223
+ // Attiva il drag solo se il movimento supera la soglia
224
+ if (!hasMoved.current && distance < DRAG_THRESHOLD)
225
+ return;
226
+ if (!hasMoved.current) {
227
+ hasMoved.current = true;
228
+ setIsDragging(true);
229
+ }
230
+ // Previeni lo scroll durante il drag (solo per touch)
231
+ if ('touches' in e) {
232
+ e.preventDefault();
233
+ }
234
+ // Calcola la nuova posizione
235
+ let newX = clientX - dragOffset.current.x;
236
+ let newY = clientY - dragOffset.current.y;
237
+ // Se non usa portal, converti le coordinate da viewport a relative al parent
238
+ if (!usePortal) {
239
+ const parentElement = toppyButtonRef.current.offsetParent;
240
+ if (parentElement) {
241
+ const parentRect = parentElement.getBoundingClientRect();
242
+ newX -= parentRect.left;
243
+ newY -= parentRect.top;
244
+ }
245
+ }
246
+ // Ottieni le dimensioni del componente
247
+ const componentRect = toppyButtonRef.current.getBoundingClientRect();
248
+ const componentWidth = componentRect.width;
249
+ const componentHeight = componentRect.height;
250
+ // Limiti del parent considerando anche la bubble
251
+ let maxX = 0;
252
+ let maxY = 0;
253
+ let minX = 0;
254
+ let minY = 0;
255
+ // Considera le dimensioni della bubble per i limiti solo se non è collassato
256
+ const bubbleWidth = isCollapsed ? 0 : (bubbleDimensions.current.width || 0);
257
+ const bubbleHeight = isCollapsed ? 0 : (bubbleDimensions.current.height || 0);
258
+ // Offset dell'ExpandButton quando Toppy è collassato (top: -8px, right: -8px)
259
+ const expandButtonOffset = isCollapsed ? 8 : 0;
260
+ if (usePortal) {
261
+ // Se usa portal, i limiti sono quelli della viewport
262
+ // Limite superiore: deve lasciare spazio per la bubble sopra o per l'ExpandButton se collassato
263
+ minY = isCollapsed ? expandButtonOffset : bubbleHeight;
264
+ // Limite inferiore: il componente non può uscire dalla viewport
265
+ maxY = window.innerHeight - componentHeight;
266
+ // Limiti orizzontali dipendono dall'allineamento della bubble
267
+ if (align === 'right') {
268
+ // Bubble a sinistra del componente: serve spazio a sinistra
269
+ minX = Math.max(0, bubbleWidth - componentWidth);
270
+ // Quando collassato, l'ExpandButton sporge a destra di 8px
271
+ maxX = window.innerWidth - componentWidth - expandButtonOffset;
272
+ }
273
+ else {
274
+ // Bubble a destra del componente: serve spazio a destra
275
+ minX = 0;
276
+ maxX = window.innerWidth - Math.max(componentWidth, bubbleWidth) - expandButtonOffset;
277
+ }
278
+ }
279
+ else {
280
+ // Se non usa portal, le coordinate devono essere relative al parent
281
+ const parentElement = toppyButtonRef.current.offsetParent;
282
+ if (parentElement) {
283
+ // Usa le dimensioni del parent come riferimento
284
+ const parentWidth = parentElement.clientWidth;
285
+ const parentHeight = parentElement.clientHeight;
286
+ // Limite superiore: deve lasciare spazio per la bubble sopra o per l'ExpandButton se collassato
287
+ minY = isCollapsed ? expandButtonOffset : bubbleHeight;
288
+ // Limite inferiore: il componente non può uscire dal parent
289
+ maxY = parentHeight - componentHeight;
290
+ // Limiti orizzontali dipendono dall'allineamento della bubble
291
+ if (align === 'right') {
292
+ // Bubble a sinistra del componente: serve spazio a sinistra
293
+ minX = Math.max(0, bubbleWidth - componentWidth);
294
+ // Quando collassato, l'ExpandButton sporge a destra di 8px
295
+ maxX = parentWidth - componentWidth - expandButtonOffset;
296
+ }
297
+ else {
298
+ // Bubble a destra del componente: serve spazio a destra
299
+ minX = 0;
300
+ maxX = parentWidth - Math.max(componentWidth, bubbleWidth) - expandButtonOffset;
301
+ }
302
+ }
303
+ }
304
+ // Applica i limiti
305
+ newX = Math.max(minX, Math.min(newX, maxX));
306
+ newY = Math.max(minY, Math.min(newY, maxY));
307
+ setPosition({ x: newX, y: newY });
308
+ };
309
+ // Handler unificato per il rilascio del drag (mouse e touch)
310
+ const handleDragEnd = () => {
311
+ dragStartPos.current = null;
312
+ dragOffset.current = null;
313
+ setIsDragging(false);
314
+ // Rimuovi tutti i listener globali
315
+ document.removeEventListener('mousemove', handleDragMove);
316
+ document.removeEventListener('mouseup', handleDragEnd);
317
+ document.removeEventListener('touchmove', handleDragMove);
318
+ document.removeEventListener('touchend', handleDragEnd);
319
+ };
320
+ // Handler per il doppio click (collassa/espande Toppy su desktop)
321
+ const toggleCollapse = () => {
322
+ setIsCollapsed(prev => {
323
+ const newIsCollapsed = !prev;
324
+ // Se stiamo espandendo (da collassato a espanso), dobbiamo verificare i limiti
325
+ if (!newIsCollapsed && position && toppyButtonRef.current && content) {
326
+ // Usa setTimeout per permettere al DOM di aggiornarsi con le nuove dimensioni
327
+ setTimeout(() => {
328
+ if (!toppyButtonRef.current)
329
+ return;
330
+ // Dimensioni espanse del componente (110px come da styled-component)
331
+ const expandedSize = 110;
332
+ // Ottieni le dimensioni della bubble (usa valori di default se non disponibili)
333
+ const bubbleWidth = bubbleDimensions.current.width || 250;
334
+ const bubbleHeight = bubbleDimensions.current.height || 100;
335
+ let newX = position.x;
336
+ let newY = position.y;
337
+ let needsUpdate = false;
338
+ if (usePortal) {
339
+ // Limiti della viewport considerando la bubble
340
+ const minY = bubbleHeight;
341
+ const maxY = window.innerHeight - expandedSize;
342
+ let minX;
343
+ let maxX;
344
+ if (align === 'right') {
345
+ minX = Math.max(0, bubbleWidth - expandedSize);
346
+ maxX = window.innerWidth - expandedSize;
347
+ }
348
+ else {
349
+ minX = 0;
350
+ maxX = window.innerWidth - Math.max(expandedSize, bubbleWidth);
351
+ }
352
+ // Verifica e correggi la posizione
353
+ if (newX < minX) {
354
+ newX = minX;
355
+ needsUpdate = true;
356
+ }
357
+ if (newX > maxX) {
358
+ newX = maxX;
359
+ needsUpdate = true;
360
+ }
361
+ if (newY < minY) {
362
+ newY = minY;
363
+ needsUpdate = true;
364
+ }
365
+ if (newY > maxY) {
366
+ newY = maxY;
367
+ needsUpdate = true;
368
+ }
369
+ }
370
+ else {
371
+ // Limiti del parent
372
+ const offsetParent = toppyButtonRef.current.offsetParent;
373
+ if (offsetParent) {
374
+ const minY = bubbleHeight;
375
+ const maxY = offsetParent.clientHeight - expandedSize;
376
+ let minX;
377
+ let maxX;
378
+ if (align === 'right') {
379
+ minX = Math.max(0, bubbleWidth - expandedSize);
380
+ maxX = offsetParent.clientWidth - expandedSize;
381
+ }
382
+ else {
383
+ minX = 0;
384
+ maxX = offsetParent.clientWidth - Math.max(expandedSize, bubbleWidth);
385
+ }
386
+ // Verifica e correggi la posizione
387
+ if (newX < minX) {
388
+ newX = minX;
389
+ needsUpdate = true;
390
+ }
391
+ if (newX > maxX) {
392
+ newX = maxX;
393
+ needsUpdate = true;
394
+ }
395
+ if (newY < minY) {
396
+ newY = minY;
397
+ needsUpdate = true;
398
+ }
399
+ if (newY > maxY) {
400
+ newY = maxY;
401
+ needsUpdate = true;
402
+ }
403
+ }
404
+ }
405
+ // Aggiorna la posizione solo se necessario
406
+ if (needsUpdate) {
407
+ setPosition({ x: newX, y: newY });
408
+ }
409
+ }, 50); // Piccolo delay per permettere l'aggiornamento delle dimensioni
410
+ }
411
+ onToppyImageClick?.();
412
+ return newIsCollapsed;
413
+ });
414
+ };
415
+ // Cleanup degli event listener al dismount
416
+ useEffect(() => {
417
+ return () => {
418
+ document.removeEventListener('mousemove', handleDragMove);
419
+ document.removeEventListener('mouseup', handleDragEnd);
420
+ document.removeEventListener('touchmove', handleDragMove);
421
+ document.removeEventListener('touchend', handleDragEnd);
422
+ };
423
+ }, []);
424
+ // Reset della posizione quando cambia la dimensione della finestra/parent
425
+ // Questo evita che Toppy rimanga nascosto oltre i limiti dopo un resize
426
+ useEffect(() => {
427
+ const handleResize = () => {
428
+ // Resetta alla posizione iniziale (bottom-right o bottom-left in base ad align)
429
+ setPosition(null);
430
+ };
431
+ window.addEventListener('resize', handleResize);
432
+ return () => {
433
+ window.removeEventListener('resize', handleResize);
434
+ };
435
+ }, []);
436
+ const toppyContent = (_jsxs(_Fragment, { children: [isDragging && _jsx(DragOverlay, {}), _jsxs(TMToppyButton, { ref: toppyButtonRef, "$align": align, "$isDragging": isDragging, "$isVisible": isVisible, "$isCollapsed": isCollapsed, "$isMobile": isMobile, "$usePortal": usePortal, onContextMenu: (e) => e.preventDefault(), onMouseDown: !isMobile ? handleMouseDown : undefined, onTouchStart: isMobile ? handleTouchStart : undefined, onDoubleClick: !isMobile ? toggleCollapse : undefined, "$x": position?.x, "$y": position?.y, children: [(content && !isCollapsed) && _jsx(TMToppySpeechBubble, { ref: bubbleRef, align: align, onClose: toggleCollapse, children: content }), (content && isCollapsed) && (_jsx(ExpandButton, { onMouseDown: (e) => {
437
+ isExpandButtonDraggingRef.current = false;
438
+ expandButtonMouseDownPosRef.current = { x: e.clientX, y: e.clientY };
439
+ }, onMouseMove: (e) => {
440
+ if (!expandButtonMouseDownPosRef.current)
441
+ return;
442
+ const deltaX = Math.abs(e.clientX - expandButtonMouseDownPosRef.current.x);
443
+ const deltaY = Math.abs(e.clientY - expandButtonMouseDownPosRef.current.y);
444
+ // Considera drag solo se il movimento supera 3px
445
+ if (deltaX > 3 || deltaY > 3) {
446
+ isExpandButtonDraggingRef.current = true;
447
+ }
448
+ }, onMouseUp: () => {
449
+ expandButtonMouseDownPosRef.current = null;
450
+ }, onClick: (e) => {
451
+ if (isExpandButtonDraggingRef.current) {
452
+ e.stopPropagation();
453
+ e.preventDefault();
454
+ return;
455
+ }
456
+ e.stopPropagation();
457
+ toggleCollapse();
458
+ }, onContextMenu: (e) => e.preventDefault(), "aria-label": SDKUI_Localizator.Maximize, title: SDKUI_Localizator.Maximize, type: "button", children: _jsx(IconWindowMaximize, {}) })), _jsx("img", { src: ToppyHelpCenterImage, alt: "Toppy Help", draggable: false })] })] }));
459
+ // Renderizza nel document.body usando un Portal se usePortal è true, altrimenti renderizza normalmente
460
+ return usePortal ? ReactDOM.createPortal(toppyContent, document.body) : toppyContent;
461
+ };
462
+ export default TMToppyDraggableHelpCenter;
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ interface TMToppySpeechBubbleProps {
3
+ /** Contenuto da visualizzare nella speech bubble */
4
+ children: React.ReactNode;
5
+ /** Allineamento della speech bubble (destra o sinistra) */
6
+ align?: 'right' | 'left';
7
+ /** Callback per chiudere/minimizzare la bubble */
8
+ onClose?: () => void;
9
+ }
10
+ declare const TMToppySpeechBubble: React.ForwardRefExoticComponent<TMToppySpeechBubbleProps & React.RefAttributes<HTMLDivElement>>;
11
+ export default TMToppySpeechBubble;
@@ -0,0 +1,126 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, useRef } from 'react';
3
+ import styled from 'styled-components';
4
+ import { SDKUI_Localizator } from '../../../helper';
5
+ import { IconWindowMinimize } from '../../../helper/TMIcons';
6
+ // Offset del CloseButton che sporge oltre i bordi della bubble
7
+ const CLOSE_BUTTON_OFFSET = 8;
8
+ /**
9
+ * Wrapper che include lo spazio per il CloseButton sporgente
10
+ * Il ref viene passato qui per includere le dimensioni complete nel calcolo
11
+ */
12
+ const BubbleWrapper = styled.div `
13
+ position: relative;
14
+ padding-top: ${({ $hasCloseButton }) => $hasCloseButton ? `${CLOSE_BUTTON_OFFSET}px` : '0'};
15
+ padding-right: ${({ $hasCloseButton }) => $hasCloseButton ? `${CLOSE_BUTTON_OFFSET}px` : '0'};
16
+ `;
17
+ /**
18
+ * Pulsante di chiusura/minimizzazione in alto a destra della bubble
19
+ * Posizionato all'interno del padding del BubbleWrapper
20
+ */
21
+ const CloseButton = styled.button `
22
+ position: absolute;
23
+ top: 0;
24
+ right: 0;
25
+ width: 24px;
26
+ height: 24px;
27
+ border-radius: 50%;
28
+ border: 2px solid rgba(255, 255, 255, 0.9);
29
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
30
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4), 0 0 20px rgba(118, 75, 162, 0.2);
31
+ cursor: pointer;
32
+ display: flex;
33
+ align-items: center;
34
+ justify-content: center;
35
+ transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
36
+ z-index: 10001;
37
+ color: white;
38
+ font-size: 14px;
39
+
40
+ &:hover {
41
+ background: linear-gradient(135deg, #764ba2 0%, #f093fb 100%);
42
+ box-shadow: 0 6px 20px rgba(118, 75, 162, 0.6), 0 0 30px rgba(240, 147, 251, 0.4);
43
+ border-color: rgba(255, 255, 255, 1);
44
+ transform: scale(1.1);
45
+ }
46
+
47
+ &:active {
48
+ transform: scale(0.95);
49
+ box-shadow: 0 2px 8px rgba(102, 126, 234, 0.4);
50
+ }
51
+
52
+ &:focus {
53
+ outline: none;
54
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4), 0 0 0 3px rgba(102, 126, 234, 0.2);
55
+ }
56
+ `;
57
+ const BubbleContainer = styled.div `
58
+ position: absolute;
59
+ bottom: 100%;
60
+ ${({ $align }) => $align === 'right' ? 'right: 0px;' : 'left: 0px;'}
61
+ z-index: 10;
62
+ `;
63
+ const Bubble = styled.div `
64
+ position: relative;
65
+ background: linear-gradient(180deg, rgba(0, 113, 188, 0.45) 0%,rgba(27, 20, 100, 0.65) 100%);
66
+ color: #333;
67
+ padding: 10px;
68
+ box-sizing: border-box;
69
+ border-radius: 18px;
70
+ box-shadow: 0 10px 28px rgba(0, 0, 0, 0.18);
71
+ font-size: 14px;
72
+ line-height: 1.5;
73
+ width: max-content;
74
+
75
+ // Arrow styles
76
+ &::after {
77
+ transform: ${({ $align }) => ($align === 'left' ? 'skewX(15deg)' : 'skewX(-15deg)')};
78
+ content: "";
79
+ position: absolute;
80
+ top: 100%;
81
+ ${({ $align }) => ($align === 'left' ? 'left: 20px;' : 'right: 15px;')}
82
+ border-width: 22px 22px 0 0;
83
+ border-style: solid;
84
+ border-color: rgba(27, 20, 100, 0.65) transparent;
85
+ display: block;
86
+ width: 0;
87
+ height: 0;
88
+ z-index: 1;
89
+ }
90
+ `;
91
+ const Content = styled.div `position: relative; z-index: 1;`;
92
+ const TMToppySpeechBubble = forwardRef((props, ref) => {
93
+ const { children, align = 'right', onClose } = props;
94
+ // Ref per tracciare il dragging del CloseButton
95
+ const isCloseButtonDraggingRef = useRef(false);
96
+ const closeButtonMouseDownPosRef = useRef(null);
97
+ const handleMouseDown = (e) => {
98
+ isCloseButtonDraggingRef.current = false;
99
+ closeButtonMouseDownPosRef.current = { x: e.clientX, y: e.clientY };
100
+ };
101
+ const handleMouseMove = (e) => {
102
+ if (!closeButtonMouseDownPosRef.current)
103
+ return;
104
+ const deltaX = Math.abs(e.clientX - closeButtonMouseDownPosRef.current.x);
105
+ const deltaY = Math.abs(e.clientY - closeButtonMouseDownPosRef.current.y);
106
+ // Considera drag solo se il movimento supera 3px
107
+ if (deltaX > 3 || deltaY > 3) {
108
+ isCloseButtonDraggingRef.current = true;
109
+ }
110
+ };
111
+ const handleMouseUp = () => {
112
+ closeButtonMouseDownPosRef.current = null;
113
+ };
114
+ const handleClick = (e) => {
115
+ if (isCloseButtonDraggingRef.current) {
116
+ e.stopPropagation();
117
+ e.preventDefault();
118
+ return;
119
+ }
120
+ e.stopPropagation();
121
+ onClose?.();
122
+ };
123
+ return (_jsx(BubbleContainer, { "$align": align, children: _jsxs(BubbleWrapper, { ref: ref, "$hasCloseButton": !!onClose, children: [onClose && (_jsx(CloseButton, { onMouseDown: handleMouseDown, onMouseMove: handleMouseMove, onMouseUp: handleMouseUp, onClick: handleClick, "aria-label": SDKUI_Localizator.Minimize, title: SDKUI_Localizator.Minimize, type: "button", children: _jsx(IconWindowMinimize, {}) })), _jsx(Bubble, { "$align": align, children: _jsx(Content, { children: children }) })] }) }));
124
+ });
125
+ TMToppySpeechBubble.displayName = 'TMToppySpeechBubble';
126
+ export default TMToppySpeechBubble;
@@ -87,6 +87,6 @@ const TMDcmtBlog = ({ tid, did, isVisible, fetchBlogDataTrigger, allTasks = [],
87
87
  }, externalBlogPost: externalBlogPost, resetExternalBlogPost: resetExternalBlogPost, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, afterTaskSaved: refreshCallback }) }) }) }), (showCommentForm && tid && did) && _jsx(TMBlogCommentForm, { context: { engine: 'SearchEngine', object: { tid, did } }, onClose: () => setShowCommentForm(false), refreshCallback: refreshCallback, participants: [], showAttachmentsSection: false, allArchivedDocumentsFileItems: [], onFilterCreated: handleFilterCreated })] }));
88
88
  };
89
89
  export default TMDcmtBlog;
90
- const StyledContainer = styled.div ` user-select: none; overflow: hidden; background-color: #ffffff; width: calc(100%); height: calc(100%); display: flex; gap: 10px; `;
90
+ const StyledContainer = styled.div ` user-select: none; -webkit-touch-callout: none; -webkit-user-select: none; overflow: hidden; background-color: #ffffff; width: calc(100%); height: calc(100%); display: flex; gap: 10px; `;
91
91
  const StyledSectionContainer = styled.div ` width: 100%; height: 100%; display:flex; flex-direction: column; `;
92
92
  const StyledBoardContainer = styled.div `width: 100%; height: 100%;`;
@@ -1,6 +1,18 @@
1
1
  import React from 'react';
2
2
  import { HomeBlogPost, LayoutModes, ObjectRef, SearchResultDescriptor, TaskDescriptor, ValidationItem } from '@topconsultnpm/sdk-ts';
3
3
  import { DcmtInfo, FormModes, MetadataValueDescriptorEx, TaskContext } from '../../../ts';
4
+ /**
5
+ * Definisce il contesto da cui è stato invocato il TMDcmtForm.
6
+ * Permette di gestire logiche diverse in base alla provenienza.
7
+ */
8
+ export declare enum InvocationContext {
9
+ /** Invocazione standard */
10
+ Default = "default",
11
+ /** Invocato dalla pagina Todo/Task */
12
+ Todo = "todo",
13
+ /** Invocato dalla pagina WorkflowCtrl */
14
+ WorkflowCtrl = "workflowCtrl"
15
+ }
4
16
  interface ITMDcmtFormProps {
5
17
  allTasks?: Array<TaskDescriptor>;
6
18
  getAllTasks?: () => Promise<void>;
@@ -24,9 +36,9 @@ interface ITMDcmtFormProps {
24
36
  canPrev?: boolean;
25
37
  isClosable?: boolean;
26
38
  groupId?: string;
27
- invokedByTodo?: boolean;
39
+ invocationContext?: InvocationContext;
28
40
  taskFormDialogComponent?: React.ReactNode;
29
- taskMoreInfo?: TaskDescriptor;
41
+ moreInfoTasks?: Array<TaskDescriptor>;
30
42
  showBackButton?: boolean;
31
43
  onNext?: () => void;
32
44
  onPrev?: () => void;