@topconsultnpm/sdkui-react 6.20.0-dev1.10 → 6.20.0-dev1.101

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 (157) hide show
  1. package/lib/assets/Toppy-help-center.png +0 -0
  2. package/lib/components/NewComponents/ContextMenu/TMContextMenu.d.ts +4 -0
  3. package/lib/components/NewComponents/ContextMenu/TMContextMenu.js +441 -0
  4. package/lib/components/NewComponents/ContextMenu/hooks.d.ts +18 -0
  5. package/lib/components/NewComponents/ContextMenu/hooks.js +120 -0
  6. package/lib/components/NewComponents/ContextMenu/index.d.ts +5 -0
  7. package/lib/components/NewComponents/ContextMenu/index.js +3 -0
  8. package/lib/components/NewComponents/ContextMenu/styles.d.ts +35 -0
  9. package/lib/components/NewComponents/ContextMenu/styles.js +428 -0
  10. package/lib/components/NewComponents/ContextMenu/types.d.ts +39 -0
  11. package/lib/components/NewComponents/ContextMenu/types.js +1 -0
  12. package/lib/components/NewComponents/ContextMenu/useLongPress.d.ts +21 -0
  13. package/lib/components/NewComponents/ContextMenu/useLongPress.js +112 -0
  14. package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.d.ts +4 -0
  15. package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +821 -0
  16. package/lib/components/NewComponents/FloatingMenuBar/index.d.ts +2 -0
  17. package/lib/components/NewComponents/FloatingMenuBar/index.js +2 -0
  18. package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +54 -0
  19. package/lib/components/NewComponents/FloatingMenuBar/styles.js +419 -0
  20. package/lib/components/NewComponents/FloatingMenuBar/types.d.ts +36 -0
  21. package/lib/components/NewComponents/FloatingMenuBar/types.js +1 -0
  22. package/lib/components/base/TMAccordionNew.js +35 -14
  23. package/lib/components/base/TMCustomButton.js +61 -17
  24. package/lib/components/base/TMDataGrid.d.ts +7 -4
  25. package/lib/components/base/TMDataGrid.js +153 -11
  26. package/lib/components/base/TMDropDownMenu.js +19 -18
  27. package/lib/components/base/TMFileManager.d.ts +4 -3
  28. package/lib/components/base/TMFileManager.js +32 -24
  29. package/lib/components/base/TMFileManagerDataGridView.d.ts +3 -2
  30. package/lib/components/base/TMFileManagerDataGridView.js +1 -11
  31. package/lib/components/base/TMFileManagerThumbnailItems.d.ts +7 -1
  32. package/lib/components/base/TMFileManagerThumbnailItems.js +5 -2
  33. package/lib/components/base/TMFileManagerThumbnailsView.d.ts +17 -4
  34. package/lib/components/base/TMFileManagerThumbnailsView.js +18 -6
  35. package/lib/components/base/TMFileManagerUtils.d.ts +0 -12
  36. package/lib/components/base/TMListView.js +33 -15
  37. package/lib/components/base/TMPanel.d.ts +1 -1
  38. package/lib/components/base/TMPanel.js +1 -1
  39. package/lib/components/choosers/TMDistinctValues.js +1 -1
  40. package/lib/components/choosers/TMInvoiceRetrieveFormats.js +1 -1
  41. package/lib/components/choosers/TMMetadataChooser.js +8 -1
  42. package/lib/components/choosers/TMOrderRetrieveFormats.js +1 -1
  43. package/lib/components/choosers/TMUserChooser.d.ts +0 -5
  44. package/lib/components/choosers/TMUserChooser.js +25 -45
  45. package/lib/components/editors/TMDateBox.js +18 -9
  46. package/lib/components/editors/TMMetadataValues.js +23 -5
  47. package/lib/components/editors/TMTextArea.js +18 -30
  48. package/lib/components/editors/TMTextBox.js +6 -3
  49. package/lib/components/features/archive/TMArchive.js +2 -2
  50. package/lib/components/features/assistant/TMToppyDraggableHelpCenter.d.ts +15 -0
  51. package/lib/components/features/assistant/TMToppyDraggableHelpCenter.js +460 -0
  52. package/lib/components/features/assistant/TMToppySpeechBubble.d.ts +11 -0
  53. package/lib/components/features/assistant/TMToppySpeechBubble.js +126 -0
  54. package/lib/components/features/documents/TMDcmtForm.d.ts +14 -2
  55. package/lib/components/features/documents/TMDcmtForm.js +457 -206
  56. package/lib/components/features/documents/TMDcmtPreview.js +45 -108
  57. package/lib/components/features/documents/TMDcmtTasks.js +9 -9
  58. package/lib/components/features/documents/TMMasterDetailDcmts.js +38 -53
  59. package/lib/components/features/documents/TMRelationViewer.d.ts +1 -1
  60. package/lib/components/features/documents/TMRelationViewer.js +2 -2
  61. package/lib/components/features/search/TMDcmtCheckoutInfoForm.d.ts +8 -0
  62. package/lib/components/features/search/{TMSearchResultCheckoutInfoForm.js → TMDcmtCheckoutInfoForm.js} +2 -2
  63. package/lib/components/features/search/TMSavedQuerySelector.js +72 -67
  64. package/lib/components/features/search/TMSearch.d.ts +3 -0
  65. package/lib/components/features/search/TMSearch.js +50 -11
  66. package/lib/components/features/search/TMSearchQueryPanel.d.ts +1 -0
  67. package/lib/components/features/search/TMSearchQueryPanel.js +29 -21
  68. package/lib/components/features/search/TMSearchResult.d.ts +3 -0
  69. package/lib/components/features/search/TMSearchResult.js +208 -250
  70. package/lib/components/features/search/TMSearchResultsMenuItems.d.ts +3 -3
  71. package/lib/components/features/search/TMSearchResultsMenuItems.js +205 -169
  72. package/lib/components/features/search/TMSignSettingsForm.js +1 -1
  73. package/lib/components/features/search/TMSignatureInfoContent.d.ts +6 -0
  74. package/lib/components/features/search/TMSignatureInfoContent.js +140 -0
  75. package/lib/components/features/search/TMViewHistoryDcmt.js +2 -2
  76. package/lib/components/features/tasks/TMTaskForm.js +20 -1
  77. package/lib/components/features/tasks/TMTasksAgenda.d.ts +3 -1
  78. package/lib/components/features/tasks/TMTasksAgenda.js +48 -9
  79. package/lib/components/features/tasks/TMTasksCalendar.d.ts +2 -0
  80. package/lib/components/features/tasks/TMTasksCalendar.js +19 -7
  81. package/lib/components/features/tasks/TMTasksUtils.d.ts +2 -2
  82. package/lib/components/features/tasks/TMTasksUtils.js +43 -36
  83. package/lib/components/features/tasks/TMTasksView.js +28 -19
  84. package/lib/components/features/workflow/TMWorkflowPopup.d.ts +33 -2
  85. package/lib/components/features/workflow/TMWorkflowPopup.js +139 -34
  86. package/lib/components/features/workflow/diagram/DiagramItemComponent.d.ts +2 -0
  87. package/lib/components/features/workflow/diagram/DiagramItemComponent.js +12 -7
  88. package/lib/components/features/workflow/diagram/RecipientList.js +3 -2
  89. package/lib/components/features/workflow/diagram/WFDiagram.d.ts +4 -0
  90. package/lib/components/features/workflow/diagram/WFDiagram.js +164 -13
  91. package/lib/components/forms/Login/LoginValidatorService.d.ts +2 -0
  92. package/lib/components/forms/Login/LoginValidatorService.js +7 -2
  93. package/lib/components/forms/Login/TMLoginForm.js +34 -6
  94. package/lib/components/forms/TMChooserForm.js +1 -1
  95. package/lib/components/grids/TMBlogsPost.js +56 -31
  96. package/lib/components/grids/TMRecentsManager.js +20 -10
  97. package/lib/components/index.d.ts +5 -3
  98. package/lib/components/index.js +5 -3
  99. package/lib/components/query/TMQueryEditor.d.ts +2 -1
  100. package/lib/components/query/TMQueryEditor.js +92 -92
  101. package/lib/components/settings/SettingsAppearance.d.ts +2 -1
  102. package/lib/components/settings/SettingsAppearance.js +99 -30
  103. package/lib/components/viewers/TMDataListItemViewer.d.ts +2 -1
  104. package/lib/components/viewers/TMDataListItemViewer.js +35 -71
  105. package/lib/components/viewers/TMDataUserIdItemViewer.d.ts +8 -0
  106. package/lib/components/viewers/TMDataUserIdItemViewer.js +39 -0
  107. package/lib/css/tm-sdkui.css +1 -1
  108. package/lib/helper/SDKUI_Globals.d.ts +22 -0
  109. package/lib/helper/SDKUI_Globals.js +10 -1
  110. package/lib/helper/SDKUI_Localizator.d.ts +17 -1
  111. package/lib/helper/SDKUI_Localizator.js +167 -1
  112. package/lib/helper/TMCommandsContextMenu.d.ts +4 -2
  113. package/lib/helper/TMCommandsContextMenu.js +15 -4
  114. package/lib/helper/TMIcons.d.ts +4 -0
  115. package/lib/helper/TMIcons.js +13 -3
  116. package/lib/helper/TMPdfViewer.d.ts +8 -0
  117. package/lib/helper/TMPdfViewer.js +373 -0
  118. package/lib/helper/checkinCheckoutManager.d.ts +31 -1
  119. package/lib/helper/checkinCheckoutManager.js +112 -30
  120. package/lib/helper/devextremeCustomMessages.d.ts +30 -0
  121. package/lib/helper/devextremeCustomMessages.js +30 -0
  122. package/lib/helper/helpers.d.ts +3 -1
  123. package/lib/helper/helpers.js +25 -3
  124. package/lib/helper/index.d.ts +2 -0
  125. package/lib/helper/index.js +2 -0
  126. package/lib/helper/queryHelper.d.ts +1 -1
  127. package/lib/helper/queryHelper.js +33 -3
  128. package/lib/helper/workItemsHelper.d.ts +6 -0
  129. package/lib/helper/workItemsHelper.js +230 -0
  130. package/lib/hooks/useCheckInOutOperations.d.ts +28 -0
  131. package/lib/hooks/useCheckInOutOperations.js +223 -0
  132. package/lib/hooks/useDataListItem.d.ts +12 -0
  133. package/lib/hooks/useDataListItem.js +132 -0
  134. package/lib/hooks/useDataUserIdItem.d.ts +10 -0
  135. package/lib/hooks/useDataUserIdItem.js +96 -0
  136. package/lib/hooks/useSettingsFeedback.d.ts +11 -0
  137. package/lib/hooks/useSettingsFeedback.js +38 -0
  138. package/lib/hooks/useWorkflowApprove.d.ts +4 -0
  139. package/lib/hooks/useWorkflowApprove.js +14 -1
  140. package/lib/index.d.ts +1 -0
  141. package/lib/index.js +3 -2
  142. package/lib/services/platform_services.d.ts +3 -3
  143. package/lib/ts/types.d.ts +61 -1
  144. package/lib/utils/theme.d.ts +1 -1
  145. package/lib/utils/theme.js +1 -1
  146. package/package.json +7 -4
  147. package/lib/components/base/TMContextMenu.d.ts +0 -25
  148. package/lib/components/base/TMContextMenu.js +0 -109
  149. package/lib/components/base/TMContextMenuOLD.d.ts +0 -26
  150. package/lib/components/base/TMContextMenuOLD.js +0 -56
  151. package/lib/components/base/TMFloatingToolbar.d.ts +0 -9
  152. package/lib/components/base/TMFloatingToolbar.js +0 -101
  153. package/lib/components/features/assistant/ToppyDraggableHelpCenter.d.ts +0 -30
  154. package/lib/components/features/assistant/ToppyDraggableHelpCenter.js +0 -482
  155. package/lib/components/features/assistant/ToppySpeechBubble.d.ts +0 -9
  156. package/lib/components/features/assistant/ToppySpeechBubble.js +0 -117
  157. package/lib/components/features/search/TMSearchResultCheckoutInfoForm.d.ts +0 -8
