ngx-dsxlibrary 2.21.28 → 2.21.30

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.
@@ -1,13 +1,17 @@
1
- import { DecimalPipe } from '@angular/common';
1
+ import * as i1$1 from '@angular/common';
2
+ import { DecimalPipe, CommonModule } from '@angular/common';
2
3
  import * as i0 from '@angular/core';
3
- import { Input, Component, forwardRef, viewChild, input, signal, effect, EventEmitter, Output, model } from '@angular/core';
4
+ import { Input, Component, forwardRef, viewChild, input, signal, EventEmitter, effect, Output, model } from '@angular/core';
4
5
  import * as i1 from 'primeng/tag';
5
6
  import { TagModule } from 'primeng/tag';
6
7
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
7
8
  import { FileUpload } from 'primeng/fileupload';
8
- import * as i1$1 from 'primeng/tree';
9
+ import * as i2 from 'primeng/tree';
9
10
  import { TreeModule } from 'primeng/tree';
11
+ import * as i3 from 'primeng/api';
10
12
  import { CountUpDirective } from 'ngx-countup';
13
+ import * as i2$1 from 'primeng/avatar';
14
+ import { AvatarModule } from 'primeng/avatar';
11
15
  import * as i1$2 from 'primeng/dialog';
12
16
  import { DialogModule } from 'primeng/dialog';
13
17
  import * as i1$3 from '@angular/platform-browser';
@@ -196,28 +200,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
196
200
 
