@neural-ui/core 1.3.2 → 1.4.0

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 (51) hide show
  1. package/README.md +12 -6
  2. package/fesm2022/neural-ui-core-accordion.mjs +8 -6
  3. package/fesm2022/neural-ui-core-accordion.mjs.map +1 -1
  4. package/fesm2022/neural-ui-core-autocomplete.mjs +121 -29
  5. package/fesm2022/neural-ui-core-autocomplete.mjs.map +1 -1
  6. package/fesm2022/neural-ui-core-badge.mjs +2 -2
  7. package/fesm2022/neural-ui-core-badge.mjs.map +1 -1
  8. package/fesm2022/neural-ui-core-button.mjs +2 -2
  9. package/fesm2022/neural-ui-core-button.mjs.map +1 -1
  10. package/fesm2022/neural-ui-core-chip.mjs +2 -2
  11. package/fesm2022/neural-ui-core-chip.mjs.map +1 -1
  12. package/fesm2022/neural-ui-core-color-picker.mjs +3 -9
  13. package/fesm2022/neural-ui-core-color-picker.mjs.map +1 -1
  14. package/fesm2022/neural-ui-core-filter-bar.mjs +2 -2
  15. package/fesm2022/neural-ui-core-filter-bar.mjs.map +1 -1
  16. package/fesm2022/neural-ui-core-modal.mjs +81 -31
  17. package/fesm2022/neural-ui-core-modal.mjs.map +1 -1
  18. package/fesm2022/neural-ui-core-multiselect.mjs +258 -99
  19. package/fesm2022/neural-ui-core-multiselect.mjs.map +1 -1
  20. package/fesm2022/neural-ui-core-nav.mjs +4 -6
  21. package/fesm2022/neural-ui-core-nav.mjs.map +1 -1
  22. package/fesm2022/neural-ui-core-select.mjs +247 -94
  23. package/fesm2022/neural-ui-core-select.mjs.map +1 -1
  24. package/fesm2022/neural-ui-core-sidebar.mjs +3 -2
  25. package/fesm2022/neural-ui-core-sidebar.mjs.map +1 -1
  26. package/fesm2022/neural-ui-core-slider.mjs +2 -2
  27. package/fesm2022/neural-ui-core-slider.mjs.map +1 -1
  28. package/fesm2022/neural-ui-core-split-button.mjs +2 -2
  29. package/fesm2022/neural-ui-core-split-button.mjs.map +1 -1
  30. package/fesm2022/neural-ui-core-table.mjs +168 -21
  31. package/fesm2022/neural-ui-core-table.mjs.map +1 -1
  32. package/fesm2022/neural-ui-core-tabs.mjs +11 -4
  33. package/fesm2022/neural-ui-core-tabs.mjs.map +1 -1
  34. package/fesm2022/neural-ui-core-toolbar.mjs +2 -2
  35. package/fesm2022/neural-ui-core-toolbar.mjs.map +1 -1
  36. package/fesm2022/neural-ui-core-url-state.mjs +90 -10
  37. package/fesm2022/neural-ui-core-url-state.mjs.map +1 -1
  38. package/fesm2022/neural-ui-core-virtual-list.mjs +52 -22
  39. package/fesm2022/neural-ui-core-virtual-list.mjs.map +1 -1
  40. package/package.json +1 -1
  41. package/styles/_tokens.scss +8 -8
  42. package/types/neural-ui-core-autocomplete.d.ts +10 -1
  43. package/types/neural-ui-core-color-picker.d.ts +0 -1
  44. package/types/neural-ui-core-modal.d.ts +22 -16
  45. package/types/neural-ui-core-multiselect.d.ts +12 -1
  46. package/types/neural-ui-core-select.d.ts +12 -1
  47. package/types/neural-ui-core-sidebar.d.ts +1 -0
  48. package/types/neural-ui-core-table.d.ts +23 -3
  49. package/types/neural-ui-core-tabs.d.ts +1 -0
  50. package/types/neural-ui-core-url-state.d.ts +9 -0
  51. package/types/neural-ui-core-virtual-list.d.ts +17 -1
