@topconsultnpm/sdkui-react 6.20.0-dev1.6 → 6.20.0-dev1.60

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 (84) hide show
  1. package/lib/components/NewComponents/ContextMenu/TMContextMenu.d.ts +4 -0
  2. package/lib/components/NewComponents/ContextMenu/TMContextMenu.js +416 -0
  3. package/lib/components/NewComponents/ContextMenu/hooks.d.ts +13 -0
  4. package/lib/components/NewComponents/ContextMenu/hooks.js +61 -0
  5. package/lib/components/NewComponents/ContextMenu/index.d.ts +5 -0
  6. package/lib/components/NewComponents/ContextMenu/index.js +3 -0
  7. package/lib/components/NewComponents/ContextMenu/styles.d.ts +31 -0
  8. package/lib/components/NewComponents/ContextMenu/styles.js +336 -0
  9. package/lib/components/NewComponents/ContextMenu/types.d.ts +39 -0
  10. package/lib/components/NewComponents/ContextMenu/types.js +1 -0
  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.d.ts +4 -0
  14. package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +745 -0
  15. package/lib/components/NewComponents/FloatingMenuBar/index.d.ts +2 -0
  16. package/lib/components/NewComponents/FloatingMenuBar/index.js +2 -0
  17. package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +51 -0
  18. package/lib/components/NewComponents/FloatingMenuBar/styles.js +385 -0
  19. package/lib/components/NewComponents/FloatingMenuBar/types.d.ts +29 -0
  20. package/lib/components/NewComponents/FloatingMenuBar/types.js +1 -0
  21. package/lib/components/base/TMAccordionNew.js +35 -14
  22. package/lib/components/base/TMCustomButton.js +61 -17
  23. package/lib/components/base/TMDataGrid.d.ts +7 -4
  24. package/lib/components/base/TMDataGrid.js +142 -11
  25. package/lib/components/choosers/TMMetadataChooser.js +8 -1
  26. package/lib/components/editors/TMMetadataValues.js +23 -5
  27. package/lib/components/editors/TMTextBox.js +6 -3
  28. package/lib/components/features/documents/TMDcmtForm.d.ts +13 -1
  29. package/lib/components/features/documents/TMDcmtForm.js +386 -194
  30. package/lib/components/features/documents/TMDcmtPreview.js +40 -69
  31. package/lib/components/features/documents/TMMasterDetailDcmts.js +37 -52
  32. package/lib/components/features/search/TMDcmtCheckoutInfoForm.d.ts +8 -0
  33. package/lib/components/features/search/{TMSearchResultCheckoutInfoForm.js → TMDcmtCheckoutInfoForm.js} +5 -10
  34. package/lib/components/features/search/TMSavedQuerySelector.js +72 -67
  35. package/lib/components/features/search/TMSearch.js +30 -5
  36. package/lib/components/features/search/TMSearchQueryPanel.js +13 -12
  37. package/lib/components/features/search/TMSearchResult.js +57 -216
  38. package/lib/components/features/search/TMSearchResultsMenuItems.d.ts +3 -3
  39. package/lib/components/features/search/TMSearchResultsMenuItems.js +205 -169
  40. package/lib/components/features/search/TMSignSettingsForm.js +1 -1
  41. package/lib/components/features/search/TMSignatureInfoContent.d.ts +6 -0
  42. package/lib/components/features/search/TMSignatureInfoContent.js +140 -0
  43. package/lib/components/features/search/TMViewHistoryDcmt.js +1 -1
  44. package/lib/components/features/tasks/TMTaskForm.js +20 -1
  45. package/lib/components/features/tasks/TMTasksUtils.d.ts +2 -2
  46. package/lib/components/features/tasks/TMTasksUtils.js +62 -52
  47. package/lib/components/features/tasks/TMTasksView.js +6 -6
  48. package/lib/components/features/workflow/TMWorkflowPopup.d.ts +32 -2
  49. package/lib/components/features/workflow/TMWorkflowPopup.js +112 -14
  50. package/lib/components/features/workflow/diagram/WFDiagram.js +2 -2
  51. package/lib/components/forms/Login/LoginValidatorService.d.ts +2 -0
  52. package/lib/components/forms/Login/LoginValidatorService.js +7 -2
  53. package/lib/components/forms/Login/TMLoginForm.js +34 -6
  54. package/lib/components/forms/TMChooserForm.js +1 -1
  55. package/lib/components/grids/TMBlogsPost.js +55 -30
  56. package/lib/components/index.d.ts +2 -0
  57. package/lib/components/index.js +2 -0
  58. package/lib/components/viewers/TMDataListItemViewer.d.ts +2 -1
  59. package/lib/components/viewers/TMDataListItemViewer.js +12 -11
  60. package/lib/css/tm-sdkui.css +1 -1
  61. package/lib/helper/SDKUI_Globals.d.ts +17 -0
  62. package/lib/helper/SDKUI_Globals.js +9 -0
  63. package/lib/helper/SDKUI_Localizator.d.ts +9 -1
  64. package/lib/helper/SDKUI_Localizator.js +87 -1
  65. package/lib/helper/TMIcons.d.ts +2 -0
  66. package/lib/helper/TMIcons.js +6 -0
  67. package/lib/helper/TMPdfViewer.d.ts +8 -0
  68. package/lib/helper/TMPdfViewer.js +368 -0
  69. package/lib/helper/checkinCheckoutManager.d.ts +32 -2
  70. package/lib/helper/checkinCheckoutManager.js +115 -38
  71. package/lib/helper/devextremeCustomMessages.d.ts +30 -0
  72. package/lib/helper/devextremeCustomMessages.js +30 -0
  73. package/lib/helper/helpers.d.ts +2 -1
  74. package/lib/helper/helpers.js +14 -3
  75. package/lib/helper/index.d.ts +1 -0
  76. package/lib/helper/index.js +1 -0
  77. package/lib/helper/queryHelper.js +29 -0
  78. package/lib/hooks/useCheckInOutOperations.d.ts +28 -0
  79. package/lib/hooks/useCheckInOutOperations.js +223 -0
  80. package/lib/hooks/useWorkflowApprove.d.ts +4 -0
  81. package/lib/hooks/useWorkflowApprove.js +14 -1
  82. package/lib/ts/types.d.ts +56 -1
  83. package/package.json +5 -2
  84. package/lib/components/features/search/TMSearchResultCheckoutInfoForm.d.ts +0 -8
