@neural-ui/core 1.6.1 → 1.6.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.
Files changed (135) hide show
  1. package/fesm2022/neural-ui-core-accordion.mjs +7 -11
  2. package/fesm2022/neural-ui-core-accordion.mjs.map +1 -1
  3. package/fesm2022/neural-ui-core-alert.mjs +14 -25
  4. package/fesm2022/neural-ui-core-alert.mjs.map +1 -1
  5. package/fesm2022/neural-ui-core-autocomplete.mjs +28 -53
  6. package/fesm2022/neural-ui-core-autocomplete.mjs.map +1 -1
  7. package/fesm2022/neural-ui-core-avatar.mjs +13 -23
  8. package/fesm2022/neural-ui-core-avatar.mjs.map +1 -1
  9. package/fesm2022/neural-ui-core-badge.mjs +9 -15
  10. package/fesm2022/neural-ui-core-badge.mjs.map +1 -1
  11. package/fesm2022/neural-ui-core-block-ui.mjs +11 -16
  12. package/fesm2022/neural-ui-core-block-ui.mjs.map +1 -1
  13. package/fesm2022/neural-ui-core-breadcrumb.mjs +6 -8
  14. package/fesm2022/neural-ui-core-breadcrumb.mjs.map +1 -1
  15. package/fesm2022/neural-ui-core-button.mjs +16 -29
  16. package/fesm2022/neural-ui-core-button.mjs.map +1 -1
  17. package/fesm2022/neural-ui-core-calendar.mjs +20 -37
  18. package/fesm2022/neural-ui-core-calendar.mjs.map +1 -1
  19. package/fesm2022/neural-ui-core-card.mjs +8 -13
  20. package/fesm2022/neural-ui-core-card.mjs.map +1 -1
  21. package/fesm2022/neural-ui-core-chart.mjs +24 -45
  22. package/fesm2022/neural-ui-core-chart.mjs.map +1 -1
  23. package/fesm2022/neural-ui-core-checkbox.mjs +9 -15
  24. package/fesm2022/neural-ui-core-checkbox.mjs.map +1 -1
  25. package/fesm2022/neural-ui-core-chip.mjs +13 -23
  26. package/fesm2022/neural-ui-core-chip.mjs.map +1 -1
  27. package/fesm2022/neural-ui-core-code-block.mjs +17 -31
  28. package/fesm2022/neural-ui-core-code-block.mjs.map +1 -1
  29. package/fesm2022/neural-ui-core-color-picker.mjs +11 -19
  30. package/fesm2022/neural-ui-core-color-picker.mjs.map +1 -1
  31. package/fesm2022/neural-ui-core-command-palette.mjs +11 -16
  32. package/fesm2022/neural-ui-core-command-palette.mjs.map +1 -1
  33. package/fesm2022/neural-ui-core-confirm-dialog.mjs +6 -6
  34. package/fesm2022/neural-ui-core-confirm-dialog.mjs.map +1 -1
  35. package/fesm2022/neural-ui-core-context-menu.mjs +9 -12
  36. package/fesm2022/neural-ui-core-context-menu.mjs.map +1 -1
  37. package/fesm2022/neural-ui-core-dashboard-grid.mjs +7 -11
  38. package/fesm2022/neural-ui-core-dashboard-grid.mjs.map +1 -1
  39. package/fesm2022/neural-ui-core-date-input.mjs +57 -111
  40. package/fesm2022/neural-ui-core-date-input.mjs.map +1 -1
  41. package/fesm2022/neural-ui-core-divider.mjs +5 -7
  42. package/fesm2022/neural-ui-core-divider.mjs.map +1 -1
  43. package/fesm2022/neural-ui-core-empty-state.mjs +8 -13
  44. package/fesm2022/neural-ui-core-empty-state.mjs.map +1 -1
  45. package/fesm2022/neural-ui-core-filter-bar.mjs +11 -19
  46. package/fesm2022/neural-ui-core-filter-bar.mjs.map +1 -1
  47. package/fesm2022/neural-ui-core-icon.mjs +7 -11
  48. package/fesm2022/neural-ui-core-icon.mjs.map +1 -1
  49. package/fesm2022/neural-ui-core-image-gallery.mjs +13 -23
  50. package/fesm2022/neural-ui-core-image-gallery.mjs.map +1 -1
  51. package/fesm2022/neural-ui-core-image-viewer.mjs +14 -22
  52. package/fesm2022/neural-ui-core-image-viewer.mjs.map +1 -1
  53. package/fesm2022/neural-ui-core-input-otp.mjs +11 -19
  54. package/fesm2022/neural-ui-core-input-otp.mjs.map +1 -1
  55. package/fesm2022/neural-ui-core-input.mjs +35 -67
  56. package/fesm2022/neural-ui-core-input.mjs.map +1 -1
  57. package/fesm2022/neural-ui-core-kanban.mjs +9 -15
  58. package/fesm2022/neural-ui-core-kanban.mjs.map +1 -1
  59. package/fesm2022/neural-ui-core-knob.mjs +22 -41
  60. package/fesm2022/neural-ui-core-knob.mjs.map +1 -1
  61. package/fesm2022/neural-ui-core-meter-group.mjs +13 -23
  62. package/fesm2022/neural-ui-core-meter-group.mjs.map +1 -1
  63. package/fesm2022/neural-ui-core-modal.mjs +11 -16
  64. package/fesm2022/neural-ui-core-modal.mjs.map +1 -1
  65. package/fesm2022/neural-ui-core-multiselect.mjs +39 -72
  66. package/fesm2022/neural-ui-core-multiselect.mjs.map +1 -1
  67. package/fesm2022/neural-ui-core-nav.mjs +13 -22
  68. package/fesm2022/neural-ui-core-nav.mjs.map +1 -1
  69. package/fesm2022/neural-ui-core-notification-center.mjs +9 -12
  70. package/fesm2022/neural-ui-core-notification-center.mjs.map +1 -1
  71. package/fesm2022/neural-ui-core-number-input.mjs +19 -35
  72. package/fesm2022/neural-ui-core-number-input.mjs.map +1 -1
  73. package/fesm2022/neural-ui-core-pagination.mjs +9 -15
  74. package/fesm2022/neural-ui-core-pagination.mjs.map +1 -1
  75. package/fesm2022/neural-ui-core-popover.mjs +14 -22
  76. package/fesm2022/neural-ui-core-popover.mjs.map +1 -1
  77. package/fesm2022/neural-ui-core-progress-bar.mjs +11 -19
  78. package/fesm2022/neural-ui-core-progress-bar.mjs.map +1 -1
  79. package/fesm2022/neural-ui-core-radio.mjs +15 -24
  80. package/fesm2022/neural-ui-core-radio.mjs.map +1 -1
  81. package/fesm2022/neural-ui-core-rating.mjs +8 -13
  82. package/fesm2022/neural-ui-core-rating.mjs.map +1 -1
  83. package/fesm2022/neural-ui-core-rich-text-editor.mjs +28 -53
  84. package/fesm2022/neural-ui-core-rich-text-editor.mjs.map +1 -1
  85. package/fesm2022/neural-ui-core-scheduler-gantt.mjs +22 -41
  86. package/fesm2022/neural-ui-core-scheduler-gantt.mjs.map +1 -1
  87. package/fesm2022/neural-ui-core-select.mjs +43 -77
  88. package/fesm2022/neural-ui-core-select.mjs.map +1 -1
  89. package/fesm2022/neural-ui-core-sidebar.mjs +12 -21
  90. package/fesm2022/neural-ui-core-sidebar.mjs.map +1 -1
  91. package/fesm2022/neural-ui-core-skeleton.mjs +7 -11
  92. package/fesm2022/neural-ui-core-skeleton.mjs.map +1 -1
  93. package/fesm2022/neural-ui-core-slider.mjs +13 -23
  94. package/fesm2022/neural-ui-core-slider.mjs.map +1 -1
  95. package/fesm2022/neural-ui-core-spinner.mjs +10 -17
  96. package/fesm2022/neural-ui-core-spinner.mjs.map +1 -1
  97. package/fesm2022/neural-ui-core-split-button.mjs +15 -27
  98. package/fesm2022/neural-ui-core-split-button.mjs.map +1 -1
  99. package/fesm2022/neural-ui-core-splitter.mjs +6 -9
  100. package/fesm2022/neural-ui-core-splitter.mjs.map +1 -1
  101. package/fesm2022/neural-ui-core-stats-card.mjs +11 -19
  102. package/fesm2022/neural-ui-core-stats-card.mjs.map +1 -1
  103. package/fesm2022/neural-ui-core-stepper.mjs +8 -13
  104. package/fesm2022/neural-ui-core-stepper.mjs.map +1 -1
  105. package/fesm2022/neural-ui-core-switch.mjs +9 -15
  106. package/fesm2022/neural-ui-core-switch.mjs.map +1 -1
  107. package/fesm2022/neural-ui-core-table.mjs +124 -242
  108. package/fesm2022/neural-ui-core-table.mjs.map +1 -1
  109. package/fesm2022/neural-ui-core-tabs.mjs +18 -30
  110. package/fesm2022/neural-ui-core-tabs.mjs.map +1 -1
  111. package/fesm2022/neural-ui-core-textarea.mjs +23 -43
  112. package/fesm2022/neural-ui-core-textarea.mjs.map +1 -1
  113. package/fesm2022/neural-ui-core-timeline-grid.mjs +12 -21
  114. package/fesm2022/neural-ui-core-timeline-grid.mjs.map +1 -1
  115. package/fesm2022/neural-ui-core-timeline.mjs +4 -5
  116. package/fesm2022/neural-ui-core-timeline.mjs.map +1 -1
  117. package/fesm2022/neural-ui-core-toast.mjs +8 -10
  118. package/fesm2022/neural-ui-core-toast.mjs.map +1 -1
  119. package/fesm2022/neural-ui-core-toggle-button-group.mjs +10 -17
  120. package/fesm2022/neural-ui-core-toggle-button-group.mjs.map +1 -1
  121. package/fesm2022/neural-ui-core-toolbar.mjs +8 -13
  122. package/fesm2022/neural-ui-core-toolbar.mjs.map +1 -1
  123. package/fesm2022/neural-ui-core-tooltip.mjs +11 -16
  124. package/fesm2022/neural-ui-core-tooltip.mjs.map +1 -1
  125. package/fesm2022/neural-ui-core-tree-table.mjs +30 -57
  126. package/fesm2022/neural-ui-core-tree-table.mjs.map +1 -1
  127. package/fesm2022/neural-ui-core-tree.mjs +17 -31
  128. package/fesm2022/neural-ui-core-tree.mjs.map +1 -1
  129. package/fesm2022/neural-ui-core-uploader.mjs +47 -91
  130. package/fesm2022/neural-ui-core-uploader.mjs.map +1 -1
  131. package/fesm2022/neural-ui-core-url-state.mjs +5 -7
  132. package/fesm2022/neural-ui-core-url-state.mjs.map +1 -1
  133. package/fesm2022/neural-ui-core-virtual-list.mjs +19 -32
  134. package/fesm2022/neural-ui-core-virtual-list.mjs.map +1 -1
  135. package/package.json +6 -6
