@nucleus-suite-pe/core 2.0.0 → 2.2.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.
|
@@ -2,6 +2,7 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { InjectionToken, makeEnvironmentProviders, inject, Injector, signal, computed, Injectable, effect, DestroyRef, ElementRef, input, Directive, model, untracked, ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, TemplateRef, viewChild, output, afterNextRender, contentChildren } from '@angular/core';
|
|
3
3
|
import { HttpContextToken, HttpClient, HttpContext, HttpErrorResponse } from '@angular/common/http';
|
|
4
4
|
import { firstValueFrom, from, switchMap, catchError, throwError } from 'rxjs';
|
|
5
|
+
import { Router, RouterLink, NavigationEnd } from '@angular/router';
|
|
5
6
|
import { DOCUMENT, NgTemplateOutlet } from '@angular/common';
|
|
6
7
|
import * as i1 from '@angular/forms';
|
|
7
8
|
import { FormsModule } from '@angular/forms';
|
|
@@ -12,7 +13,6 @@ import Lara from '@primeuix/themes/lara';
|
|
|
12
13
|
import { providePrimeNG } from 'primeng/config';
|
|
13
14
|
import * as i1$1 from 'primeng/skeleton';
|
|
14
15
|
import { SkeletonModule } from 'primeng/skeleton';
|
|
15
|
-
import { RouterLink, Router } from '@angular/router';
|
|
16
16
|
import { ConfirmationService, MessageService } from 'primeng/api';
|
|
17
17
|
import * as i2$1 from 'primeng/inputtext';
|
|
18
18
|
import { InputTextModule } from 'primeng/inputtext';
|
|
@@ -24,23 +24,26 @@ import * as i5 from 'primeng/textarea';
|
|
|
24
24
|
import { TextareaModule } from 'primeng/textarea';
|
|
25
25
|
import * as i6 from 'primeng/toggleswitch';
|
|
26
26
|
import { ToggleSwitchModule } from 'primeng/toggleswitch';
|
|
27
|
+
import { CdkDrag, CdkDragHandle, CdkDropList } from '@angular/cdk/drag-drop';
|
|
27
28
|
import * as i1$2 from 'primeng/button';
|
|
28
29
|
import { ButtonModule } from 'primeng/button';
|
|
29
|
-
import * as
|
|
30
|
+
import * as i2$3 from 'primeng/paginator';
|
|
31
|
+
import { PaginatorModule } from 'primeng/paginator';
|
|
32
|
+
import * as i4 from 'primeng/table';
|
|
30
33
|
import { TableModule } from 'primeng/table';
|
|
31
|
-
import * as
|
|
34
|
+
import * as i5$1 from 'primeng/tag';
|
|
32
35
|
import { TagModule } from 'primeng/tag';
|
|
33
|
-
import * as
|
|
36
|
+
import * as i6$1 from 'primeng/tooltip';
|
|
34
37
|
import { TooltipModule } from 'primeng/tooltip';
|
|
35
38
|
import * as i1$3 from 'primeng/avatar';
|
|
36
39
|
import { AvatarModule } from 'primeng/avatar';
|
|
37
|
-
import * as i2$
|
|
40
|
+
import * as i2$4 from 'primeng/breadcrumb';
|
|
38
41
|
import { BreadcrumbModule } from 'primeng/breadcrumb';
|
|
39
42
|
import * as i4$1 from 'primeng/confirmdialog';
|
|
40
43
|
import { ConfirmDialogModule } from 'primeng/confirmdialog';
|
|
41
44
|
import * as i5$2 from 'primeng/toast';
|
|
42
45
|
import { ToastModule } from 'primeng/toast';
|
|
43
|
-
import * as i6$
|
|
46
|
+
import * as i6$2 from 'primeng/drawer';
|
|
44
47
|
import { DrawerModule } from 'primeng/drawer';
|
|
45
48
|
|
|
46
49
|
const NUCLEUS_CONFIG = new InjectionToken('NUCLEUS_CONFIG');
|
|
@@ -76,6 +79,29 @@ function trimSlash(value) {
|
|
|
76
79
|
return (value ?? '').trim().replace(/\/+$/, '');
|
|
77
80
|
}
|
|
78
81
|
|
|
82
|
+
const NUCLEUS_HOME = new InjectionToken('NUCLEUS_HOME', {
|
|
83
|
+
providedIn: 'root',
|
|
84
|
+
factory: () => '/',
|
|
85
|
+
});
|
|
86
|
+
function normalizeHomeRoute(route) {
|
|
87
|
+
const trimmed = (route ?? '').trim().replace(/\/+$/, '');
|
|
88
|
+
if (!trimmed)
|
|
89
|
+
return '/';
|
|
90
|
+
return trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
|
|
91
|
+
}
|
|
92
|
+
function provideNucleusHome(route) {
|
|
93
|
+
return makeEnvironmentProviders([
|
|
94
|
+
{ provide: NUCLEUS_HOME, useValue: normalizeHomeRoute(route) },
|
|
95
|
+
]);
|
|
96
|
+
}
|
|
97
|
+
function routePath(url) {
|
|
98
|
+
const path = (url ?? '').replace(/[?#].*$/, '').replace(/\/+$/, '');
|
|
99
|
+
return path.length ? path : '/';
|
|
100
|
+
}
|
|
101
|
+
function isHomeRoute(home, url) {
|
|
102
|
+
return routePath(url) === normalizeHomeRoute(home);
|
|
103
|
+
}
|
|
104
|
+
|
|
79
105
|
class NucleusAuth {
|
|
80
106
|
}
|
|
81
107
|
|
|
@@ -242,48 +268,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
242
268
|
args: [{ providedIn: 'root' }]
|
|
243
269
|
}] });
|
|
244
270
|
|
|
245
|
-
const COMMON_COPY = {
|
|
246
|
-
es: {
|
|
247
|
-
search: 'Buscar',
|
|
248
|
-
choose: 'Selecciona',
|
|
249
|
-
noIcon: 'Sin icono',
|
|
250
|
-
noColor: 'Sin color',
|
|
251
|
-
searchIcon: 'Busca un icono',
|
|
252
|
-
noMatches: 'Ningún icono coincide',
|
|
253
|
-
sessionExpired: 'Tu sesión expiró. Vuelve a iniciar sesión.',
|
|
254
|
-
errorNetwork: 'No se pudo conectar con el servidor. Revisa tu conexión o inténtalo en unos minutos.',
|
|
255
|
-
errorTimeout: 'El servidor tardó demasiado en responder. Inténtalo de nuevo.',
|
|
256
|
-
errorServer: 'Algo falló en el servidor y no pudimos completar la operación. Inténtalo de nuevo en unos ' +
|
|
257
|
-
'minutos; si sigue pasando, avísale al equipo.',
|
|
258
|
-
errorInvalid: 'Revisa los datos: hay algo que no es válido.',
|
|
259
|
-
errorForbidden: 'No tienes permiso para hacer esto.',
|
|
260
|
-
errorNotFound: 'No encontramos lo que buscabas. Puede que ya no exista.',
|
|
261
|
-
errorConflict: 'Ese cambio choca con algo que ya existe.',
|
|
262
|
-
errorUnknown: 'No se pudo completar la operación. Inténtalo de nuevo.',
|
|
263
|
-
},
|
|
264
|
-
en: {
|
|
265
|
-
search: 'Search',
|
|
266
|
-
choose: 'Select',
|
|
267
|
-
noIcon: 'No icon',
|
|
268
|
-
noColor: 'No colour',
|
|
269
|
-
searchIcon: 'Search an icon',
|
|
270
|
-
noMatches: 'No icon matches',
|
|
271
|
-
sessionExpired: 'Your session expired. Sign in again.',
|
|
272
|
-
errorNetwork: 'Could not reach the server. Check your connection or try again in a moment.',
|
|
273
|
-
errorTimeout: 'The server took too long to answer. Try again.',
|
|
274
|
-
errorServer: 'Something broke on the server and we could not finish. Try again in a few minutes; if it ' +
|
|
275
|
-
'keeps happening, tell the team.',
|
|
276
|
-
errorInvalid: 'Check the data: something is not valid.',
|
|
277
|
-
errorForbidden: 'You do not have permission to do this.',
|
|
278
|
-
errorNotFound: 'We could not find that. It may no longer exist.',
|
|
279
|
-
errorConflict: 'That change clashes with something that already exists.',
|
|
280
|
-
errorUnknown: 'We could not finish the operation. Try again.',
|
|
281
|
-
},
|
|
282
|
-
};
|
|
283
|
-
function commonCopyOf(lang) {
|
|
284
|
-
return lang === 'en' ? COMMON_COPY.en : COMMON_COPY.es;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
271
|
const NUCLEUS_LANGS = ['es', 'en'];
|
|
288
272
|
const STORAGE_KEY$3 = 'nucleus_lang';
|
|
289
273
|
function isLang(value) {
|
|
@@ -327,6 +311,101 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
327
311
|
args: [{ providedIn: 'root' }]
|
|
328
312
|
}], ctorParameters: () => [] });
|
|
329
313
|
|
|
314
|
+
const NO_PERMISSIONS = {
|
|
315
|
+
canView: false,
|
|
316
|
+
canInsert: false,
|
|
317
|
+
canEdit: false,
|
|
318
|
+
canDelete: false,
|
|
319
|
+
canExport: false,
|
|
320
|
+
};
|
|
321
|
+
function findMenuByRoute(nodes, route) {
|
|
322
|
+
for (const node of nodes) {
|
|
323
|
+
if (node.route && route.startsWith(node.route))
|
|
324
|
+
return node;
|
|
325
|
+
const child = findMenuByRoute(node.children, route);
|
|
326
|
+
if (child)
|
|
327
|
+
return child;
|
|
328
|
+
}
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
function isUnderRoute(url, route) {
|
|
332
|
+
return url === route || url.startsWith(`${route}/`);
|
|
333
|
+
}
|
|
334
|
+
function matchMenuByRoute(nodes, url) {
|
|
335
|
+
let best = null;
|
|
336
|
+
for (const node of nodes) {
|
|
337
|
+
if (node.route && isUnderRoute(url, node.route)) {
|
|
338
|
+
if (!best || node.route.length > (best.route ?? '').length)
|
|
339
|
+
best = node;
|
|
340
|
+
}
|
|
341
|
+
const child = matchMenuByRoute(node.children, url);
|
|
342
|
+
if (child && (!best || (child.route ?? '').length > (best.route ?? '').length))
|
|
343
|
+
best = child;
|
|
344
|
+
}
|
|
345
|
+
return best;
|
|
346
|
+
}
|
|
347
|
+
function permissionsOf(node) {
|
|
348
|
+
if (!node)
|
|
349
|
+
return NO_PERMISSIONS;
|
|
350
|
+
return {
|
|
351
|
+
canView: node.canView,
|
|
352
|
+
canInsert: node.canInsert,
|
|
353
|
+
canEdit: node.canEdit,
|
|
354
|
+
canDelete: node.canDelete,
|
|
355
|
+
canExport: node.canExport,
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
const COMMON_COPY = {
|
|
360
|
+
es: {
|
|
361
|
+
search: 'Buscar',
|
|
362
|
+
choose: 'Selecciona',
|
|
363
|
+
noIcon: 'Sin icono',
|
|
364
|
+
noColor: 'Sin color',
|
|
365
|
+
searchIcon: 'Busca un icono',
|
|
366
|
+
noMatches: 'Ningún icono coincide',
|
|
367
|
+
reorderHandle: 'Arrastra para cambiar el orden',
|
|
368
|
+
noResults: 'Ningún registro coincide con la búsqueda',
|
|
369
|
+
viewGrid: 'Vista en mosaico',
|
|
370
|
+
viewRows: 'Vista en filas',
|
|
371
|
+
sessionExpired: 'Tu sesión expiró. Vuelve a iniciar sesión.',
|
|
372
|
+
errorNetwork: 'No se pudo conectar con el servidor. Revisa tu conexión o inténtalo en unos minutos.',
|
|
373
|
+
errorTimeout: 'El servidor tardó demasiado en responder. Inténtalo de nuevo.',
|
|
374
|
+
errorServer: 'Algo falló en el servidor y no pudimos completar la operación. Inténtalo de nuevo en unos ' +
|
|
375
|
+
'minutos; si sigue pasando, avísale al equipo.',
|
|
376
|
+
errorInvalid: 'Revisa los datos: hay algo que no es válido.',
|
|
377
|
+
errorForbidden: 'No tienes permiso para hacer esto.',
|
|
378
|
+
errorNotFound: 'No encontramos lo que buscabas. Puede que ya no exista.',
|
|
379
|
+
errorConflict: 'Ese cambio choca con algo que ya existe.',
|
|
380
|
+
errorUnknown: 'No se pudo completar la operación. Inténtalo de nuevo.',
|
|
381
|
+
},
|
|
382
|
+
en: {
|
|
383
|
+
search: 'Search',
|
|
384
|
+
choose: 'Select',
|
|
385
|
+
noIcon: 'No icon',
|
|
386
|
+
noColor: 'No colour',
|
|
387
|
+
searchIcon: 'Search an icon',
|
|
388
|
+
noMatches: 'No icon matches',
|
|
389
|
+
reorderHandle: 'Drag to reorder',
|
|
390
|
+
noResults: 'No records match your search',
|
|
391
|
+
viewGrid: 'Tile view',
|
|
392
|
+
viewRows: 'Row view',
|
|
393
|
+
sessionExpired: 'Your session expired. Sign in again.',
|
|
394
|
+
errorNetwork: 'Could not reach the server. Check your connection or try again in a moment.',
|
|
395
|
+
errorTimeout: 'The server took too long to answer. Try again.',
|
|
396
|
+
errorServer: 'Something broke on the server and we could not finish. Try again in a few minutes; if it ' +
|
|
397
|
+
'keeps happening, tell the team.',
|
|
398
|
+
errorInvalid: 'Check the data: something is not valid.',
|
|
399
|
+
errorForbidden: 'You do not have permission to do this.',
|
|
400
|
+
errorNotFound: 'We could not find that. It may no longer exist.',
|
|
401
|
+
errorConflict: 'That change clashes with something that already exists.',
|
|
402
|
+
errorUnknown: 'We could not finish the operation. Try again.',
|
|
403
|
+
},
|
|
404
|
+
};
|
|
405
|
+
function commonCopyOf(lang) {
|
|
406
|
+
return lang === 'en' ? COMMON_COPY.en : COMMON_COPY.es;
|
|
407
|
+
}
|
|
408
|
+
|
|
330
409
|
const SPOKEN = [400, 402, 403, 404, 409, 422];
|
|
331
410
|
function problemOf(error) {
|
|
332
411
|
const body = error.error;
|
|
@@ -375,87 +454,6 @@ function nucleusErrorMessage(error, lang) {
|
|
|
375
454
|
return copy.errorUnknown;
|
|
376
455
|
}
|
|
377
456
|
|
|
378
|
-
const DEFAULT_TTL_MS = 30_000;
|
|
379
|
-
class NucleusCache {
|
|
380
|
-
entries = new Map();
|
|
381
|
-
inFlight = new Map();
|
|
382
|
-
read(key, loader, ttlMs = DEFAULT_TTL_MS) {
|
|
383
|
-
const entry = this.entries.get(key);
|
|
384
|
-
if (entry && Date.now() - entry.at < ttlMs) {
|
|
385
|
-
return Promise.resolve(entry.value);
|
|
386
|
-
}
|
|
387
|
-
return this.load(key, loader);
|
|
388
|
-
}
|
|
389
|
-
prefetch(key, loader, ttlMs = DEFAULT_TTL_MS) {
|
|
390
|
-
const entry = this.entries.get(key);
|
|
391
|
-
if (entry && Date.now() - entry.at < ttlMs)
|
|
392
|
-
return;
|
|
393
|
-
if (this.inFlight.has(key))
|
|
394
|
-
return;
|
|
395
|
-
void this.load(key, loader).catch(() => undefined);
|
|
396
|
-
}
|
|
397
|
-
invalidate(...prefixes) {
|
|
398
|
-
if (prefixes.length === 0) {
|
|
399
|
-
this.entries.clear();
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
for (const key of [...this.entries.keys()]) {
|
|
403
|
-
if (prefixes.some((prefix) => key.startsWith(prefix)))
|
|
404
|
-
this.entries.delete(key);
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
load(key, loader) {
|
|
408
|
-
const running = this.inFlight.get(key);
|
|
409
|
-
if (running)
|
|
410
|
-
return running;
|
|
411
|
-
const promise = loader()
|
|
412
|
-
.then((value) => {
|
|
413
|
-
this.entries.set(key, { at: Date.now(), value });
|
|
414
|
-
return value;
|
|
415
|
-
})
|
|
416
|
-
.finally(() => {
|
|
417
|
-
this.inFlight.delete(key);
|
|
418
|
-
});
|
|
419
|
-
this.inFlight.set(key, promise);
|
|
420
|
-
return promise;
|
|
421
|
-
}
|
|
422
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusCache, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
423
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusCache, providedIn: 'root' });
|
|
424
|
-
}
|
|
425
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusCache, decorators: [{
|
|
426
|
-
type: Injectable,
|
|
427
|
-
args: [{ providedIn: 'root' }]
|
|
428
|
-
}] });
|
|
429
|
-
|
|
430
|
-
const NO_PERMISSIONS = {
|
|
431
|
-
canView: false,
|
|
432
|
-
canInsert: false,
|
|
433
|
-
canEdit: false,
|
|
434
|
-
canDelete: false,
|
|
435
|
-
canExport: false,
|
|
436
|
-
};
|
|
437
|
-
function findMenuByRoute(nodes, route) {
|
|
438
|
-
for (const node of nodes) {
|
|
439
|
-
if (node.route && route.startsWith(node.route))
|
|
440
|
-
return node;
|
|
441
|
-
const child = findMenuByRoute(node.children, route);
|
|
442
|
-
if (child)
|
|
443
|
-
return child;
|
|
444
|
-
}
|
|
445
|
-
return null;
|
|
446
|
-
}
|
|
447
|
-
function permissionsOf(node) {
|
|
448
|
-
if (!node)
|
|
449
|
-
return NO_PERMISSIONS;
|
|
450
|
-
return {
|
|
451
|
-
canView: node.canView,
|
|
452
|
-
canInsert: node.canInsert,
|
|
453
|
-
canEdit: node.canEdit,
|
|
454
|
-
canDelete: node.canDelete,
|
|
455
|
-
canExport: node.canExport,
|
|
456
|
-
};
|
|
457
|
-
}
|
|
458
|
-
|
|
459
457
|
class SessionService {
|
|
460
458
|
http = inject(HttpClient);
|
|
461
459
|
auth = inject(NucleusAuth, { optional: true });
|
|
@@ -474,6 +472,7 @@ class SessionService {
|
|
|
474
472
|
_switching = signal(false, ...(ngDevMode ? [{ debugName: "_switching" }] : /* istanbul ignore next */ []));
|
|
475
473
|
_error = signal(null, ...(ngDevMode ? [{ debugName: "_error" }] : /* istanbul ignore next */ []));
|
|
476
474
|
inFlight = false;
|
|
475
|
+
current = null;
|
|
477
476
|
loadedKey = null;
|
|
478
477
|
language = 'es';
|
|
479
478
|
me = this._me.asReadonly();
|
|
@@ -517,7 +516,17 @@ class SessionService {
|
|
|
517
516
|
return null;
|
|
518
517
|
return this.companyOptions().find((company) => company.id === id)?.name ?? null;
|
|
519
518
|
}, ...(ngDevMode ? [{ debugName: "companyName" }] : /* istanbul ignore next */ []));
|
|
520
|
-
|
|
519
|
+
load(language, force = false) {
|
|
520
|
+
if (this.inFlight && this.current)
|
|
521
|
+
return this.current;
|
|
522
|
+
const task = this.run(language, force);
|
|
523
|
+
this.current = task;
|
|
524
|
+
return task;
|
|
525
|
+
}
|
|
526
|
+
ready() {
|
|
527
|
+
return this.current ?? Promise.resolve();
|
|
528
|
+
}
|
|
529
|
+
async run(language, force) {
|
|
521
530
|
if (!isNucleusConfigured(this.config))
|
|
522
531
|
return;
|
|
523
532
|
const identity = this.auth?.user() ?? null;
|
|
@@ -677,6 +686,73 @@ function isSessionRejected(error) {
|
|
|
677
686
|
return error instanceof HttpErrorResponse && (error.status === 401 || error.status === 403);
|
|
678
687
|
}
|
|
679
688
|
|
|
689
|
+
const nucleusAccessGuard = async (_route, state) => {
|
|
690
|
+
const session = inject(SessionService);
|
|
691
|
+
const language = inject(NucleusLanguage);
|
|
692
|
+
const router = inject(Router);
|
|
693
|
+
const home = normalizeHomeRoute(inject(NUCLEUS_HOME));
|
|
694
|
+
const url = routePath(state.url);
|
|
695
|
+
if (isHomeRoute(home, url))
|
|
696
|
+
return true;
|
|
697
|
+
await session.load(language.lang());
|
|
698
|
+
const node = matchMenuByRoute(session.menu(), url);
|
|
699
|
+
if (node && node.route !== home && node.canView)
|
|
700
|
+
return true;
|
|
701
|
+
return router.parseUrl(home);
|
|
702
|
+
};
|
|
703
|
+
|
|
704
|
+
const DEFAULT_TTL_MS = 30_000;
|
|
705
|
+
class NucleusCache {
|
|
706
|
+
entries = new Map();
|
|
707
|
+
inFlight = new Map();
|
|
708
|
+
read(key, loader, ttlMs = DEFAULT_TTL_MS) {
|
|
709
|
+
const entry = this.entries.get(key);
|
|
710
|
+
if (entry && Date.now() - entry.at < ttlMs) {
|
|
711
|
+
return Promise.resolve(entry.value);
|
|
712
|
+
}
|
|
713
|
+
return this.load(key, loader);
|
|
714
|
+
}
|
|
715
|
+
prefetch(key, loader, ttlMs = DEFAULT_TTL_MS) {
|
|
716
|
+
const entry = this.entries.get(key);
|
|
717
|
+
if (entry && Date.now() - entry.at < ttlMs)
|
|
718
|
+
return;
|
|
719
|
+
if (this.inFlight.has(key))
|
|
720
|
+
return;
|
|
721
|
+
void this.load(key, loader).catch(() => undefined);
|
|
722
|
+
}
|
|
723
|
+
invalidate(...prefixes) {
|
|
724
|
+
if (prefixes.length === 0) {
|
|
725
|
+
this.entries.clear();
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
for (const key of [...this.entries.keys()]) {
|
|
729
|
+
if (prefixes.some((prefix) => key.startsWith(prefix)))
|
|
730
|
+
this.entries.delete(key);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
load(key, loader) {
|
|
734
|
+
const running = this.inFlight.get(key);
|
|
735
|
+
if (running)
|
|
736
|
+
return running;
|
|
737
|
+
const promise = loader()
|
|
738
|
+
.then((value) => {
|
|
739
|
+
this.entries.set(key, { at: Date.now(), value });
|
|
740
|
+
return value;
|
|
741
|
+
})
|
|
742
|
+
.finally(() => {
|
|
743
|
+
this.inFlight.delete(key);
|
|
744
|
+
});
|
|
745
|
+
this.inFlight.set(key, promise);
|
|
746
|
+
return promise;
|
|
747
|
+
}
|
|
748
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusCache, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
749
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusCache, providedIn: 'root' });
|
|
750
|
+
}
|
|
751
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusCache, decorators: [{
|
|
752
|
+
type: Injectable,
|
|
753
|
+
args: [{ providedIn: 'root' }]
|
|
754
|
+
}] });
|
|
755
|
+
|
|
680
756
|
const DATE_LOCALES = {
|
|
681
757
|
es: 'es-PE',
|
|
682
758
|
en: 'en-US',
|
|
@@ -1570,6 +1646,20 @@ const FRAMES = [
|
|
|
1570
1646
|
glow: '#5b4fd6',
|
|
1571
1647
|
},
|
|
1572
1648
|
},
|
|
1649
|
+
{
|
|
1650
|
+
id: 'studio',
|
|
1651
|
+
scheme: 'light',
|
|
1652
|
+
starfield: false,
|
|
1653
|
+
accent: 'amber',
|
|
1654
|
+
tokens: {
|
|
1655
|
+
bg: '#f1cba0',
|
|
1656
|
+
raised: '#f6dfc4',
|
|
1657
|
+
ink: '#3b2f24',
|
|
1658
|
+
muted: '#5f4e3d',
|
|
1659
|
+
line: '#ccb383',
|
|
1660
|
+
glow: '#7a4a0a',
|
|
1661
|
+
},
|
|
1662
|
+
},
|
|
1573
1663
|
{
|
|
1574
1664
|
id: 'mist',
|
|
1575
1665
|
scheme: 'light',
|
|
@@ -1609,6 +1699,29 @@ const CANVASES = [
|
|
|
1609
1699
|
warning: '#8a5a00',
|
|
1610
1700
|
},
|
|
1611
1701
|
},
|
|
1702
|
+
{
|
|
1703
|
+
id: 'soft',
|
|
1704
|
+
tokens: {
|
|
1705
|
+
bg: '#d9dce3',
|
|
1706
|
+
surface: '#eef0f4',
|
|
1707
|
+
surfaceAlt: '#c8ccd6',
|
|
1708
|
+
text: '#16151d',
|
|
1709
|
+
textMuted: '#545a66',
|
|
1710
|
+
border: '#c0c6d1',
|
|
1711
|
+
},
|
|
1712
|
+
effects: {
|
|
1713
|
+
shadowOne: '0 1px 2px rgb(16 20 30 / 8%), 0 2px 8px rgb(16 20 30 / 6%)',
|
|
1714
|
+
shadowTwo: '0 4px 12px rgb(16 20 30 / 10%), 0 12px 32px rgb(16 20 30 / 8%)',
|
|
1715
|
+
wash: 0.1,
|
|
1716
|
+
washStrong: 0.18,
|
|
1717
|
+
headerBg: '#c6ccd8',
|
|
1718
|
+
headerInk: '#333a47',
|
|
1719
|
+
headerLine: '#aeb6c4',
|
|
1720
|
+
danger: '#b02121',
|
|
1721
|
+
success: '#136b35',
|
|
1722
|
+
warning: '#8a5a00',
|
|
1723
|
+
},
|
|
1724
|
+
},
|
|
1612
1725
|
{
|
|
1613
1726
|
id: 'dim',
|
|
1614
1727
|
tokens: {
|
|
@@ -1776,6 +1889,7 @@ const FRAMES_ES = {
|
|
|
1776
1889
|
slate: 'Pizarra',
|
|
1777
1890
|
ink: 'Tinta',
|
|
1778
1891
|
graphite: 'Grafito',
|
|
1892
|
+
studio: 'Estudio',
|
|
1779
1893
|
paper: 'Papel',
|
|
1780
1894
|
mist: 'Bruma',
|
|
1781
1895
|
};
|
|
@@ -1790,6 +1904,7 @@ const FRAMES_EN = {
|
|
|
1790
1904
|
slate: 'Slate',
|
|
1791
1905
|
ink: 'Ink',
|
|
1792
1906
|
graphite: 'Graphite',
|
|
1907
|
+
studio: 'Studio',
|
|
1793
1908
|
paper: 'Paper',
|
|
1794
1909
|
mist: 'Mist',
|
|
1795
1910
|
};
|
|
@@ -1829,7 +1944,13 @@ const THEME_COPY = {
|
|
|
1829
1944
|
densityTitle: 'Densidad',
|
|
1830
1945
|
densityHint: 'Cuántas filas quieres ver de una sola pasada.',
|
|
1831
1946
|
frames: FRAMES_ES,
|
|
1832
|
-
canvases: {
|
|
1947
|
+
canvases: {
|
|
1948
|
+
light: 'Claro',
|
|
1949
|
+
soft: 'Suave',
|
|
1950
|
+
dim: 'Atenuado',
|
|
1951
|
+
dark: 'Oscuro',
|
|
1952
|
+
system: 'Del sistema',
|
|
1953
|
+
},
|
|
1833
1954
|
accents: ACCENTS_ES,
|
|
1834
1955
|
densities: { comfortable: 'Cómoda', compact: 'Compacta' },
|
|
1835
1956
|
},
|
|
@@ -1844,7 +1965,13 @@ const THEME_COPY = {
|
|
|
1844
1965
|
densityTitle: 'Density',
|
|
1845
1966
|
densityHint: 'How many rows you want to see at a glance.',
|
|
1846
1967
|
frames: FRAMES_EN,
|
|
1847
|
-
canvases: {
|
|
1968
|
+
canvases: {
|
|
1969
|
+
light: 'Light',
|
|
1970
|
+
soft: 'Soft',
|
|
1971
|
+
dim: 'Dim',
|
|
1972
|
+
dark: 'Dark',
|
|
1973
|
+
system: 'System',
|
|
1974
|
+
},
|
|
1848
1975
|
accents: ACCENTS_EN,
|
|
1849
1976
|
densities: { comfortable: 'Comfortable', compact: 'Compact' },
|
|
1850
1977
|
},
|
|
@@ -2882,6 +3009,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
2882
3009
|
], hostDirectives: [NucleusEnterAdvance], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ns-form-grid\" [class]=\"gridClass()\">\n @for (field of fields(); track field.key) {\n <div class=\"ns-field\" [class]=\"fieldClass(field)\">\n @if (kindOf(field) !== 'checkbox' && kindOf(field) !== 'switch') {\n <label [attr.for]=\"kindOf(field) === 'color' ? null : 'nf-' + field.key\">\n {{ field.label }}\n </label>\n }\n\n @switch (kindOf(field)) {\n @case ('textarea') {\n <textarea\n pTextarea\n [id]=\"'nf-' + field.key\"\n [rows]=\"field.rows ?? 3\"\n [ngModel]=\"text(field)\"\n (ngModelChange)=\"write(field, $event)\"\n [disabled]=\"isDisabled(field)\"\n [attr.maxlength]=\"field.maxlength ?? null\"\n [attr.placeholder]=\"field.placeholder ?? null\"\n [ngModelOptions]=\"{ standalone: true }\"\n fluid\n ></textarea>\n }\n @case ('select') {\n <p-select\n [inputId]=\"'nf-' + field.key\"\n [options]=\"optionsOf(field)\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"read(field)\"\n (ngModelChange)=\"write(field, $event)\"\n [disabled]=\"isDisabled(field)\"\n [placeholder]=\"field.placeholder ?? labels().choose\"\n [showClear]=\"field.clearable === true\"\n [filter]=\"isSearchable(field)\"\n filterBy=\"label\"\n [filterPlaceholder]=\"labels().search\"\n [autofocusFilter]=\"true\"\n [resetFilterOnHide]=\"true\"\n [ngModelOptions]=\"{ standalone: true }\"\n fluid\n />\n }\n @case ('icon') {\n <nucleus-icon-picker\n [inputId]=\"'nf-' + field.key\"\n [value]=\"nullableText(field)\"\n (valueChange)=\"write(field, $event)\"\n [disabled]=\"isDisabled(field)\"\n />\n }\n @case ('color') {\n <nucleus-color-picker\n [value]=\"nullableText(field)\"\n (valueChange)=\"write(field, $event)\"\n [disabled]=\"isDisabled(field)\"\n [ariaLabel]=\"field.label\"\n />\n }\n @case ('checkbox') {\n <div class=\"ns-inline\">\n <p-checkbox\n [inputId]=\"'nf-' + field.key\"\n [binary]=\"true\"\n [ngModel]=\"checked(field)\"\n (ngModelChange)=\"write(field, $event)\"\n [disabled]=\"isDisabled(field)\"\n [ngModelOptions]=\"{ standalone: true }\"\n />\n <label [attr.for]=\"'nf-' + field.key\" class=\"ns-inline-label\">{{ field.label }}</label>\n </div>\n }\n @case ('switch') {\n <div class=\"ns-inline\">\n <p-toggleswitch\n [inputId]=\"'nf-' + field.key\"\n [ngModel]=\"checked(field)\"\n (ngModelChange)=\"write(field, $event)\"\n [disabled]=\"isDisabled(field)\"\n [ngModelOptions]=\"{ standalone: true }\"\n />\n <label [attr.for]=\"'nf-' + field.key\" class=\"ns-inline-label\">{{ field.label }}</label>\n </div>\n }\n @default {\n <input\n pInputText\n [id]=\"'nf-' + field.key\"\n [type]=\"kindOf(field) === 'number' ? 'number' : kindOf(field)\"\n [ngModel]=\"text(field)\"\n (ngModelChange)=\"write(field, $event)\"\n [disabled]=\"isDisabled(field)\"\n [attr.maxlength]=\"field.maxlength ?? null\"\n [attr.placeholder]=\"field.placeholder ?? null\"\n [ngModelOptions]=\"{ standalone: true }\"\n autocomplete=\"off\"\n fluid\n />\n }\n }\n\n @if (field.hint) {\n <p class=\"ns-hint\">{{ field.hint }}</p>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block}\n"] }]
|
|
2883
3010
|
}], ctorParameters: () => [], propDecorators: { fields: [{ type: i0.Input, args: [{ isSignal: true, alias: "fields", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
|
|
2884
3011
|
|
|
3012
|
+
class NucleusLink {
|
|
3013
|
+
route = input(null, ...(ngDevMode ? [{ debugName: "route" }] : /* istanbul ignore next */ []));
|
|
3014
|
+
queryParams = input(null, ...(ngDevMode ? [{ debugName: "queryParams" }] : /* istanbul ignore next */ []));
|
|
3015
|
+
href = input(null, ...(ngDevMode ? [{ debugName: "href" }] : /* istanbul ignore next */ []));
|
|
3016
|
+
hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
|
|
3017
|
+
muted = input(false, ...(ngDevMode ? [{ debugName: "muted" }] : /* istanbul ignore next */ []));
|
|
3018
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusLink, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3019
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: NucleusLink, isStandalone: true, selector: "nucleus-link", inputs: { route: { classPropertyName: "route", publicName: "route", isSignal: true, isRequired: false, transformFunction: null }, queryParams: { classPropertyName: "queryParams", publicName: "queryParams", isSignal: true, isRequired: false, transformFunction: null }, href: { classPropertyName: "href", publicName: "href", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, muted: { classPropertyName: "muted", publicName: "muted", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-template #body>\n <span class=\"label\"><ng-content /></span>\n <i class=\"pi pi-arrow-up-right\" aria-hidden=\"true\"></i>\n</ng-template>\n\n@if (route(); as target) {\n <a\n class=\"chip\"\n [class.is-muted]=\"muted()\"\n [routerLink]=\"target\"\n [queryParams]=\"queryParams()\"\n [attr.title]=\"hint() || null\"\n >\n <ng-container [ngTemplateOutlet]=\"body\" />\n </a>\n} @else {\n <a\n class=\"chip\"\n [class.is-muted]=\"muted()\"\n [href]=\"href() ?? '#'\"\n [attr.title]=\"hint() || null\"\n >\n <ng-container [ngTemplateOutlet]=\"body\" />\n </a>\n}\n", styles: [":host{display:inline-flex;min-width:0}.chip{display:inline-flex;min-width:0;align-items:center;gap:7px;padding:3px 7px 3px 10px;border:1px solid color-mix(in srgb,var(--ac-accent) 34%,transparent);border-radius:6px;background:color-mix(in srgb,var(--ac-accent) 11%,transparent);color:var(--ac-accent);font-variant-numeric:tabular-nums;text-decoration:none;transition:background .12s ease,border-color .12s ease}.chip.is-muted{border-color:var(--ac-border);background:color-mix(in srgb,var(--ac-text) 6%,transparent);color:var(--ac-text)}.chip .label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.chip .pi{flex:none;font-size:.72em;opacity:.7;transition:opacity .12s ease,transform .12s ease}.chip:hover{border-color:color-mix(in srgb,var(--ac-accent) 60%,transparent);background:color-mix(in srgb,var(--ac-accent) 18%,transparent)}.chip:hover .pi{opacity:1;transform:translate(1px,-1px)}.chip:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3020
|
+
}
|
|
3021
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusLink, decorators: [{
|
|
3022
|
+
type: Component,
|
|
3023
|
+
args: [{ selector: 'nucleus-link', imports: [NgTemplateOutlet, RouterLink], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template #body>\n <span class=\"label\"><ng-content /></span>\n <i class=\"pi pi-arrow-up-right\" aria-hidden=\"true\"></i>\n</ng-template>\n\n@if (route(); as target) {\n <a\n class=\"chip\"\n [class.is-muted]=\"muted()\"\n [routerLink]=\"target\"\n [queryParams]=\"queryParams()\"\n [attr.title]=\"hint() || null\"\n >\n <ng-container [ngTemplateOutlet]=\"body\" />\n </a>\n} @else {\n <a\n class=\"chip\"\n [class.is-muted]=\"muted()\"\n [href]=\"href() ?? '#'\"\n [attr.title]=\"hint() || null\"\n >\n <ng-container [ngTemplateOutlet]=\"body\" />\n </a>\n}\n", styles: [":host{display:inline-flex;min-width:0}.chip{display:inline-flex;min-width:0;align-items:center;gap:7px;padding:3px 7px 3px 10px;border:1px solid color-mix(in srgb,var(--ac-accent) 34%,transparent);border-radius:6px;background:color-mix(in srgb,var(--ac-accent) 11%,transparent);color:var(--ac-accent);font-variant-numeric:tabular-nums;text-decoration:none;transition:background .12s ease,border-color .12s ease}.chip.is-muted{border-color:var(--ac-border);background:color-mix(in srgb,var(--ac-text) 6%,transparent);color:var(--ac-text)}.chip .label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.chip .pi{flex:none;font-size:.72em;opacity:.7;transition:opacity .12s ease,transform .12s ease}.chip:hover{border-color:color-mix(in srgb,var(--ac-accent) 60%,transparent);background:color-mix(in srgb,var(--ac-accent) 18%,transparent)}.chip:hover .pi{opacity:1;transform:translate(1px,-1px)}.chip:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}\n"] }]
|
|
3024
|
+
}], propDecorators: { route: [{ type: i0.Input, args: [{ isSignal: true, alias: "route", required: false }] }], queryParams: [{ type: i0.Input, args: [{ isSignal: true, alias: "queryParams", required: false }] }], href: [{ type: i0.Input, args: [{ isSignal: true, alias: "href", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], muted: [{ type: i0.Input, args: [{ isSignal: true, alias: "muted", required: false }] }] } });
|
|
3025
|
+
|
|
2885
3026
|
class NucleusCell {
|
|
2886
3027
|
nucleusCell = input.required(...(ngDevMode ? [{ debugName: "nucleusCell" }] : /* istanbul ignore next */ []));
|
|
2887
3028
|
template = inject(TemplateRef);
|
|
@@ -2895,6 +3036,48 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
2895
3036
|
}]
|
|
2896
3037
|
}], propDecorators: { nucleusCell: [{ type: i0.Input, args: [{ isSignal: true, alias: "nucleusCell", required: true }] }] } });
|
|
2897
3038
|
|
|
3039
|
+
function menuTile(label, icon, color) {
|
|
3040
|
+
return { label, icon, color, ink: color ? readableOn(color) : null, ghost: false };
|
|
3041
|
+
}
|
|
3042
|
+
function menuGlyph(icon) {
|
|
3043
|
+
return { label: '', icon, color: null, ink: null, ghost: true };
|
|
3044
|
+
}
|
|
3045
|
+
function foldText(value) {
|
|
3046
|
+
return value
|
|
3047
|
+
.normalize('NFD')
|
|
3048
|
+
.replace(/[̀-ͯ]/g, '')
|
|
3049
|
+
.toLowerCase();
|
|
3050
|
+
}
|
|
3051
|
+
function matchesRow(row, term) {
|
|
3052
|
+
return foldText(row.name).includes(term) || foldText(row.meta ?? '').includes(term);
|
|
3053
|
+
}
|
|
3054
|
+
function selectableRows(sections) {
|
|
3055
|
+
return sections.flatMap((section) => section.rows).filter((row) => !row.disabled && !row.current);
|
|
3056
|
+
}
|
|
3057
|
+
|
|
3058
|
+
const NUCLEUS_NARROW_QUERY = '(max-width: 720px)';
|
|
3059
|
+
class NucleusViewport {
|
|
3060
|
+
query = typeof window !== 'undefined' && typeof window.matchMedia === 'function'
|
|
3061
|
+
? window.matchMedia(NUCLEUS_NARROW_QUERY)
|
|
3062
|
+
: null;
|
|
3063
|
+
_narrow = signal(this.query?.matches ?? false, ...(ngDevMode ? [{ debugName: "_narrow" }] : /* istanbul ignore next */ []));
|
|
3064
|
+
narrow = this._narrow.asReadonly();
|
|
3065
|
+
constructor() {
|
|
3066
|
+
const query = this.query;
|
|
3067
|
+
if (!query)
|
|
3068
|
+
return;
|
|
3069
|
+
const onChange = (event) => this._narrow.set(event.matches);
|
|
3070
|
+
query.addEventListener('change', onChange);
|
|
3071
|
+
inject(DestroyRef).onDestroy(() => query.removeEventListener('change', onChange));
|
|
3072
|
+
}
|
|
3073
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusViewport, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3074
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusViewport, providedIn: 'root' });
|
|
3075
|
+
}
|
|
3076
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusViewport, decorators: [{
|
|
3077
|
+
type: Injectable,
|
|
3078
|
+
args: [{ providedIn: 'root' }]
|
|
3079
|
+
}], ctorParameters: () => [] });
|
|
3080
|
+
|
|
2898
3081
|
class NucleusList {
|
|
2899
3082
|
rows = input.required(...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
|
|
2900
3083
|
columns = input.required(...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
|
|
@@ -2904,16 +3087,120 @@ class NucleusList {
|
|
|
2904
3087
|
minWidth = input('640px', ...(ngDevMode ? [{ debugName: "minWidth" }] : /* istanbul ignore next */ []));
|
|
2905
3088
|
skeletonRows = input(5, ...(ngDevMode ? [{ debugName: "skeletonRows" }] : /* istanbul ignore next */ []));
|
|
2906
3089
|
rowClass = input(() => '', ...(ngDevMode ? [{ debugName: "rowClass" }] : /* istanbul ignore next */ []));
|
|
2907
|
-
pageSize = input(
|
|
3090
|
+
pageSize = input(5, ...(ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []));
|
|
2908
3091
|
pageSizes = input([5, 10, 20, 25], ...(ngDevMode ? [{ debugName: "pageSizes" }] : /* istanbul ignore next */ []));
|
|
3092
|
+
cards = input(true, ...(ngDevMode ? [{ debugName: "cards" }] : /* istanbul ignore next */ []));
|
|
3093
|
+
reorderable = input(false, ...(ngDevMode ? [{ debugName: "reorderable" }] : /* istanbul ignore next */ []));
|
|
3094
|
+
searchable = input(true, ...(ngDevMode ? [{ debugName: "searchable" }] : /* istanbul ignore next */ []));
|
|
3095
|
+
reorderGroup = input(null, ...(ngDevMode ? [{ debugName: "reorderGroup" }] : /* istanbul ignore next */ []));
|
|
2909
3096
|
action = output();
|
|
3097
|
+
reorder = output();
|
|
3098
|
+
dragStart = output();
|
|
2910
3099
|
toggle = output();
|
|
2911
3100
|
cells = contentChildren(NucleusCell, ...(ngDevMode ? [{ debugName: "cells" }] : /* istanbul ignore next */ []));
|
|
3101
|
+
language = inject(NucleusLanguage);
|
|
3102
|
+
viewport = inject(NucleusViewport);
|
|
3103
|
+
copy = computed(() => commonCopyOf(this.language.lang()), ...(ngDevMode ? [{ debugName: "copy" }] : /* istanbul ignore next */ []));
|
|
3104
|
+
term = signal('', ...(ngDevMode ? [{ debugName: "term" }] : /* istanbul ignore next */ []));
|
|
3105
|
+
chosenView = signal('rows', ...(ngDevMode ? [{ debugName: "chosenView" }] : /* istanbul ignore next */ []));
|
|
3106
|
+
canChooseView = computed(() => !this.viewport.narrow(), ...(ngDevMode ? [{ debugName: "canChooseView" }] : /* istanbul ignore next */ []));
|
|
3107
|
+
view = computed(() => this.canChooseView() ? this.chosenView() : 'grid', ...(ngDevMode ? [{ debugName: "view" }] : /* istanbul ignore next */ []));
|
|
3108
|
+
chooseView(value) {
|
|
3109
|
+
this.chosenView.set(value);
|
|
3110
|
+
}
|
|
3111
|
+
filtered = computed(() => {
|
|
3112
|
+
const term = foldText(this.term().trim());
|
|
3113
|
+
const all = this.rows();
|
|
3114
|
+
if (!term)
|
|
3115
|
+
return [...all];
|
|
3116
|
+
const columns = this.columns();
|
|
3117
|
+
return all.filter((row) => columns.some((column) => foldText(this.text(column, row)).includes(term)));
|
|
3118
|
+
}, ...(ngDevMode ? [{ debugName: "filtered" }] : /* istanbul ignore next */ []));
|
|
3119
|
+
dragLocked = computed(() => !this.reorderable() || this.term().trim().length > 0, ...(ngDevMode ? [{ debugName: "dragLocked" }] : /* istanbul ignore next */ []));
|
|
3120
|
+
showNoResults = computed(() => !this.loading() && this.rows().length > 0 && this.filtered().length === 0, ...(ngDevMode ? [{ debugName: "showNoResults" }] : /* istanbul ignore next */ []));
|
|
3121
|
+
onSearch(event) {
|
|
3122
|
+
this.term.set(event.target.value);
|
|
3123
|
+
}
|
|
3124
|
+
firstRow = signal(0, ...(ngDevMode ? [{ debugName: "firstRow" }] : /* istanbul ignore next */ []));
|
|
3125
|
+
rowsOverride = signal(0, ...(ngDevMode ? [{ debugName: "rowsOverride" }] : /* istanbul ignore next */ []));
|
|
3126
|
+
compact = computed(() => this.cards(), ...(ngDevMode ? [{ debugName: "compact" }] : /* istanbul ignore next */ []));
|
|
3127
|
+
rowsPerPage = computed(() => this.rowsOverride() || this.pageSize(), ...(ngDevMode ? [{ debugName: "rowsPerPage" }] : /* istanbul ignore next */ []));
|
|
3128
|
+
identityColumn = computed(() => {
|
|
3129
|
+
const columns = this.columns();
|
|
3130
|
+
return (columns.find((column) => column.role === 'identity') ??
|
|
3131
|
+
columns.find((column) => !column.role) ??
|
|
3132
|
+
columns[0] ??
|
|
3133
|
+
null);
|
|
3134
|
+
}, ...(ngDevMode ? [{ debugName: "identityColumn" }] : /* istanbul ignore next */ []));
|
|
3135
|
+
statusColumn = computed(() => {
|
|
3136
|
+
const columns = this.columns();
|
|
3137
|
+
const explicit = columns.find((column) => column.role === 'status');
|
|
3138
|
+
if (explicit)
|
|
3139
|
+
return explicit;
|
|
3140
|
+
const identity = this.identityColumn();
|
|
3141
|
+
return columns.find((column) => column !== identity && !column.role && !!column.tag) ?? null;
|
|
3142
|
+
}, ...(ngDevMode ? [{ debugName: "statusColumn" }] : /* istanbul ignore next */ []));
|
|
3143
|
+
attributeColumns = computed(() => {
|
|
3144
|
+
const identity = this.identityColumn();
|
|
3145
|
+
const status = this.statusColumn();
|
|
3146
|
+
return this.columns().filter((column) => column !== identity && column !== status && column.role !== 'hidden');
|
|
3147
|
+
}, ...(ngDevMode ? [{ debugName: "attributeColumns" }] : /* istanbul ignore next */ []));
|
|
3148
|
+
pagedRows = computed(() => {
|
|
3149
|
+
const all = this.filtered();
|
|
3150
|
+
if (!this.paginate())
|
|
3151
|
+
return [...all];
|
|
3152
|
+
const size = this.rowsPerPage();
|
|
3153
|
+
const start = this.firstRow() < all.length ? this.firstRow() : 0;
|
|
3154
|
+
return all.slice(start, start + size);
|
|
3155
|
+
}, ...(ngDevMode ? [{ debugName: "pagedRows" }] : /* istanbul ignore next */ []));
|
|
3156
|
+
resetPage = effect(() => {
|
|
3157
|
+
const total = this.filtered().length;
|
|
3158
|
+
untracked(() => {
|
|
3159
|
+
if (this.firstRow() >= total)
|
|
3160
|
+
this.firstRow.set(0);
|
|
3161
|
+
});
|
|
3162
|
+
}, ...(ngDevMode ? [{ debugName: "resetPage" }] : /* istanbul ignore next */ []));
|
|
3163
|
+
page = this.firstRow.asReadonly();
|
|
3164
|
+
sortAllowed = (index, drag) => {
|
|
3165
|
+
const group = this.reorderGroup();
|
|
3166
|
+
if (!group)
|
|
3167
|
+
return true;
|
|
3168
|
+
const target = this.pagedRows()[index];
|
|
3169
|
+
const dragged = drag.data;
|
|
3170
|
+
if (!target || !dragged)
|
|
3171
|
+
return true;
|
|
3172
|
+
return group(target) === group(dragged);
|
|
3173
|
+
};
|
|
3174
|
+
onRowReorder(event) {
|
|
3175
|
+
this.applyMove(event.dragIndex ?? -1, event.dropIndex ?? -1);
|
|
3176
|
+
}
|
|
3177
|
+
onCardDrop(event) {
|
|
3178
|
+
const offset = this.firstRow();
|
|
3179
|
+
this.applyMove(event.previousIndex + offset, event.currentIndex + offset);
|
|
3180
|
+
}
|
|
3181
|
+
applyMove(from, to) {
|
|
3182
|
+
const all = this.rows();
|
|
3183
|
+
if (from < 0 || to < 0 || from === to)
|
|
3184
|
+
return;
|
|
3185
|
+
if (from >= all.length || to >= all.length)
|
|
3186
|
+
return;
|
|
3187
|
+
const next = [...all];
|
|
3188
|
+
const [moved] = next.splice(from, 1);
|
|
3189
|
+
if (!moved)
|
|
3190
|
+
return;
|
|
3191
|
+
next.splice(to, 0, moved);
|
|
3192
|
+
this.reorder.emit(next);
|
|
3193
|
+
}
|
|
3194
|
+
onPage(event) {
|
|
3195
|
+
this.firstRow.set(event.first ?? 0);
|
|
3196
|
+
if (event.rows)
|
|
3197
|
+
this.rowsOverride.set(event.rows);
|
|
3198
|
+
}
|
|
2912
3199
|
paginate = computed(() => !this.loading(), ...(ngDevMode ? [{ debugName: "paginate" }] : /* istanbul ignore next */ []));
|
|
2913
3200
|
tableStyle = computed(() => ({ 'min-width': this.minWidth() }), ...(ngDevMode ? [{ debugName: "tableStyle" }] : /* istanbul ignore next */ []));
|
|
2914
3201
|
showEmpty = computed(() => !this.loading() && this.rows().length === 0, ...(ngDevMode ? [{ debugName: "showEmpty" }] : /* istanbul ignore next */ []));
|
|
2915
3202
|
placeholders = computed(() => Array.from({ length: Math.max(this.skeletonRows(), 1) }, (_, index) => ({ index })), ...(ngDevMode ? [{ debugName: "placeholders" }] : /* istanbul ignore next */ []));
|
|
2916
|
-
data = computed(() => this.loading() ? this.placeholders() : this.rows(), ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
3203
|
+
data = computed(() => this.loading() ? this.placeholders() : [...this.rows()], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
2917
3204
|
skeletonWidth(column) {
|
|
2918
3205
|
if (column.kind === 'switch')
|
|
2919
3206
|
return '84px';
|
|
@@ -2932,6 +3219,9 @@ class NucleusList {
|
|
|
2932
3219
|
const raw = row[column.key];
|
|
2933
3220
|
return raw === null || raw === undefined ? '—' : String(raw);
|
|
2934
3221
|
}
|
|
3222
|
+
linkOf(column, row) {
|
|
3223
|
+
return column.link ? column.link(row) : null;
|
|
3224
|
+
}
|
|
2935
3225
|
tagOf(column, row) {
|
|
2936
3226
|
return column.tag ? column.tag(row) : null;
|
|
2937
3227
|
}
|
|
@@ -2959,12 +3249,24 @@ class NucleusList {
|
|
|
2959
3249
|
this.toggle.emit({ key: column.key, row, value: !this.isChecked(column, row) });
|
|
2960
3250
|
}
|
|
2961
3251
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusList, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2962
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: NucleusList, isStandalone: true, selector: "nucleus-list", inputs: { rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, empty: { classPropertyName: "empty", publicName: "empty", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, skeletonRows: { classPropertyName: "skeletonRows", publicName: "skeletonRows", isSignal: true, isRequired: false, transformFunction: null }, rowClass: { classPropertyName: "rowClass", publicName: "rowClass", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, pageSizes: { classPropertyName: "pageSizes", publicName: "pageSizes", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action", toggle: "toggle" }, queries: [{ propertyName: "cells", predicate: NucleusCell, isSignal: true }], ngImport: i0, template: "<div class=\"head\">\n <ng-content select=\"[nucleusListTitle]\" />\n <div class=\"head-actions\">\n <ng-content select=\"[nucleusListActions]\" />\n </div>\n</div>\n\n@if (showEmpty()) {\n <div class=\"placeholder\">{{ empty() }}</div>\n} @else {\n <p-table\n [value]=\"data()\"\n styleClass=\"ns-table\"\n [tableStyle]=\"tableStyle()\"\n [paginator]=\"paginate()\"\n [rows]=\"pageSize()\"\n [rowsPerPageOptions]=\"pageSizes()\"\n [alwaysShowPaginator]=\"true\"\n >\n <ng-template #header>\n <tr>\n @for (column of columns(); track column.key) {\n <th [class]=\"'align-' + (column.align ?? 'left')\" [style.width]=\"column.width\">\n {{ column.header }}\n </th>\n }\n @if (actions().length) {\n <th class=\"align-right\"></th>\n }\n </tr>\n </ng-template>\n\n <ng-template #body let-row>\n @if (loading()) {\n <tr class=\"is-skeleton\">\n @for (column of columns(); track column.key) {\n <td [class]=\"'align-' + (column.align ?? 'left')\">\n <p-skeleton height=\"13px\" [width]=\"skeletonWidth(column)\" />\n </td>\n }\n @if (actions().length) {\n <td class=\"align-right actions\">\n <p-skeleton shape=\"circle\" size=\"26px\" />\n </td>\n }\n </tr>\n } @else {\n <tr [class]=\"rowClass()(row)\">\n @for (column of columns(); track column.key) {\n <td [class]=\"'align-' + (column.align ?? 'left')\" [class.strong]=\"column.strong\">\n @if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else if (column.kind === 'switch') {\n <span class=\"switch-cell\">\n <button\n type=\"button\"\n class=\"ns-switch\"\n role=\"switch\"\n [class.is-on]=\"isChecked(column, row)\"\n [attr.aria-checked]=\"isChecked(column, row)\"\n [attr.aria-label]=\"text(column, row)\"\n [disabled]=\"isLocked(column, row)\"\n [pTooltip]=\"hintOf(column, row)\"\n tooltipPosition=\"top\"\n (click)=\"flip(column, row)\"\n >\n <span class=\"knob\"></span>\n </button>\n <span class=\"switch-label\">{{ text(column, row) }}</span>\n </span>\n } @else {\n {{ text(column, row) }}\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n }\n }\n </td>\n }\n\n @if (actions().length) {\n <td class=\"align-right actions\">\n @for (entry of visibleActions(row); track entry.id) {\n <p-button\n [icon]=\"entry.icon\"\n [severity]=\"entry.tone === 'danger' ? 'danger' : 'secondary'\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [pTooltip]=\"entry.label\"\n tooltipPosition=\"left\"\n [ariaLabel]=\"entry.label\"\n [disabled]=\"isActionLocked(entry, row)\"\n (onClick)=\"run(entry, row)\"\n />\n }\n </td>\n }\n </tr>\n }\n </ng-template>\n </p-table>\n}\n", styles: [":host{display:block}.head{display:flex;align-items:center;justify-content:space-between;gap:12px}.head:has(>*:not(.head-actions)),.head:has(.head-actions>*){min-height:34px;margin-bottom:12px}.head-actions{display:flex;gap:8px}.placeholder{padding:26px;border:1px dashed var(--ac-border);border-radius:10px;color:var(--ac-text-muted);font-size:14px}.align-left{text-align:left}.align-center{text-align:center}.align-right{text-align:right}.strong{font-weight:600}.actions{white-space:nowrap}.switch-cell{display:inline-flex;align-items:center;gap:10px}.switch-label{color:var(--ac-text-muted);font-size:12px}.ns-switch{position:relative;width:38px;height:22px;flex:none;padding:0;border:1px solid var(--ac-border);border-radius:var(--ac-radius-pill);background:color-mix(in srgb,var(--ac-text) 10%,transparent);cursor:pointer;transition:background .14s ease,border-color .14s ease}.ns-switch .knob{position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--ac-text);transition:transform .14s ease}.ns-switch.is-on{border-color:var(--ac-accent);background:var(--ac-accent)}.ns-switch.is-on .knob{background:var(--ac-on-accent);transform:translate(16px)}.ns-switch:disabled{cursor:not-allowed;opacity:.45}.ns-switch:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i3$1.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i4.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i5$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3252
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: NucleusList, isStandalone: true, selector: "nucleus-list", inputs: { rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, empty: { classPropertyName: "empty", publicName: "empty", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, skeletonRows: { classPropertyName: "skeletonRows", publicName: "skeletonRows", isSignal: true, isRequired: false, transformFunction: null }, rowClass: { classPropertyName: "rowClass", publicName: "rowClass", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, pageSizes: { classPropertyName: "pageSizes", publicName: "pageSizes", isSignal: true, isRequired: false, transformFunction: null }, cards: { classPropertyName: "cards", publicName: "cards", isSignal: true, isRequired: false, transformFunction: null }, reorderable: { classPropertyName: "reorderable", publicName: "reorderable", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, reorderGroup: { classPropertyName: "reorderGroup", publicName: "reorderGroup", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action", reorder: "reorder", dragStart: "dragStart", toggle: "toggle" }, queries: [{ propertyName: "cells", predicate: NucleusCell, isSignal: true }], ngImport: i0, template: "<div class=\"head\">\n <ng-content select=\"[nucleusListTitle]\" />\n <div class=\"head-actions\">\n <ng-content select=\"[nucleusListActions]\" />\n </div>\n</div>\n\n@if (showEmpty()) {\n <div class=\"placeholder\">{{ empty() }}</div>\n} @else {\n <div class=\"bar\">\n @if (searchable()) {\n <label class=\"search\">\n <i class=\"pi pi-search\" aria-hidden=\"true\"></i>\n <input\n type=\"search\"\n [value]=\"term()\"\n [placeholder]=\"copy().search\"\n [attr.aria-label]=\"copy().search\"\n (input)=\"onSearch($event)\"\n />\n </label>\n }\n\n <span class=\"bar-spacer\"></span>\n\n @if (canChooseView()) {\n <span class=\"views\">\n <button\n type=\"button\"\n class=\"view\"\n [class.is-on]=\"view() === 'grid'\"\n [attr.aria-pressed]=\"view() === 'grid'\"\n [attr.aria-label]=\"copy().viewGrid\"\n [pTooltip]=\"copy().viewGrid\"\n tooltipPosition=\"bottom\"\n (click)=\"chooseView('grid')\"\n >\n <i class=\"pi pi-th-large\" aria-hidden=\"true\"></i>\n </button>\n <button\n type=\"button\"\n class=\"view\"\n [class.is-on]=\"view() === 'rows'\"\n [attr.aria-pressed]=\"view() === 'rows'\"\n [attr.aria-label]=\"copy().viewRows\"\n [pTooltip]=\"copy().viewRows\"\n tooltipPosition=\"bottom\"\n (click)=\"chooseView('rows')\"\n >\n <i class=\"pi pi-list\" aria-hidden=\"true\"></i>\n </button>\n </span>\n }\n </div>\n\n @if (compact()) {\n @if (showNoResults()) {\n <div class=\"placeholder\">{{ copy().noResults }}</div>\n }\n\n <div\n class=\"cards\"\n [class.is-rows]=\"view() === 'rows'\"\n cdkDropList\n cdkDropListOrientation=\"mixed\"\n [cdkDropListDisabled]=\"dragLocked()\"\n [cdkDropListSortPredicate]=\"sortAllowed\"\n (cdkDropListDropped)=\"onCardDrop($event)\"\n >\n @if (loading()) {\n @for (item of placeholders(); track $index) {\n <div class=\"card\">\n <div class=\"card-top\">\n <p-skeleton height=\"15px\" width=\"52%\" />\n </div>\n <div class=\"card-foot\">\n <p-skeleton height=\"12px\" width=\"30%\" />\n <p-skeleton height=\"12px\" width=\"30%\" />\n </div>\n </div>\n }\n } @else {\n @for (row of pagedRows(); track $index) {\n <article class=\"card\" [class]=\"rowClass()(row)\" cdkDrag\n [cdkDragData]=\"row\"\n [cdkDragDisabled]=\"dragLocked()\"\n (cdkDragStarted)=\"dragStart.emit(row)\">\n <div class=\"card-top\">\n @if (reorderable()) {\n <button\n type=\"button\"\n class=\"grip\"\n cdkDragHandle\n [disabled]=\"dragLocked()\"\n [attr.aria-label]=\"copy().reorderHandle\"\n >\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </button>\n }\n @if (identityColumn(); as column) {\n <span class=\"card-name\">\n @if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else {\n {{ text(column, row) }}\n }\n </span>\n }\n\n @if (statusColumn(); as column) {\n <span class=\"card-status\">\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n } @else if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else {\n {{ text(column, row) }}\n }\n </span>\n }\n </div>\n\n @if (attributeColumns().length || visibleActions(row).length) {\n <div class=\"card-foot\">\n <div class=\"card-fields\">\n @for (column of attributeColumns(); track column.key) {\n <div class=\"field\">\n <span class=\"field-label\">{{ column.header }}</span>\n <span class=\"field-value\">\n @if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else if (linkOf(column, row); as target) {\n <nucleus-link\n [route]=\"target.route\"\n [queryParams]=\"target.queryParams ?? null\"\n [hint]=\"column.header\"\n >\n {{ text(column, row) }}\n </nucleus-link>\n } @else if (column.kind === 'switch') {\n <button\n type=\"button\"\n class=\"ns-switch\"\n role=\"switch\"\n [class.is-on]=\"isChecked(column, row)\"\n [attr.aria-checked]=\"isChecked(column, row)\"\n [attr.aria-label]=\"column.header\"\n [disabled]=\"isLocked(column, row)\"\n (click)=\"flip(column, row)\"\n >\n <span class=\"knob\"></span>\n </button>\n } @else {\n {{ text(column, row) }}\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n }\n }\n </span>\n </div>\n }\n </div>\n\n @if (visibleActions(row).length) {\n <div class=\"card-actions\">\n @for (entry of visibleActions(row); track entry.id) {\n <p-button\n [icon]=\"entry.icon\"\n [severity]=\"entry.tone === 'danger' ? 'danger' : 'secondary'\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"entry.label\"\n [disabled]=\"isActionLocked(entry, row)\"\n (onClick)=\"run(entry, row)\"\n />\n }\n </div>\n }\n </div>\n }\n </article>\n }\n }\n </div>\n\n @if (paginate()) {\n <div class=\"foot\">\n <p-paginator\n styleClass=\"ns-cards-paginator\"\n [first]=\"page()\"\n [rows]=\"rowsPerPage()\"\n [totalRecords]=\"filtered().length\"\n [rowsPerPageOptions]=\"pageSizes()\"\n (onPageChange)=\"onPage($event)\"\n />\n </div>\n }\n} @else {\n <p-table\n [value]=\"data()\"\n styleClass=\"ns-table\"\n [tableStyle]=\"tableStyle()\"\n [paginator]=\"paginate()\"\n [rows]=\"pageSize()\"\n [rowsPerPageOptions]=\"pageSizes()\"\n [alwaysShowPaginator]=\"true\"\n (onRowReorder)=\"onRowReorder($event)\"\n >\n <ng-template #header>\n <tr>\n @if (reorderable()) {\n <th class=\"grip-head\"></th>\n }\n @for (column of columns(); track column.key) {\n <th [class]=\"'align-' + (column.align ?? 'left')\" [style.width]=\"column.width\">\n {{ column.header }}\n </th>\n }\n @if (actions().length) {\n <th class=\"align-right\"></th>\n }\n </tr>\n </ng-template>\n\n <ng-template #body let-row let-rowIndex=\"rowIndex\">\n @if (loading()) {\n <tr class=\"is-skeleton\">\n @if (reorderable()) {\n <td class=\"grip-cell\"></td>\n }\n @for (column of columns(); track column.key) {\n <td [class]=\"'align-' + (column.align ?? 'left')\">\n <p-skeleton height=\"13px\" [width]=\"skeletonWidth(column)\" />\n </td>\n }\n @if (actions().length) {\n <td class=\"align-right actions\">\n <p-skeleton shape=\"circle\" size=\"26px\" />\n </td>\n }\n </tr>\n } @else {\n <tr\n [class]=\"rowClass()(row)\"\n [pReorderableRow]=\"rowIndex\"\n [pReorderableRowDisabled]=\"dragLocked()\"\n >\n @if (reorderable()) {\n <td class=\"grip-cell\">\n <span class=\"grip\" pReorderableRowHandle [attr.aria-label]=\"copy().reorderHandle\">\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </span>\n </td>\n }\n @for (column of columns(); track column.key) {\n <td [class]=\"'align-' + (column.align ?? 'left')\" [class.strong]=\"column.strong\">\n @if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else if (column.kind === 'switch') {\n <span class=\"switch-cell\">\n <button\n type=\"button\"\n class=\"ns-switch\"\n role=\"switch\"\n [class.is-on]=\"isChecked(column, row)\"\n [attr.aria-checked]=\"isChecked(column, row)\"\n [attr.aria-label]=\"text(column, row)\"\n [disabled]=\"isLocked(column, row)\"\n [pTooltip]=\"hintOf(column, row)\"\n tooltipPosition=\"top\"\n (click)=\"flip(column, row)\"\n >\n <span class=\"knob\"></span>\n </button>\n <span class=\"switch-label\">{{ text(column, row) }}</span>\n </span>\n } @else {\n {{ text(column, row) }}\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n }\n }\n </td>\n }\n\n @if (actions().length) {\n <td class=\"align-right actions\">\n @for (entry of visibleActions(row); track entry.id) {\n <p-button\n [icon]=\"entry.icon\"\n [severity]=\"entry.tone === 'danger' ? 'danger' : 'secondary'\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [pTooltip]=\"entry.label\"\n tooltipPosition=\"left\"\n [ariaLabel]=\"entry.label\"\n [disabled]=\"isActionLocked(entry, row)\"\n (onClick)=\"run(entry, row)\"\n />\n }\n </td>\n }\n </tr>\n }\n </ng-template>\n </p-table>\n}\n}\n", styles: [":host{display:block}.head{display:flex;align-items:center;justify-content:space-between;gap:12px}.head:has(>*:not(.head-actions)),.head:has(.head-actions>*){min-height:34px;margin-bottom:12px}.head-actions{display:flex;gap:8px}.placeholder{padding:26px;border:1px dashed var(--ac-border);border-radius:10px;color:var(--ac-text-muted);font-size:14px}.align-left{text-align:left}.align-center{text-align:center}.align-right{text-align:right}.strong{font-weight:600}.actions{white-space:nowrap}.switch-cell{display:inline-flex;align-items:center;gap:10px}.switch-label{color:var(--ac-text-muted);font-size:12px}.ns-switch{position:relative;width:38px;height:22px;flex:none;padding:0;border:1px solid var(--ac-border);border-radius:var(--ac-radius-pill);background:color-mix(in srgb,var(--ac-text) 10%,transparent);cursor:pointer;transition:background .14s ease,border-color .14s ease}.ns-switch .knob{position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--ac-text);transition:transform .14s ease}.ns-switch.is-on{border-color:var(--ac-accent);background:var(--ac-accent)}.ns-switch.is-on .knob{background:var(--ac-on-accent);transform:translate(16px)}.ns-switch:disabled{cursor:not-allowed;opacity:.45}.ns-switch:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}.cards{display:grid;gap:12px;grid-template-columns:repeat(auto-fill,minmax(320px,1fr))}.card{padding:13px 14px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.card-top{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.card-name{display:flex;min-width:0;flex:1;align-items:center;gap:10px;font-size:15px;font-weight:600;line-height:1.3}.card-status{flex:none}.card-foot{display:flex;align-items:flex-end;gap:12px;margin-top:11px;padding-top:11px;border-top:1px solid var(--ac-border)}.card-fields{display:flex;min-width:0;flex:1;flex-wrap:wrap;gap:10px 20px}.card-actions{display:flex;flex:none;align-items:center;gap:2px}.field{display:flex;min-width:0;flex-direction:column;gap:2px}.field-label{color:var(--ac-text-muted);font-size:10px;font-weight:600;letter-spacing:.07em;text-transform:uppercase}.field-value{display:flex;align-items:center;gap:8px;font-size:15px;font-weight:600;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}::ng-deep .ns-cards-paginator{background:transparent}.grip{display:inline-grid;width:26px;height:26px;flex:none;padding:0;border:0;border-radius:4px;background:transparent;color:var(--ac-text-muted);cursor:grab;place-items:center;touch-action:none}.grip:hover{background:color-mix(in srgb,var(--ac-text) 8%,transparent);color:var(--ac-text)}.grip:active{cursor:grabbing}.grip:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}.grip .pi{font-size:13px}.grip-head,.grip-cell{width:38px;padding-right:0!important}.cdk-drag-preview{border:1px solid var(--ac-accent);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-2);opacity:.96}.cdk-drag-placeholder{border:1px dashed var(--ac-border);background:color-mix(in srgb,var(--ac-text) 4%,transparent);opacity:.6}.cdk-drag-placeholder *{visibility:hidden}.cards.cdk-drop-list-dragging .card:not(.cdk-drag-placeholder){transition:transform .18s cubic-bezier(0,0,.2,1)}.cdk-drag-animating{transition:transform .22s cubic-bezier(0,0,.2,1)}.bar{display:flex;align-items:center;gap:10px;margin-bottom:12px;padding:7px 10px;border:1px solid var(--ac-border);border-radius:10px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.bar-spacer{flex:1}.search{display:flex;min-width:0;max-width:340px;flex:1 1 220px;align-items:center;gap:8px;padding:5px 10px;border:1px solid var(--ac-border);border-radius:6px;background:color-mix(in srgb,var(--ac-text) 4%,transparent);color:var(--ac-text-muted)}.search:focus-within{border-color:var(--ac-accent);color:var(--ac-text)}.search .pi{font-size:13px}.search input{min-width:0;flex:1;padding:0;border:0;background:transparent;color:var(--ac-text);font:inherit;font-size:13px;outline:none}.search input::-webkit-search-cancel-button{filter:grayscale(1) opacity(.6)}.views{display:inline-flex;flex:none;padding:2px;border:1px solid var(--ac-border);border-radius:7px}.view{display:grid;width:30px;height:28px;padding:0;border:0;border-radius:5px;background:transparent;color:var(--ac-text-muted);cursor:pointer;place-items:center}.view:hover{color:var(--ac-text)}.view.is-on{background:color-mix(in srgb,var(--ac-accent) 18%,transparent);color:var(--ac-accent)}.view:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}.view .pi{font-size:14px}.foot{margin-top:12px;padding:4px 6px;border:1px solid var(--ac-border);border-radius:10px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}@media(min-width:721px){.cards.is-rows{gap:8px;grid-template-columns:minmax(0,1fr)}.cards.is-rows .card{display:grid;align-items:center;gap:18px;grid-template-columns:minmax(0,2fr) minmax(0,3fr);padding:9px 14px}.cards.is-rows .card-top{min-width:0;align-items:center;gap:12px}.cards.is-rows .card-foot{margin-top:0;padding-top:0;border-top:0;gap:14px}.cards.is-rows .card-fields{display:grid;min-width:0;flex:1;gap:14px;grid-auto-columns:minmax(0,1fr);grid-auto-flow:column}.cards.is-rows .field-label,.cards.is-rows .field-value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NucleusLink, selector: "nucleus-link", inputs: ["route", "queryParams", "href", "hint", "muted"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i2$3.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first", "appendTo"], outputs: ["onPageChange"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i4.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i4.ReorderableRowHandle, selector: "[pReorderableRowHandle]" }, { kind: "directive", type: i4.ReorderableRow, selector: "[pReorderableRow]", inputs: ["pReorderableRow", "pReorderableRowDisabled"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i5$1.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2963
3253
|
}
|
|
2964
3254
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusList, decorators: [{
|
|
2965
3255
|
type: Component,
|
|
2966
|
-
args: [{ selector: 'nucleus-list', imports: [
|
|
2967
|
-
|
|
3256
|
+
args: [{ selector: 'nucleus-list', imports: [
|
|
3257
|
+
NgTemplateOutlet,
|
|
3258
|
+
NucleusLink,
|
|
3259
|
+
CdkDrag,
|
|
3260
|
+
CdkDragHandle,
|
|
3261
|
+
CdkDropList,
|
|
3262
|
+
ButtonModule,
|
|
3263
|
+
PaginatorModule,
|
|
3264
|
+
SkeletonModule,
|
|
3265
|
+
TableModule,
|
|
3266
|
+
TagModule,
|
|
3267
|
+
TooltipModule,
|
|
3268
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"head\">\n <ng-content select=\"[nucleusListTitle]\" />\n <div class=\"head-actions\">\n <ng-content select=\"[nucleusListActions]\" />\n </div>\n</div>\n\n@if (showEmpty()) {\n <div class=\"placeholder\">{{ empty() }}</div>\n} @else {\n <div class=\"bar\">\n @if (searchable()) {\n <label class=\"search\">\n <i class=\"pi pi-search\" aria-hidden=\"true\"></i>\n <input\n type=\"search\"\n [value]=\"term()\"\n [placeholder]=\"copy().search\"\n [attr.aria-label]=\"copy().search\"\n (input)=\"onSearch($event)\"\n />\n </label>\n }\n\n <span class=\"bar-spacer\"></span>\n\n @if (canChooseView()) {\n <span class=\"views\">\n <button\n type=\"button\"\n class=\"view\"\n [class.is-on]=\"view() === 'grid'\"\n [attr.aria-pressed]=\"view() === 'grid'\"\n [attr.aria-label]=\"copy().viewGrid\"\n [pTooltip]=\"copy().viewGrid\"\n tooltipPosition=\"bottom\"\n (click)=\"chooseView('grid')\"\n >\n <i class=\"pi pi-th-large\" aria-hidden=\"true\"></i>\n </button>\n <button\n type=\"button\"\n class=\"view\"\n [class.is-on]=\"view() === 'rows'\"\n [attr.aria-pressed]=\"view() === 'rows'\"\n [attr.aria-label]=\"copy().viewRows\"\n [pTooltip]=\"copy().viewRows\"\n tooltipPosition=\"bottom\"\n (click)=\"chooseView('rows')\"\n >\n <i class=\"pi pi-list\" aria-hidden=\"true\"></i>\n </button>\n </span>\n }\n </div>\n\n @if (compact()) {\n @if (showNoResults()) {\n <div class=\"placeholder\">{{ copy().noResults }}</div>\n }\n\n <div\n class=\"cards\"\n [class.is-rows]=\"view() === 'rows'\"\n cdkDropList\n cdkDropListOrientation=\"mixed\"\n [cdkDropListDisabled]=\"dragLocked()\"\n [cdkDropListSortPredicate]=\"sortAllowed\"\n (cdkDropListDropped)=\"onCardDrop($event)\"\n >\n @if (loading()) {\n @for (item of placeholders(); track $index) {\n <div class=\"card\">\n <div class=\"card-top\">\n <p-skeleton height=\"15px\" width=\"52%\" />\n </div>\n <div class=\"card-foot\">\n <p-skeleton height=\"12px\" width=\"30%\" />\n <p-skeleton height=\"12px\" width=\"30%\" />\n </div>\n </div>\n }\n } @else {\n @for (row of pagedRows(); track $index) {\n <article class=\"card\" [class]=\"rowClass()(row)\" cdkDrag\n [cdkDragData]=\"row\"\n [cdkDragDisabled]=\"dragLocked()\"\n (cdkDragStarted)=\"dragStart.emit(row)\">\n <div class=\"card-top\">\n @if (reorderable()) {\n <button\n type=\"button\"\n class=\"grip\"\n cdkDragHandle\n [disabled]=\"dragLocked()\"\n [attr.aria-label]=\"copy().reorderHandle\"\n >\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </button>\n }\n @if (identityColumn(); as column) {\n <span class=\"card-name\">\n @if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else {\n {{ text(column, row) }}\n }\n </span>\n }\n\n @if (statusColumn(); as column) {\n <span class=\"card-status\">\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n } @else if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else {\n {{ text(column, row) }}\n }\n </span>\n }\n </div>\n\n @if (attributeColumns().length || visibleActions(row).length) {\n <div class=\"card-foot\">\n <div class=\"card-fields\">\n @for (column of attributeColumns(); track column.key) {\n <div class=\"field\">\n <span class=\"field-label\">{{ column.header }}</span>\n <span class=\"field-value\">\n @if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else if (linkOf(column, row); as target) {\n <nucleus-link\n [route]=\"target.route\"\n [queryParams]=\"target.queryParams ?? null\"\n [hint]=\"column.header\"\n >\n {{ text(column, row) }}\n </nucleus-link>\n } @else if (column.kind === 'switch') {\n <button\n type=\"button\"\n class=\"ns-switch\"\n role=\"switch\"\n [class.is-on]=\"isChecked(column, row)\"\n [attr.aria-checked]=\"isChecked(column, row)\"\n [attr.aria-label]=\"column.header\"\n [disabled]=\"isLocked(column, row)\"\n (click)=\"flip(column, row)\"\n >\n <span class=\"knob\"></span>\n </button>\n } @else {\n {{ text(column, row) }}\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n }\n }\n </span>\n </div>\n }\n </div>\n\n @if (visibleActions(row).length) {\n <div class=\"card-actions\">\n @for (entry of visibleActions(row); track entry.id) {\n <p-button\n [icon]=\"entry.icon\"\n [severity]=\"entry.tone === 'danger' ? 'danger' : 'secondary'\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"entry.label\"\n [disabled]=\"isActionLocked(entry, row)\"\n (onClick)=\"run(entry, row)\"\n />\n }\n </div>\n }\n </div>\n }\n </article>\n }\n }\n </div>\n\n @if (paginate()) {\n <div class=\"foot\">\n <p-paginator\n styleClass=\"ns-cards-paginator\"\n [first]=\"page()\"\n [rows]=\"rowsPerPage()\"\n [totalRecords]=\"filtered().length\"\n [rowsPerPageOptions]=\"pageSizes()\"\n (onPageChange)=\"onPage($event)\"\n />\n </div>\n }\n} @else {\n <p-table\n [value]=\"data()\"\n styleClass=\"ns-table\"\n [tableStyle]=\"tableStyle()\"\n [paginator]=\"paginate()\"\n [rows]=\"pageSize()\"\n [rowsPerPageOptions]=\"pageSizes()\"\n [alwaysShowPaginator]=\"true\"\n (onRowReorder)=\"onRowReorder($event)\"\n >\n <ng-template #header>\n <tr>\n @if (reorderable()) {\n <th class=\"grip-head\"></th>\n }\n @for (column of columns(); track column.key) {\n <th [class]=\"'align-' + (column.align ?? 'left')\" [style.width]=\"column.width\">\n {{ column.header }}\n </th>\n }\n @if (actions().length) {\n <th class=\"align-right\"></th>\n }\n </tr>\n </ng-template>\n\n <ng-template #body let-row let-rowIndex=\"rowIndex\">\n @if (loading()) {\n <tr class=\"is-skeleton\">\n @if (reorderable()) {\n <td class=\"grip-cell\"></td>\n }\n @for (column of columns(); track column.key) {\n <td [class]=\"'align-' + (column.align ?? 'left')\">\n <p-skeleton height=\"13px\" [width]=\"skeletonWidth(column)\" />\n </td>\n }\n @if (actions().length) {\n <td class=\"align-right actions\">\n <p-skeleton shape=\"circle\" size=\"26px\" />\n </td>\n }\n </tr>\n } @else {\n <tr\n [class]=\"rowClass()(row)\"\n [pReorderableRow]=\"rowIndex\"\n [pReorderableRowDisabled]=\"dragLocked()\"\n >\n @if (reorderable()) {\n <td class=\"grip-cell\">\n <span class=\"grip\" pReorderableRowHandle [attr.aria-label]=\"copy().reorderHandle\">\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </span>\n </td>\n }\n @for (column of columns(); track column.key) {\n <td [class]=\"'align-' + (column.align ?? 'left')\" [class.strong]=\"column.strong\">\n @if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else if (column.kind === 'switch') {\n <span class=\"switch-cell\">\n <button\n type=\"button\"\n class=\"ns-switch\"\n role=\"switch\"\n [class.is-on]=\"isChecked(column, row)\"\n [attr.aria-checked]=\"isChecked(column, row)\"\n [attr.aria-label]=\"text(column, row)\"\n [disabled]=\"isLocked(column, row)\"\n [pTooltip]=\"hintOf(column, row)\"\n tooltipPosition=\"top\"\n (click)=\"flip(column, row)\"\n >\n <span class=\"knob\"></span>\n </button>\n <span class=\"switch-label\">{{ text(column, row) }}</span>\n </span>\n } @else {\n {{ text(column, row) }}\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n }\n }\n </td>\n }\n\n @if (actions().length) {\n <td class=\"align-right actions\">\n @for (entry of visibleActions(row); track entry.id) {\n <p-button\n [icon]=\"entry.icon\"\n [severity]=\"entry.tone === 'danger' ? 'danger' : 'secondary'\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [pTooltip]=\"entry.label\"\n tooltipPosition=\"left\"\n [ariaLabel]=\"entry.label\"\n [disabled]=\"isActionLocked(entry, row)\"\n (onClick)=\"run(entry, row)\"\n />\n }\n </td>\n }\n </tr>\n }\n </ng-template>\n </p-table>\n}\n}\n", styles: [":host{display:block}.head{display:flex;align-items:center;justify-content:space-between;gap:12px}.head:has(>*:not(.head-actions)),.head:has(.head-actions>*){min-height:34px;margin-bottom:12px}.head-actions{display:flex;gap:8px}.placeholder{padding:26px;border:1px dashed var(--ac-border);border-radius:10px;color:var(--ac-text-muted);font-size:14px}.align-left{text-align:left}.align-center{text-align:center}.align-right{text-align:right}.strong{font-weight:600}.actions{white-space:nowrap}.switch-cell{display:inline-flex;align-items:center;gap:10px}.switch-label{color:var(--ac-text-muted);font-size:12px}.ns-switch{position:relative;width:38px;height:22px;flex:none;padding:0;border:1px solid var(--ac-border);border-radius:var(--ac-radius-pill);background:color-mix(in srgb,var(--ac-text) 10%,transparent);cursor:pointer;transition:background .14s ease,border-color .14s ease}.ns-switch .knob{position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--ac-text);transition:transform .14s ease}.ns-switch.is-on{border-color:var(--ac-accent);background:var(--ac-accent)}.ns-switch.is-on .knob{background:var(--ac-on-accent);transform:translate(16px)}.ns-switch:disabled{cursor:not-allowed;opacity:.45}.ns-switch:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}.cards{display:grid;gap:12px;grid-template-columns:repeat(auto-fill,minmax(320px,1fr))}.card{padding:13px 14px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.card-top{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.card-name{display:flex;min-width:0;flex:1;align-items:center;gap:10px;font-size:15px;font-weight:600;line-height:1.3}.card-status{flex:none}.card-foot{display:flex;align-items:flex-end;gap:12px;margin-top:11px;padding-top:11px;border-top:1px solid var(--ac-border)}.card-fields{display:flex;min-width:0;flex:1;flex-wrap:wrap;gap:10px 20px}.card-actions{display:flex;flex:none;align-items:center;gap:2px}.field{display:flex;min-width:0;flex-direction:column;gap:2px}.field-label{color:var(--ac-text-muted);font-size:10px;font-weight:600;letter-spacing:.07em;text-transform:uppercase}.field-value{display:flex;align-items:center;gap:8px;font-size:15px;font-weight:600;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}::ng-deep .ns-cards-paginator{background:transparent}.grip{display:inline-grid;width:26px;height:26px;flex:none;padding:0;border:0;border-radius:4px;background:transparent;color:var(--ac-text-muted);cursor:grab;place-items:center;touch-action:none}.grip:hover{background:color-mix(in srgb,var(--ac-text) 8%,transparent);color:var(--ac-text)}.grip:active{cursor:grabbing}.grip:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}.grip .pi{font-size:13px}.grip-head,.grip-cell{width:38px;padding-right:0!important}.cdk-drag-preview{border:1px solid var(--ac-accent);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-2);opacity:.96}.cdk-drag-placeholder{border:1px dashed var(--ac-border);background:color-mix(in srgb,var(--ac-text) 4%,transparent);opacity:.6}.cdk-drag-placeholder *{visibility:hidden}.cards.cdk-drop-list-dragging .card:not(.cdk-drag-placeholder){transition:transform .18s cubic-bezier(0,0,.2,1)}.cdk-drag-animating{transition:transform .22s cubic-bezier(0,0,.2,1)}.bar{display:flex;align-items:center;gap:10px;margin-bottom:12px;padding:7px 10px;border:1px solid var(--ac-border);border-radius:10px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.bar-spacer{flex:1}.search{display:flex;min-width:0;max-width:340px;flex:1 1 220px;align-items:center;gap:8px;padding:5px 10px;border:1px solid var(--ac-border);border-radius:6px;background:color-mix(in srgb,var(--ac-text) 4%,transparent);color:var(--ac-text-muted)}.search:focus-within{border-color:var(--ac-accent);color:var(--ac-text)}.search .pi{font-size:13px}.search input{min-width:0;flex:1;padding:0;border:0;background:transparent;color:var(--ac-text);font:inherit;font-size:13px;outline:none}.search input::-webkit-search-cancel-button{filter:grayscale(1) opacity(.6)}.views{display:inline-flex;flex:none;padding:2px;border:1px solid var(--ac-border);border-radius:7px}.view{display:grid;width:30px;height:28px;padding:0;border:0;border-radius:5px;background:transparent;color:var(--ac-text-muted);cursor:pointer;place-items:center}.view:hover{color:var(--ac-text)}.view.is-on{background:color-mix(in srgb,var(--ac-accent) 18%,transparent);color:var(--ac-accent)}.view:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}.view .pi{font-size:14px}.foot{margin-top:12px;padding:4px 6px;border:1px solid var(--ac-border);border-radius:10px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}@media(min-width:721px){.cards.is-rows{gap:8px;grid-template-columns:minmax(0,1fr)}.cards.is-rows .card{display:grid;align-items:center;gap:18px;grid-template-columns:minmax(0,2fr) minmax(0,3fr);padding:9px 14px}.cards.is-rows .card-top{min-width:0;align-items:center;gap:12px}.cards.is-rows .card-foot{margin-top:0;padding-top:0;border-top:0;gap:14px}.cards.is-rows .card-fields{display:grid;min-width:0;flex:1;gap:14px;grid-auto-columns:minmax(0,1fr);grid-auto-flow:column}.cards.is-rows .field-label,.cards.is-rows .field-value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}}\n"] }]
|
|
3269
|
+
}], propDecorators: { rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], empty: [{ type: i0.Input, args: [{ isSignal: true, alias: "empty", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], minWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "minWidth", required: false }] }], skeletonRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "skeletonRows", required: false }] }], rowClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowClass", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], pageSizes: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizes", required: false }] }], cards: [{ type: i0.Input, args: [{ isSignal: true, alias: "cards", required: false }] }], reorderable: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderable", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], reorderGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderGroup", required: false }] }], action: [{ type: i0.Output, args: ["action"] }], reorder: [{ type: i0.Output, args: ["reorder"] }], dragStart: [{ type: i0.Output, args: ["dragStart"] }], toggle: [{ type: i0.Output, args: ["toggle"] }], cells: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => NucleusCell), { isSignal: true }] }] } });
|
|
2968
3270
|
|
|
2969
3271
|
function toggleCollapsed(collapsed, id) {
|
|
2970
3272
|
const next = new Set(collapsed);
|
|
@@ -3108,25 +3410,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
3108
3410
|
args: [{ selector: 'nucleus-appearance', changeDetection: ChangeDetectionStrategy.OnPush, template: "@let t = copy();\n@let current = appearance();\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.frameTitle }}</h3>\n <p class=\"group-hint\">{{ t.frameHint }}</p>\n\n <div class=\"frames\" role=\"radiogroup\" [attr.aria-label]=\"t.frameTitle\">\n @for (frame of frames(); track frame.id) {\n <button\n type=\"button\"\n class=\"frame\"\n role=\"radio\"\n [class.is-active]=\"frame.id === current.frame\"\n [attr.aria-checked]=\"frame.id === current.frame\"\n [attr.aria-label]=\"frame.label\"\n [style.--f-bg]=\"frame.tokens.bg\"\n [style.--f-raised]=\"frame.tokens.raised\"\n [style.--f-ink]=\"frame.tokens.ink\"\n [style.--f-muted]=\"frame.tokens.muted\"\n [style.--f-line]=\"frame.tokens.line\"\n [style.--f-glow]=\"frame.tokens.glow\"\n (click)=\"pickFrame(frame.id)\"\n >\n <span class=\"frame-chip\" aria-hidden=\"true\">\n <span class=\"frame-bar\">\n <span class=\"frame-dot\"></span>\n </span>\n <span class=\"frame-lower\">\n <span class=\"frame-rail\">\n <span class=\"frame-pin\"></span>\n <span class=\"frame-row is-on\"></span>\n <span class=\"frame-row\"></span>\n <span class=\"frame-row\"></span>\n </span>\n <span class=\"frame-canvas\"></span>\n </span>\n </span>\n <span class=\"frame-name\">{{ frame.label }}</span>\n </button>\n }\n </div>\n</section>\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.canvasTitle }}</h3>\n <p class=\"group-hint\">{{ t.canvasHint }}</p>\n\n <div class=\"canvases\" role=\"radiogroup\" [attr.aria-label]=\"t.canvasTitle\">\n @for (canvas of canvases(); track canvas.id) {\n <button\n type=\"button\"\n class=\"canvas\"\n role=\"radio\"\n [class.is-active]=\"canvas.id === current.canvas\"\n [attr.aria-checked]=\"canvas.id === current.canvas\"\n (click)=\"pickCanvas(canvas.id)\"\n >\n <span\n class=\"canvas-chip\"\n aria-hidden=\"true\"\n [style.background]=\"canvas.bg\"\n [style.color]=\"canvas.text\"\n >\n @if (canvas.icon) {\n <i [class]=\"canvas.icon\"></i>\n } @else {\n <span class=\"canvas-sheet\" [style.background]=\"canvas.surface\"></span>\n }\n </span>\n <span class=\"canvas-name\">{{ canvas.label }}</span>\n </button>\n }\n </div>\n</section>\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.accentTitle }}</h3>\n <p class=\"group-hint\">{{ t.accentHint }}</p>\n\n <div class=\"accents\" role=\"radiogroup\" [attr.aria-label]=\"t.accentTitle\">\n @for (accent of accents(); track accent.id) {\n <button\n type=\"button\"\n class=\"accent\"\n role=\"radio\"\n [class.is-auto]=\"accent.id === 'auto'\"\n [class.is-active]=\"accent.id === current.accent\"\n [attr.aria-checked]=\"accent.id === current.accent\"\n [attr.aria-label]=\"accent.label\"\n [title]=\"accent.label\"\n [style.background]=\"accent.color\"\n [style.color]=\"accent.ink\"\n (click)=\"pickAccent(accent.id)\"\n >\n @if (accent.id === current.accent) {\n <i class=\"pi pi-check\" aria-hidden=\"true\"></i>\n } @else if (accent.id === 'auto') {\n <i class=\"pi pi-sparkles\" aria-hidden=\"true\"></i>\n }\n </button>\n }\n </div>\n</section>\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.densityTitle }}</h3>\n <p class=\"group-hint\">{{ t.densityHint }}</p>\n\n <div class=\"densities\" role=\"radiogroup\" [attr.aria-label]=\"t.densityTitle\">\n @for (density of densities(); track density.id) {\n <button\n type=\"button\"\n class=\"density\"\n role=\"radio\"\n [class.is-active]=\"density.id === current.density\"\n [attr.aria-checked]=\"density.id === current.density\"\n (click)=\"pickDensity(density.id)\"\n >\n <span class=\"density-chip\" aria-hidden=\"true\" [style.gap.px]=\"density.gap\">\n <span class=\"density-row\"></span>\n <span class=\"density-row\"></span>\n <span class=\"density-row\"></span>\n </span>\n <span class=\"density-name\">{{ density.label }}</span>\n </button>\n }\n </div>\n</section>\n", styles: [":host{display:flex;flex-direction:column;gap:26px}.group{display:flex;flex-direction:column;gap:2px}.group-title{margin:0;font-size:13px;font-weight:600;letter-spacing:.02em}.group-hint{margin:0 0 12px;color:var(--ac-text-muted);font-size:12px;font-weight:300;line-height:1.45}.frames{display:grid;grid-template-columns:repeat(auto-fill,minmax(84px,1fr));gap:10px}.frame{display:flex;flex-direction:column;gap:6px;padding:4px;border:2px solid transparent;border-radius:10px;background:transparent;color:var(--ac-text-muted);cursor:pointer}.frame:hover{color:var(--ac-text)}.frame.is-active{border-color:var(--ac-accent);color:var(--ac-text)}.frame-chip{display:flex;overflow:hidden;flex-direction:column;height:52px;border:1px solid var(--f-line);border-radius:6px;background:var(--f-bg)}.frame-bar{display:flex;flex:none;align-items:center;height:12px;padding-left:5px;border-bottom:1px solid var(--f-line)}.frame-dot{width:5px;height:5px;border-radius:50%;background:var(--f-glow)}.frame-lower{display:flex;flex:1;min-height:0}.frame-rail{display:flex;flex:none;flex-direction:column;gap:3px;width:22px;padding:4px 3px;border-right:1px solid var(--f-line)}.frame-pin{height:7px;border-left:2px solid var(--f-glow);border-radius:2px;background:var(--f-raised)}.frame-row{height:3px;border-radius:2px;background:var(--f-muted);opacity:.55}.frame-row.is-on{background:var(--f-glow);opacity:1}.frame-canvas{flex:1;background:var(--ac-bg)}.frame-name{overflow:hidden;font-size:11px;font-weight:500;text-align:center;text-overflow:ellipsis;white-space:nowrap}.canvases{display:grid;grid-template-columns:repeat(auto-fit,minmax(70px,1fr));gap:8px}.canvas{display:flex;flex-direction:column;gap:6px;padding:4px;border:2px solid transparent;border-radius:10px;background:transparent;color:var(--ac-text-muted);cursor:pointer}.canvas:hover{color:var(--ac-text)}.canvas.is-active{border-color:var(--ac-accent);color:var(--ac-text)}.canvas-chip{display:flex;align-items:center;justify-content:center;height:40px;border:1px solid var(--ac-border);border-radius:6px}.canvas-chip i{font-size:15px}.canvas-sheet{width:60%;height:58%;border-radius:3px;box-shadow:0 1px 4px #00000038}.canvas-name{font-size:11px;font-weight:500;text-align:center}.accents{display:flex;flex-wrap:wrap;gap:9px}.accent{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:2px solid transparent;border-radius:50%;cursor:pointer;transition:transform .12s ease}.accent:hover{transform:scale(1.12)}.accent.is-auto{border-style:dashed;border-color:var(--ac-border)}.accent.is-active{border-style:solid;border-color:var(--ac-text);box-shadow:0 0 0 2px var(--ac-surface) inset}.accent i{font-size:11px}.densities{display:flex;gap:10px}.density{display:flex;flex:1;flex-direction:column;gap:6px;padding:4px;border:2px solid transparent;border-radius:10px;background:transparent;color:var(--ac-text-muted);cursor:pointer}.density:hover{color:var(--ac-text)}.density.is-active{border-color:var(--ac-accent);color:var(--ac-text)}.density-chip{display:flex;flex-direction:column;justify-content:center;height:42px;padding:0 10px;border:1px solid var(--ac-border);border-radius:6px;background:var(--ac-surface)}.density-row{height:3px;border-radius:2px;background:var(--ac-text-muted);opacity:.5}.density-name{font-size:11px;font-weight:500;text-align:center}@media(prefers-reduced-motion:reduce){.accent{transition:none}}\n"] }]
|
|
3109
3411
|
}] });
|
|
3110
3412
|
|
|
3111
|
-
function menuTile(label, icon, color) {
|
|
3112
|
-
return { label, icon, color, ink: color ? readableOn(color) : null, ghost: false };
|
|
3113
|
-
}
|
|
3114
|
-
function menuGlyph(icon) {
|
|
3115
|
-
return { label: '', icon, color: null, ink: null, ghost: true };
|
|
3116
|
-
}
|
|
3117
|
-
function foldText(value) {
|
|
3118
|
-
return value
|
|
3119
|
-
.normalize('NFD')
|
|
3120
|
-
.replace(/[̀-ͯ]/g, '')
|
|
3121
|
-
.toLowerCase();
|
|
3122
|
-
}
|
|
3123
|
-
function matchesRow(row, term) {
|
|
3124
|
-
return foldText(row.name).includes(term) || foldText(row.meta ?? '').includes(term);
|
|
3125
|
-
}
|
|
3126
|
-
function selectableRows(sections) {
|
|
3127
|
-
return sections.flatMap((section) => section.rows).filter((row) => !row.disabled && !row.current);
|
|
3128
|
-
}
|
|
3129
|
-
|
|
3130
3413
|
class NucleusMenu {
|
|
3131
3414
|
sections = input([], ...(ngDevMode ? [{ debugName: "sections" }] : /* istanbul ignore next */ []));
|
|
3132
3415
|
heading = input('', ...(ngDevMode ? [{ debugName: "heading" }] : /* istanbul ignore next */ []));
|
|
@@ -3384,6 +3667,7 @@ const SHELL_COPY = {
|
|
|
3384
3667
|
signOut: 'Cerrar sesión',
|
|
3385
3668
|
accountManage: 'Gestionar mi cuenta',
|
|
3386
3669
|
accountSwitch: 'Cambiar de cuenta',
|
|
3670
|
+
homeLabel: 'Inicio',
|
|
3387
3671
|
accessLoading: 'Cargando accesos...',
|
|
3388
3672
|
accessEmpty: 'Sin accesos asignados',
|
|
3389
3673
|
accountScope: 'Mi cuenta',
|
|
@@ -3420,6 +3704,7 @@ const SHELL_COPY = {
|
|
|
3420
3704
|
signOut: 'Sign out',
|
|
3421
3705
|
accountManage: 'Manage my account',
|
|
3422
3706
|
accountSwitch: 'Switch account',
|
|
3707
|
+
homeLabel: 'Home',
|
|
3423
3708
|
accessLoading: 'Loading access...',
|
|
3424
3709
|
accessEmpty: 'No access granted',
|
|
3425
3710
|
accountScope: 'My account',
|
|
@@ -3443,6 +3728,7 @@ const SHELL_COPY = {
|
|
|
3443
3728
|
const LAUNCHER_RICH_THRESHOLD = 6;
|
|
3444
3729
|
const RECENT_LIMIT = 3;
|
|
3445
3730
|
const FALLBACK_APP_COLOR = '#64748b';
|
|
3731
|
+
const HOME_MENU_ID = 'nucleus-home';
|
|
3446
3732
|
class NucleusShell {
|
|
3447
3733
|
session = inject(SessionService);
|
|
3448
3734
|
sessionAuth = inject(NucleusSessionAuth);
|
|
@@ -3465,14 +3751,26 @@ class NucleusShell {
|
|
|
3465
3751
|
menuPlaceholders = ['64%', '80%', '52%', '72%', '58%'];
|
|
3466
3752
|
title = computed(() => this.heading() || this.page.heading(), ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
3467
3753
|
pageActions = this.page.actions;
|
|
3468
|
-
home = computed(() => ({
|
|
3754
|
+
home = computed(() => ({
|
|
3755
|
+
icon: 'pi pi-home',
|
|
3756
|
+
routerLink: this.homeRoute,
|
|
3757
|
+
}), ...(ngDevMode ? [{ debugName: "home" }] : /* istanbul ignore next */ []));
|
|
3469
3758
|
crumbs = computed(() => this.page.crumbs().map((crumb) => ({
|
|
3470
3759
|
label: crumb.label,
|
|
3471
3760
|
routerLink: crumb.route ? [...crumb.route] : undefined,
|
|
3472
3761
|
})), ...(ngDevMode ? [{ debugName: "crumbs" }] : /* istanbul ignore next */ []));
|
|
3473
3762
|
copy = computed(() => SHELL_COPY[this.lang()], ...(ngDevMode ? [{ debugName: "copy" }] : /* istanbul ignore next */ []));
|
|
3474
3763
|
starfield = this.themes.starfield;
|
|
3475
|
-
|
|
3764
|
+
homeRoute = normalizeHomeRoute(inject(NUCLEUS_HOME));
|
|
3765
|
+
currentUrl = signal(this.router.url, ...(ngDevMode ? [{ debugName: "currentUrl" }] : /* istanbul ignore next */ []));
|
|
3766
|
+
menu = computed(() => {
|
|
3767
|
+
const nodes = this.session.menu();
|
|
3768
|
+
if (!nodes.length && !this.session.me())
|
|
3769
|
+
return nodes;
|
|
3770
|
+
if (hasRoute(nodes, this.homeRoute))
|
|
3771
|
+
return nodes;
|
|
3772
|
+
return [homeNode(this.homeRoute, this.copy().homeLabel), ...nodes];
|
|
3773
|
+
}, ...(ngDevMode ? [{ debugName: "menu" }] : /* istanbul ignore next */ []));
|
|
3476
3774
|
collapsedIds = signal(new Set(), ...(ngDevMode ? [{ debugName: "collapsedIds" }] : /* istanbul ignore next */ []));
|
|
3477
3775
|
menuLoading = this.session.loading;
|
|
3478
3776
|
menuError = this.session.error;
|
|
@@ -3612,6 +3910,22 @@ class NucleusShell {
|
|
|
3612
3910
|
this.siteOptions.set([]);
|
|
3613
3911
|
});
|
|
3614
3912
|
}, ...(ngDevMode ? [{ debugName: "syncContext" }] : /* istanbul ignore next */ []));
|
|
3913
|
+
lastUid = null;
|
|
3914
|
+
watchIdentity = effect(() => {
|
|
3915
|
+
const uid = this.auth?.user()?.uid ?? null;
|
|
3916
|
+
untracked(() => {
|
|
3917
|
+
if (!uid)
|
|
3918
|
+
return;
|
|
3919
|
+
if (this.lastUid === null) {
|
|
3920
|
+
this.lastUid = uid;
|
|
3921
|
+
return;
|
|
3922
|
+
}
|
|
3923
|
+
if (this.lastUid === uid)
|
|
3924
|
+
return;
|
|
3925
|
+
this.lastUid = uid;
|
|
3926
|
+
this.goHome();
|
|
3927
|
+
});
|
|
3928
|
+
}, ...(ngDevMode ? [{ debugName: "watchIdentity" }] : /* istanbul ignore next */ []));
|
|
3615
3929
|
loadSession = effect(() => {
|
|
3616
3930
|
const language = this.lang();
|
|
3617
3931
|
const user = this.auth?.user() ?? null;
|
|
@@ -3620,6 +3934,12 @@ class NucleusShell {
|
|
|
3620
3934
|
untracked(() => void this.session.load(language));
|
|
3621
3935
|
}, ...(ngDevMode ? [{ debugName: "loadSession" }] : /* istanbul ignore next */ []));
|
|
3622
3936
|
constructor() {
|
|
3937
|
+
const destroyRef = inject(DestroyRef);
|
|
3938
|
+
const navigation = this.router.events.subscribe((event) => {
|
|
3939
|
+
if (event instanceof NavigationEnd)
|
|
3940
|
+
this.currentUrl.set(event.urlAfterRedirects);
|
|
3941
|
+
});
|
|
3942
|
+
destroyRef.onDestroy(() => navigation.unsubscribe());
|
|
3623
3943
|
const query = this.narrowQuery;
|
|
3624
3944
|
if (!query)
|
|
3625
3945
|
return;
|
|
@@ -3628,7 +3948,7 @@ class NucleusShell {
|
|
|
3628
3948
|
this.sidebarOpen.set(!event.matches);
|
|
3629
3949
|
};
|
|
3630
3950
|
query.addEventListener('change', onChange);
|
|
3631
|
-
|
|
3951
|
+
destroyRef.onDestroy(() => query.removeEventListener('change', onChange));
|
|
3632
3952
|
}
|
|
3633
3953
|
setLang(lang) {
|
|
3634
3954
|
this.language.setLang(lang);
|
|
@@ -3667,6 +3987,8 @@ class NucleusShell {
|
|
|
3667
3987
|
this.sidebarOpen.set(false);
|
|
3668
3988
|
}
|
|
3669
3989
|
isSelected(node) {
|
|
3990
|
+
if (node.id === HOME_MENU_ID)
|
|
3991
|
+
return isHomeRoute(this.homeRoute, this.currentUrl());
|
|
3670
3992
|
return this.selectedMenuId() === node.id;
|
|
3671
3993
|
}
|
|
3672
3994
|
async onCompanyChange(companyId) {
|
|
@@ -3677,8 +3999,10 @@ class NucleusShell {
|
|
|
3677
3999
|
const sites = await this.loadSites(companyId);
|
|
3678
4000
|
const first = sites[0]?.id ?? null;
|
|
3679
4001
|
this.siteChoice.set(first);
|
|
3680
|
-
if (first)
|
|
4002
|
+
if (first) {
|
|
3681
4003
|
await this.session.switchContext(companyId, first);
|
|
4004
|
+
this.goHome();
|
|
4005
|
+
}
|
|
3682
4006
|
}
|
|
3683
4007
|
async onSiteChange(siteId) {
|
|
3684
4008
|
const companyId = this.companyChoice();
|
|
@@ -3686,6 +4010,12 @@ class NucleusShell {
|
|
|
3686
4010
|
return;
|
|
3687
4011
|
this.siteChoice.set(siteId);
|
|
3688
4012
|
await this.session.switchContext(companyId, siteId);
|
|
4013
|
+
this.goHome();
|
|
4014
|
+
}
|
|
4015
|
+
goHome() {
|
|
4016
|
+
if (isHomeRoute(this.homeRoute, this.router.url))
|
|
4017
|
+
return;
|
|
4018
|
+
void this.router.navigateByUrl(this.homeRoute);
|
|
3689
4019
|
}
|
|
3690
4020
|
appRow(app, current) {
|
|
3691
4021
|
const hint = current ? this.copy().appsHere : this.launchHint(app);
|
|
@@ -3767,7 +4097,7 @@ class NucleusShell {
|
|
|
3767
4097
|
}
|
|
3768
4098
|
}
|
|
3769
4099
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusShell, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3770
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: NucleusShell, isStandalone: true, selector: "nucleus-shell", inputs: { brand: { classPropertyName: "brand", publicName: "brand", isSignal: true, isRequired: false, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, navItems: { classPropertyName: "navItems", publicName: "navItems", isSignal: true, isRequired: false, transformFunction: null }, activeNavId: { classPropertyName: "activeNavId", publicName: "activeNavId", isSignal: true, isRequired: false, transformFunction: null }, selectedMenuId: { classPropertyName: "selectedMenuId", publicName: "selectedMenuId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { navSelect: "navSelect", menuSelect: "menuSelect" }, host: { properties: { "style.--ns-topbar-h": "topbarHeight()" } }, ngImport: i0, template: "@let t = copy();\n@let me = identity();\n\n@if (starfield()) {\n <nucleus-starfield />\n}\n\n<header class=\"topbar ns-frame\">\n <div class=\"side\">\n <p-button\n icon=\"pi pi-bars\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.navToggle\"\n [pTooltip]=\"t.navToggle\"\n tooltipPosition=\"bottom\"\n (onClick)=\"toggleSidebar()\"\n />\n\n <div class=\"brand\">\n <nucleus-mark [size]=\"20\" />\n <div class=\"brand-name\">\n <span class=\"brand-primary\">NUCLEUS</span>\n <span class=\"brand-secondary\">{{ brand() }}</span>\n </div>\n </div>\n\n </div>\n\n @if (hasSiteContext()) {\n <div class=\"context ns-context\">\n <p-select\n styleClass=\"context-select\"\n [options]=\"companyChoices()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"companyChoice()\"\n (ngModelChange)=\"onCompanyChange($event)\"\n [placeholder]=\"t.companyPlaceholder\"\n [disabled]=\"switching()\"\n [filter]=\"companyChoices().length > 8\"\n filterBy=\"name\"\n [filterPlaceholder]=\"words().search\"\n [autofocusFilter]=\"true\"\n [resetFilterOnHide]=\"true\"\n [ariaLabel]=\"t.companyLabel\"\n [ngModelOptions]=\"{ standalone: true }\"\n >\n <ng-template #item let-option>\n <span class=\"company-option\">\n <span class=\"company-name\">{{ option.name }}</span>\n <p-tag [value]=\"option.tag\" severity=\"secondary\" />\n </span>\n </ng-template>\n </p-select>\n\n <p-select\n styleClass=\"context-select\"\n [options]=\"siteOptions()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"siteChoice()\"\n (ngModelChange)=\"onSiteChange($event)\"\n [placeholder]=\"sitePlaceholder()\"\n [disabled]=\"switching() || sitesLoading() || !siteOptions().length\"\n [filter]=\"siteOptions().length > 8\"\n filterBy=\"name\"\n [filterPlaceholder]=\"words().search\"\n [autofocusFilter]=\"true\"\n [resetFilterOnHide]=\"true\"\n [ariaLabel]=\"t.siteLabel\"\n [ngModelOptions]=\"{ standalone: true }\"\n />\n </div>\n }\n\n <div class=\"side is-end\">\n <div class=\"lang-switch\" role=\"group\" aria-label=\"Idioma / Language\">\n <button\n type=\"button\"\n class=\"lang-pill\"\n [class.is-active]=\"lang() === 'es'\"\n [attr.aria-pressed]=\"lang() === 'es'\"\n (click)=\"setLang('es')\"\n >\n ES\n </button>\n <button\n type=\"button\"\n class=\"lang-pill\"\n [class.is-active]=\"lang() === 'en'\"\n [attr.aria-pressed]=\"lang() === 'en'\"\n (click)=\"setLang('en')\"\n >\n EN\n </button>\n </div>\n\n <p-button\n icon=\"pi pi-th-large\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.appsLauncher\"\n [pTooltip]=\"t.appsLauncher\"\n tooltipPosition=\"bottom\"\n (onClick)=\"launcher.toggle($event)\"\n />\n\n <p-popover #launcher styleClass=\"ns-flush-popover\">\n @if (!hasCompany()) {\n <div class=\"launcher-notice\">\n <i class=\"pi pi-building\" aria-hidden=\"true\"></i>\n <div>\n <p class=\"launcher-notice-title\">{{ t.noCompanyTitle }}</p>\n <p class=\"launcher-notice-body\">{{ t.noCompanyHint }}</p>\n </div>\n </div>\n }\n\n <nucleus-menu\n [heading]=\"t.appsSwitch\"\n [badge]=\"launcherCount()\"\n [sections]=\"launcherSections()\"\n [searchable]=\"launcherRich()\"\n [searchPlaceholder]=\"t.appsSearch\"\n [emptyText]=\"launcherRich() ? t.appsNoMatch : t.appsEmpty\"\n [keyboardHint]=\"t.keyboardHint\"\n [width]=\"336\"\n (select)=\"onLauncherSelect($event); launcher.hide()\"\n (dismiss)=\"launcher.hide()\"\n />\n </p-popover>\n\n <p-button\n icon=\"pi pi-cog\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.settingsTitle\"\n [pTooltip]=\"t.settingsTitle\"\n tooltipPosition=\"bottom\"\n (onClick)=\"settingsOpen.set(true)\"\n />\n\n @if (me) {\n <p-button\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n styleClass=\"avatar-trigger\"\n [ariaLabel]=\"me.name\"\n [pTooltip]=\"me.name\"\n tooltipPosition=\"bottom\"\n (onClick)=\"account.toggle($event)\"\n >\n <p-avatar\n [image]=\"me.photoUrl ?? undefined\"\n [label]=\"me.photoUrl ? undefined : initials()\"\n shape=\"circle\"\n size=\"normal\"\n />\n </p-button>\n }\n </div>\n</header>\n\n<p-popover #account styleClass=\"ns-flush-popover\">\n @if (me) {\n <div class=\"who\">\n @if (me.photoUrl) {\n <img class=\"who-photo\" [src]=\"me.photoUrl\" alt=\"\" width=\"42\" height=\"42\" />\n } @else {\n <span class=\"who-photo who-initials\">{{ initials() }}</span>\n }\n <span class=\"who-text\">\n <span class=\"who-name\">{{ me.name }}</span>\n <span class=\"who-mail\">{{ me.email }}</span>\n </span>\n </div>\n\n <p class=\"who-role\">\n <span class=\"who-dot\" aria-hidden=\"true\"></span>\n @if (roleName(); as role) {\n <b>{{ role }}</b>\n <span class=\"who-sep\">\u00B7</span>\n }\n <span class=\"who-context\">{{ accountContext() }}</span>\n </p>\n\n <nucleus-menu\n [sections]=\"accountSections()\"\n [width]=\"304\"\n (select)=\"onAccountSelect($event); account.hide()\"\n (dismiss)=\"account.hide()\"\n />\n }\n</p-popover>\n\n<div class=\"body\">\n @if (narrow() && sidebarOpen()) {\n <button\n type=\"button\"\n class=\"sidebar-scrim\"\n [attr.aria-label]=\"t.navToggle\"\n (click)=\"toggleSidebar()\"\n ></button>\n }\n\n <aside class=\"sidebar ns-frame\" [class.is-collapsed]=\"!sidebarOpen()\">\n @if (roleName(); as role) {\n <div class=\"role-badge\" [pTooltip]=\"sidebarOpen() ? '' : role\" tooltipPosition=\"right\">\n <i class=\"pi pi-key\" aria-hidden=\"true\"></i>\n <span class=\"nav-label role-text\">\n <span class=\"role-name\">{{ role }}</span>\n <span class=\"role-caption\">{{ t.roleCaption }}</span>\n </span>\n </div>\n }\n\n @if (navItems().length) {\n <nav>\n @for (item of navItems(); track item.id) {\n <button\n type=\"button\"\n class=\"nav-item\"\n [class.is-active]=\"activeNavId() === item.id\"\n [attr.aria-current]=\"activeNavId() === item.id ? 'page' : null\"\n [pTooltip]=\"sidebarOpen() ? '' : item.label\"\n tooltipPosition=\"right\"\n (click)=\"selectNav(item.id)\"\n >\n <i [class]=\"item.icon\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ item.label }}</span>\n </button>\n }\n </nav>\n }\n\n <nav class=\"access-menu\">\n @if (menuLoading()) {\n <div class=\"nav-skeleton\" role=\"status\" [attr.aria-label]=\"t.accessLoading\">\n @for (width of menuPlaceholders; track $index) {\n <div class=\"nav-skeleton-item\">\n <p-skeleton shape=\"circle\" size=\"15px\" />\n <p-skeleton height=\"9px\" [width]=\"width\" />\n </div>\n }\n </div>\n } @else if (menuError()) {\n <p class=\"access-state is-error\">{{ menuError() }}</p>\n } @else if (!menu().length) {\n <p class=\"access-state\">{{ t.accessEmpty }}</p>\n } @else {\n @for (node of menu(); track node.id) {\n @let group = isGroup(node);\n @let open = isExpanded(node);\n\n <button\n type=\"button\"\n class=\"nav-item\"\n [class.is-active]=\"!group && isSelected(node)\"\n [class.is-inert]=\"!group && !node.route\"\n [attr.aria-expanded]=\"group ? open : null\"\n [disabled]=\"!group && !node.route\"\n [pTooltip]=\"sidebarOpen() ? '' : node.label\"\n tooltipPosition=\"right\"\n (click)=\"selectMenu(node)\"\n >\n <i [class]=\"node.icon ?? 'pi pi-circle'\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ node.label }}</span>\n @if (group && sidebarOpen()) {\n <i\n class=\"pi nav-caret\"\n [class.pi-chevron-down]=\"open\"\n [class.pi-chevron-right]=\"!open\"\n aria-hidden=\"true\"\n ></i>\n }\n </button>\n\n @if (open) {\n @for (child of node.children; track child.id) {\n <button\n type=\"button\"\n class=\"nav-item is-child\"\n [class.is-active]=\"isSelected(child)\"\n [pTooltip]=\"sidebarOpen() ? '' : child.label\"\n tooltipPosition=\"right\"\n (click)=\"selectMenu(child)\"\n >\n <i [class]=\"child.icon ?? 'pi pi-circle'\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ child.label }}</span>\n </button>\n }\n }\n }\n }\n </nav>\n </aside>\n\n <main class=\"content\">\n <div class=\"measure\">\n <ng-content select=\"[nucleusTop]\" />\n\n @if (crumbs().length || title() || pageActions()) {\n <header class=\"page-head\">\n <div class=\"page-head-main\">\n @if (crumbs().length) {\n <p-breadcrumb [model]=\"crumbs()\" [home]=\"home()\" styleClass=\"ns-crumbs\" />\n }\n\n @if (title()) {\n <h1>{{ title() }}</h1>\n }\n </div>\n\n @if (pageActions(); as actions) {\n <div class=\"page-head-actions\">\n <ng-container [ngTemplateOutlet]=\"actions\" />\n </div>\n }\n </header>\n }\n\n <ng-content />\n </div>\n </main>\n</div>\n\n<p-drawer\n [visible]=\"settingsOpen()\"\n (visibleChange)=\"settingsOpen.set($event)\"\n position=\"right\"\n [header]=\"t.settingsTitle\"\n [modal]=\"false\"\n [blockScroll]=\"false\"\n styleClass=\"ns-settings-drawer\"\n [style]=\"{ width: '380px' }\"\n>\n <nucleus-appearance />\n</p-drawer>\n\n<p-toast position=\"bottom-right\" styleClass=\"ns-toast\">\n <ng-template #message let-message>\n <nucleus-lordicon\n [src]=\"message.severity === 'success' ? icons.check : icons.warning\"\n [tone]=\"message.severity === 'success' ? 'accent' : 'danger'\"\n [size]=\"34\"\n trigger=\"in\"\n />\n <div class=\"toast-text\">\n <p class=\"toast-summary\">{{ message.summary }}</p>\n @if (message.detail) {\n <p class=\"toast-detail\">{{ message.detail }}</p>\n }\n </div>\n </ng-template>\n</p-toast>\n\n<p-confirmdialog [style]=\"{ width: '420px' }\">\n <ng-template #headless let-message let-onAccept=\"onAccept\" let-onReject=\"onReject\">\n <div class=\"confirm\">\n <nucleus-lordicon\n [src]=\"message.icon\"\n [tone]=\"message.acceptButtonStyleClass ? 'danger' : 'accent'\"\n [size]=\"64\"\n trigger=\"loop\"\n />\n <h2>{{ message.header }}</h2>\n <p>{{ message.message }}</p>\n <div class=\"confirm-actions\">\n <p-button\n [label]=\"message.rejectLabel\"\n severity=\"secondary\"\n [text]=\"true\"\n (onClick)=\"onReject()\"\n />\n <p-button\n [label]=\"message.acceptLabel\"\n [severity]=\"message.acceptButtonStyleClass ? 'danger' : 'primary'\"\n (onClick)=\"onAccept()\"\n />\n </div>\n </div>\n </ng-template>\n</p-confirmdialog>\n", styles: [":host{display:flex;flex-direction:column;min-height:100dvh;background:var(--ac-bg);color:var(--ac-text)}.topbar{position:sticky;top:0;z-index:20;display:flex;align-items:center;justify-content:flex-start;gap:16px;height:56px;padding:0 12px 0 8px;border-bottom:1px solid var(--ns-frame-line)}.side{display:flex;min-width:0;align-items:center;gap:4px}.side.is-end{margin-left:auto}.brand{display:flex;align-items:center;gap:9px;margin-left:4px}.brand-name{display:flex;align-items:baseline;gap:7px}.brand-primary{font-size:13px;font-weight:700;letter-spacing:.15em}.brand-secondary{font-size:9px;font-weight:500;letter-spacing:.22em;color:var(--ns-frame-muted)}.lang-switch{display:flex;align-items:center;gap:2px;margin-right:6px;border:1px solid var(--ns-frame-line);border-radius:999px;padding:2px}.lang-pill{font-size:10px;font-weight:600;letter-spacing:.08em;padding:4px 10px;border:none;border-radius:999px;background:transparent;color:var(--ns-frame-muted);cursor:pointer}.lang-pill:hover{color:var(--ns-frame-ink)}.lang-pill.is-active{background:var(--ns-frame-glow);color:var(--ns-frame-on-glow)}.body{display:flex;flex:1;min-height:0}.sidebar{flex:none;width:max-content;min-width:224px;max-width:340px;padding:12px 10px;border-right:1px solid var(--ns-frame-line);transition:width .18s ease}.sidebar.is-collapsed{width:60px;min-width:0}.sidebar nav{display:flex;flex-direction:column;gap:3px}.nav-item{display:flex;align-items:center;gap:12px;width:100%;padding:var(--ns-nav-y, 9px) 12px;border:none;border-radius:6px;background:transparent;color:var(--ns-frame-muted);font-size:13px;font-weight:500;text-align:left;white-space:nowrap;cursor:pointer}.nav-item i{flex:none;font-size:15px}.nav-item:hover{background:var(--ns-frame-raised);color:var(--ns-frame-ink)}.nav-item.is-active{background:var(--ns-frame-raised);box-shadow:inset 2px 0 0 var(--ns-frame-glow);color:var(--ns-frame-ink)}.nav-item.is-active i{color:var(--ns-frame-glow)}.nav-caret{margin-left:auto;font-size:11px!important;opacity:.7}.nav-item.is-inert{opacity:.45;cursor:default}.nav-item.is-inert:hover{background:transparent;color:var(--ns-frame-muted)}.nav-label{overflow:hidden;text-overflow:ellipsis}.sidebar.is-collapsed .nav-label{display:none}.sidebar.is-collapsed .nav-item{justify-content:center;padding-inline:0}.content{flex:1;min-width:0;padding:28px 28px 64px;display:flex;flex-direction:column;gap:14px}.page-head{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:46px;padding:7px 16px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.page-head-main{display:flex;min-width:0;flex:1;align-items:center;gap:14px}.page-head-actions{display:flex;flex:none;align-items:center;gap:8px}.page-head h1{margin:0;font-size:19px;font-weight:600}.measure{display:flex;width:100%;max-width:var(--ac-content-max, 1440px);flex-direction:column;gap:14px;margin-inline:0}h1{margin:0;font-size:26px;line-height:1.2;font-weight:500;letter-spacing:-.02em}.access-menu{display:flex;flex-direction:column;gap:.15rem;margin-top:.75rem;padding-top:.75rem;border-top:1px solid var(--ns-frame-line)}.access-caption{margin:0 0 .4rem;padding:0 .75rem;color:var(--ns-frame-muted);font-size:.68rem;letter-spacing:.06em;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.access-state{margin:0;padding:.35rem .75rem;color:var(--ns-frame-muted);font-size:.78rem}.access-state.is-error{color:var(--p-red-400, #f87171)}.nav-item.is-child{padding-left:2.1rem;font-size:.86rem}@media(max-width:720px){.sidebar{max-width:none;position:fixed;top:var(--ns-topbar-h, 56px);bottom:0;left:0;z-index:30;width:268px;max-width:82vw;overflow-y:auto;box-shadow:0 18px 44px #00000073;transform:translate(-100%);transition:transform .18s ease}.sidebar.is-collapsed{width:268px;max-width:82vw;transform:translate(-100%)}.sidebar:not(.is-collapsed){transform:translate(0)}.sidebar.is-collapsed .nav-label{display:inline}.sidebar.is-collapsed .role-text{display:flex}.sidebar.is-collapsed .nav-item,.sidebar.is-collapsed .role-badge{justify-content:flex-start;padding-inline:12px}.brand-secondary{display:none}.topbar{height:auto;min-height:56px;flex-wrap:wrap;padding-bottom:8px;row-gap:8px}.context{order:3;width:100%;margin-left:0}.context-select{min-width:0;max-width:none;flex:1 1 0}.content{padding:20px 16px 48px}h1{font-size:22px}.page-head{align-items:stretch;flex-direction:column;gap:10px;padding:10px 14px}.page-head-actions{justify-content:flex-end}}.who{display:flex;align-items:center;gap:12px;padding:15px 15px 13px;border-bottom:1px solid var(--ac-border);background:var(--ns-header-bg)}.who-photo{width:42px;height:42px;flex:none;border-radius:999px;object-fit:cover}.who-initials{display:inline-flex;align-items:center;justify-content:center;background:var(--ac-accent);color:var(--ac-on-accent);font-size:15px;font-weight:600}.who-text{display:flex;min-width:0;flex-direction:column}.who-name{overflow:hidden;font-size:14px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.who-mail{overflow:hidden;color:var(--ac-text-muted);font-size:11.5px;text-overflow:ellipsis;white-space:nowrap}.who-role{display:flex;align-items:center;gap:7px;margin:0;overflow:hidden;padding:9px 15px;border-bottom:1px solid var(--ac-border);color:var(--ac-text-muted);font-size:11.5px;white-space:nowrap}.who-role b{flex:none;color:var(--ac-text);font-size:12px;font-weight:600}.who-sep{flex:none}.who-context{overflow:hidden;text-overflow:ellipsis}.who-dot{width:5px;height:5px;flex:none;border-radius:50%;background:var(--ac-accent)}.company-option{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%}.company-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.launcher-notice{display:flex;gap:10px;margin:12px 12px 0;padding:12px;border:1px solid color-mix(in srgb,var(--ac-accent) 40%,transparent);border-radius:8px;background:color-mix(in srgb,var(--ac-accent) 10%,transparent)}.launcher-notice i{margin-top:2px;color:var(--ac-accent);font-size:15px}.launcher-notice-title{margin:0 0 4px;font-size:13px;font-weight:600}.launcher-notice-body{margin:0;color:var(--ac-text-muted);font-size:12px;line-height:1.45}.confirm{display:flex;flex-direction:column;align-items:center;gap:6px;padding:26px 24px 20px;border:1px solid var(--ac-border);border-radius:14px;background:var(--ac-surface);text-align:center}.confirm h2{margin:8px 0 0;font-size:17px;font-weight:600}.confirm p{margin:0;max-width:34ch;color:var(--ac-text-muted);font-size:13px;line-height:1.5}.confirm-actions{display:flex;justify-content:center;gap:8px;margin-top:18px}.toast-text{flex:1;margin-left:12px}.toast-summary{margin:0;font-size:13px;font-weight:600}.toast-detail{margin:2px 0 0;color:var(--ac-text-muted);font-size:12px}.context{display:flex;min-width:0;align-items:center;gap:8px;margin-left:14px}.context-select{min-width:150px;max-width:210px}.role-badge{display:flex;align-items:center;gap:12px;margin-bottom:10px;padding:9px 12px;border-left:2px solid var(--ns-frame-glow);border-radius:0 7px 7px 0;background:var(--ns-frame-raised);box-shadow:-2px 0 12px -3px color-mix(in srgb,var(--ns-frame-glow) 65%,transparent)}.role-badge>i{flex:none;color:var(--ns-frame-glow);font-size:14px}.role-text{display:flex;min-width:0;flex-direction:column;gap:1px}.role-name{overflow:hidden;color:var(--ns-frame-ink);font-size:13px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.role-caption{color:var(--ns-frame-muted);font-size:10px;letter-spacing:.06em;text-transform:uppercase}.sidebar.is-collapsed .role-badge{justify-content:center;padding-inline:0}.sidebar-scrim{position:fixed;top:var(--ns-topbar-h, 56px);right:0;bottom:0;left:0;z-index:29;padding:0;border:0;background:#00000073;cursor:pointer}.nav-skeleton{display:flex;flex-direction:column;gap:3px}.nav-skeleton-item{display:flex;align-items:center;gap:12px;padding:11px 12px}.sidebar.is-collapsed .nav-skeleton-item .p-skeleton:last-child{display:none}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i1$3.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "ngmodule", type: BreadcrumbModule }, { kind: "component", type: i2$3.Breadcrumb, selector: "p-breadcrumb", inputs: ["model", "style", "styleClass", "home", "homeAriaLabel"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ConfirmDialogModule }, { kind: "component", type: i4$1.ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "ngmodule", type: ToastModule }, { kind: "component", type: i5$2.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "life", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "motionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i6$1.Drawer, selector: "p-drawer", inputs: ["appendTo", "motionOptions", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i3.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i2.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i4.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i5$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: NucleusAppearance, selector: "nucleus-appearance" }, { kind: "component", type: NucleusLordicon, selector: "nucleus-lordicon", inputs: ["src", "trigger", "state", "size", "tone"] }, { kind: "component", type: NucleusMenu, selector: "nucleus-menu", inputs: ["sections", "heading", "badge", "searchable", "searchPlaceholder", "emptyText", "keyboardHint", "width"], outputs: ["select", "dismiss"] }, { kind: "component", type: NucleusMark, selector: "nucleus-mark", inputs: ["accent", "size"] }, { kind: "component", type: NucleusStarfield, selector: "nucleus-starfield" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4100
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: NucleusShell, isStandalone: true, selector: "nucleus-shell", inputs: { brand: { classPropertyName: "brand", publicName: "brand", isSignal: true, isRequired: false, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, navItems: { classPropertyName: "navItems", publicName: "navItems", isSignal: true, isRequired: false, transformFunction: null }, activeNavId: { classPropertyName: "activeNavId", publicName: "activeNavId", isSignal: true, isRequired: false, transformFunction: null }, selectedMenuId: { classPropertyName: "selectedMenuId", publicName: "selectedMenuId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { navSelect: "navSelect", menuSelect: "menuSelect" }, host: { properties: { "style.--ns-topbar-h": "topbarHeight()" } }, ngImport: i0, template: "@let t = copy();\n@let me = identity();\n\n@if (starfield()) {\n <nucleus-starfield />\n}\n\n<header class=\"topbar ns-frame\">\n <div class=\"side\">\n <p-button\n icon=\"pi pi-bars\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.navToggle\"\n [pTooltip]=\"t.navToggle\"\n tooltipPosition=\"bottom\"\n (onClick)=\"toggleSidebar()\"\n />\n\n <div class=\"brand\">\n <nucleus-mark [size]=\"20\" />\n <div class=\"brand-name\">\n <span class=\"brand-primary\">NUCLEUS</span>\n <span class=\"brand-secondary\">{{ brand() }}</span>\n </div>\n </div>\n\n </div>\n\n @if (hasSiteContext()) {\n <div class=\"context ns-context\">\n <p-select\n styleClass=\"context-select\"\n [options]=\"companyChoices()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"companyChoice()\"\n (ngModelChange)=\"onCompanyChange($event)\"\n [placeholder]=\"t.companyPlaceholder\"\n [disabled]=\"switching()\"\n [filter]=\"companyChoices().length > 8\"\n filterBy=\"name\"\n [filterPlaceholder]=\"words().search\"\n [autofocusFilter]=\"true\"\n [resetFilterOnHide]=\"true\"\n [ariaLabel]=\"t.companyLabel\"\n [ngModelOptions]=\"{ standalone: true }\"\n >\n <ng-template #item let-option>\n <span class=\"company-option\">\n <span class=\"company-name\">{{ option.name }}</span>\n <p-tag [value]=\"option.tag\" severity=\"secondary\" />\n </span>\n </ng-template>\n </p-select>\n\n <p-select\n styleClass=\"context-select\"\n [options]=\"siteOptions()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"siteChoice()\"\n (ngModelChange)=\"onSiteChange($event)\"\n [placeholder]=\"sitePlaceholder()\"\n [disabled]=\"switching() || sitesLoading() || !siteOptions().length\"\n [filter]=\"siteOptions().length > 8\"\n filterBy=\"name\"\n [filterPlaceholder]=\"words().search\"\n [autofocusFilter]=\"true\"\n [resetFilterOnHide]=\"true\"\n [ariaLabel]=\"t.siteLabel\"\n [ngModelOptions]=\"{ standalone: true }\"\n />\n </div>\n }\n\n <div class=\"side is-end\">\n <div class=\"lang-switch\" role=\"group\" aria-label=\"Idioma / Language\">\n <button\n type=\"button\"\n class=\"lang-pill\"\n [class.is-active]=\"lang() === 'es'\"\n [attr.aria-pressed]=\"lang() === 'es'\"\n (click)=\"setLang('es')\"\n >\n ES\n </button>\n <button\n type=\"button\"\n class=\"lang-pill\"\n [class.is-active]=\"lang() === 'en'\"\n [attr.aria-pressed]=\"lang() === 'en'\"\n (click)=\"setLang('en')\"\n >\n EN\n </button>\n </div>\n\n <p-button\n icon=\"pi pi-th-large\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.appsLauncher\"\n [pTooltip]=\"t.appsLauncher\"\n tooltipPosition=\"bottom\"\n (onClick)=\"launcher.toggle($event)\"\n />\n\n <p-popover #launcher styleClass=\"ns-flush-popover\">\n @if (!hasCompany()) {\n <div class=\"launcher-notice\">\n <i class=\"pi pi-building\" aria-hidden=\"true\"></i>\n <div>\n <p class=\"launcher-notice-title\">{{ t.noCompanyTitle }}</p>\n <p class=\"launcher-notice-body\">{{ t.noCompanyHint }}</p>\n </div>\n </div>\n }\n\n <nucleus-menu\n [heading]=\"t.appsSwitch\"\n [badge]=\"launcherCount()\"\n [sections]=\"launcherSections()\"\n [searchable]=\"launcherRich()\"\n [searchPlaceholder]=\"t.appsSearch\"\n [emptyText]=\"launcherRich() ? t.appsNoMatch : t.appsEmpty\"\n [keyboardHint]=\"t.keyboardHint\"\n [width]=\"336\"\n (select)=\"onLauncherSelect($event); launcher.hide()\"\n (dismiss)=\"launcher.hide()\"\n />\n </p-popover>\n\n <p-button\n icon=\"pi pi-cog\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.settingsTitle\"\n [pTooltip]=\"t.settingsTitle\"\n tooltipPosition=\"bottom\"\n (onClick)=\"settingsOpen.set(true)\"\n />\n\n @if (me) {\n <p-button\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n styleClass=\"avatar-trigger\"\n [ariaLabel]=\"me.name\"\n [pTooltip]=\"me.name\"\n tooltipPosition=\"bottom\"\n (onClick)=\"account.toggle($event)\"\n >\n <p-avatar\n [image]=\"me.photoUrl ?? undefined\"\n [label]=\"me.photoUrl ? undefined : initials()\"\n shape=\"circle\"\n size=\"normal\"\n />\n </p-button>\n }\n </div>\n</header>\n\n<p-popover #account styleClass=\"ns-flush-popover\">\n @if (me) {\n <div class=\"who\">\n @if (me.photoUrl) {\n <img class=\"who-photo\" [src]=\"me.photoUrl\" alt=\"\" width=\"42\" height=\"42\" />\n } @else {\n <span class=\"who-photo who-initials\">{{ initials() }}</span>\n }\n <span class=\"who-text\">\n <span class=\"who-name\">{{ me.name }}</span>\n <span class=\"who-mail\">{{ me.email }}</span>\n </span>\n </div>\n\n <p class=\"who-role\">\n <span class=\"who-dot\" aria-hidden=\"true\"></span>\n @if (roleName(); as role) {\n <b>{{ role }}</b>\n <span class=\"who-sep\">\u00B7</span>\n }\n <span class=\"who-context\">{{ accountContext() }}</span>\n </p>\n\n <nucleus-menu\n [sections]=\"accountSections()\"\n [width]=\"304\"\n (select)=\"onAccountSelect($event); account.hide()\"\n (dismiss)=\"account.hide()\"\n />\n }\n</p-popover>\n\n<div class=\"body\">\n @if (narrow() && sidebarOpen()) {\n <button\n type=\"button\"\n class=\"sidebar-scrim\"\n [attr.aria-label]=\"t.navToggle\"\n (click)=\"toggleSidebar()\"\n ></button>\n }\n\n <aside class=\"sidebar ns-frame\" [class.is-collapsed]=\"!sidebarOpen()\">\n @if (roleName(); as role) {\n <div class=\"role-badge\" [pTooltip]=\"sidebarOpen() ? '' : role\" tooltipPosition=\"right\">\n <i class=\"pi pi-key\" aria-hidden=\"true\"></i>\n <span class=\"nav-label role-text\">\n <span class=\"role-name\">{{ role }}</span>\n <span class=\"role-caption\">{{ t.roleCaption }}</span>\n </span>\n </div>\n }\n\n @if (navItems().length) {\n <nav>\n @for (item of navItems(); track item.id) {\n <button\n type=\"button\"\n class=\"nav-item\"\n [class.is-active]=\"activeNavId() === item.id\"\n [attr.aria-current]=\"activeNavId() === item.id ? 'page' : null\"\n [pTooltip]=\"sidebarOpen() ? '' : item.label\"\n tooltipPosition=\"right\"\n (click)=\"selectNav(item.id)\"\n >\n <i [class]=\"item.icon\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ item.label }}</span>\n </button>\n }\n </nav>\n }\n\n <nav class=\"access-menu\">\n @if (menuLoading()) {\n <div class=\"nav-skeleton\" role=\"status\" [attr.aria-label]=\"t.accessLoading\">\n @for (width of menuPlaceholders; track $index) {\n <div class=\"nav-skeleton-item\">\n <p-skeleton shape=\"circle\" size=\"15px\" />\n <p-skeleton height=\"9px\" [width]=\"width\" />\n </div>\n }\n </div>\n } @else if (menuError()) {\n <p class=\"access-state is-error\">{{ menuError() }}</p>\n } @else if (!menu().length) {\n <p class=\"access-state\">{{ t.accessEmpty }}</p>\n } @else {\n @for (node of menu(); track node.id) {\n @let group = isGroup(node);\n @let open = isExpanded(node);\n\n <button\n type=\"button\"\n class=\"nav-item\"\n [class.is-active]=\"!group && isSelected(node)\"\n [class.is-inert]=\"!group && !node.route\"\n [attr.aria-expanded]=\"group ? open : null\"\n [disabled]=\"!group && !node.route\"\n [pTooltip]=\"sidebarOpen() ? '' : node.label\"\n tooltipPosition=\"right\"\n (click)=\"selectMenu(node)\"\n >\n <i [class]=\"node.icon ?? 'pi pi-circle'\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ node.label }}</span>\n @if (group && sidebarOpen()) {\n <i\n class=\"pi nav-caret\"\n [class.pi-chevron-down]=\"open\"\n [class.pi-chevron-right]=\"!open\"\n aria-hidden=\"true\"\n ></i>\n }\n </button>\n\n @if (open) {\n @for (child of node.children; track child.id) {\n <button\n type=\"button\"\n class=\"nav-item is-child\"\n [class.is-active]=\"isSelected(child)\"\n [pTooltip]=\"sidebarOpen() ? '' : child.label\"\n tooltipPosition=\"right\"\n (click)=\"selectMenu(child)\"\n >\n <i [class]=\"child.icon ?? 'pi pi-circle'\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ child.label }}</span>\n </button>\n }\n }\n }\n }\n </nav>\n </aside>\n\n <main class=\"content\">\n <div class=\"measure\">\n <ng-content select=\"[nucleusTop]\" />\n\n @if (crumbs().length || title() || pageActions()) {\n <header class=\"page-head\">\n <div class=\"page-head-main\">\n @if (crumbs().length) {\n <p-breadcrumb [model]=\"crumbs()\" [home]=\"home()\" styleClass=\"ns-crumbs\" />\n }\n\n @if (title()) {\n <h1>{{ title() }}</h1>\n }\n </div>\n\n @if (pageActions(); as actions) {\n <div class=\"page-head-actions\">\n <ng-container [ngTemplateOutlet]=\"actions\" />\n </div>\n }\n </header>\n }\n\n <ng-content />\n </div>\n </main>\n</div>\n\n<p-drawer\n [visible]=\"settingsOpen()\"\n (visibleChange)=\"settingsOpen.set($event)\"\n position=\"right\"\n [header]=\"t.settingsTitle\"\n [modal]=\"false\"\n [blockScroll]=\"false\"\n styleClass=\"ns-settings-drawer\"\n [style]=\"{ width: '380px' }\"\n>\n <nucleus-appearance />\n</p-drawer>\n\n<p-toast position=\"bottom-right\" styleClass=\"ns-toast\">\n <ng-template #message let-message>\n <nucleus-lordicon\n [src]=\"message.severity === 'success' ? icons.check : icons.warning\"\n [tone]=\"message.severity === 'success' ? 'accent' : 'danger'\"\n [size]=\"34\"\n trigger=\"in\"\n />\n <div class=\"toast-text\">\n <p class=\"toast-summary\">{{ message.summary }}</p>\n @if (message.detail) {\n <p class=\"toast-detail\">{{ message.detail }}</p>\n }\n </div>\n </ng-template>\n</p-toast>\n\n<p-confirmdialog [style]=\"{ width: '420px' }\">\n <ng-template #headless let-message let-onAccept=\"onAccept\" let-onReject=\"onReject\">\n <div class=\"confirm\">\n <nucleus-lordicon\n [src]=\"message.icon\"\n [tone]=\"message.acceptButtonStyleClass ? 'danger' : 'accent'\"\n [size]=\"64\"\n trigger=\"loop\"\n />\n <h2>{{ message.header }}</h2>\n <p>{{ message.message }}</p>\n <div class=\"confirm-actions\">\n <p-button\n [label]=\"message.rejectLabel\"\n severity=\"secondary\"\n [text]=\"true\"\n (onClick)=\"onReject()\"\n />\n <p-button\n [label]=\"message.acceptLabel\"\n [severity]=\"message.acceptButtonStyleClass ? 'danger' : 'primary'\"\n (onClick)=\"onAccept()\"\n />\n </div>\n </div>\n </ng-template>\n</p-confirmdialog>\n", styles: [":host{display:flex;flex-direction:column;min-height:100dvh;background:var(--ac-bg);color:var(--ac-text)}.topbar{position:sticky;top:0;z-index:20;display:flex;align-items:center;justify-content:flex-start;gap:16px;height:56px;padding:0 12px 0 8px;border-bottom:1px solid var(--ns-frame-line)}.side{display:flex;min-width:0;align-items:center;gap:4px}.side.is-end{margin-left:auto}.brand{display:flex;align-items:center;gap:9px;margin-left:4px}.brand-name{display:flex;align-items:baseline;gap:7px}.brand-primary{font-size:13px;font-weight:700;letter-spacing:.15em}.brand-secondary{font-size:9px;font-weight:500;letter-spacing:.22em;color:var(--ns-frame-muted)}.lang-switch{display:flex;align-items:center;gap:2px;margin-right:6px;border:1px solid var(--ns-frame-line);border-radius:999px;padding:2px}.lang-pill{font-size:10px;font-weight:600;letter-spacing:.08em;padding:4px 10px;border:none;border-radius:999px;background:transparent;color:var(--ns-frame-muted);cursor:pointer}.lang-pill:hover{color:var(--ns-frame-ink)}.lang-pill.is-active{background:var(--ns-frame-glow);color:var(--ns-frame-on-glow)}.body{display:flex;flex:1;min-height:0}.sidebar{flex:none;width:max-content;min-width:224px;max-width:340px;padding:12px 10px;border-right:1px solid var(--ns-frame-line);transition:width .18s ease}.sidebar.is-collapsed{width:60px;min-width:0}.sidebar nav{display:flex;flex-direction:column;gap:3px}.nav-item{display:flex;align-items:center;gap:12px;width:100%;padding:var(--ns-nav-y, 9px) 12px;border:none;border-radius:6px;background:transparent;color:var(--ns-frame-muted);font-size:13px;font-weight:500;text-align:left;white-space:nowrap;cursor:pointer}.nav-item i{flex:none;font-size:15px}.nav-item:hover{background:var(--ns-frame-raised);color:var(--ns-frame-ink)}.nav-item.is-active{background:var(--ns-frame-raised);box-shadow:inset 2px 0 0 var(--ns-frame-glow);color:var(--ns-frame-ink)}.nav-item.is-active i{color:var(--ns-frame-glow)}.nav-caret{margin-left:auto;font-size:11px!important;opacity:.7}.nav-item.is-inert{opacity:.45;cursor:default}.nav-item.is-inert:hover{background:transparent;color:var(--ns-frame-muted)}.nav-label{overflow:hidden;text-overflow:ellipsis}.sidebar.is-collapsed .nav-label{display:none}.sidebar.is-collapsed .nav-item{justify-content:center;padding-inline:0}.content{flex:1;min-width:0;padding:28px 28px 64px;display:flex;flex-direction:column;gap:14px}.page-head{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:46px;padding:7px 16px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.page-head-main{display:flex;min-width:0;flex:1;align-items:center;gap:14px}.page-head-actions{display:flex;flex:none;align-items:center;gap:8px}.page-head h1{margin:0;font-size:19px;font-weight:600}.measure{display:flex;width:100%;max-width:var(--ac-content-max, 1440px);flex-direction:column;gap:14px;margin-inline:0}h1{margin:0;font-size:26px;line-height:1.2;font-weight:500;letter-spacing:-.02em}.access-menu{display:flex;flex-direction:column;gap:.15rem;margin-top:.75rem;padding-top:.75rem;border-top:1px solid var(--ns-frame-line)}.access-caption{margin:0 0 .4rem;padding:0 .75rem;color:var(--ns-frame-muted);font-size:.68rem;letter-spacing:.06em;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.access-state{margin:0;padding:.35rem .75rem;color:var(--ns-frame-muted);font-size:.78rem}.access-state.is-error{color:var(--p-red-400, #f87171)}.nav-item.is-child{padding-left:2.1rem;font-size:.86rem}@media(max-width:720px){.sidebar{max-width:none;position:fixed;top:var(--ns-topbar-h, 56px);bottom:0;left:0;z-index:30;width:268px;max-width:82vw;overflow-y:auto;box-shadow:0 18px 44px #00000073;transform:translate(-100%);transition:transform .18s ease}.sidebar.is-collapsed{width:268px;max-width:82vw;transform:translate(-100%)}.sidebar:not(.is-collapsed){transform:translate(0)}.sidebar.is-collapsed .nav-label{display:inline}.sidebar.is-collapsed .role-text{display:flex}.sidebar.is-collapsed .nav-item,.sidebar.is-collapsed .role-badge{justify-content:flex-start;padding-inline:12px}.brand-secondary{display:none}.topbar{height:auto;min-height:56px;flex-wrap:wrap;padding-bottom:8px;row-gap:8px}.context{order:3;width:100%;margin-left:0}.context-select{min-width:0;max-width:none;flex:1 1 0}.content{padding:20px 16px 48px}h1{font-size:22px}.page-head{gap:10px;min-height:42px;padding:7px 12px}.page-head-main{gap:8px}.page-head h1{overflow:hidden;min-width:0;font-size:16px;text-overflow:ellipsis;white-space:nowrap}.page-head-actions{flex-wrap:wrap;justify-content:flex-end;gap:6px}.page-head-actions ::ng-deep .p-button{padding-block:6px;padding-inline:11px;font-size:13px;white-space:nowrap}.page-head-actions ::ng-deep .p-button-icon{font-size:13px}}.who{display:flex;align-items:center;gap:12px;padding:15px 15px 13px;border-bottom:1px solid var(--ac-border);background:var(--ns-header-bg)}.who-photo{width:42px;height:42px;flex:none;border-radius:999px;object-fit:cover}.who-initials{display:inline-flex;align-items:center;justify-content:center;background:var(--ac-accent);color:var(--ac-on-accent);font-size:15px;font-weight:600}.who-text{display:flex;min-width:0;flex-direction:column}.who-name{overflow:hidden;font-size:14px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.who-mail{overflow:hidden;color:var(--ac-text-muted);font-size:11.5px;text-overflow:ellipsis;white-space:nowrap}.who-role{display:flex;align-items:center;gap:7px;margin:0;overflow:hidden;padding:9px 15px;border-bottom:1px solid var(--ac-border);color:var(--ac-text-muted);font-size:11.5px;white-space:nowrap}.who-role b{flex:none;color:var(--ac-text);font-size:12px;font-weight:600}.who-sep{flex:none}.who-context{overflow:hidden;text-overflow:ellipsis}.who-dot{width:5px;height:5px;flex:none;border-radius:50%;background:var(--ac-accent)}.company-option{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%}.company-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.launcher-notice{display:flex;gap:10px;margin:12px 12px 0;padding:12px;border:1px solid color-mix(in srgb,var(--ac-accent) 40%,transparent);border-radius:8px;background:color-mix(in srgb,var(--ac-accent) 10%,transparent)}.launcher-notice i{margin-top:2px;color:var(--ac-accent);font-size:15px}.launcher-notice-title{margin:0 0 4px;font-size:13px;font-weight:600}.launcher-notice-body{margin:0;color:var(--ac-text-muted);font-size:12px;line-height:1.45}.confirm{display:flex;flex-direction:column;align-items:center;gap:6px;padding:26px 24px 20px;border:1px solid var(--ac-border);border-radius:14px;background:var(--ac-surface);text-align:center}.confirm h2{margin:8px 0 0;font-size:17px;font-weight:600}.confirm p{margin:0;max-width:34ch;color:var(--ac-text-muted);font-size:13px;line-height:1.5}.confirm-actions{display:flex;justify-content:center;gap:8px;margin-top:18px}.toast-text{flex:1;margin-left:12px}.toast-summary{margin:0;font-size:13px;font-weight:600}.toast-detail{margin:2px 0 0;color:var(--ac-text-muted);font-size:12px}.context{display:flex;min-width:0;align-items:center;gap:8px;margin-left:14px}.context-select{min-width:150px;max-width:210px}.role-badge{display:flex;align-items:center;gap:12px;margin-bottom:10px;padding:9px 12px;border-left:2px solid var(--ns-frame-glow);border-radius:0 7px 7px 0;background:var(--ns-frame-raised);box-shadow:-2px 0 12px -3px color-mix(in srgb,var(--ns-frame-glow) 65%,transparent)}.role-badge>i{flex:none;color:var(--ns-frame-glow);font-size:14px}.role-text{display:flex;min-width:0;flex-direction:column;gap:1px}.role-name{overflow:hidden;color:var(--ns-frame-ink);font-size:13px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.role-caption{color:var(--ns-frame-muted);font-size:10px;letter-spacing:.06em;text-transform:uppercase}.sidebar.is-collapsed .role-badge{justify-content:center;padding-inline:0}.sidebar-scrim{position:fixed;top:var(--ns-topbar-h, 56px);right:0;bottom:0;left:0;z-index:29;padding:0;border:0;background:#00000073;cursor:pointer}.nav-skeleton{display:flex;flex-direction:column;gap:3px}.nav-skeleton-item{display:flex;align-items:center;gap:12px;padding:11px 12px}.sidebar.is-collapsed .nav-skeleton-item .p-skeleton:last-child{display:none}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i1$3.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "ngmodule", type: BreadcrumbModule }, { kind: "component", type: i2$4.Breadcrumb, selector: "p-breadcrumb", inputs: ["model", "style", "styleClass", "home", "homeAriaLabel"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ConfirmDialogModule }, { kind: "component", type: i4$1.ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "ngmodule", type: ToastModule }, { kind: "component", type: i5$2.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "life", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "motionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i6$2.Drawer, selector: "p-drawer", inputs: ["appendTo", "motionOptions", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i3.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i2.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i5$1.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: NucleusAppearance, selector: "nucleus-appearance" }, { kind: "component", type: NucleusLordicon, selector: "nucleus-lordicon", inputs: ["src", "trigger", "state", "size", "tone"] }, { kind: "component", type: NucleusMenu, selector: "nucleus-menu", inputs: ["sections", "heading", "badge", "searchable", "searchPlaceholder", "emptyText", "keyboardHint", "width"], outputs: ["select", "dismiss"] }, { kind: "component", type: NucleusMark, selector: "nucleus-mark", inputs: ["accent", "size"] }, { kind: "component", type: NucleusStarfield, selector: "nucleus-starfield" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3771
4101
|
}
|
|
3772
4102
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusShell, decorators: [{
|
|
3773
4103
|
type: Component,
|
|
@@ -3790,7 +4120,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
3790
4120
|
NucleusMenu,
|
|
3791
4121
|
NucleusMark,
|
|
3792
4122
|
NucleusStarfield,
|
|
3793
|
-
], host: { '[style.--ns-topbar-h]': 'topbarHeight()' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let t = copy();\n@let me = identity();\n\n@if (starfield()) {\n <nucleus-starfield />\n}\n\n<header class=\"topbar ns-frame\">\n <div class=\"side\">\n <p-button\n icon=\"pi pi-bars\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.navToggle\"\n [pTooltip]=\"t.navToggle\"\n tooltipPosition=\"bottom\"\n (onClick)=\"toggleSidebar()\"\n />\n\n <div class=\"brand\">\n <nucleus-mark [size]=\"20\" />\n <div class=\"brand-name\">\n <span class=\"brand-primary\">NUCLEUS</span>\n <span class=\"brand-secondary\">{{ brand() }}</span>\n </div>\n </div>\n\n </div>\n\n @if (hasSiteContext()) {\n <div class=\"context ns-context\">\n <p-select\n styleClass=\"context-select\"\n [options]=\"companyChoices()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"companyChoice()\"\n (ngModelChange)=\"onCompanyChange($event)\"\n [placeholder]=\"t.companyPlaceholder\"\n [disabled]=\"switching()\"\n [filter]=\"companyChoices().length > 8\"\n filterBy=\"name\"\n [filterPlaceholder]=\"words().search\"\n [autofocusFilter]=\"true\"\n [resetFilterOnHide]=\"true\"\n [ariaLabel]=\"t.companyLabel\"\n [ngModelOptions]=\"{ standalone: true }\"\n >\n <ng-template #item let-option>\n <span class=\"company-option\">\n <span class=\"company-name\">{{ option.name }}</span>\n <p-tag [value]=\"option.tag\" severity=\"secondary\" />\n </span>\n </ng-template>\n </p-select>\n\n <p-select\n styleClass=\"context-select\"\n [options]=\"siteOptions()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"siteChoice()\"\n (ngModelChange)=\"onSiteChange($event)\"\n [placeholder]=\"sitePlaceholder()\"\n [disabled]=\"switching() || sitesLoading() || !siteOptions().length\"\n [filter]=\"siteOptions().length > 8\"\n filterBy=\"name\"\n [filterPlaceholder]=\"words().search\"\n [autofocusFilter]=\"true\"\n [resetFilterOnHide]=\"true\"\n [ariaLabel]=\"t.siteLabel\"\n [ngModelOptions]=\"{ standalone: true }\"\n />\n </div>\n }\n\n <div class=\"side is-end\">\n <div class=\"lang-switch\" role=\"group\" aria-label=\"Idioma / Language\">\n <button\n type=\"button\"\n class=\"lang-pill\"\n [class.is-active]=\"lang() === 'es'\"\n [attr.aria-pressed]=\"lang() === 'es'\"\n (click)=\"setLang('es')\"\n >\n ES\n </button>\n <button\n type=\"button\"\n class=\"lang-pill\"\n [class.is-active]=\"lang() === 'en'\"\n [attr.aria-pressed]=\"lang() === 'en'\"\n (click)=\"setLang('en')\"\n >\n EN\n </button>\n </div>\n\n <p-button\n icon=\"pi pi-th-large\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.appsLauncher\"\n [pTooltip]=\"t.appsLauncher\"\n tooltipPosition=\"bottom\"\n (onClick)=\"launcher.toggle($event)\"\n />\n\n <p-popover #launcher styleClass=\"ns-flush-popover\">\n @if (!hasCompany()) {\n <div class=\"launcher-notice\">\n <i class=\"pi pi-building\" aria-hidden=\"true\"></i>\n <div>\n <p class=\"launcher-notice-title\">{{ t.noCompanyTitle }}</p>\n <p class=\"launcher-notice-body\">{{ t.noCompanyHint }}</p>\n </div>\n </div>\n }\n\n <nucleus-menu\n [heading]=\"t.appsSwitch\"\n [badge]=\"launcherCount()\"\n [sections]=\"launcherSections()\"\n [searchable]=\"launcherRich()\"\n [searchPlaceholder]=\"t.appsSearch\"\n [emptyText]=\"launcherRich() ? t.appsNoMatch : t.appsEmpty\"\n [keyboardHint]=\"t.keyboardHint\"\n [width]=\"336\"\n (select)=\"onLauncherSelect($event); launcher.hide()\"\n (dismiss)=\"launcher.hide()\"\n />\n </p-popover>\n\n <p-button\n icon=\"pi pi-cog\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.settingsTitle\"\n [pTooltip]=\"t.settingsTitle\"\n tooltipPosition=\"bottom\"\n (onClick)=\"settingsOpen.set(true)\"\n />\n\n @if (me) {\n <p-button\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n styleClass=\"avatar-trigger\"\n [ariaLabel]=\"me.name\"\n [pTooltip]=\"me.name\"\n tooltipPosition=\"bottom\"\n (onClick)=\"account.toggle($event)\"\n >\n <p-avatar\n [image]=\"me.photoUrl ?? undefined\"\n [label]=\"me.photoUrl ? undefined : initials()\"\n shape=\"circle\"\n size=\"normal\"\n />\n </p-button>\n }\n </div>\n</header>\n\n<p-popover #account styleClass=\"ns-flush-popover\">\n @if (me) {\n <div class=\"who\">\n @if (me.photoUrl) {\n <img class=\"who-photo\" [src]=\"me.photoUrl\" alt=\"\" width=\"42\" height=\"42\" />\n } @else {\n <span class=\"who-photo who-initials\">{{ initials() }}</span>\n }\n <span class=\"who-text\">\n <span class=\"who-name\">{{ me.name }}</span>\n <span class=\"who-mail\">{{ me.email }}</span>\n </span>\n </div>\n\n <p class=\"who-role\">\n <span class=\"who-dot\" aria-hidden=\"true\"></span>\n @if (roleName(); as role) {\n <b>{{ role }}</b>\n <span class=\"who-sep\">\u00B7</span>\n }\n <span class=\"who-context\">{{ accountContext() }}</span>\n </p>\n\n <nucleus-menu\n [sections]=\"accountSections()\"\n [width]=\"304\"\n (select)=\"onAccountSelect($event); account.hide()\"\n (dismiss)=\"account.hide()\"\n />\n }\n</p-popover>\n\n<div class=\"body\">\n @if (narrow() && sidebarOpen()) {\n <button\n type=\"button\"\n class=\"sidebar-scrim\"\n [attr.aria-label]=\"t.navToggle\"\n (click)=\"toggleSidebar()\"\n ></button>\n }\n\n <aside class=\"sidebar ns-frame\" [class.is-collapsed]=\"!sidebarOpen()\">\n @if (roleName(); as role) {\n <div class=\"role-badge\" [pTooltip]=\"sidebarOpen() ? '' : role\" tooltipPosition=\"right\">\n <i class=\"pi pi-key\" aria-hidden=\"true\"></i>\n <span class=\"nav-label role-text\">\n <span class=\"role-name\">{{ role }}</span>\n <span class=\"role-caption\">{{ t.roleCaption }}</span>\n </span>\n </div>\n }\n\n @if (navItems().length) {\n <nav>\n @for (item of navItems(); track item.id) {\n <button\n type=\"button\"\n class=\"nav-item\"\n [class.is-active]=\"activeNavId() === item.id\"\n [attr.aria-current]=\"activeNavId() === item.id ? 'page' : null\"\n [pTooltip]=\"sidebarOpen() ? '' : item.label\"\n tooltipPosition=\"right\"\n (click)=\"selectNav(item.id)\"\n >\n <i [class]=\"item.icon\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ item.label }}</span>\n </button>\n }\n </nav>\n }\n\n <nav class=\"access-menu\">\n @if (menuLoading()) {\n <div class=\"nav-skeleton\" role=\"status\" [attr.aria-label]=\"t.accessLoading\">\n @for (width of menuPlaceholders; track $index) {\n <div class=\"nav-skeleton-item\">\n <p-skeleton shape=\"circle\" size=\"15px\" />\n <p-skeleton height=\"9px\" [width]=\"width\" />\n </div>\n }\n </div>\n } @else if (menuError()) {\n <p class=\"access-state is-error\">{{ menuError() }}</p>\n } @else if (!menu().length) {\n <p class=\"access-state\">{{ t.accessEmpty }}</p>\n } @else {\n @for (node of menu(); track node.id) {\n @let group = isGroup(node);\n @let open = isExpanded(node);\n\n <button\n type=\"button\"\n class=\"nav-item\"\n [class.is-active]=\"!group && isSelected(node)\"\n [class.is-inert]=\"!group && !node.route\"\n [attr.aria-expanded]=\"group ? open : null\"\n [disabled]=\"!group && !node.route\"\n [pTooltip]=\"sidebarOpen() ? '' : node.label\"\n tooltipPosition=\"right\"\n (click)=\"selectMenu(node)\"\n >\n <i [class]=\"node.icon ?? 'pi pi-circle'\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ node.label }}</span>\n @if (group && sidebarOpen()) {\n <i\n class=\"pi nav-caret\"\n [class.pi-chevron-down]=\"open\"\n [class.pi-chevron-right]=\"!open\"\n aria-hidden=\"true\"\n ></i>\n }\n </button>\n\n @if (open) {\n @for (child of node.children; track child.id) {\n <button\n type=\"button\"\n class=\"nav-item is-child\"\n [class.is-active]=\"isSelected(child)\"\n [pTooltip]=\"sidebarOpen() ? '' : child.label\"\n tooltipPosition=\"right\"\n (click)=\"selectMenu(child)\"\n >\n <i [class]=\"child.icon ?? 'pi pi-circle'\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ child.label }}</span>\n </button>\n }\n }\n }\n }\n </nav>\n </aside>\n\n <main class=\"content\">\n <div class=\"measure\">\n <ng-content select=\"[nucleusTop]\" />\n\n @if (crumbs().length || title() || pageActions()) {\n <header class=\"page-head\">\n <div class=\"page-head-main\">\n @if (crumbs().length) {\n <p-breadcrumb [model]=\"crumbs()\" [home]=\"home()\" styleClass=\"ns-crumbs\" />\n }\n\n @if (title()) {\n <h1>{{ title() }}</h1>\n }\n </div>\n\n @if (pageActions(); as actions) {\n <div class=\"page-head-actions\">\n <ng-container [ngTemplateOutlet]=\"actions\" />\n </div>\n }\n </header>\n }\n\n <ng-content />\n </div>\n </main>\n</div>\n\n<p-drawer\n [visible]=\"settingsOpen()\"\n (visibleChange)=\"settingsOpen.set($event)\"\n position=\"right\"\n [header]=\"t.settingsTitle\"\n [modal]=\"false\"\n [blockScroll]=\"false\"\n styleClass=\"ns-settings-drawer\"\n [style]=\"{ width: '380px' }\"\n>\n <nucleus-appearance />\n</p-drawer>\n\n<p-toast position=\"bottom-right\" styleClass=\"ns-toast\">\n <ng-template #message let-message>\n <nucleus-lordicon\n [src]=\"message.severity === 'success' ? icons.check : icons.warning\"\n [tone]=\"message.severity === 'success' ? 'accent' : 'danger'\"\n [size]=\"34\"\n trigger=\"in\"\n />\n <div class=\"toast-text\">\n <p class=\"toast-summary\">{{ message.summary }}</p>\n @if (message.detail) {\n <p class=\"toast-detail\">{{ message.detail }}</p>\n }\n </div>\n </ng-template>\n</p-toast>\n\n<p-confirmdialog [style]=\"{ width: '420px' }\">\n <ng-template #headless let-message let-onAccept=\"onAccept\" let-onReject=\"onReject\">\n <div class=\"confirm\">\n <nucleus-lordicon\n [src]=\"message.icon\"\n [tone]=\"message.acceptButtonStyleClass ? 'danger' : 'accent'\"\n [size]=\"64\"\n trigger=\"loop\"\n />\n <h2>{{ message.header }}</h2>\n <p>{{ message.message }}</p>\n <div class=\"confirm-actions\">\n <p-button\n [label]=\"message.rejectLabel\"\n severity=\"secondary\"\n [text]=\"true\"\n (onClick)=\"onReject()\"\n />\n <p-button\n [label]=\"message.acceptLabel\"\n [severity]=\"message.acceptButtonStyleClass ? 'danger' : 'primary'\"\n (onClick)=\"onAccept()\"\n />\n </div>\n </div>\n </ng-template>\n</p-confirmdialog>\n", styles: [":host{display:flex;flex-direction:column;min-height:100dvh;background:var(--ac-bg);color:var(--ac-text)}.topbar{position:sticky;top:0;z-index:20;display:flex;align-items:center;justify-content:flex-start;gap:16px;height:56px;padding:0 12px 0 8px;border-bottom:1px solid var(--ns-frame-line)}.side{display:flex;min-width:0;align-items:center;gap:4px}.side.is-end{margin-left:auto}.brand{display:flex;align-items:center;gap:9px;margin-left:4px}.brand-name{display:flex;align-items:baseline;gap:7px}.brand-primary{font-size:13px;font-weight:700;letter-spacing:.15em}.brand-secondary{font-size:9px;font-weight:500;letter-spacing:.22em;color:var(--ns-frame-muted)}.lang-switch{display:flex;align-items:center;gap:2px;margin-right:6px;border:1px solid var(--ns-frame-line);border-radius:999px;padding:2px}.lang-pill{font-size:10px;font-weight:600;letter-spacing:.08em;padding:4px 10px;border:none;border-radius:999px;background:transparent;color:var(--ns-frame-muted);cursor:pointer}.lang-pill:hover{color:var(--ns-frame-ink)}.lang-pill.is-active{background:var(--ns-frame-glow);color:var(--ns-frame-on-glow)}.body{display:flex;flex:1;min-height:0}.sidebar{flex:none;width:max-content;min-width:224px;max-width:340px;padding:12px 10px;border-right:1px solid var(--ns-frame-line);transition:width .18s ease}.sidebar.is-collapsed{width:60px;min-width:0}.sidebar nav{display:flex;flex-direction:column;gap:3px}.nav-item{display:flex;align-items:center;gap:12px;width:100%;padding:var(--ns-nav-y, 9px) 12px;border:none;border-radius:6px;background:transparent;color:var(--ns-frame-muted);font-size:13px;font-weight:500;text-align:left;white-space:nowrap;cursor:pointer}.nav-item i{flex:none;font-size:15px}.nav-item:hover{background:var(--ns-frame-raised);color:var(--ns-frame-ink)}.nav-item.is-active{background:var(--ns-frame-raised);box-shadow:inset 2px 0 0 var(--ns-frame-glow);color:var(--ns-frame-ink)}.nav-item.is-active i{color:var(--ns-frame-glow)}.nav-caret{margin-left:auto;font-size:11px!important;opacity:.7}.nav-item.is-inert{opacity:.45;cursor:default}.nav-item.is-inert:hover{background:transparent;color:var(--ns-frame-muted)}.nav-label{overflow:hidden;text-overflow:ellipsis}.sidebar.is-collapsed .nav-label{display:none}.sidebar.is-collapsed .nav-item{justify-content:center;padding-inline:0}.content{flex:1;min-width:0;padding:28px 28px 64px;display:flex;flex-direction:column;gap:14px}.page-head{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:46px;padding:7px 16px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.page-head-main{display:flex;min-width:0;flex:1;align-items:center;gap:14px}.page-head-actions{display:flex;flex:none;align-items:center;gap:8px}.page-head h1{margin:0;font-size:19px;font-weight:600}.measure{display:flex;width:100%;max-width:var(--ac-content-max, 1440px);flex-direction:column;gap:14px;margin-inline:0}h1{margin:0;font-size:26px;line-height:1.2;font-weight:500;letter-spacing:-.02em}.access-menu{display:flex;flex-direction:column;gap:.15rem;margin-top:.75rem;padding-top:.75rem;border-top:1px solid var(--ns-frame-line)}.access-caption{margin:0 0 .4rem;padding:0 .75rem;color:var(--ns-frame-muted);font-size:.68rem;letter-spacing:.06em;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.access-state{margin:0;padding:.35rem .75rem;color:var(--ns-frame-muted);font-size:.78rem}.access-state.is-error{color:var(--p-red-400, #f87171)}.nav-item.is-child{padding-left:2.1rem;font-size:.86rem}@media(max-width:720px){.sidebar{max-width:none;position:fixed;top:var(--ns-topbar-h, 56px);bottom:0;left:0;z-index:30;width:268px;max-width:82vw;overflow-y:auto;box-shadow:0 18px 44px #00000073;transform:translate(-100%);transition:transform .18s ease}.sidebar.is-collapsed{width:268px;max-width:82vw;transform:translate(-100%)}.sidebar:not(.is-collapsed){transform:translate(0)}.sidebar.is-collapsed .nav-label{display:inline}.sidebar.is-collapsed .role-text{display:flex}.sidebar.is-collapsed .nav-item,.sidebar.is-collapsed .role-badge{justify-content:flex-start;padding-inline:12px}.brand-secondary{display:none}.topbar{height:auto;min-height:56px;flex-wrap:wrap;padding-bottom:8px;row-gap:8px}.context{order:3;width:100%;margin-left:0}.context-select{min-width:0;max-width:none;flex:1 1 0}.content{padding:20px 16px 48px}h1{font-size:22px}.page-head{align-items:stretch;flex-direction:column;gap:10px;padding:10px 14px}.page-head-actions{justify-content:flex-end}}.who{display:flex;align-items:center;gap:12px;padding:15px 15px 13px;border-bottom:1px solid var(--ac-border);background:var(--ns-header-bg)}.who-photo{width:42px;height:42px;flex:none;border-radius:999px;object-fit:cover}.who-initials{display:inline-flex;align-items:center;justify-content:center;background:var(--ac-accent);color:var(--ac-on-accent);font-size:15px;font-weight:600}.who-text{display:flex;min-width:0;flex-direction:column}.who-name{overflow:hidden;font-size:14px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.who-mail{overflow:hidden;color:var(--ac-text-muted);font-size:11.5px;text-overflow:ellipsis;white-space:nowrap}.who-role{display:flex;align-items:center;gap:7px;margin:0;overflow:hidden;padding:9px 15px;border-bottom:1px solid var(--ac-border);color:var(--ac-text-muted);font-size:11.5px;white-space:nowrap}.who-role b{flex:none;color:var(--ac-text);font-size:12px;font-weight:600}.who-sep{flex:none}.who-context{overflow:hidden;text-overflow:ellipsis}.who-dot{width:5px;height:5px;flex:none;border-radius:50%;background:var(--ac-accent)}.company-option{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%}.company-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.launcher-notice{display:flex;gap:10px;margin:12px 12px 0;padding:12px;border:1px solid color-mix(in srgb,var(--ac-accent) 40%,transparent);border-radius:8px;background:color-mix(in srgb,var(--ac-accent) 10%,transparent)}.launcher-notice i{margin-top:2px;color:var(--ac-accent);font-size:15px}.launcher-notice-title{margin:0 0 4px;font-size:13px;font-weight:600}.launcher-notice-body{margin:0;color:var(--ac-text-muted);font-size:12px;line-height:1.45}.confirm{display:flex;flex-direction:column;align-items:center;gap:6px;padding:26px 24px 20px;border:1px solid var(--ac-border);border-radius:14px;background:var(--ac-surface);text-align:center}.confirm h2{margin:8px 0 0;font-size:17px;font-weight:600}.confirm p{margin:0;max-width:34ch;color:var(--ac-text-muted);font-size:13px;line-height:1.5}.confirm-actions{display:flex;justify-content:center;gap:8px;margin-top:18px}.toast-text{flex:1;margin-left:12px}.toast-summary{margin:0;font-size:13px;font-weight:600}.toast-detail{margin:2px 0 0;color:var(--ac-text-muted);font-size:12px}.context{display:flex;min-width:0;align-items:center;gap:8px;margin-left:14px}.context-select{min-width:150px;max-width:210px}.role-badge{display:flex;align-items:center;gap:12px;margin-bottom:10px;padding:9px 12px;border-left:2px solid var(--ns-frame-glow);border-radius:0 7px 7px 0;background:var(--ns-frame-raised);box-shadow:-2px 0 12px -3px color-mix(in srgb,var(--ns-frame-glow) 65%,transparent)}.role-badge>i{flex:none;color:var(--ns-frame-glow);font-size:14px}.role-text{display:flex;min-width:0;flex-direction:column;gap:1px}.role-name{overflow:hidden;color:var(--ns-frame-ink);font-size:13px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.role-caption{color:var(--ns-frame-muted);font-size:10px;letter-spacing:.06em;text-transform:uppercase}.sidebar.is-collapsed .role-badge{justify-content:center;padding-inline:0}.sidebar-scrim{position:fixed;top:var(--ns-topbar-h, 56px);right:0;bottom:0;left:0;z-index:29;padding:0;border:0;background:#00000073;cursor:pointer}.nav-skeleton{display:flex;flex-direction:column;gap:3px}.nav-skeleton-item{display:flex;align-items:center;gap:12px;padding:11px 12px}.sidebar.is-collapsed .nav-skeleton-item .p-skeleton:last-child{display:none}\n"] }]
|
|
4123
|
+
], host: { '[style.--ns-topbar-h]': 'topbarHeight()' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let t = copy();\n@let me = identity();\n\n@if (starfield()) {\n <nucleus-starfield />\n}\n\n<header class=\"topbar ns-frame\">\n <div class=\"side\">\n <p-button\n icon=\"pi pi-bars\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.navToggle\"\n [pTooltip]=\"t.navToggle\"\n tooltipPosition=\"bottom\"\n (onClick)=\"toggleSidebar()\"\n />\n\n <div class=\"brand\">\n <nucleus-mark [size]=\"20\" />\n <div class=\"brand-name\">\n <span class=\"brand-primary\">NUCLEUS</span>\n <span class=\"brand-secondary\">{{ brand() }}</span>\n </div>\n </div>\n\n </div>\n\n @if (hasSiteContext()) {\n <div class=\"context ns-context\">\n <p-select\n styleClass=\"context-select\"\n [options]=\"companyChoices()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"companyChoice()\"\n (ngModelChange)=\"onCompanyChange($event)\"\n [placeholder]=\"t.companyPlaceholder\"\n [disabled]=\"switching()\"\n [filter]=\"companyChoices().length > 8\"\n filterBy=\"name\"\n [filterPlaceholder]=\"words().search\"\n [autofocusFilter]=\"true\"\n [resetFilterOnHide]=\"true\"\n [ariaLabel]=\"t.companyLabel\"\n [ngModelOptions]=\"{ standalone: true }\"\n >\n <ng-template #item let-option>\n <span class=\"company-option\">\n <span class=\"company-name\">{{ option.name }}</span>\n <p-tag [value]=\"option.tag\" severity=\"secondary\" />\n </span>\n </ng-template>\n </p-select>\n\n <p-select\n styleClass=\"context-select\"\n [options]=\"siteOptions()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"siteChoice()\"\n (ngModelChange)=\"onSiteChange($event)\"\n [placeholder]=\"sitePlaceholder()\"\n [disabled]=\"switching() || sitesLoading() || !siteOptions().length\"\n [filter]=\"siteOptions().length > 8\"\n filterBy=\"name\"\n [filterPlaceholder]=\"words().search\"\n [autofocusFilter]=\"true\"\n [resetFilterOnHide]=\"true\"\n [ariaLabel]=\"t.siteLabel\"\n [ngModelOptions]=\"{ standalone: true }\"\n />\n </div>\n }\n\n <div class=\"side is-end\">\n <div class=\"lang-switch\" role=\"group\" aria-label=\"Idioma / Language\">\n <button\n type=\"button\"\n class=\"lang-pill\"\n [class.is-active]=\"lang() === 'es'\"\n [attr.aria-pressed]=\"lang() === 'es'\"\n (click)=\"setLang('es')\"\n >\n ES\n </button>\n <button\n type=\"button\"\n class=\"lang-pill\"\n [class.is-active]=\"lang() === 'en'\"\n [attr.aria-pressed]=\"lang() === 'en'\"\n (click)=\"setLang('en')\"\n >\n EN\n </button>\n </div>\n\n <p-button\n icon=\"pi pi-th-large\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.appsLauncher\"\n [pTooltip]=\"t.appsLauncher\"\n tooltipPosition=\"bottom\"\n (onClick)=\"launcher.toggle($event)\"\n />\n\n <p-popover #launcher styleClass=\"ns-flush-popover\">\n @if (!hasCompany()) {\n <div class=\"launcher-notice\">\n <i class=\"pi pi-building\" aria-hidden=\"true\"></i>\n <div>\n <p class=\"launcher-notice-title\">{{ t.noCompanyTitle }}</p>\n <p class=\"launcher-notice-body\">{{ t.noCompanyHint }}</p>\n </div>\n </div>\n }\n\n <nucleus-menu\n [heading]=\"t.appsSwitch\"\n [badge]=\"launcherCount()\"\n [sections]=\"launcherSections()\"\n [searchable]=\"launcherRich()\"\n [searchPlaceholder]=\"t.appsSearch\"\n [emptyText]=\"launcherRich() ? t.appsNoMatch : t.appsEmpty\"\n [keyboardHint]=\"t.keyboardHint\"\n [width]=\"336\"\n (select)=\"onLauncherSelect($event); launcher.hide()\"\n (dismiss)=\"launcher.hide()\"\n />\n </p-popover>\n\n <p-button\n icon=\"pi pi-cog\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.settingsTitle\"\n [pTooltip]=\"t.settingsTitle\"\n tooltipPosition=\"bottom\"\n (onClick)=\"settingsOpen.set(true)\"\n />\n\n @if (me) {\n <p-button\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n styleClass=\"avatar-trigger\"\n [ariaLabel]=\"me.name\"\n [pTooltip]=\"me.name\"\n tooltipPosition=\"bottom\"\n (onClick)=\"account.toggle($event)\"\n >\n <p-avatar\n [image]=\"me.photoUrl ?? undefined\"\n [label]=\"me.photoUrl ? undefined : initials()\"\n shape=\"circle\"\n size=\"normal\"\n />\n </p-button>\n }\n </div>\n</header>\n\n<p-popover #account styleClass=\"ns-flush-popover\">\n @if (me) {\n <div class=\"who\">\n @if (me.photoUrl) {\n <img class=\"who-photo\" [src]=\"me.photoUrl\" alt=\"\" width=\"42\" height=\"42\" />\n } @else {\n <span class=\"who-photo who-initials\">{{ initials() }}</span>\n }\n <span class=\"who-text\">\n <span class=\"who-name\">{{ me.name }}</span>\n <span class=\"who-mail\">{{ me.email }}</span>\n </span>\n </div>\n\n <p class=\"who-role\">\n <span class=\"who-dot\" aria-hidden=\"true\"></span>\n @if (roleName(); as role) {\n <b>{{ role }}</b>\n <span class=\"who-sep\">\u00B7</span>\n }\n <span class=\"who-context\">{{ accountContext() }}</span>\n </p>\n\n <nucleus-menu\n [sections]=\"accountSections()\"\n [width]=\"304\"\n (select)=\"onAccountSelect($event); account.hide()\"\n (dismiss)=\"account.hide()\"\n />\n }\n</p-popover>\n\n<div class=\"body\">\n @if (narrow() && sidebarOpen()) {\n <button\n type=\"button\"\n class=\"sidebar-scrim\"\n [attr.aria-label]=\"t.navToggle\"\n (click)=\"toggleSidebar()\"\n ></button>\n }\n\n <aside class=\"sidebar ns-frame\" [class.is-collapsed]=\"!sidebarOpen()\">\n @if (roleName(); as role) {\n <div class=\"role-badge\" [pTooltip]=\"sidebarOpen() ? '' : role\" tooltipPosition=\"right\">\n <i class=\"pi pi-key\" aria-hidden=\"true\"></i>\n <span class=\"nav-label role-text\">\n <span class=\"role-name\">{{ role }}</span>\n <span class=\"role-caption\">{{ t.roleCaption }}</span>\n </span>\n </div>\n }\n\n @if (navItems().length) {\n <nav>\n @for (item of navItems(); track item.id) {\n <button\n type=\"button\"\n class=\"nav-item\"\n [class.is-active]=\"activeNavId() === item.id\"\n [attr.aria-current]=\"activeNavId() === item.id ? 'page' : null\"\n [pTooltip]=\"sidebarOpen() ? '' : item.label\"\n tooltipPosition=\"right\"\n (click)=\"selectNav(item.id)\"\n >\n <i [class]=\"item.icon\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ item.label }}</span>\n </button>\n }\n </nav>\n }\n\n <nav class=\"access-menu\">\n @if (menuLoading()) {\n <div class=\"nav-skeleton\" role=\"status\" [attr.aria-label]=\"t.accessLoading\">\n @for (width of menuPlaceholders; track $index) {\n <div class=\"nav-skeleton-item\">\n <p-skeleton shape=\"circle\" size=\"15px\" />\n <p-skeleton height=\"9px\" [width]=\"width\" />\n </div>\n }\n </div>\n } @else if (menuError()) {\n <p class=\"access-state is-error\">{{ menuError() }}</p>\n } @else if (!menu().length) {\n <p class=\"access-state\">{{ t.accessEmpty }}</p>\n } @else {\n @for (node of menu(); track node.id) {\n @let group = isGroup(node);\n @let open = isExpanded(node);\n\n <button\n type=\"button\"\n class=\"nav-item\"\n [class.is-active]=\"!group && isSelected(node)\"\n [class.is-inert]=\"!group && !node.route\"\n [attr.aria-expanded]=\"group ? open : null\"\n [disabled]=\"!group && !node.route\"\n [pTooltip]=\"sidebarOpen() ? '' : node.label\"\n tooltipPosition=\"right\"\n (click)=\"selectMenu(node)\"\n >\n <i [class]=\"node.icon ?? 'pi pi-circle'\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ node.label }}</span>\n @if (group && sidebarOpen()) {\n <i\n class=\"pi nav-caret\"\n [class.pi-chevron-down]=\"open\"\n [class.pi-chevron-right]=\"!open\"\n aria-hidden=\"true\"\n ></i>\n }\n </button>\n\n @if (open) {\n @for (child of node.children; track child.id) {\n <button\n type=\"button\"\n class=\"nav-item is-child\"\n [class.is-active]=\"isSelected(child)\"\n [pTooltip]=\"sidebarOpen() ? '' : child.label\"\n tooltipPosition=\"right\"\n (click)=\"selectMenu(child)\"\n >\n <i [class]=\"child.icon ?? 'pi pi-circle'\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ child.label }}</span>\n </button>\n }\n }\n }\n }\n </nav>\n </aside>\n\n <main class=\"content\">\n <div class=\"measure\">\n <ng-content select=\"[nucleusTop]\" />\n\n @if (crumbs().length || title() || pageActions()) {\n <header class=\"page-head\">\n <div class=\"page-head-main\">\n @if (crumbs().length) {\n <p-breadcrumb [model]=\"crumbs()\" [home]=\"home()\" styleClass=\"ns-crumbs\" />\n }\n\n @if (title()) {\n <h1>{{ title() }}</h1>\n }\n </div>\n\n @if (pageActions(); as actions) {\n <div class=\"page-head-actions\">\n <ng-container [ngTemplateOutlet]=\"actions\" />\n </div>\n }\n </header>\n }\n\n <ng-content />\n </div>\n </main>\n</div>\n\n<p-drawer\n [visible]=\"settingsOpen()\"\n (visibleChange)=\"settingsOpen.set($event)\"\n position=\"right\"\n [header]=\"t.settingsTitle\"\n [modal]=\"false\"\n [blockScroll]=\"false\"\n styleClass=\"ns-settings-drawer\"\n [style]=\"{ width: '380px' }\"\n>\n <nucleus-appearance />\n</p-drawer>\n\n<p-toast position=\"bottom-right\" styleClass=\"ns-toast\">\n <ng-template #message let-message>\n <nucleus-lordicon\n [src]=\"message.severity === 'success' ? icons.check : icons.warning\"\n [tone]=\"message.severity === 'success' ? 'accent' : 'danger'\"\n [size]=\"34\"\n trigger=\"in\"\n />\n <div class=\"toast-text\">\n <p class=\"toast-summary\">{{ message.summary }}</p>\n @if (message.detail) {\n <p class=\"toast-detail\">{{ message.detail }}</p>\n }\n </div>\n </ng-template>\n</p-toast>\n\n<p-confirmdialog [style]=\"{ width: '420px' }\">\n <ng-template #headless let-message let-onAccept=\"onAccept\" let-onReject=\"onReject\">\n <div class=\"confirm\">\n <nucleus-lordicon\n [src]=\"message.icon\"\n [tone]=\"message.acceptButtonStyleClass ? 'danger' : 'accent'\"\n [size]=\"64\"\n trigger=\"loop\"\n />\n <h2>{{ message.header }}</h2>\n <p>{{ message.message }}</p>\n <div class=\"confirm-actions\">\n <p-button\n [label]=\"message.rejectLabel\"\n severity=\"secondary\"\n [text]=\"true\"\n (onClick)=\"onReject()\"\n />\n <p-button\n [label]=\"message.acceptLabel\"\n [severity]=\"message.acceptButtonStyleClass ? 'danger' : 'primary'\"\n (onClick)=\"onAccept()\"\n />\n </div>\n </div>\n </ng-template>\n</p-confirmdialog>\n", styles: [":host{display:flex;flex-direction:column;min-height:100dvh;background:var(--ac-bg);color:var(--ac-text)}.topbar{position:sticky;top:0;z-index:20;display:flex;align-items:center;justify-content:flex-start;gap:16px;height:56px;padding:0 12px 0 8px;border-bottom:1px solid var(--ns-frame-line)}.side{display:flex;min-width:0;align-items:center;gap:4px}.side.is-end{margin-left:auto}.brand{display:flex;align-items:center;gap:9px;margin-left:4px}.brand-name{display:flex;align-items:baseline;gap:7px}.brand-primary{font-size:13px;font-weight:700;letter-spacing:.15em}.brand-secondary{font-size:9px;font-weight:500;letter-spacing:.22em;color:var(--ns-frame-muted)}.lang-switch{display:flex;align-items:center;gap:2px;margin-right:6px;border:1px solid var(--ns-frame-line);border-radius:999px;padding:2px}.lang-pill{font-size:10px;font-weight:600;letter-spacing:.08em;padding:4px 10px;border:none;border-radius:999px;background:transparent;color:var(--ns-frame-muted);cursor:pointer}.lang-pill:hover{color:var(--ns-frame-ink)}.lang-pill.is-active{background:var(--ns-frame-glow);color:var(--ns-frame-on-glow)}.body{display:flex;flex:1;min-height:0}.sidebar{flex:none;width:max-content;min-width:224px;max-width:340px;padding:12px 10px;border-right:1px solid var(--ns-frame-line);transition:width .18s ease}.sidebar.is-collapsed{width:60px;min-width:0}.sidebar nav{display:flex;flex-direction:column;gap:3px}.nav-item{display:flex;align-items:center;gap:12px;width:100%;padding:var(--ns-nav-y, 9px) 12px;border:none;border-radius:6px;background:transparent;color:var(--ns-frame-muted);font-size:13px;font-weight:500;text-align:left;white-space:nowrap;cursor:pointer}.nav-item i{flex:none;font-size:15px}.nav-item:hover{background:var(--ns-frame-raised);color:var(--ns-frame-ink)}.nav-item.is-active{background:var(--ns-frame-raised);box-shadow:inset 2px 0 0 var(--ns-frame-glow);color:var(--ns-frame-ink)}.nav-item.is-active i{color:var(--ns-frame-glow)}.nav-caret{margin-left:auto;font-size:11px!important;opacity:.7}.nav-item.is-inert{opacity:.45;cursor:default}.nav-item.is-inert:hover{background:transparent;color:var(--ns-frame-muted)}.nav-label{overflow:hidden;text-overflow:ellipsis}.sidebar.is-collapsed .nav-label{display:none}.sidebar.is-collapsed .nav-item{justify-content:center;padding-inline:0}.content{flex:1;min-width:0;padding:28px 28px 64px;display:flex;flex-direction:column;gap:14px}.page-head{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:46px;padding:7px 16px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.page-head-main{display:flex;min-width:0;flex:1;align-items:center;gap:14px}.page-head-actions{display:flex;flex:none;align-items:center;gap:8px}.page-head h1{margin:0;font-size:19px;font-weight:600}.measure{display:flex;width:100%;max-width:var(--ac-content-max, 1440px);flex-direction:column;gap:14px;margin-inline:0}h1{margin:0;font-size:26px;line-height:1.2;font-weight:500;letter-spacing:-.02em}.access-menu{display:flex;flex-direction:column;gap:.15rem;margin-top:.75rem;padding-top:.75rem;border-top:1px solid var(--ns-frame-line)}.access-caption{margin:0 0 .4rem;padding:0 .75rem;color:var(--ns-frame-muted);font-size:.68rem;letter-spacing:.06em;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.access-state{margin:0;padding:.35rem .75rem;color:var(--ns-frame-muted);font-size:.78rem}.access-state.is-error{color:var(--p-red-400, #f87171)}.nav-item.is-child{padding-left:2.1rem;font-size:.86rem}@media(max-width:720px){.sidebar{max-width:none;position:fixed;top:var(--ns-topbar-h, 56px);bottom:0;left:0;z-index:30;width:268px;max-width:82vw;overflow-y:auto;box-shadow:0 18px 44px #00000073;transform:translate(-100%);transition:transform .18s ease}.sidebar.is-collapsed{width:268px;max-width:82vw;transform:translate(-100%)}.sidebar:not(.is-collapsed){transform:translate(0)}.sidebar.is-collapsed .nav-label{display:inline}.sidebar.is-collapsed .role-text{display:flex}.sidebar.is-collapsed .nav-item,.sidebar.is-collapsed .role-badge{justify-content:flex-start;padding-inline:12px}.brand-secondary{display:none}.topbar{height:auto;min-height:56px;flex-wrap:wrap;padding-bottom:8px;row-gap:8px}.context{order:3;width:100%;margin-left:0}.context-select{min-width:0;max-width:none;flex:1 1 0}.content{padding:20px 16px 48px}h1{font-size:22px}.page-head{gap:10px;min-height:42px;padding:7px 12px}.page-head-main{gap:8px}.page-head h1{overflow:hidden;min-width:0;font-size:16px;text-overflow:ellipsis;white-space:nowrap}.page-head-actions{flex-wrap:wrap;justify-content:flex-end;gap:6px}.page-head-actions ::ng-deep .p-button{padding-block:6px;padding-inline:11px;font-size:13px;white-space:nowrap}.page-head-actions ::ng-deep .p-button-icon{font-size:13px}}.who{display:flex;align-items:center;gap:12px;padding:15px 15px 13px;border-bottom:1px solid var(--ac-border);background:var(--ns-header-bg)}.who-photo{width:42px;height:42px;flex:none;border-radius:999px;object-fit:cover}.who-initials{display:inline-flex;align-items:center;justify-content:center;background:var(--ac-accent);color:var(--ac-on-accent);font-size:15px;font-weight:600}.who-text{display:flex;min-width:0;flex-direction:column}.who-name{overflow:hidden;font-size:14px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.who-mail{overflow:hidden;color:var(--ac-text-muted);font-size:11.5px;text-overflow:ellipsis;white-space:nowrap}.who-role{display:flex;align-items:center;gap:7px;margin:0;overflow:hidden;padding:9px 15px;border-bottom:1px solid var(--ac-border);color:var(--ac-text-muted);font-size:11.5px;white-space:nowrap}.who-role b{flex:none;color:var(--ac-text);font-size:12px;font-weight:600}.who-sep{flex:none}.who-context{overflow:hidden;text-overflow:ellipsis}.who-dot{width:5px;height:5px;flex:none;border-radius:50%;background:var(--ac-accent)}.company-option{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%}.company-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.launcher-notice{display:flex;gap:10px;margin:12px 12px 0;padding:12px;border:1px solid color-mix(in srgb,var(--ac-accent) 40%,transparent);border-radius:8px;background:color-mix(in srgb,var(--ac-accent) 10%,transparent)}.launcher-notice i{margin-top:2px;color:var(--ac-accent);font-size:15px}.launcher-notice-title{margin:0 0 4px;font-size:13px;font-weight:600}.launcher-notice-body{margin:0;color:var(--ac-text-muted);font-size:12px;line-height:1.45}.confirm{display:flex;flex-direction:column;align-items:center;gap:6px;padding:26px 24px 20px;border:1px solid var(--ac-border);border-radius:14px;background:var(--ac-surface);text-align:center}.confirm h2{margin:8px 0 0;font-size:17px;font-weight:600}.confirm p{margin:0;max-width:34ch;color:var(--ac-text-muted);font-size:13px;line-height:1.5}.confirm-actions{display:flex;justify-content:center;gap:8px;margin-top:18px}.toast-text{flex:1;margin-left:12px}.toast-summary{margin:0;font-size:13px;font-weight:600}.toast-detail{margin:2px 0 0;color:var(--ac-text-muted);font-size:12px}.context{display:flex;min-width:0;align-items:center;gap:8px;margin-left:14px}.context-select{min-width:150px;max-width:210px}.role-badge{display:flex;align-items:center;gap:12px;margin-bottom:10px;padding:9px 12px;border-left:2px solid var(--ns-frame-glow);border-radius:0 7px 7px 0;background:var(--ns-frame-raised);box-shadow:-2px 0 12px -3px color-mix(in srgb,var(--ns-frame-glow) 65%,transparent)}.role-badge>i{flex:none;color:var(--ns-frame-glow);font-size:14px}.role-text{display:flex;min-width:0;flex-direction:column;gap:1px}.role-name{overflow:hidden;color:var(--ns-frame-ink);font-size:13px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.role-caption{color:var(--ns-frame-muted);font-size:10px;letter-spacing:.06em;text-transform:uppercase}.sidebar.is-collapsed .role-badge{justify-content:center;padding-inline:0}.sidebar-scrim{position:fixed;top:var(--ns-topbar-h, 56px);right:0;bottom:0;left:0;z-index:29;padding:0;border:0;background:#00000073;cursor:pointer}.nav-skeleton{display:flex;flex-direction:column;gap:3px}.nav-skeleton-item{display:flex;align-items:center;gap:12px;padding:11px 12px}.sidebar.is-collapsed .nav-skeleton-item .p-skeleton:last-child{display:none}\n"] }]
|
|
3794
4124
|
}], ctorParameters: () => [], propDecorators: { brand: [{ type: i0.Input, args: [{ isSignal: true, alias: "brand", required: false }] }], heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: false }] }], navItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "navItems", required: false }] }], activeNavId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeNavId", required: false }] }], selectedMenuId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedMenuId", required: false }] }], navSelect: [{ type: i0.Output, args: ["navSelect"] }], menuSelect: [{ type: i0.Output, args: ["menuSelect"] }] } });
|
|
3795
4125
|
function initialsOf(source) {
|
|
3796
4126
|
const parts = source.trim().split(/\s+/).filter(Boolean);
|
|
@@ -3800,10 +4130,28 @@ function initialsOf(source) {
|
|
|
3800
4130
|
return parts[0].slice(0, 2).toUpperCase();
|
|
3801
4131
|
return (parts[0][0] + parts[1][0]).toUpperCase();
|
|
3802
4132
|
}
|
|
4133
|
+
function hasRoute(nodes, route) {
|
|
4134
|
+
return nodes.some((node) => node.route === route || hasRoute(node.children, route));
|
|
4135
|
+
}
|
|
4136
|
+
function homeNode(route, label) {
|
|
4137
|
+
return {
|
|
4138
|
+
id: HOME_MENU_ID,
|
|
4139
|
+
label,
|
|
4140
|
+
icon: 'pi pi-home',
|
|
4141
|
+
route,
|
|
4142
|
+
sortOrder: -1,
|
|
4143
|
+
canView: true,
|
|
4144
|
+
canInsert: false,
|
|
4145
|
+
canEdit: false,
|
|
4146
|
+
canDelete: false,
|
|
4147
|
+
canExport: false,
|
|
4148
|
+
children: [],
|
|
4149
|
+
};
|
|
4150
|
+
}
|
|
3803
4151
|
|
|
3804
4152
|
/**
|
|
3805
4153
|
* Generated bundle index. Do not edit.
|
|
3806
4154
|
*/
|
|
3807
4155
|
|
|
3808
|
-
export { ACCENTS, CANVASES, COMMON_COPY, CONTROL_CONTRAST, DEFAULT_APPEARANCE, DENSITIES, EMPTY_GEO_VALUE, FIELD_TARGETS, FRAMES, GEO_COPY, LEGACY_THEMES, NO_PERMISSIONS, NUCLEUS_ACCENTS, NUCLEUS_CONFIG, NUCLEUS_DARK_SELECTOR, NUCLEUS_FORCE_BEARER, NUCLEUS_ICONS, NUCLEUS_ICON_CATALOG, NUCLEUS_LANGS, NUCLEUS_LOGOUT_PARAM, NUCLEUS_SKIP_AUTH, NucleusAppearance, NucleusAuth, NucleusCache, NucleusCard, NucleusCell, NucleusColorPicker, NucleusEnterAdvance, NucleusFeedback, NucleusForm, NucleusGeo, NucleusGeoSelect, NucleusIconPicker, NucleusLanguage, NucleusList, NucleusLordicon, NucleusMark, NucleusMenu, NucleusMetric, NucleusMetrics, NucleusPage, NucleusPageActions, NucleusPreset, NucleusRecentApps, NucleusSessionAuth, NucleusShell, NucleusShortcut, NucleusShortcuts, NucleusStarfield, NucleusTabs, SHELL_COPY, SessionService, TEXT_CONTRAST, THEME_COPY, ThemeService, UserSyncService, accentById, accentLabelOf, accentOn, ariaKeysOf, auditAppearance, canvasById, clock, comboOf, commonCopyOf, consumeNucleusLogout, contrastIssue, contrastRatio, day, densityById, endOfDayUtc, fieldsIn, findMenuByRoute, flagOf, foldText, frameById, geoCopyOf, hasChildren, hasModifier, iconClassOf, iconNameOf, integer, isAccentPreference, isApplePlatform, isBeforeToday, isCanvasPreference, isDarkCanvas, isDensityId, isFieldSearchable, isFrameId, isNucleusConfigured, isOnOrBeforeToday, isReachable, isToday, isTypingTarget, isoDay, levelLabel, loadLordicon, loadNucleusConfig, matchesRow, meetsContrast, menuGlyph, menuTile, minutesAsClock, mixHex, money, moveTo, normalizeKeys, nucleusAuthInterceptor, nucleusErrorMessage, nucleusLang, nucleusLogoutUrl, nucleusParseDate, ownsUrl, percent, permissionsOf, provideNucleus, provideNucleusFeedback, provideNucleusTheme, qty, readableOn, relativeLuminance, resolveAccent, resolveFieldSize, searchIcons, selectableRows, shiftDay, shortcutHint, signedMoney, stamp, startOfDayUtc, themeCopyOf, toNumber, toggleCollapsed, visibleTreeRows };
|
|
4156
|
+
export { ACCENTS, CANVASES, COMMON_COPY, CONTROL_CONTRAST, DEFAULT_APPEARANCE, DENSITIES, EMPTY_GEO_VALUE, FIELD_TARGETS, FRAMES, GEO_COPY, LEGACY_THEMES, NO_PERMISSIONS, NUCLEUS_ACCENTS, NUCLEUS_CONFIG, NUCLEUS_DARK_SELECTOR, NUCLEUS_FORCE_BEARER, NUCLEUS_HOME, NUCLEUS_ICONS, NUCLEUS_ICON_CATALOG, NUCLEUS_LANGS, NUCLEUS_LOGOUT_PARAM, NUCLEUS_NARROW_QUERY, NUCLEUS_SKIP_AUTH, NucleusAppearance, NucleusAuth, NucleusCache, NucleusCard, NucleusCell, NucleusColorPicker, NucleusEnterAdvance, NucleusFeedback, NucleusForm, NucleusGeo, NucleusGeoSelect, NucleusIconPicker, NucleusLanguage, NucleusLink, NucleusList, NucleusLordicon, NucleusMark, NucleusMenu, NucleusMetric, NucleusMetrics, NucleusPage, NucleusPageActions, NucleusPreset, NucleusRecentApps, NucleusSessionAuth, NucleusShell, NucleusShortcut, NucleusShortcuts, NucleusStarfield, NucleusTabs, NucleusViewport, SHELL_COPY, SessionService, TEXT_CONTRAST, THEME_COPY, ThemeService, UserSyncService, accentById, accentLabelOf, accentOn, ariaKeysOf, auditAppearance, canvasById, clock, comboOf, commonCopyOf, consumeNucleusLogout, contrastIssue, contrastRatio, day, densityById, endOfDayUtc, fieldsIn, findMenuByRoute, flagOf, foldText, frameById, geoCopyOf, hasChildren, hasModifier, iconClassOf, iconNameOf, integer, isAccentPreference, isApplePlatform, isBeforeToday, isCanvasPreference, isDarkCanvas, isDensityId, isFieldSearchable, isFrameId, isHomeRoute, isNucleusConfigured, isOnOrBeforeToday, isReachable, isToday, isTypingTarget, isUnderRoute, isoDay, levelLabel, loadLordicon, loadNucleusConfig, matchMenuByRoute, matchesRow, meetsContrast, menuGlyph, menuTile, minutesAsClock, mixHex, money, moveTo, normalizeHomeRoute, normalizeKeys, nucleusAccessGuard, nucleusAuthInterceptor, nucleusErrorMessage, nucleusLang, nucleusLogoutUrl, nucleusParseDate, ownsUrl, percent, permissionsOf, provideNucleus, provideNucleusFeedback, provideNucleusHome, provideNucleusTheme, qty, readableOn, relativeLuminance, resolveAccent, resolveFieldSize, routePath, searchIcons, selectableRows, shiftDay, shortcutHint, signedMoney, stamp, startOfDayUtc, themeCopyOf, toNumber, toggleCollapsed, visibleTreeRows };
|
|
3809
4157
|
//# sourceMappingURL=nucleus-suite-pe-core.mjs.map
|