@@ -0,0 +1,2 @@
1
+ export { default } from './TMFloatingMenuBar';
2
+ export * from './types';
@@ -0,0 +1,2 @@
1
+ export { default } from './TMFloatingMenuBar';
2
+ export * from './types';
@@ -0,0 +1,51 @@
1
+ export declare const Overlay: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
2
+ $visible: boolean;
3
+ }>> & string;
4
+ export declare const FloatingContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("styled-components/dist/types").Substitute<import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
5
+ ref?: ((instance: HTMLDivElement | null) => void | import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import("react").RefObject<HTMLDivElement> | null | undefined;
6
+ }>, {
7
+ $x: number;
8
+ $y: number;
9
+ $orientation: "horizontal" | "vertical";
10
+ $isDragging: boolean;
11
+ $isConfigMode: boolean;
12
+ $isConstrained?: boolean;
13
+ }>, {
14
+ $x: number;
15
+ $y: number;
16
+ $orientation: "horizontal" | "vertical";
17
+ $isDragging: boolean;
18
+ $isConfigMode: boolean;
19
+ $isConstrained?: boolean;
20
+ }>> & string;
21
+ export declare const GripHandle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
22
+ $orientation: "horizontal" | "vertical";
23
+ }>> & string;
24
+ export declare const Separator: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
25
+ $orientation: "horizontal" | "vertical";
26
+ }>> & string;
27
+ export declare const ItemSeparator: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
28
+ $orientation: "horizontal" | "vertical";
29
+ $isConfigMode: boolean;
30
+ }>> & string;
31
+ export declare const MenuButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, {
32
+ $isActive?: boolean;
33
+ }>> & string;
34
+ export declare const ConfigButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
35
+ export declare const ApplyButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
36
+ export declare const ContextMenuButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<Omit<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "$isActive"> & {
37
+ $isActive?: boolean;
38
+ }, "ref"> & {
39
+ ref?: ((instance: HTMLButtonElement | null) => void | import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import("react").RefObject<HTMLButtonElement> | null | undefined;
40
+ }, never>> & string;
41
+ export declare const AddButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
42
+ export declare const RemoveButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
43
+ export declare const UndoButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
44
+ export declare const DraggableItem: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
45
+ $isDragging: boolean;
46
+ $isDragOver: boolean;
47
+ }>> & string;
48
+ export declare const ContextMenuWrapper: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
49
+ export declare const ButtonGroup: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
50
+ $orientation: "horizontal" | "vertical";
51
+ }>> & string;
@@ -0,0 +1,385 @@
1
+ import styled, { keyframes, css } from 'styled-components';
2
+ const fadeIn = keyframes `
3
+ from {
4
+ opacity: 0;
5
+ transform: scale(0.95);
6
+ }
7
+ to {
8
+ opacity: 1;
9
+ transform: scale(1);
10
+ }
11
+ `;
12
+ const shake = keyframes `
13
+ 0%, 100% { transform: translateX(0); }
14
+ 25% { transform: translateX(-2px); }
15
+ 75% { transform: translateX(2px); }
16
+ `;
17
+ export const Overlay = styled.div `
18
+ position: fixed;
19
+ top: 0;
20
+ left: 0;
21
+ right: 0;
22
+ bottom: 0;
23
+ background: rgba(255, 255, 255, 0.8);
24
+ z-index: 9998;
25
+ display: ${props => props.$visible ? 'block' : 'none'};
26
+ animation: ${fadeIn} 0.2s ease-out;
27
+ backdrop-filter: blur(2px);
28
+
29
+ [data-theme='dark'] & {
30
+ background: rgba(0, 0, 0, 0.8);
31
+ }
32
+ `;
33
+ export const FloatingContainer = styled.div.attrs(props => ({
34
+ style: {
35
+ left: `${props.$x}px`,
36
+ top: `${props.$y}px`,
37
+ },
38
+ })) `
39
+ position: ${props => props.$isConstrained ? 'absolute' : 'fixed'};
40
+ z-index: ${props => props.$isConfigMode ? 9999 : 10000};
41
+ display: flex;
42
+ flex-direction: ${props => props.$orientation === 'horizontal' ? 'row' : 'column'};
43
+ align-items: center;
44
+ background: linear-gradient(135deg, #0071BC 0%, #1B1464 100%);
45
+ border: 1px solid #667eea;
46
+ border-radius: 14px;
47
+ padding: 6px;
48
+ gap: 3px;
49
+ box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3),
50
+ 0 6px 16px rgba(0, 0, 0, 0.2);
51
+ cursor: ${props => props.$isDragging ? 'grabbing' : 'default'};
52
+ user-select: none;
53
+ animation: ${props => props.$isConfigMode && css `${shake} 0.3s ease-in-out`};
54
+ transition: none;
55
+
56
+ &:hover {
57
+ background: linear-gradient(135deg, #0071BC 0%, #1B1464 100%);
58
+ border: 1px solid #667eea;
59
+ box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3),
60
+ 0 6px 16px rgba(0, 0, 0, 0.2);
61
+ }
62
+
63
+ [data-theme='dark'] & {
64
+ background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
65
+ border: 1px solid #1a1a2e;
66
+
67
+ &:hover {
68
+ background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
69
+ border: 1px solid #1a1a2e;
70
+ }
71
+ }
72
+ `;
73
+ export const GripHandle = styled.div `
74
+ display: flex;
75
+ align-items: center;
76
+ justify-content: center;
77
+ padding: ${props => props.$orientation === 'horizontal' ? '10px 6px' : '6px 10px'};
78
+ cursor: grab;
79
+ color: rgba(255, 255, 255, 0.7);
80
+ transition: all 0.2s ease;
81
+ border-radius: 6px;
82
+
83
+ &:hover {
84
+ background: rgba(255, 255, 255, 0.1);
85
+ color: rgba(255, 255, 255, 1);
86
+ }
87
+
88
+ &:active {
89
+ cursor: grabbing;
90
+ background: rgba(255, 255, 255, 0.15);
91
+ }
92
+
93
+ svg {
94
+ width: 14px;
95
+ height: 14px;
96
+ }
97
+ `;
98
+ export const Separator = styled.div `
99
+ background: rgba(255, 255, 255, 0.25);
100
+ width: ${props => props.$orientation === 'horizontal' ? '1px' : '100%'};
101
+ height: ${props => props.$orientation === 'horizontal' ? '24px' : '1px'};
102
+ margin: ${props => props.$orientation === 'horizontal' ? '0 4px' : '4px 0'};
103
+ flex-shrink: 0;
104
+ `;
105
+ export const ItemSeparator = styled.div `
106
+ flex-shrink: 0;
107
+ transition: all 0.2s ease;
108
+
109
+ ${props => props.$isConfigMode ? `
110
+ /* Edit mode: look exactly like MenuButton */
111
+ display: flex;
112
+ align-items: center;
113
+ justify-content: center;
114
+ width: 34px;
115
+ height: 34px;
116
+ background: transparent;
117
+ border-radius: 8px;
118
+ cursor: grab;
119
+ position: relative;
120
+
121
+ &::before {
122
+ content: '';
123
+ background: rgba(255, 255, 255, 0.25);
124
+ width: ${props.$orientation === 'horizontal' ? '2px' : '100%'};
125
+ height: ${props.$orientation === 'horizontal' ? '20px' : '2px'};
126
+ border-radius: 1px;
127
+ }
128
+
129
+ &:hover {
130
+ background: rgba(255, 255, 255, 0.2);
131
+ }
132
+
133
+ &:active {
134
+ opacity: 0.8;
135
+ }
136
+ ` : `
137
+ /* Normal mode: simple line with tight spacing */
138
+ background: rgba(255, 255, 255, 0.25);
139
+ width: ${props.$orientation === 'horizontal' ? '1px' : '100%'};
140
+ height: ${props.$orientation === 'horizontal' ? '24px' : '1px'};
141
+ margin: ${props.$orientation === 'horizontal' ? '0 2px' : '2px 0'};
142
+ `}
143
+ `;
144
+ export const MenuButton = styled.button `
145
+ display: flex;
146
+ align-items: center;
147
+ justify-content: center;
148
+ width: 34px;
149
+ height: 34px;
150
+ background: transparent;
151
+ border: none;
152
+ border-radius: 8px;
153
+ color: white;
154
+ font-size: 16px;
155
+ cursor: pointer;
156
+ transition: background 0.2s ease;
157
+ position: relative;
158
+
159
+ &:hover:not(:disabled) {
160
+ background: rgba(255, 255, 255, 0.2);
161
+ }
162
+
163
+ &:active:not(:disabled) {
164
+ opacity: 0.8;
165
+ }
166
+
167
+ &:disabled {
168
+ opacity: 0.5;
169
+ cursor: default;
170
+ color: rgba(255, 255, 255, 0.6);
171
+ }
172
+
173
+ svg {
174
+ width: 18px;
175
+ height: 18px;
176
+ }
177
+ `;
178
+ export const ConfigButton = styled.button `
179
+ display: flex;
180
+ align-items: center;
181
+ justify-content: center;
182
+ width: 21px;
183
+ height: 21px;
184
+ background: transparent;
185
+ border: none;
186
+ border-radius: 4px;
187
+ color: rgba(255, 255, 255, 0.5);
188
+ font-size: 10px;
189
+ cursor: pointer;
190
+ transition: all 0.2s ease;
191
+ padding: 4px;
192
+
193
+ &:hover:not(:disabled) {
194
+ background: rgba(255, 255, 255, 0.1);
195
+ color: rgba(255, 255, 255, 0.8);
196
+ }
197
+
198
+ &:active:not(:disabled) {
199
+ transform: scale(0.9);
200
+ }
201
+
202
+ &:disabled {
203
+ opacity: 0.3;
204
+ cursor: not-allowed;
205
+ }
206
+
207
+ svg {
208
+ width: 16px;
209
+ height: 16px;
210
+ }
211
+ `;
212
+ export const ApplyButton = styled.button `
213
+ display: flex;
214
+ align-items: center;
215
+ justify-content: center;
216
+ width: 24px;
217
+ height: 24px;
218
+ background: transparent;
219
+ border: none;
220
+ border-radius: 4px;
221
+ color: rgba(34, 197, 94, 1);
222
+ font-size: 10px;
223
+ cursor: pointer;
224
+ transition: all 0.2s ease;
225
+ padding: 3px;
226
+
227
+ &:hover:not(:disabled) {
228
+ background: rgba(255, 255, 255, 0.1);
229
+ color: rgba(34, 197, 94, 1);
230
+ }
231
+
232
+ &:active:not(:disabled) {
233
+ transform: scale(0.9);
234
+ }
235
+
236
+ &:disabled {
237
+ opacity: 0.3;
238
+ cursor: default;
239
+ }
240
+
241
+ svg {
242
+ width: 20px;
243
+ height: 20px;
244
+ }
245
+ `;
246
+ export const ContextMenuButton = styled(MenuButton) `
247
+ svg {
248
+ transform: translateY(0);
249
+ }
250
+ `;
251
+ export const AddButton = styled.button `
252
+ display: flex;
253
+ align-items: center;
254
+ justify-content: center;
255
+ width: 28px;
256
+ height: 28px;
257
+ background: rgba(255, 255, 255, 0.15);
258
+ border: 1px dashed rgba(255, 255, 255, 0.4);
259
+ border-radius: 8px;
260
+ color: white;
261
+ font-size: 20px;
262
+ font-weight: bold;
263
+ line-height: 0;
264
+ cursor: pointer;
265
+ transition: all 0.2s ease;
266
+ position: relative;
267
+ margin-right: 6px;
268
+ margin-left: 8px;
269
+ padding: 0;
270
+
271
+ &:hover {
272
+ background: rgba(255, 255, 255, 0.25);
273
+ border-color: rgba(255, 255, 255, 0.6);
274
+ }
275
+
276
+ &:active {
277
+ transform: scale(0.95);
278
+ }
279
+ `;
280
+ export const RemoveButton = styled.button `
281
+ position: absolute;
282
+ top: -6px;
283
+ right: -6px;
284
+ width: 20px;
285
+ height: 20px;
286
+ background: #ef4444;
287
+ border: none;
288
+ border-radius: 50%;
289
+ color: white;
290
+ font-size: 14px;
291
+ font-weight: bold;
292
+ line-height: 0;
293
+ cursor: pointer;
294
+ display: flex;
295
+ align-items: center;
296
+ justify-content: center;
297
+ padding: 0;
298
+ transition: all 0.2s ease;
299
+ z-index: 1;
300
+
301
+ &:hover {
302
+ background: #dc2626;
303
+ }
304
+
305
+ &:active {
306
+ background: #b91c1c;
307
+ }
308
+ `;
309
+ export const UndoButton = styled.button `
310
+ display: flex;
311
+ align-items: center;
312
+ justify-content: center;
313
+ width: 24px;
314
+ height: 24px;
315
+ background: transparent;
316
+ border: none;
317
+ border-radius: 4px;
318
+ color: rgba(249, 115, 22, 1);
319
+ font-size: 10px;
320
+ cursor: pointer;
321
+ transition: all 0.2s ease;
322
+ padding: 2px;
323
+
324
+ &:hover:not(:disabled) {
325
+ background: rgba(255, 255, 255, 0.1);
326
+ color: rgba(249, 115, 22, 1);
327
+ }
328
+
329
+ &:active:not(:disabled) {
330
+ transform: scale(0.9);
331
+ }
332
+
333
+ &:disabled {
334
+ opacity: 0.3;
335
+ cursor: default;
336
+ }
337
+
338
+ svg {
339
+ width: 16px;
340
+ height: 16px;
341
+ }
342
+ `;
343
+ export const DraggableItem = styled.div `
344
+ position: relative;
345
+ opacity: ${props => props.$isDragging ? 0.3 : 1};
346
+ transform: ${props => {
347
+ if (props.$isDragging)
348
+ return 'scale(1.1) rotate(5deg)';
349
+ if (props.$isDragOver)
350
+ return 'scale(1.05)';
351
+ return 'scale(1)';
352
+ }};
353
+ transition: all 0.2s ease;
354
+ filter: ${props => props.$isDragging ? 'brightness(1.3)' : 'brightness(1)'};
355
+
356
+ ${props => props.$isDragging && css `
357
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
358
+ z-index: 100;
359
+ `}
360
+
361
+ ${props => props.$isDragOver && css `
362
+ &::before {
363
+ content: '';
364
+ position: absolute;
365
+ top: -4px;
366
+ left: 50%;
367
+ transform: translateX(-50%);
368
+ width: 40px;
369
+ height: 3px;
370
+ background: rgba(255, 255, 255, 0.8);
371
+ border-radius: 2px;
372
+ box-shadow: 0 0 8px rgba(255, 255, 255, 0.6);
373
+ }
374
+ `}
375
+ `;
376
+ export const ContextMenuWrapper = styled.div `
377
+ position: static;
378
+ display: contents;
379
+ `;
380
+ export const ButtonGroup = styled.div `
381
+ display: flex;
382
+ flex-direction: ${props => props.$orientation === 'vertical' ? 'column' : 'row'};
383
+ align-items: center;
384
+ gap: 0;
385
+ `;
@@ -0,0 +1,29 @@
1
+ import type { TMContextMenuItemProps } from '../ContextMenu';
2
+ export interface TMFloatingMenuItem {
3
+ id: string;
4
+ name: string;
5
+ icon: React.ReactNode;
6
+ onClick: () => void;
7
+ disabled?: boolean;
8
+ isPinned?: boolean;
9
+ isSeparator?: boolean;
10
+ }
11
+ export interface TMFloatingMenuBarProps {
12
+ containerRef: React.RefObject<HTMLElement | null>;
13
+ contextMenuItems?: TMContextMenuItemProps[];
14
+ isConstrained?: boolean;
15
+ defaultPosition?: Position;
16
+ maxItems?: number;
17
+ }
18
+ export interface Position {
19
+ x: number;
20
+ y: number;
21
+ }
22
+ export interface TMFloatingMenuBarState {
23
+ position: Position;
24
+ isDragging: boolean;
25
+ isConfigMode: boolean;
26
+ orientation: 'horizontal' | 'vertical';
27
+ items: TMFloatingMenuItem[];
28
+ draggedItemIndex: number | null;
29
+ }
@@ -1,9 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useState, useEffect, useCallback } from 'react';
3
3
  import styled from 'styled-components';
