@topconsultnpm/sdkui-react 6.20.0-dev1.52 → 6.20.0-dev1.54

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.
@@ -348,6 +348,7 @@ export declare class SDKUI_Localizator {
348
348
  static get Login(): string;
349
349
  static get LogDelete(): "Löschen der Logik" | "Logical delete" | "Cancelación lógica" | "Suppression logique" | "Lógica de cancelamento" | "Cancellazione logica";
350
350
  static get Logout(): "Abmelden" | "Logout" | "Cerrar sesión" | "Déconnexion" | "Sair" | "Esci";
351
+ static get LogScreenFolder(): "Ordner für Screenshot-Protokolle" | "Log screenshot folder" | "Carpeta de registro de capturas de pantalla" | "Dossier de journal des captures d'écran" | "Pasta de log de capturas de tela" | "Cartella di log screenshot";
351
352
  static get Low(): "Niedrig" | "Low" | "Baja" | "Faible" | "Baixa" | "Bassa";
352
353
  static get MakeEditable(): "Bearbeitbar machen" | "Make editable" | "Hacer editable" | "Rendre modifiable" | "Faça editável" | "Rendi editabile";
353
354
  static get Mark(): "Markierung" | "Mark" | "Marca" | "Marque" | "Segno";
@@ -492,6 +493,8 @@ export declare class SDKUI_Localizator {
492
493
  static get PhysDelete(): "Physische Stornierung" | "Physical delete" | "Cancelación física" | "Supression" | "Cancelamento física" | "Cancellazione fisica";
493
494
  static get PhysicalHistoryDeletion(): string;
494
495
  static get Postponed(): "Verschoben" | "Postponed" | "Aplazada" | "Reportée" | "Adiadas" | "Rinviata";
496
+ static get PotentiallyUnsafeContent(): "Potenziell unsichere Inhalte" | "Potentially Unsafe Content" | "Contenido potencialmente no seguro" | "Contenu potentiellement non sécurisé" | "Conteúdo potencialmente não seguro" | "Contenuti potenzialmente non sicuri";
497
+ static get PotentiallyUnsafeCodePatternsDetected(): "{{0}} potenziell unsicheres Code-Muster in diesem Dokument erkannt." | "{{0}} potentially unsafe code pattern detected in this document." | "Se han detectado {{0}} patrones de código potencialmente no seguro en este documento." | "{{0}} motifs de code potentiellement non sécurisé détectés dans ce document." | "{{0}} padrões de código potencialmente não seguro detectados neste documento." | "Sono stati rilevati {{0}} pattern di codice potenzialmente non sicuro in questo documento.";
495
498
  static get PreparingFileForArchive(): "Datei für Archivierung vorbereiten..." | "Preparing file for archive..." | "Preparando archivo para archivar..." | "Préparation du fichier pour l'archive..." | "Preparando arquivo para arquivar..." | "Preparazione del file per l'archivio...";
496
499
  static get Preview(): "Vorschau" | "Preview" | "Vista previa" | "Aperçu" | "Pré-visualização" | "Anteprima";
497
500
  static get PreviewDocument(): "Vorschau-Dokument" | "Preview document" | "Documento de vista previa" | "Document d'aperçu" | "Documento de pré-visualização" | "Anteprima documento";
@@ -531,7 +534,7 @@ export declare class SDKUI_Localizator {
531
534
  static get ReplaceDocument(): "Dokument ersetzen" | "Replace Document" | "Reemplazar Documento" | "Remplacer le Document" | "Substituir Documento" | "Sostituisci Documento";
532
535
  static get Request(): string;
533
536
  static get RequestTo(): string;
534
- static get RequestType(): "Anforderungstyp" | "Request type" | "Tipo de solicitud" | "Type de demande" | "Tipo de requisição" | "Tipo richiesta";
537
+ static get SearchType(): "Suchtyp" | "Search type" | "Tipo de búsqueda" | "Type de recherche" | "Tipo de pesquisa" | "Tipo di ricerca";
535
538
  static get Required(): "Obligatorisch" | "Required" | "Obligatorio" | "Obbligatoire" | "Obrigatório" | "Obbligatorio";
536
539
  static get RequiredField(): "Erforderliches Feld" | "Required field" | "Campo obligatorio" | "Champ obligatoire" | "Campo obrigatório" | "Campo Obbligatorio";
537
540
  static get RequiredNOT(): "Nicht obligatorisch" | "Not mandatory" | "No obligatorio" | "Pas obligatoire" | "Não é obrigatório" | "Non obbligatorio";
@@ -628,6 +631,7 @@ export declare class SDKUI_Localizator {
628
631
  static get Statistics(): "Statistiken" | "Statistics" | "Estadística" | "Statistiques" | "Estatísticas" | "Statistiche";
629
632
  static get Status(): "Status" | "Estado" | "Statut" | "Stato";
630
633
  static get Subject(): "Betreff" | "Subject" | "Asunto" | "Objet" | "Assunto" | "Oggetto";
634
+ static get SubjectType(): "Betreff-Typ" | "Subject type" | "Tipo de asunto" | "Type de sujet" | "Tipo de assunto" | "Tipo soggetto";
631
635
  static get Summary(): "Zusammenfassung" | "Summary" | "Resumen" | "Résumé" | "Resumo" | "Riepilogo";
632
636
  static get SwitchUser(): "Benutzer wechseln" | "Switch user" | "Cambiar usuario" | "Changer d'utilisateur" | "Mudar de usuário" | "Cambia utente";
633
637
  static get TargetedSearch(): "Gezielte Suche" | "Targeted search" | "Búsqueda dirigida" | "Recherche ciblée" | "Pesquisa direcionada" | "Ricerca puntuale";
@@ -3446,6 +3446,16 @@ export class SDKUI_Localizator {
3446
3446
  default: return "Esci";
3447
3447
  }
3448
3448
  }
3449
+ static get LogScreenFolder() {
3450
+ switch (this._cultureID) {
3451
+ case CultureIDs.De_DE: return "Ordner für Screenshot-Protokolle";
3452
+ case CultureIDs.En_US: return "Log screenshot folder";
3453
+ case CultureIDs.Es_ES: return "Carpeta de registro de capturas de pantalla";
3454
+ case CultureIDs.Fr_FR: return "Dossier de journal des captures d'écran";
3455
+ case CultureIDs.Pt_PT: return "Pasta de log de capturas de tela";
3456
+ default: return "Cartella di log screenshot";
3457
+ }
3458
+ }
3449
3459
  static get Low() {
3450
3460
  switch (this._cultureID) {
3451
3461
  case CultureIDs.De_DE: return "Niedrig";
@@ -4878,6 +4888,32 @@ export class SDKUI_Localizator {
4878
4888
  default: return "Rinviata";
4879
4889
  }
4880
4890
  }
4891
+ static get PotentiallyUnsafeContent() {
4892
+ switch (this._cultureID) {
4893
+ case CultureIDs.De_DE: return "Potenziell unsichere Inhalte";
4894
+ case CultureIDs.En_US: return "Potentially Unsafe Content";
4895
+ case CultureIDs.Es_ES: return "Contenido potencialmente no seguro";
4896
+ case CultureIDs.Fr_FR: return "Contenu potentiellement non sécurisé";
4897
+ case CultureIDs.Pt_PT: return "Conteúdo potencialmente não seguro";
4898
+ default: return "Contenuti potenzialmente non sicuri";
4899
+ }
4900
+ }
4901
+ static get PotentiallyUnsafeCodePatternsDetected() {
4902
+ switch (this._cultureID) {
4903
+ case CultureIDs.De_DE:
4904
+ return "{{0}} potenziell unsicheres Code-Muster in diesem Dokument erkannt.";
4905
+ case CultureIDs.En_US:
4906
+ return "{{0}} potentially unsafe code pattern detected in this document.";
4907
+ case CultureIDs.Es_ES:
4908
+ return "Se han detectado {{0}} patrones de código potencialmente no seguro en este documento.";
4909
+ case CultureIDs.Fr_FR:
4910
+ return "{{0}} motifs de code potentiellement non sécurisé détectés dans ce document.";
4911
+ case CultureIDs.Pt_PT:
4912
+ return "{{0}} padrões de código potencialmente não seguro detectados neste documento.";
4913
+ default:
4914
+ return "Sono stati rilevati {{0}} pattern di codice potenzialmente non sicuro in questo documento.";
4915
+ }
4916
+ }
4881
4917
  static get PreparingFileForArchive() {
4882
4918
  switch (this._cultureID) {
4883
4919
  case CultureIDs.De_DE: return "Datei für Archivierung vorbereiten...";
@@ -5275,14 +5311,14 @@ export class SDKUI_Localizator {
5275
5311
  default: return "Richiedi a";
5276
5312
  }
5277
5313
  }
5278
- static get RequestType() {
5314
+ static get SearchType() {
5279
5315
  switch (this._cultureID) {
5280
- case CultureIDs.De_DE: return "Anforderungstyp";
5281
- case CultureIDs.En_US: return "Request type";
5282
- case CultureIDs.Es_ES: return "Tipo de solicitud";
5283
- case CultureIDs.Fr_FR: return "Type de demande";
5284
- case CultureIDs.Pt_PT: return "Tipo de requisição";
5285
- default: return "Tipo richiesta";
5316
+ case CultureIDs.De_DE: return "Suchtyp";
5317
+ case CultureIDs.En_US: return "Search type";
5318
+ case CultureIDs.Es_ES: return "Tipo de búsqueda";
5319
+ case CultureIDs.Fr_FR: return "Type de recherche";
5320
+ case CultureIDs.Pt_PT: return "Tipo de pesquisa";
5321
+ default: return "Tipo di ricerca";
5286
5322
  }
5287
5323
  }
5288
5324
  static get Required() {
@@ -6246,6 +6282,16 @@ export class SDKUI_Localizator {
6246
6282
  default: return "Oggetto";
6247
6283
  }
6248
6284
  }
6285
+ static get SubjectType() {
6286
+ switch (this._cultureID) {
6287
+ case CultureIDs.De_DE: return "Betreff-Typ";
6288
+ case CultureIDs.En_US: return "Subject type";
6289
+ case CultureIDs.Es_ES: return "Tipo de asunto";
6290
+ case CultureIDs.Fr_FR: return "Type de sujet";
6291
+ case CultureIDs.Pt_PT: return "Tipo de assunto";
6292
+ default: return "Tipo soggetto";
6293
+ }
6294
+ }
6249
6295
  static get Summary() {
6250
6296
  switch (this._cultureID) {
6251
6297
  case CultureIDs.De_DE: return "Zusammenfassung";
@@ -1,10 +1,11 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useState, useRef, useCallback } from "react";
3
3
  import styled from "styled-components";
4
4
  import { LoadIndicator } from 'devextreme-react/load-indicator';
5
5
  import { IconCloseOutline } from "./TMIcons";
6
6
  import { SDKUI_Localizator } from "./SDKUI_Localizator";
7
7
  import { TMColors } from "../utils/theme";
8
+ import { TMMessageBoxManager, ButtonNames } from "../components/base/TMPopUp";
8
9
  // Dynamic imports for optional dependencies
9
10
  let pdfjs;
10
11
  let Document;
@@ -68,6 +69,9 @@ const TMPdfViewer = (props) => {
68
69
  const [loadedPagesNumber, setLoadedPagesNumber] = useState(0);
69
70
  const [visiblePages, setVisiblePages] = useState(new Set([1]));
70
71
  const [pdfUrl, setPdfUrl] = useState("");
72
+ const [hasUnsafeContent, setHasUnsafeContent] = useState(false);
73
+ const [isCheckingPdf, setIsCheckingPdf] = useState(true);
74
+ const [jsMatches, setJsMatches] = useState([]);
71
75
  const observerRef = useRef(null);
72
76
  useEffect(() => {
73
77
  const checkIsMobile = () => {
@@ -82,7 +86,60 @@ const TMPdfViewer = (props) => {
82
86
  (navigator.maxTouchPoints > 1 && !/Win|Mac|Linux x86_64/i.test(userAgent));
83
87
  setIsMobile(isMobileDevice);
84
88
  };
89
+ const checkPdfForJavaScript = async () => {
90
+ setIsCheckingPdf(true);
91
+ try {
92
+ // Legge il PDF come testo per cercare pattern di JavaScript
93
+ const arrayBuffer = await pdfBlob.arrayBuffer();
94
+ const uint8Array = new Uint8Array(arrayBuffer);
95
+ const text = new TextDecoder('latin1').decode(uint8Array);
96
+ // Pattern specifici per rilevare JavaScript effettivo nelle strutture PDF
97
+ const jsPatterns = [
98
+ // Esempio: /JavaScript [ (app.alert('Hello');) ]
99
+ { name: 'JavaScript Dictionary Entry', pattern: /\/JavaScript\s*[(\[<][\s\S]*?[)\]>]/i },
100
+ // Esempio: /JS 15 0 R (riferimento a un oggetto JavaScript)
101
+ { name: 'JavaScript Object Reference', pattern: /\/JS\s+\d+\s+\d+\s+R/i },
102
+ // Esempio: /JS (app.alert('Click');) o /JS <hexstring>
103
+ { name: 'Inline JavaScript Code', pattern: /\/JS\s*[(<][\s\S]*?[)>]/i },
104
+ // Esempio: /AA << /O << /S /JavaScript /JS (app.alert('Open');) >> >>
105
+ { name: 'Additional Actions (AA) with JavaScript', pattern: /\/AA\s*<<[\s\S]*?\/JS[\s\S]*?>>/is },
106
+ // Esempio: /OpenAction << /S /JavaScript /JS (this.print();) >>
107
+ { name: 'Document Open Action with JavaScript', pattern: /\/OpenAction\s*<<[\s\S]*?\/JS[\s\S]*?>>/is },
108
+ // Esempio: /Names << /JavaScript [ (MyScript) 12 0 R ] >>
109
+ { name: 'Named JavaScript Functions', pattern: /\/Names\s*<<[\s\S]*?\/JavaScript[\s\S]*?>>/is },
110
+ ];
111
+ let foundJS = false;
112
+ const matches = [];
113
+ jsPatterns.forEach(({ name, pattern }) => {
114
+ const match = text.match(pattern);
115
+ if (match) {
116
+ foundJS = true;
117
+ const matchIndex = match.index || 0;
118
+ const contextStart = Math.max(0, matchIndex - 50);
119
+ const contextEnd = Math.min(text.length, matchIndex + match[0].length + 50);
120
+ const context = text.substring(contextStart, contextEnd);
121
+ matches.push({
122
+ name,
123
+ pattern: pattern.toString(),
124
+ match: match[0],
125
+ context: context.replace(/[\r\n]+/g, ' ').trim()
126
+ });
127
+ }
128
+ });
129
+ setHasUnsafeContent(foundJS);
130
+ setJsMatches(matches);
131
+ }
132
+ catch (error) {
133
+ // console.error('Errore nella validazione del PDF:', error);
134
+ // In caso di errore, permetti la visualizzazione
135
+ setHasUnsafeContent(false);
136
+ }
137
+ finally {
138
+ setIsCheckingPdf(false);
139
+ }
140
+ };
85
141
  checkIsMobile();
142
+ checkPdfForJavaScript();
86
143
  // Create URL for iframe
87
144
  const url = URL.createObjectURL(pdfBlob);
88
145
  setPdfUrl(url);
@@ -133,8 +190,100 @@ const TMPdfViewer = (props) => {
133
190
  observerRef.current?.disconnect();
134
191
  };
135
192
  }, [pageObserverCallback]);
136
- // Use iframe se react-pdf non è disponibile O se è desktop
137
- if (!isReactPdfAvailable || (!isMobile && pdfUrl)) {
193
+ const showMatchDetails = () => {
194
+ const highlightMatch = (context, matchText) => {
195
+ const matchIndex = context.indexOf(matchText);
196
+ if (matchIndex === -1) {
197
+ // Se non trova il match esatto, prova con una versione normalizzata
198
+ const normalizedContext = context.replace(/\s+/g, ' ');
199
+ const normalizedMatch = matchText.replace(/\s+/g, ' ');
200
+ const normalizedIndex = normalizedContext.indexOf(normalizedMatch);
201
+ if (normalizedIndex === -1) {
202
+ // Se ancora non trova, mostra tutto in grassetto rosso
203
+ return _jsx("strong", { style: { color: '#d32f2f', fontWeight: 'bold' }, children: context });
204
+ }
205
+ return (_jsxs(_Fragment, { children: [normalizedContext.substring(0, normalizedIndex), _jsx("strong", { style: { color: '#d32f2f', fontWeight: 'bold', background: '#ffebee' }, children: normalizedContext.substring(normalizedIndex, normalizedIndex + normalizedMatch.length) }), normalizedContext.substring(normalizedIndex + normalizedMatch.length)] }));
206
+ }
207
+ return (_jsxs(_Fragment, { children: [context.substring(0, matchIndex), _jsx("strong", { style: { color: '#d32f2f', fontWeight: 'bold', background: '#ffebee' }, children: context.substring(matchIndex, matchIndex + matchText.length) }), context.substring(matchIndex + matchText.length)] }));
208
+ };
209
+ TMMessageBoxManager.show({
210
+ title: `${SDKUI_Localizator.Attention}: ${SDKUI_Localizator.PotentiallyUnsafeContent}`,
211
+ buttons: [ButtonNames.OK],
212
+ showToppy: false,
213
+ resizable: true,
214
+ initialWidth: !isMobile ? '800px' : undefined,
215
+ message: (_jsxs("div", { style: { maxHeight: '500px', overflowY: 'auto', padding: '10px', lineHeight: '1.6' }, children: [_jsxs("div", { style: {
216
+ marginBottom: '20px',
217
+ padding: '12px',
218
+ background: '#fff3cd',
219
+ border: '1px solid #ffc107',
220
+ borderRadius: '6px',
221
+ fontSize: '14px',
222
+ wordBreak: 'normal',
223
+ hyphens: 'none'
224
+ }, children: [_jsxs("strong", { children: [SDKUI_Localizator.Attention, ":"] }), " ", SDKUI_Localizator.PotentiallyUnsafeCodePatternsDetected.replaceParams(jsMatches.length.toString())] }), jsMatches.length > 0 ? (jsMatches.map((match, index) => (_jsxs("div", { style: {
225
+ marginBottom: '16px',
226
+ padding: '16px',
227
+ border: '1px solid #ffcdd2',
228
+ borderRadius: '8px',
229
+ background: '#fff',
230
+ boxShadow: '0 1px 3px rgba(0,0,0,0.1)'
231
+ }, children: [_jsx("div", { style: {
232
+ marginBottom: '12px',
233
+ paddingBottom: '8px',
234
+ borderBottom: '2px solid #f44336'
235
+ }, children: _jsxs("strong", { style: {
236
+ color: '#d32f2f',
237
+ fontSize: '15px',
238
+ display: 'flex',
239
+ alignItems: 'center',
240
+ gap: '8px'
241
+ }, children: [_jsx("span", { style: {
242
+ background: '#f44336',
243
+ color: '#fff',
244
+ borderRadius: '50%',
245
+ width: '24px',
246
+ height: '24px',
247
+ display: 'inline-flex',
248
+ alignItems: 'center',
249
+ justifyContent: 'center',
250
+ fontSize: '13px',
251
+ fontWeight: 'bold'
252
+ }, children: index + 1 }), match.name] }) }), _jsx("div", { style: { fontSize: '13px' }, children: _jsx("div", { style: {
253
+ background: '#f5f5f5',
254
+ padding: '10px',
255
+ borderRadius: '4px',
256
+ borderLeft: '3px solid #f44336',
257
+ fontFamily: 'Consolas, Monaco, monospace',
258
+ fontSize: '12px',
259
+ wordBreak: 'break-all',
260
+ color: '#333',
261
+ maxHeight: '200px',
262
+ overflowY: 'auto',
263
+ userSelect: 'text'
264
+ }, children: highlightMatch(match.context, match.match) }) })] }, index)))) : (_jsx("div", { style: { textAlign: 'center', padding: '20px', color: '#999' }, children: "Nessun dettaglio disponibile" }))] }))
265
+ });
266
+ };
267
+ // Mostra loading durante la validazione
268
+ if (isCheckingPdf) {
269
+ return (_jsx(PDFViewerContainer, { children: _jsxs("div", { style: {
270
+ display: 'flex',
271
+ justifyContent: 'center',
272
+ alignItems: 'center',
273
+ height: '100%',
274
+ flexDirection: 'column',
275
+ gap: '10px'
276
+ }, children: [_jsx(LoadIndicator, { height: 60, width: 60 }), _jsx("div", { children: "Validazione PDF in corso..." })] }) }));
277
+ }
278
+ /**
279
+ * Usa <iframe> nei seguenti casi:
280
+ * 1. react-pdf non è disponibile (libreria non installata)
281
+ * 2. Desktop E nessun contenuto JavaScript rilevato (visualizzazione nativa del browser più performante)
282
+ *
283
+ * L'iframe sfrutta il visualizzatore PDF nativo del browser, ma non può prevenire
284
+ * l'esecuzione di JavaScript embedded nel PDF.
285
+ */
286
+ if (!isReactPdfAvailable || (!isMobile && !hasUnsafeContent && pdfUrl)) {
138
287
  return (_jsx(PDFViewerContainer, { children: _jsx("iframe", { src: `${pdfUrl}#${enableFitToWidth ? 'view=FitH&' : ''}scrollbar=1`, title: title, style: {
139
288
  width: '100%',
140
289
  height: '100%',
@@ -143,14 +292,25 @@ const TMPdfViewer = (props) => {
143
292
  pointerEvents: isResizingActive === true ? "none" : "auto"
144
293
  } }, pdfUrl) }));
145
294
  }
146
- // Usa react-pdf solo per mobile e solo se disponibile
147
- return _jsxs(PDFViewerContainer, { children: [loadedPagesNumber === 0 && totalPagesNumber > 0 && _jsx(LoadingOverlay, { children: _jsxs("div", { style: {
295
+ /**
296
+ * Usa react-pdf nei seguenti casi:
297
+ * 1. Dispositivo mobile (migliore esperienza utente con lazy loading)
298
+ * 2. Desktop con contenuto JavaScript rilevato (rendering sicuro senza esecuzione di script)
299
+ *
300
+ * react-pdf renderizza il PDF come canvas, prevenendo l'esecuzione di JavaScript embedded,
301
+ * ma è meno performante dell'iframe nativo su desktop.
302
+ */
303
+ return _jsxs(PDFViewerContainer, { style: { display: 'flex', flexDirection: 'column' }, children: [loadedPagesNumber === 0 && totalPagesNumber > 0 && _jsx(LoadingOverlay, { children: _jsxs("div", { style: {
148
304
  display: 'flex',
149
305
  justifyContent: 'center',
150
306
  alignItems: 'center',
151
307
  flexDirection: 'column',
152
308
  gap: '10px'
153
- }, children: [_jsx(LoadIndicator, { height: 60, width: 60 }), _jsxs("div", { children: [SDKUI_Localizator.Loading, "..."] })] }) }), _jsx("div", { style: { display: loadedPagesNumber > 0 && totalPagesNumber > 0 ? 'block' : 'none' }, children: _jsx(Document, { file: pdfBlob, onLoadSuccess: ({ numPages }) => {
309
+ }, children: [_jsx(LoadIndicator, { height: 60, width: 60 }), _jsxs("div", { children: [SDKUI_Localizator.Loading, "..."] })] }) }), _jsx("div", { style: {
310
+ display: loadedPagesNumber > 0 && totalPagesNumber > 0 ? 'block' : 'none',
311
+ flex: 1,
312
+ overflow: 'auto'
313
+ }, children: _jsx(Document, { file: pdfBlob, onLoadSuccess: ({ numPages }) => {
154
314
  setTotalPagesNumber(numPages);
155
315
  setLoadedPagesNumber(0);
156
316
  }, loading: _jsxs("div", { style: {
@@ -182,6 +342,27 @@ const TMPdfViewer = (props) => {
182
342
  }, children: shouldRender && (_jsx(Page, { pageNumber: pageNumber, renderTextLayer: false, renderAnnotationLayer: false, width: Math.min(window.innerWidth - 40, 1200), loading: _jsx("div", { style: { padding: '20px' }, children: _jsx(LoadIndicator, { height: 40, width: 40 }) }), onLoadSuccess: () => {
183
343
  setLoadedPagesNumber(prev => prev + 1);
184
344
  } })) }, `page_${pageNumber}`));
185
- }) }) })] });
345
+ }) }) }), hasUnsafeContent && (_jsxs("div", { style: {
346
+ display: 'flex',
347
+ justifyContent: 'center',
348
+ alignItems: 'center',
349
+ padding: '12px 20px',
350
+ background: '#fff3cd',
351
+ borderTop: '2px solid #ffc107',
352
+ gap: '8px',
353
+ flexShrink: 0
354
+ }, children: [_jsxs("span", { style: {
355
+ color: '#856404',
356
+ whiteSpace: 'nowrap',
357
+ overflow: 'hidden',
358
+ textOverflow: 'ellipsis',
359
+ flex: 1
360
+ }, children: [_jsx("strong", { children: "Attenzione:" }), " Questo documento contiene contenuti potenzialmente non sicuri."] }), jsMatches.length > 0 && (_jsx("span", { className: "dx-icon-info", style: {
361
+ fontSize: '20px',
362
+ color: '#d32f2f',
363
+ cursor: 'pointer',
364
+ transition: 'color 0.2s',
365
+ marginLeft: '4px'
366
+ }, onClick: showMatchDetails, title: "Clicca per vedere i dettagli", onMouseEnter: (e) => e.currentTarget.style.color = '#b71c1c', onMouseLeave: (e) => e.currentTarget.style.color = '#d32f2f' }))] }))] });
186
367
  };
187
368
  export default TMPdfViewer;
@@ -667,7 +667,7 @@ export function versionAndBuildtypeInfo(module) {
667
667
  switch (module) {
668
668
  case moduleTypes.SDK:
669
669
  case moduleTypes.SDKUI:
670
- return moduleVersion(module).replace("-hotfix", "+hotfix");
670
+ return moduleVersion(module).replace("-hotfix.", "+hotfix").replace("-hotfix", "+hotfix");
671
671
  default:
672
672
  return moduleVersion(module);
673
673
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react",
3
- "version": "6.20.0-dev1.52",
3
+ "version": "6.20.0-dev1.54",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",