@topconsultnpm/sdkui-react 6.22.0-dev4.4 → 6.22.0-dev4.6

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 (123) hide show
  1. package/lib/components/NewComponents/ContextMenu/styles.d.ts +45 -43
  2. package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +67 -60
  3. package/lib/components/base/Styled.d.ts +93 -77
  4. package/lib/components/base/TMCounterBar.d.ts +2 -2
  5. package/lib/components/base/TMCounterContainer.d.ts +5 -2
  6. package/lib/components/base/TMCounterContainer.js +16 -1
  7. package/lib/components/base/TMCustomButton.d.ts +1 -1
  8. package/lib/components/base/TMDataGrid.js +243 -223
  9. package/lib/components/base/TMDataGridExportForm.d.ts +2 -1
  10. package/lib/components/base/TMFileManager.d.ts +2 -1
  11. package/lib/components/base/TMFileManagerDataGridView.d.ts +2 -1
  12. package/lib/components/base/TMFileManagerThumbnailItems.d.ts +1 -1
  13. package/lib/components/base/TMFileManagerThumbnailsView.d.ts +1 -1
  14. package/lib/components/base/TMFileManagerUtils.d.ts +4 -6
  15. package/lib/components/base/TMLayout.d.ts +4 -4
  16. package/lib/components/base/TMList.d.ts +2 -1
  17. package/lib/components/base/TMListView.d.ts +1 -1
  18. package/lib/components/base/TMSpinner.d.ts +3 -2
  19. package/lib/components/base/TMTab.d.ts +4 -3
  20. package/lib/components/base/TMTabControl.js +208 -208
  21. package/lib/components/base/TMTooltip.d.ts +1 -1
  22. package/lib/components/base/TMTreeView.d.ts +14 -8
  23. package/lib/components/base/TMUserAvatar.d.ts +2 -1
  24. package/lib/components/base/TMVilViewer.d.ts +2 -1
  25. package/lib/components/base/TMWaitPanel.d.ts +3 -2
  26. package/lib/components/base/waitPanel/TMWaitPanelManager.d.ts +16 -6
  27. package/lib/components/base/waitPanel/TMWaitPanelManager.js +55 -2
  28. package/lib/components/base/waitPanel/TMWaitPanelView.d.ts +7 -1
  29. package/lib/components/base/waitPanel/TMWaitPanelView.js +257 -185
  30. package/lib/components/choosers/TMDistinctValues.js +3 -3
  31. package/lib/components/choosers/TMDynDataListItemChooser.d.ts +1 -1
  32. package/lib/components/choosers/TMInvoiceRetrieveFormats.d.ts +2 -1
  33. package/lib/components/choosers/TMOrderRetrieveFormats.d.ts +2 -1
  34. package/lib/components/choosers/TMQuickSearchInfo.d.ts +2 -1
  35. package/lib/components/choosers/TMRelationChooser.d.ts +3 -3
  36. package/lib/components/choosers/TMUserChooser.d.ts +2 -2
  37. package/lib/components/editors/TMEditorStyled.d.ts +20 -42
  38. package/lib/components/editors/TMFormulaEditor.d.ts +1 -1
  39. package/lib/components/editors/TMHtmlContentDisplay.d.ts +2 -1
  40. package/lib/components/editors/TMHtmlEditor.d.ts +2 -1
  41. package/lib/components/editors/TMTreeDropDown.d.ts +1 -1
  42. package/lib/components/features/assistant/TMToppyDraggableHelpCenter.d.ts +1 -1
  43. package/lib/components/features/blog/TMBlogCommentForm.d.ts +2 -1
  44. package/lib/components/features/documents/TMDcmtFormActionButtons.d.ts +1 -1
  45. package/lib/components/features/documents/TMDcmtIcon.d.ts +2 -1
  46. package/lib/components/features/documents/TMDcmtPreview.d.ts +8 -6
  47. package/lib/components/features/documents/TMDcmtTasks.d.ts +2 -1
  48. package/lib/components/features/documents/TMDragDropOverlay.d.ts +1 -1
  49. package/lib/components/features/documents/TMFileUploader.js +21 -21
  50. package/lib/components/features/documents/TMMasterInfoFields.d.ts +2 -1
  51. package/lib/components/features/documents/TMMergeToPdfForm.d.ts +2 -1
  52. package/lib/components/features/documents/TMMergeToPdfForm.js +5 -4
  53. package/lib/components/features/documents/TMMultiMasterDetailDcmtsForm.d.ts +2 -1
  54. package/lib/components/features/documents/TMMultiMasterDetailDcmtsUtils.d.ts +4 -4
  55. package/lib/components/features/search/TMDcmtCheckoutInfoForm.d.ts +2 -1
  56. package/lib/components/features/search/TMMetadataOutputForm.d.ts +2 -1
  57. package/lib/components/features/search/TMMetadataSorterForm.d.ts +2 -1
  58. package/lib/components/features/search/TMSavedQuerySelector.d.ts +2 -2
  59. package/lib/components/features/search/TMSearch.d.ts +2 -1
  60. package/lib/components/features/search/TMSearchQueryPanel.d.ts +9 -3
  61. package/lib/components/features/search/TMSearchResult.js +7 -8
  62. package/lib/components/features/search/TMSearchResultFloatingActionButton.d.ts +1 -1
  63. package/lib/components/features/search/TMSignatureInfoContent.d.ts +2 -1
  64. package/lib/components/features/search/TMViewHistoryDcmt.d.ts +2 -1
  65. package/lib/components/features/search/TMViewHistoryDcmt.js +1 -1
  66. package/lib/components/features/tasks/TMTaskForm.d.ts +1 -1
  67. package/lib/components/features/tasks/TMTaskFormUtils.d.ts +10 -10
  68. package/lib/components/features/tasks/TMTasksAgenda.d.ts +1 -1
  69. package/lib/components/features/tasks/TMTasksCalendar.d.ts +1 -1
  70. package/lib/components/features/tasks/TMTasksHeader.d.ts +1 -1
  71. package/lib/components/features/tasks/TMTasksPanelContent.d.ts +1 -1
  72. package/lib/components/features/tasks/TMTasksUtilsView.d.ts +5 -5
  73. package/lib/components/features/tasks/TMTasksView.d.ts +1 -1
  74. package/lib/components/features/tasks/TMTasksView.js +15 -9
  75. package/lib/components/features/wg/TMWGsCopyMoveForm.d.ts +3 -2
  76. package/lib/components/features/wg/TMWGsCopyMoveForm.js +17 -13
  77. package/lib/components/features/workflow/TMWorkflowPopup.d.ts +8 -7
  78. package/lib/components/features/workflow/diagram/WorkitemRecipientsEditor.d.ts +3 -1
  79. package/lib/components/forms/Login/ChangePasswordInputs.d.ts +3 -1
  80. package/lib/components/forms/Login/Chooser.d.ts +2 -2
  81. package/lib/components/forms/TMChooserForm.d.ts +2 -1
  82. package/lib/components/forms/TMSaveForm.d.ts +4 -4
  83. package/lib/components/grids/TMBlogAttachments.d.ts +2 -1
  84. package/lib/components/grids/TMBlogHeader.d.ts +1 -1
  85. package/lib/components/grids/TMBlogsPost.d.ts +1 -1
  86. package/lib/components/grids/TMBlogsPost.js +1 -1
  87. package/lib/components/grids/TMBlogsPostUtils.d.ts +9 -9
  88. package/lib/components/grids/TMValidationItemsList.d.ts +2 -1
  89. package/lib/components/layout/panelManager/TMPanelManagerContainer.d.ts +2 -1
  90. package/lib/components/layout/panelManager/TMPanelManagerContainer.js +12 -12
  91. package/lib/components/layout/panelManager/TMPanelManagerContext.d.ts +2 -2
  92. package/lib/components/layout/panelManager/TMPanelManagerLoader.d.ts +2 -1
  93. package/lib/components/layout/panelManager/TMPanelManagerToolbar.d.ts +5 -6
  94. package/lib/components/layout/panelManager/TMPanelManagerWithPersistenceProvider.d.ts +2 -2
  95. package/lib/components/layout/panelManager/TMPanelWrapper.d.ts +2 -2
  96. package/lib/components/pages/TMPage.d.ts +1 -1
  97. package/lib/components/pages/TMPage.js +7 -4
  98. package/lib/components/query/TMQueryEditor.d.ts +14 -10
  99. package/lib/components/settings/SettingsAppearance.d.ts +2 -1
  100. package/lib/components/sidebar/TMAboutApp.d.ts +2 -1
  101. package/lib/components/sidebar/TMCommandsPanel.d.ts +4 -4
  102. package/lib/components/sidebar/TMHeader.d.ts +3 -3
  103. package/lib/components/viewers/TMDataListItemViewer.d.ts +3 -2
  104. package/lib/components/viewers/TMDataUserIdItemViewer.d.ts +3 -2
  105. package/lib/components/viewers/TMMidViewer.d.ts +2 -2
  106. package/lib/components/viewers/TMTidViewer.d.ts +2 -2
  107. package/lib/helper/SDKUI_Globals.d.ts +3 -4
  108. package/lib/helper/SDKUI_Globals.js +3 -4
  109. package/lib/helper/SDKUI_Localizator.d.ts +8 -4
  110. package/lib/helper/SDKUI_Localizator.js +77 -37
  111. package/lib/helper/TMAppUpdatedModal.d.ts +2 -1
  112. package/lib/helper/TMAppUpdatedModal.js +93 -93
  113. package/lib/helper/TMCommandsContextMenu.d.ts +1 -1
  114. package/lib/helper/TMIcons.d.ts +280 -280
  115. package/lib/helper/TMPdfViewer.d.ts +2 -1
  116. package/lib/helper/TMToppyMessage.d.ts +2 -2
  117. package/lib/helper/TMUtils.d.ts +10 -4
  118. package/lib/helper/helpers.d.ts +1 -1
  119. package/lib/hooks/useDcmtOperations.js +23 -14
  120. package/lib/hooks/useInputDialog.d.ts +2 -1
  121. package/lib/hooks/useMultiMasterDetailDcmts.js +10 -6
  122. package/lib/services/platform_services.d.ts +3 -2
  123. package/package.json +1 -1