4
- import { ContextMenu, LoadIndicator } from 'devextreme-react';
4
+ import { LoadIndicator } from 'devextreme-react';
5
5
  import { LocalStorageService } from '@topconsultnpm/sdk-ts';
6
6
  import TMTooltip from './TMTooltip';
7
+ import TMContextMenu from '../NewComponents/ContextMenu/TMContextMenu';
7
8
  const Container = styled.div `
8
9
  width: 100%;
9
10
  height: 100%;
@@ -154,12 +155,15 @@ const DEFAULT_COLORS = ['#339af0', '#fa5252', '#40c057', '#f59f00', '#e64980', '
154
155
  const TMAccordion = ({ groups, localStorageKey, selectedItem, onSelectedItemChange }) => {
155
156
  const [openAccordions, setOpenAccordions] = useState({});
156
157
  const [isInitialized, setIsInitialized] = useState(false);
157
- const [anchorEl, setAnchorEl] = useState(null);
158
- const [contextMenuItems, setContextMenuItems] = useState([]);
159
158
  const [focusedItem, setFocusedItem] = useState(undefined);
159
+ // Item context menu state
160
+ const [itemContextMenuVisible, setItemContextMenuVisible] = useState(false);
161
+ const [itemContextMenuPosition, setItemContextMenuPosition] = useState({ x: 0, y: 0 });
162
+ const [itemContextMenuItems, setItemContextMenuItems] = useState([]);
163
+ // Header context menu state
160
164
  const [headerContextGroupId, setHeaderContextGroupId] = useState(null);
161
165
  const [headerContextVisible, setHeaderContextVisible] = useState(false);
162
- const [headerContextPosition, setHeaderContextPosition] = useState(null);
166
+ const [headerContextPosition, setHeaderContextPosition] = useState({ x: 0, y: 0 });
163
167
  useEffect(() => {
164
168
  const initialState = {};
165
169
  if (!groups || groups.length === 0) {
@@ -240,11 +244,21 @@ const TMAccordion = ({ groups, localStorageKey, selectedItem, onSelectedItemChan
240
244
  if (menuItems.length === 0) {
241
245
  return;
242
246
  }
243
- setAnchorEl(event.currentTarget);
244
- setContextMenuItems(menuItems);
247
+ // Convert to TMContextMenuItemProps format
248
+ const convertedItems = menuItems.map((mi) => ({
249
+ name: mi.text || mi.name || '',
250
+ // Only pass icon if it's a React element, not a string (DevExtreme used string icons)
251
+ icon: typeof mi.icon === 'string' ? undefined : mi.icon,
252
+ disabled: mi.disabled,
253
+ onClick: mi.onClick,
254
+ submenu: mi.items || mi.submenu,
255
+ }));
256
+ setItemContextMenuPosition({ x: event.clientX, y: event.clientY });
257
+ setItemContextMenuItems(convertedItems);
258
+ setItemContextMenuVisible(true);
245
259
  };
246
260
  const closeContextMenu = useCallback(() => {
247
- setAnchorEl(null);
261
+ setItemContextMenuVisible(false);
248
262
  }, []);
249
263
  const handleHeaderContextMenu = (event, groupId) => {
250
264
  event.preventDefault();
@@ -260,12 +274,11 @@ const TMAccordion = ({ groups, localStorageKey, selectedItem, onSelectedItemChan
260
274
  };
261
275
  const closeHeaderContextMenu = useCallback(() => {
262
276
  setHeaderContextVisible(false);
263
- setHeaderContextPosition(null);
264
277
  setHeaderContextGroupId(null);
265
278
  }, []);
266
279
  const headerContextMenuItems = headerContextGroupId ? [
267
280
  {
268
- text: openAccordions[headerContextGroupId] ? 'Collassa' : 'Espandi',
281
+ name: openAccordions[headerContextGroupId] ? 'Collassa' : 'Espandi',
269
282
  onClick: () => {
270
283
  toggleAccordion(headerContextGroupId);
271
284
  closeHeaderContextMenu();
@@ -295,19 +308,19 @@ const TMAccordion = ({ groups, localStorageKey, selectedItem, onSelectedItemChan
295
308
  const color = getGroupColor(group, index);
296
309
  const isOpen = openAccordions[group.id] ?? true;
297
310
  if (group.customComponent) {
298
- return (_jsxs(AccordionItem, { children: [_jsxs(AccordionHeader, { "$color": color, "$isOpen": isOpen, onClick: (e) => handleHeaderClick(e, group.id), onContextMenu: (e) => handleHeaderContextMenu(e, group.id), children: [_jsxs(AccordionTitle, { children: [group.icon, _jsx(TitleText, { children: group.title })] }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '10px' }, children: [renderBadges(group, color), _jsx(ToggleIcon, { "$isOpen": isOpen, children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: _jsx("path", { d: "M4 6L8 10L12 6", stroke: "#495057", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) })] })] }), isOpen && (_jsx(CustomComponentContainer, { children: group.customComponent }))] }, group.id));
311
+ return (_jsxs(AccordionItem, { children: [_jsxs(AccordionHeader, { id: `accordion-header-${group.id}`, "$color": color, "$isOpen": isOpen, onClick: (e) => handleHeaderClick(e, group.id), onContextMenu: (e) => handleHeaderContextMenu(e, group.id), children: [_jsxs(AccordionTitle, { children: [group.icon, _jsx(TitleText, { children: group.title })] }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '10px' }, children: [renderBadges(group, color), _jsx(ToggleIcon, { "$isOpen": isOpen, children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: _jsx("path", { d: "M4 6L8 10L12 6", stroke: "#495057", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) })] })] }), isOpen && (_jsx(CustomComponentContainer, { children: group.customComponent }))] }, group.id));
299
312
  }
300
313
  if (!group.dataSource || group.dataSource.length === 0)
301
314
  return null;
302
315
  if (!group.renderItem) {
303
- return (_jsxs(AccordionItem, { children: [_jsxs(AccordionHeader, { "$color": color, "$isOpen": isOpen, onClick: (e) => handleHeaderClick(e, group.id), onContextMenu: (e) => handleHeaderContextMenu(e, group.id), children: [_jsxs(AccordionTitle, { children: [group.icon, _jsx(TitleText, { children: group.title })] }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '10px' }, children: [renderBadges(group, color), _jsx(ToggleIcon, { "$isOpen": isOpen, children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: _jsx("path", { d: "M4 6L8 10L12 6", stroke: "#495057", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) })] })] }), _jsx(AccordionContent, { "$isOpen": isOpen, "$maxHeight": 100, children: _jsxs(ErrorMessage, { children: ["\u26A0\uFE0F renderItem function is required for \"", group.title, "\" group"] }) })] }, group.id));
316
+ return (_jsxs(AccordionItem, { children: [_jsxs(AccordionHeader, { id: `accordion-header-${group.id}`, "$color": color, "$isOpen": isOpen, onClick: (e) => handleHeaderClick(e, group.id), onContextMenu: (e) => handleHeaderContextMenu(e, group.id), children: [_jsxs(AccordionTitle, { children: [group.icon, _jsx(TitleText, { children: group.title })] }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '10px' }, children: [renderBadges(group, color), _jsx(ToggleIcon, { "$isOpen": isOpen, children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: _jsx("path", { d: "M4 6L8 10L12 6", stroke: "#495057", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) })] })] }), _jsx(AccordionContent, { "$isOpen": isOpen, "$maxHeight": 100, children: _jsxs(ErrorMessage, { children: ["\u26A0\uFE0F renderItem function is required for \"", group.title, "\" group"] }) })] }, group.id));
304
317
  }
305
318
  const itemHeight = group.itemHeight || 80;
306
319
  const maxHeight = group.dataSource.length * itemHeight + 20;
307
- return (_jsxs(AccordionItem, { children: [_jsxs(AccordionHeader, { "$color": color, "$isOpen": isOpen, onClick: (e) => handleHeaderClick(e, group.id), onContextMenu: (e) => handleHeaderContextMenu(e, group.id), children: [_jsxs(AccordionTitle, { children: [group.icon, _jsx(TitleText, { children: group.title })] }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '10px' }, children: [renderBadges(group, color), _jsx(ToggleIcon, { "$isOpen": isOpen, children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: _jsx("path", { d: "M4 6L8 10L12 6", stroke: "#495057", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) })] })] }), _jsx(AccordionContent, { "$isOpen": isOpen, "$maxHeight": maxHeight, children: _jsx(ItemsList, { children: group.dataSource.map((item, itemIndex) => {
320
+ return (_jsxs(AccordionItem, { children: [_jsxs(AccordionHeader, { id: `accordion-header-${group.id}`, "$color": color, "$isOpen": isOpen, onClick: (e) => handleHeaderClick(e, group.id), onContextMenu: (e) => handleHeaderContextMenu(e, group.id), children: [_jsxs(AccordionTitle, { children: [group.icon, _jsx(TitleText, { children: group.title })] }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '10px' }, children: [renderBadges(group, color), _jsx(ToggleIcon, { "$isOpen": isOpen, children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: _jsx("path", { d: "M4 6L8 10L12 6", stroke: "#495057", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) })] })] }), _jsx(AccordionContent, { "$isOpen": isOpen, "$maxHeight": maxHeight, children: _jsx(ItemsList, { children: group.dataSource.map((item, itemIndex) => {
308
321
  const isSelected = selectedItem === item;
309
322
  const isFocused = focusedItem === item;
310
- return (_jsx(ListItem, { "$isSelected": isSelected, "$color": color, onClick: () => handleItemClick(item, group), onDoubleClick: () => handleItemDoubleClick(item, group), onMouseEnter: () => setFocusedItem(item), onMouseLeave: () => setFocusedItem(undefined), onContextMenu: (e) => handleContextMenu(e, item, group), children: group.renderItem(item, isSelected, isFocused, color) }, itemIndex * 2));
323
+ return (_jsx(ListItem, { id: `accordion-item-${group.id}-${itemIndex}`, className: "tm-accordion-list-item", "$isSelected": isSelected, "$color": color, onClick: () => handleItemClick(item, group), onDoubleClick: () => handleItemDoubleClick(item, group), onMouseEnter: () => setFocusedItem(item), onMouseLeave: () => setFocusedItem(undefined), onContextMenu: (e) => handleContextMenu(e, item, group), children: group.renderItem(item, isSelected, isFocused, color) }, itemIndex * 2));
311
324
  }) }) })] }, group.id));
312
325
  };
313
326
  if (!isInitialized) {
@@ -321,6 +334,14 @@ const TMAccordion = ({ groups, localStorageKey, selectedItem, onSelectedItemChan
321
334
  event.preventDefault();
322
335
  }
323
336
  };
324
- return (_jsxs(_Fragment, { children: [_jsx(Container, { onContextMenu: handleContainerContextMenu, children: groups.map((group, index) => renderAccordion(group, index)) }), anchorEl && contextMenuItems.length > 0 && (_jsx(ContextMenu, { dataSource: contextMenuItems, target: anchorEl, onHiding: closeContextMenu })), headerContextPosition && headerContextMenuItems.length > 0 && (_jsx(ContextMenu, { dataSource: headerContextMenuItems, visible: headerContextVisible, position: { my: 'left top', at: 'left top', offset: `${headerContextPosition.x} ${headerContextPosition.y}` }, onHiding: closeHeaderContextMenu }))] }));
337
+ return (_jsxs(_Fragment, { children: [_jsx(Container, { onContextMenu: handleContainerContextMenu, children: groups.map((group, index) => renderAccordion(group, index)) }), _jsx(TMContextMenu, { items: itemContextMenuItems, target: ".tm-accordion-list-item", externalControl: {
338
+ visible: itemContextMenuVisible,
339
+ position: itemContextMenuPosition,
340
+ onClose: closeContextMenu
341
+ } }), _jsx(TMContextMenu, { items: headerContextMenuItems, target: "[id^='accordion-header-']", externalControl: {
342
+ visible: headerContextVisible,
343
+ position: headerContextPosition,
344
+ onClose: closeHeaderContextMenu
345
+ } })] }));
325
346
  };
326
347
  export default TMAccordion;