@neural-ui/core 1.8.1 → 1.8.3

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.
@@ -24,6 +24,8 @@ class NeuDialogComponent {
24
24
  title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
25
25
  /** Tamaño del panel: sm | md | lg | xl | full. / Panel size: sm | md | lg | xl | full. */
26
26
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
27
+ /** Ajusta la altura al contenido o al viewport disponible. / Fits height to content or to the available viewport. */
28
+ layout = input('auto', ...(ngDevMode ? [{ debugName: "layout" }] : /* istanbul ignore next */ []));
27
29
  /** Si es true, el backdrop y el botón cerrar no funcionan. / If true, the backdrop and close button do not work. */
28
30
  disableClose = input(false, ...(ngDevMode ? [{ debugName: "disableClose" }] : /* istanbul ignore next */ []));
29
31
  /** Adapta el panel a mobile/full-width cuando el viewport es estrecho. */
@@ -103,7 +105,7 @@ class NeuDialogComponent {
103
105
  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'));
104
106
  }
105
107
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
106
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", 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 }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null }, restoreFocus: { classPropertyName: "restoreFocus", publicName: "restoreFocus", 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: `
108
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", 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 }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null }, disableClose: { classPropertyName: "disableClose", publicName: "disableClose", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null }, restoreFocus: { classPropertyName: "restoreFocus", publicName: "restoreFocus", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, host: { properties: { "class.neu-dialog--open": "open()", "class.neu-dialog--responsive": "responsive()", "class.neu-dialog--layout-auto": "layout() === \"auto\"", "class.neu-dialog--layout-viewport": "layout() === \"viewport\"", "attr.aria-hidden": "!open()" } }, viewQueries: [{ propertyName: "panelRef", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: `
107
109
  @if (open()) {
108
110
  <!-- Backdrop -->
109
111
  <div
@@ -112,48 +114,55 @@ class NeuDialogComponent {
112
114
  aria-hidden="true"
113
115
  ></div>
114
116
 
115
- <!-- Panel -->
116
- <div
117
- #panel
118
- class="neu-dialog__panel neu-dialog__panel--{{ size() }}"
119
- [class.neu-dialog__panel--responsive]="responsive()"
120
- role="dialog"
121
- tabindex="-1"
122
- [id]="'neu-dialog-' + _uid"
123
- [attr.aria-labelledby]="'neu-dialog-title-' + _uid"
124
- [attr.aria-modal]="true"
125
- (keydown)="onPanelKeydown($event)"
126
- >
127
- <!-- Header -->
128
- <div class="neu-dialog__header">
129
- <h2 class="neu-dialog__title" [id]="'neu-dialog-title-' + _uid">{{ title() }}</h2>
130
- @if (!disableClose()) {
131
- <button
132
- class="neu-dialog__close"
133
- type="button"
134
- aria-label="Close dialog"
135
- (click)="close()"
136
- >
137
- <neu-icon name="lucideX" size="1.125rem" />
138
- </button>
139
- }
140
- </div>
117
+ <div class="neu-dialog__viewport">
118
+ <!-- Panel -->
119
+ <div
120
+ #panel
121
+ class="neu-dialog__panel neu-dialog__panel--{{ size() }}"
122
+ [class.neu-dialog__panel--responsive]="responsive()"
123
+ [class.neu-dialog__panel--layout-auto]="layout() === 'auto'"
124
+ [class.neu-dialog__panel--layout-viewport]="layout() === 'viewport'"
125
+ role="dialog"
126
+ tabindex="-1"
127
+ [id]="'neu-dialog-' + _uid"
128
+ [attr.aria-labelledby]="'neu-dialog-title-' + _uid"
129
+ [attr.aria-modal]="true"
130
+ (keydown)="onPanelKeydown($event)"
131
+ >
132
+ <!-- Header -->
133
+ <div class="neu-dialog__header">
134
+ <h2 class="neu-dialog__title" [id]="'neu-dialog-title-' + _uid">{{ title() }}</h2>
135
+ @if (!disableClose()) {
136
+ <button
137
+ class="neu-dialog__close"
138
+ type="button"
139
+ aria-label="Close dialog"
140
+ (click)="close()"
141
+ >
142
+ <neu-icon name="lucideX" size="1.125rem" />
143
+ </button>
144
+ }
145
+ </div>
141
146
 
142
- <!-- Body -->
143
- <div class="neu-dialog__body">
144
- <ng-content />
145
- </div>
147
+ <!-- Body -->
148
+ <div class="neu-dialog__body">
149
+ <ng-content />
150
+ </div>
146
151
 
147
- <!-- Footer (opcional via slot) -->
148
- <ng-content select="[neu-dialog-footer]" />
152
+ <!-- Footer (opcional via slot) -->
153
+ <ng-content select="[neu-dialog-footer]" />
154
+ </div>
149
155
  </div>
150
156
  }
151
- `, 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)}@media(max-width:640px){.neu-dialog__panel--responsive{width:calc(100vw - 24px);max-width:calc(100vw - 24px);max-height:calc(100vh - 24px);margin:12px}}.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", "decorative", "ariaLabel", "strokeWidth", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
157
+ `, 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;width:min(100vw - 2rem,var(--neu-dialog-width-md, 560px));height:var(--neu-dialog-height, auto);max-height:var(--neu-dialog-max-height, 90vh);margin:var(--neu-dialog-margin, auto);overflow:hidden;animation:neu-dialog-in .2s cubic-bezier(.22,1,.36,1) both}.neu-dialog-panel--sm{width:min(100vw - 2rem,var(--neu-dialog-width-sm, 400px))}.neu-dialog-panel--md{width:min(100vw - 2rem,var(--neu-dialog-width-md, 560px))}.neu-dialog-panel--lg{width:min(100vw - 2rem,var(--neu-dialog-width-lg, 720px))}.neu-dialog-panel--xl{width:min(100vw - 2rem,var(--neu-dialog-width-xl, 900px))}.neu-dialog-panel--full{width:min(100vw - 2rem,var(--neu-dialog-width-full, 1120px))}:where(.neu-dialog-panel--layout-viewport){--neu-dialog-height: 90vh;--neu-dialog-body-flex: 1 1 auto}@keyframes neu-dialog-in{0%{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}neu-dialog{display:contents}:where(neu-dialog.neu-dialog--layout-viewport){--neu-dialog-height: 90vh;--neu-dialog-body-flex: 1 1 auto}@supports (height: 100dvh){:where(neu-dialog),:where(.neu-dialog-panel){--neu-dialog-max-height: 90dvh}:where(neu-dialog.neu-dialog--layout-viewport),:where(.neu-dialog-panel--layout-viewport){--neu-dialog-height: 90dvh}}.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__viewport{position:fixed;inset:var(--neu-dialog-inset, 0);z-index:var(--neu-z-modal, 200);display:flex;align-items:center;justify-content:center;pointer-events:none;min-width:0;min-height:0}.neu-dialog__panel{position:relative;margin:var(--neu-dialog-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;height:var(--neu-dialog-height, auto);max-height:var(--neu-dialog-max-height, 90vh);max-width:100%;overflow:hidden;pointer-events:auto;animation:neu-dialog-in .2s cubic-bezier(.22,1,.36,1) both}.neu-dialog__panel--sm{width:min(100%,var(--neu-dialog-width-sm, 400px))}.neu-dialog__panel--md{width:min(100%,var(--neu-dialog-width-md, 560px))}.neu-dialog__panel--lg{width:min(100%,var(--neu-dialog-width-lg, 720px))}.neu-dialog__panel--xl{width:min(100%,var(--neu-dialog-width-xl, 900px))}.neu-dialog__panel--full{width:min(100%,var(--neu-dialog-width-full, 1120px))}@media(max-width:640px){:where(.neu-dialog-panel--responsive){width:min(100vw - max(24px,env(safe-area-inset-left)) - max(24px,env(safe-area-inset-right)),var(--neu-dialog-width-full, 1120px));max-width:none;--neu-dialog-max-height: calc(100vh - max(24px, env(safe-area-inset-top)) - max(24px, env(safe-area-inset-bottom))) }:where(.neu-dialog-panel--responsive.neu-dialog-panel--layout-viewport){--neu-dialog-height: calc(100vh - max(24px, env(safe-area-inset-top)) - max(24px, env(safe-area-inset-bottom))) }:where(neu-dialog.neu-dialog--responsive){--neu-dialog-inset: max(12px, env(safe-area-inset-top)) max(12px, env(safe-area-inset-right)) max(12px, env(safe-area-inset-bottom)) max(12px, env(safe-area-inset-left));--neu-dialog-margin: auto}:where(neu-dialog.neu-dialog--responsive.neu-dialog--layout-viewport){--neu-dialog-height: calc(100vh - max(12px, env(safe-area-inset-top)) - max(12px, env(safe-area-inset-bottom))) ;--neu-dialog-max-height: calc(100vh - max(12px, env(safe-area-inset-top)) - max(12px, env(safe-area-inset-bottom))) }@supports (height: 100dvh){:where(.neu-dialog-panel--responsive){--neu-dialog-max-height: calc(100dvh - max(24px, env(safe-area-inset-top)) - max(24px, env(safe-area-inset-bottom))) }:where(.neu-dialog-panel--responsive.neu-dialog-panel--layout-viewport){--neu-dialog-height: calc(100dvh - max(24px, env(safe-area-inset-top)) - max(24px, env(safe-area-inset-bottom))) }:where(neu-dialog.neu-dialog--responsive.neu-dialog--layout-viewport){--neu-dialog-height: calc(100dvh - max(12px, env(safe-area-inset-top)) - max(12px, env(safe-area-inset-bottom))) ;--neu-dialog-max-height: calc(100dvh - max(12px, env(safe-area-inset-top)) - max(12px, env(safe-area-inset-bottom))) }}}.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:44px;height:44px;min-width:44px;min-height:44px;flex:none;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{min-height:0;max-height:var(--neu-dialog-body-max-height, none);padding:var(--neu-dialog-body-padding, var(--neu-space-5, 1.25rem));overflow-y:auto;flex:var(--neu-dialog-body-flex, 0 1 auto);-webkit-overflow-scrolling:touch;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);flex-wrap:var(--neu-dialog-footer-wrap, nowrap);padding:var(--neu-dialog-footer-padding, var(--neu-space-4, 1rem) var(--neu-space-5, 1.25rem));border-top:1px solid var(--neu-border);flex-shrink:0}[neu-dialog-footer] :where(button,[role=button]){min-height:44px}\n"], dependencies: [{ kind: "component", type: NeuIconComponent, selector: "neu-icon", inputs: ["name", "decorative", "ariaLabel", "strokeWidth", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
152
158
  }
153
159
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuDialogComponent, decorators: [{
154
160
  type: Component,
155
161
  args: [{ selector: 'neu-dialog', imports: [NeuIconComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: {
156
162
  '[class.neu-dialog--open]': 'open()',
163
+ '[class.neu-dialog--responsive]': 'responsive()',
164
+ '[class.neu-dialog--layout-auto]': 'layout() === "auto"',
165
+ '[class.neu-dialog--layout-viewport]': 'layout() === "viewport"',
157
166
  '[attr.aria-hidden]': '!open()',
158
167
  }, template: `