@@ -4,6 +4,12 @@ import { SDKUI_Localizator } from '../../../helper';
4
4
  import TMWaitPanelView from './TMWaitPanelView';
5
5
  const Z_INDEX_BASE = 2147483601;
6
6
  const RESOLVED = Promise.resolve();
7
+ /** Accumula un messaggio in testa, tenendo solo quelli visibili nel popover. */
8
+ const pushMessage = (list, message, max) => {
9
+ list.unshift(message);
10
+ if (list.length > max)
11
+ list.length = max;
12
+ };
7
13
  const pad2 = (n) => (n < 10 ? '0' + n : String(n));
8
14
  /** Formatta una durata in millisecondi come "42s", "3m 07s", "1h 12m". */
9
15
  const formatDuration = (ms) => {
@@ -37,6 +43,11 @@ class TMWaitPanelInstance {
37
43
  this._error = 0;
38
44
  this._secondaryValue = 0;
39
45
  this._secondaryMax = 0;
46
+ this._warningMessages = [];
47
+ this._errorMessages = [];
48
+ this.warningMessageTotal = 0;
49
+ this.errorMessageTotal = 0;
50
+ this.messagesDirty = false;
40
51
  // Ultimi valori scritti sul DOM: servono a non riscrivere testo identico.
41
52
  this.lastPercentText = '';
42
53
  this.lastSubtitleText = '';
@@ -55,8 +66,24 @@ class TMWaitPanelInstance {
55
66
  this.setTitle = (title) => { this._title = title; this.schedule(); };
56
67
  this.setSubtitle = (subtitle) => { this._subtitleOverride = subtitle; this.schedule(); };
57
68
  this.ok = (delta = 1) => { this._ok += delta; this.schedule(); };
58
- this.warning = (delta = 1) => { this._warning += delta; this.schedule(); };
59
- this.error = (delta = 1) => { this._error += delta; this.schedule(); };
69
+ this.warning = (delta = 1, message) => {
70
+ this._warning += delta;
71
+ if (message) {
72
+ pushMessage(this._warningMessages, message, this.maxVisibleMessages);
73
+ this.warningMessageTotal++;
74
+ this.messagesDirty = true;
75
+ }
76
+ this.schedule();
77
+ };
78
+ this.error = (delta = 1, message) => {
79
+ this._error += delta;
80
+ if (message) {
81
+ pushMessage(this._errorMessages, message, this.maxVisibleMessages);
82
+ this.errorMessageTotal++;
83
+ this.messagesDirty = true;
84
+ }
85
+ this.schedule();
86
+ };
60
87
  this.setSecondary = (patch) => {
61
88
  if (patch.value !== undefined)
62
89
  this._secondaryValue = patch.value;
@@ -210,12 +237,18 @@ class TMWaitPanelInstance {
210
237
  this.lastError = this._error;
211
238
  nodes.errorValue.textContent = String(this._error);
212
239
  }
240
+ if (this.messagesDirty) {
241
+ this.messagesDirty = false;
242
+ this.flushMessages(nodes.warningPopover, nodes.warningList, this._warningMessages, this.warningMessageTotal);
243
+ this.flushMessages(nodes.errorPopover, nodes.errorList, this._errorMessages, this.errorMessageTotal);
244
+ }
213
245
  if (nodes.secondaryFill)
214
246
  this.flushSecondary(nodes);
215
247
  if (this.options.showEta ?? true)
216
248
  this.flushEta(nodes, ratio);
217
249
  };
218
250
  this.options = options;
251
+ this.maxVisibleMessages = Math.max(1, options.maxVisibleMessages ?? 5);
219
252
  this._max = options.max ?? 0;
220
253
  this._title = options.title ?? '';
221
254
  this._secondaryText = options.secondaryText ?? '';
@@ -256,6 +289,26 @@ class TMWaitPanelInstance {
256
289
  return template.replace('{{0}}', String(this._value)).replace('{{1}}', String(this._max));
257
290
  return this.options.subtitle ?? '';
258
291
  }
292
+ /** Riscrive la lista di un popover con gli ultimi messaggi e la riga "... e altri N". Il popover si apre solo se non e' vuoto. */
293
+ flushMessages(popover, list, messages, total) {
294
+ if (total === 0)
295
+ return;
296
+ const visible = messages.length;
297
+ const items = [];
298
+ for (let i = 0; i < visible; i++) {
299
+ const item = document.createElement('li');
300
+ item.textContent = messages[i];
301
+ items.push(item);
302
+ }
303
+ if (total > visible) {
304
+ const more = document.createElement('li');
305
+ more.className = 'tm-wait-panel-more';
306
+ more.textContent = SDKUI_Localizator.AndOthersCount.replace('{{0}}', String(total - visible));
307
+ items.push(more);
308
+ }
309
+ list.replaceChildren(...items);
310
+ popover.dataset.empty = 'false';
311
+ }
259
312
  /** Riversa sul DOM la seconda barra. Invocata solo quando la view l'ha renderizzata. */
260
313
  flushSecondary(nodes) {
261
314
  const ratio = this._secondaryMax > 0 ? Math.min(1, Math.max(0, this._secondaryValue / this._secondaryMax)) : 0;
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  /** Guscio statico del wait panel: montato una sola volta e mai ri-renderizzato, il manager lo aggiorna via DOM. Le props sono valori iniziali. */
2
3
  /** Nodi DOM mutabili di cui il manager ha bisogno per aggiornare il pannello senza React. */
3
4
  export interface ITMWaitPanelNodes {
@@ -12,6 +13,11 @@ export interface ITMWaitPanelNodes {
12
13
  okValue: HTMLElement;
13
14
  warningValue: HTMLElement;
14
15
  errorValue: HTMLElement;
16
+ /** Popover delle pill: il manager riempie la lista e toglie `data-empty` al primo messaggio. */
17
+ warningPopover: HTMLElement;
18
+ warningList: HTMLElement;
19
+ errorPopover: HTMLElement;
20
+ errorList: HTMLElement;
15
21
  abortButton: HTMLButtonElement | null;
16
22
  /** Presenti solo con `showSecondary`: riga di avanzamento dell'operazione di dettaglio. */
17
23
  secondaryText: HTMLElement | null;
@@ -48,5 +54,5 @@ export interface ITMWaitPanelViewProps {
48
54
  /** Invocato dopo il commit con i nodi DOM da aggiornare imperativamente. */
49
55
  onMount?: (nodes: ITMWaitPanelNodes) => void;
50
56
  }
51
- declare const TMWaitPanelView: ({ title, subtitle, cancelable, showEta, showCounters, showSecondary, secondaryText, primaryLabel, secondaryLabel, zIndex, onAbort, onConfirmYes, onConfirmNo, onMount }: ITMWaitPanelViewProps) => import("react/jsx-runtime").JSX.Element;
57
+ declare const TMWaitPanelView: ({ title, subtitle, cancelable, showEta, showCounters, showSecondary, secondaryText, primaryLabel, secondaryLabel, zIndex, onAbort, onConfirmYes, onConfirmNo, onMount }: ITMWaitPanelViewProps) => React.JSX.Element;
52
58
  export default TMWaitPanelView;
@@ -14,215 +14,245 @@ const getProgressColor = () => {
14
14
  catch { /* nessuna sessione: resta il default */ }
15
15
  return getAppModuleButtonColors(appModuleID).base;
16
16
  };
17
- const fadeIn = keyframes `
18
- from { opacity: 0; }
19
- to { opacity: 1; }
17
+ const fadeIn = keyframes `
18
+ from { opacity: 0; }
19
+ to { opacity: 1; }
20
20
  `;
21
21
  // Sfondo su uno pseudo-elemento: il layer composito dell'animazione sgranerebbe Toppy.
22
- const StyledOverlay = styled.div `
23
- position: fixed;
24
- inset: 0;
25
- z-index: ${props => props.$zIndex};
26
-
27
- &::before {
28
- content: '';
29
- position: absolute;
30
- inset: 0;
31
- background-color: rgba(17, 24, 39, 0.16);
32
- animation: ${fadeIn} 140ms ease-out;
33
- }
22
+ const StyledOverlay = styled.div `
23
+ position: fixed;
24
+ inset: 0;
25
+ z-index: ${props => props.$zIndex};
26
+
27
+ &::before {
28
+ content: '';
29
+ position: absolute;
30
+ inset: 0;
31
+ background-color: rgba(17, 24, 39, 0.16);
32
+ animation: ${fadeIn} 140ms ease-out;
33
+ }
34
34
  `;
35
- const StyledCard = styled.div `
36
- position: absolute;
37
- top: 50%;
38
- left: 50%;
39
- transform: translate(-50%, -50%);
40
- width: 420px;
41
- max-width: calc(100% - 24px);
42
- max-height: calc(100% - 24px);
43
- overflow-y: auto;
44
- box-sizing: border-box;
45
- padding: 22px 24px 18px 24px;
46
- background: #ffffff;
47
- border-radius: 16px;
48
- box-shadow: 0 18px 48px rgba(16, 24, 40, 0.22);
49
- font-family: inherit;
35
+ const StyledCard = styled.div `
36
+ position: absolute;
37
+ top: 50%;
38
+ left: 50%;
39
+ transform: translate(-50%, -50%);
40
+ width: 420px;
41
+ max-width: calc(100% - 24px);
42
+ max-height: calc(100% - 24px);
43
+ overflow-y: auto;
44
+ box-sizing: border-box;
45
+ padding: 22px 24px 18px 24px;
46
+ background: #ffffff;
47
+ border-radius: 16px;
48
+ box-shadow: 0 18px 48px rgba(16, 24, 40, 0.22);
49
+ font-family: inherit;
50
50
  `;
51
- const StyledHeader = styled.div `
52
- display: flex;
53
- flex-direction: row;
54
- align-items: center;
55
- gap: 16px;
51
+ const StyledHeader = styled.div `
52
+ display: flex;
53
+ flex-direction: row;
54
+ align-items: center;
55
+ gap: 16px;
56
56
  `;
57
57
  // Ritaglio dal contenitore, non object-fit: cover darebbe un'altezza frazionaria e sgranerebbe l'immagine.
58
- const StyledToppyClip = styled.div `
59
- height: 61px;
60
- width: 68px;
61
- overflow: hidden;
62
- flex: 0 0 auto;
58
+ const StyledToppyClip = styled.div `
59
+ height: 61px;
60
+ width: 68px;
61
+ overflow: hidden;
62
+ flex: 0 0 auto;
63
63
  `;
64
- const StyledToppy = styled.img `
65
- display: block;
66
- width: 68px;
67
- height: 79px;
68
- user-select: none;
69
- -webkit-user-drag: none;
64
+ const StyledToppy = styled.img `
65
+ display: block;
66
+ width: 68px;
67
+ height: 79px;
68
+ user-select: none;
69
+ -webkit-user-drag: none;
70
70
  `;
71
- const StyledHeaderText = styled.div `
72
- flex: 1;
73
- min-width: 0;
71
+ const StyledHeaderText = styled.div `
72
+ flex: 1;
73
+ min-width: 0;
74
74
  `;
75
- const StyledTitle = styled.div `
76
- font-size: 17px;
77
- font-weight: 600;
78
- color: #1f2937;
79
- line-height: 1.3;
80
- overflow-wrap: anywhere;
75
+ const StyledTitle = styled.div `
76
+ font-size: 17px;
77
+ font-weight: 600;
78
+ color: #1f2937;
79
+ line-height: 1.3;
80
+ overflow-wrap: anywhere;
81
81
  `;
82
- const StyledSubtitle = styled.div `
83
- margin-top: 3px;
84
- font-size: 13px;
85
- color: #6b7280;
86
- line-height: 1.3;
87
- font-variant-numeric: tabular-nums;
88
- overflow-wrap: anywhere;
82
+ const StyledSubtitle = styled.div `
83
+ margin-top: 3px;
84
+ font-size: 13px;
85
+ color: #6b7280;
86
+ line-height: 1.3;
87
+ font-variant-numeric: tabular-nums;
88
+ overflow-wrap: anywhere;
89
89
  `;
90
90
  // Didascalia di una barra: con due avanzamenti e' l'unica cosa che dice quale sia quale.
91
- const StyledBarLabel = styled.div `
92
- margin-top: 18px;
93
- font-size: 11px;
94
- font-weight: 700;
95
- letter-spacing: 0.04em;
96
- text-transform: uppercase;
97
- color: #9aa3b2;
98
- overflow: hidden;
99
- text-overflow: ellipsis;
100
- white-space: nowrap;
91
+ const StyledBarLabel = styled.div `
92
+ margin-top: 18px;
93
+ font-size: 11px;
94
+ font-weight: 700;
95
+ letter-spacing: 0.04em;
96
+ text-transform: uppercase;
97
+ color: #9aa3b2;
98
+ overflow: hidden;
99
+ text-overflow: ellipsis;
100
+ white-space: nowrap;
101
+ `;
102
+ const StyledPercentRow = styled.div `
103
+ display: flex;
104
+ flex-direction: row;
105
+ align-items: flex-end;
106
+ justify-content: space-between;
107
+ flex-wrap: wrap;
108
+ gap: 8px 12px;
109
+ margin-top: ${props => (props.$hasLabel ? '4px' : '18px')};
110
+ `;
111
+ const StyledPercent = styled.div `
112
+ font-size: 34px;
113
+ font-weight: 700;
114
+ color: #111827;
115
+ line-height: 1;
116
+ font-variant-numeric: tabular-nums;
101
117
  `;
102
- const StyledPercentRow = styled.div `
103
- display: flex;
104
- flex-direction: row;
105
- align-items: flex-end;
106
- justify-content: space-between;
107
- flex-wrap: wrap;
108
- gap: 8px 12px;
109
- margin-top: ${props => (props.$hasLabel ? '4px' : '18px')};
118
+ const StyledCounters = styled.div `
119
+ display: flex;
120
+ flex-direction: row;
121
+ align-items: center;
122
+ gap: 6px;
123
+ padding-bottom: 3px;
110
124
  `;
111
- const StyledPercent = styled.div `
112
- font-size: 34px;
113
- font-weight: 700;
114
- color: #111827;
115
- line-height: 1;
116
- font-variant-numeric: tabular-nums;
125
+ const StyledPill = styled.span `
126
+ display: inline-flex;
127
+ flex-direction: row;
128
+ align-items: center;
129
+ gap: 4px;
130
+ padding: 2px 8px 2px 6px;
131
+ border-radius: 999px;
132
+ font-size: 12px;
133
+ font-weight: 600;
134
+ line-height: 18px;
135
+ color: ${props => props.$color};
136
+ background: ${props => props.$background};
137
+ font-variant-numeric: tabular-nums;
138
+
139
+ svg { flex: 0 0 auto; }
117
140
  `;
118
- const StyledCounters = styled.div `
119
- display: flex;
120
- flex-direction: row;
121
- align-items: center;
122
- gap: 6px;
123
- padding-bottom: 3px;
141
+ // Fratello della card, non figlio: l'overflow della card lo taglierebbe. Coordinate dell'overlay, calcolate all'apertura.
142
+ const StyledPopover = styled.div `
143
+ display: none;
144
+ position: absolute;
145
+ width: 320px;
146
+ max-width: calc(100% - 24px);
147
+ overflow-y: auto;
148
+ box-sizing: border-box;
149
+ padding: 10px 12px;
150
+ background: #ffffff;
151
+ border-left: 3px solid ${props => props.$accent};
152
+ border-radius: 10px;
153
+ box-shadow: 0 10px 30px rgba(16, 24, 40, 0.22);
154
+ font-size: 12px;
155
+ color: #374151;
156
+
157
+ ul { margin: 6px 0 0 0; padding: 0; list-style: none; }
158
+ li { padding: 4px 0; border-top: 1px solid #eef1f6; overflow-wrap: anywhere; line-height: 1.35; }
159
+ li:first-child { border-top: none; }
160
+ li.tm-wait-panel-more { color: #8a94a6; font-style: italic; }
124
161
  `;
125
- const StyledPill = styled.span `
126
- display: inline-flex;
127
- flex-direction: row;
128
- align-items: center;
129
- gap: 4px;
130
- padding: 2px 8px 2px 6px;
131
- border-radius: 999px;
132
- font-size: 12px;
133
- font-weight: 600;
134
- line-height: 18px;
135
- color: ${props => props.$color};
136
- background: ${props => props.$background};
137
- font-variant-numeric: tabular-nums;
138
-
139
- svg { flex: 0 0 auto; }
162
+ const StyledPopoverTitle = styled.div `
163
+ font-size: 11px;
164
+ font-weight: 700;
165
+ letter-spacing: 0.04em;
166
+ text-transform: uppercase;
167
+ color: ${props => props.$color};
140
168
  `;
141
- const StyledTrack = styled.div `
142
- margin-top: 12px;
143
- width: 100%;
144
- height: 8px;
145
- border-radius: 999px;
146
- background: #e8edf4;
147
- overflow: hidden;
169
+ /** Tempo per spostare il mouse dalla pill al popover. */
170
+ const POPOVER_HIDE_DELAY_MS = 250;
171
+ const StyledTrack = styled.div `
172
+ margin-top: 12px;
173
+ width: 100%;
174
+ height: 8px;
175
+ border-radius: 999px;
176
+ background: #e8edf4;
177
+ overflow: hidden;
148
178
  `;
149
- const StyledFill = styled.div `
150
- width: 100%;
151
- height: 100%;
152
- background: ${props => props.$color};
153
- transform: scaleX(0);
154
- transform-origin: left center;
155
- transition: transform 120ms linear;
156
- will-change: transform;
179
+ const StyledFill = styled.div `
180
+ width: 100%;
181
+ height: 100%;
182
+ background: ${props => props.$color};
183
+ transform: scaleX(0);
184
+ transform-origin: left center;
185
+ transition: transform 120ms linear;
186
+ will-change: transform;
157
187
  `;
158
- const StyledTimeRow = styled.div `
159
- display: flex;
160
- flex-direction: row;
161
- align-items: center;
162
- justify-content: space-between;
163
- gap: 12px;
164
- margin-top: 8px;
165
- font-size: 12px;
166
- color: #8a94a6;
167
- font-variant-numeric: tabular-nums;
188
+ const StyledTimeRow = styled.div `
189
+ display: flex;
190
+ flex-direction: row;
191
+ align-items: center;
192
+ justify-content: space-between;
193
+ gap: 12px;
194
+ margin-top: 8px;
195
+ font-size: 12px;
196
+ color: #8a94a6;
197
+ font-variant-numeric: tabular-nums;
168
198
  `;
169
199
  // Seconda barra: come la principale ma piu' piccola e in tono minore.
170
- const StyledSecondary = styled.div `
171
- margin-top: ${props => (props.$hasLabel ? '4px' : '14px')};
200
+ const StyledSecondary = styled.div `
201
+ margin-top: ${props => (props.$hasLabel ? '4px' : '14px')};
172
202
  `;
173
- const StyledSecondaryRow = styled.div `
174
- display: flex;
175
- flex-direction: row;
176
- align-items: baseline;
177
- justify-content: space-between;
178
- gap: 12px;
179
- font-size: 12px;
180
- color: #6b7280;
181
- font-variant-numeric: tabular-nums;
203
+ const StyledSecondaryRow = styled.div `
204
+ display: flex;
205
+ flex-direction: row;
206
+ align-items: baseline;
207
+ justify-content: space-between;
208
+ gap: 12px;
209
+ font-size: 12px;
210
+ color: #6b7280;
211
+ font-variant-numeric: tabular-nums;
182
212
  `;
183
- const StyledSecondaryText = styled.span `
184
- overflow: hidden;
185
- text-overflow: ellipsis;
186
- white-space: nowrap;
213
+ const StyledSecondaryText = styled.span `
214
+ overflow: hidden;
215
+ text-overflow: ellipsis;
216
+ white-space: nowrap;
187
217
  `;
188
- const StyledSecondaryTrack = styled.div `
189
- margin-top: 5px;
190
- width: 100%;
191
- height: 5px;
192
- border-radius: 999px;
193
- background: #eef1f6;
194
- overflow: hidden;
218
+ const StyledSecondaryTrack = styled.div `
219
+ margin-top: 5px;
220
+ width: 100%;
221
+ height: 5px;
222
+ border-radius: 999px;
223
+ background: #eef1f6;
224
+ overflow: hidden;
195
225
  `;
196
- const StyledSecondaryFill = styled.div `
197
- width: 100%;
198
- height: 100%;
199
- background: ${props => props.$color};
200
- opacity: 0.55;
201
- transform: scaleX(0);
202
- transform-origin: left center;
203
- transition: transform 120ms linear;
204
- will-change: transform;
226
+ const StyledSecondaryFill = styled.div `
227
+ width: 100%;
228
+ height: 100%;
229
+ background: ${props => props.$color};
230
+ opacity: 0.55;
231
+ transform: scaleX(0);
232
+ transform-origin: left center;
233
+ transition: transform 120ms linear;
234
+ will-change: transform;
205
235
  `;
206
- const StyledFooter = styled.div `
207
- display: flex;
208
- flex-direction: row;
209
- justify-content: flex-end;
210
- margin-top: 18px;
236
+ const StyledFooter = styled.div `
237
+ display: flex;
238
+ flex-direction: row;
239
+ justify-content: flex-end;
240
+ margin-top: 18px;
211
241
  `;
212
- const StyledAbortButton = styled.button `
213
- padding: 9px 18px;
214
- border: 1px solid #d5dbe5;
215
- border-radius: 10px;
216
- background: #ffffff;
217
- color: #374151;
218
- font-size: 13px;
219
- font-family: inherit;
220
- cursor: pointer;
221
- transition: background-color 120ms ease, border-color 120ms ease;
222
-
223
- &:hover:not(:disabled) { background: #f3f5f9; border-color: #c3cbd8; }
224
- &:active:not(:disabled) { background: #e9edf4; }
225
- &:disabled { cursor: default; opacity: 0.55; }
242
+ const StyledAbortButton = styled.button `
243
+ padding: 9px 18px;
244
+ border: 1px solid #d5dbe5;
245
+ border-radius: 10px;
246
+ background: #ffffff;
247
+ color: #374151;
248
+ font-size: 13px;
249
+ font-family: inherit;
250
+ cursor: pointer;
251
+ transition: background-color 120ms ease, border-color 120ms ease;
252
+
253
+ &:hover:not(:disabled) { background: #f3f5f9; border-color: #c3cbd8; }
254
+ &:active:not(:disabled) { background: #e9edf4; }
255
+ &:disabled { cursor: default; opacity: 0.55; }
226
256
  `;
227
257
  const IconOk = () => (_jsx("svg", { width: '13', height: '13', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '3', strokeLinecap: 'round', strokeLinejoin: 'round', children: _jsx("polyline", { points: '20 6 9 17 4 12' }) }));
228
258
  const IconWarning = () => (_jsxs("svg", { width: '13', height: '13', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2.4', strokeLinecap: 'round', strokeLinejoin: 'round', children: [_jsx("path", { d: 'M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z' }), _jsx("line", { x1: '12', y1: '9', x2: '12', y2: '13' }), _jsx("line", { x1: '12', y1: '17', x2: '12.01', y2: '17' })] }));
@@ -238,6 +268,14 @@ const TMWaitPanelView = ({ title = '', subtitle = '', cancelable = false, showEt
238
268
  const okValueRef = useRef(null);
239
269
  const warningValueRef = useRef(null);
240
270
  const errorValueRef = useRef(null);
271
+ const overlayRef = useRef(null);
272
+ const warningPillRef = useRef(null);
273
+ const errorPillRef = useRef(null);
274
+ const warningPopoverRef = useRef(null);
275
+ const warningListRef = useRef(null);
276
+ const errorPopoverRef = useRef(null);
277
+ const errorListRef = useRef(null);
278
+ const hideTimerRef = useRef();
241
279
  const abortRef = useRef(null);
242
280
  const secondaryTextRef = useRef(null);
243
281
  const secondaryPercentRef = useRef(null);
@@ -249,6 +287,8 @@ const TMWaitPanelView = ({ title = '', subtitle = '', cancelable = false, showEt
249
287
  return;
250
288
  if (!okValueRef.current || !warningValueRef.current || !errorValueRef.current)
251
289
  return;
290
+ if (!warningPopoverRef.current || !warningListRef.current || !errorPopoverRef.current || !errorListRef.current)
291
+ return;
252
292
  onMount?.({
253
293
  confirm: confirmRef.current,
254
294
  title: titleRef.current,
@@ -260,15 +300,47 @@ const TMWaitPanelView = ({ title = '', subtitle = '', cancelable = false, showEt
260
300
  okValue: okValueRef.current,
261
301
  warningValue: warningValueRef.current,
262
302
  errorValue: errorValueRef.current,
303
+ warningPopover: warningPopoverRef.current,
304
+ warningList: warningListRef.current,
305
+ errorPopover: errorPopoverRef.current,
306
+ errorList: errorListRef.current,
263
307
  abortButton: abortRef.current,
264
308
  secondaryText: secondaryTextRef.current,
265
309
  secondaryPercent: secondaryPercentRef.current,
266
310
  secondaryFill: secondaryFillRef.current,
267
311
  });
268
312
  // Montaggio una tantum: da qui in avanti il manager aggiorna il pannello via DOM, non via render.
313
+ return () => clearTimeout(hideTimerRef.current);
269
314
  }, []);
270
- return (_jsxs(_Fragment, { children: [_jsx(StyledOverlay, { $zIndex: zIndex, children: _jsxs(StyledCard, { role: 'dialog', "aria-live": 'polite', children: [_jsxs(StyledHeader, { children: [_jsx(StyledToppyClip, { children: _jsx(StyledToppy, { src: toppy, alt: '', draggable: false }) }), _jsxs(StyledHeaderText, { children: [_jsx(StyledTitle, { ref: titleRef, children: title }), _jsx(StyledSubtitle, { ref: subtitleRef, children: subtitle })] })] }), primaryLabel && _jsx(StyledBarLabel, { children: primaryLabel }), _jsxs(StyledPercentRow, { $hasLabel: !!primaryLabel, children: [_jsx(StyledPercent, { ref: percentRef, children: "0.00%" }), _jsxs(StyledCounters, { style: { display: showCounters ? 'flex' : 'none' }, children: [_jsxs(StyledPill, { $color: '#3E7B1C', $background: '#E8F5E0', children: [_jsx(IconOk, {}), _jsx("span", { ref: okValueRef, children: "0" })] }), _jsxs(StyledPill, { $color: '#8A6D00', $background: '#FBF3CF', children: [_jsx(IconWarning, {}), _jsx("span", { ref: warningValueRef, children: "0" })] }), _jsxs(StyledPill, { $color: '#B00F2B', $background: '#FBE1E6', children: [_jsx(IconError, {}), _jsx("span", { ref: errorValueRef, children: "0" })] })] })] }), _jsx(StyledTrack, { children: _jsx(StyledFill, { ref: fillRef, $color: getProgressColor() }) }), _jsxs(StyledTimeRow, { style: { visibility: showEta ? 'visible' : 'hidden' }, children: [_jsx("span", { ref: elapsedRef }), _jsx("span", { ref: remainingRef })] }), showSecondary && secondaryLabel && _jsx(StyledBarLabel, { children: secondaryLabel }), showSecondary &&
271
- _jsxs(StyledSecondary, { $hasLabel: !!secondaryLabel, children: [_jsxs(StyledSecondaryRow, { children: [_jsx(StyledSecondaryText, { ref: secondaryTextRef, children: secondaryText }), _jsx("span", { ref: secondaryPercentRef, children: "0.00%" })] }), _jsx(StyledSecondaryTrack, { children: _jsx(StyledSecondaryFill, { ref: secondaryFillRef, $color: getProgressColor() }) })] }), cancelable &&
272
- _jsx(StyledFooter, { children: _jsx(StyledAbortButton, { ref: abortRef, type: 'button', onClick: onAbort, children: SDKUI_Localizator.Abort }) })] }) }), _jsx(TMWaitPanelConfirm, { ref: confirmRef, zIndex: zIndex + 1, onYes: onConfirmYes, onNo: onConfirmNo })] }));
315
+ // Popover gestiti via DOM come il resto del pannello: nessuno stato React, nessun render durante il progresso.
316
+ const hidePopovers = () => {
317
+ clearTimeout(hideTimerRef.current);
318
+ if (warningPopoverRef.current)
319
+ warningPopoverRef.current.style.display = 'none';
320
+ if (errorPopoverRef.current)
321
+ errorPopoverRef.current.style.display = 'none';
322
+ };
323
+ const scheduleHide = () => {
324
+ clearTimeout(hideTimerRef.current);
325
+ hideTimerRef.current = setTimeout(hidePopovers, POPOVER_HIDE_DELAY_MS);
326
+ };
327
+ const cancelHide = () => clearTimeout(hideTimerRef.current);
328
+ /** Apre il popover sotto la pill, allineato a destra. Finche' non arriva un messaggio resta chiuso. */
329
+ const openPopover = (pill, popover) => {
330
+ const overlay = overlayRef.current;
331
+ if (!pill || !popover || !overlay || popover.dataset.empty !== 'false')
332
+ return;
333
+ hidePopovers();
334
+ const overlayRect = overlay.getBoundingClientRect();
335
+ const pillRect = pill.getBoundingClientRect();
336
+ const top = pillRect.bottom - overlayRect.top + 6;
337
+ popover.style.top = `${top}px`;
338
+ popover.style.right = `${Math.max(12, overlayRect.right - pillRect.right)}px`;
339
+ popover.style.maxHeight = `${Math.max(80, overlayRect.height - top - 12)}px`;
340
+ popover.style.display = 'block';
341
+ };
342
+ return (_jsxs(_Fragment, { children: [_jsxs(StyledOverlay, { ref: overlayRef, $zIndex: zIndex, children: [_jsxs(StyledCard, { role: 'dialog', "aria-live": 'polite', children: [_jsxs(StyledHeader, { children: [_jsx(StyledToppyClip, { children: _jsx(StyledToppy, { src: toppy, alt: '', draggable: false }) }), _jsxs(StyledHeaderText, { children: [_jsx(StyledTitle, { ref: titleRef, children: title }), _jsx(StyledSubtitle, { ref: subtitleRef, children: subtitle })] })] }), primaryLabel && _jsx(StyledBarLabel, { children: primaryLabel }), _jsxs(StyledPercentRow, { $hasLabel: !!primaryLabel, children: [_jsx(StyledPercent, { ref: percentRef, children: "0.00%" }), _jsxs(StyledCounters, { style: { display: showCounters ? 'flex' : 'none' }, children: [_jsxs(StyledPill, { $color: '#3E7B1C', $background: '#E8F5E0', children: [_jsx(IconOk, {}), _jsx("span", { ref: okValueRef, children: "0" })] }), _jsxs(StyledPill, { ref: warningPillRef, $color: '#8A6D00', $background: '#FBF3CF', onMouseEnter: () => openPopover(warningPillRef.current, warningPopoverRef.current), onMouseLeave: scheduleHide, onClick: () => openPopover(warningPillRef.current, warningPopoverRef.current), children: [_jsx(IconWarning, {}), _jsx("span", { ref: warningValueRef, children: "0" })] }), _jsxs(StyledPill, { ref: errorPillRef, $color: '#B00F2B', $background: '#FBE1E6', onMouseEnter: () => openPopover(errorPillRef.current, errorPopoverRef.current), onMouseLeave: scheduleHide, onClick: () => openPopover(errorPillRef.current, errorPopoverRef.current), children: [_jsx(IconError, {}), _jsx("span", { ref: errorValueRef, children: "0" })] })] })] }), _jsx(StyledTrack, { children: _jsx(StyledFill, { ref: fillRef, $color: getProgressColor() }) }), _jsxs(StyledTimeRow, { style: { visibility: showEta ? 'visible' : 'hidden' }, children: [_jsx("span", { ref: elapsedRef }), _jsx("span", { ref: remainingRef })] }), showSecondary && secondaryLabel && _jsx(StyledBarLabel, { children: secondaryLabel }), showSecondary &&
343
+ _jsxs(StyledSecondary, { $hasLabel: !!secondaryLabel, children: [_jsxs(StyledSecondaryRow, { children: [_jsx(StyledSecondaryText, { ref: secondaryTextRef, children: secondaryText }), _jsx("span", { ref: secondaryPercentRef, children: "0.00%" })] }), _jsx(StyledSecondaryTrack, { children: _jsx(StyledSecondaryFill, { ref: secondaryFillRef, $color: getProgressColor() }) })] }), cancelable &&
344
+ _jsx(StyledFooter, { children: _jsx(StyledAbortButton, { ref: abortRef, type: 'button', onClick: onAbort, children: SDKUI_Localizator.Abort }) })] }), _jsxs(StyledPopover, { ref: warningPopoverRef, $accent: '#E0B400', "data-empty": 'true', onMouseEnter: cancelHide, onMouseLeave: scheduleHide, children: [_jsx(StyledPopoverTitle, { $color: '#8A6D00', children: SDKUI_Localizator.LatestWarnings }), _jsx("ul", { ref: warningListRef })] }), _jsxs(StyledPopover, { ref: errorPopoverRef, $accent: '#B00F2B', "data-empty": 'true', onMouseEnter: cancelHide, onMouseLeave: scheduleHide, children: [_jsx(StyledPopoverTitle, { $color: '#B00F2B', children: SDKUI_Localizator.LatestErrors }), _jsx("ul", { ref: errorListRef })] })] }), _jsx(TMWaitPanelConfirm, { ref: confirmRef, zIndex: zIndex + 1, onYes: onConfirmYes, onNo: onConfirmNo })] }));
273
345
  };
274
346
  export default TMWaitPanelView;
@@ -5,7 +5,7 @@ import styled from 'styled-components';
5
5
  import { calcResponsiveSizes, IconAll, IconDelete, IconPencil, IconRefresh, IconSelected, SDKUI_Localizator } from '../../helper';
6
6
  import TMButton from '../base/TMButton';
7
7
  import TMDataGrid from '../base/TMDataGrid';
8
- import { CounterItemKey } from '../base/TMCounterContainer';
8
+ import { CounterItemKey, formatCount } from '../base/TMCounterContainer';
9
9
  import { useDeviceType } from '../base/TMDeviceProvider';
10
10
  import TMCheckBox from '../editors/TMCheckBox';
11
11
  import TMDropDown from '../editors/TMDropDown';
@@ -126,8 +126,8 @@ const TMDistinctValues = ({ tid, mid, layoutMode = LayoutModes.None, allowAppend
126
126
  items.set(CounterItemKey.allItems, {
127
127
  key: CounterItemKey.allItems,
128
128
  show: true,
129
- caption: `${counts.returned} restituiti su ${counts.found} trovati`,
130
- value: `${counts.returned}/${counts.found}`,
129
+ caption: `${formatCount(counts.returned)} restituiti su ${formatCount(counts.found)} trovati`,
130
+ value: `${formatCount(counts.returned)}/${formatCount(counts.found)}`,
131
131
  icon: _jsx(IconAll, {}),
132
132
  order: -1
133
133
  });
@@ -41,4 +41,4 @@ interface ITMDynDataListItemChooserFormProps extends ITMChooserFormProps<DataLis
41
41
  /** Se presente, sono i parametri da passare alla query per recuperare il dataSource */
42
42
  queryParamsDynDataList?: string[];
43
43
  }
44
- export declare const TMDynDataListItemChooserForm: (props: ITMDynDataListItemChooserFormProps) => import("react/jsx-runtime").JSX.Element;
44
+ export declare const TMDynDataListItemChooserForm: (props: ITMDynDataListItemChooserFormProps) => React.JSX.Element;
@@ -1,4 +1,5 @@
1
+ import React from 'react';
1
2
  import { InvoiceRetrieveFormats } from '@topconsultnpm/sdk-ts';
2
3
  import { ITMEnumDataBinding } from '../../ts';
3
- declare const TMInvoiceRetrieveFormats: ({ value, valueOrig, onValueChanged, valuesToExclude, label, width }: ITMEnumDataBinding<InvoiceRetrieveFormats>) => import("react/jsx-runtime").JSX.Element;
4
+ declare const TMInvoiceRetrieveFormats: ({ value, valueOrig, onValueChanged, valuesToExclude, label, width }: ITMEnumDataBinding<InvoiceRetrieveFormats>) => React.JSX.Element;
4
5
  export default TMInvoiceRetrieveFormats;