197
201
  class JsonViewerComponent {
198
202
  data = input(null, ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
203
+ mode = input('view', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
204
+ textKey = input('Texto', ...(ngDevMode ? [{ debugName: "textKey" }] : /* istanbul ignore next */ []));
205
+ activeKey = input('Activo', ...(ngDevMode ? [{ debugName: "activeKey" }] : /* istanbul ignore next */ []));
206
+ itemsKey = input('Items', ...(ngDevMode ? [{ debugName: "itemsKey" }] : /* istanbul ignore next */ []));
207
+ showStatusAsSymbol = input(true, ...(ngDevMode ? [{ debugName: "showStatusAsSymbol" }] : /* istanbul ignore next */ []));
208
+ valueChange = new EventEmitter();
199
209
  nodes = [];
200
210
  selectedNode = null;
211
+ disabled = false;
201
212
  controlValue = null;
213
+ normalizedValue = {};
214
+ maxNormalizationDepth = 20;
215
+ onChange = () => undefined;
216
+ onTouched = () => undefined;
202
217
  constructor() {
203
218
  effect(() => {
204
219
  if (this.controlValue === null || this.controlValue === undefined) {
205
- this.updateNodes(this.data());
220
+ this.updateNodes(this.data(), false);
206
221
  }
207
222
  });
208
223
  }
209
224
  writeValue(value) {
210
225
  this.controlValue = value;
211
- this.updateNodes(value);
226
+ this.updateNodes(value, false);
212
227
  }
213
228
  registerOnChange(fn) {
214
- void fn;
229
+ this.onChange = fn;
215
230
  }
216
231
  registerOnTouched(fn) {
217
- void fn;
232
+ this.onTouched = fn;
218
233
  }
219
234
  setDisabledState(isDisabled) {
220
- void isDisabled;
235
+ this.disabled = isDisabled;
221
236
  }
222
237
  onNodeSelect(event) {
223
238
  const node = event?.node;
@@ -227,57 +242,225 @@ class JsonViewerComponent {
227
242
  this.selectedNode = null;
228
243
  this.nodes = [...this.nodes];
229
244
  }
230
- updateNodes(value) {
231
- this.nodes = this.buildTree(this.parseIfNeeded(value));
245
+ isEditMode() {
246
+ const modeValue = this.mode();
247
+ const editEnabled = typeof modeValue === 'boolean' ? modeValue : modeValue === 'edit';
248
+ return editEnabled && !this.disabled;
249
+ }
250
+ getNodeMeta(node) {
251
+ const nodeData = node.data;
252
+ if (!nodeData || typeof nodeData !== 'object')
253
+ return null;
254
+ const kind = nodeData.kind;
255
+ if (!kind)
256
+ return null;
257
+ return nodeData;
258
+ }
259
+ onTextEdit(path, value, nodeMeta) {
260
+ if (!this.isEditMode())
261
+ return;
262
+ this.setValueAtPath(path, value);
263
+ // Actualiza solo el meta del nodo para reflejar el cambio sin reconstruir el árbol.
264
+ if (nodeMeta.kind === 'compact-item') {
265
+ nodeMeta.text = value;
266
+ }
267
+ else if (nodeMeta.kind === 'text-primitive') {
268
+ nodeMeta.value = value;
269
+ }
270
+ this.emitCurrentValue();
271
+ }
272
+ onTextBlur() {
273
+ this.onTouched();
274
+ }
275
+ onActiveToggle(path, checked, nodeMeta) {
276
+ if (!this.isEditMode())
277
+ return;
278
+ this.setValueAtPath(path, checked);
279
+ // Actualiza el meta del nodo y recalcula el visual del símbolo.
280
+ nodeMeta.activeBoolean = checked;
281
+ nodeMeta.activeVisual = checked
282
+ ? this.showStatusAsSymbol()
283
+ ? '✓'
284
+ : 'true'
285
+ : this.showStatusAsSymbol()
286
+ ? '✗'
287
+ : 'false';
288
+ // Fuerza detección de cambio en el array sin reconstruir el árbol.
289
+ this.nodes = [...this.nodes];
290
+ this.emitCurrentValue();
291
+ this.onTouched();
292
+ }
293
+ updateNodes(value, emit) {
294
+ this.normalizedValue = this.parseIfNeeded(value);
295
+ this.nodes = this.buildTree(this.normalizedValue);
296
+ if (emit) {
297
+ this.emitCurrentValue();
298
+ }
232
299
  }
233
300
  parseIfNeeded(data) {
234
- if (!data)
301
+ if (data === null || data === undefined || data === '')
235
302
  return {};
303
+ return this.normalizeData(data, 0);
304
+ }
305
+ normalizeData(data, depth) {
306
+ if (depth > this.maxNormalizationDepth)
307
+ return data;
236
308
  if (typeof data === 'string') {
237
- try {
238
- return JSON.parse(data);
239
- }
240
- catch {
241
- return {};
309
+ const parsed = this.tryParseJsonString(data);
310
+ if (parsed.parsed) {
311
+ return this.normalizeData(parsed.value, depth + 1);
242
312
  }
313
+ return data;
314
+ }
315
+ if (Array.isArray(data)) {
316
+ return data.map((item) => this.normalizeData(item, depth + 1));
317
+ }
318
+ if (typeof data === 'object' && data !== null) {
319
+ return Object.entries(data).reduce((acc, [key, value]) => {
320
+ acc[key] = this.normalizeData(value, depth + 1);
321
+ return acc;
322
+ }, {});
243
323
  }
244
324
  return data;
245
325
  }
246
- buildTree(data, parentKey = '0') {
326
+ tryParseJsonString(value) {
327
+ const trimmed = value.trim();
328
+ // Solo intentamos parsear si parece JSON para evitar costo innecesario
329
+ // en strings de texto común.
330
+ const looksLikeJson = (trimmed.startsWith('{') && trimmed.endsWith('}')) ||
331
+ (trimmed.startsWith('[') && trimmed.endsWith(']'));
332
+ if (!looksLikeJson) {
333
+ return { parsed: false, value };
334
+ }
335
+ try {
336
+ return { parsed: true, value: JSON.parse(trimmed) };
337
+ }
338
+ catch {
339
+ return { parsed: false, value };
340
+ }
341
+ }
342
+ buildTree(data, parentKey = '0', path = []) {
247
343
  if (Array.isArray(data)) {
248
344
  return data.map((item, index) => {
249
345
  const key = `${parentKey}-${index}`;
346
+ const itemPath = [...path, index];
347
+ const compactItem = this.toCompactTextAndActive(item, itemPath, `[${String(index).padStart(2, '0')}]`);
348
+ if (compactItem) {
349
+ return {
350
+ key,
351
+ label: `${compactItem.indexLabel} Texto: ${compactItem.text} | ${compactItem.activeVisual}`,
352
+ icon: 'pi pi-file',
353
+ data: compactItem,
354
+ };
355
+ }
250
356
  if (this.isComplex(item)) {
251
357
  return {
252
358
  key,
253
359
  label: `[${index}]`,
254
- //icon: this.getIcon(item),
255
- children: this.buildTree(item, key),
360
+ icon: this.getIcon(item),
361
+ children: this.buildTree(item, key, itemPath),
256
362
  };
257
363
  }
258
364
  return {
259
365
  key,
260
366
  label: `[${index}]: ${this.formatPrimitive(item)}`,
261
- //icon: 'pi pi-file',
367
+ icon: 'pi pi-file',
262
368
  };
263
369
  });
264
370
  }
265
371
  if (typeof data === 'object' && data !== null) {
266
- return Object.keys(data).map((key, index) => {
267
- const value = data[key];
372
+ const objectData = data;
373
+ return Object.keys(objectData).flatMap((key, index) => {
374
+ const value = objectData[key];
268
375
  const nodeKey = `${parentKey}-${index}`;
376
+ const childPath = [...path, key];
377
+ const activeKeyName = this.activeKey();
378
+ const itemsKeyName = this.itemsKey();
379
+ const textKeyName = this.textKey();
380
+ if (key === itemsKeyName && Array.isArray(value)) {
381
+ return this.buildTree(value, nodeKey, childPath);
382
+ }
383
+ if (this.isItemsContainer(value)) {
384
+ const container = value;
385
+ const hasActive = Object.prototype.hasOwnProperty.call(container, activeKeyName);
386
+ const label = hasActive
387
+ ? `${key} | ${this.formatActiveSymbol(container[activeKeyName])}`
388
+ : key;
389
+ const itemsChildren = this.buildTree(container[itemsKeyName], `${nodeKey}-0`, [...childPath, itemsKeyName]);
390
+ const additionalChildren = Object.keys(container)
391
+ .filter((childKey) => childKey !== itemsKeyName && childKey !== activeKeyName)
392
+ .flatMap((childKey, childIndex) => {
393
+ return this.buildTree({ [childKey]: container[childKey] }, `${nodeKey}-${childIndex + 1}`, childPath);
394
+ });
395
+ const nodeMeta = hasActive
396
+ ? {
397
+ kind: 'group-active',
398
+ title: key,
399
+ activeVisual: this.formatActiveSymbol(container[activeKeyName]),
400
+ activeBoolean: this.toBooleanLike(container[activeKeyName]),
401
+ activePath: [...childPath, activeKeyName],
402
+ }
403
+ : undefined;
404
+ return {
405
+ key: nodeKey,
406
+ label,
407
+ icon: 'pi pi-folder',
408
+ children: [...itemsChildren, ...additionalChildren],
409
+ data: nodeMeta,
410
+ };
411
+ }
412
+ const compactValue = this.toCompactTextAndActive(value, childPath, key);
413
+ if (compactValue) {
414
+ return {
415
+ key: nodeKey,
416
+ label: `${key}: Texto: ${compactValue.text} | ${compactValue.activeVisual}`,
417
+ icon: 'pi pi-file',
418
+ data: compactValue,
419
+ };
420
+ }
421
+ const groupedValue = this.toGroupWithActive(value);
422
+ if (groupedValue) {
423
+ groupedValue.meta.title = key;
424
+ groupedValue.meta.activePath = [...childPath, activeKeyName];
425
+ return {
426
+ key: nodeKey,
427
+ label: `${key} | ${groupedValue.activeSymbol}`,
428
+ icon: 'pi pi-folder',
429
+ children: this.buildTree(groupedValue.children, nodeKey, childPath),
430
+ data: groupedValue.meta,
431
+ };
432
+ }
269
433
  if (this.isComplex(value)) {
270
434
  return {
271
435
  key: nodeKey,
272
436
  label: key,
273
- //icon: this.getIcon(value),
274
- children: this.buildTree(value, nodeKey),
437
+ icon: this.getIcon(value),
438
+ children: this.buildTree(value, nodeKey, childPath),
275
439
  };
276
440
  }
441
+ const primitiveMeta = key === textKeyName
442
+ ? {
443
+ kind: 'text-primitive',
444
+ key,
445
+ value: this.formatPrimitive(value),
446
+ path: childPath,
447
+ }
448
+ : key === activeKeyName
449
+ ? {
450
+ kind: 'active-primitive',
451
+ key,
452
+ activeVisual: this.formatActiveSymbol(value),
453
+ activeBoolean: this.toBooleanLike(value),
454
+ path: childPath,
455
+ }
456
+ : undefined;
277
457
  return {
278
458
  key: nodeKey,
279
- label: `${key}: ${this.formatPrimitive(value)}`,
459
+ label: key === activeKeyName
460
+ ? `${key}: ${this.formatActiveSymbol(value)}`
461
+ : `${key}: ${this.formatPrimitive(value)}`,
280
462
  icon: 'pi pi-file',
463
+ data: primitiveMeta,
281
464
  };
282
465
  });
283
466
  }
@@ -299,6 +482,87 @@ class JsonViewerComponent {
299
482
  return value;
300
483
  return String(value);
301
484
  }
485
+ toCompactTextAndActive(value, basePath, indexLabel) {
486
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
487
+ return null;
488
+ }
489
+ const record = value;
490
+ const textKeyName = this.textKey();
491
+ const activeKeyName = this.activeKey();
492
+ const hasText = Object.prototype.hasOwnProperty.call(record, textKeyName);
493
+ const hasActive = Object.prototype.hasOwnProperty.call(record, activeKeyName);
494
+ if (!hasText || !hasActive)
495
+ return null;
496
+ const activeValue = record[activeKeyName];
497
+ return {
498
+ kind: 'compact-item',
499
+ indexLabel,
500
+ text: this.formatPrimitive(record[textKeyName]),
501
+ activeVisual: this.formatActiveSymbol(activeValue),
502
+ activeBoolean: this.toBooleanLike(activeValue),
503
+ textPath: [...basePath, textKeyName],
504
+ activePath: [...basePath, activeKeyName],
505
+ };
506
+ }
507
+ isItemsContainer(value) {
508
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
509
+ return false;
510
+ }
511
+ return Array.isArray(value[this.itemsKey()]);
512
+ }
513
+ toGroupWithActive(value) {
514
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
515
+ return null;
516
+ }
517
+ const record = value;
518
+ const activeKeyName = this.activeKey();
519
+ const hasActive = Object.prototype.hasOwnProperty.call(record, activeKeyName);
520
+ if (!hasActive)
521
+ return null;
522
+ const childEntries = Object.entries(record).filter(([childKey]) => childKey !== activeKeyName);
523
+ if (childEntries.length === 0)
524
+ return null;
525
+ const hasComplexChildren = childEntries.some(([, childValue]) => this.isComplex(childValue));
526
+ if (!hasComplexChildren)
527
+ return null;
528
+ return {
529
+ activeSymbol: this.formatActiveSymbol(record[activeKeyName]),
530
+ children: Object.fromEntries(childEntries),
531
+ meta: {
532
+ kind: 'group-active',
533
+ title: '',
534
+ activeVisual: this.formatActiveSymbol(record[activeKeyName]),
535
+ activeBoolean: this.toBooleanLike(record[activeKeyName]),
536
+ },
537
+ };
538
+ }
539
+ formatActiveSymbol(value) {
540
+ const boolLike = this.toBooleanLike(value);
541
+ if (boolLike === true)
542
+ return this.showStatusAsSymbol() ? '✓' : 'true';
543
+ if (boolLike === false)
544
+ return this.showStatusAsSymbol() ? '✗' : 'false';
545
+ return this.formatPrimitive(value);
546
+ }
547
+ toBooleanLike(value) {
548
+ if (typeof value === 'boolean')
549
+ return value;
550
+ if (typeof value === 'number') {
551
+ if (value === 1)
552
+ return true;
553
+ if (value === 0)
554
+ return false;
555
+ return null;
556
+ }
557
+ if (typeof value === 'string') {
558
+ const normalized = value.trim().toLowerCase();
559
+ if (normalized === 'true' || normalized === '1')
560
+ return true;
561
+ if (normalized === 'false' || normalized === '0')
562
+ return false;
563
+ }
564
+ return null;
565
+ }
302
566
  getIcon(value) {
303
567
  if (Array.isArray(value))
304
568
  return 'pi pi-list';
@@ -306,25 +570,64 @@ class JsonViewerComponent {
306
570
  return 'pi pi-folder';
307
571
  return 'pi pi-file';
308
572
  }
573
+ setValueAtPath(path, value) {
574
+ if (!path.length ||
575
+ typeof this.normalizedValue !== 'object' ||
576
+ this.normalizedValue === null) {
577
+ return;
578
+ }
579
+ let target = this.normalizedValue;
580
+ for (let index = 0; index < path.length - 1; index += 1) {
581
+ const segment = path[index];
582
+ if (target === null || target === undefined)
583
+ return;
584
+ target = target[segment];
585
+ }
586
+ const lastSegment = path[path.length - 1];
587
+ if (target !== null && target !== undefined) {
588
+ target[lastSegment] = value;
589
+ }
590
+ }
591
+ emitUpdatedValue() {
592
+ this.nodes = this.buildTree(this.normalizedValue);
593
+ this.emitCurrentValue();
594
+ this.onTouched();
595
+ }
596
+ emitCurrentValue() {
597
+ const payload = this.cloneValue(this.normalizedValue);
598
+ this.controlValue = payload;
599
+ this.onChange(payload);
600
+ this.valueChange.emit(payload);
601
+ }
602
+ cloneValue(value) {
603
+ try {
604
+ return JSON.parse(JSON.stringify(value));
605
+ }
606
+ catch {
607
+ return value;
608
+ }
609
+ }
309
610
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: JsonViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
310
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.11", type: JsonViewerComponent, isStandalone: true, selector: "app-json-viewer", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
611
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.11", type: JsonViewerComponent, isStandalone: true, selector: "app-json-viewer", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, textKey: { classPropertyName: "textKey", publicName: "textKey", isSignal: true, isRequired: false, transformFunction: null }, activeKey: { classPropertyName: "activeKey", publicName: "activeKey", isSignal: true, isRequired: false, transformFunction: null }, itemsKey: { classPropertyName: "itemsKey", publicName: "itemsKey", isSignal: true, isRequired: false, transformFunction: null }, showStatusAsSymbol: { classPropertyName: "showStatusAsSymbol", publicName: "showStatusAsSymbol", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, providers: [
311
612
  {
312
613
  provide: NG_VALUE_ACCESSOR,
313
614
  useExisting: forwardRef(() => JsonViewerComponent),
314
615
  multi: true,
315
616
  },
316
- ], ngImport: i0, template: "<p-tree\r\n\t[value]=\"nodes\"\r\n\tclass=\"json-tree w-full\"\r\n\tselectionMode=\"single\"\r\n\t[(selection)]=\"selectedNode\"\r\n\t[highlightOnSelect]=\"false\"\r\n\t(onNodeSelect)=\"onNodeSelect($event)\"\r\n>\r\n</p-tree>\r\n", styles: [":host ::ng-deep .json-tree .p-tree-node-content,:host ::ng-deep .json-tree .p-treenode-content{padding:.02rem .15rem!important}\n"], dependencies: [{ kind: "ngmodule", type: TreeModule }, { kind: "component", type: i1$1.Tree, selector: "p-tree", inputs: ["value", "selectionMode", "loadingMode", "selection", "styleClass", "contextMenu", "contextMenuSelectionMode", "contextMenuSelection", "draggableScope", "droppableScope", "draggableNodes", "droppableNodes", "metaKeySelection", "propagateSelectionUp", "propagateSelectionDown", "loading", "loadingIcon", "emptyMessage", "ariaLabel", "togglerAriaLabel", "ariaLabelledBy", "validateDrop", "filter", "filterInputAutoFocus", "filterBy", "filterMode", "filterOptions", "filterPlaceholder", "filteredNodes", "filterLocale", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "indentation", "_templateMap", "trackBy", "highlightOnSelect"], outputs: ["selectionChange", "contextMenuSelectionChange", "onNodeSelect", "onNodeUnselect", "onNodeExpand", "onNodeCollapse", "onNodeContextMenuSelect", "onNodeDoubleClick", "onNodeDrop", "onLazyLoad", "onScroll", "onScrollIndexChange", "onFilter"] }] });
617
+ ], ngImport: i0, template: "<p-tree\r\n [value]=\"nodes\"\r\n class=\"json-tree w-full\"\r\n selectionMode=\"single\"\r\n [(selection)]=\"selectedNode\"\r\n [highlightOnSelect]=\"false\"\r\n (onNodeSelect)=\"onNodeSelect($event)\"\r\n>\r\n <ng-template let-node pTemplate=\"default\">\r\n <div class=\"json-node\">\r\n <ng-container *ngIf=\"getNodeMeta(node) as meta; else defaultLabel\">\r\n <ng-container [ngSwitch]=\"meta.kind\">\r\n <ng-container *ngSwitchCase=\"'compact-item'\">\r\n <span class=\"json-prefix\">{{ meta.indexLabel || \"\" }}</span>\r\n <span class=\"json-key\"> Texto: </span>\r\n <ng-container *ngIf=\"isEditMode(); else compactTextView\">\r\n <input\r\n type=\"text\"\r\n class=\"json-text-input\"\r\n [class.json-text-inactive]=\"meta.activeBoolean === false\"\r\n [value]=\"meta.text || ''\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n (click)=\"$event.stopPropagation()\"\r\n (keydown)=\"$event.stopPropagation()\"\r\n (input)=\"\r\n onTextEdit(\r\n $any(meta.textPath),\r\n $any($event.target).value,\r\n meta\r\n )\r\n \"\r\n (blur)=\"onTextBlur()\"\r\n />\r\n </ng-container>\r\n <ng-template #compactTextView>\r\n <span [class.json-text-inactive]=\"meta.activeBoolean === false\">{{\r\n meta.text || \"\"\r\n }}</span>\r\n </ng-template>\r\n <span class=\"json-separator\"> | </span>\r\n <span class=\"json-status\">{{ meta.activeVisual || \"\" }}</span>\r\n <input\r\n *ngIf=\"isEditMode()\"\r\n type=\"checkbox\"\r\n class=\"json-checkbox\"\r\n [checked]=\"meta.activeBoolean === true\"\r\n [disabled]=\"meta.activeBoolean === null\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n (click)=\"$event.stopPropagation()\"\r\n (change)=\"\r\n onActiveToggle(\r\n $any(meta.activePath),\r\n $any($event.target).checked,\r\n meta\r\n )\r\n \"\r\n />\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'group-active'\">\r\n <span>{{ meta.title || \"\" }}</span>\r\n <span class=\"json-separator\"> | </span>\r\n <span class=\"json-status\">{{ meta.activeVisual || \"\" }}</span>\r\n <input\r\n *ngIf=\"isEditMode() && meta.activePath\"\r\n type=\"checkbox\"\r\n class=\"json-checkbox\"\r\n [checked]=\"meta.activeBoolean === true\"\r\n [disabled]=\"meta.activeBoolean === null\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n (click)=\"$event.stopPropagation()\"\r\n (change)=\"\r\n onActiveToggle(\r\n $any(meta.activePath),\r\n $any($event.target).checked,\r\n meta\r\n )\r\n \"\r\n />\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'text-primitive'\">\r\n <span>{{ meta.key || \"\" }}:</span>\r\n <ng-container *ngIf=\"isEditMode(); else textPrimitiveView\">\r\n <input\r\n type=\"text\"\r\n class=\"json-text-input\"\r\n [value]=\"meta.value || ''\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n (click)=\"$event.stopPropagation()\"\r\n (keydown)=\"$event.stopPropagation()\"\r\n (input)=\"\r\n onTextEdit($any(meta.path), $any($event.target).value, meta)\r\n \"\r\n (blur)=\"onTextBlur()\"\r\n />\r\n </ng-container>\r\n <ng-template #textPrimitiveView>\r\n <span>{{ meta.value || \"\" }}</span>\r\n </ng-template>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'active-primitive'\">\r\n <span>{{ meta.key || \"\" }}:</span>\r\n <span class=\"json-status\">{{ meta.activeVisual || \"\" }}</span>\r\n <input\r\n *ngIf=\"isEditMode()\"\r\n type=\"checkbox\"\r\n class=\"json-checkbox\"\r\n [checked]=\"meta.activeBoolean === true\"\r\n [disabled]=\"meta.activeBoolean === null\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n (click)=\"$event.stopPropagation()\"\r\n (change)=\"\r\n onActiveToggle(\r\n $any(meta.path),\r\n $any($event.target).checked,\r\n meta\r\n )\r\n \"\r\n />\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchDefault>\r\n {{ node.label }}\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-template #defaultLabel>\r\n {{ node.label }}\r\n </ng-template>\r\n </div>\r\n </ng-template>\r\n</p-tree>\r\n", styles: [":host ::ng-deep .json-tree .p-tree-node-content,:host ::ng-deep .json-tree .p-treenode-content{padding:.02rem .15rem!important;display:flex;align-items:center;width:100%;min-width:0}:host ::ng-deep .json-tree .p-tree-node-label,:host ::ng-deep .json-tree .p-tree-node-label>span{flex:1 1 0;min-width:0;display:flex}:host ::ng-deep .json-tree .json-node{display:flex;align-items:center;gap:.25rem;width:100%;min-width:0}:host ::ng-deep .json-tree .json-prefix,:host ::ng-deep .json-tree .json-key,:host ::ng-deep .json-tree .json-separator,:host ::ng-deep .json-tree .json-status{white-space:nowrap;flex-shrink:0}:host ::ng-deep .json-tree .json-text-input{flex:1 1 0;min-width:0;border:1px solid #cbd5e1;border-radius:.25rem;padding:.15rem .5rem;font-size:.875rem}:host ::ng-deep .json-tree .json-text-inactive{color:#8b5e61}:host ::ng-deep .json-tree input.json-text-input.json-text-inactive{background-color:#f9f2f2;border-color:#e5c8cb}:host ::ng-deep .json-tree .json-checkbox{width:.9rem;height:.9rem;cursor:pointer;flex-shrink:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "ngmodule", type: TreeModule }, { kind: "component", type: i2.Tree, selector: "p-tree", inputs: ["value", "selectionMode", "loadingMode", "selection", "styleClass", "contextMenu", "contextMenuSelectionMode", "contextMenuSelection", "draggableScope", "droppableScope", "draggableNodes", "droppableNodes", "metaKeySelection", "propagateSelectionUp", "propagateSelectionDown", "loading", "loadingIcon", "emptyMessage", "ariaLabel", "togglerAriaLabel", "ariaLabelledBy", "validateDrop", "filter", "filterInputAutoFocus", "filterBy", "filterMode", "filterOptions", "filterPlaceholder", "filteredNodes", "filterLocale", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "indentation", "_templateMap", "trackBy", "highlightOnSelect"], outputs: ["selectionChange", "contextMenuSelectionChange", "onNodeSelect", "onNodeUnselect", "onNodeExpand", "onNodeCollapse", "onNodeContextMenuSelect", "onNodeDoubleClick", "onNodeDrop", "onLazyLoad", "onScroll", "onScrollIndexChange", "onFilter"] }, { kind: "directive", type: i3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }] });
317
618
  }
318
619
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: JsonViewerComponent, decorators: [{
319
620
  type: Component,
320
- args: [{ selector: 'app-json-viewer', standalone: true, imports: [TreeModule], providers: [
621
+ args: [{ selector: 'app-json-viewer', standalone: true, imports: [CommonModule, TreeModule], providers: [
321
622
  {
322
623
  provide: NG_VALUE_ACCESSOR,
323
624
  useExisting: forwardRef(() => JsonViewerComponent),
324
625
  multi: true,
325
626
  },
326
- ], template: "<p-tree\r\n\t[value]=\"nodes\"\r\n\tclass=\"json-tree w-full\"\r\n\tselectionMode=\"single\"\r\n\t[(selection)]=\"selectedNode\"\r\n\t[highlightOnSelect]=\"false\"\r\n\t(onNodeSelect)=\"onNodeSelect($event)\"\r\n>\r\n</p-tree>\r\n", styles: [":host ::ng-deep .json-tree .p-tree-node-content,:host ::ng-deep .json-tree .p-treenode-content{padding:.02rem .15rem!important}\n"] }]
327
- }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }] } });
627
+ ], template: "<p-tree\r\n [value]=\"nodes\"\r\n class=\"json-tree w-full\"\r\n selectionMode=\"single\"\r\n [(selection)]=\"selectedNode\"\r\n [highlightOnSelect]=\"false\"\r\n (onNodeSelect)=\"onNodeSelect($event)\"\r\n>\r\n <ng-template let-node pTemplate=\"default\">\r\n <div class=\"json-node\">\r\n <ng-container *ngIf=\"getNodeMeta(node) as meta; else defaultLabel\">\r\n <ng-container [ngSwitch]=\"meta.kind\">\r\n <ng-container *ngSwitchCase=\"'compact-item'\">\r\n <span class=\"json-prefix\">{{ meta.indexLabel || \"\" }}</span>\r\n <span class=\"json-key\"> Texto: </span>\r\n <ng-container *ngIf=\"isEditMode(); else compactTextView\">\r\n <input\r\n type=\"text\"\r\n class=\"json-text-input\"\r\n [class.json-text-inactive]=\"meta.activeBoolean === false\"\r\n [value]=\"meta.text || ''\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n (click)=\"$event.stopPropagation()\"\r\n (keydown)=\"$event.stopPropagation()\"\r\n (input)=\"\r\n onTextEdit(\r\n $any(meta.textPath),\r\n $any($event.target).value,\r\n meta\r\n )\r\n \"\r\n (blur)=\"onTextBlur()\"\r\n />\r\n </ng-container>\r\n <ng-template #compactTextView>\r\n <span [class.json-text-inactive]=\"meta.activeBoolean === false\">{{\r\n meta.text || \"\"\r\n }}</span>\r\n </ng-template>\r\n <span class=\"json-separator\"> | </span>\r\n <span class=\"json-status\">{{ meta.activeVisual || \"\" }}</span>\r\n <input\r\n *ngIf=\"isEditMode()\"\r\n type=\"checkbox\"\r\n class=\"json-checkbox\"\r\n [checked]=\"meta.activeBoolean === true\"\r\n [disabled]=\"meta.activeBoolean === null\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n (click)=\"$event.stopPropagation()\"\r\n (change)=\"\r\n onActiveToggle(\r\n $any(meta.activePath),\r\n $any($event.target).checked,\r\n meta\r\n )\r\n \"\r\n />\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'group-active'\">\r\n <span>{{ meta.title || \"\" }}</span>\r\n <span class=\"json-separator\"> | </span>\r\n <span class=\"json-status\">{{ meta.activeVisual || \"\" }}</span>\r\n <input\r\n *ngIf=\"isEditMode() && meta.activePath\"\r\n type=\"checkbox\"\r\n class=\"json-checkbox\"\r\n [checked]=\"meta.activeBoolean === true\"\r\n [disabled]=\"meta.activeBoolean === null\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n (click)=\"$event.stopPropagation()\"\r\n (change)=\"\r\n onActiveToggle(\r\n $any(meta.activePath),\r\n $any($event.target).checked,\r\n meta\r\n )\r\n \"\r\n />\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'text-primitive'\">\r\n <span>{{ meta.key || \"\" }}:</span>\r\n <ng-container *ngIf=\"isEditMode(); else textPrimitiveView\">\r\n <input\r\n type=\"text\"\r\n class=\"json-text-input\"\r\n [value]=\"meta.value || ''\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n (click)=\"$event.stopPropagation()\"\r\n (keydown)=\"$event.stopPropagation()\"\r\n (input)=\"\r\n onTextEdit($any(meta.path), $any($event.target).value, meta)\r\n \"\r\n (blur)=\"onTextBlur()\"\r\n />\r\n </ng-container>\r\n <ng-template #textPrimitiveView>\r\n <span>{{ meta.value || \"\" }}</span>\r\n </ng-template>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'active-primitive'\">\r\n <span>{{ meta.key || \"\" }}:</span>\r\n <span class=\"json-status\">{{ meta.activeVisual || \"\" }}</span>\r\n <input\r\n *ngIf=\"isEditMode()\"\r\n type=\"checkbox\"\r\n class=\"json-checkbox\"\r\n [checked]=\"meta.activeBoolean === true\"\r\n [disabled]=\"meta.activeBoolean === null\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n (click)=\"$event.stopPropagation()\"\r\n (change)=\"\r\n onActiveToggle(\r\n $any(meta.path),\r\n $any($event.target).checked,\r\n meta\r\n )\r\n \"\r\n />\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchDefault>\r\n {{ node.label }}\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-template #defaultLabel>\r\n {{ node.label }}\r\n </ng-template>\r\n </div>\r\n </ng-template>\r\n</p-tree>\r\n", styles: [":host ::ng-deep .json-tree .p-tree-node-content,:host ::ng-deep .json-tree .p-treenode-content{padding:.02rem .15rem!important;display:flex;align-items:center;width:100%;min-width:0}:host ::ng-deep .json-tree .p-tree-node-label,:host ::ng-deep .json-tree .p-tree-node-label>span{flex:1 1 0;min-width:0;display:flex}:host ::ng-deep .json-tree .json-node{display:flex;align-items:center;gap:.25rem;width:100%;min-width:0}:host ::ng-deep .json-tree .json-prefix,:host ::ng-deep .json-tree .json-key,:host ::ng-deep .json-tree .json-separator,:host ::ng-deep .json-tree .json-status{white-space:nowrap;flex-shrink:0}:host ::ng-deep .json-tree .json-text-input{flex:1 1 0;min-width:0;border:1px solid #cbd5e1;border-radius:.25rem;padding:.15rem .5rem;font-size:.875rem}:host ::ng-deep .json-tree .json-text-inactive{color:#8b5e61}:host ::ng-deep .json-tree input.json-text-input.json-text-inactive{background-color:#f9f2f2;border-color:#e5c8cb}:host ::ng-deep .json-tree .json-checkbox{width:.9rem;height:.9rem;cursor:pointer;flex-shrink:0}\n"] }]
628
+ }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], textKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "textKey", required: false }] }], activeKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeKey", required: false }] }], itemsKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemsKey", required: false }] }], showStatusAsSymbol: [{ type: i0.Input, args: [{ isSignal: true, alias: "showStatusAsSymbol", required: false }] }], valueChange: [{
629
+ type: Output
630
+ }] } });
328
631
 
