@widergy/energy-ui 3.98.0 → 3.98.2

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [3.98.2](https://github.com/widergy/energy-ui/compare/v3.98.1...v3.98.2) (2025-08-12)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * [SFPE-483] UTDataCategory empty data ([#664](https://github.com/widergy/energy-ui/issues/664)) ([be73350](https://github.com/widergy/energy-ui/commit/be7335017612682e9b44a7950c6d9e0999427867))
7
+
8
+ ## [3.98.1](https://github.com/widergy/energy-ui/compare/v3.98.0...v3.98.1) (2025-08-12)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * [PDI-149] fix on utils ([#663](https://github.com/widergy/energy-ui/issues/663)) ([a642070](https://github.com/widergy/energy-ui/commit/a642070e196b634ea54113c2140cf306b0cf8011))
14
+
1
15
  # [3.98.0](https://github.com/widergy/energy-ui/compare/v3.97.0...v3.98.0) (2025-08-12)
2
16
 
3
17
 
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.WITHOUT_DATA_TEXT = void 0;
7
+ const WITHOUT_DATA_TEXT = exports.WITHOUT_DATA_TEXT = 'Sin datos';
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  var _propTypes = require("prop-types");
8
8
  var _react = _interopRequireWildcard(require("react"));
9
+ var _isEmpty = _interopRequireDefault(require("lodash/isEmpty"));
9
10
  var _WithTheme = _interopRequireDefault(require("../WithTheme"));
10
11
  var _UTDataElement = _interopRequireDefault(require("../UTDataElement"));
11
12
  var _UTLabel = _interopRequireDefault(require("../UTLabel"));
@@ -14,6 +15,7 @@ var _classesUtils = require("../../utils/classesUtils");
14
15
  var _testIds = require("../../constants/testIds");
15
16
  var _stylesModule = _interopRequireDefault(require("./styles.module.scss"));
16
17
  var _theme = require("./theme");
18
+ var _constants = require("./constants");
17
19
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
18
20
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
19
21
  function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
@@ -65,7 +67,10 @@ const UTDataCategory = _ref => {
65
67
  }, /*#__PURE__*/_react.default.createElement("div", {
66
68
  ref: childrenRef,
67
69
  className: _stylesModule.default.childrenContent
68
- }, elements.map((element, index) => {
70
+ }, (0, _isEmpty.default)(elements) ? /*#__PURE__*/_react.default.createElement(_UTLabel.default, {
71
+ align: "center",
72
+ colorTheme: "gray"
73
+ }, _constants.WITHOUT_DATA_TEXT) : elements.map((element, index) => {
69
74
  const {
70
75
  key,
71
76
  ...dataElementProps
package/dist/index.js CHANGED
@@ -480,7 +480,7 @@ Object.defineProperty(exports, "keyboardUtils", {
480
480
  Object.defineProperty(exports, "stylesDeduplicationUtils", {
481
481
  enumerable: true,
482
482
  get: function () {
483
- return _styleDeduplication.default;
483
+ return _stylesDeduplicationUtils.default;
484
484
  }
485
485
  });
486
486
  var _AlertHandler = _interopRequireDefault(require("./components/UTAlert/AlertHandler"));
@@ -562,5 +562,5 @@ var _UTVirtualKeyboard = _interopRequireDefault(require("./components/UTVirtualK
562
562
  var _UTWorkflowContainer = _interopRequireDefault(require("./components/UTWorkflowContainer"));
563
563
  var _WithLoading = _interopRequireDefault(require("./components/WithLoading"));
564
564
  var _WithTouch = _interopRequireDefault(require("./components/WithTouch"));
565
- var _styleDeduplication = _interopRequireDefault(require("./utils/styleDeduplication"));
565
+ var _stylesDeduplicationUtils = _interopRequireDefault(require("./utils/stylesDeduplicationUtils"));
566
566
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -0,0 +1,453 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _react = require("react");
8
+ /**
9
+ * Sistema de deduplicación de estilos para Energy UI
10
+ * Evita que los estilos se carguen múltiples veces cuando la librería se importa desde diferentes proyectos
11
+ */
12
+
13
+ // Cache global para estilos ya cargados
14
+ const loadedStyles = new Set(); // Set de hashes de contenido CSS ya procesados
15
+ const styleElementsByHash = new Map(); // Map de hash -> elemento DOM para estilos ya cargados
16
+
17
+ // Cache global para URLs de hojas de estilos externas ya cargadas
18
+ const loadedStylesheets = new Set(); // Set de URLs normalizadas de hojas externas ya cargadas
19
+
20
+ // Referencias globales para cleanup
21
+ let globalObserver = null;
22
+ let isConfigured = false;
23
+
24
+ /**
25
+ * Normaliza el contenido CSS para comparaciones consistentes
26
+ */
27
+ const normalizeCSSContent = content => {
28
+ if (!content || typeof content !== 'string') {
29
+ return '';
30
+ }
31
+ return content
32
+ // Remover comentarios CSS (pero preservar source maps)
33
+ .replace(/\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\//g, match => {
34
+ // Preservar source maps que pueden contener información importante
35
+ if (match.includes('sourceMappingURL')) {
36
+ return match;
37
+ }
38
+ return '';
39
+ })
40
+ // Remover espacios en blanco extra
41
+ .replace(/\s+/g, ' ')
42
+ // Remover espacios al inicio y final
43
+ .trim()
44
+ // Normalizar saltos de línea
45
+ .replace(/\r\n/g, '\n').replace(/\r/g, '\n')
46
+ // Remover espacios alrededor de caracteres especiales
47
+ .replace(/\s*([{}:;,])\s*/g, '$1')
48
+ // Normalizar valores de colores
49
+ .replace(/#([0-9a-fA-F]{3})\b/g, (match, hex) => // Expandir colores de 3 dígitos a 6 dígitos
50
+ "#".concat(hex.split('').map(char => char + char).join('')))
51
+ // Normalizar valores de unidades
52
+ .replace(/(\d+)px/g, '$1px').replace(/(\d+)em/g, '$1em').replace(/(\d+)rem/g, '$1rem')
53
+ // Remover espacios extra entre reglas
54
+ .replace(/}\s*{/g, '}{')
55
+ // Normalizar selectores
56
+ .replace(/\s*,\s*/g, ',').replace(/\s*>\s*/g, '>').replace(/\s*\+\s*/g, '+').replace(/\s*~\s*/g, '~');
57
+ };
58
+
59
+ /**
60
+ * Normaliza URLs para comparaciones consistentes
61
+ */
62
+ const normalizeURL = url => {
63
+ if (!url || typeof url !== 'string') {
64
+ return '';
65
+ }
66
+ try {
67
+ const urlObj = new URL(url, window.location.href);
68
+
69
+ // Remover parámetros de query que no afectan el contenido
70
+ const paramsToRemove = ['v', 'version', 't', 'timestamp', 'cache', 'cb'];
71
+ paramsToRemove.forEach(param => {
72
+ urlObj.searchParams.delete(param);
73
+ });
74
+
75
+ // Normalizar el path
76
+ let path = urlObj.pathname;
77
+
78
+ // Remover extensiones de archivo para comparación
79
+ path = path.replace(/\.(css|scss|sass|less)$/i, '');
80
+
81
+ // Remover hashes de build (ej: main.abc123.css -> main)
82
+ path = path.replace(/\.([a-f0-9]{8,})\./i, '.');
83
+
84
+ // Construir URL normalizada
85
+ const normalizedURL = "".concat(urlObj.origin).concat(path);
86
+ return normalizedURL.toLowerCase();
87
+ } catch (e) {
88
+ // Si no es una URL válida, normalizar como string
89
+ return url.toLowerCase().replace(/[?#].*$/, '') // Remover query params y hash
90
+ .replace(/\.(css|scss|sass|less)$/i, '') // Remover extensiones
91
+ .replace(/\.([a-f0-9]{8,})\./i, '.') // Remover hashes de build
92
+ .trim();
93
+ }
94
+ };
95
+
96
+ /**
97
+ * Genera un hash único para un conjunto de estilos normalizado
98
+ */
99
+ const generateStyleHash = content => {
100
+ const normalizedContent = normalizeCSSContent(content);
101
+
102
+ // Usar un algoritmo de hash más robusto
103
+ let hash = 0;
104
+ const prime = 31;
105
+ for (let i = 0; i < normalizedContent.length; i++) {
106
+ const char = normalizedContent.charCodeAt(i);
107
+ hash = hash * prime + char >>> 0; // Mantener como entero de 32 bits sin signo
108
+ }
109
+ return hash.toString(36);
110
+ };
111
+
112
+ /**
113
+ * Verifica si el contenido es un estilo de Energy UI
114
+ */
115
+ const isEnergyUIStyle = content => {
116
+ if (!content || typeof content !== 'string') {
117
+ return false;
118
+ }
119
+ const normalizedContent = normalizeCSSContent(content);
120
+
121
+ // Patrones específicos de Energy UI - MÁS SEGUROS
122
+ const energyUIPatterns = [
123
+ // Clases de componentes UT (muy específicas)
124
+ /\.[a-z]*UT[A-Z][a-zA-Z]*/g,
125
+ // Clases CSS Modules con hash de UT (muy específicas)
126
+ /\.UT[A-Z][a-zA-Z]*__[a-zA-Z0-9_-]+/g,
127
+ // Variables CSS de Energy UI (muy específicas)
128
+ /--energy-ui-/g, /--ut-/g,
129
+ // Selectores específicos de Energy UI (muy específicos)
130
+ /\[data-energy-ui\]/g, /\[data-ut-/g,
131
+ // Comentarios específicos de Energy UI (muy específicos)
132
+ /\/\*.*energy.*ui.*\*\//gi, /\/\*.*ut.*\*\//gi,
133
+ // CSS Modules internos de Energy UI (patrón específico .styles_[name]_[hash])
134
+ /\.styles_[a-zA-Z0-9_-]+_[a-zA-Z0-9_-]+/g,
135
+ // Source maps específicos de Energy UI
136
+ /sourceMappingURL.*energy/i, /sourceMappingURL.*ut/i];
137
+
138
+ // Verificación adicional de seguridad: debe contener al menos 2 patrones específicos
139
+ const matches = energyUIPatterns.filter(pattern => pattern.test(normalizedContent));
140
+
141
+ // Solo considerar Energy UI si hay al menos 2 coincidencias (más seguro)
142
+ if (matches.length >= 2) {
143
+ return true;
144
+ }
145
+
146
+ // Caso especial: si contiene el patrón .styles_[name]_[hash] Y algún otro patrón específico
147
+ const stylesPattern = /\.styles_[a-zA-Z0-9_-]+_[a-zA-Z0-9_-]+/g;
148
+ const hasStylesPattern = stylesPattern.test(normalizedContent);
149
+ const hasOtherPattern = energyUIPatterns.some(pattern => pattern !== stylesPattern && pattern.test(normalizedContent));
150
+ const isEnergyUI = hasStylesPattern && hasOtherPattern;
151
+ return isEnergyUI;
152
+ };
153
+
154
+ /**
155
+ * Verifica si una URL es de Energy UI
156
+ */
157
+ const isEnergyUIURL = url => {
158
+ if (!url || typeof url !== 'string') {
159
+ return false;
160
+ }
161
+ const normalizedURL = normalizeURL(url);
162
+
163
+ // Patrones de URL de Energy UI - MÁS SEGUROS
164
+ const energyUIPatterns = [
165
+ // URLs específicas de Energy UI
166
+ /energy-ui/i, /energyui/i, /ut-components/i, /energy.*ui/i,
167
+ // URLs locales específicas de Energy UI (más restrictivas)
168
+ /localhost.*\/energy/i, /localhost.*\/ut/i, /localhost.*energy-ui/i, /localhost.*ut-components/i];
169
+ return energyUIPatterns.some(pattern => pattern.test(normalizedURL));
170
+ };
171
+
172
+ /**
173
+ * Verifica si un estilo ya está cargado
174
+ */
175
+ const isStyleAlreadyLoaded = content => {
176
+ const hash = generateStyleHash(content);
177
+ return loadedStyles.has(hash);
178
+ };
179
+
180
+ /**
181
+ * Marca un estilo como cargado
182
+ */
183
+ const markStyleAsLoaded = (content, element) => {
184
+ const hash = generateStyleHash(content);
185
+ loadedStyles.add(hash);
186
+ styleElementsByHash.set(hash, element);
187
+ };
188
+
189
+ /**
190
+ * Verifica si una hoja de estilos externa ya está cargada
191
+ */
192
+ const isStylesheetAlreadyLoaded = href => {
193
+ const normalizedHref = normalizeURL(href);
194
+ return loadedStylesheets.has(normalizedHref);
195
+ };
196
+
197
+ /**
198
+ * Marca una hoja de estilos externa como cargada
199
+ */
200
+ const markStylesheetAsLoaded = href => {
201
+ const normalizedHref = normalizeURL(href);
202
+ loadedStylesheets.add(normalizedHref);
203
+ };
204
+
205
+ /**
206
+ * Verifica si estamos en un entorno compatible
207
+ */
208
+ const isCompatibleEnvironment = () => typeof window !== 'undefined' && typeof document !== 'undefined' && typeof document.head !== 'undefined';
209
+
210
+ /**
211
+ * Intercepta la creación de elementos <style> para evitar duplicados
212
+ */
213
+ const interceptStyleCreation = () => {
214
+ // Verificar si estamos en un entorno con DOM disponible
215
+ if (!isCompatibleEnvironment()) {
216
+ return;
217
+ }
218
+ if (isConfigured) {
219
+ return;
220
+ }
221
+
222
+ // Usar el punto de inserción existente (meta tag)
223
+ const insertionPoint = document.getElementById('energyui-insertion-point');
224
+ if (!insertionPoint) {
225
+ console.warn('Energy UI: No se encontró el punto de inserción <meta id="energyui-insertion-point"/>');
226
+ return;
227
+ }
228
+
229
+ // Observer específico que solo procesa elementos después del meta tag
230
+
231
+ // Observer que solo observa los cambios DESPUÉS del meta tag (más seguro)
232
+ const observeAfterMetaTag = () => {
233
+ // Observar solo los nodos que se insertan después del meta tag
234
+ const observer = new MutationObserver(mutations => {
235
+ mutations.forEach(mutation => {
236
+ if (mutation.type === 'childList') {
237
+ mutation.addedNodes.forEach(node => {
238
+ if (node.nodeType === Node.ELEMENT_NODE) {
239
+ // Solo procesar elementos que están después del meta tag
240
+ if (insertionPoint.compareDocumentPosition(node) & Node.DOCUMENT_POSITION_FOLLOWING) {
241
+ // Procesar elementos <style>
242
+ if (node.tagName === 'STYLE') {
243
+ const content = node.textContent || '';
244
+
245
+ // Usar detección mejorada de Energy UI
246
+ if (content && isEnergyUIStyle(content)) {
247
+ if (isStyleAlreadyLoaded(content)) {
248
+ node.remove();
249
+ } else {
250
+ markStyleAsLoaded(content, node);
251
+ }
252
+ }
253
+ }
254
+
255
+ // Procesar elementos <link> con hojas de estilos
256
+ if (node.tagName === 'LINK' && node.rel === 'stylesheet') {
257
+ const href = node.href || '';
258
+
259
+ // Usar detección mejorada de URLs de Energy UI
260
+ if (href && isEnergyUIURL(href)) {
261
+ // Detección silenciosa de hojas de estilos externas
262
+ }
263
+ }
264
+ }
265
+ }
266
+ });
267
+ }
268
+ });
269
+ });
270
+
271
+ // Observar solo el head, pero filtrar por posición relativa al meta tag
272
+ observer.observe(document.head, {
273
+ childList: true,
274
+ subtree: false // No observar subtree, solo nodos directos
275
+ });
276
+ return observer;
277
+ };
278
+
279
+ // Usar el observer específico
280
+ globalObserver = observeAfterMetaTag();
281
+
282
+ // Marcar como configurado
283
+ isConfigured = true;
284
+ };
285
+
286
+ /**
287
+ * Función para limpiar estilos duplicados existentes
288
+ */
289
+ const cleanupDuplicateStyles = () => {
290
+ // Limpiar elementos <style> duplicados
291
+ const existingStyleElements = document.querySelectorAll('style');
292
+ const seenContents = new Set();
293
+ existingStyleElements.forEach(style => {
294
+ const content = style.textContent || '';
295
+
296
+ // Usar detección mejorada de Energy UI
297
+ if (content && isEnergyUIStyle(content)) {
298
+ const hash = generateStyleHash(content);
299
+ if (seenContents.has(hash)) {
300
+ style.remove();
301
+ } else {
302
+ seenContents.add(hash);
303
+ markStyleAsLoaded(content, style);
304
+ }
305
+ }
306
+ });
307
+
308
+ // Limpiar hojas de estilos externas duplicadas
309
+ const linkElements = document.querySelectorAll('link[rel="stylesheet"]');
310
+ linkElements.forEach(link => {
311
+ const href = link.href || '';
312
+
313
+ // Usar detección mejorada de URLs de Energy UI
314
+ if (href && isEnergyUIURL(href)) {
315
+ if (isStylesheetAlreadyLoaded(href)) {
316
+ link.remove();
317
+ } else {
318
+ markStylesheetAsLoaded(href);
319
+ }
320
+ }
321
+ });
322
+ };
323
+
324
+ /**
325
+ * Función para limpiar recursos y desconectar observers
326
+ */
327
+ const cleanupStyleDeduplication = () => {
328
+ if (globalObserver) {
329
+ globalObserver.disconnect();
330
+ globalObserver = null;
331
+ }
332
+
333
+ // Limpiar caches
334
+ loadedStyles.clear();
335
+ styleElementsByHash.clear();
336
+ loadedStylesheets.clear();
337
+
338
+ // Resetear estado
339
+ isConfigured = false;
340
+ };
341
+
342
+ /**
343
+ * Hook para React
344
+ */
345
+ const useStyleDeduplication = function () {
346
+ let enableStyleDeduplication = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
347
+ (0, _react.useEffect)(() => {
348
+ if (enableStyleDeduplication) {
349
+ interceptStyleCreation();
350
+ cleanupDuplicateStyles();
351
+ }
352
+
353
+ // Cleanup automático cuando el componente se desmonta
354
+ return () => {
355
+ if (enableStyleDeduplication) {
356
+ cleanupStyleDeduplication();
357
+ }
358
+ };
359
+ }, [enableStyleDeduplication]);
360
+ };
361
+
362
+ /**
363
+ * Función para configuración manual
364
+ */
365
+ const setupStyleDeduplication = () => {
366
+ interceptStyleCreation();
367
+ cleanupDuplicateStyles();
368
+ };
369
+
370
+ /**
371
+ * Función para verificar si está configurado
372
+ */
373
+ const isStyleDeduplicationConfigured = () => isConfigured && globalObserver !== null;
374
+
375
+ /**
376
+ * Función para obtener estadísticas de deduplicación
377
+ */
378
+ const getDeduplicationStats = () => ({
379
+ loadedStylesCount: loadedStyles.size,
380
+ styleElementsByHashCount: styleElementsByHash.size,
381
+ loadedStylesheetsCount: loadedStylesheets.size,
382
+ isConfigured: isStyleDeduplicationConfigured()
383
+ });
384
+
385
+ /**
386
+ * Función para testing: verificar si un contenido sería detectado como Energy UI
387
+ */
388
+ const testEnergyUIDetection = content => ({
389
+ isEnergyUI: isEnergyUIStyle(content),
390
+ normalizedContent: normalizeCSSContent(content),
391
+ hash: generateStyleHash(content)
392
+ });
393
+
394
+ /**
395
+ * Función para testing: verificar si una URL sería detectada como Energy UI
396
+ */
397
+ const testEnergyUIURLDetection = url => ({
398
+ isEnergyUI: isEnergyUIURL(url),
399
+ normalizedURL: normalizeURL(url)
400
+ });
401
+
402
+ /**
403
+ * Función para debugging: obtener información detallada de estilos cargados
404
+ */
405
+ const getDetailedStats = () => {
406
+ const currentStyleElements = document.querySelectorAll('style');
407
+ const currentLinkElements = document.querySelectorAll('link[rel="stylesheet"]');
408
+ const energyUIStyles = [];
409
+ const energyUILinks = [];
410
+ currentStyleElements.forEach((style, index) => {
411
+ const content = style.textContent || '';
412
+ if (isEnergyUIStyle(content)) {
413
+ energyUIStyles.push({
414
+ index,
415
+ hash: generateStyleHash(content),
416
+ isDuplicate: isStyleAlreadyLoaded(content),
417
+ normalizedContent: "".concat(normalizeCSSContent(content).substring(0, 100), "...")
418
+ });
419
+ }
420
+ });
421
+ currentLinkElements.forEach((link, index) => {
422
+ const href = link.href || '';
423
+ if (isEnergyUIURL(href)) {
424
+ energyUILinks.push({
425
+ index,
426
+ href,
427
+ normalizedURL: normalizeURL(href),
428
+ isDuplicate: isStylesheetAlreadyLoaded(href)
429
+ });
430
+ }
431
+ });
432
+ return {
433
+ totalStyles: currentStyleElements.length,
434
+ totalLinks: currentLinkElements.length,
435
+ energyUIStyles,
436
+ energyUILinks,
437
+ loadedStylesCount: loadedStyles.size,
438
+ styleElementsByHashCount: styleElementsByHash.size,
439
+ isConfigured: isStyleDeduplicationConfigured()
440
+ };
441
+ };
442
+ var _default = exports.default = {
443
+ getDeduplicationStats,
444
+ isStyleDeduplicationConfigured,
445
+ setupStyleDeduplication,
446
+ cleanupStyleDeduplication,
447
+ useStyleDeduplication,
448
+ isCompatibleEnvironment,
449
+ isStylesheetAlreadyLoaded,
450
+ testEnergyUIDetection,
451
+ testEnergyUIURLDetection,
452
+ getDetailedStats
453
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@widergy/energy-ui",
3
- "version": "3.98.0",
3
+ "version": "3.98.2",
4
4
  "description": "Widergy Web Components",
5
5
  "author": "widergy",
6
6
  "license": "MIT",
@@ -1,183 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.useStyleDeduplication = exports.setupStyleDeduplication = exports.isStyleDeduplicationConfigured = exports.getDeduplicationStats = exports.default = void 0;
7
- var _react = require("react");
8
- /**
9
- * Sistema de deduplicación de estilos para Energy UI
10
- * Evita que los estilos se carguen múltiples veces cuando la librería se importa desde diferentes proyectos
11
- */
12
-
13
- // Cache global para estilos ya cargados
14
- const loadedStyles = new Set();
15
- const styleElements = new Map();
16
-
17
- /**
18
- * Genera un hash único para un conjunto de estilos
19
- */
20
- const generateStyleHash = content => {
21
- let hash = 0;
22
- for (let i = 0; i < content.length; i++) {
23
- const char = content.charCodeAt(i);
24
- hash = (hash << 5) - hash + char;
25
- hash = hash & hash; // Convertir a entero de 32 bits
26
- }
27
- return hash.toString(36);
28
- };
29
-
30
- /**
31
- * Verifica si un estilo ya está cargado
32
- */
33
- const isStyleAlreadyLoaded = content => {
34
- const hash = generateStyleHash(content);
35
- return loadedStyles.has(hash);
36
- };
37
-
38
- /**
39
- * Marca un estilo como cargado
40
- */
41
- const markStyleAsLoaded = (content, element) => {
42
- const hash = generateStyleHash(content);
43
- loadedStyles.add(hash);
44
- styleElements.set(hash, element);
45
- };
46
-
47
- /**
48
- * Intercepta la creación de elementos <style> para evitar duplicados
49
- */
50
- const interceptStyleCreation = () => {
51
- if (window.__energyUI_styleDeduplicationConfigured) {
52
- return;
53
- }
54
-
55
- // Crear el punto de inserción si no existe
56
- let insertionPoint = document.getElementById('energyui-insertion-point');
57
- if (!insertionPoint) {
58
- insertionPoint = document.createElement('div');
59
- insertionPoint.id = 'energyui-insertion-point';
60
- insertionPoint.setAttribute('data-energy-ui', 'deduplication-insertion-point');
61
- document.head.appendChild(insertionPoint);
62
- }
63
-
64
- // Usar un enfoque más simple: solo observar el DOM
65
- const observer = new MutationObserver(mutations => {
66
- mutations.forEach(mutation => {
67
- mutation.addedNodes.forEach(node => {
68
- if (node.nodeType === Node.ELEMENT_NODE && node.tagName === 'STYLE') {
69
- const content = node.textContent || '';
70
- if (content && (content.includes('UT') || content.includes('energy-ui') || content.includes('energyui') || content.includes('__'))) {
71
- if (isStyleAlreadyLoaded(content)) {
72
- console.log('Energy UI: Estilo duplicado detectado en DOM, removiendo...');
73
- node.remove();
74
- } else {
75
- markStyleAsLoaded(content, node);
76
- }
77
- }
78
- }
79
- });
80
- });
81
- });
82
- observer.observe(document.head, {
83
- childList: true,
84
- subtree: true
85
- });
86
-
87
- // Interceptar la inserción de reglas CSS para JSS
88
- const originalInsertRule = CSSStyleSheet.prototype.insertRule;
89
- CSSStyleSheet.prototype.insertRule = function (rule, index) {
90
- // Verificar si la regla ya existe en otra hoja de estilos
91
- if (rule && typeof rule === 'string') {
92
- const existingSheets = Array.from(document.styleSheets);
93
- for (const sheet of existingSheets) {
94
- try {
95
- const rules = Array.from(sheet.cssRules || []);
96
- for (const existingRule of rules) {
97
- if (existingRule.cssText === rule) {
98
- console.log('Energy UI: Regla CSS duplicada detectada y evitada');
99
- return 0; // Retornar índice 0 para evitar errores
100
- }
101
- }
102
- } catch (e) {
103
- // Ignorar errores de CORS
104
- }
105
- }
106
- }
107
- return originalInsertRule.call(this, rule, index);
108
- };
109
-
110
- // Marcar como configurado
111
- window.__energyUI_styleDeduplicationConfigured = true;
112
- console.log('Energy UI: Sistema de deduplicación de estilos configurado');
113
- };
114
-
115
- /**
116
- * Función para limpiar estilos duplicados existentes
117
- */
118
- const cleanupDuplicateStyles = () => {
119
- const styleElements = document.querySelectorAll('style');
120
- const seenContents = new Set();
121
- styleElements.forEach(style => {
122
- const content = style.textContent || '';
123
- if (content && (content.includes('UT') || content.includes('energy-ui') || content.includes('energyui') || content.includes('__'))) {
124
- const hash = generateStyleHash(content);
125
- if (seenContents.has(hash)) {
126
- console.log('Energy UI: Removiendo estilo duplicado existente');
127
- style.remove();
128
- } else {
129
- seenContents.add(hash);
130
- markStyleAsLoaded(content, style);
131
- }
132
- }
133
- });
134
- };
135
-
136
- /**
137
- * Hook para React
138
- */
139
- const useStyleDeduplication = function () {
140
- let enableStyleDeduplication = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
141
- (0, _react.useEffect)(() => {
142
- if (enableStyleDeduplication) {
143
- interceptStyleCreation();
144
- cleanupDuplicateStyles();
145
- }
146
- }, [enableStyleDeduplication]);
147
- };
148
-
149
- /**
150
- * Función para configuración manual
151
- */
152
- exports.useStyleDeduplication = useStyleDeduplication;
153
- const setupStyleDeduplication = () => {
154
- interceptStyleCreation();
155
- cleanupDuplicateStyles();
156
- };
157
-
158
- /**
159
- * Función para verificar si está configurado
160
- */
161
- exports.setupStyleDeduplication = setupStyleDeduplication;
162
- const isStyleDeduplicationConfigured = () => {
163
- return window.__energyUI_styleDeduplicationConfigured === true;
164
- };
165
-
166
- /**
167
- * Función para obtener estadísticas de deduplicación
168
- */
169
- exports.isStyleDeduplicationConfigured = isStyleDeduplicationConfigured;
170
- const getDeduplicationStats = () => {
171
- return {
172
- loadedStylesCount: loadedStyles.size,
173
- styleElementsCount: styleElements.size,
174
- isConfigured: isStyleDeduplicationConfigured()
175
- };
176
- };
177
- exports.getDeduplicationStats = getDeduplicationStats;
178
- var _default = exports.default = {
179
- getDeduplicationStats,
180
- isStyleDeduplicationConfigured,
181
- setupStyleDeduplication,
182
- useStyleDeduplication
183
- };