@@ -1,27 +1,8 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, Injectable, input, output, ChangeDetectionStrategy, ViewEncapsulation, Component } from '@angular/core';
3
- import { Dialog } from '@angular/cdk/dialog';
4
- import * as i1 from '@angular/cdk/a11y';
5
- import { A11yModule } from '@angular/cdk/a11y';
2
+ import { input, output, viewChild, effect, ChangeDetectionStrategy, ViewEncapsulation, Component, inject, Injectable } from '@angular/core';
6
3
  import { NeuIconComponent } from '@neural-ui/core/icon';
4
+ import { Dialog } from '@angular/cdk/dialog';
7
5
 
8
- class NeuDialogService {
9
- dialog = inject(Dialog);
10
- open(component, config) {
11
- return this.dialog.open(component, {
12
- data: { title: config?.title, data: config?.data },
13
- panelClass: ['neu-dialog-panel', `neu-dialog-panel--${config?.size ?? 'md'}`],
14
- backdropClass: 'neu-dialog-backdrop',
15
- disableClose: config?.disableClose ?? false,
16
- });
17
- }
18
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuDialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
19
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuDialogService, providedIn: 'root' });
20
- }
21
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuDialogService, decorators: [{
22
- type: Injectable,
23
- args: [{ providedIn: 'root' }]
24
- }] });
25
6
  /**
26
7
  * NeuDialogComponent — Diálogo accesible con header, body y footer. / Accessible dialog with header, body and footer.
27
8
  * Úsalo directamente como componente declarativo pasando `open` como signal. / Use it directly as a declarative component passing `open` as a signal.
@@ -47,10 +28,61 @@ class NeuDialogComponent {
47
28
  disableClose = input(false, ...(ngDevMode ? [{ debugName: "disableClose" }] : /* istanbul ignore next */ []));
48
29
  /** Emite cuando el usuario cierra el diálogo. / Emits when the user closes the dialog. */
49
30
  closed = output();
31
+ panelRef = viewChild('panel', ...(ngDevMode ? [{ debugName: "panelRef" }] : /* istanbul ignore next */ []));
50
32
  /** @internal — ID único para aria-labelledby / Unique ID for aria-labelledby */
51
33
  _uid = Math.random().toString(36).slice(2, 7);