159
168
  @if (open()) {
@@ -164,52 +173,62 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
164
173
  aria-hidden="true"
165
174
  ></div>
166
175
 
167
- <!-- Panel -->
168
- <div
169
- #panel
170
- class="neu-dialog__panel neu-dialog__panel--{{ size() }}"
171
- [class.neu-dialog__panel--responsive]="responsive()"
172
- role="dialog"
173
- tabindex="-1"
174
- [id]="'neu-dialog-' + _uid"
175
- [attr.aria-labelledby]="'neu-dialog-title-' + _uid"
176
- [attr.aria-modal]="true"
177
- (keydown)="onPanelKeydown($event)"
178
- >
179
- <!-- Header -->
180
- <div class="neu-dialog__header">
181
- <h2 class="neu-dialog__title" [id]="'neu-dialog-title-' + _uid">{{ title() }}</h2>
182
- @if (!disableClose()) {
183
- <button
184
- class="neu-dialog__close"
185
- type="button"
186
- aria-label="Close dialog"
187
- (click)="close()"
188
- >
189
- <neu-icon name="lucideX" size="1.125rem" />
190
- </button>
191
- }
192
- </div>
176
+ <div class="neu-dialog__viewport">
177
+ <!-- Panel -->
178
+ <div
179
+ #panel
180
+ class="neu-dialog__panel neu-dialog__panel--{{ size() }}"
181
+ [class.neu-dialog__panel--responsive]="responsive()"
182
+ [class.neu-dialog__panel--layout-auto]="layout() === 'auto'"
183
+ [class.neu-dialog__panel--layout-viewport]="layout() === 'viewport'"
184
+ role="dialog"
185
+ tabindex="-1"
186
+ [id]="'neu-dialog-' + _uid"
187
+ [attr.aria-labelledby]="'neu-dialog-title-' + _uid"
188
+ [attr.aria-modal]="true"
189
+ (keydown)="onPanelKeydown($event)"
190
+ >
191
+ <!-- Header -->
192
+ <div class="neu-dialog__header">
193
+ <h2 class="neu-dialog__title" [id]="'neu-dialog-title-' + _uid">{{ title() }}</h2>
194
+ @if (!disableClose()) {
195
+ <button
196
+ class="neu-dialog__close"
197
+ type="button"
198
+ aria-label="Close dialog"
199
+ (click)="close()"
200
+ >
201
+ <neu-icon name="lucideX" size="1.125rem" />
202
+ </button>
203
+ }
204
+ </div>
193
205
 
194
- <!-- Body -->
195
- <div class="neu-dialog__body">
196
- <ng-content />
197
- </div>
206
+ <!-- Body -->
207
+ <div class="neu-dialog__body">
208
+ <ng-content />
209
+ </div>
198
210
 
199
- <!-- Footer (opcional via slot) -->
200
- <ng-content select="[neu-dialog-footer]" />
211
+ <!-- Footer (opcional via slot) -->
212
+ <ng-content select="[neu-dialog-footer]" />
213
+ </div>
201
214
  </div>
202
215
  }