@@ -0,0 +1,821 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState, useRef, useEffect, useCallback } from 'react';
3
+ import { ContextMenu } from '../ContextMenu';
4
+ import ShowAlert from '../../base/TMAlert';
5
+ import TMTooltip from '../../base/TMTooltip';
6
+ import * as S from './styles';
7
+ import { IconAdd, IconCloseOutline, IconMenuVertical, IconPin, IconSave, IconSeparator, IconUndo, SDKUI_Globals, SDKUI_Localizator } from '../../../helper';
8
+ import { ButtonNames, TMMessageBoxManager } from '../../base/TMPopUp';
9
+ const Separator = (props) => (_jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", height: "1em", width: "1em", ...props, children: _jsx("path", { d: "M12 2v20", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round" }) }));
10
+ const IconDraggableDots = (props) => (_jsx("svg", { fontSize: 18, viewBox: "0 0 24 24", fill: "currentColor", height: "1em", width: "1em", ...props, children: _jsx("path", { d: "M9 3a2 2 0 11-4 0 2 2 0 014 0zm0 9a2 2 0 11-4 0 2 2 0 014 0zm0 9a2 2 0 11-4 0 2 2 0 014 0zm10-18a2 2 0 11-4 0 2 2 0 014 0zm0 9a2 2 0 11-4 0 2 2 0 014 0zm0 9a2 2 0 11-4 0 2 2 0 014 0z" }) }));
11
+ const TMFloatingMenuBar = ({ containerRef, contextMenuItems = [], isConstrained = false, defaultPosition = { x: 1, y: 90 }, defaultOrientation = 'horizontal', maxItems = 100, contextMenuDefaultPinnedIds = [], defaultItems = [], disbaleConfigMode = false, bgColor = undefined, }) => {
12
+ const percentToPixels = (percent, containerSize) => {
13
+ return (percent / 100) * containerSize;
14
+ };
15
+ const pixelsToPercent = (pixels, containerSize) => {
16
+ return (pixels / containerSize) * 100;
17
+ };
18
+ const isPixelFormat = (pos) => {
19
+ return pos.x > 100 || pos.y > 100;
20
+ };
21
+ const migrateToPercentage = (pixelPos) => {
22
+ const container = containerRef.current?.getBoundingClientRect();
23
+ const containerWidth = isConstrained && container ? container.width : window.innerWidth;
24
+ const containerHeight = isConstrained && container ? container.height : window.innerHeight;
25
+ return {
26
+ x: pixelsToPercent(pixelPos.x, containerWidth),
27
+ y: pixelsToPercent(pixelPos.y, containerHeight),
28
+ };
29
+ };
30
+ const getDefaultConfig = () => ({
31
+ orientation: defaultOrientation,
32
+ savedItemIds: contextMenuDefaultPinnedIds,
33
+ position: defaultPosition,
34
+ });
35
+ const resetFloatingBarSettings = () => {
36
+ // Reset the floatingMenuBar settings in SDKUI_Globals to empty
37
+ SDKUI_Globals.userSettings.searchSettings.floatingMenuBar = {
38
+ orientation: undefined,
39
+ itemIds: undefined,
40
+ position: undefined,
41
+ };
42
+ };
43
+ const loadConfig = () => {
44
+ // If config mode is disabled, use default position and orientation
45
+ if (disbaleConfigMode) {
46
+ return {
47
+ orientation: defaultOrientation,
48
+ savedItemIds: contextMenuDefaultPinnedIds,
49
+ position: defaultPosition,
50
+ };
51
+ }
52
+ try {
53
+ const settings = SDKUI_Globals.userSettings.searchSettings.floatingMenuBar;
54
+ // If localStorage is empty (first time), use props as defaults
55
+ if (!settings || !settings.position || !settings.itemIds) {
56
+ return getDefaultConfig();
57
+ }
58
+ // Validate position
59
+ const hasValidPosition = settings.position &&
60
+ typeof settings.position.x === 'number' &&
61
+ typeof settings.position.y === 'number' &&
62
+ !Number.isNaN(settings.position.x) &&
63
+ !Number.isNaN(settings.position.y) &&
64
+ Number.isFinite(settings.position.x) &&
65
+ Number.isFinite(settings.position.y);
66
+ if (!hasValidPosition) {
67
+ console.warn('FloatingMenuBar: Invalid position, resetting to defaults');
68
+ resetFloatingBarSettings();
69
+ return getDefaultConfig();
70
+ }
71
+ // Ensure position is within reasonable viewport bounds
72
+ const maxX = globalThis.window?.innerWidth ? globalThis.window.innerWidth - 50 : 1000;
73
+ const maxY = globalThis.window?.innerHeight ? globalThis.window.innerHeight - 50 : 800;
74
+ if (settings.position.x < 0 || settings.position.x > maxX ||
75
+ settings.position.y < 0 || settings.position.y > maxY) {
76
+ console.warn('FloatingMenuBar: Position out of bounds, resetting to defaults');
77
+ resetFloatingBarSettings();
78
+ return getDefaultConfig();
79
+ }
80
+ // Validate orientation
81
+ const validOrientation = (settings.orientation === 'horizontal' || settings.orientation === 'vertical')
82
+ ? settings.orientation
83
+ : 'horizontal';
84
+ // Validate itemIds
85
+ const validItemIds = Array.isArray(settings.itemIds) ? settings.itemIds : [];
86
+ if (validItemIds.length > 0) {
87
+ // Check if any ID looks like the old format (contains language-specific text or is too long)
88
+ const hasOldFormatIds = validItemIds.some(id => typeof id === 'string' &&
89
+ !id.startsWith('separator-') &&
90
+ (id.length > 20 || id.includes(' ')));
91
+ if (hasOldFormatIds) {
92
+ console.warn('FloatingMenuBar: Detected old name-based configuration, resetting to defaults');
93
+ resetFloatingBarSettings();
94
+ return getDefaultConfig();
95
+ }
96
+ }
97
+ // Migrate old pixel-based position to percentage-based
98
+ let finalPosition = settings.position;
99
+ if (isPixelFormat(settings.position) || settings.positionFormat === 'pixels') {
100
+ console.log('FloatingMenuBar: Migrating pixel-based position to percentage-based');
101
+ finalPosition = migrateToPercentage(settings.position);
102
+ // Save migrated position immediately
103
+ SDKUI_Globals.userSettings.searchSettings.floatingMenuBar = {
104
+ orientation: validOrientation,
105
+ itemIds: validItemIds,
106
+ position: finalPosition,
107
+ positionFormat: 'percentage',
108
+ };
109
+ }
110
+ return {
111
+ orientation: validOrientation,
112
+ savedItemIds: validItemIds,
113
+ position: finalPosition,
114
+ };
115
+ }
116
+ catch (error) {
117
+ console.error('Failed to load FloatingMenuBar config:', error);
118
+ // Reset to defaults on any error
119
+ try {
120
+ resetFloatingBarSettings();
121
+ }
122
+ catch (e) {
123
+ console.error('Failed to reset FloatingMenuBar settings:', e);
124
+ }
125
+ return getDefaultConfig();
126
+ }
127
+ };
128
+ const initialConfig = loadConfig();
129
+ const [state, setState] = useState({
130
+ position: initialConfig.position, // Stored as percentage
131
+ isDragging: false,
132
+ isConfigMode: false,
133
+ orientation: initialConfig.orientation,
134
+ items: [],
135
+ draggedItemIndex: null,
136
+ });
137
+ const floatingRef = useRef(null);
138
+ const dragOffset = useRef({ x: 0, y: 0 });
139
+ const [dragOverIndex, setDragOverIndex] = useState(null);
140
+ const [pixelPosition, setPixelPosition] = useState({ x: 0, y: 0 }); // Calculated pixel position
141
+ const containerSizeRef = useRef({ width: 0, height: 0 });
142
+ const stateSnapshot = useRef(null);
143
+ const floatingBarItemIds = useRef(new Set());
144
+ const floatingBarItemNames = useRef(new Set());
145
+ useEffect(() => {
146
+ floatingBarItemIds.current = new Set(state.items.map(i => i.id));
147
+ floatingBarItemNames.current = new Set(state.items.map(i => i.name));
148
+ }, [state.items]);
149
+ // Calculate pixel position from percentage when container size or position changes
150
+ useEffect(() => {
151
+ const updatePixelPosition = () => {
152
+ if (!containerRef.current || !floatingRef.current)
153
+ return;
154
+ const container = containerRef.current.getBoundingClientRect();
155
+ const floating = floatingRef.current.getBoundingClientRect();
156
+ const containerWidth = isConstrained ? container.width : window.innerWidth;
157
+ const containerHeight = isConstrained ? container.height : window.innerHeight;
158
+ containerSizeRef.current = { width: containerWidth, height: containerHeight };
159
+ let newX = percentToPixels(state.position.x, containerWidth);
160
+ let newY = percentToPixels(state.position.y, containerHeight);
161
+ newX = Math.max(0, Math.min(newX, containerWidth - floating.width));
162
+ newY = Math.max(0, Math.min(newY, containerHeight - floating.height));
163
+ setPixelPosition({ x: newX, y: newY });
164
+ };
165
+ updatePixelPosition();
166
+ const resizeObserver = new ResizeObserver(() => {
167
+ updatePixelPosition();
168
+ });
169
+ if (containerRef.current) {
170
+ resizeObserver.observe(containerRef.current);
171
+ }
172
+ if (!isConstrained) {
173
+ window.addEventListener('resize', updatePixelPosition);
174
+ }
175
+ return () => {
176
+ resizeObserver.disconnect();
177
+ if (!isConstrained) {
178
+ window.removeEventListener('resize', updatePixelPosition);
179
+ }
180
+ };
181
+ }, [state.position, isConstrained]);
182
+ const flattenMenuItems = useCallback((items, parentPath = '') => {
183
+ const result = [];
184
+ items.forEach((item, index) => {
185
+ const itemId = item.id || `${parentPath}${item.name}-${index}`;
186
+ if (item.onClick && !item.submenu) {
187
+ const isPinned = state.items.some(i => i.id === itemId);
188
+ result.push({
189
+ id: itemId,
190
+ name: item.name,
191
+ icon: item.icon || _jsx(IconPin, {}),
192
+ onClick: item.onClick,
193
+ disabled: item.disabled,
194
+ isPinned: isPinned,
195
+ });
196
+ }
197
+ // Recursively process submenus
198
+ if (item.submenu) {
199
+ result.push(...flattenMenuItems(item.submenu, `${itemId}/`));
200
+ }
201
+ });
202
+ return result;
203
+ }, [state.items]);
204
+ // Restore items on mount from savedItemIds
205
+ useEffect(() => {
206
+ if (contextMenuItems.length > 0 || initialConfig.savedItemIds.length > 0 || defaultItems.length > 0) {
207
+ const flatItems = flattenMenuItems(contextMenuItems);
208
+ let itemsToSet = [];
209
+ // If disbaleConfigMode is true and defaultItems provided, use only defaultItems
210
+ if (disbaleConfigMode && defaultItems.length > 0) {
211
+ itemsToSet = defaultItems;
212
+ }
213
+ else if (!disbaleConfigMode && initialConfig.savedItemIds.length > 0) {
214
+ // Restore items in the saved order from localStorage (only if config mode is enabled)
215
+ const restoredItems = initialConfig.savedItemIds
216
+ .map((id) => {
217
+ if (id.startsWith('separator-')) {
218
+ return {
219
+ id,
220
+ name: 'Separator',
221
+ icon: _jsx(Separator, {}),
222
+ onClick: () => { },
223
+ isSeparator: true,
224
+ };
225
+ }
226
+ return flatItems.find(item => item.id === id);
227
+ })
228
+ .filter((item) => item !== undefined);
229
+ itemsToSet = restoredItems;
230
+ }
231
+ else if (contextMenuDefaultPinnedIds.length > 0) {
232
+ // First time: Use contextMenuDefaultPinnedIds from props to find items by ID
233
+ const defaultPinnedItems = contextMenuDefaultPinnedIds
234
+ .map((id) => flatItems.find(item => item.id === id))
235
+ .filter((item) => item !== undefined);
236
+ itemsToSet = defaultPinnedItems;
237
+ }
238
+ else if (defaultItems.length > 0) {
239
+ // Use defaultItems as fallback
240
+ itemsToSet = defaultItems;
241
+ }
242
+ if (itemsToSet.length > 0) {
243
+ setState(s => ({ ...s, items: itemsToSet }));
244
+ }
245
+ }
246
+ }, disbaleConfigMode ? [defaultItems] : []); // Update when defaultItems change if config mode is disabled
247
+ const togglePin = useCallback((item) => {
248
+ setState(s => {
249
+ const isInFloatingBar = s.items.some(i => i.id === item.id);
250
+ if (isInFloatingBar) {
251
+ // Remove from floating bar
252
+ const newItems = s.items.filter(i => i.id !== item.id);
253
+ return { ...s, items: newItems };
254
+ }
255
+ else {
256
+ // Add to floating bar
257
+ if (s.items.length >= maxItems) {
258
+ ShowAlert({
259
+ mode: 'warning',
260
+ title: 'Limite Massimo Raggiunto',
261
+ message: `Hai raggiunto il massimo di ${maxItems} elementi. Rimuovine uno prima di aggiungerne altri.`,
262
+ duration: 4000,
263
+ });
264
+ return s;
265
+ }
266
+ return { ...s, items: [...s.items, item] };
267
+ }
268
+ });
269
+ }, [maxItems]);
270
+ // Get current item state (disabled and onClick) from contextMenuItems
271
+ const getCurrentItemState = useCallback((itemId) => {
272
+ const findInItems = (items) => {
273
+ for (let i = 0; i < items.length; i++) {
274
+ const item = items[i];
275
+ // Match by ID if the item has one
276
+ if (item.id === itemId)
277
+ return item;
278
+ // Check in submenu
279
+ if (item.submenu) {
280
+ const found = findInItems(item.submenu);
281
+ if (found)
282
+ return found;
283
+ }
284
+ }
285
+ return undefined;
286
+ };
287
+ const foundItem = findInItems(contextMenuItems);
288
+ return {
289
+ disabled: foundItem?.disabled,
290
+ onClick: foundItem?.onClick
291
+ };
292
+ }, [contextMenuItems]);
293
+ // Remove trailing separators from items array
294
+ const removeTrailingSeparators = useCallback((items) => {
295
+ const result = [...items];
296
+ while (result.length > 0 && result.at(-1)?.isSeparator) {
297
+ result.pop();
298
+ }
299
+ return result;
300
+ }, []);
301
+ // Create a new separator item
302
+ const createSeparator = useCallback(() => {
303
+ const separatorId = `separator-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
304
+ return {
305
+ id: separatorId,
306
+ name: 'Separator',
307
+ icon: _jsx(Separator, {}),
308
+ onClick: () => { },
309
+ isSeparator: true,
310
+ };
311
+ }, []);
312
+ // Add separator to items
313
+ const addSeparator = useCallback(() => {
314
+ if (state.items.length >= maxItems) {
315
+ ShowAlert({
316
+ mode: 'warning',
317
+ title: 'Limite Massimo Raggiunto',
318
+ message: `Hai raggiunto il massimo di ${maxItems} elementi. Rimuovine uno prima di aggiungerne altri.`,
319
+ duration: 4000,
320
+ });
321
+ return;
322
+ }
323
+ const separator = createSeparator();
324
+ setState(s => ({ ...s, items: [...s.items, separator] }));
325
+ }, [state.items.length, maxItems, createSeparator]);
326
+ const getPinContextMenuItems = useCallback(() => {
327
+ const flatItems = flattenMenuItems(contextMenuItems);
328
+ const currentItemIds = new Set(state.items.map(i => i.id));
329
+ const createPinItems = (items) => {
330
+ return items.map(item => {
331
+ const flatItem = flatItems.find(fi => fi.id === item.id);
332
+ const itemId = flatItem?.id || item.id || '';
333
+ const isAlreadyPinned = currentItemIds.has(itemId);
334
+ const pinItem = {
335
+ ...item,
336
+ onClick: item.onClick && !item.submenu ? () => {
337
+ if (flatItem && !isAlreadyPinned) {
338
+ togglePin(flatItem);
339
+ }
340
+ } : undefined,
341
+ disabled: isAlreadyPinned,
342
+ };
343
+ if (item.submenu) {
344
+ pinItem.submenu = createPinItems(item.submenu);
345
+ }
346
+ return pinItem;
347
+ });
348
+ };
349
+ const pinItems = createPinItems(contextMenuItems);
350
+ // Add separator option at the end
351
+ pinItems.push({
352
+ id: 'add-separator',
353
+ name: SDKUI_Localizator.Add + ' separatore',
354
+ icon: _jsx(IconSeparator, {}),
355
+ onClick: addSeparator,
356
+ beginGroup: true
357
+ });
358
+ return pinItems;
359
+ }, [contextMenuItems, flattenMenuItems, togglePin, state.items, addSeparator]);
360
+ const getContextMenuItemsWithPinIcons = useCallback(() => {
361
+ const flatItems = flattenMenuItems(contextMenuItems);
362
+ const currentItemIds = new Set(state.items.map(i => i.id));
363
+ const addPinIcons = (items) => {
364
+ return items.map(item => {
365
+ const flatItem = flatItems.find(fi => fi.id === item.id);
366
+ const itemId = flatItem?.id || item.id || '';
367
+ const isPinned = currentItemIds.has(itemId);
368
+ const itemWithPin = {
369
+ ...item,
370
+ rightIcon: flatItem ? _jsx(IconPin, { color: isPinned ? 'red' : 'black' }) : undefined,
371
+ onRightIconClick: flatItem ? () => {
372
+ togglePin(flatItem);
373
+ } : undefined,
374
+ };
375
+ if (item.submenu) {
376
+ itemWithPin.submenu = addPinIcons(item.submenu);
377
+ }
378
+ return itemWithPin;
379
+ });
380
+ };
381
+ return addPinIcons(contextMenuItems);
382
+ }, [contextMenuItems, flattenMenuItems, togglePin, state.items]);
383
+ const handleMouseDown = (e) => {
384
+ if (state.isConfigMode)
385
+ return;
386
+ const containerRect = containerRef.current?.getBoundingClientRect();
387
+ if (containerRect) {
388
+ // Calculate drag offset based on positioning mode
389
+ if (isConstrained) {
390
+ // For absolute positioning, offset is relative to container
391
+ dragOffset.current = {
392
+ x: e.clientX - containerRect.left - pixelPosition.x,
393
+ y: e.clientY - containerRect.top - pixelPosition.y,
394
+ };
395
+ }
396
+ else {
397
+ // For fixed positioning, offset is relative to viewport
398
+ dragOffset.current = {
399
+ x: e.clientX - pixelPosition.x,
400
+ y: e.clientY - pixelPosition.y,
401
+ };
402
+ }
403
+ }
404
+ setState(s => ({ ...s, isDragging: true }));
405
+ };
406
+ const handleGripDoubleClick = () => {
407
+ if (state.isConfigMode)
408
+ return;
409
+ toggleOrientation();
410
+ };
411
+ const handleMouseMove = useCallback((e) => {
412
+ if (!state.isDragging || !containerRef.current || !floatingRef.current)
413
+ return;
414
+ const container = containerRef.current.getBoundingClientRect();
415
+ const floating = floatingRef.current.getBoundingClientRect();
416
+ let newX, newY;
417
+ if (isConstrained) {
418
+ // For constrained (absolute positioning), use container coordinates
419
+ newX = e.clientX - container.left - dragOffset.current.x;
420
+ newY = e.clientY - container.top - dragOffset.current.y;
421
+ // Constrain to container bounds
422
+ newX = Math.max(0, Math.min(newX, container.width - floating.width));
423
+ newY = Math.max(0, Math.min(newY, container.height - floating.height));
424
+ }
425
+ else {
426
+ // For unconstrained (fixed positioning), use viewport coordinates
427
+ newX = e.clientX - dragOffset.current.x;
428
+ newY = e.clientY - dragOffset.current.y;
429
+ // Constrain to viewport bounds
430
+ newX = Math.max(0, Math.min(newX, window.innerWidth - floating.width));
431
+ newY = Math.max(0, Math.min(newY, window.innerHeight - floating.height));
432
+ }
433
+ // Update pixel position directly during drag
434
+ setPixelPosition({ x: newX, y: newY });
435
+ }, [state.isDragging, containerRef, isConstrained]);
436
+ const handleMouseUp = useCallback(() => {
437
+ if (state.isDragging && containerSizeRef.current.width > 0) {
438
+ // Convert final pixel position to percentage before updating state
439
+ const percentagePosition = {
440
+ x: pixelsToPercent(pixelPosition.x, containerSizeRef.current.width),
441
+ y: pixelsToPercent(pixelPosition.y, containerSizeRef.current.height),
442
+ };
443
+ setState(s => ({
444
+ ...s,
445
+ isDragging: false,
446
+ position: percentagePosition,
447
+ }));
448
+ }
449
+ else {
450
+ setState(s => ({ ...s, isDragging: false }));
451
+ }
452
+ }, [state.isDragging, pixelPosition]);
453
+ // Touch event handlers for tablet support
454
+ const handleTouchStart = (e) => {
455
+ if (state.isConfigMode)
456
+ return;
457
+ const touch = e.touches[0];
458
+ const containerRect = containerRef.current?.getBoundingClientRect();
459
+ if (containerRect) {
460
+ if (isConstrained) {
461
+ dragOffset.current = {
462
+ x: touch.clientX - containerRect.left - pixelPosition.x,
463
+ y: touch.clientY - containerRect.top - pixelPosition.y,
464
+ };
465
+ }
466
+ else {
467
+ dragOffset.current = {
468
+ x: touch.clientX - pixelPosition.x,
469
+ y: touch.clientY - pixelPosition.y,
470
+ };
471
+ }
472
+ }
473
+ setState(s => ({ ...s, isDragging: true }));
474
+ };
475
+ const handleTouchMove = useCallback((e) => {
476
+ if (!state.isDragging || !containerRef.current || !floatingRef.current)
477
+ return;
478
+ const touch = e.touches[0];
479
+ const container = containerRef.current.getBoundingClientRect();
480
+ const floating = floatingRef.current.getBoundingClientRect();
481
+ let newX, newY;
482
+ if (isConstrained) {
483
+ newX = touch.clientX - container.left - dragOffset.current.x;
484
+ newY = touch.clientY - container.top - dragOffset.current.y;
485
+ newX = Math.max(0, Math.min(newX, container.width - floating.width));
486
+ newY = Math.max(0, Math.min(newY, container.height - floating.height));
487
+ }
488
+ else {
489
+ newX = touch.clientX - dragOffset.current.x;
490
+ newY = touch.clientY - dragOffset.current.y;
491
+ newX = Math.max(0, Math.min(newX, window.innerWidth - floating.width));
492
+ newY = Math.max(0, Math.min(newY, window.innerHeight - floating.height));
493
+ }
494
+ setPixelPosition({ x: newX, y: newY });
495
+ }, [state.isDragging, containerRef, isConstrained]);
496
+ const handleTouchEnd = useCallback(() => {
497
+ if (state.isDragging && containerSizeRef.current.width > 0) {
498
+ const percentagePosition = {
499
+ x: pixelsToPercent(pixelPosition.x, containerSizeRef.current.width),
500
+ y: pixelsToPercent(pixelPosition.y, containerSizeRef.current.height),
501
+ };
502
+ setState(s => ({
503
+ ...s,
504
+ isDragging: false,
505
+ position: percentagePosition,
506
+ }));
507
+ }
508
+ else {
509
+ setState(s => ({ ...s, isDragging: false }));
510
+ }
511
+ }, [state.isDragging, pixelPosition]);
512
+ useEffect(() => {
513
+ if (state.isDragging) {
514
+ document.addEventListener('mousemove', handleMouseMove);
515
+ document.addEventListener('mouseup', handleMouseUp);
516
+ document.addEventListener('touchmove', handleTouchMove);
517
+ document.addEventListener('touchend', handleTouchEnd);
518
+ return () => {
519
+ document.removeEventListener('mousemove', handleMouseMove);
520
+ document.removeEventListener('mouseup', handleMouseUp);
521
+ document.removeEventListener('touchmove', handleTouchMove);
522
+ document.removeEventListener('touchend', handleTouchEnd);
523
+ };
524
+ }
525
+ return undefined;
526
+ }, [state.isDragging, handleMouseMove, handleMouseUp, handleTouchMove, handleTouchEnd]);
527
+ // Save to SDKUI_Globals.userSettings only when NOT in config mode (when applying changes)
528
+ useEffect(() => {
529
+ if (state.isConfigMode)
530
+ return; // Don't save during edit mode
531
+ if (disbaleConfigMode)
532
+ return; // Don't save if config mode is disabled
533
+ try {
534
+ // Replace the entire object to trigger the Proxy
535
+ SDKUI_Globals.userSettings.searchSettings.floatingMenuBar = {
536
+ orientation: state.orientation,
537
+ itemIds: state.items.map(item => item.id),
538
+ position: state.position,
539
+ positionFormat: 'percentage',
540
+ };
541
+ }
542
+ catch (error) {
543
+ console.error('Failed to save FloatingMenuBar config:', error);
544
+ }
545
+ }, [state.orientation, state.items, state.position, state.isConfigMode, disbaleConfigMode]);
546
+ const toggleConfigMode = () => {
547
+ setState(s => {
548
+ if (!s.isConfigMode) {
549
+ stateSnapshot.current = {
550
+ items: [...s.items],
551
+ orientation: s.orientation,
552
+ position: { ...s.position },
553
+ };
554
+ return { ...s, isConfigMode: true };
555
+ }
556
+ else {
557
+ // Exiting edit mode (applying changes) - clean up trailing separators and clear snapshot
558
+ stateSnapshot.current = null;
559
+ const cleanedItems = removeTrailingSeparators(s.items);
560
+ return { ...s, isConfigMode: false, items: cleanedItems };
561
+ }
562
+ });
563
+ };
564
+ // Auto-reposition when entering edit mode to ensure Apply/Undo buttons are visible
565
+ useEffect(() => {
566
+ if (!state.isConfigMode || !floatingRef.current)
567
+ return;
568
+ // Use double requestAnimationFrame to ensure the DOM has fully updated with new buttons
569
+ requestAnimationFrame(() => {
570
+ requestAnimationFrame(() => {
571
+ if (!floatingRef.current)
572
+ return;
573
+ const floating = floatingRef.current.getBoundingClientRect();
574
+ const containerWidth = isConstrained && containerRef.current
575
+ ? containerRef.current.getBoundingClientRect().width
576
+ : window.innerWidth;
577
+ const containerHeight = isConstrained && containerRef.current
578
+ ? containerRef.current.getBoundingClientRect().height
579
+ : window.innerHeight;
580
+ // Use current pixel position
581
+ let newPixelX = pixelPosition.x;
582
+ let newPixelY = pixelPosition.y;
583
+ let needsUpdate = false;
584
+ // Check horizontal overflow
585
+ if (newPixelX + floating.width > containerWidth) {
586
+ newPixelX = Math.max(0, containerWidth - floating.width);
587
+ needsUpdate = true;
588
+ }
589
+ // Check vertical overflow
590
+ if (newPixelY + floating.height > containerHeight) {
591
+ newPixelY = Math.max(0, containerHeight - floating.height);
592
+ needsUpdate = true;
593
+ }
594
+ if (needsUpdate) {
595
+ // Update pixel position immediately
596
+ setPixelPosition({ x: newPixelX, y: newPixelY });
597
+ // Convert to percentage for state
598
+ const newPercentagePosition = {
599
+ x: pixelsToPercent(newPixelX, containerWidth),
600
+ y: pixelsToPercent(newPixelY, containerHeight),
601
+ };
602
+ setState(s => ({
603
+ ...s,
604
+ position: newPercentagePosition,
605
+ }));
606
+ // Update snapshot position to the corrected position so Undo restores to visible position
607
+ if (stateSnapshot.current) {
608
+ stateSnapshot.current.position = newPercentagePosition;
609
+ }
610
+ }
611
+ });
612
+ });
613
+ }, [state.isConfigMode, state.orientation, isConstrained, state.items, pixelPosition.x, pixelPosition.y]);
614
+ const handleUndo = () => {
615
+ if (stateSnapshot.current) {
616
+ setState(s => ({
617
+ ...s,
618
+ items: [...stateSnapshot.current.items],
619
+ orientation: stateSnapshot.current.orientation,
620
+ position: { ...stateSnapshot.current.position },
621
+ isConfigMode: true,
622
+ }));
623
+ }
624
+ };
625
+ // Check if current state has changed from snapshot
626
+ const hasChanges = () => {
627
+ if (!stateSnapshot.current)
628
+ return false;
629
+ // Check if items have changed (different IDs or different order)
630
+ const currentIds = state.items.map(i => i.id).join(',');
631
+ const snapshotIds = stateSnapshot.current.items.map(i => i.id).join(',');
632
+ return currentIds !== snapshotIds;
633
+ };
634
+ const handleClose = () => {
635
+ // If all items removed, exit without asking and restore last items
636
+ if (state.items.length === 0 && stateSnapshot.current) {
637
+ setState(s => ({
638
+ ...s,
639
+ items: [...stateSnapshot.current.items],
640
+ orientation: stateSnapshot.current.orientation,
641
+ position: { ...stateSnapshot.current.position },
642
+ isConfigMode: false,
643
+ }));
644
+ stateSnapshot.current = null;
645
+ return;
646
+ }
647
+ // If no changes, simply exit config mode
648
+ if (!hasChanges()) {
649
+ stateSnapshot.current = null;
650
+ const cleanedItems = removeTrailingSeparators(state.items);
651
+ setState(s => ({ ...s, isConfigMode: false, items: cleanedItems }));
652
+ return;
653
+ }
654
+ // If there are changes, ask for confirmation
655
+ TMMessageBoxManager.show({
656
+ message: 'Perderai le tue modifiche, sei sicuro?',
657
+ buttons: [ButtonNames.YES, ButtonNames.NO],
658
+ onButtonClick: (buttonName) => {
659
+ if (buttonName === ButtonNames.YES && stateSnapshot.current) {
660
+ // Restore snapshot and exit config mode
661
+ setState(s => ({
662
+ ...s,
663
+ items: [...stateSnapshot.current.items],
664
+ orientation: stateSnapshot.current.orientation,
665
+ position: { ...stateSnapshot.current.position },
666
+ isConfigMode: false,
667
+ }));
668
+ stateSnapshot.current = null;
669
+ }
670
+ },
671
+ });
672
+ };
673
+ const toggleOrientation = () => {
674
+ const newOrientation = state.orientation === 'horizontal' ? 'vertical' : 'horizontal';
675
+ if (state.orientation === 'horizontal' && newOrientation === 'vertical') {
676
+ if (floatingRef.current) {
677
+ const floating = floatingRef.current.getBoundingClientRect();
678
+ const screenHeight = window.innerHeight;
679
+ if (floating.width > screenHeight - 70) {
680
+ ShowAlert({
681
+ mode: 'warning',
682
+ title: 'Troppi elementi',
683
+ message: 'Ci sono troppi elementi nella barra mobile per la modalità verticale.',
684
+ duration: 4000,
685
+ });
686
+ return;
687
+ }
688
+ }
689
+ }
690
+ setState(s => ({
691
+ ...s,
692
+ orientation: newOrientation,
693
+ }));
694
+ requestAnimationFrame(() => {
695
+ requestAnimationFrame(() => {
696
+ if (containerRef.current && floatingRef.current) {
697
+ const container = containerRef.current.getBoundingClientRect();
698
+ const floating = floatingRef.current.getBoundingClientRect();
699
+ let newX, newY;
700
+ if (isConstrained) {
701
+ // For constrained mode, use container bounds
702
+ newX = Math.max(0, Math.min(state.position.x, container.width - floating.width));
703
+ newY = Math.max(0, Math.min(state.position.y, container.height - floating.height));
704
+ }
705
+ else {
706
+ // For unconstrained mode, use viewport bounds
707
+ newX = Math.max(0, Math.min(state.position.x, window.innerWidth - floating.width));
708
+ newY = Math.max(0, Math.min(state.position.y, window.innerHeight - floating.height));
709
+ }
710
+ // Only update position if it changed (to avoid unnecessary re-render)
711
+ if (newX !== state.position.x || newY !== state.position.y) {
712
+ setState(s => ({
713
+ ...s,
714
+ position: { x: newX, y: newY },
715
+ }));
716
+ }
717
+ }
718
+ });
719
+ });
720
+ };
721
+ const removeItem = (itemId) => {
722
+ setState(s => ({
723
+ ...s,
724
+ items: s.items.filter(item => item.id !== itemId),
725
+ }));
726
+ };
727
+ // Drag and drop for reordering
728
+ const handleDragStart = (e, index) => {
729
+ if (!state.isConfigMode)
730
+ return;
731
+ e.dataTransfer.effectAllowed = 'move';
732
+ e.dataTransfer.setData('text/plain', index.toString());
733
+ setState(s => ({ ...s, draggedItemIndex: index }));
734
+ };
735
+ const handleDragEnter = (e, index) => {
736
+ if (!state.isConfigMode)
737
+ return;
738
+ e.preventDefault();
739
+ if (state.draggedItemIndex !== index) {
740
+ setDragOverIndex(index);
741
+ }
742
+ };
743
+ const handleDragOver = (e) => {
744
+ if (!state.isConfigMode)
745
+ return;
746
+ e.preventDefault();
747
+ e.dataTransfer.dropEffect = 'move';
748
+ };
749
+ const handleDragLeave = (_e, index) => {
750
+ if (!state.isConfigMode)
751
+ return;
752
+ // Only clear if we're actually leaving this specific item
753
+ if (dragOverIndex === index) {
754
+ setDragOverIndex(null);
755
+ }
756
+ };
757
+ const handleDrop = (e, dropIndex) => {
758
+ if (!state.isConfigMode || state.draggedItemIndex === null)
759
+ return;
760
+ e.preventDefault();
761
+ e.stopPropagation();
762
+ const dragIndex = state.draggedItemIndex;
763
+ if (dragIndex === dropIndex) {
764
+ setDragOverIndex(null);
765
+ return;
766
+ }
767
+ const newItems = [...state.items];
768
+ const [draggedItem] = newItems.splice(dragIndex, 1);
769
+ newItems.splice(dropIndex, 0, draggedItem);
770
+ setState(s => ({
771
+ ...s,
772
+ items: newItems,
773
+ draggedItemIndex: null,
774
+ }));
775
+ setDragOverIndex(null);
776
+ };
777
+ const handleDragEnd = () => {
778
+ setState(s => ({ ...s, draggedItemIndex: null }));
779
+ setDragOverIndex(null);
780
+ };
781
+ return (_jsxs(_Fragment, { children: [_jsx(S.Overlay, { "$visible": state.isConfigMode }), _jsxs(S.FloatingContainer, { ref: floatingRef, "$x": pixelPosition.x, "$y": pixelPosition.y, "$orientation": state.orientation, "$isDragging": state.isDragging, "$isConfigMode": state.isConfigMode, "$isConstrained": isConstrained, "$bgColor": bgColor, onContextMenu: (e) => e.preventDefault(), children: [!state.isConfigMode ? (_jsx(ContextMenu, { items: [
782
+ ...(!disbaleConfigMode ? [{
783
+ name: SDKUI_Localizator.Configure,
784
+ onClick: () => {
785
+ if (!state.isConfigMode) {
786
+ toggleConfigMode();
787
+ }
788
+ },
789
+ }] : []),
790
+ {
791
+ name: state.orientation === 'horizontal' ? 'Floating bar verticale' : 'Floating bar orizzontale',
792
+ onClick: toggleOrientation,
793
+ },
794
+ ], trigger: "right", children: _jsx(S.GripHandle, { "$orientation": state.orientation, onMouseDown: handleMouseDown, onTouchStart: handleTouchStart, onDoubleClick: handleGripDoubleClick, children: _jsx(IconDraggableDots, {}) }) })) : (_jsx(S.GripHandle, { "$orientation": state.orientation, onMouseDown: handleMouseDown, onTouchStart: handleTouchStart, onDoubleClick: handleGripDoubleClick, children: _jsx(IconDraggableDots, {}) })), _jsx(S.Separator, { "$orientation": state.orientation }), state.items.map((item, index) => {
795
+ // Handle separator items
796
+ if (item.isSeparator) {
797
+ return (_jsxs(S.DraggableItem, { "$isDragging": state.draggedItemIndex === index, "$isDragOver": dragOverIndex === index && state.draggedItemIndex !== index, draggable: state.isConfigMode, onDragStart: (e) => handleDragStart(e, index), onDragEnter: (e) => handleDragEnter(e, index), onDragOver: handleDragOver, onDragLeave: (e) => handleDragLeave(e, index), onDrop: (e) => handleDrop(e, index), onDragEnd: handleDragEnd, children: [_jsx(S.ItemSeparator, { "$orientation": state.orientation, "$isConfigMode": state.isConfigMode }), state.isConfigMode && (_jsx(S.RemoveButton, { onClick: () => removeItem(item.id), children: "\u00D7" }))] }, item.id));
798
+ }
799
+ // Get current state (disabled and onClick) from contextMenuItems
800
+ const currentState = getCurrentItemState(item.id);
801
+ // Prefer currentState.disabled if contextMenuItems has items, otherwise use item.disabled
802
+ const isDisabled = (contextMenuItems.length > 0 && currentState.disabled !== undefined)
803
+ ? currentState.disabled === true
804
+ : item.disabled === true;
805
+ const currentOnClick = currentState.onClick || item.onClick; // Fallback to stored onClick if not found
806
+ return (_jsx(S.DraggableItem, { "$isDragging": state.draggedItemIndex === index, "$isDragOver": dragOverIndex === index && state.draggedItemIndex !== index, draggable: state.isConfigMode, onDragStart: (e) => handleDragStart(e, index), onDragEnter: (e) => handleDragEnter(e, index), onDragOver: handleDragOver, onDragLeave: (e) => handleDragLeave(e, index), onDrop: (e) => handleDrop(e, index), onDragEnd: handleDragEnd, children: item.staticItem ? (
807
+ // Visualizza l'elemento statico personalizzato
808
+ _jsxs(_Fragment, { children: [item.staticItem, state.isConfigMode && (_jsx(S.RemoveButton, { onClick: () => removeItem(item.id), children: "\u00D7" }))] })) : (
809
+ // Visualizza il pulsante standard
810
+ _jsxs(_Fragment, { children: [_jsx(TMTooltip, { content: item.name, position: "bottom", children: _jsx(S.MenuButton, { onClick: () => {
811
+ if (state.isConfigMode || isDisabled)
812
+ return;
813
+ if (currentOnClick) {
814
+ currentOnClick();
815
+ }
816
+ }, disabled: isDisabled, "$isActive": item.isToggle, children: item.icon }) }), state.isConfigMode && (_jsx(S.RemoveButton, { onClick: () => removeItem(item.id), children: "\u00D7" }))] })) }, item.id));
817
+ }), !state.isConfigMode && !disbaleConfigMode && contextMenuItems.length > 0 && (_jsx(ContextMenu, { items: getContextMenuItemsWithPinIcons(), trigger: "left", keepOpenOnClick: false, children: _jsx(S.ContextMenuButton, { children: _jsx(IconMenuVertical, {}) }) })), state.isConfigMode && state.items.length < maxItems && contextMenuItems.length > 0 && (_jsx(ContextMenu, { items: getPinContextMenuItems(), trigger: "left", keepOpenOnClick: true, children: _jsx(TMTooltip, { content: SDKUI_Localizator.Add, children: _jsx(S.AddButton, { children: _jsx(IconAdd, {}) }) }) })), state.isConfigMode && (_jsxs(_Fragment, { children: [_jsx(S.Separator, { "$orientation": state.orientation }), _jsxs(S.ButtonGroup, { "$orientation": state.orientation, children: [_jsx(TMTooltip, { content: SDKUI_Localizator.Undo, position: state.orientation === 'horizontal' ? 'right' : 'top', children: _jsx(S.UndoButton, { onClick: handleUndo, disabled: !hasChanges(), children: _jsx(IconUndo, { fontSize: 18 }) }) }), _jsx(TMTooltip, { content: state.items.length === 0
818
+ ? 'Devi aggiungere almeno un item'
819
+ : SDKUI_Localizator.Save, position: state.orientation === 'horizontal' ? 'right' : 'top', children: _jsx(S.ApplyButton, { onClick: toggleConfigMode, disabled: state.items.length === 0 || !hasChanges(), children: _jsx(IconSave, { fontSize: 20 }) }) }), _jsx(TMTooltip, { content: SDKUI_Localizator.Close, position: state.orientation === 'horizontal' ? 'right' : 'top', children: _jsx(S.CloseButton, { onClick: handleClose, children: _jsx(IconCloseOutline, { fontSize: 20 }) }) })] })] }))] })] }));
820
+ };
821
+ export default TMFloatingMenuBar;