329
632
  class KpicardComponent {
330
633
  //type = input.required<string>();
@@ -433,10 +736,12 @@ class DocxPreviewComponent {
433
736
  }
434
737
  async renderDocx(fileBlob, container, options, token) {
435
738
  try {
436
- // Use Function constructor to bypass Vite's static import analysis.
437
- // This makes 'docx-preview' a truly optional peer dependency.
438
- const load = new Function('m', 'return import(m)');
439
- const docxPreviewModule = (await load('docx-preview'));
739
+ // Import dinámico directo: esbuild/Vite lo interceptan en build time.
740
+ // Si el consumidor no instaló docx-preview, el catch captura el error
741
+ // y muestra el mensaje de fallback sin romper el resto de la librería.
742
+ const docxPreviewModule = (await import(
743
+ // @ts-ignore — peer opcional; puede no existir en todos los consumidores
744
+ 'docx-preview'));
440
745
  if (token !== this.renderToken || !this.visibleState()) {
441
746
  return;
442
747
  }
@@ -460,11 +765,11 @@ class DocxPreviewComponent {
460
765
  this.visibleChange.emit(false);
461
766
  }
462
767
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DocxPreviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
463
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.11", type: DocxPreviewComponent, isStandalone: true, selector: "app-docx-preview", inputs: { visible: { classPropertyName: "visible", publicName: "visible", isSignal: false, isRequired: false, transformFunction: null }, blob: { classPropertyName: "blob", publicName: "blob", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { visibleChange: "visibleChange" }, viewQueries: [{ propertyName: "view", first: true, predicate: ["viewer"], descendants: true, isSignal: true }], ngImport: i0, template: "<p-dialog\r\n header=\"Vista preliminar del documento\"\r\n [visible]=\"visible\"\r\n (onHide)=\"onHide()\"\r\n [modal]=\"true\"\r\n [breakpoints]=\"{ '1199px': '75vw', '575px': '90vw' }\"\r\n [style]=\"{ width: '80vw' }\"\r\n [draggable]=\"false\"\r\n [resizable]=\"false\"\r\n>\r\n <div #viewer></div>\r\n</p-dialog>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: DialogModule }, { kind: "component", type: i1$2.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }] });
768
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.11", type: DocxPreviewComponent, isStandalone: true, selector: "app-docx-preview", inputs: { visible: { classPropertyName: "visible", publicName: "visible", isSignal: false, isRequired: false, transformFunction: null }, blob: { classPropertyName: "blob", publicName: "blob", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { visibleChange: "visibleChange" }, viewQueries: [{ propertyName: "view", first: true, predicate: ["viewer"], descendants: true, isSignal: true }], ngImport: i0, template: "<p-dialog\r\n [visible]=\"visible\"\r\n (onHide)=\"onHide()\"\r\n [modal]=\"true\"\r\n [breakpoints]=\"{ '1199px': '75vw', '575px': '90vw' }\"\r\n [style]=\"{ width: '80vw' }\"\r\n [draggable]=\"false\"\r\n [resizable]=\"false\"\r\n [closable]=\"true\"\r\n [maximizable]=\"true\"\r\n>\r\n <ng-template #header>\r\n <div class=\"flex justify-content-center align-items-center gap-2 px-2\">\r\n <p-avatar image=\"icon2/word-2019.png\" />\r\n <span class=\"font-bold\">Vista preliminar del documento</span>\r\n </div>\r\n </ng-template>\r\n <div #viewer></div>\r\n</p-dialog>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: DialogModule }, { kind: "component", type: i1$2.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i2$1.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }] });
464
769
  }
465
770
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DocxPreviewComponent, decorators: [{
466
771
  type: Component,
467
- args: [{ selector: 'app-docx-preview', imports: [DialogModule], template: "<p-dialog\r\n header=\"Vista preliminar del documento\"\r\n [visible]=\"visible\"\r\n (onHide)=\"onHide()\"\r\n [modal]=\"true\"\r\n [breakpoints]=\"{ '1199px': '75vw', '575px': '90vw' }\"\r\n [style]=\"{ width: '80vw' }\"\r\n [draggable]=\"false\"\r\n [resizable]=\"false\"\r\n>\r\n <div #viewer></div>\r\n</p-dialog>\r\n" }]
772
+ args: [{ selector: 'app-docx-preview', imports: [DialogModule, AvatarModule], template: "<p-dialog\r\n [visible]=\"visible\"\r\n (onHide)=\"onHide()\"\r\n [modal]=\"true\"\r\n [breakpoints]=\"{ '1199px': '75vw', '575px': '90vw' }\"\r\n [style]=\"{ width: '80vw' }\"\r\n [draggable]=\"false\"\r\n [resizable]=\"false\"\r\n [closable]=\"true\"\r\n [maximizable]=\"true\"\r\n>\r\n <ng-template #header>\r\n <div class=\"flex justify-content-center align-items-center gap-2 px-2\">\r\n <p-avatar image=\"icon2/word-2019.png\" />\r\n <span class=\"font-bold\">Vista preliminar del documento</span>\r\n </div>\r\n </ng-template>\r\n <div #viewer></div>\r\n</p-dialog>\r\n" }]
468
773
  }], ctorParameters: () => [], propDecorators: { view: [{ type: i0.ViewChild, args: ['viewer', { isSignal: true }] }], visible: [{
469
774
  type: Input
470
775
  }], visibleChange: [{