203
- `, 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)}@media(max-width:640px){.neu-dialog__panel--responsive{width:calc(100vw - 24px);max-width:calc(100vw - 24px);max-height:calc(100vh - 24px);margin:12px}}.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"] }]
204
- }], 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 }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }], restoreFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "restoreFocus", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }] } });
216
+ `, 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;width:min(100vw - 2rem,var(--neu-dialog-width-md, 560px));height:var(--neu-dialog-height, auto);max-height:var(--neu-dialog-max-height, 90vh);margin:var(--neu-dialog-margin, auto);overflow:hidden;animation:neu-dialog-in .2s cubic-bezier(.22,1,.36,1) both}.neu-dialog-panel--sm{width:min(100vw - 2rem,var(--neu-dialog-width-sm, 400px))}.neu-dialog-panel--md{width:min(100vw - 2rem,var(--neu-dialog-width-md, 560px))}.neu-dialog-panel--lg{width:min(100vw - 2rem,var(--neu-dialog-width-lg, 720px))}.neu-dialog-panel--xl{width:min(100vw - 2rem,var(--neu-dialog-width-xl, 900px))}.neu-dialog-panel--full{width:min(100vw - 2rem,var(--neu-dialog-width-full, 1120px))}:where(.neu-dialog-panel--layout-viewport){--neu-dialog-height: 90vh;--neu-dialog-body-flex: 1 1 auto}@keyframes neu-dialog-in{0%{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}neu-dialog{display:contents}:where(neu-dialog.neu-dialog--layout-viewport){--neu-dialog-height: 90vh;--neu-dialog-body-flex: 1 1 auto}@supports (height: 100dvh){:where(neu-dialog),:where(.neu-dialog-panel){--neu-dialog-max-height: 90dvh}:where(neu-dialog.neu-dialog--layout-viewport),:where(.neu-dialog-panel--layout-viewport){--neu-dialog-height: 90dvh}}.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__viewport{position:fixed;inset:var(--neu-dialog-inset, 0);z-index:var(--neu-z-modal, 200);display:flex;align-items:center;justify-content:center;pointer-events:none;min-width:0;min-height:0}.neu-dialog__panel{position:relative;margin:var(--neu-dialog-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;height:var(--neu-dialog-height, auto);max-height:var(--neu-dialog-max-height, 90vh);max-width:100%;overflow:hidden;pointer-events:auto;animation:neu-dialog-in .2s cubic-bezier(.22,1,.36,1) both}.neu-dialog__panel--sm{width:min(100%,var(--neu-dialog-width-sm, 400px))}.neu-dialog__panel--md{width:min(100%,var(--neu-dialog-width-md, 560px))}.neu-dialog__panel--lg{width:min(100%,var(--neu-dialog-width-lg, 720px))}.neu-dialog__panel--xl{width:min(100%,var(--neu-dialog-width-xl, 900px))}.neu-dialog__panel--full{width:min(100%,var(--neu-dialog-width-full, 1120px))}@media(max-width:640px){:where(.neu-dialog-panel--responsive){width:min(100vw - max(24px,env(safe-area-inset-left)) - max(24px,env(safe-area-inset-right)),var(--neu-dialog-width-full, 1120px));max-width:none;--neu-dialog-max-height: calc(100vh - max(24px, env(safe-area-inset-top)) - max(24px, env(safe-area-inset-bottom))) }:where(.neu-dialog-panel--responsive.neu-dialog-panel--layout-viewport){--neu-dialog-height: calc(100vh - max(24px, env(safe-area-inset-top)) - max(24px, env(safe-area-inset-bottom))) }:where(neu-dialog.neu-dialog--responsive){--neu-dialog-inset: max(12px, env(safe-area-inset-top)) max(12px, env(safe-area-inset-right)) max(12px, env(safe-area-inset-bottom)) max(12px, env(safe-area-inset-left));--neu-dialog-margin: auto}:where(neu-dialog.neu-dialog--responsive.neu-dialog--layout-viewport){--neu-dialog-height: calc(100vh - max(12px, env(safe-area-inset-top)) - max(12px, env(safe-area-inset-bottom))) ;--neu-dialog-max-height: calc(100vh - max(12px, env(safe-area-inset-top)) - max(12px, env(safe-area-inset-bottom))) }@supports (height: 100dvh){:where(.neu-dialog-panel--responsive){--neu-dialog-max-height: calc(100dvh - max(24px, env(safe-area-inset-top)) - max(24px, env(safe-area-inset-bottom))) }:where(.neu-dialog-panel--responsive.neu-dialog-panel--layout-viewport){--neu-dialog-height: calc(100dvh - max(24px, env(safe-area-inset-top)) - max(24px, env(safe-area-inset-bottom))) }:where(neu-dialog.neu-dialog--responsive.neu-dialog--layout-viewport){--neu-dialog-height: calc(100dvh - max(12px, env(safe-area-inset-top)) - max(12px, env(safe-area-inset-bottom))) ;--neu-dialog-max-height: calc(100dvh - max(12px, env(safe-area-inset-top)) - max(12px, env(safe-area-inset-bottom))) }}}.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:44px;height:44px;min-width:44px;min-height:44px;flex:none;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{min-height:0;max-height:var(--neu-dialog-body-max-height, none);padding:var(--neu-dialog-body-padding, var(--neu-space-5, 1.25rem));overflow-y:auto;flex:var(--neu-dialog-body-flex, 0 1 auto);-webkit-overflow-scrolling:touch;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);flex-wrap:var(--neu-dialog-footer-wrap, nowrap);padding:var(--neu-dialog-footer-padding, var(--neu-space-4, 1rem) var(--neu-space-5, 1.25rem));border-top:1px solid var(--neu-border);flex-shrink:0}[neu-dialog-footer] :where(button,[role=button]){min-height:44px}\n"] }]
217
+ }], 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 }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], disableClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableClose", required: false }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }], restoreFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "restoreFocus", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }] } });
205
218
 