34
+ constructor() {
35
+ effect(() => {
36
+ if (!this.open())
37
+ return;
38
+ queueMicrotask(() => this.focusInitialElement());
39
+ });
40
+ }
41
+ onPanelKeydown(event) {
42
+ if (event.key === 'Escape') {
43
+ if (!this.disableClose()) {
44
+ this.closed.emit();
45
+ }
46
+ return;
47
+ }
48
+ if (event.key !== 'Tab')
49
+ return;
50
+ const panel = this.panelRef()?.nativeElement;
51
+ if (!panel)
52
+ return;
53
+ const focusable = this.getFocusableElements(panel);
54
+ if (!focusable.length) {
55
+ event.preventDefault();
56
+ panel.focus();
57
+ return;
58
+ }
59
+ const first = focusable[0];
60
+ const last = focusable[focusable.length - 1];
61
+ const activeElement = document.activeElement;
62
+ if (event.shiftKey) {
63
+ if (activeElement === first || activeElement === panel) {
64
+ event.preventDefault();
65
+ last.focus();
66
+ }
67
+ return;
68
+ }
69
+ if (activeElement === last) {
70
+ event.preventDefault();
71
+ first.focus();
72
+ }
73
+ }
74
+ focusInitialElement() {
75
+ const panel = this.panelRef()?.nativeElement;
76
+ if (!panel)
77
+ return;
78
+ const [firstFocusable] = this.getFocusableElements(panel);
79
+ (firstFocusable ?? panel).focus();
80
+ }
81
+ getFocusableElements(panel) {
82
+ return Array.from(panel.querySelectorAll('button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])')).filter((element) => !element.hasAttribute('aria-hidden'));
83
+ }
52
84
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
53
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: NeuDialogComponent, isStandalone: true, selector: "neu-dialog", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disableClose: { classPropertyName: "disableClose", publicName: "disableClose", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, host: { properties: { "class.neu-dialog--open": "open()", "attr.aria-hidden": "!open()" } }, ngImport: i0, template: `
85
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: NeuDialogComponent, isStandalone: true, selector: "neu-dialog", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disableClose: { classPropertyName: "disableClose", publicName: "disableClose", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, host: { properties: { "class.neu-dialog--open": "open()", "attr.aria-hidden": "!open()" } }, viewQueries: [{ propertyName: "panelRef", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: `
54
86
  @if (open()) {
55
87
  <!-- Backdrop -->
56
88
  <div
@@ -61,14 +93,14 @@ class NeuDialogComponent {
61
93
 
62
94
  <!-- Panel -->
63
95
  <div
64
- cdkTrapFocus
65
- [cdkTrapFocusAutoCapture]="true"
96
+ #panel
66
97
  class="neu-dialog__panel neu-dialog__panel--{{ size() }}"
67
98
  role="dialog"
99
+ tabindex="-1"
68
100
  [id]="'neu-dialog-' + _uid"
69
101
  [attr.aria-labelledby]="'neu-dialog-title-' + _uid"
70
102
  [attr.aria-modal]="true"
71
- (keydown.escape)="!disableClose() && closed.emit()"
103
+ (keydown)="onPanelKeydown($event)"
72
104
  >
73
105
  <!-- Header -->
74
106
  <div class="neu-dialog__header">
@@ -94,11 +126,11 @@ class NeuDialogComponent {
94
126
  <ng-content select="[neu-dialog-footer]" />
95
127
  </div>
96
128
  }
97
- `, isInline: true, styles: [".neu-dialog-backdrop{position:fixed;inset:0;background:var(--neu-overlay-bg);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:calc(var(--neu-z-modal, 200) - 1);animation:neu-backdrop-in .15s ease both}@keyframes neu-backdrop-in{0%{opacity:0}to{opacity:1}}.neu-dialog-panel{background:var(--neu-surface);border-radius:var(--neu-radius-lg, 16px);box-shadow:var(--neu-shadow-lg);border:1px solid var(--neu-border);outline:none;display:flex;flex-direction:column;max-height:90dvh;overflow:hidden;animation:neu-dialog-in .2s cubic-bezier(.22,1,.36,1) both}.neu-dialog-panel--sm{width:min(100% - 2rem,400px)}.neu-dialog-panel--md{width:min(100% - 2rem,560px)}.neu-dialog-panel--lg{width:min(100% - 2rem,720px)}.neu-dialog-panel--xl{width:min(100% - 2rem,900px)}.neu-dialog-panel--full{width:min(100% - 2rem,1120px)}@keyframes neu-dialog-in{0%{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}neu-dialog{display:contents}.neu-dialog__backdrop{position:fixed;inset:0;background:var(--neu-overlay-bg);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:calc(var(--neu-z-modal, 200) - 1);animation:neu-backdrop-in .15s ease both}.neu-dialog__panel{position:fixed;inset:0;margin:auto;background:var(--neu-surface);border-radius:var(--neu-radius-lg, 16px);box-shadow:var(--neu-shadow-lg);border:1px solid var(--neu-border);display:flex;flex-direction:column;z-index:var(--neu-z-modal, 200);max-height:90dvh;overflow:hidden;animation:neu-dialog-in .2s cubic-bezier(.22,1,.36,1) both;height:fit-content}.neu-dialog__panel--sm{width:min(100% - 2rem,400px)}.neu-dialog__panel--md{width:min(100% - 2rem,560px)}.neu-dialog__panel--lg{width:min(100% - 2rem,720px)}.neu-dialog__panel--xl{width:min(100% - 2rem,900px)}.neu-dialog__panel--full{width:min(100% - 2rem,1120px)}.neu-dialog__header{display:flex;align-items:center;justify-content:space-between;padding:var(--neu-space-4, 1rem) var(--neu-space-5, 1.25rem);border-bottom:1px solid var(--neu-border);gap:var(--neu-space-3, .75rem);flex-shrink:0}.neu-dialog__title{margin:0;font-size:var(--neu-text-lg, 1.125rem);font-weight:600;color:var(--neu-text);line-height:1.3}.neu-dialog__close{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:1px solid var(--neu-border);border-radius:var(--neu-radius);background:transparent;color:var(--neu-text-muted);cursor:pointer;transition:all var(--neu-transition);flex-shrink:0;padding:0}.neu-dialog__close:hover{background:var(--neu-surface-2);color:var(--neu-text);border-color:var(--neu-border-hover)}.neu-dialog__body{padding:var(--neu-space-5, 1.25rem);overflow-y:auto;flex:1;overscroll-behavior:contain;color:var(--neu-text);font-size:var(--neu-text-sm, .875rem);line-height:1.6}[neu-dialog-footer]{display:flex;align-items:center;justify-content:flex-end;gap:var(--neu-space-3, .75rem);padding:var(--neu-space-4, 1rem) var(--neu-space-5, 1.25rem);border-top:1px solid var(--neu-border);flex-shrink:0}\n"], dependencies: [{ kind: "component", type: NeuIconComponent, selector: "neu-icon", inputs: ["name", "strokeWidth", "size"] }, { kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i1.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
129
+ `, isInline: true, styles: [".neu-dialog-backdrop{position:fixed;inset:0;background:var(--neu-overlay-bg);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:calc(var(--neu-z-modal, 200) - 1);animation:neu-backdrop-in .15s ease both}@keyframes neu-backdrop-in{0%{opacity:0}to{opacity:1}}.neu-dialog-panel{background:var(--neu-surface);border-radius:var(--neu-radius-lg, 16px);box-shadow:var(--neu-shadow-lg);border:1px solid var(--neu-border);outline:none;display:flex;flex-direction:column;max-height:90dvh;overflow:hidden;animation:neu-dialog-in .2s cubic-bezier(.22,1,.36,1) both}.neu-dialog-panel--sm{width:min(100% - 2rem,400px)}.neu-dialog-panel--md{width:min(100% - 2rem,560px)}.neu-dialog-panel--lg{width:min(100% - 2rem,720px)}.neu-dialog-panel--xl{width:min(100% - 2rem,900px)}.neu-dialog-panel--full{width:min(100% - 2rem,1120px)}@keyframes neu-dialog-in{0%{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}neu-dialog{display:contents}.neu-dialog__backdrop{position:fixed;inset:0;background:var(--neu-overlay-bg);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:calc(var(--neu-z-modal, 200) - 1);animation:neu-backdrop-in .15s ease both}.neu-dialog__panel{position:fixed;inset:0;margin:auto;background:var(--neu-surface);border-radius:var(--neu-radius-lg, 16px);box-shadow:var(--neu-shadow-lg);border:1px solid var(--neu-border);display:flex;flex-direction:column;z-index:var(--neu-z-modal, 200);max-height:90dvh;overflow:hidden;animation:neu-dialog-in .2s cubic-bezier(.22,1,.36,1) both;height:fit-content}.neu-dialog__panel--sm{width:min(100% - 2rem,400px)}.neu-dialog__panel--md{width:min(100% - 2rem,560px)}.neu-dialog__panel--lg{width:min(100% - 2rem,720px)}.neu-dialog__panel--xl{width:min(100% - 2rem,900px)}.neu-dialog__panel--full{width:min(100% - 2rem,1120px)}.neu-dialog__header{display:flex;align-items:center;justify-content:space-between;padding:var(--neu-space-4, 1rem) var(--neu-space-5, 1.25rem);border-bottom:1px solid var(--neu-border);gap:var(--neu-space-3, .75rem);flex-shrink:0}.neu-dialog__title{margin:0;font-size:var(--neu-text-lg, 1.125rem);font-weight:600;color:var(--neu-text);line-height:1.3}.neu-dialog__close{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:1px solid var(--neu-border);border-radius:var(--neu-radius);background:transparent;color:var(--neu-text-muted);cursor:pointer;transition:all var(--neu-transition);flex-shrink:0;padding:0}.neu-dialog__close:hover{background:var(--neu-surface-2);color:var(--neu-text);border-color:var(--neu-border-hover)}.neu-dialog__body{padding:var(--neu-space-5, 1.25rem);overflow-y:auto;flex:1;overscroll-behavior:contain;color:var(--neu-text);font-size:var(--neu-text-sm, .875rem);line-height:1.6}[neu-dialog-footer]{display:flex;align-items:center;justify-content:flex-end;gap:var(--neu-space-3, .75rem);padding:var(--neu-space-4, 1rem) var(--neu-space-5, 1.25rem);border-top:1px solid var(--neu-border);flex-shrink:0}\n"], dependencies: [{ kind: "component", type: NeuIconComponent, selector: "neu-icon", inputs: ["name", "strokeWidth", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
98
130
  }
99
131
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuDialogComponent, decorators: [{
100
132
  type: Component,
101
- args: [{ selector: 'neu-dialog', imports: [NeuIconComponent, A11yModule], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: {
133
+ args: [{ selector: 'neu-dialog', imports: [NeuIconComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: {
102
134
  '[class.neu-dialog--open]': 'open()',
103
135
  '[attr.aria-hidden]': '!open()',
104
136
  }, template: `
@@ -112,14 +144,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
112
144
 
113
145
  <!-- Panel -->
114
146
  <div
115
- cdkTrapFocus
116
- [cdkTrapFocusAutoCapture]="true"
147
+ #panel
117
148
  class="neu-dialog__panel neu-dialog__panel--{{ size() }}"
118
149
  role="dialog"
150
+ tabindex="-1"
119
151
  [id]="'neu-dialog-' + _uid"
120
152
  [attr.aria-labelledby]="'neu-dialog-title-' + _uid"
121
153
  [attr.aria-modal]="true"
122
- (keydown.escape)="!disableClose() && closed.emit()"
154
+ (keydown)="onPanelKeydown($event)"
123
155
  >
124
156
  <!-- Header -->
125
157
  <div class="neu-dialog__header">
@@ -146,7 +178,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
146
178
  </div>
147
179
  }
148
180
  `, styles: [".neu-dialog-backdrop{position:fixed;inset:0;background:var(--neu-overlay-bg);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:calc(var(--neu-z-modal, 200) - 1);animation:neu-backdrop-in .15s ease both}@keyframes neu-backdrop-in{0%{opacity:0}to{opacity:1}}.neu-dialog-panel{background:var(--neu-surface);border-radius:var(--neu-radius-lg, 16px);box-shadow:var(--neu-shadow-lg);border:1px solid var(--neu-border);outline:none;display:flex;flex-direction:column;max-height:90dvh;overflow:hidden;animation:neu-dialog-in .2s cubic-bezier(.22,1,.36,1) both}.neu-dialog-panel--sm{width:min(100% - 2rem,400px)}.neu-dialog-panel--md{width:min(100% - 2rem,560px)}.neu-dialog-panel--lg{width:min(100% - 2rem,720px)}.neu-dialog-panel--xl{width:min(100% - 2rem,900px)}.neu-dialog-panel--full{width:min(100% - 2rem,1120px)}@keyframes neu-dialog-in{0%{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}neu-dialog{display:contents}.neu-dialog__backdrop{position:fixed;inset:0;background:var(--neu-overlay-bg);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:calc(var(--neu-z-modal, 200) - 1);animation:neu-backdrop-in .15s ease both}.neu-dialog__panel{position:fixed;inset:0;margin:auto;background:var(--neu-surface);border-radius:var(--neu-radius-lg, 16px);box-shadow:var(--neu-shadow-lg);border:1px solid var(--neu-border);display:flex;flex-direction:column;z-index:var(--neu-z-modal, 200);max-height:90dvh;overflow:hidden;animation:neu-dialog-in .2s cubic-bezier(.22,1,.36,1) both;height:fit-content}.neu-dialog__panel--sm{width:min(100% - 2rem,400px)}.neu-dialog__panel--md{width:min(100% - 2rem,560px)}.neu-dialog__panel--lg{width:min(100% - 2rem,720px)}.neu-dialog__panel--xl{width:min(100% - 2rem,900px)}.neu-dialog__panel--full{width:min(100% - 2rem,1120px)}.neu-dialog__header{display:flex;align-items:center;justify-content:space-between;padding:var(--neu-space-4, 1rem) var(--neu-space-5, 1.25rem);border-bottom:1px solid var(--neu-border);gap:var(--neu-space-3, .75rem);flex-shrink:0}.neu-dialog__title{margin:0;font-size:var(--neu-text-lg, 1.125rem);font-weight:600;color:var(--neu-text);line-height:1.3}.neu-dialog__close{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:1px solid var(--neu-border);border-radius:var(--neu-radius);background:transparent;color:var(--neu-text-muted);cursor:pointer;transition:all var(--neu-transition);flex-shrink:0;padding:0}.neu-dialog__close:hover{background:var(--neu-surface-2);color:var(--neu-text);border-color:var(--neu-border-hover)}.neu-dialog__body{padding:var(--neu-space-5, 1.25rem);overflow-y:auto;flex:1;overscroll-behavior:contain;color:var(--neu-text);font-size:var(--neu-text-sm, .875rem);line-height:1.6}[neu-dialog-footer]{display:flex;align-items:center;justify-content:flex-end;gap:var(--neu-space-3, .75rem);padding:var(--neu-space-4, 1rem) var(--neu-space-5, 1.25rem);border-top:1px solid var(--neu-border);flex-shrink:0}\n"] }]
149
- }], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disableClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableClose", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
181
+ }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disableClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableClose", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }] } });
182
+
183
+ class NeuDialogService {
184
+ dialog = inject(Dialog);
185
+ open(component, config) {
186
+ return this.dialog.open(component, {
187
+ data: { title: config?.title, data: config?.data },
188
+ panelClass: ['neu-dialog-panel', `neu-dialog-panel--${config?.size ?? 'md'}`],
189
+ backdropClass: 'neu-dialog-backdrop',
190
+ disableClose: config?.disableClose ?? false,
191
+ });
192
+ }
193
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuDialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
194
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuDialogService, providedIn: 'root' });
195
+ }
196
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuDialogService, decorators: [{
197
+ type: Injectable,
198
+ args: [{ providedIn: 'root' }]
199
+ }] });
150
200
 
151
201
  /**
152
202
  * Generated bundle index. Do not edit.
@@ -1 +1 @@
1
- {"version":3,"file":"neural-ui-core-modal.mjs","sources":["../../../../projects/ui-core/modal/neu-modal.component.ts","../../../../projects/ui-core/modal/neural-ui-core-modal.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n Type,\n ViewEncapsulation,\n inject,\n input,\n output,\n} from '@angular/core';\nimport { Dialog, DialogConfig, DialogRef } from '@angular/cdk/dialog';\nimport { A11yModule } from '@angular/cdk/a11y';\nimport { NeuIconComponent } from '@neural-ui/core/icon';\n\nexport type NeuDialogSize = 'sm' | 'md' | 'lg' | 'xl' | 'full';\n\n/** Datos que se inyectan en el componente del diálogo / Data injected into the dialog component */\nexport interface NeuDialogData<T = unknown> {\n title?: string;\n data?: T;\n}\n\n/**\n * NeuDialogService — Servicio para abrir diálogos programáticamente. / Service to open dialogs programmatically.\n *\n * Uso:\n * const dialog = inject(NeuDialogService);\n * const ref = dialog.open(MyContentComponent, { title: 'Editar', data: item });\n * ref.closed.subscribe(result => console.log(result));\n */\nimport { Injectable } from '@angular/core';\n\n@Injectable({ providedIn: 'root' })\nexport class NeuDialogService {\n private readonly dialog = inject(Dialog);\n\n open<T = unknown, R = unknown>(\n component: Type<unknown>,\n config?: {\n title?: string;\n data?: T;\n size?: NeuDialogSize;\n disableClose?: boolean;\n },\n ): DialogRef<R> {\n return this.dialog.open<R>(component, {\n data: { title: config?.title, data: config?.data } satisfies NeuDialogData<T>,\n panelClass: ['neu-dialog-panel', `neu-dialog-panel--${config?.size ?? 'md'}`],\n backdropClass: 'neu-dialog-backdrop',\n disableClose: config?.disableClose ?? false,\n } satisfies DialogConfig);\n }\n}\n\n/**\n * NeuDialogComponent — Diálogo accesible con header, body y footer. / Accessible dialog with header, body and footer.\n * Úsalo directamente como componente declarativo pasando `open` como signal. / Use it directly as a declarative component passing `open` as a signal.\n *\n * Para uso programático, utiliza NeuDialogService.open().\n *\n * Uso declarativo:\n * <neu-dialog [open]=\"isOpen()\" title=\"Editar usuario\" (closed)=\"isOpen.set(false)\">\n * <p>Contenido del diálogo</p>\n * <div neu-dialog-footer>\n * <neu-button (click)=\"save()\">Guardar</neu-button>\n * </div>\n * </neu-dialog>\n */\n@Component({\n selector: 'neu-dialog',\n imports: [NeuIconComponent, A11yModule],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class.neu-dialog--open]': 'open()',\n '[attr.aria-hidden]': '!open()',\n },\n template: `\n @if (open()) {\n <!-- Backdrop -->\n <div\n class=\"neu-dialog__backdrop\"\n (click)=\"!disableClose() && closed.emit()\"\n aria-hidden=\"true\"\n ></div>\n\n <!-- Panel -->\n <div\n cdkTrapFocus\n [cdkTrapFocusAutoCapture]=\"true\"\n class=\"neu-dialog__panel neu-dialog__panel--{{ size() }}\"\n role=\"dialog\"\n [id]=\"'neu-dialog-' + _uid\"\n [attr.aria-labelledby]=\"'neu-dialog-title-' + _uid\"\n [attr.aria-modal]=\"true\"\n (keydown.escape)=\"!disableClose() && closed.emit()\"\n >\n <!-- Header -->\n <div class=\"neu-dialog__header\">\n <h2 class=\"neu-dialog__title\" [id]=\"'neu-dialog-title-' + _uid\">{{ title() }}</h2>\n @if (!disableClose()) {\n <button\n class=\"neu-dialog__close\"\n type=\"button\"\n aria-label=\"Close dialog\"\n (click)=\"closed.emit()\"\n >\n <neu-icon name=\"lucideX\" size=\"1.125rem\" />\n </button>\n }\n </div>\n\n <!-- Body -->\n <div class=\"neu-dialog__body\">\n <ng-content />\n </div>\n\n <!-- Footer (opcional via slot) -->\n <ng-content select=\"[neu-dialog-footer]\" />\n </div>\n }\n `,\n styleUrl: './neu-modal.component.scss',\n})\nexport class NeuDialogComponent {\n /** Controla la visibilidad del diálogo. / Controls dialog visibility. */\n open = input<boolean>(false);\n /** Título que aparece en el header. / Title shown in the header. */\n title = input<string>('');\n /** Tamaño del panel: sm | md | lg | xl | full. / Panel size: sm | md | lg | xl | full. */\n size = input<NeuDialogSize>('md');\n /** Si es true, el backdrop y el botón cerrar no funcionan. / If true, the backdrop and close button do not work. */\n disableClose = input<boolean>(false);\n\n /** Emite cuando el usuario cierra el diálogo. / Emits when the user closes the dialog. */\n closed = output<void>();\n\n /** @internal — ID único para aria-labelledby / Unique ID for aria-labelledby */\n readonly _uid = Math.random().toString(36).slice(2, 7);\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-modal.mjs","sources":["../../../../projects/ui-core/modal/neu-modal.component.ts","../../../../projects/ui-core/modal/neu-dialog.service.ts","../../../../projects/ui-core/modal/neural-ui-core-modal.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n ViewEncapsulation,\n effect,\n input,\n output,\n viewChild,\n} from '@angular/core';\nimport { NeuIconComponent } from '@neural-ui/core/icon';\n\nexport type NeuDialogSize = 'sm' | 'md' | 'lg' | 'xl' | 'full';\n\n/**\n * NeuDialogComponent — Diálogo accesible con header, body y footer. / Accessible dialog with header, body and footer.\n * Úsalo directamente como componente declarativo pasando `open` como signal. / Use it directly as a declarative component passing `open` as a signal.\n *\n * Para uso programático, utiliza NeuDialogService.open().\n *\n * Uso declarativo:\n * <neu-dialog [open]=\"isOpen()\" title=\"Editar usuario\" (closed)=\"isOpen.set(false)\">\n * <p>Contenido del diálogo</p>\n * <div neu-dialog-footer>\n * <neu-button (click)=\"save()\">Guardar</neu-button>\n * </div>\n * </neu-dialog>\n */\n@Component({\n selector: 'neu-dialog',\n imports: [NeuIconComponent],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class.neu-dialog--open]': 'open()',\n '[attr.aria-hidden]': '!open()',\n },\n template: `\n @if (open()) {\n <!-- Backdrop -->\n <div\n class=\"neu-dialog__backdrop\"\n (click)=\"!disableClose() && closed.emit()\"\n aria-hidden=\"true\"\n ></div>\n\n <!-- Panel -->\n <div\n #panel\n class=\"neu-dialog__panel neu-dialog__panel--{{ size() }}\"\n role=\"dialog\"\n tabindex=\"-1\"\n [id]=\"'neu-dialog-' + _uid\"\n [attr.aria-labelledby]=\"'neu-dialog-title-' + _uid\"\n [attr.aria-modal]=\"true\"\n (keydown)=\"onPanelKeydown($event)\"\n >\n <!-- Header -->\n <div class=\"neu-dialog__header\">\n <h2 class=\"neu-dialog__title\" [id]=\"'neu-dialog-title-' + _uid\">{{ title() }}</h2>\n @if (!disableClose()) {\n <button\n class=\"neu-dialog__close\"\n type=\"button\"\n aria-label=\"Close dialog\"\n (click)=\"closed.emit()\"\n >\n <neu-icon name=\"lucideX\" size=\"1.125rem\" />\n </button>\n }\n </div>\n\n <!-- Body -->\n <div class=\"neu-dialog__body\">\n <ng-content />\n </div>\n\n <!-- Footer (opcional via slot) -->\n <ng-content select=\"[neu-dialog-footer]\" />\n </div>\n }\n `,\n styleUrl: './neu-modal.component.scss',\n})\nexport class NeuDialogComponent {\n /** Controla la visibilidad del diálogo. / Controls dialog visibility. */\n open = input<boolean>(false);\n /** Título que aparece en el header. / Title shown in the header. */\n title = input<string>('');\n /** Tamaño del panel: sm | md | lg | xl | full. / Panel size: sm | md | lg | xl | full. */\n size = input<NeuDialogSize>('md');\n /** Si es true, el backdrop y el botón cerrar no funcionan. / If true, the backdrop and close button do not work. */\n disableClose = input<boolean>(false);\n\n /** Emite cuando el usuario cierra el diálogo. / Emits when the user closes the dialog. */\n closed = output<void>();\n\n private readonly panelRef = viewChild<ElementRef<HTMLElement>>('panel');\n\n /** @internal — ID único para aria-labelledby / Unique ID for aria-labelledby */\n readonly _uid = Math.random().toString(36).slice(2, 7);\n\n constructor() {\n effect(() => {\n if (!this.open()) return;\n\n queueMicrotask(() => this.focusInitialElement());\n });\n }\n\n onPanelKeydown(event: KeyboardEvent): void {\n if (event.key === 'Escape') {\n if (!this.disableClose()) {\n this.closed.emit();\n }\n return;\n }\n\n if (event.key !== 'Tab') return;\n\n const panel = this.panelRef()?.nativeElement;\n if (!panel) return;\n\n const focusable = this.getFocusableElements(panel);\n if (!focusable.length) {\n event.preventDefault();\n panel.focus();\n return;\n }\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const activeElement = document.activeElement as HTMLElement | null;\n\n if (event.shiftKey) {\n if (activeElement === first || activeElement === panel) {\n event.preventDefault();\n last.focus();\n }\n return;\n }\n\n if (activeElement === last) {\n event.preventDefault();\n first.focus();\n }\n }\n\n private focusInitialElement(): void {\n const panel = this.panelRef()?.nativeElement;\n if (!panel) return;\n\n const [firstFocusable] = this.getFocusableElements(panel);\n (firstFocusable ?? panel).focus();\n }\n\n private getFocusableElements(panel: HTMLElement): HTMLElement[] {\n return Array.from(\n panel.querySelectorAll<HTMLElement>(\n 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])',\n ),\n ).filter((element) => !element.hasAttribute('aria-hidden'));\n }\n}\n","import { Injectable, Type, inject } from '@angular/core';\nimport { Dialog, DialogConfig, DialogRef } from '@angular/cdk/dialog';\nimport { NeuDialogSize } from './neu-modal.component';\n\n/** Datos que se inyectan en el componente del diálogo / Data injected into the dialog component */\nexport interface NeuDialogData<T = unknown> {\n title?: string;\n data?: T;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class NeuDialogService {\n private readonly dialog = inject(Dialog);\n\n open<T = unknown, R = unknown>(\n component: Type<unknown>,\n config?: {\n title?: string;\n data?: T;\n size?: NeuDialogSize;\n disableClose?: boolean;\n },\n ): DialogRef<R> {\n return this.dialog.open<R>(component, {\n data: { title: config?.title, data: config?.data } satisfies NeuDialogData<T>,\n panelClass: ['neu-dialog-panel', `neu-dialog-panel--${config?.size ?? 'md'}`],\n backdropClass: 'neu-dialog-backdrop',\n disableClose: config?.disableClose ?? false,\n } satisfies DialogConfig);\n }\n}","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}