@@ -12,35 +12,26 @@ class NeuNavComponent {
12
12
  currentUrl = toSignal(this.router.events.pipe(filter((e) => e instanceof NavigationEnd)), { initialValue: null });
13
13
  // ---- Inputs ----
14
14
  /** Lista de ítems de navegación / Navigation item list */
15
- items = input([], /* @ts-ignore */
16
- ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
15
+ items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
17
16
  /** Estado inicial colapsado / Initial collapsed state */
18
- collapsed = input(false, /* @ts-ignore */
19
- ...(ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []));
17
+ collapsed = input(false, ...(ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []));
20
18
  /** Muestra el botón de colapsar/expandir / Shows the collapse/expand button */
21
- collapsible = input(true, /* @ts-ignore */
22
- ...(ngDevMode ? [{ debugName: "collapsible" }] : /* istanbul ignore next */ []));
19
+ collapsible = input(true, ...(ngDevMode ? [{ debugName: "collapsible" }] : /* istanbul ignore next */ []));
23
20
  /** Etiqueta accesible del <nav> / Accessible label for the <nav> */
24
- ariaLabel = input('Navegación principal', /* @ts-ignore */
25
- ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
21
+ ariaLabel = input('Navegación principal', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
26
22
  /** Aria-label del botón cuando el nav está colapsado / Aria-label for the button when the nav is collapsed */
27
- expandLabel = input('Expandir menú', /* @ts-ignore */
28
- ...(ngDevMode ? [{ debugName: "expandLabel" }] : /* istanbul ignore next */ []));
23
+ expandLabel = input('Expandir menú', ...(ngDevMode ? [{ debugName: "expandLabel" }] : /* istanbul ignore next */ []));
29
24
  /** Aria-label del botón cuando el nav está expandido / Aria-label for the button when the nav is expanded */
30
- collapseLabel = input('Colapsar menú', /* @ts-ignore */
31
- ...(ngDevMode ? [{ debugName: "collapseLabel" }] : /* istanbul ignore next */ []));
25
+ collapseLabel = input('Colapsar menú', ...(ngDevMode ? [{ debugName: "collapseLabel" }] : /* istanbul ignore next */ []));
32
26
  /** Emite cuando cambia el estado colapsado / Emits when the collapsed state changes */
33
27
  collapsedChange = output();
34
28
  // ---- Estado interno / Internal state ----
35
29
  // Sigue el input `collapsed` del padre (permite el configurador)
36
30
  // pero puede ser sobreescrito localmente con toggleCollapse()
37
- isCollapsed = linkedSignal(() => this.collapsed(), /* @ts-ignore */
38
- ...(ngDevMode ? [{ debugName: "isCollapsed" }] : /* istanbul ignore next */ []));
39
- openGroups = signal(new Set(), /* @ts-ignore */
40
- ...(ngDevMode ? [{ debugName: "openGroups" }] : /* istanbul ignore next */ []));
31
+ isCollapsed = linkedSignal(() => this.collapsed(), ...(ngDevMode ? [{ debugName: "isCollapsed" }] : /* istanbul ignore next */ []));
32
+ openGroups = signal(new Set(), ...(ngDevMode ? [{ debugName: "openGroups" }] : /* istanbul ignore next */ []));
41
33
  // ---- Flyout para modo colapsado / Flyout for collapsed mode ----
42
- flyoutState = signal(null, /* @ts-ignore */
43
- ...(ngDevMode ? [{ debugName: "flyoutState" }] : /* istanbul ignore next */ []));
34
+ flyoutState = signal(null, ...(ngDevMode ? [{ debugName: "flyoutState" }] : /* istanbul ignore next */ []));
44
35
  _flyoutTimer = null;
45
36
  constructor() {
46
37
  // Abrimos el grupo activo DESPUÉS de que el padre haya pasado los inputs
@@ -133,8 +124,8 @@ class NeuNavComponent {
133
124
  this.openGroups.set(toOpen);
134
125
  }
135
126
  }
136
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NeuNavComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
137
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: NeuNavComponent, isStandalone: true, selector: "neu-nav", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, expandLabel: { classPropertyName: "expandLabel", publicName: "expandLabel", isSignal: true, isRequired: false, transformFunction: null }, collapseLabel: { classPropertyName: "collapseLabel", publicName: "collapseLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { collapsedChange: "collapsedChange" }, ngImport: i0, template: `
127
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuNavComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
128
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: NeuNavComponent, isStandalone: true, selector: "neu-nav", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, expandLabel: { classPropertyName: "expandLabel", publicName: "expandLabel", isSignal: true, isRequired: false, transformFunction: null }, collapseLabel: { classPropertyName: "collapseLabel", publicName: "collapseLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { collapsedChange: "collapsedChange" }, ngImport: i0, template: `
138
129
  <div class="neu-nav-wrapper" [class.neu-nav-wrapper--collapsed]="isCollapsed()">
139
130
  <nav
140
131
  class="neu-nav"
@@ -539,9 +530,9 @@ class NeuNavComponent {
539
530
  </button>
540
531
  }
541
532
  </div>
542
- `, isInline: true, styles: ["@charset \"UTF-8\";.neu-nav{display:flex;flex-direction:column;width:268px;height:100%;background:var(--neu-surface);border-right:1px solid var(--neu-border);transition:width .28s cubic-bezier(.4,0,.2,1);overflow:hidden;flex-shrink:0;-webkit-user-select:none;user-select:none}.neu-nav--collapsed{width:64px}.neu-nav--collapsed .neu-nav__brand{justify-content:center;padding:0;gap:0}.neu-nav--collapsed .neu-nav__brand-content{flex:0 0 0;width:0;opacity:0;overflow:hidden;pointer-events:none}.neu-nav--collapsed .neu-nav__items{padding-left:0;padding-right:0}.neu-nav--collapsed .neu-nav__item{justify-content:center;width:64px;padding:0;gap:0}.neu-nav--collapsed .neu-nav__item--parent .neu-nav__group-chevron{margin-left:0}.neu-nav--collapsed .neu-nav__item-label,.neu-nav--collapsed .neu-nav__item-badge,.neu-nav--collapsed .neu-nav__group-chevron,.neu-nav--collapsed .neu-nav__external-icon{flex:0 0 0;width:0;margin:0;opacity:0;overflow:hidden;pointer-events:none;white-space:nowrap}.neu-nav--collapsed .neu-nav__footer{height:0;opacity:0;overflow:hidden;pointer-events:none}.neu-nav__brand{display:flex;align-items:center;justify-content:space-between;min-height:64px;padding:0 var(--neu-space-4);border-bottom:1px solid var(--neu-border);flex-shrink:0;gap:var(--neu-space-3)}.neu-nav__brand-content{flex:1;min-width:0;display:flex;align-items:center;gap:10px;transition:opacity .2s ease,width .28s cubic-bezier(.4,0,.2,1);overflow:hidden}.neu-nav__brand-icon{display:none;align-items:center;justify-content:center;width:64px;height:64px;flex-shrink:0;background:none;border:none;cursor:pointer;padding:0;color:inherit}.neu-nav__brand-icon:focus-visible{outline:2px solid var(--neu-primary);outline-offset:-2px}.neu-nav--collapsed .neu-nav__brand-icon{display:flex}.neu-nav-wrapper{position:relative;height:100%;flex-shrink:0;display:flex}.neu-nav__toggle-tab{position:absolute;right:-13px;top:16px;transform:none;width:13px;height:40px;display:flex;align-items:center;justify-content:center;background:var(--neu-surface);border:1px solid var(--neu-border);border-left:none;border-radius:0 6px 6px 0;color:var(--neu-text-muted);cursor:pointer;padding:0;z-index:10;transition:background var(--neu-transition),color var(--neu-transition)}.neu-nav__toggle-tab:hover{background:var(--neu-surface-2);color:var(--neu-text)}.neu-nav__toggle-tab:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px}.neu-nav__items{flex:1;overflow-y:auto;overflow-x:hidden;padding:var(--neu-space-3) var(--neu-space-2);display:flex;flex-direction:column;gap:2px}.neu-nav__items::-webkit-scrollbar{width:4px}.neu-nav__items::-webkit-scrollbar-track{background:transparent}.neu-nav__items::-webkit-scrollbar-thumb{background:var(--neu-border);border-radius:4px}.neu-nav__item{position:relative;display:flex;align-items:center;gap:10px;height:40px;padding:0 var(--neu-space-3);border-radius:8px;font-size:var(--neu-text-sm);font-weight:500;color:var(--neu-text-muted);text-decoration:none;cursor:pointer;background:none;border:none;font-family:inherit;width:100%;text-align:left;transition:background var(--neu-transition),color var(--neu-transition);white-space:nowrap;flex-shrink:0}.neu-nav__item:focus-visible{outline:2px solid var(--neu-primary);outline-offset:-2px}.neu-nav__item:hover:not(.neu-nav__item--disabled){background:var(--neu-surface-2);color:var(--neu-text)}.neu-nav__item:hover:not(.neu-nav__item--disabled) .neu-nav__item-icon{color:var(--neu-text)}.neu-nav__item--active{background:var(--neu-primary-50);color:var(--neu-primary-dark, var(--neu-primary));font-weight:600}.neu-nav__item--active .neu-nav__item-icon{color:var(--neu-primary-dark, var(--neu-primary))}.neu-nav__item--active:before{content:\"\";position:absolute;left:0;top:6px;bottom:6px;width:3px;background:var(--neu-primary-dark, var(--neu-primary));border-radius:0 var(--neu-radius-full) var(--neu-radius-full) 0}.neu-nav__item--disabled{opacity:1;color:var(--neu-text-disabled);cursor:not-allowed;pointer-events:none}.neu-nav__item--disabled .neu-nav__item-icon{color:var(--neu-text-disabled)}.neu-nav__item--child{height:36px;padding-left:calc(var(--neu-space-3) + 6px);font-size:.8125rem}.neu-nav__item--parent .neu-nav__group-chevron{margin-left:auto;flex-shrink:0;transition:transform var(--neu-transition);color:var(--neu-text-disabled)}.neu-nav__item-icon{flex-shrink:0;color:var(--neu-text-disabled);transition:color var(--neu-transition)}.neu-nav__item-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;transition:opacity .2s ease,width .28s cubic-bezier(.4,0,.2,1)}.neu-nav__item-badge{flex-shrink:0;font-size:10px;font-weight:700;line-height:1;padding:2px 6px;border-radius:var(--neu-radius-full);text-transform:uppercase;letter-spacing:.04em;transition:opacity .2s ease}.neu-nav__item-badge--default{background:var(--neu-surface-3);color:var(--neu-text-muted)}.neu-nav__item-badge--success{background:var(--neu-success-bg);color:var(--neu-success-text)}.neu-nav__item-badge--warning{background:var(--neu-warning-bg);color:var(--neu-warning-text)}.neu-nav__item-badge--danger{background:var(--neu-error-bg);color:var(--neu-error-text)}.neu-nav__item-badge--info{background:var(--neu-info-bg);color:var(--neu-info-text)}.neu-nav__group{display:flex;flex-direction:column}.neu-nav__group--open .neu-nav__group-chevron{transform:rotate(90deg)}.neu-nav__group--open>.neu-nav__item--parent{color:var(--neu-text);background:var(--neu-surface-2)}.neu-nav__group--open>.neu-nav__item--parent .neu-nav__item-icon{color:var(--neu-text-muted)}.neu-nav__submenu{display:flex;flex-direction:column;gap:1px;padding:2px 0 4px var(--neu-space-3);margin-top:2px;border-left:2px solid var(--neu-border);margin-left:calc(var(--neu-space-3) + 9px)}.neu-nav__submenu--nested{padding-left:var(--neu-space-2);margin-left:calc(var(--neu-space-2) + 7px);border-color:var(--neu-border);border-left-style:dashed}.neu-nav__item--grandchild{height:32px;padding-left:calc(var(--neu-space-2) + 4px);font-size:.75rem}.neu-nav__external-icon{flex-shrink:0;margin-left:auto;color:var(--neu-text-disabled);opacity:.7;transition:opacity var(--neu-transition),color var(--neu-transition)}.neu-nav__item:hover .neu-nav__external-icon{opacity:1;color:var(--neu-text-muted)}.neu-nav__footer{border-top:1px solid var(--neu-border);padding:var(--neu-space-3) var(--neu-space-4);flex-shrink:0;font-size:var(--neu-text-xs);color:var(--neu-text-muted);transition:opacity .2s ease,height .28s cubic-bezier(.4,0,.2,1)}.neu-nav--collapsed .neu-nav__item--parent:after{content:\"\\203a\";position:absolute;right:8px;top:50%;transform:translateY(-50%);font-size:11px;line-height:1;color:var(--neu-text-disabled);pointer-events:none}.neu-nav__flyout{position:fixed;z-index:1000;min-width:200px;max-width:240px;background:var(--neu-surface);border:1px solid var(--neu-border);border-radius:8px;box-shadow:0 4px 20px #0000001f;padding:6px;margin-left:6px}.neu-nav__flyout-title{font-size:.6875rem;font-weight:700;color:var(--neu-text-muted);text-transform:uppercase;letter-spacing:.06em;padding:4px 8px 6px}.neu-nav__flyout-item{display:flex;align-items:center;gap:8px;height:34px;padding:0 8px;border-radius:6px;font-size:.8125rem;color:var(--neu-text-muted);text-decoration:none;cursor:pointer;white-space:nowrap;transition:background var(--neu-transition),color var(--neu-transition)}.neu-nav__flyout-item:hover{background:var(--neu-surface-2);color:var(--neu-text)}.neu-nav__flyout-item--active{background:var(--neu-primary-50);color:var(--neu-primary);font-weight:600}.neu-nav__flyout-item .neu-nav__external-icon{margin-left:auto;opacity:.6}.neu-nav__flyout-group{margin-top:4px;padding-top:4px;border-top:1px solid var(--neu-border)}.neu-nav__flyout-group-label{display:block;font-size:.6875rem;font-weight:600;color:var(--neu-text-disabled);text-transform:uppercase;letter-spacing:.05em;padding:2px 8px 4px}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "component", type: NeuIconComponent, selector: "neu-icon", inputs: ["name", "strokeWidth", "size"] }, { kind: "directive", type: NeuTooltipDirective, selector: "[neuTooltip]", inputs: ["neuTooltip", "neuTooltipPosition", "neuTooltipDisabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
533
+ `, isInline: true, styles: ["@charset \"UTF-8\";.neu-nav{display:flex;flex-direction:column;width:268px;height:100%;background:var(--neu-surface);border-right:1px solid var(--neu-border);transition:width .28s cubic-bezier(.4,0,.2,1);overflow:hidden;flex-shrink:0;-webkit-user-select:none;user-select:none}.neu-nav--collapsed{width:64px}.neu-nav--collapsed .neu-nav__brand{justify-content:center;padding:0;gap:0}.neu-nav--collapsed .neu-nav__brand-content{flex:0 0 0;width:0;opacity:0;overflow:hidden;pointer-events:none}.neu-nav--collapsed .neu-nav__items{padding-left:0;padding-right:0}.neu-nav--collapsed .neu-nav__item{justify-content:center;width:64px;padding:0;gap:0}.neu-nav--collapsed .neu-nav__item--parent .neu-nav__group-chevron{margin-left:0}.neu-nav--collapsed .neu-nav__item-label,.neu-nav--collapsed .neu-nav__item-badge,.neu-nav--collapsed .neu-nav__group-chevron,.neu-nav--collapsed .neu-nav__external-icon{flex:0 0 0;width:0;margin:0;opacity:0;overflow:hidden;pointer-events:none;white-space:nowrap}.neu-nav--collapsed .neu-nav__footer{height:0;opacity:0;overflow:hidden;pointer-events:none}.neu-nav__brand{display:flex;align-items:center;justify-content:space-between;min-height:64px;padding:0 var(--neu-space-4);border-bottom:1px solid var(--neu-border);flex-shrink:0;gap:var(--neu-space-3)}.neu-nav__brand-content{flex:1;min-width:0;display:flex;align-items:center;gap:10px;transition:opacity .2s ease,width .28s cubic-bezier(.4,0,.2,1);overflow:hidden}.neu-nav__brand-icon{display:none;align-items:center;justify-content:center;width:64px;height:64px;flex-shrink:0;background:none;border:none;cursor:pointer;padding:0;color:inherit}.neu-nav__brand-icon:focus-visible{outline:2px solid var(--neu-primary);outline-offset:-2px}.neu-nav--collapsed .neu-nav__brand-icon{display:flex}.neu-nav-wrapper{position:relative;height:100%;flex-shrink:0;display:flex}.neu-nav__toggle-tab{position:absolute;right:-13px;top:16px;transform:none;width:13px;height:40px;display:flex;align-items:center;justify-content:center;background:var(--neu-surface);border:1px solid var(--neu-border);border-left:none;border-radius:0 6px 6px 0;color:var(--neu-text-muted);cursor:pointer;padding:0;z-index:10;transition:background var(--neu-transition),color var(--neu-transition)}.neu-nav__toggle-tab:hover{background:var(--neu-surface-2);color:var(--neu-text)}.neu-nav__toggle-tab:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px}.neu-nav__items{flex:1;overflow-y:auto;overflow-x:hidden;padding:var(--neu-space-3) var(--neu-space-2);display:flex;flex-direction:column;gap:2px}.neu-nav__items::-webkit-scrollbar{width:4px}.neu-nav__items::-webkit-scrollbar-track{background:transparent}.neu-nav__items::-webkit-scrollbar-thumb{background:var(--neu-border);border-radius:4px}.neu-nav__item{position:relative;display:flex;align-items:center;gap:10px;height:40px;padding:0 var(--neu-space-3);border-radius:8px;font-size:var(--neu-text-sm);font-weight:500;color:var(--neu-text-muted);text-decoration:none;cursor:pointer;background:none;border:none;font-family:inherit;width:100%;text-align:left;transition:background var(--neu-transition),color var(--neu-transition);white-space:nowrap;flex-shrink:0}.neu-nav__item:focus-visible{outline:2px solid var(--neu-primary);outline-offset:-2px}.neu-nav__item:hover:not(.neu-nav__item--disabled){background:var(--neu-surface-2);color:var(--neu-text)}.neu-nav__item:hover:not(.neu-nav__item--disabled) .neu-nav__item-icon{color:var(--neu-text)}.neu-nav__item--active{background:var(--neu-primary-50);color:var(--neu-primary-dark, var(--neu-primary));font-weight:600}.neu-nav__item--active .neu-nav__item-icon{color:var(--neu-primary-dark, var(--neu-primary))}.neu-nav__item--active:before{content:\"\";position:absolute;left:0;top:6px;bottom:6px;width:3px;background:var(--neu-primary-dark, var(--neu-primary));border-radius:0 var(--neu-radius-full) var(--neu-radius-full) 0}.neu-nav__item--disabled{opacity:1;color:var(--neu-text-disabled);cursor:not-allowed;pointer-events:none}.neu-nav__item--disabled .neu-nav__item-icon{color:var(--neu-text-disabled)}.neu-nav__item--child{height:36px;padding-left:calc(var(--neu-space-3) + 6px);font-size:.8125rem}.neu-nav__item--parent .neu-nav__group-chevron{margin-left:auto;flex-shrink:0;transition:transform var(--neu-transition);color:var(--neu-text-disabled)}.neu-nav__item-icon{flex-shrink:0;color:var(--neu-text-disabled);transition:color var(--neu-transition)}.neu-nav__item-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;transition:opacity .2s ease,width .28s cubic-bezier(.4,0,.2,1)}.neu-nav__item-badge{flex-shrink:0;font-size:10px;font-weight:700;line-height:1;padding:2px 6px;border-radius:var(--neu-radius-full);text-transform:uppercase;letter-spacing:.04em;transition:opacity .2s ease}.neu-nav__item-badge--default{background:var(--neu-surface-3);color:var(--neu-text-muted)}.neu-nav__item-badge--success{background:var(--neu-success-bg);color:var(--neu-success-text)}.neu-nav__item-badge--warning{background:var(--neu-warning-bg);color:var(--neu-warning-text)}.neu-nav__item-badge--danger{background:var(--neu-error-bg);color:var(--neu-error-text)}.neu-nav__item-badge--info{background:var(--neu-info-bg);color:var(--neu-info-text)}.neu-nav__group{display:flex;flex-direction:column}.neu-nav__group--open .neu-nav__group-chevron{transform:rotate(90deg)}.neu-nav__group--open>.neu-nav__item--parent{color:var(--neu-text);background:var(--neu-surface-2)}.neu-nav__group--open>.neu-nav__item--parent .neu-nav__item-icon{color:var(--neu-text-muted)}.neu-nav__submenu{display:flex;flex-direction:column;gap:1px;padding:2px 0 4px var(--neu-space-3);margin-top:2px;border-left:2px solid var(--neu-border);margin-left:calc(var(--neu-space-3) + 9px)}.neu-nav__submenu--nested{padding-left:var(--neu-space-2);margin-left:calc(var(--neu-space-2) + 7px);border-color:var(--neu-border);border-left-style:dashed}.neu-nav__item--grandchild{height:32px;padding-left:calc(var(--neu-space-2) + 4px);font-size:.75rem}.neu-nav__external-icon{flex-shrink:0;margin-left:auto;color:var(--neu-text-disabled);opacity:.7;transition:opacity var(--neu-transition),color var(--neu-transition)}.neu-nav__item:hover .neu-nav__external-icon{opacity:1;color:var(--neu-text-muted)}.neu-nav__footer{border-top:1px solid var(--neu-border);padding:var(--neu-space-3) var(--neu-space-4);flex-shrink:0;font-size:var(--neu-text-xs);color:var(--neu-text-muted);transition:opacity .2s ease,height .28s cubic-bezier(.4,0,.2,1)}.neu-nav--collapsed .neu-nav__item--parent:after{content:\"\\203a\";position:absolute;right:8px;top:50%;transform:translateY(-50%);font-size:11px;line-height:1;color:var(--neu-text-disabled);pointer-events:none}.neu-nav__flyout{position:fixed;z-index:1000;min-width:200px;max-width:240px;background:var(--neu-surface);border:1px solid var(--neu-border);border-radius:8px;box-shadow:0 4px 20px #0000001f;padding:6px;margin-left:6px}.neu-nav__flyout-title{font-size:.6875rem;font-weight:700;color:var(--neu-text-muted);text-transform:uppercase;letter-spacing:.06em;padding:4px 8px 6px}.neu-nav__flyout-item{display:flex;align-items:center;gap:8px;height:34px;padding:0 8px;border-radius:6px;font-size:.8125rem;color:var(--neu-text-muted);text-decoration:none;cursor:pointer;white-space:nowrap;transition:background var(--neu-transition),color var(--neu-transition)}.neu-nav__flyout-item:hover{background:var(--neu-surface-2);color:var(--neu-text)}.neu-nav__flyout-item--active{background:var(--neu-primary-50);color:var(--neu-primary);font-weight:600}.neu-nav__flyout-item .neu-nav__external-icon{margin-left:auto;opacity:.6}.neu-nav__flyout-group{margin-top:4px;padding-top:4px;border-top:1px solid var(--neu-border)}.neu-nav__flyout-group-label{display:block;font-size:.6875rem;font-weight:600;color:var(--neu-text-disabled);text-transform:uppercase;letter-spacing:.05em;padding:2px 8px 4px}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "component", type: NeuIconComponent, selector: "neu-icon", inputs: ["name", "strokeWidth", "size"] }, { kind: "directive", type: NeuTooltipDirective, selector: "[neuTooltip]", inputs: ["neuTooltip", "neuTooltipPosition", "neuTooltipDisabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
543
534
  }
544
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NeuNavComponent, decorators: [{
535
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuNavComponent, decorators: [{
545
536
  type: Component,
546
537
  args: [{ selector: 'neu-nav', imports: [RouterLink, RouterLinkActive, NeuIconComponent, NeuTooltipDirective], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: `
547
538
  <div class="neu-nav-wrapper" [class.neu-nav-wrapper--collapsed]="isCollapsed()">
@@ -1 +1 @@
1
- {"version":3,"file":"neural-ui-core-nav.mjs","sources":["../../../../projects/ui-core/nav/neu-nav.component.ts","../../../../projects/ui-core/nav/neural-ui-core-nav.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n ViewEncapsulation,\n afterNextRender,\n inject,\n input,\n linkedSignal,\n output,\n signal,\n} from '@angular/core';\nimport { RouterLink, RouterLinkActive, Router, NavigationEnd } from '@angular/router';\nimport { filter } from 'rxjs';\nimport { toSignal } from '@angular/core/rxjs-interop';\nimport { NeuIconComponent } from '@neural-ui/core/icon';\nimport { NeuTooltipDirective } from '@neural-ui/core/tooltip';\n\n// ---- Tipos públicos / Public types ----\n\n/**\n * Ítem de navegación con soporte para 3 niveles de profundidad.\n *\n * Destino del enlace — usa UNO de los dos:\n * - `route` → navegación interna Angular (RouterLink)\n * - `href` → URL externa, se abre en nueva pestaña con rel=\"noopener noreferrer\"\n *\n * Los ítems con `children` actúan como grupo acordeón (sin destino propio).\n * Máximo 3 niveles: raíz → hijos → nietos.\n * Los nietos no pueden tener `children`.\n */\nexport interface NeuNavItem {\n id: string;\n label: string;\n icon: string;\n /** Ruta Angular interna (RouterLink). Excluye `href`. / Internal Angular route (RouterLink). Excludes `href`. */\n route?: string;\n /** URL externa. Se abre en nueva pestaña. Excluye `route`. / External URL. Opens in a new tab. Excludes `route`. */\n href?: string;\n /** Ítems hijo (nivel 2). Cada hijo puede tener sus propios `children` (nivel 3). / Child items (level 2). Each child can have its own `children` (level 3). */\n children?: NeuNavItem[];\n badge?: string;\n badgeVariant?: 'default' | 'success' | 'warning' | 'danger' | 'info';\n disabled?: boolean;\n}\n\n@Component({\n selector: 'neu-nav',\n imports: [RouterLink, RouterLinkActive, NeuIconComponent, NeuTooltipDirective],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div class=\"neu-nav-wrapper\" [class.neu-nav-wrapper--collapsed]=\"isCollapsed()\">\n <nav\n class=\"neu-nav\"\n [class.neu-nav--collapsed]=\"isCollapsed()\"\n [attr.aria-label]=\"ariaLabel()\"\n >\n <!-- Brand slot -->\n <div class=\"neu-nav__brand\">\n <!-- Icono visible solo en modo colapsado -->\n <div class=\"neu-nav__brand-icon\">\n <ng-content select=\"[neu-nav-brand-icon]\" />\n </div>\n <!-- Contenido completo visible en modo expandido -->\n <div class=\"neu-nav__brand-content\">\n <ng-content select=\"[neu-nav-brand]\" />\n </div>\n </div>\n\n <!-- Items (nivel 1) -->\n <div class=\"neu-nav__items\" role=\"list\">\n @for (item of items(); track item.id) {\n @if (item.children?.length) {\n <!-- NIVEL 1 — Grupo acordeón -->\n <div\n class=\"neu-nav__group\"\n [class.neu-nav__group--open]=\"isGroupOpen(item.id)\"\n role=\"listitem\"\n (mouseenter)=\"onGroupMouseEnter(item, $event)\"\n (mouseleave)=\"onGroupMouseLeave()\"\n >\n <button\n class=\"neu-nav__item neu-nav__item--parent\"\n type=\"button\"\n [class.neu-nav__item--active]=\"isGroupActive(item)\"\n [class.neu-nav__item--disabled]=\"item.disabled\"\n [attr.aria-expanded]=\"isGroupOpen(item.id)\"\n [attr.aria-haspopup]=\"true\"\n [attr.disabled]=\"item.disabled ? '' : null\"\n [neuTooltip]=\"isCollapsed() ? item.label : ''\"\n neuTooltipPosition=\"right\"\n (click)=\"!isCollapsed() && toggleGroup(item.id)\"\n >\n <neu-icon\n [name]=\"item.icon\"\n size=\"18px\"\n class=\"neu-nav__item-icon\"\n aria-hidden=\"true\"\n />\n <span class=\"neu-nav__item-label\">{{ item.label }}</span>\n @if (item.badge) {\n <span\n class=\"neu-nav__item-badge neu-nav__item-badge--{{\n item.badgeVariant ?? 'default'\n }}\"\n >{{ item.badge }}</span\n >\n }\n <neu-icon\n name=\"lucideChevronRight\"\n size=\"14px\"\n class=\"neu-nav__group-chevron\"\n aria-hidden=\"true\"\n />\n </button>\n\n <!-- Submenú nivel 2 -->\n @if (!isCollapsed() && isGroupOpen(item.id)) {\n <div class=\"neu-nav__submenu\" role=\"list\">\n @for (child of item.children; track child.id) {\n @if (child.children?.length) {\n <!-- NIVEL 2 — Subgrupo acordeón -->\n <div\n class=\"neu-nav__group neu-nav__group--nested\"\n [class.neu-nav__group--open]=\"isGroupOpen(child.id)\"\n role=\"listitem\"\n >\n <button\n class=\"neu-nav__item neu-nav__item--child neu-nav__item--parent\"\n type=\"button\"\n [class.neu-nav__item--active]=\"isGroupActive(child)\"\n [class.neu-nav__item--disabled]=\"child.disabled\"\n [attr.aria-expanded]=\"isGroupOpen(child.id)\"\n [attr.aria-haspopup]=\"true\"\n [attr.disabled]=\"child.disabled ? '' : null\"\n (click)=\"toggleGroup(child.id)\"\n >\n <neu-icon\n [name]=\"child.icon\"\n size=\"15px\"\n class=\"neu-nav__item-icon\"\n aria-hidden=\"true\"\n />\n <span class=\"neu-nav__item-label\">{{ child.label }}</span>\n @if (child.badge) {\n <span\n class=\"neu-nav__item-badge neu-nav__item-badge--{{\n child.badgeVariant ?? 'default'\n }}\"\n >{{ child.badge }}</span\n >\n }\n <neu-icon\n name=\"lucideChevronRight\"\n size=\"13px\"\n class=\"neu-nav__group-chevron\"\n aria-hidden=\"true\"\n />\n </button>\n\n <!-- Submenú nivel 3 -->\n @if (isGroupOpen(child.id)) {\n <div class=\"neu-nav__submenu neu-nav__submenu--nested\" role=\"list\">\n @for (grand of child.children; track grand.id) {\n @if (grand.href) {\n <!-- NIVEL 3 — Enlace externo -->\n <a\n class=\"neu-nav__item neu-nav__item--grandchild\"\n [class.neu-nav__item--disabled]=\"grand.disabled\"\n [href]=\"grand.disabled ? null : grand.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n [attr.aria-disabled]=\"grand.disabled ? 'true' : null\"\n role=\"listitem\"\n >\n <neu-icon\n [name]=\"grand.icon\"\n size=\"14px\"\n class=\"neu-nav__item-icon\"\n aria-hidden=\"true\"\n />\n <span class=\"neu-nav__item-label\">{{ grand.label }}</span>\n <neu-icon\n name=\"lucideExternalLink\"\n size=\"11px\"\n class=\"neu-nav__external-icon\"\n aria-hidden=\"true\"\n />\n </a>\n } @else {\n <!-- NIVEL 3 — Enlace interno -->\n <a\n class=\"neu-nav__item neu-nav__item--grandchild\"\n [class.neu-nav__item--disabled]=\"grand.disabled\"\n [routerLink]=\"grand.disabled ? null : (grand.route ?? null)\"\n routerLinkActive=\"neu-nav__item--active\"\n [routerLinkActiveOptions]=\"{ exact: true }\"\n [attr.aria-current]=\"\n isCurrentRoute(grand.route ?? '') ? 'page' : null\n \"\n role=\"listitem\"\n >\n <neu-icon\n [name]=\"grand.icon\"\n size=\"14px\"\n class=\"neu-nav__item-icon\"\n aria-hidden=\"true\"\n />\n <span class=\"neu-nav__item-label\">{{ grand.label }}</span>\n @if (grand.badge) {\n <span\n class=\"neu-nav__item-badge neu-nav__item-badge--{{\n grand.badgeVariant ?? 'default'\n }}\"\n >{{ grand.badge }}</span\n >\n }\n </a>\n }\n }\n </div>\n }\n </div>\n } @else if (child.href) {\n <!-- NIVEL 2 — Enlace externo -->\n <a\n class=\"neu-nav__item neu-nav__item--child\"\n [class.neu-nav__item--disabled]=\"child.disabled\"\n [href]=\"child.disabled ? null : child.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n [attr.aria-disabled]=\"child.disabled ? 'true' : null\"\n role=\"listitem\"\n >\n <neu-icon\n [name]=\"child.icon\"\n size=\"15px\"\n class=\"neu-nav__item-icon\"\n aria-hidden=\"true\"\n />\n <span class=\"neu-nav__item-label\">{{ child.label }}</span>\n @if (child.badge) {\n <span\n class=\"neu-nav__item-badge neu-nav__item-badge--{{\n child.badgeVariant ?? 'default'\n }}\"\n >{{ child.badge }}</span\n >\n }\n <neu-icon\n name=\"lucideExternalLink\"\n size=\"12px\"\n class=\"neu-nav__external-icon\"\n aria-hidden=\"true\"\n />\n </a>\n } @else {\n <!-- NIVEL 2 — Enlace interno -->\n <a\n class=\"neu-nav__item neu-nav__item--child\"\n [class.neu-nav__item--disabled]=\"child.disabled\"\n [routerLink]=\"child.disabled ? null : (child.route ?? null)\"\n routerLinkActive=\"neu-nav__item--active\"\n [routerLinkActiveOptions]=\"{ exact: true }\"\n [attr.aria-current]=\"isCurrentRoute(child.route ?? '') ? 'page' : null\"\n role=\"listitem\"\n >\n <neu-icon\n [name]=\"child.icon\"\n size=\"15px\"\n class=\"neu-nav__item-icon\"\n aria-hidden=\"true\"\n />\n <span class=\"neu-nav__item-label\">{{ child.label }}</span>\n @if (child.badge) {\n <span\n class=\"neu-nav__item-badge neu-nav__item-badge--{{\n child.badgeVariant ?? 'default'\n }}\"\n >{{ child.badge }}</span\n >\n }\n </a>\n }\n }\n </div>\n }\n </div>\n } @else if (item.href) {\n <!-- NIVEL 1 — Enlace externo -->\n <a\n class=\"neu-nav__item\"\n [class.neu-nav__item--disabled]=\"item.disabled\"\n [href]=\"item.disabled ? null : item.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n [attr.aria-disabled]=\"item.disabled ? 'true' : null\"\n [neuTooltip]=\"isCollapsed() ? item.label : ''\"\n neuTooltipPosition=\"right\"\n role=\"listitem\"\n >\n <neu-icon\n [name]=\"item.icon\"\n size=\"18px\"\n class=\"neu-nav__item-icon\"\n aria-hidden=\"true\"\n />\n <span class=\"neu-nav__item-label\">{{ item.label }}</span>\n @if (item.badge) {\n <span\n class=\"neu-nav__item-badge neu-nav__item-badge--{{\n item.badgeVariant ?? 'default'\n }}\"\n >{{ item.badge }}</span\n >\n }\n <neu-icon\n name=\"lucideExternalLink\"\n size=\"13px\"\n class=\"neu-nav__external-icon\"\n aria-hidden=\"true\"\n />\n </a>\n } @else {\n <!-- NIVEL 1 — Enlace interno -->\n <a\n class=\"neu-nav__item\"\n [class.neu-nav__item--disabled]=\"item.disabled\"\n [routerLink]=\"item.disabled ? null : (item.route ?? null)\"\n routerLinkActive=\"neu-nav__item--active\"\n [routerLinkActiveOptions]=\"{ exact: item.route === '/' }\"\n [attr.aria-current]=\"isCurrentRoute(item.route ?? '') ? 'page' : null\"\n [neuTooltip]=\"isCollapsed() ? item.label : ''\"\n neuTooltipPosition=\"right\"\n role=\"listitem\"\n >\n <neu-icon\n [name]=\"item.icon\"\n size=\"18px\"\n class=\"neu-nav__item-icon\"\n aria-hidden=\"true\"\n />\n <span class=\"neu-nav__item-label\">{{ item.label }}</span>\n @if (item.badge) {\n <span\n class=\"neu-nav__item-badge neu-nav__item-badge--{{\n item.badgeVariant ?? 'default'\n }}\"\n >{{ item.badge }}</span\n >\n }\n </a>\n }\n }\n </div>\n\n <!-- Footer slot -->\n <div class=\"neu-nav__footer\">\n <ng-content select=\"[neu-nav-footer]\" />\n </div>\n </nav>\n\n <!-- Flyout panel para grupos en modo colapsado -->\n @if (flyoutState(); as flyout) {\n <div\n class=\"neu-nav__flyout\"\n [style.top.px]=\"flyout.top\"\n [style.left.px]=\"flyout.left\"\n role=\"menu\"\n (mouseenter)=\"onFlyoutMouseEnter()\"\n (mouseleave)=\"onFlyoutMouseLeave()\"\n >\n <div class=\"neu-nav__flyout-title\">{{ flyout.item.label }}</div>\n @for (child of flyout.item.children ?? []; track child.id) {\n @if (child.children?.length) {\n <div class=\"neu-nav__flyout-group\">\n <span class=\"neu-nav__flyout-group-label\">{{ child.label }}</span>\n @for (grand of child.children; track grand.id) {\n @if (grand.href) {\n <a\n class=\"neu-nav__flyout-item\"\n role=\"menuitem\"\n [href]=\"grand.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n (click)=\"flyoutState.set(null)\"\n >\n <neu-icon [name]=\"grand.icon\" size=\"13px\" aria-hidden=\"true\" />\n <span>{{ grand.label }}</span>\n <neu-icon\n name=\"lucideExternalLink\"\n size=\"10px\"\n class=\"neu-nav__external-icon\"\n />\n </a>\n } @else {\n <a\n class=\"neu-nav__flyout-item\"\n role=\"menuitem\"\n [routerLink]=\"grand.route\"\n routerLinkActive=\"neu-nav__flyout-item--active\"\n (click)=\"flyoutState.set(null)\"\n >\n <neu-icon [name]=\"grand.icon\" size=\"13px\" aria-hidden=\"true\" />\n <span>{{ grand.label }}</span>\n </a>\n }\n }\n </div>\n } @else if (child.href) {\n <a\n class=\"neu-nav__flyout-item\"\n role=\"menuitem\"\n [href]=\"child.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n (click)=\"flyoutState.set(null)\"\n >\n <neu-icon [name]=\"child.icon\" size=\"13px\" aria-hidden=\"true\" />\n <span>{{ child.label }}</span>\n <neu-icon name=\"lucideExternalLink\" size=\"10px\" class=\"neu-nav__external-icon\" />\n </a>\n } @else {\n <a\n class=\"neu-nav__flyout-item\"\n role=\"menuitem\"\n [routerLink]=\"child.route\"\n routerLinkActive=\"neu-nav__flyout-item--active\"\n (click)=\"flyoutState.set(null)\"\n >\n <neu-icon [name]=\"child.icon\" size=\"13px\" aria-hidden=\"true\" />\n <span>{{ child.label }}</span>\n </a>\n }\n }\n </div>\n }\n\n <!-- Pestaña collapse/expand — fuera del nav para no ser recortada -->\n @if (collapsible()) {\n <button\n class=\"neu-nav__toggle-tab\"\n type=\"button\"\n [attr.aria-label]=\"isCollapsed() ? expandLabel() : collapseLabel()\"\n [attr.aria-expanded]=\"!isCollapsed()\"\n (click)=\"toggleCollapse()\"\n >\n <neu-icon\n [name]=\"isCollapsed() ? 'lucideChevronRight' : 'lucideChevronLeft'\"\n size=\"12px\"\n aria-hidden=\"true\"\n />\n </button>\n }\n </div>\n `,\n styleUrl: './neu-nav.component.scss',\n})\nexport class NeuNavComponent {\n private readonly router = inject(Router);\n\n // ---- Señal reactiva de ruta activa / Reactive active route signal ----\n private readonly currentUrl = toSignal(\n this.router.events.pipe(filter((e): e is NavigationEnd => e instanceof NavigationEnd)),\n { initialValue: null },\n );\n\n // ---- Inputs ----\n\n /** Lista de ítems de navegación / Navigation item list */\n items = input<NeuNavItem[]>([]);\n\n /** Estado inicial colapsado / Initial collapsed state */\n collapsed = input<boolean>(false);\n\n /** Muestra el botón de colapsar/expandir / Shows the collapse/expand button */\n collapsible = input<boolean>(true);\n\n /** Etiqueta accesible del <nav> / Accessible label for the <nav> */\n ariaLabel = input<string>('Navegación principal');\n\n /** Aria-label del botón cuando el nav está colapsado / Aria-label for the button when the nav is collapsed */\n expandLabel = input<string>('Expandir menú');\n\n /** Aria-label del botón cuando el nav está expandido / Aria-label for the button when the nav is expanded */\n collapseLabel = input<string>('Colapsar menú');\n\n /** Emite cuando cambia el estado colapsado / Emits when the collapsed state changes */\n collapsedChange = output<boolean>();\n\n // ---- Estado interno / Internal state ----\n\n // Sigue el input `collapsed` del padre (permite el configurador)\n // pero puede ser sobreescrito localmente con toggleCollapse()\n readonly isCollapsed = linkedSignal(() => this.collapsed());\n private readonly openGroups = signal<Set<string>>(new Set());\n\n // ---- Flyout para modo colapsado / Flyout for collapsed mode ----\n readonly flyoutState = signal<{ item: NeuNavItem; top: number; left: number } | null>(null);\n private _flyoutTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor() {\n // Abrimos el grupo activo DESPUÉS de que el padre haya pasado los inputs\n afterNextRender(() => this._openActiveGroup());\n // Limpiamos el timer del flyout al destruir el componente\n inject(DestroyRef).onDestroy(() => {\n if (this._flyoutTimer) clearTimeout(this._flyoutTimer);\n });\n }\n\n // ---- Helpers de estado / State helpers ----\n\n toggleCollapse(): void {\n this.isCollapsed.update((v) => {\n const next = !v;\n this.collapsedChange.emit(next);\n return next;\n });\n }\n\n toggleGroup(id: string): void {\n this.openGroups.update((s) => {\n const next = new Set(s);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n }\n\n isGroupOpen(id: string): boolean {\n return this.openGroups().has(id);\n }\n\n isCurrentRoute(route: string): boolean {\n if (!route) return false;\n // Consume la señal para que OnPush re-evalúe tras navegación\n this.currentUrl();\n return this.router.url === route || this.router.url.startsWith(route + '?');\n }\n\n isGroupActive(item: NeuNavItem): boolean {\n if (!item.children?.length) return false;\n return item.children.some(\n (c) =>\n this.isCurrentRoute(c.route ?? '') ||\n (c.children?.some((g) => this.isCurrentRoute(g.route ?? '')) ?? false),\n );\n }\n\n // ---- Flyout handlers ----\n\n onGroupMouseEnter(item: NeuNavItem, event: MouseEvent): void {\n if (!this.isCollapsed() || !item.children?.length) return;\n if (this._flyoutTimer) {\n clearTimeout(this._flyoutTimer);\n this._flyoutTimer = null;\n }\n const rect = (event.currentTarget as HTMLElement).getBoundingClientRect();\n this.flyoutState.set({ item, top: rect.top, left: rect.right });\n }\n\n onGroupMouseLeave(): void {\n if (!this.isCollapsed()) return;\n this._flyoutTimer = setTimeout(() => this.flyoutState.set(null), 150);\n }\n\n onFlyoutMouseEnter(): void {\n if (this._flyoutTimer) {\n clearTimeout(this._flyoutTimer);\n this._flyoutTimer = null;\n }\n }\n\n onFlyoutMouseLeave(): void {\n this._flyoutTimer = setTimeout(() => this.flyoutState.set(null), 150);\n }\n\n private _openActiveGroup(): void {\n const toOpen = new Set<string>();\n for (const item of this.items()) {\n if (!item.children) continue;\n for (const child of item.children) {\n if (child.route && this.router.url.startsWith(child.route)) {\n toOpen.add(item.id);\n }\n if (child.children) {\n for (const grand of child.children) {\n if (grand.route && this.router.url.startsWith(grand.route)) {\n toOpen.add(item.id);\n toOpen.add(child.id);\n }\n }\n }\n }\n }\n if (toOpen.size > 0) {\n this.openGroups.set(toOpen);\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"neural-ui-core-nav.mjs","sources":["../../../../projects/ui-core/nav/neu-nav.component.ts","../../../../projects/ui-core/nav/neural-ui-core-nav.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n ViewEncapsulation,\n afterNextRender,\n inject,\n input,\n linkedSignal,\n output,\n signal,\n} from '@angular/core';\nimport { RouterLink, RouterLinkActive, Router, NavigationEnd } from '@angular/router';\nimport { filter } from 'rxjs';\nimport { toSignal } from '@angular/core/rxjs-interop';\nimport { NeuIconComponent } from '@neural-ui/core/icon';\nimport { NeuTooltipDirective } from '@neural-ui/core/tooltip';\n\n// ---- Tipos públicos / Public types ----\n\n/**\n * Ítem de navegación con soporte para 3 niveles de profundidad.\n *\n * Destino del enlace — usa UNO de los dos:\n * - `route` → navegación interna Angular (RouterLink)\n * - `href` → URL externa, se abre en nueva pestaña con rel=\"noopener noreferrer\"\n *\n * Los ítems con `children` actúan como grupo acordeón (sin destino propio).\n * Máximo 3 niveles: raíz → hijos → nietos.\n * Los nietos no pueden tener `children`.\n */\nexport interface NeuNavItem {\n id: string;\n label: string;\n icon: string;\n /** Ruta Angular interna (RouterLink). Excluye `href`. / Internal Angular route (RouterLink). Excludes `href`. */\n route?: string;\n /** URL externa. Se abre en nueva pestaña. Excluye `route`. / External URL. Opens in a new tab. Excludes `route`. */\n href?: string;\n /** Ítems hijo (nivel 2). Cada hijo puede tener sus propios `children` (nivel 3). / Child items (level 2). Each child can have its own `children` (level 3). */\n children?: NeuNavItem[];\n badge?: string;\n badgeVariant?: 'default' | 'success' | 'warning' | 'danger' | 'info';\n disabled?: boolean;\n}\n\n@Component({\n selector: 'neu-nav',\n imports: [RouterLink, RouterLinkActive, NeuIconComponent, NeuTooltipDirective],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div class=\"neu-nav-wrapper\" [class.neu-nav-wrapper--collapsed]=\"isCollapsed()\">\n <nav\n class=\"neu-nav\"\n [class.neu-nav--collapsed]=\"isCollapsed()\"\n [attr.aria-label]=\"ariaLabel()\"\n >\n <!-- Brand slot -->\n <div class=\"neu-nav__brand\">\n <!-- Icono visible solo en modo colapsado -->\n <div class=\"neu-nav__brand-icon\">\n <ng-content select=\"[neu-nav-brand-icon]\" />\n </div>\n <!-- Contenido completo visible en modo expandido -->\n <div class=\"neu-nav__brand-content\">\n <ng-content select=\"[neu-nav-brand]\" />\n </div>\n </div>\n\n <!-- Items (nivel 1) -->\n <div class=\"neu-nav__items\" role=\"list\">\n @for (item of items(); track item.id) {\n @if (item.children?.length) {\n <!-- NIVEL 1 — Grupo acordeón -->\n <div\n class=\"neu-nav__group\"\n [class.neu-nav__group--open]=\"isGroupOpen(item.id)\"\n role=\"listitem\"\n (mouseenter)=\"onGroupMouseEnter(item, $event)\"\n (mouseleave)=\"onGroupMouseLeave()\"\n >\n <button\n class=\"neu-nav__item neu-nav__item--parent\"\n type=\"button\"\n [class.neu-nav__item--active]=\"isGroupActive(item)\"\n [class.neu-nav__item--disabled]=\"item.disabled\"\n [attr.aria-expanded]=\"isGroupOpen(item.id)\"\n [attr.aria-haspopup]=\"true\"\n [attr.disabled]=\"item.disabled ? '' : null\"\n [neuTooltip]=\"isCollapsed() ? item.label : ''\"\n neuTooltipPosition=\"right\"\n (click)=\"!isCollapsed() && toggleGroup(item.id)\"\n >\n <neu-icon\n [name]=\"item.icon\"\n size=\"18px\"\n class=\"neu-nav__item-icon\"\n aria-hidden=\"true\"\n />\n <span class=\"neu-nav__item-label\">{{ item.label }}</span>\n @if (item.badge) {\n <span\n class=\"neu-nav__item-badge neu-nav__item-badge--{{\n item.badgeVariant ?? 'default'\n }}\"\n >{{ item.badge }}</span\n >\n }\n <neu-icon\n name=\"lucideChevronRight\"\n size=\"14px\"\n class=\"neu-nav__group-chevron\"\n aria-hidden=\"true\"\n />\n </button>\n\n <!-- Submenú nivel 2 -->\n @if (!isCollapsed() && isGroupOpen(item.id)) {\n <div class=\"neu-nav__submenu\" role=\"list\">\n @for (child of item.children; track child.id) {\n @if (child.children?.length) {\n <!-- NIVEL 2 — Subgrupo acordeón -->\n <div\n class=\"neu-nav__group neu-nav__group--nested\"\n [class.neu-nav__group--open]=\"isGroupOpen(child.id)\"\n role=\"listitem\"\n >\n <button\n class=\"neu-nav__item neu-nav__item--child neu-nav__item--parent\"\n type=\"button\"\n [class.neu-nav__item--active]=\"isGroupActive(child)\"\n [class.neu-nav__item--disabled]=\"child.disabled\"\n [attr.aria-expanded]=\"isGroupOpen(child.id)\"\n [attr.aria-haspopup]=\"true\"\n [attr.disabled]=\"child.disabled ? '' : null\"\n (click)=\"toggleGroup(child.id)\"\n >\n <neu-icon\n [name]=\"child.icon\"\n size=\"15px\"\n class=\"neu-nav__item-icon\"\n aria-hidden=\"true\"\n />\n <span class=\"neu-nav__item-label\">{{ child.label }}</span>\n @if (child.badge) {\n <span\n class=\"neu-nav__item-badge neu-nav__item-badge--{{\n child.badgeVariant ?? 'default'\n }}\"\n >{{ child.badge }}</span\n >\n }\n <neu-icon\n name=\"lucideChevronRight\"\n size=\"13px\"\n class=\"neu-nav__group-chevron\"\n aria-hidden=\"true\"\n />\n </button>\n\n <!-- Submenú nivel 3 -->\n @if (isGroupOpen(child.id)) {\n <div class=\"neu-nav__submenu neu-nav__submenu--nested\" role=\"list\">\n @for (grand of child.children; track grand.id) {\n @if (grand.href) {\n <!-- NIVEL 3 — Enlace externo -->\n <a\n class=\"neu-nav__item neu-nav__item--grandchild\"\n [class.neu-nav__item--disabled]=\"grand.disabled\"\n [href]=\"grand.disabled ? null : grand.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n [attr.aria-disabled]=\"grand.disabled ? 'true' : null\"\n role=\"listitem\"\n >\n <neu-icon\n [name]=\"grand.icon\"\n size=\"14px\"\n class=\"neu-nav__item-icon\"\n aria-hidden=\"true\"\n />\n <span class=\"neu-nav__item-label\">{{ grand.label }}</span>\n <neu-icon\n name=\"lucideExternalLink\"\n size=\"11px\"\n class=\"neu-nav__external-icon\"\n aria-hidden=\"true\"\n />\n </a>\n } @else {\n <!-- NIVEL 3 — Enlace interno -->\n <a\n class=\"neu-nav__item neu-nav__item--grandchild\"\n [class.neu-nav__item--disabled]=\"grand.disabled\"\n [routerLink]=\"grand.disabled ? null : (grand.route ?? null)\"\n routerLinkActive=\"neu-nav__item--active\"\n [routerLinkActiveOptions]=\"{ exact: true }\"\n [attr.aria-current]=\"\n isCurrentRoute(grand.route ?? '') ? 'page' : null\n \"\n role=\"listitem\"\n >\n <neu-icon\n [name]=\"grand.icon\"\n size=\"14px\"\n class=\"neu-nav__item-icon\"\n aria-hidden=\"true\"\n />\n <span class=\"neu-nav__item-label\">{{ grand.label }}</span>\n @if (grand.badge) {\n <span\n class=\"neu-nav__item-badge neu-nav__item-badge--{{\n grand.badgeVariant ?? 'default'\n }}\"\n >{{ grand.badge }}</span\n >\n }\n </a>\n }\n }\n </div>\n }\n </div>\n } @else if (child.href) {\n <!-- NIVEL 2 — Enlace externo -->\n <a\n class=\"neu-nav__item neu-nav__item--child\"\n [class.neu-nav__item--disabled]=\"child.disabled\"\n [href]=\"child.disabled ? null : child.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n [attr.aria-disabled]=\"child.disabled ? 'true' : null\"\n role=\"listitem\"\n >\n <neu-icon\n [name]=\"child.icon\"\n size=\"15px\"\n class=\"neu-nav__item-icon\"\n aria-hidden=\"true\"\n />\n <span class=\"neu-nav__item-label\">{{ child.label }}</span>\n @if (child.badge) {\n <span\n class=\"neu-nav__item-badge neu-nav__item-badge--{{\n child.badgeVariant ?? 'default'\n }}\"\n >{{ child.badge }}</span\n >\n }\n <neu-icon\n name=\"lucideExternalLink\"\n size=\"12px\"\n class=\"neu-nav__external-icon\"\n aria-hidden=\"true\"\n />\n </a>\n } @else {\n <!-- NIVEL 2 — Enlace interno -->\n <a\n class=\"neu-nav__item neu-nav__item--child\"\n [class.neu-nav__item--disabled]=\"child.disabled\"\n [routerLink]=\"child.disabled ? null : (child.route ?? null)\"\n routerLinkActive=\"neu-nav__item--active\"\n [routerLinkActiveOptions]=\"{ exact: true }\"\n [attr.aria-current]=\"isCurrentRoute(child.route ?? '') ? 'page' : null\"\n role=\"listitem\"\n >\n <neu-icon\n [name]=\"child.icon\"\n size=\"15px\"\n class=\"neu-nav__item-icon\"\n aria-hidden=\"true\"\n />\n <span class=\"neu-nav__item-label\">{{ child.label }}</span>\n @if (child.badge) {\n <span\n class=\"neu-nav__item-badge neu-nav__item-badge--{{\n child.badgeVariant ?? 'default'\n }}\"\n >{{ child.badge }}</span\n >\n }\n </a>\n }\n }\n </div>\n }\n </div>\n } @else if (item.href) {\n <!-- NIVEL 1 — Enlace externo -->\n <a\n class=\"neu-nav__item\"\n [class.neu-nav__item--disabled]=\"item.disabled\"\n [href]=\"item.disabled ? null : item.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n [attr.aria-disabled]=\"item.disabled ? 'true' : null\"\n [neuTooltip]=\"isCollapsed() ? item.label : ''\"\n neuTooltipPosition=\"right\"\n role=\"listitem\"\n >\n <neu-icon\n [name]=\"item.icon\"\n size=\"18px\"\n class=\"neu-nav__item-icon\"\n aria-hidden=\"true\"\n />\n <span class=\"neu-nav__item-label\">{{ item.label }}</span>\n @if (item.badge) {\n <span\n class=\"neu-nav__item-badge neu-nav__item-badge--{{\n item.badgeVariant ?? 'default'\n }}\"\n >{{ item.badge }}</span\n >\n }\n <neu-icon\n name=\"lucideExternalLink\"\n size=\"13px\"\n class=\"neu-nav__external-icon\"\n aria-hidden=\"true\"\n />\n </a>\n } @else {\n <!-- NIVEL 1 — Enlace interno -->\n <a\n class=\"neu-nav__item\"\n [class.neu-nav__item--disabled]=\"item.disabled\"\n [routerLink]=\"item.disabled ? null : (item.route ?? null)\"\n routerLinkActive=\"neu-nav__item--active\"\n [routerLinkActiveOptions]=\"{ exact: item.route === '/' }\"\n [attr.aria-current]=\"isCurrentRoute(item.route ?? '') ? 'page' : null\"\n [neuTooltip]=\"isCollapsed() ? item.label : ''\"\n neuTooltipPosition=\"right\"\n role=\"listitem\"\n >\n <neu-icon\n [name]=\"item.icon\"\n size=\"18px\"\n class=\"neu-nav__item-icon\"\n aria-hidden=\"true\"\n />\n <span class=\"neu-nav__item-label\">{{ item.label }}</span>\n @if (item.badge) {\n <span\n class=\"neu-nav__item-badge neu-nav__item-badge--{{\n item.badgeVariant ?? 'default'\n }}\"\n >{{ item.badge }}</span\n >\n }\n </a>\n }\n }\n </div>\n\n <!-- Footer slot -->\n <div class=\"neu-nav__footer\">\n <ng-content select=\"[neu-nav-footer]\" />\n </div>\n </nav>\n\n <!-- Flyout panel para grupos en modo colapsado -->\n @if (flyoutState(); as flyout) {\n <div\n class=\"neu-nav__flyout\"\n [style.top.px]=\"flyout.top\"\n [style.left.px]=\"flyout.left\"\n role=\"menu\"\n (mouseenter)=\"onFlyoutMouseEnter()\"\n (mouseleave)=\"onFlyoutMouseLeave()\"\n >\n <div class=\"neu-nav__flyout-title\">{{ flyout.item.label }}</div>\n @for (child of flyout.item.children ?? []; track child.id) {\n @if (child.children?.length) {\n <div class=\"neu-nav__flyout-group\">\n <span class=\"neu-nav__flyout-group-label\">{{ child.label }}</span>\n @for (grand of child.children; track grand.id) {\n @if (grand.href) {\n <a\n class=\"neu-nav__flyout-item\"\n role=\"menuitem\"\n [href]=\"grand.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n (click)=\"flyoutState.set(null)\"\n >\n <neu-icon [name]=\"grand.icon\" size=\"13px\" aria-hidden=\"true\" />\n <span>{{ grand.label }}</span>\n <neu-icon\n name=\"lucideExternalLink\"\n size=\"10px\"\n class=\"neu-nav__external-icon\"\n />\n </a>\n } @else {\n <a\n class=\"neu-nav__flyout-item\"\n role=\"menuitem\"\n [routerLink]=\"grand.route\"\n routerLinkActive=\"neu-nav__flyout-item--active\"\n (click)=\"flyoutState.set(null)\"\n >\n <neu-icon [name]=\"grand.icon\" size=\"13px\" aria-hidden=\"true\" />\n <span>{{ grand.label }}</span>\n </a>\n }\n }\n </div>\n } @else if (child.href) {\n <a\n class=\"neu-nav__flyout-item\"\n role=\"menuitem\"\n [href]=\"child.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n (click)=\"flyoutState.set(null)\"\n >\n <neu-icon [name]=\"child.icon\" size=\"13px\" aria-hidden=\"true\" />\n <span>{{ child.label }}</span>\n <neu-icon name=\"lucideExternalLink\" size=\"10px\" class=\"neu-nav__external-icon\" />\n </a>\n } @else {\n <a\n class=\"neu-nav__flyout-item\"\n role=\"menuitem\"\n [routerLink]=\"child.route\"\n routerLinkActive=\"neu-nav__flyout-item--active\"\n (click)=\"flyoutState.set(null)\"\n >\n <neu-icon [name]=\"child.icon\" size=\"13px\" aria-hidden=\"true\" />\n <span>{{ child.label }}</span>\n </a>\n }\n }\n </div>\n }\n\n <!-- Pestaña collapse/expand — fuera del nav para no ser recortada -->\n @if (collapsible()) {\n <button\n class=\"neu-nav__toggle-tab\"\n type=\"button\"\n [attr.aria-label]=\"isCollapsed() ? expandLabel() : collapseLabel()\"\n [attr.aria-expanded]=\"!isCollapsed()\"\n (click)=\"toggleCollapse()\"\n >\n <neu-icon\n [name]=\"isCollapsed() ? 'lucideChevronRight' : 'lucideChevronLeft'\"\n size=\"12px\"\n aria-hidden=\"true\"\n />\n </button>\n }\n </div>\n `,\n styleUrl: './neu-nav.component.scss',\n})\nexport class NeuNavComponent {\n private readonly router = inject(Router);\n\n // ---- Señal reactiva de ruta activa / Reactive active route signal ----\n private readonly currentUrl = toSignal(\n this.router.events.pipe(filter((e): e is NavigationEnd => e instanceof NavigationEnd)),\n { initialValue: null },\n );\n\n // ---- Inputs ----\n\n /** Lista de ítems de navegación / Navigation item list */\n items = input<NeuNavItem[]>([]);\n\n /** Estado inicial colapsado / Initial collapsed state */\n collapsed = input<boolean>(false);\n\n /** Muestra el botón de colapsar/expandir / Shows the collapse/expand button */\n collapsible = input<boolean>(true);\n\n /** Etiqueta accesible del <nav> / Accessible label for the <nav> */\n ariaLabel = input<string>('Navegación principal');\n\n /** Aria-label del botón cuando el nav está colapsado / Aria-label for the button when the nav is collapsed */\n expandLabel = input<string>('Expandir menú');\n\n /** Aria-label del botón cuando el nav está expandido / Aria-label for the button when the nav is expanded */\n collapseLabel = input<string>('Colapsar menú');\n\n /** Emite cuando cambia el estado colapsado / Emits when the collapsed state changes */\n collapsedChange = output<boolean>();\n\n // ---- Estado interno / Internal state ----\n\n // Sigue el input `collapsed` del padre (permite el configurador)\n // pero puede ser sobreescrito localmente con toggleCollapse()\n readonly isCollapsed = linkedSignal(() => this.collapsed());\n private readonly openGroups = signal<Set<string>>(new Set());\n\n // ---- Flyout para modo colapsado / Flyout for collapsed mode ----\n readonly flyoutState = signal<{ item: NeuNavItem; top: number; left: number } | null>(null);\n private _flyoutTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor() {\n // Abrimos el grupo activo DESPUÉS de que el padre haya pasado los inputs\n afterNextRender(() => this._openActiveGroup());\n // Limpiamos el timer del flyout al destruir el componente\n inject(DestroyRef).onDestroy(() => {\n if (this._flyoutTimer) clearTimeout(this._flyoutTimer);\n });\n }\n\n // ---- Helpers de estado / State helpers ----\n\n toggleCollapse(): void {\n this.isCollapsed.update((v) => {\n const next = !v;\n this.collapsedChange.emit(next);\n return next;\n });\n }\n\n toggleGroup(id: string): void {\n this.openGroups.update((s) => {\n const next = new Set(s);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n }\n\n isGroupOpen(id: string): boolean {\n return this.openGroups().has(id);\n }\n\n isCurrentRoute(route: string): boolean {\n if (!route) return false;\n // Consume la señal para que OnPush re-evalúe tras navegación\n this.currentUrl();\n return this.router.url === route || this.router.url.startsWith(route + '?');\n }\n\n isGroupActive(item: NeuNavItem): boolean {\n if (!item.children?.length) return false;\n return item.children.some(\n (c) =>\n this.isCurrentRoute(c.route ?? '') ||\n (c.children?.some((g) => this.isCurrentRoute(g.route ?? '')) ?? false),\n );\n }\n\n // ---- Flyout handlers ----\n\n onGroupMouseEnter(item: NeuNavItem, event: MouseEvent): void {\n if (!this.isCollapsed() || !item.children?.length) return;\n if (this._flyoutTimer) {\n clearTimeout(this._flyoutTimer);\n this._flyoutTimer = null;\n }\n const rect = (event.currentTarget as HTMLElement).getBoundingClientRect();\n this.flyoutState.set({ item, top: rect.top, left: rect.right });\n }\n\n onGroupMouseLeave(): void {\n if (!this.isCollapsed()) return;\n this._flyoutTimer = setTimeout(() => this.flyoutState.set(null), 150);\n }\n\n onFlyoutMouseEnter(): void {\n if (this._flyoutTimer) {\n clearTimeout(this._flyoutTimer);\n this._flyoutTimer = null;\n }\n }\n\n onFlyoutMouseLeave(): void {\n this._flyoutTimer = setTimeout(() => this.flyoutState.set(null), 150);\n }\n\n private _openActiveGroup(): void {\n const toOpen = new Set<string>();\n for (const item of this.items()) {\n if (!item.children) continue;\n for (const child of item.children) {\n if (child.route && this.router.url.startsWith(child.route)) {\n toOpen.add(item.id);\n }\n if (child.children) {\n for (const grand of child.children) {\n if (grand.route && this.router.url.startsWith(grand.route)) {\n toOpen.add(item.id);\n toOpen.add(child.id);\n }\n }\n }\n }\n }\n if (toOpen.size > 0) {\n this.openGroups.set(toOpen);\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
@@ -19,10 +19,8 @@ let _idSeq = 0;
19
19
  * inject(NeuNotificationService).push({ type: 'success', message: '¡Guardado!' });
20
20
  */
21
21
  class NeuNotificationService {
22
- notifications = signal([], /* @ts-ignore */
23
- ...(ngDevMode ? [{ debugName: "notifications" }] : /* istanbul ignore next */ []));
24
- unreadCount = computed(() => this.notifications().filter((n) => !n.read).length, /* @ts-ignore */
25
- ...(ngDevMode ? [{ debugName: "unreadCount" }] : /* istanbul ignore next */ []));
22
+ notifications = signal([], ...(ngDevMode ? [{ debugName: "notifications" }] : /* istanbul ignore next */ []));
23
+ unreadCount = computed(() => this.notifications().filter((n) => !n.read).length, ...(ngDevMode ? [{ debugName: "unreadCount" }] : /* istanbul ignore next */ []));
26
24
  timers = new Map();
27
25
  /** Agrega una notificación / Adds a notification */
28
26
  push(opts) {
@@ -68,10 +66,10 @@ class NeuNotificationService {
68
66
  clearTimeout(timer);
69
67
  this.timers.delete(id);
70
68
  }
71
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NeuNotificationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
72
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NeuNotificationService, providedIn: 'root' });
69
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuNotificationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
70
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuNotificationService, providedIn: 'root' });
73
71
  }
74
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NeuNotificationService, decorators: [{
72
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuNotificationService, decorators: [{
75
73
  type: Injectable,
76
74
  args: [{ providedIn: 'root' }]
77
75
  }] });
@@ -88,8 +86,7 @@ let _panelSeq = 0;
88
86
  class NeuNotificationCenterComponent {
89
87
  _svc = inject(NeuNotificationService);
90
88
  overlay = inject(Overlay);
91
- _isOpen = signal(false, /* @ts-ignore */
92
- ...(ngDevMode ? [{ debugName: "_isOpen" }] : /* istanbul ignore next */ []));
89
+ _isOpen = signal(false, ...(ngDevMode ? [{ debugName: "_isOpen" }] : /* istanbul ignore next */ []));
93
90
  _panelId = `neu-nc-panel-${++_panelSeq}`;
94
91
  _viewportMargin = 16;
95
92
  overlayPositions = [
@@ -136,8 +133,8 @@ class NeuNotificationCenterComponent {
136
133
  return `Hace ${hours}h`;
137
134
  return `Hace ${Math.floor(hours / 24)}d`;
138
135
  }
139
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NeuNotificationCenterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
140
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: NeuNotificationCenterComponent, isStandalone: true, selector: "neu-notification-center", host: { properties: { "attr.aria-label": "\"Centro de notificaciones\"" }, classAttribute: "neu-nc" }, ngImport: i0, template: `
136
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuNotificationCenterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
137
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: NeuNotificationCenterComponent, isStandalone: true, selector: "neu-notification-center", host: { properties: { "attr.aria-label": "\"Centro de notificaciones\"" }, classAttribute: "neu-nc" }, ngImport: i0, template: `
141
138
  <!-- Bell button -->
142
139
  <button
143
140
  cdkOverlayOrigin
@@ -230,7 +227,7 @@ class NeuNotificationCenterComponent {
230
227
  </ng-template>
231
228
  `, isInline: true, styles: ["@charset \"UTF-8\";.neu-nc{position:relative;display:inline-block}.neu-nc__bell{all:unset;position:relative;display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:var(--neu-radius-lg, 12px);cursor:pointer;transition:background .12s}.neu-nc__bell:hover{background:var(--neu-surface-2, #f3f4f6)}.neu-nc__bell:focus-visible{outline:2px solid var(--neu-focus-ring, #0ea5e9);outline-offset:2px}.neu-nc__bell-icon{font-size:1.2rem}.neu-nc__badge{position:absolute;top:4px;right:4px;min-width:16px;height:16px;padding:0 4px;border-radius:999px;background:var(--neu-error);color:var(--neu-text-inverse);font-size:.625rem;font-weight:700;display:flex;align-items:center;justify-content:center;line-height:1}.neu-nc__panel{position:relative;width:320px;max-height:420px;display:flex;flex-direction:column;background:var(--neu-surface-1, #ffffff);border:1px solid var(--neu-border-color, #e5e7eb);border-radius:var(--neu-radius-xl, 16px);box-shadow:0 12px 28px -6px #00000024;z-index:1001;overflow:hidden;animation:neu-nc-in .1s ease}@keyframes neu-nc-in{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}.neu-nc__panel-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--neu-border-color, #e5e7eb);flex-shrink:0}.neu-nc__panel-title{font-size:.9375rem;font-weight:600;color:var(--neu-text-primary, #111)}.neu-nc__panel-actions{display:flex;gap:8px}.neu-nc__action-btn{all:unset;font-size:.75rem;color:var(--neu-color-primary, #0ea5e9);cursor:pointer;padding:2px 6px;border-radius:var(--neu-radius-sm, 4px)}.neu-nc__action-btn:hover{background:var(--neu-color-primary-alpha, rgba(14, 165, 233, .1))}.neu-nc__list{overflow-y:auto;flex:1;padding:6px}.neu-nc__empty{padding:24px;text-align:center;font-size:.875rem;color:var(--neu-text-secondary, #6b7280)}.neu-nc__item{display:flex;align-items:flex-start;gap:10px;padding:10px 10px 10px 12px;border-radius:var(--neu-radius-lg, 12px);position:relative;transition:background .1s}.neu-nc__item:hover{background:var(--neu-surface-2, #f3f4f6)}.neu-nc__item--unread:before{content:\"\";position:absolute;left:4px;top:50%;transform:translateY(-50%);width:6px;height:6px;border-radius:50%;background:var(--neu-color-primary, #0ea5e9)}.neu-nc__item-icon{font-size:1.1rem;flex-shrink:0;padding-top:2px}.neu-nc__item-body{flex:1;min-width:0}.neu-nc__item-title{margin:0 0 2px;font-size:.8125rem;font-weight:600;color:var(--neu-text-primary, #111)}.neu-nc__item-msg{margin:0 0 4px;font-size:.8125rem;color:var(--neu-text-secondary, #4b5563);line-height:1.4}.neu-nc__item-time{font-size:.6875rem;color:var(--neu-text-secondary, #9ca3af)}.neu-nc__item-close{all:unset;opacity:0;cursor:pointer;padding:2px 6px;border-radius:4px;font-size:1rem;color:var(--neu-text-secondary, #9ca3af);flex-shrink:0;transition:opacity .1s}.neu-nc__item:hover .neu-nc__item-close{opacity:1}.neu-nc__item-close:hover{color:var(--neu-text-primary, #111)}\n"], dependencies: [{ kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
232
229
  }
233
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NeuNotificationCenterComponent, decorators: [{
230
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuNotificationCenterComponent, decorators: [{
234
231
  type: Component,
235
232
  args: [{ selector: 'neu-notification-center', imports: [OverlayModule], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: {
236
233
  class: 'neu-nc',
@@ -1 +1 @@
1
- {"version":3,"file":"neural-ui-core-notification-center.mjs","sources":["../../../../projects/ui-core/notification-center/neu-notification-center.component.ts","../../../../projects/ui-core/notification-center/neural-ui-core-notification-center.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n Injectable,\n OnDestroy,\n ViewEncapsulation,\n computed,\n inject,\n signal,\n} from '@angular/core';\nimport { ConnectedPosition, Overlay, OverlayModule } from '@angular/cdk/overlay';\n\nexport type NeuNotificationType = 'info' | 'success' | 'warning' | 'error';\n\nexport interface NeuNotification {\n id: string;\n type: NeuNotificationType;\n title?: string;\n message: string;\n /** Auto-dismiss duration in ms (0 = persistent) */\n duration?: number;\n /** Icon text / emoji */\n icon?: string;\n timestamp: Date;\n read: boolean;\n}\n\nexport interface NeuNotificationOptions extends Omit<\n NeuNotification,\n 'id' | 'timestamp' | 'read'\n> {}\n\nconst DEFAULT_ICONS: Record<NeuNotificationType, string> = {\n info: 'ℹ️',\n success: '✅',\n warning: '⚠️',\n error: '❌',\n};\n\nlet _idSeq = 0;\n\n/**\n * NeuralUI NotificationService\n *\n * Servicio inyectable que gestiona la cola de notificaciones.\n *\n * Uso:\n * inject(NeuNotificationService).push({ type: 'success', message: '¡Guardado!' });\n */\n@Injectable({ providedIn: 'root' })\nexport class NeuNotificationService {\n readonly notifications = signal<NeuNotification[]>([]);\n\n readonly unreadCount = computed(() => this.notifications().filter((n) => !n.read).length);\n\n private readonly timers = new Map<string, ReturnType<typeof setTimeout>>();\n\n /** Agrega una notificación / Adds a notification */\n push(opts: Partial<NeuNotificationOptions> & Pick<NeuNotificationOptions, 'message'>): string {\n const id = `neu-notif-${++_idSeq}`;\n const n: NeuNotification = {\n id,\n type: opts.type ?? 'info',\n title: opts.title,\n message: opts.message,\n icon: opts.icon ?? DEFAULT_ICONS[opts.type ?? 'info'],\n duration: opts.duration ?? 5000,\n timestamp: new Date(),\n read: false,\n };\n this.notifications.update((list) => [n, ...list]);\n\n if (n.duration && n.duration > 0) {\n const timer = setTimeout(() => this.remove(id), n.duration);\n this.timers.set(id, timer);\n }\n return id;\n }\n\n /** Elimina una notificación / Removes a notification */\n remove(id: string): void {\n this.clearTimer(id);\n this.notifications.update((list) => list.filter((n) => n.id !== id));\n }\n\n /** Marca todas como leídas / Marks all as read */\n markAllRead(): void {\n this.notifications.update((list) => list.map((n) => ({ ...n, read: true })));\n }\n\n /** Elimina todas / Clears all */\n clearAll(): void {\n for (const timer of this.timers.values()) {\n clearTimeout(timer);\n }\n this.timers.clear();\n this.notifications.set([]);\n }\n\n private clearTimer(id: string): void {\n const timer = this.timers.get(id);\n if (!timer) return;\n clearTimeout(timer);\n this.timers.delete(id);\n }\n}\n\nlet _panelSeq = 0;\n\n/**\n * NeuralUI NotificationCenter Component\n *\n * Icono de campana con badge de no leídos y panel de notificaciones\n * deslizante. Consume NeuNotificationService.\n *\n * Uso:\n * <neu-notification-center />\n */\n@Component({\n selector: 'neu-notification-center',\n imports: [OverlayModule],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'neu-nc',\n '[attr.aria-label]': '\"Centro de notificaciones\"',\n },\n template: `\n <!-- Bell button -->\n <button\n cdkOverlayOrigin\n #notificationOrigin=\"cdkOverlayOrigin\"\n type=\"button\"\n class=\"neu-nc__bell\"\n [attr.aria-expanded]=\"_isOpen()\"\n [attr.aria-controls]=\"_panelId\"\n [attr.aria-label]=\"'Notificaciones. ' + _svc.unreadCount() + ' sin leer'\"\n (click)=\"_toggle()\"\n >\n <span class=\"neu-nc__bell-icon\" aria-hidden=\"true\">🔔</span>\n @if (_svc.unreadCount() > 0) {\n <span class=\"neu-nc__badge\" aria-hidden=\"true\">{{\n _svc.unreadCount() > 99 ? '99+' : _svc.unreadCount()\n }}</span>\n }\n </button>\n\n <!-- Panel -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"notificationOrigin\"\n [cdkConnectedOverlayOpen]=\"_isOpen()\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayScrollStrategy]=\"overlayScrollStrategy\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop'\"\n [cdkConnectedOverlayPush]=\"true\"\n [cdkConnectedOverlayViewportMargin]=\"_viewportMargin\"\n (backdropClick)=\"_isOpen.set(false)\"\n (detach)=\"_isOpen.set(false)\"\n >\n <div\n class=\"neu-nc__panel\"\n [id]=\"_panelId\"\n role=\"dialog\"\n aria-modal=\"false\"\n aria-label=\"Notificaciones\"\n >\n <div class=\"neu-nc__panel-header\">\n <span class=\"neu-nc__panel-title\">Notificaciones</span>\n <div class=\"neu-nc__panel-actions\">\n @if (_svc.unreadCount() > 0) {\n <button type=\"button\" class=\"neu-nc__action-btn\" (click)=\"_svc.markAllRead()\">\n Leer todo\n </button>\n }\n @if (_svc.notifications().length > 0) {\n <button type=\"button\" class=\"neu-nc__action-btn\" (click)=\"_svc.clearAll()\">\n Limpiar\n </button>\n }\n </div>\n </div>\n\n <div class=\"neu-nc__list\" role=\"list\">\n @if (!_svc.notifications().length) {\n <div class=\"neu-nc__empty\" role=\"status\">No hay notificaciones</div>\n }\n @for (n of _svc.notifications(); track n.id) {\n <div\n class=\"neu-nc__item\"\n role=\"listitem\"\n [class.neu-nc__item--unread]=\"!n.read\"\n [class]=\"'neu-nc__item--' + n.type\"\n >\n <span class=\"neu-nc__item-icon\" aria-hidden=\"true\">{{ n.icon }}</span>\n <div class=\"neu-nc__item-body\">\n @if (n.title) {\n <p class=\"neu-nc__item-title\">{{ n.title }}</p>\n }\n <p class=\"neu-nc__item-msg\">{{ n.message }}</p>\n <time class=\"neu-nc__item-time\" [dateTime]=\"n.timestamp.toISOString()\">\n {{ _relativeTime(n.timestamp) }}\n </time>\n </div>\n <button\n type=\"button\"\n class=\"neu-nc__item-close\"\n [attr.aria-label]=\"'Cerrar notificación'\"\n (click)=\"_svc.remove(n.id)\"\n >\n ×\n </button>\n </div>\n }\n </div>\n </div>\n </ng-template>\n `,\n styleUrl: './neu-notification-center.component.scss',\n})\nexport class NeuNotificationCenterComponent {\n readonly _svc = inject(NeuNotificationService);\n private readonly overlay = inject(Overlay);\n readonly _isOpen = signal(false);\n readonly _panelId = `neu-nc-panel-${++_panelSeq}`;\n readonly _viewportMargin = 16;\n readonly overlayPositions: ConnectedPosition[] = [\n {\n originX: 'end',\n originY: 'bottom',\n overlayX: 'end',\n overlayY: 'top',\n offsetY: 8,\n },\n {\n originX: 'end',\n originY: 'top',\n overlayX: 'end',\n overlayY: 'bottom',\n offsetY: -8,\n },\n {\n originX: 'start',\n originY: 'bottom',\n overlayX: 'start',\n overlayY: 'top',\n offsetY: 8,\n },\n ];\n readonly overlayScrollStrategy = this.overlay.scrollStrategies.reposition();\n\n _toggle(): void {\n const opening = !this._isOpen();\n this._isOpen.set(opening);\n if (opening) {\n // Mark all as read when panel opens\n setTimeout(() => this._svc.markAllRead(), 500);\n }\n }\n\n _relativeTime(date: Date): string {\n const diff = Date.now() - date.getTime();\n const mins = Math.floor(diff / 60000);\n if (mins < 1) return 'Ahora';\n if (mins < 60) return `Hace ${mins} min`;\n const hours = Math.floor(mins / 60);\n if (hours < 24) return `Hace ${hours}h`;\n return `Hace ${Math.floor(hours / 24)}d`;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"neural-ui-core-notification-center.mjs","sources":["../../../../projects/ui-core/notification-center/neu-notification-center.component.ts","../../../../projects/ui-core/notification-center/neural-ui-core-notification-center.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n Injectable,\n OnDestroy,\n ViewEncapsulation,\n computed,\n inject,\n signal,\n} from '@angular/core';\nimport { ConnectedPosition, Overlay, OverlayModule } from '@angular/cdk/overlay';\n\nexport type NeuNotificationType = 'info' | 'success' | 'warning' | 'error';\n\nexport interface NeuNotification {\n id: string;\n type: NeuNotificationType;\n title?: string;\n message: string;\n /** Auto-dismiss duration in ms (0 = persistent) */\n duration?: number;\n /** Icon text / emoji */\n icon?: string;\n timestamp: Date;\n read: boolean;\n}\n\nexport interface NeuNotificationOptions extends Omit<\n NeuNotification,\n 'id' | 'timestamp' | 'read'\n> {}\n\nconst DEFAULT_ICONS: Record<NeuNotificationType, string> = {\n info: 'ℹ️',\n success: '✅',\n warning: '⚠️',\n error: '❌',\n};\n\nlet _idSeq = 0;\n\n/**\n * NeuralUI NotificationService\n *\n * Servicio inyectable que gestiona la cola de notificaciones.\n *\n * Uso:\n * inject(NeuNotificationService).push({ type: 'success', message: '¡Guardado!' });\n */\n@Injectable({ providedIn: 'root' })\nexport class NeuNotificationService {\n readonly notifications = signal<NeuNotification[]>([]);\n\n readonly unreadCount = computed(() => this.notifications().filter((n) => !n.read).length);\n\n private readonly timers = new Map<string, ReturnType<typeof setTimeout>>();\n\n /** Agrega una notificación / Adds a notification */\n push(opts: Partial<NeuNotificationOptions> & Pick<NeuNotificationOptions, 'message'>): string {\n const id = `neu-notif-${++_idSeq}`;\n const n: NeuNotification = {\n id,\n type: opts.type ?? 'info',\n title: opts.title,\n message: opts.message,\n icon: opts.icon ?? DEFAULT_ICONS[opts.type ?? 'info'],\n duration: opts.duration ?? 5000,\n timestamp: new Date(),\n read: false,\n };\n this.notifications.update((list) => [n, ...list]);\n\n if (n.duration && n.duration > 0) {\n const timer = setTimeout(() => this.remove(id), n.duration);\n this.timers.set(id, timer);\n }\n return id;\n }\n\n /** Elimina una notificación / Removes a notification */\n remove(id: string): void {\n this.clearTimer(id);\n this.notifications.update((list) => list.filter((n) => n.id !== id));\n }\n\n /** Marca todas como leídas / Marks all as read */\n markAllRead(): void {\n this.notifications.update((list) => list.map((n) => ({ ...n, read: true })));\n }\n\n /** Elimina todas / Clears all */\n clearAll(): void {\n for (const timer of this.timers.values()) {\n clearTimeout(timer);\n }\n this.timers.clear();\n this.notifications.set([]);\n }\n\n private clearTimer(id: string): void {\n const timer = this.timers.get(id);\n if (!timer) return;\n clearTimeout(timer);\n this.timers.delete(id);\n }\n}\n\nlet _panelSeq = 0;\n\n/**\n * NeuralUI NotificationCenter Component\n *\n * Icono de campana con badge de no leídos y panel de notificaciones\n * deslizante. Consume NeuNotificationService.\n *\n * Uso:\n * <neu-notification-center />\n */\n@Component({\n selector: 'neu-notification-center',\n imports: [OverlayModule],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'neu-nc',\n '[attr.aria-label]': '\"Centro de notificaciones\"',\n },\n template: `\n <!-- Bell button -->\n <button\n cdkOverlayOrigin\n #notificationOrigin=\"cdkOverlayOrigin\"\n type=\"button\"\n class=\"neu-nc__bell\"\n [attr.aria-expanded]=\"_isOpen()\"\n [attr.aria-controls]=\"_panelId\"\n [attr.aria-label]=\"'Notificaciones. ' + _svc.unreadCount() + ' sin leer'\"\n (click)=\"_toggle()\"\n >\n <span class=\"neu-nc__bell-icon\" aria-hidden=\"true\">🔔</span>\n @if (_svc.unreadCount() > 0) {\n <span class=\"neu-nc__badge\" aria-hidden=\"true\">{{\n _svc.unreadCount() > 99 ? '99+' : _svc.unreadCount()\n }}</span>\n }\n </button>\n\n <!-- Panel -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"notificationOrigin\"\n [cdkConnectedOverlayOpen]=\"_isOpen()\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayScrollStrategy]=\"overlayScrollStrategy\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop'\"\n [cdkConnectedOverlayPush]=\"true\"\n [cdkConnectedOverlayViewportMargin]=\"_viewportMargin\"\n (backdropClick)=\"_isOpen.set(false)\"\n (detach)=\"_isOpen.set(false)\"\n >\n <div\n class=\"neu-nc__panel\"\n [id]=\"_panelId\"\n role=\"dialog\"\n aria-modal=\"false\"\n aria-label=\"Notificaciones\"\n >\n <div class=\"neu-nc__panel-header\">\n <span class=\"neu-nc__panel-title\">Notificaciones</span>\n <div class=\"neu-nc__panel-actions\">\n @if (_svc.unreadCount() > 0) {\n <button type=\"button\" class=\"neu-nc__action-btn\" (click)=\"_svc.markAllRead()\">\n Leer todo\n </button>\n }\n @if (_svc.notifications().length > 0) {\n <button type=\"button\" class=\"neu-nc__action-btn\" (click)=\"_svc.clearAll()\">\n Limpiar\n </button>\n }\n </div>\n </div>\n\n <div class=\"neu-nc__list\" role=\"list\">\n @if (!_svc.notifications().length) {\n <div class=\"neu-nc__empty\" role=\"status\">No hay notificaciones</div>\n }\n @for (n of _svc.notifications(); track n.id) {\n <div\n class=\"neu-nc__item\"\n role=\"listitem\"\n [class.neu-nc__item--unread]=\"!n.read\"\n [class]=\"'neu-nc__item--' + n.type\"\n >\n <span class=\"neu-nc__item-icon\" aria-hidden=\"true\">{{ n.icon }}</span>\n <div class=\"neu-nc__item-body\">\n @if (n.title) {\n <p class=\"neu-nc__item-title\">{{ n.title }}</p>\n }\n <p class=\"neu-nc__item-msg\">{{ n.message }}</p>\n <time class=\"neu-nc__item-time\" [dateTime]=\"n.timestamp.toISOString()\">\n {{ _relativeTime(n.timestamp) }}\n </time>\n </div>\n <button\n type=\"button\"\n class=\"neu-nc__item-close\"\n [attr.aria-label]=\"'Cerrar notificación'\"\n (click)=\"_svc.remove(n.id)\"\n >\n ×\n </button>\n </div>\n }\n </div>\n </div>\n </ng-template>\n `,\n styleUrl: './neu-notification-center.component.scss',\n})\nexport class NeuNotificationCenterComponent {\n readonly _svc = inject(NeuNotificationService);\n private readonly overlay = inject(Overlay);\n readonly _isOpen = signal(false);\n readonly _panelId = `neu-nc-panel-${++_panelSeq}`;\n readonly _viewportMargin = 16;\n readonly overlayPositions: ConnectedPosition[] = [\n {\n originX: 'end',\n originY: 'bottom',\n overlayX: 'end',\n overlayY: 'top',\n offsetY: 8,\n },\n {\n originX: 'end',\n originY: 'top',\n overlayX: 'end',\n overlayY: 'bottom',\n offsetY: -8,\n },\n {\n originX: 'start',\n originY: 'bottom',\n overlayX: 'start',\n overlayY: 'top',\n offsetY: 8,\n },\n ];\n readonly overlayScrollStrategy = this.overlay.scrollStrategies.reposition();\n\n _toggle(): void {\n const opening = !this._isOpen();\n this._isOpen.set(opening);\n if (opening) {\n // Mark all as read when panel opens\n setTimeout(() => this._svc.markAllRead(), 500);\n }\n }\n\n _relativeTime(date: Date): string {\n const diff = Date.now() - date.getTime();\n const mins = Math.floor(diff / 60000);\n if (mins < 1) return 'Ahora';\n if (mins < 60) return `Hace ${mins} min`;\n const hours = Math.floor(mins / 60);\n if (hours < 24) return `Hace ${hours}h`;\n return `Hace ${Math.floor(hours / 24)}d`;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
@@ -16,48 +16,33 @@ let _seq = 0;
16
16
  */
17
17
  class NeuNumberInputComponent {
18
18
  /** Valor mínimo / Min value */
19
- min = input(-Infinity, /* @ts-ignore */
20
- ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
19
+ min = input(-Infinity, ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
21
20
  /** Valor máximo / Max value */
22
- max = input(Infinity, /* @ts-ignore */
23
- ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
21
+ max = input(Infinity, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
24
22
  /** Incremento / Step */
25
- step = input(1, /* @ts-ignore */
26
- ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
23
+ step = input(1, ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
27
24
  /** Etiqueta para el input (accesibilidad) / Label for the input (accessibility) */
28
- label = input('', /* @ts-ignore */
29
- ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
25
+ label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
30
26
  /** Muestra el label como flotante dentro del campo. No compatible con vertical=true. / Shows the label as floating inside the field. Not compatible with vertical=true. */
31
- floatingLabel = input(false, /* @ts-ignore */
32
- ...(ngDevMode ? [{ debugName: "floatingLabel" }] : /* istanbul ignore next */ []));
27
+ floatingLabel = input(false, ...(ngDevMode ? [{ debugName: "floatingLabel" }] : /* istanbul ignore next */ []));
33
28
  /** Aria-label del botón de decremento */
34
- decrementLabel = input('Disminuir', /* @ts-ignore */
35
- ...(ngDevMode ? [{ debugName: "decrementLabel" }] : /* istanbul ignore next */ []));
29
+ decrementLabel = input('Disminuir', ...(ngDevMode ? [{ debugName: "decrementLabel" }] : /* istanbul ignore next */ []));
36
30
  /** Aria-label del botón de incremento */
37
- incrementLabel = input('Aumentar', /* @ts-ignore */
38
- ...(ngDevMode ? [{ debugName: "incrementLabel" }] : /* istanbul ignore next */ []));
31
+ incrementLabel = input('Aumentar', ...(ngDevMode ? [{ debugName: "incrementLabel" }] : /* istanbul ignore next */ []));
39
32
  /** Muestra los botones en vertical / Shows buttons vertically */
40
- vertical = input(false, /* @ts-ignore */
41
- ...(ngDevMode ? [{ debugName: "vertical" }] : /* istanbul ignore next */ []));
33
+ vertical = input(false, ...(ngDevMode ? [{ debugName: "vertical" }] : /* istanbul ignore next */ []));
42
34
  /** Agrupa ambos botones apilados al final del input / Groups both buttons stacked at input end */
43
- stacked = input(true, /* @ts-ignore */
44
- ...(ngDevMode ? [{ debugName: "stacked" }] : /* istanbul ignore next */ []));
35
+ stacked = input(true, ...(ngDevMode ? [{ debugName: "stacked" }] : /* istanbul ignore next */ []));
45
36
  /** Tamaño del campo: 'sm' = 36px | 'md' = 48px | 'lg' = 56px / Field size */
46
- size = input('md', /* @ts-ignore */
47
- ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
37
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
48
38
  /** Emitido en cada cambio / Emitted on each change */
49
39
  valueChange = output();
50
40
  _id = `neu-number-input-${++_seq}`;
51
- _cvaDisabled = signal(false, /* @ts-ignore */
52
- ...(ngDevMode ? [{ debugName: "_cvaDisabled" }] : /* istanbul ignore next */ []));
53
- _value = signal(0, /* @ts-ignore */
54
- ...(ngDevMode ? [{ debugName: "_value" }] : /* istanbul ignore next */ []));
55
- _focused = signal(false, /* @ts-ignore */
56
- ...(ngDevMode ? [{ debugName: "_focused" }] : /* istanbul ignore next */ []));
57
- hasValue = computed(() => Number.isFinite(this._value()), /* @ts-ignore */
58
- ...(ngDevMode ? [{ debugName: "hasValue" }] : /* istanbul ignore next */ []));
59
- effectiveFloatingLabel = computed(() => this.floatingLabel() && !this.vertical(), /* @ts-ignore */
60
- ...(ngDevMode ? [{ debugName: "effectiveFloatingLabel" }] : /* istanbul ignore next */ []));
41
+ _cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_cvaDisabled" }] : /* istanbul ignore next */ []));
42
+ _value = signal(0, ...(ngDevMode ? [{ debugName: "_value" }] : /* istanbul ignore next */ []));
43
+ _focused = signal(false, ...(ngDevMode ? [{ debugName: "_focused" }] : /* istanbul ignore next */ []));
44
+ hasValue = computed(() => Number.isFinite(this._value()), ...(ngDevMode ? [{ debugName: "hasValue" }] : /* istanbul ignore next */ []));
45
+ effectiveFloatingLabel = computed(() => this.floatingLabel() && !this.vertical(), ...(ngDevMode ? [{ debugName: "effectiveFloatingLabel" }] : /* istanbul ignore next */ []));
61
46
  hostClasses = computed(() => ({
62
47
  'neu-number-input': true,
63
48
  'neu-number-input--vertical': this.vertical(),
@@ -66,8 +51,7 @@ class NeuNumberInputComponent {
66
51
  'neu-number-input--disabled': this._cvaDisabled(),
67
52
  'neu-number-input--sm': this.size() === 'sm',
68
53
  'neu-number-input--lg': this.size() === 'lg',
69
- }), /* @ts-ignore */
70
- ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
54
+ }), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
71
55
  _onChange = () => { };
72
56
  _onTouched = () => { };
73
57
  writeValue(val) {
@@ -107,8 +91,8 @@ class NeuNumberInputComponent {
107
91
  _clamp(v) {
108
92
  return Math.min(this.max(), Math.max(this.min(), v));
109
93
  }
110
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NeuNumberInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
111
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: NeuNumberInputComponent, isStandalone: true, selector: "neu-number-input", inputs: { min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, floatingLabel: { classPropertyName: "floatingLabel", publicName: "floatingLabel", isSignal: true, isRequired: false, transformFunction: null }, decrementLabel: { classPropertyName: "decrementLabel", publicName: "decrementLabel", isSignal: true, isRequired: false, transformFunction: null }, incrementLabel: { classPropertyName: "incrementLabel", publicName: "incrementLabel", isSignal: true, isRequired: false, transformFunction: null }, vertical: { classPropertyName: "vertical", publicName: "vertical", isSignal: true, isRequired: false, transformFunction: null }, stacked: { classPropertyName: "stacked", publicName: "stacked", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, host: { properties: { "class": "hostClasses()" } }, providers: [
94
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuNumberInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
95
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: NeuNumberInputComponent, isStandalone: true, selector: "neu-number-input", inputs: { min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, floatingLabel: { classPropertyName: "floatingLabel", publicName: "floatingLabel", isSignal: true, isRequired: false, transformFunction: null }, decrementLabel: { classPropertyName: "decrementLabel", publicName: "decrementLabel", isSignal: true, isRequired: false, transformFunction: null }, incrementLabel: { classPropertyName: "incrementLabel", publicName: "incrementLabel", isSignal: true, isRequired: false, transformFunction: null }, vertical: { classPropertyName: "vertical", publicName: "vertical", isSignal: true, isRequired: false, transformFunction: null }, stacked: { classPropertyName: "stacked", publicName: "stacked", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, host: { properties: { "class": "hostClasses()" } }, providers: [
112
96
  {
113
97
  provide: NG_VALUE_ACCESSOR,
114
98
  useExisting: forwardRef(() => NeuNumberInputComponent),
@@ -239,7 +223,7 @@ class NeuNumberInputComponent {
239
223
  </div>
240
224
  `, isInline: true, styles: ["@charset \"UTF-8\";.neu-number-input{display:inline-flex;flex-direction:column;align-items:flex-start;gap:6px}.neu-number-input--disabled{opacity:.5;pointer-events:none}.neu-number-input--vertical .neu-number-input__control{flex-direction:column;gap:0;align-items:stretch;border:1px solid var(--neu-border);border-radius:var(--neu-radius-md, 8px);overflow:hidden;width:var(--neu-number-input-width, 80px)}.neu-number-input--vertical .neu-number-input__field{width:100%;border:none;border-top:1px solid var(--neu-border);border-bottom:1px solid var(--neu-border);border-radius:0}.neu-number-input--vertical .neu-number-input__control>.neu-number-input__btn{width:100%;border:none;border-radius:0}.neu-number-input--stacked .neu-number-input__control{align-items:stretch;gap:0}.neu-number-input--stacked .neu-number-input__field{flex:1 1 auto;width:auto;min-width:var(--neu-number-input-stacked-min-width, 120px);border-radius:var(--neu-radius-md, 8px) 0 0 var(--neu-radius-md, 8px);border-right:none;text-align:left;padding:0 10px}.neu-number-input--horizontal .neu-number-input__floating-label{left:calc(var(--neu-number-input-btn-size, 48px) + 12px);max-width:calc(100% - var(--neu-number-input-btn-size, 48px) * 2 - 28px)}.neu-number-input--sm{--neu-number-input-height: 36px;--neu-number-input-btn-size: 36px}.neu-number-input--sm .neu-number-input__field{font-size:var(--neu-text-sm)}.neu-number-input--lg{--neu-number-input-height: 56px;--neu-number-input-btn-size: 56px}.neu-number-input__label{font-size:var(--neu-text-sm, .875rem);font-weight:500;color:var(--neu-text);line-height:1.4;cursor:pointer}.neu-number-input__control{position:relative;display:inline-flex;align-items:center;gap:4px}.neu-number-input__field{width:var(--neu-number-input-width, 80px);height:var(--neu-number-input-height, 48px);padding:0 8px;border:1px solid var(--neu-border);border-radius:var(--neu-radius-md, 8px);background:var(--neu-surface);color:var(--neu-text);font-size:.9375rem;font-variant-numeric:tabular-nums;text-align:center;outline:none;transition:border-color .15s;-moz-appearance:textfield}.neu-number-input__field::-webkit-inner-spin-button,.neu-number-input__field::-webkit-outer-spin-button{display:none}.neu-number-input__field:focus{border-color:var(--neu-primary);box-shadow:var(--neu-focus-ring)}.neu-number-input__floating-label{position:absolute;left:6px;top:50%;z-index:1;transform:translateY(-50%);max-width:calc(100% - var(--neu-number-input-btn-size, 26px) - 18px);padding:0 4px;overflow:hidden;color:var(--neu-text-muted);font-size:var(--neu-text-base, 1rem);line-height:1.2;pointer-events:none;text-overflow:ellipsis;transition:top var(--neu-transition),color var(--neu-transition),font-size var(--neu-transition),transform var(--neu-transition),background var(--neu-transition);white-space:nowrap}.neu-number-input__control--focused .neu-number-input__floating-label,.neu-number-input__control--has-value .neu-number-input__floating-label{top:0;transform:translateY(-50%);background:var(--neu-surface);color:var(--neu-text-muted);font-size:12px;font-weight:600}.neu-number-input__control--focused .neu-number-input__floating-label{color:var(--neu-primary)}.neu-number-input__stack{display:flex;flex-direction:column;border:1px solid var(--neu-border);border-radius:0 var(--neu-radius-md, 8px) var(--neu-radius-md, 8px) 0;overflow:hidden;flex-shrink:0}.neu-number-input__stack .neu-number-input__btn{all:unset;box-sizing:border-box;cursor:pointer;display:flex;align-items:center;justify-content:center;flex:1;width:var(--neu-number-input-btn-size, 26px);border:none;border-radius:0;background:var(--neu-surface);color:var(--neu-text-muted);font-size:.625rem;font-weight:700;line-height:1;transition:background .1s,color .1s}.neu-number-input__stack .neu-number-input__btn:not(:disabled):hover{background:var(--neu-surface-2);color:var(--neu-text)}.neu-number-input__stack .neu-number-input__btn:focus-visible{outline:2px solid var(--neu-primary);outline-offset:-1px}.neu-number-input__stack .neu-number-input__btn:disabled{opacity:.4;cursor:not-allowed}.neu-number-input__stack .neu-number-input__btn--inc{border-bottom:1px solid var(--neu-border)}.neu-number-input__control>.neu-number-input__btn{all:unset;box-sizing:border-box;cursor:pointer;display:flex;align-items:center;justify-content:center;width:var(--neu-number-input-btn-size, 48px);height:var(--neu-number-input-btn-size, 48px);border:1px solid var(--neu-border);border-radius:var(--neu-radius-md, 8px);background:var(--neu-surface);color:var(--neu-text-muted);font-size:.6875rem;line-height:1;transition:background .12s,color .12s,border-color .12s}.neu-number-input__control>.neu-number-input__btn:not(:disabled):hover{background:var(--neu-surface-2);color:var(--neu-text);border-color:var(--neu-primary)}.neu-number-input__control>.neu-number-input__btn:focus-visible{outline:2px solid var(--neu-primary);outline-offset:1px}.neu-number-input__control>.neu-number-input__btn:disabled{opacity:.4;cursor:not-allowed}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
241
225
  }
242
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NeuNumberInputComponent, decorators: [{
226
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuNumberInputComponent, decorators: [{
243
227
  type: Component,
244
228
  args: [{ selector: 'neu-number-input', imports: [], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: { '[class]': 'hostClasses()' }, providers: [
245
229
  {