206
219
  class NeuDialogService {
207
220
  dialog = inject(Dialog);
208
221
  open(component, config) {
209
222
  return this.dialog.open(component, {
210
223
  data: { title: config?.title, data: config?.data },
211
- panelClass: ['neu-dialog-panel', `neu-dialog-panel--${config?.size ?? 'md'}`],
224
+ panelClass: [
225
+ 'neu-dialog-panel',
226
+ `neu-dialog-panel--${config?.size ?? 'md'}`,
227
+ `neu-dialog-panel--layout-${config?.layout ?? 'auto'}`,
228
+ ...(config?.responsive ?? true ? ['neu-dialog-panel--responsive'] : []),
229
+ ],
212
230
  backdropClass: 'neu-dialog-backdrop',
231
+ maxWidth: 'none',
213
232
  disableClose: config?.disableClose ?? false,
214
233
  restoreFocus: config?.restoreFocus ?? true,
215
234
  });
@@ -1 +1 @@
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() && close()\"\n aria-hidden=\"true\"\n ></div>\n\n <!-- Panel -->\n <div\n #panel\n class=\"neu-dialog__panel neu-dialog__panel--{{ size() }}\"\n [class.neu-dialog__panel--responsive]=\"responsive()\"\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)=\"close()\"\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 /** Adapta el panel a mobile/full-width cuando el viewport es estrecho. */\n responsive = input<boolean>(true);\n /** Devuelve el foco al elemento activo antes de abrir. */\n restoreFocus = input<boolean>(true);\n\n /** Emite cuando el usuario cierra el diálogo. / Emits when the user closes the dialog. */\n closed = output<unknown>();\n\n private readonly panelRef = viewChild<ElementRef<HTMLElement>>('panel');\n private previousActiveElement: HTMLElement | null = null;\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()) {\n this.restorePreviousFocus();\n return;\n }\n\n this.previousActiveElement = document.activeElement as HTMLElement | null;\n queueMicrotask(() => this.focusInitialElement());\n });\n }\n\n close(result?: unknown): void {\n this.closed.emit(result);\n }\n\n onPanelKeydown(event: KeyboardEvent): void {\n if (event.key === 'Escape') {\n if (!this.disableClose()) {\n this.close();\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 restorePreviousFocus(): void {\n if (!this.restoreFocus() || !this.previousActiveElement?.focus) {\n this.previousActiveElement = null;\n return;\n }\n\n queueMicrotask(() => {\n this.previousActiveElement?.focus();\n this.previousActiveElement = null;\n });\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 restoreFocus?: 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 restoreFocus: config?.restoreFocus ?? true,\n } satisfies DialogConfig);\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-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';\nexport type NeuDialogLayout = 'auto' | 'viewport';\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 '[class.neu-dialog--responsive]': 'responsive()',\n '[class.neu-dialog--layout-auto]': 'layout() === \"auto\"',\n '[class.neu-dialog--layout-viewport]': 'layout() === \"viewport\"',\n '[attr.aria-hidden]': '!open()',\n },\n template: `\n @if (open()) {\n <!-- Backdrop -->\n <div\n class=\"neu-dialog__backdrop\"\n (click)=\"!disableClose() && close()\"\n aria-hidden=\"true\"\n ></div>\n\n <div class=\"neu-dialog__viewport\">\n <!-- Panel -->\n <div\n #panel\n class=\"neu-dialog__panel neu-dialog__panel--{{ size() }}\"\n [class.neu-dialog__panel--responsive]=\"responsive()\"\n [class.neu-dialog__panel--layout-auto]=\"layout() === 'auto'\"\n [class.neu-dialog__panel--layout-viewport]=\"layout() === 'viewport'\"\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)=\"close()\"\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 </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 /** Ajusta la altura al contenido o al viewport disponible. / Fits height to content or to the available viewport. */\n layout = input<NeuDialogLayout>('auto');\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 /** Adapta el panel a mobile/full-width cuando el viewport es estrecho. */\n responsive = input<boolean>(true);\n /** Devuelve el foco al elemento activo antes de abrir. */\n restoreFocus = input<boolean>(true);\n\n /** Emite cuando el usuario cierra el diálogo. / Emits when the user closes the dialog. */\n closed = output<unknown>();\n\n private readonly panelRef = viewChild<ElementRef<HTMLElement>>('panel');\n private previousActiveElement: HTMLElement | null = null;\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()) {\n this.restorePreviousFocus();\n return;\n }\n\n this.previousActiveElement = document.activeElement as HTMLElement | null;\n queueMicrotask(() => this.focusInitialElement());\n });\n }\n\n close(result?: unknown): void {\n this.closed.emit(result);\n }\n\n onPanelKeydown(event: KeyboardEvent): void {\n if (event.key === 'Escape') {\n if (!this.disableClose()) {\n this.close();\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 restorePreviousFocus(): void {\n if (!this.restoreFocus() || !this.previousActiveElement?.focus) {\n this.previousActiveElement = null;\n return;\n }\n\n queueMicrotask(() => {\n this.previousActiveElement?.focus();\n this.previousActiveElement = null;\n });\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 { NeuDialogLayout, 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 layout?: NeuDialogLayout;\n responsive?: boolean;\n disableClose?: boolean;\n restoreFocus?: 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: [\n 'neu-dialog-panel',\n `neu-dialog-panel--${config?.size ?? 'md'}`,\n `neu-dialog-panel--layout-${config?.layout ?? 'auto'}`,\n ...(config?.responsive ?? true ? ['neu-dialog-panel--responsive'] : []),\n ],\n backdropClass: 'neu-dialog-backdrop',\n maxWidth: 'none',\n disableClose: config?.disableClose ?? false,\n restoreFocus: config?.restoreFocus ?? true,\n } satisfies DialogConfig);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neural-ui/core",
3
- "version": "1.8.1",
3
+ "version": "1.8.3",
4
4
  "description": "Modern Angular UI component library built with signals, standalone components, and OnPush change detection.",
5
5
  "author": "PedroMorenoTrujillo",
6
6
  "keywords": [
@@ -124,6 +124,22 @@
124
124
  --neu-sidebar-width: 260px;
125
125
  --neu-sidebar-bg: var(--neu-surface);
126
126
 
127
+ // Dialog — layout configurable without piercing component encapsulation
128
+ --neu-dialog-height: auto;
129
+ --neu-dialog-max-height: 90vh;
130
+ --neu-dialog-inset: 0;
131
+ --neu-dialog-margin: auto;
132
+ --neu-dialog-body-flex: 0 1 auto;
133
+ --neu-dialog-body-max-height: none;
134
+ --neu-dialog-body-padding: var(--neu-space-5);
135
+ --neu-dialog-footer-padding: var(--neu-space-4) var(--neu-space-5);
136
+ --neu-dialog-footer-wrap: nowrap;
137
+ --neu-dialog-width-sm: 400px;
138
+ --neu-dialog-width-md: 560px;
139
+ --neu-dialog-width-lg: 720px;
140
+ --neu-dialog-width-xl: 900px;
141
+ --neu-dialog-width-full: 1120px;
142
+
127
143
  // ------------------------------------------------
128
144
  // Z-index
129
145
  // ------------------------------------------------
@@ -3,6 +3,7 @@ import { Type } from '@angular/core';
3
3
  import { DialogRef } from '@angular/cdk/dialog';
4
4
 
5
5
  type NeuDialogSize = 'sm' | 'md' | 'lg' | 'xl' | 'full';
6
+ type NeuDialogLayout = 'auto' | 'viewport';
6
7
  /**
7
8
  * NeuDialogComponent — Diálogo accesible con header, body y footer. / Accessible dialog with header, body and footer.
8
9
  * Úsalo directamente como componente declarativo pasando `open` como signal. / Use it directly as a declarative component passing `open` as a signal.
@@ -24,6 +25,8 @@ declare class NeuDialogComponent {
24
25
  title: _angular_core.InputSignal<string>;
25
26
  /** Tamaño del panel: sm | md | lg | xl | full. / Panel size: sm | md | lg | xl | full. */
26
27
  size: _angular_core.InputSignal<NeuDialogSize>;
28
+ /** Ajusta la altura al contenido o al viewport disponible. / Fits height to content or to the available viewport. */
29
+ layout: _angular_core.InputSignal<NeuDialogLayout>;
27
30
  /** Si es true, el backdrop y el botón cerrar no funcionan. / If true, the backdrop and close button do not work. */
28
31
  disableClose: _angular_core.InputSignal<boolean>;
29
32
  /** Adapta el panel a mobile/full-width cuando el viewport es estrecho. */
@@ -43,7 +46,7 @@ declare class NeuDialogComponent {
43
46
  private restorePreviousFocus;
44
47
  private getFocusableElements;
45
48
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<NeuDialogComponent, never>;
46
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<NeuDialogComponent, "neu-dialog", never, { "open": { "alias": "open"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "disableClose": { "alias": "disableClose"; "required": false; "isSignal": true; }; "responsive": { "alias": "responsive"; "required": false; "isSignal": true; }; "restoreFocus": { "alias": "restoreFocus"; "required": false; "isSignal": true; }; }, { "closed": "closed"; }, never, ["*", "[neu-dialog-footer]"], true, never>;
49
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NeuDialogComponent, "neu-dialog", never, { "open": { "alias": "open"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "layout": { "alias": "layout"; "required": false; "isSignal": true; }; "disableClose": { "alias": "disableClose"; "required": false; "isSignal": true; }; "responsive": { "alias": "responsive"; "required": false; "isSignal": true; }; "restoreFocus": { "alias": "restoreFocus"; "required": false; "isSignal": true; }; }, { "closed": "closed"; }, never, ["*", "[neu-dialog-footer]"], true, never>;
47
50
  }
48
51
 
49
52
  /** Datos que se inyectan en el componente del diálogo / Data injected into the dialog component */
@@ -57,6 +60,8 @@ declare class NeuDialogService {
57
60
  title?: string;
58
61
  data?: T;
59
62
  size?: NeuDialogSize;
63
+ layout?: NeuDialogLayout;
64
+ responsive?: boolean;
60
65
  disableClose?: boolean;
61
66
  restoreFocus?: boolean;
62
67
  }): DialogRef<R>;
@@ -65,4 +70,4 @@ declare class NeuDialogService {
65
70
  }
66
71
 
67
72
  export { NeuDialogComponent, NeuDialogService };
68
- export type { NeuDialogData, NeuDialogSize };
73
+ export type { NeuDialogData, NeuDialogLayout, NeuDialogSize };