@nucleus-suite-pe/core 0.6.1 → 0.7.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.
@@ -1,34 +1,34 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, makeEnvironmentProviders, inject, Injector, signal, computed, Injectable, effect, input, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, model, output, TemplateRef, Directive, contentChildren, untracked } from '@angular/core';
2
+ import { InjectionToken, makeEnvironmentProviders, inject, Injector, signal, computed, Injectable, effect, model, input, untracked, ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, output, TemplateRef, Directive, contentChildren } from '@angular/core';
3
3
  import { HttpContextToken, HttpClient, HttpContext, HttpErrorResponse } from '@angular/common/http';
4
4
  import { firstValueFrom, catchError, throwError, from, switchMap } from 'rxjs';
5
+ import * as i6 from '@angular/forms';
6
+ import { FormsModule } from '@angular/forms';
7
+ import * as i1 from 'primeng/select';
8
+ import { SelectModule } from 'primeng/select';
5
9
  import { definePreset } from '@primeuix/themes';
6
10
  import Lara from '@primeuix/themes/lara';
7
11
  import { providePrimeNG } from 'primeng/config';
8
12
  import { ConfirmationService, MessageService } from 'primeng/api';
9
- import * as i6 from '@angular/forms';
10
- import { FormsModule } from '@angular/forms';
11
- import * as i1 from 'primeng/checkbox';
13
+ import * as i1$1 from 'primeng/checkbox';
12
14
  import { CheckboxModule } from 'primeng/checkbox';
13
15
  import * as i2 from 'primeng/inputtext';
14
16
  import { InputTextModule } from 'primeng/inputtext';
15
- import * as i3 from 'primeng/select';
16
- import { SelectModule } from 'primeng/select';
17
17
  import * as i4 from 'primeng/textarea';
18
18
  import { TextareaModule } from 'primeng/textarea';
19
19
  import * as i5 from 'primeng/toggleswitch';
20
20
  import { ToggleSwitchModule } from 'primeng/toggleswitch';
21
21
  import { NgTemplateOutlet } from '@angular/common';
22
- import * as i1$1 from 'primeng/button';
22
+ import * as i1$2 from 'primeng/button';
23
23
  import { ButtonModule } from 'primeng/button';
24
24
  import * as i2$1 from 'primeng/table';
25
25
  import { TableModule } from 'primeng/table';
26
- import * as i3$1 from 'primeng/tag';
26
+ import * as i3 from 'primeng/tag';
27
27
  import { TagModule } from 'primeng/tag';
28
28
  import * as i4$1 from 'primeng/tooltip';
29
29
  import { TooltipModule } from 'primeng/tooltip';
30
30
  import { Router } from '@angular/router';
31
- import * as i1$2 from 'primeng/avatar';
31
+ import * as i1$3 from 'primeng/avatar';
32
32
  import { AvatarModule } from 'primeng/avatar';
33
33
  import * as i2$2 from 'primeng/breadcrumb';
34
34
  import { BreadcrumbModule } from 'primeng/breadcrumb';
@@ -485,6 +485,332 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
485
485
  args: [{ providedIn: 'root' }]
486
486
  }], ctorParameters: () => [] });
487
487
 
488
+ const EMPTY_GEO_VALUE = { countryId: null, divisionId: null };
489
+ function flagOf(code) {
490
+ if (code.length !== 2)
491
+ return '';
492
+ return String.fromCodePoint(...[...code.toUpperCase()].map((letter) => 0x1f1a5 + letter.charCodeAt(0)));
493
+ }
494
+
495
+ const GEO_COPY = {
496
+ es: {
497
+ country: 'País',
498
+ choose: 'Selecciona',
499
+ search: 'Buscar',
500
+ levels: ['Región', 'Provincia', 'Distrito', 'Zona'],
501
+ kinds: {
502
+ department: 'Departamento',
503
+ province: 'Provincia',
504
+ district: 'Distrito',
505
+ region: 'Región',
506
+ state: 'Estado',
507
+ municipality: 'Municipio',
508
+ county: 'Condado',
509
+ parish: 'Parroquia',
510
+ prefecture: 'Prefectura',
511
+ governorate: 'Gobernación',
512
+ territory: 'Territorio',
513
+ canton: 'Cantón',
514
+ emirate: 'Emirato',
515
+ oblast: 'Óblast',
516
+ city: 'Ciudad',
517
+ division: 'División',
518
+ republic: 'República',
519
+ 'autonomous community': 'Comunidad autónoma',
520
+ 'federal district': 'Distrito federal',
521
+ 'capital city': 'Ciudad capital',
522
+ 'metropolitan department': 'Departamento metropolitano',
523
+ 'unitary authority': 'Autoridad unitaria',
524
+ },
525
+ },
526
+ en: {
527
+ country: 'Country',
528
+ choose: 'Select',
529
+ search: 'Search',
530
+ levels: ['Region', 'Province', 'District', 'Area'],
531
+ kinds: {
532
+ department: 'Department',
533
+ province: 'Province',
534
+ district: 'District',
535
+ region: 'Region',
536
+ state: 'State',
537
+ municipality: 'Municipality',
538
+ county: 'County',
539
+ parish: 'Parish',
540
+ prefecture: 'Prefecture',
541
+ governorate: 'Governorate',
542
+ territory: 'Territory',
543
+ canton: 'Canton',
544
+ emirate: 'Emirate',
545
+ oblast: 'Oblast',
546
+ city: 'City',
547
+ division: 'Division',
548
+ republic: 'Republic',
549
+ 'autonomous community': 'Autonomous community',
550
+ 'federal district': 'Federal district',
551
+ 'capital city': 'Capital city',
552
+ 'metropolitan department': 'Metropolitan department',
553
+ 'unitary authority': 'Unitary authority',
554
+ },
555
+ },
556
+ };
557
+ function geoCopyOf(lang) {
558
+ return lang === 'en' ? GEO_COPY.en : GEO_COPY.es;
559
+ }
560
+ function levelLabel(copy, level, kind) {
561
+ if (kind) {
562
+ const known = copy.kinds[kind.toLowerCase()];
563
+ if (known)
564
+ return known;
565
+ }
566
+ const index = Math.min(Math.max(level, 1), copy.levels.length) - 1;
567
+ return copy.levels[index];
568
+ }
569
+
570
+ const EMPTY_LEVEL = { level: 0, kind: null, items: [] };
571
+ class NucleusGeo {
572
+ http = inject(HttpClient);
573
+ config = inject(NUCLEUS_CONFIG);
574
+ cache = new Map();
575
+ countries(language) {
576
+ return this.once(`countries|${language}`, () => firstValueFrom(this.http.get(`${this.config.securityApiUrl}/geo/countries`, {
577
+ params: { language },
578
+ })));
579
+ }
580
+ divisions(countryId, parentId, language) {
581
+ const params = { language };
582
+ if (parentId)
583
+ params['parentId'] = parentId;
584
+ return this.once(`divisions|${countryId}|${parentId ?? ''}|${language}`, () => firstValueFrom(this.http.get(`${this.config.securityApiUrl}/geo/countries/${countryId}/divisions`, { params })));
585
+ }
586
+ place(divisionId, language) {
587
+ return this.once(`place|${divisionId}|${language}`, () => firstValueFrom(this.http.get(`${this.config.securityApiUrl}/geo/divisions/${divisionId}/place`, { params: { language } })));
588
+ }
589
+ async levelOf(countryId, parentId, language) {
590
+ try {
591
+ return await this.divisions(countryId, parentId, language);
592
+ }
593
+ catch {
594
+ return EMPTY_LEVEL;
595
+ }
596
+ }
597
+ once(key, load) {
598
+ const cached = this.cache.get(key);
599
+ if (cached)
600
+ return cached;
601
+ const started = load().catch((error) => {
602
+ this.cache.delete(key);
603
+ throw error;
604
+ });
605
+ this.cache.set(key, started);
606
+ return started;
607
+ }
608
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusGeo, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
609
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusGeo, providedIn: 'root' });
610
+ }
611
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusGeo, decorators: [{
612
+ type: Injectable,
613
+ args: [{ providedIn: 'root' }]
614
+ }] });
615
+
616
+ class NucleusGeoSelect {
617
+ geo = inject(NucleusGeo);
618
+ language = inject(NucleusLanguage);
619
+ value = model(EMPTY_GEO_VALUE, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
620
+ readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
621
+ columns = input(null, ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
622
+ countries = signal([], ...(ngDevMode ? [{ debugName: "countries" }] : /* istanbul ignore next */ []));
623
+ steps = signal([], ...(ngDevMode ? [{ debugName: "steps" }] : /* istanbul ignore next */ []));
624
+ labels = computed(() => geoCopyOf(this.language.lang()), ...(ngDevMode ? [{ debugName: "labels" }] : /* istanbul ignore next */ []));
625
+ syncedKey = null;
626
+ constructor() {
627
+ effect(() => {
628
+ const lang = this.language.lang();
629
+ const current = this.value();
630
+ const key = `${lang}|${current.countryId ?? ''}|${current.divisionId ?? ''}`;
631
+ if (key === this.syncedKey)
632
+ return;
633
+ this.syncedKey = key;
634
+ untracked(() => void this.sync(current, lang));
635
+ });
636
+ }
637
+ gridClass() {
638
+ const columns = this.columns();
639
+ return columns ? `is-cap-${Math.min(Math.max(columns, 1), 4)}` : '';
640
+ }
641
+ nameOf(step) {
642
+ return levelLabel(this.labels(), step.level, step.kind);
643
+ }
644
+ async pickCountry(countryId) {
645
+ const lang = this.language.lang();
646
+ this.syncedKey = `${lang}|${countryId ?? ''}|`;
647
+ this.value.set({ countryId, divisionId: null });
648
+ if (!countryId) {
649
+ this.steps.set([]);
650
+ return;
651
+ }
652
+ const first = await this.geo.levelOf(countryId, null, lang);
653
+ this.steps.set(first.items.length ? [toStep(first.level, first.kind, first.items, null)] : []);
654
+ }
655
+ async pick(index, divisionId) {
656
+ const countryId = this.value().countryId;
657
+ if (!countryId)
658
+ return;
659
+ const lang = this.language.lang();
660
+ const next = this.steps().slice(0, index + 1);
661
+ const current = next[index];
662
+ if (!current)
663
+ return;
664
+ next[index] = { ...current, selectedId: divisionId };
665
+ if (divisionId) {
666
+ const child = await this.geo.levelOf(countryId, divisionId, lang);
667
+ if (child.items.length) {
668
+ next.push(toStep(child.level, child.kind, child.items, null));
669
+ }
670
+ }
671
+ this.steps.set(next);
672
+ const deepest = deepestOf(next);
673
+ this.syncedKey = `${lang}|${countryId}|${deepest ?? ''}`;
674
+ this.value.set({ countryId, divisionId: deepest });
675
+ }
676
+ async sync(value, lang) {
677
+ this.countries.set([...(await this.geo.countries(lang))]);
678
+ if (!value.countryId) {
679
+ this.steps.set([]);
680
+ return;
681
+ }
682
+ if (!value.divisionId) {
683
+ const first = await this.geo.levelOf(value.countryId, null, lang);
684
+ this.steps.set(first.items.length ? [toStep(first.level, first.kind, first.items, null)] : []);
685
+ return;
686
+ }
687
+ const place = await this.geo.place(value.divisionId, lang);
688
+ const built = [];
689
+ let parentId = null;
690
+ for (const node of place.trail) {
691
+ const level = await this.geo.levelOf(place.countryId, parentId, lang);
692
+ if (!level.items.length)
693
+ break;
694
+ built.push(toStep(level.level, level.kind, level.items, node.id));
695
+ parentId = node.id;
696
+ }
697
+ const tail = await this.geo.levelOf(place.countryId, parentId, lang);
698
+ if (tail.items.length) {
699
+ built.push(toStep(tail.level, tail.kind, tail.items, null));
700
+ }
701
+ this.steps.set(built);
702
+ }
703
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusGeoSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
704
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: NucleusGeoSelect, isStandalone: true, selector: "nucleus-geo-select", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, ngImport: i0, template: `
705
+ @let copy = labels();
706
+
707
+ <div class="ns-form-grid" [class]="gridClass()">
708
+ <div class="ns-field is-span-1 is-size-md">
709
+ <label for="ns-geo-country">{{ copy.country }}</label>
710
+ <p-select
711
+ inputId="ns-geo-country"
712
+ [options]="countries()"
713
+ optionLabel="name"
714
+ optionValue="id"
715
+ [ngModel]="value().countryId"
716
+ (ngModelChange)="pickCountry($event)"
717
+ [disabled]="readonly()"
718
+ [filter]="true"
719
+ filterBy="name"
720
+ [filterPlaceholder]="copy.search"
721
+ [showClear]="true"
722
+ [placeholder]="copy.choose"
723
+ [ngModelOptions]="{ standalone: true }"
724
+ fluid
725
+ />
726
+ </div>
727
+
728
+ @for (step of steps(); track step.level; let index = $index) {
729
+ <div class="ns-field is-span-1 is-size-md">
730
+ <label [attr.for]="'ns-geo-' + step.level">{{ nameOf(step) }}</label>
731
+ <p-select
732
+ [inputId]="'ns-geo-' + step.level"
733
+ [options]="step.items"
734
+ optionLabel="name"
735
+ optionValue="id"
736
+ [ngModel]="step.selectedId"
737
+ (ngModelChange)="pick(index, $event)"
738
+ [disabled]="readonly()"
739
+ [filter]="step.items.length > 12"
740
+ filterBy="name"
741
+ [filterPlaceholder]="copy.search"
742
+ [showClear]="true"
743
+ [placeholder]="copy.choose"
744
+ [ngModelOptions]="{ standalone: true }"
745
+ fluid
746
+ />
747
+ </div>
748
+ }
749
+ </div>
750
+ `, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: SelectModule }, { kind: "component", type: i1.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: FormsModule }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
751
+ }
752
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusGeoSelect, decorators: [{
753
+ type: Component,
754
+ args: [{ selector: 'nucleus-geo-select', imports: [SelectModule, FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
755
+ @let copy = labels();
756
+
757
+ <div class="ns-form-grid" [class]="gridClass()">
758
+ <div class="ns-field is-span-1 is-size-md">
759
+ <label for="ns-geo-country">{{ copy.country }}</label>
760
+ <p-select
761
+ inputId="ns-geo-country"
762
+ [options]="countries()"
763
+ optionLabel="name"
764
+ optionValue="id"
765
+ [ngModel]="value().countryId"
766
+ (ngModelChange)="pickCountry($event)"
767
+ [disabled]="readonly()"
768
+ [filter]="true"
769
+ filterBy="name"
770
+ [filterPlaceholder]="copy.search"
771
+ [showClear]="true"
772
+ [placeholder]="copy.choose"
773
+ [ngModelOptions]="{ standalone: true }"
774
+ fluid
775
+ />
776
+ </div>
777
+
778
+ @for (step of steps(); track step.level; let index = $index) {
779
+ <div class="ns-field is-span-1 is-size-md">
780
+ <label [attr.for]="'ns-geo-' + step.level">{{ nameOf(step) }}</label>
781
+ <p-select
782
+ [inputId]="'ns-geo-' + step.level"
783
+ [options]="step.items"
784
+ optionLabel="name"
785
+ optionValue="id"
786
+ [ngModel]="step.selectedId"
787
+ (ngModelChange)="pick(index, $event)"
788
+ [disabled]="readonly()"
789
+ [filter]="step.items.length > 12"
790
+ filterBy="name"
791
+ [filterPlaceholder]="copy.search"
792
+ [showClear]="true"
793
+ [placeholder]="copy.choose"
794
+ [ngModelOptions]="{ standalone: true }"
795
+ fluid
796
+ />
797
+ </div>
798
+ }
799
+ </div>
800
+ `, styles: [":host{display:block}\n"] }]
801
+ }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }] } });
802
+ function toStep(level, kind, items, selectedId) {
803
+ return { level, kind, items: [...items], selectedId };
804
+ }
805
+ function deepestOf(steps) {
806
+ for (let index = steps.length - 1; index >= 0; index -= 1) {
807
+ const selected = steps[index]?.selectedId;
808
+ if (selected)
809
+ return selected;
810
+ }
811
+ return null;
812
+ }
813
+
488
814
  const THEMES = [
489
815
  {
490
816
  id: 'nucleus',
@@ -1192,7 +1518,7 @@ class NucleusForm {
1192
1518
  return field.kind ?? 'text';
1193
1519
  }
1194
1520
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
1195
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: NucleusForm, isStandalone: true, selector: "nucleus-form", inputs: { fields: { classPropertyName: "fields", publicName: "fields", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: "<div class=\"grid\" [class]=\"gridClass()\">\n @for (field of fields(); track field.key) {\n <div class=\"field\" [class]=\"fieldClass(field)\">\n @if (kindOf(field) !== 'checkbox' && kindOf(field) !== 'switch') {\n <label [attr.for]=\"'nf-' + field.key\">{{ field.label }}</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 ?? ''\"\n [showClear]=\"field.clearable === true\"\n [ngModelOptions]=\"{ standalone: true }\"\n fluid\n />\n }\n @case ('checkbox') {\n <div class=\"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=\"inline-label\">{{ field.label }}</label>\n </div>\n }\n @case ('switch') {\n <div class=\"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=\"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=\"hint\">{{ field.hint }}</p>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block}.grid{display:grid;grid-template-columns:1fr;gap:18px 20px}.field{display:flex;min-width:0;flex-direction:column;gap:6px}.field label{color:var(--ac-text-muted);font-size:12px;letter-spacing:.04em;text-transform:uppercase}.field .hint{margin:0;max-width:52ch;color:var(--ac-text-muted);font-size:12px;line-height:1.45}.inline{display:flex;min-height:38px;align-items:center;gap:10px}.inline-label{color:var(--ac-text);font-size:13px;letter-spacing:normal;text-transform:none}.is-size-xs :is(input,textarea,.p-select,.p-inputtext){max-width:6rem}.is-size-sm :is(input,textarea,.p-select,.p-inputtext){max-width:11rem}.is-size-md :is(input,textarea,.p-select,.p-inputtext){max-width:17rem}.is-size-lg :is(input,textarea,.p-select,.p-inputtext){max-width:26rem}.is-span-full{grid-column:1 / -1}@media(min-width:640px){.grid{grid-template-columns:repeat(2,minmax(0,1fr))}.is-span-2,.is-span-3,.is-span-4{grid-column:span 2}}@media(min-width:1080px){.grid:not(.is-cap-1):not(.is-cap-2){grid-template-columns:repeat(3,minmax(0,1fr))}.grid:not(.is-cap-1):not(.is-cap-2) .is-span-2{grid-column:span 2}.grid:not(.is-cap-1):not(.is-cap-2) :is(.is-span-3,.is-span-4){grid-column:span 3}}@media(min-width:1500px){.grid:not(.is-cap-1):not(.is-cap-2):not(.is-cap-3){grid-template-columns:repeat(4,minmax(0,1fr))}.grid:not(.is-cap-1):not(.is-cap-2):not(.is-cap-3) .is-span-3{grid-column:span 3}.grid:not(.is-cap-1):not(.is-cap-2):not(.is-cap-3) .is-span-4{grid-column:span 4}}.grid.is-cap-1{grid-template-columns:1fr}.grid.is-cap-1 .field{grid-column:1 / -1}\n"], dependencies: [{ kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i1.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["hostName", "value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i2.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i3.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: TextareaModule }, { kind: "directive", type: i4.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i5.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1521
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: NucleusForm, isStandalone: true, selector: "nucleus-form", inputs: { fields: { classPropertyName: "fields", publicName: "fields", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, ngImport: i0, 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]=\"'nf-' + field.key\">{{ field.label }}</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 ?? ''\"\n [showClear]=\"field.clearable === true\"\n [ngModelOptions]=\"{ standalone: true }\"\n fluid\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"], dependencies: [{ kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i1$1.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["hostName", "value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i2.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i1.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: TextareaModule }, { kind: "directive", type: i4.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i5.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1196
1522
  }
1197
1523
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusForm, decorators: [{
1198
1524
  type: Component,
@@ -1203,7 +1529,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
1203
1529
  TextareaModule,
1204
1530
  ToggleSwitchModule,
1205
1531
  FormsModule,
1206
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"grid\" [class]=\"gridClass()\">\n @for (field of fields(); track field.key) {\n <div class=\"field\" [class]=\"fieldClass(field)\">\n @if (kindOf(field) !== 'checkbox' && kindOf(field) !== 'switch') {\n <label [attr.for]=\"'nf-' + field.key\">{{ field.label }}</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 ?? ''\"\n [showClear]=\"field.clearable === true\"\n [ngModelOptions]=\"{ standalone: true }\"\n fluid\n />\n }\n @case ('checkbox') {\n <div class=\"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=\"inline-label\">{{ field.label }}</label>\n </div>\n }\n @case ('switch') {\n <div class=\"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=\"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=\"hint\">{{ field.hint }}</p>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block}.grid{display:grid;grid-template-columns:1fr;gap:18px 20px}.field{display:flex;min-width:0;flex-direction:column;gap:6px}.field label{color:var(--ac-text-muted);font-size:12px;letter-spacing:.04em;text-transform:uppercase}.field .hint{margin:0;max-width:52ch;color:var(--ac-text-muted);font-size:12px;line-height:1.45}.inline{display:flex;min-height:38px;align-items:center;gap:10px}.inline-label{color:var(--ac-text);font-size:13px;letter-spacing:normal;text-transform:none}.is-size-xs :is(input,textarea,.p-select,.p-inputtext){max-width:6rem}.is-size-sm :is(input,textarea,.p-select,.p-inputtext){max-width:11rem}.is-size-md :is(input,textarea,.p-select,.p-inputtext){max-width:17rem}.is-size-lg :is(input,textarea,.p-select,.p-inputtext){max-width:26rem}.is-span-full{grid-column:1 / -1}@media(min-width:640px){.grid{grid-template-columns:repeat(2,minmax(0,1fr))}.is-span-2,.is-span-3,.is-span-4{grid-column:span 2}}@media(min-width:1080px){.grid:not(.is-cap-1):not(.is-cap-2){grid-template-columns:repeat(3,minmax(0,1fr))}.grid:not(.is-cap-1):not(.is-cap-2) .is-span-2{grid-column:span 2}.grid:not(.is-cap-1):not(.is-cap-2) :is(.is-span-3,.is-span-4){grid-column:span 3}}@media(min-width:1500px){.grid:not(.is-cap-1):not(.is-cap-2):not(.is-cap-3){grid-template-columns:repeat(4,minmax(0,1fr))}.grid:not(.is-cap-1):not(.is-cap-2):not(.is-cap-3) .is-span-3{grid-column:span 3}.grid:not(.is-cap-1):not(.is-cap-2):not(.is-cap-3) .is-span-4{grid-column:span 4}}.grid.is-cap-1{grid-template-columns:1fr}.grid.is-cap-1 .field{grid-column:1 / -1}\n"] }]
1532
+ ], 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]=\"'nf-' + field.key\">{{ field.label }}</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 ?? ''\"\n [showClear]=\"field.clearable === true\"\n [ngModelOptions]=\"{ standalone: true }\"\n fluid\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"] }]
1207
1533
  }], 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 }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
1208
1534
 
1209
1535
  class NucleusCell {
@@ -1265,7 +1591,7 @@ class NucleusList {
1265
1591
  this.toggle.emit({ key: column.key, row, value: !this.isChecked(column, row) });
1266
1592
  }
1267
1593
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusList, deps: [], target: i0.ɵɵFactoryTarget.Component });
1268
- 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 }, rowClass: { classPropertyName: "rowClass", publicName: "rowClass", 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 [value]=\"rows()\" styleClass=\"ns-table\" [tableStyle]=\"tableStyle()\">\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 <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 (onClick)=\"run(entry, row)\"\n />\n }\n </td>\n }\n </tr>\n </ng-template>\n </p-table>\n}\n", styles: [":host{display:block}.head{display:flex;min-height:34px;align-items:center;justify-content:space-between;gap:12px;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$1.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: TableModule }, { kind: "component", type: i2$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: i3$1.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i4$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 });
1594
+ 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 }, rowClass: { classPropertyName: "rowClass", publicName: "rowClass", 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 [value]=\"rows()\" styleClass=\"ns-table\" [tableStyle]=\"tableStyle()\">\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 <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 (onClick)=\"run(entry, row)\"\n />\n }\n </td>\n }\n </tr>\n </ng-template>\n </p-table>\n}\n", styles: [":host{display:block}.head{display:flex;min-height:34px;align-items:center;justify-content:space-between;gap:12px;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: TableModule }, { kind: "component", type: i2$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: i3.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i4$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 });
1269
1595
  }
1270
1596
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusList, decorators: [{
1271
1597
  type: Component,
@@ -1671,7 +1997,7 @@ class NucleusShell {
1671
1997
  }
1672
1998
  }
1673
1999
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusShell, deps: [], target: i0.ɵɵFactoryTarget.Component });
1674
- 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 }, lead: { classPropertyName: "lead", publicName: "lead", 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" }, ngImport: i0, template: "@let t = copy();\n@let me = identity();\n\n@if (starfield()) {\n <nucleus-starfield />\n}\n\n<header class=\"topbar\">\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 </div>\n\n <div class=\"side\">\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>\n <div class=\"launcher\">\n <p class=\"launcher-title\">{{ t.appsLauncher }}</p>\n\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 @if (!launcherApps().length) {\n <p class=\"launcher-empty\">{{ t.appsEmpty }}</p>\n }\n\n <div class=\"launcher-grid\">\n @for (app of launcherApps(); track app.id) {\n <button\n type=\"button\"\n class=\"launcher-item\"\n [class.is-disabled]=\"!canOpen(app)\"\n [disabled]=\"!canOpen(app)\"\n [pTooltip]=\"launchHint(app)\"\n tooltipPosition=\"bottom\"\n (click)=\"launch(app); launcher.hide()\"\n >\n <span class=\"launcher-icon\" [style.background]=\"app.color ?? '#64748b'\">\n @if (app.icon) {\n <i [class]=\"app.icon\" aria-hidden=\"true\"></i>\n } @else {\n <span class=\"launcher-initials\">{{ appInitials(app) }}</span>\n }\n </span>\n <span class=\"launcher-name\">{{ app.name }}</span>\n @if (launchHint(app)) {\n <span class=\"launcher-badge\">{{ launchHint(app) }}</span>\n }\n </button>\n }\n </div>\n </div>\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>\n @if (me) {\n <div class=\"account\">\n <p class=\"account-email\">{{ me.email }}</p>\n\n <div class=\"account-head\">\n @if (me.photoUrl) {\n <img class=\"account-photo\" [src]=\"me.photoUrl\" alt=\"\" width=\"72\" height=\"72\" />\n } @else {\n <span class=\"account-photo account-initials\">{{ initials() }}</span>\n }\n <p class=\"account-hi\">{{ me.name }}</p>\n </div>\n\n <div class=\"account-context\">\n @if (roleName()) {\n <p-tag [value]=\"roleName()!\" severity=\"secondary\" />\n }\n <p class=\"account-place\">{{ contextCaption() }}</p>\n <p-button\n [label]=\"t.switchSite\"\n icon=\"pi pi-building\"\n severity=\"secondary\"\n size=\"small\"\n [outlined]=\"true\"\n [rounded]=\"true\"\n [fluid]=\"true\"\n (onClick)=\"openContext(); account.hide()\"\n />\n </div>\n\n <div class=\"account-actions\">\n @if (canSwitchAccount()) {\n <p-button\n [label]=\"t.accountSwitch\"\n icon=\"pi pi-users\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [fluid]=\"true\"\n (onClick)=\"switchAccount(); account.hide()\"\n />\n }\n <p-button\n [label]=\"t.signOut\"\n icon=\"pi pi-sign-out\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [fluid]=\"true\"\n (onClick)=\"signOut(); account.hide()\"\n />\n </div>\n </div>\n }\n</p-popover>\n\n<div class=\"body\">\n <aside class=\"sidebar\" [class.is-collapsed]=\"!sidebarOpen()\">\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 <p class=\"access-state\">{{ t.accessLoading }}</p>\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 <button\n type=\"button\"\n class=\"nav-item\"\n [class.is-active]=\"isSelected(node)\"\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 </button>\n\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 </nav>\n </aside>\n\n <main class=\"content\">\n <div class=\"measure\">\n <ng-content select=\"[nucleusTop]\" />\n\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 @if (subtitle()) {\n <p class=\"lead\">{{ subtitle() }}</p>\n }\n\n <ng-content />\n </div>\n </main>\n</div>\n\n<p-drawer\n [visible]=\"contextOpen()\"\n (visibleChange)=\"contextOpen.set($event)\"\n position=\"right\"\n [header]=\"t.contextTitle\"\n [style]=\"{ width: '380px' }\"\n>\n <p class=\"settings-hint\">{{ t.contextHint }}</p>\n\n <label class=\"field-label\" for=\"nucleus-company\">{{ t.companyLabel }}</label>\n <p-select\n inputId=\"nucleus-company\"\n [options]=\"companyChoices()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"companyChoice()\"\n (ngModelChange)=\"onCompanyChange($event)\"\n [placeholder]=\"t.companyPlaceholder\"\n [fluid]=\"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 <label class=\"field-label\" for=\"nucleus-site\">{{ t.siteLabel }}</label>\n\n @if (sitesLoading()) {\n <p class=\"access-state\">{{ t.sitesLoading }}</p>\n } @else if (!siteOptions().length) {\n <p class=\"access-state\">{{ t.sitesEmpty }}</p>\n } @else {\n <p-select\n inputId=\"nucleus-site\"\n [options]=\"siteOptions()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"siteChoice()\"\n (ngModelChange)=\"siteChoice.set($event)\"\n [placeholder]=\"t.sitePlaceholder\"\n [fluid]=\"true\"\n />\n }\n\n <div class=\"context-actions\">\n <p-button\n [label]=\"t.confirmSwitch\"\n icon=\"pi pi-arrow-right\"\n [disabled]=\"!canConfirm()\"\n [loading]=\"switching()\"\n [fluid]=\"true\"\n (onClick)=\"confirmSwitch()\"\n />\n </div>\n</p-drawer>\n\n<p-drawer\n [visible]=\"settingsOpen()\"\n (visibleChange)=\"settingsOpen.set($event)\"\n position=\"right\"\n [header]=\"t.settingsTitle\"\n [style]=\"{ width: '340px' }\"\n>\n <h3 class=\"settings-heading\">{{ t.settingsTheme }}</h3>\n <p class=\"settings-hint\">{{ t.settingsThemeHint }}</p>\n\n <p-listbox\n [options]=\"themeOptions()\"\n optionValue=\"value\"\n optionLabel=\"label\"\n [ngModel]=\"themePreference()\"\n (ngModelChange)=\"selectTheme($event)\"\n [ariaLabel]=\"t.settingsTheme\"\n >\n <ng-template #item let-option>\n <span class=\"theme-option\">\n @if (option.swatch) {\n <span class=\"theme-swatch\" [style.background]=\"option.swatch\" aria-hidden=\"true\"></span>\n } @else {\n <i class=\"pi pi-desktop theme-swatch-icon\" aria-hidden=\"true\"></i>\n }\n <span>{{ option.label }}</span>\n </span>\n </ng-template>\n </p-listbox>\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:space-between;gap:16px;height:56px;padding:0 12px 0 8px;background:var(--ac-surface);border-bottom:1px solid var(--ac-border)}.side{display:flex;align-items:center;gap:4px}.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(--ac-text-muted)}.lang-switch{display:flex;align-items:center;gap:2px;margin-right:6px;border:1px solid var(--ac-border);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(--ac-text-muted);cursor:pointer}.lang-pill.is-active{background:var(--ac-accent);color:var(--ac-on-accent)}.launcher{width:320px;padding:4px}.launcher-title{margin:0 0 10px;font-size:12px;font-weight:600;color:var(--ac-text-muted)}.launcher-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:4px}.launcher-item{position:relative;display:flex;flex-direction:column;align-items:center;gap:7px;padding:12px 6px;border:none;border-radius:8px;background:transparent;color:var(--ac-text);cursor:pointer}.launcher-item:hover:not(:disabled){background:var(--ac-surface-alt)}.launcher-item.is-disabled{opacity:.5;cursor:default}.launcher-icon{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:10px;color:#fff}.launcher-icon i{font-size:18px}.launcher-name{font-size:11px;font-weight:500;line-height:1.3;text-align:center}.launcher-badge{font-size:9px;font-weight:500;color:var(--ac-text-muted)}.account{width:300px;padding:4px;text-align:center}.account-email{margin:0 0 12px;font-size:12px;color:var(--ac-text-muted)}.account-head{display:flex;flex-direction:column;align-items:center;gap:8px;padding-bottom:14px;border-bottom:1px solid var(--ac-border)}.account-photo{width:72px;height:72px;border-radius:999px;object-fit:cover}.account-initials{display:inline-flex;align-items:center;justify-content:center;background:var(--ac-accent);color:var(--ac-on-accent);font-size:26px;font-weight:600}.account-hi{margin:0;font-size:16px;font-weight:500}.account-actions{display:flex;flex-direction:column;gap:2px;padding-top:8px}.body{display:flex;flex:1;min-height:0}.sidebar{flex:none;width:224px;padding:12px 10px;background:var(--ac-surface);border-right:1px solid var(--ac-border);transition:width .18s ease}.sidebar.is-collapsed{width:60px}.sidebar nav{display:flex;flex-direction:column;gap:3px}.nav-item{display:flex;align-items:center;gap:12px;width:100%;padding:9px 12px;border:none;border-radius:6px;background:transparent;color:var(--ac-text-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(--ac-surface-alt);color:var(--ac-text)}.nav-item.is-active{background:color-mix(in srgb,var(--ac-accent) 18%,transparent);color:var(--ac-text)}.nav-item.is-active i{color:var(--ac-accent)}.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}.measure{display:flex;width:100%;max-width:var(--ac-content-max, 1440px);flex-direction:column;gap:14px;margin-inline:auto}h1{margin:0;font-size:26px;line-height:1.2;font-weight:500;letter-spacing:-.02em}.lead{margin:0;font-size:14px;line-height:1.6;font-weight:300;color:var(--ac-text-muted)}.settings-heading{margin:0 0 4px;font-size:14px;font-weight:600}.settings-hint{margin:0 0 14px;font-size:12px;font-weight:300;color:var(--ac-text-muted)}.theme-option{display:flex;align-items:center;gap:10px}.theme-swatch{flex:none;width:16px;height:16px;border-radius:3px;border:1px solid var(--ac-border)}.theme-swatch-icon{flex:none;width:16px;font-size:14px;color:var(--ac-text-muted)}.access-menu{display:flex;flex-direction:column;gap:.15rem;margin-top:.75rem;padding-top:.75rem;border-top:1px solid color-mix(in srgb,currentColor 12%,transparent)}.access-caption{margin:0 0 .4rem;padding:0 .75rem;font-size:.68rem;letter-spacing:.06em;text-transform:uppercase;opacity:.65;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.access-state{margin:0;padding:.35rem .75rem;font-size:.78rem;opacity:.7}.access-state.is-error{color:var(--p-red-400, #f87171);opacity:1}.nav-item.is-child{padding-left:2.1rem;font-size:.86rem}.launcher-initials{font-size:.85rem;font-weight:600;letter-spacing:.02em;line-height:1;color:#fff}.launcher-empty{margin:.25rem 0 .5rem;font-size:.82rem;opacity:.7}@media(max-width:720px){.sidebar{width:60px}.sidebar .nav-label{display:none}.sidebar .nav-item{justify-content:center;padding-inline:0}.brand-secondary{display:none}.content{padding:20px 16px 48px}h1{font-size:22px}.launcher{width:260px}}.account-context{display:flex;flex-direction:column;align-items:center;gap:8px;padding:14px 0;border-top:1px solid var(--ac-border);border-bottom:1px solid var(--ac-border)}.account-place{margin:0;color:var(--ac-text-muted);font-size:12px;text-align:center}.field-label{display:block;margin:18px 0 6px;color:var(--ac-text-muted);font-size:12px;letter-spacing:.04em;text-transform:uppercase}.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}.context-actions{margin-top:24px}.launcher-notice{display:flex;gap:10px;margin-bottom:14px;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}\n"], dependencies: [{ kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i1$2.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "ngmodule", type: BreadcrumbModule }, { kind: "component", type: i2$2.Breadcrumb, selector: "p-breadcrumb", inputs: ["model", "style", "styleClass", "home", "homeAriaLabel"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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$2.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$1.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: ListboxModule }, { kind: "component", type: i7.Listbox, selector: "p-listbox, p-listBox, p-list-box", inputs: ["hostName", "id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "ariaLabel", "selectOnFocus", "searchLocale", "focusOnHover", "filterMessage", "filterFields", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "scrollHeight", "tabindex", "multiple", "styleClass", "listStyle", "listStyleClass", "readonly", "checkbox", "filter", "filterBy", "filterMatchMode", "filterLocale", "metaKeySelection", "dataKey", "showToggleAll", "optionLabel", "optionValue", "optionGroupChildren", "optionGroupLabel", "optionDisabled", "ariaFilterLabel", "filterPlaceHolder", "emptyFilterMessage", "emptyMessage", "group", "options", "filterValue", "selectAll", "striped", "highlightOnSelect", "checkmark", "dragdrop", "dropListData", "fluid"], outputs: ["onChange", "onClick", "onDblClick", "onFilter", "onFocus", "onBlur", "onSelectAllChange", "onLazyLoad", "onDrop"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i8.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: i3.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: TagModule }, { kind: "component", type: i3$1.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i4$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: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: NucleusLordicon, selector: "nucleus-lordicon", inputs: ["src", "trigger", "state", "size", "tone"] }, { kind: "component", type: NucleusMark, selector: "nucleus-mark", inputs: ["accent", "size"] }, { kind: "component", type: NucleusStarfield, selector: "nucleus-starfield" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2000
+ 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 }, lead: { classPropertyName: "lead", publicName: "lead", 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" }, ngImport: i0, template: "@let t = copy();\n@let me = identity();\n\n@if (starfield()) {\n <nucleus-starfield />\n}\n\n<header class=\"topbar\">\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 </div>\n\n <div class=\"side\">\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>\n <div class=\"launcher\">\n <p class=\"launcher-title\">{{ t.appsLauncher }}</p>\n\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 @if (!launcherApps().length) {\n <p class=\"launcher-empty\">{{ t.appsEmpty }}</p>\n }\n\n <div class=\"launcher-grid\">\n @for (app of launcherApps(); track app.id) {\n <button\n type=\"button\"\n class=\"launcher-item\"\n [class.is-disabled]=\"!canOpen(app)\"\n [disabled]=\"!canOpen(app)\"\n [pTooltip]=\"launchHint(app)\"\n tooltipPosition=\"bottom\"\n (click)=\"launch(app); launcher.hide()\"\n >\n <span class=\"launcher-icon\" [style.background]=\"app.color ?? '#64748b'\">\n @if (app.icon) {\n <i [class]=\"app.icon\" aria-hidden=\"true\"></i>\n } @else {\n <span class=\"launcher-initials\">{{ appInitials(app) }}</span>\n }\n </span>\n <span class=\"launcher-name\">{{ app.name }}</span>\n @if (launchHint(app)) {\n <span class=\"launcher-badge\">{{ launchHint(app) }}</span>\n }\n </button>\n }\n </div>\n </div>\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>\n @if (me) {\n <div class=\"account\">\n <p class=\"account-email\">{{ me.email }}</p>\n\n <div class=\"account-head\">\n @if (me.photoUrl) {\n <img class=\"account-photo\" [src]=\"me.photoUrl\" alt=\"\" width=\"72\" height=\"72\" />\n } @else {\n <span class=\"account-photo account-initials\">{{ initials() }}</span>\n }\n <p class=\"account-hi\">{{ me.name }}</p>\n </div>\n\n <div class=\"account-context\">\n @if (roleName()) {\n <p-tag [value]=\"roleName()!\" severity=\"secondary\" />\n }\n <p class=\"account-place\">{{ contextCaption() }}</p>\n <p-button\n [label]=\"t.switchSite\"\n icon=\"pi pi-building\"\n severity=\"secondary\"\n size=\"small\"\n [outlined]=\"true\"\n [rounded]=\"true\"\n [fluid]=\"true\"\n (onClick)=\"openContext(); account.hide()\"\n />\n </div>\n\n <div class=\"account-actions\">\n @if (canSwitchAccount()) {\n <p-button\n [label]=\"t.accountSwitch\"\n icon=\"pi pi-users\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [fluid]=\"true\"\n (onClick)=\"switchAccount(); account.hide()\"\n />\n }\n <p-button\n [label]=\"t.signOut\"\n icon=\"pi pi-sign-out\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [fluid]=\"true\"\n (onClick)=\"signOut(); account.hide()\"\n />\n </div>\n </div>\n }\n</p-popover>\n\n<div class=\"body\">\n <aside class=\"sidebar\" [class.is-collapsed]=\"!sidebarOpen()\">\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 <p class=\"access-state\">{{ t.accessLoading }}</p>\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 <button\n type=\"button\"\n class=\"nav-item\"\n [class.is-active]=\"isSelected(node)\"\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 </button>\n\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 </nav>\n </aside>\n\n <main class=\"content\">\n <div class=\"measure\">\n <ng-content select=\"[nucleusTop]\" />\n\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 @if (subtitle()) {\n <p class=\"lead\">{{ subtitle() }}</p>\n }\n\n <ng-content />\n </div>\n </main>\n</div>\n\n<p-drawer\n [visible]=\"contextOpen()\"\n (visibleChange)=\"contextOpen.set($event)\"\n position=\"right\"\n [header]=\"t.contextTitle\"\n [style]=\"{ width: '380px' }\"\n>\n <p class=\"settings-hint\">{{ t.contextHint }}</p>\n\n <label class=\"field-label\" for=\"nucleus-company\">{{ t.companyLabel }}</label>\n <p-select\n inputId=\"nucleus-company\"\n [options]=\"companyChoices()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"companyChoice()\"\n (ngModelChange)=\"onCompanyChange($event)\"\n [placeholder]=\"t.companyPlaceholder\"\n [fluid]=\"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 <label class=\"field-label\" for=\"nucleus-site\">{{ t.siteLabel }}</label>\n\n @if (sitesLoading()) {\n <p class=\"access-state\">{{ t.sitesLoading }}</p>\n } @else if (!siteOptions().length) {\n <p class=\"access-state\">{{ t.sitesEmpty }}</p>\n } @else {\n <p-select\n inputId=\"nucleus-site\"\n [options]=\"siteOptions()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"siteChoice()\"\n (ngModelChange)=\"siteChoice.set($event)\"\n [placeholder]=\"t.sitePlaceholder\"\n [fluid]=\"true\"\n />\n }\n\n <div class=\"context-actions\">\n <p-button\n [label]=\"t.confirmSwitch\"\n icon=\"pi pi-arrow-right\"\n [disabled]=\"!canConfirm()\"\n [loading]=\"switching()\"\n [fluid]=\"true\"\n (onClick)=\"confirmSwitch()\"\n />\n </div>\n</p-drawer>\n\n<p-drawer\n [visible]=\"settingsOpen()\"\n (visibleChange)=\"settingsOpen.set($event)\"\n position=\"right\"\n [header]=\"t.settingsTitle\"\n [style]=\"{ width: '340px' }\"\n>\n <h3 class=\"settings-heading\">{{ t.settingsTheme }}</h3>\n <p class=\"settings-hint\">{{ t.settingsThemeHint }}</p>\n\n <p-listbox\n [options]=\"themeOptions()\"\n optionValue=\"value\"\n optionLabel=\"label\"\n [ngModel]=\"themePreference()\"\n (ngModelChange)=\"selectTheme($event)\"\n [ariaLabel]=\"t.settingsTheme\"\n >\n <ng-template #item let-option>\n <span class=\"theme-option\">\n @if (option.swatch) {\n <span class=\"theme-swatch\" [style.background]=\"option.swatch\" aria-hidden=\"true\"></span>\n } @else {\n <i class=\"pi pi-desktop theme-swatch-icon\" aria-hidden=\"true\"></i>\n }\n <span>{{ option.label }}</span>\n </span>\n </ng-template>\n </p-listbox>\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:space-between;gap:16px;height:56px;padding:0 12px 0 8px;background:var(--ac-surface);border-bottom:1px solid var(--ac-border)}.side{display:flex;align-items:center;gap:4px}.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(--ac-text-muted)}.lang-switch{display:flex;align-items:center;gap:2px;margin-right:6px;border:1px solid var(--ac-border);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(--ac-text-muted);cursor:pointer}.lang-pill.is-active{background:var(--ac-accent);color:var(--ac-on-accent)}.launcher{width:320px;padding:4px}.launcher-title{margin:0 0 10px;font-size:12px;font-weight:600;color:var(--ac-text-muted)}.launcher-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:4px}.launcher-item{position:relative;display:flex;flex-direction:column;align-items:center;gap:7px;padding:12px 6px;border:none;border-radius:8px;background:transparent;color:var(--ac-text);cursor:pointer}.launcher-item:hover:not(:disabled){background:var(--ac-surface-alt)}.launcher-item.is-disabled{opacity:.5;cursor:default}.launcher-icon{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:10px;color:#fff}.launcher-icon i{font-size:18px}.launcher-name{font-size:11px;font-weight:500;line-height:1.3;text-align:center}.launcher-badge{font-size:9px;font-weight:500;color:var(--ac-text-muted)}.account{width:300px;padding:4px;text-align:center}.account-email{margin:0 0 12px;font-size:12px;color:var(--ac-text-muted)}.account-head{display:flex;flex-direction:column;align-items:center;gap:8px;padding-bottom:14px;border-bottom:1px solid var(--ac-border)}.account-photo{width:72px;height:72px;border-radius:999px;object-fit:cover}.account-initials{display:inline-flex;align-items:center;justify-content:center;background:var(--ac-accent);color:var(--ac-on-accent);font-size:26px;font-weight:600}.account-hi{margin:0;font-size:16px;font-weight:500}.account-actions{display:flex;flex-direction:column;gap:2px;padding-top:8px}.body{display:flex;flex:1;min-height:0}.sidebar{flex:none;width:224px;padding:12px 10px;background:var(--ac-surface);border-right:1px solid var(--ac-border);transition:width .18s ease}.sidebar.is-collapsed{width:60px}.sidebar nav{display:flex;flex-direction:column;gap:3px}.nav-item{display:flex;align-items:center;gap:12px;width:100%;padding:9px 12px;border:none;border-radius:6px;background:transparent;color:var(--ac-text-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(--ac-surface-alt);color:var(--ac-text)}.nav-item.is-active{background:color-mix(in srgb,var(--ac-accent) 18%,transparent);color:var(--ac-text)}.nav-item.is-active i{color:var(--ac-accent)}.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}.measure{display:flex;width:100%;max-width:var(--ac-content-max, 1440px);flex-direction:column;gap:14px;margin-inline:auto}h1{margin:0;font-size:26px;line-height:1.2;font-weight:500;letter-spacing:-.02em}.lead{margin:0;font-size:14px;line-height:1.6;font-weight:300;color:var(--ac-text-muted)}.settings-heading{margin:0 0 4px;font-size:14px;font-weight:600}.settings-hint{margin:0 0 14px;font-size:12px;font-weight:300;color:var(--ac-text-muted)}.theme-option{display:flex;align-items:center;gap:10px}.theme-swatch{flex:none;width:16px;height:16px;border-radius:3px;border:1px solid var(--ac-border)}.theme-swatch-icon{flex:none;width:16px;font-size:14px;color:var(--ac-text-muted)}.access-menu{display:flex;flex-direction:column;gap:.15rem;margin-top:.75rem;padding-top:.75rem;border-top:1px solid color-mix(in srgb,currentColor 12%,transparent)}.access-caption{margin:0 0 .4rem;padding:0 .75rem;font-size:.68rem;letter-spacing:.06em;text-transform:uppercase;opacity:.65;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.access-state{margin:0;padding:.35rem .75rem;font-size:.78rem;opacity:.7}.access-state.is-error{color:var(--p-red-400, #f87171);opacity:1}.nav-item.is-child{padding-left:2.1rem;font-size:.86rem}.launcher-initials{font-size:.85rem;font-weight:600;letter-spacing:.02em;line-height:1;color:#fff}.launcher-empty{margin:.25rem 0 .5rem;font-size:.82rem;opacity:.7}@media(max-width:720px){.sidebar{width:60px}.sidebar .nav-label{display:none}.sidebar .nav-item{justify-content:center;padding-inline:0}.brand-secondary{display:none}.content{padding:20px 16px 48px}h1{font-size:22px}.launcher{width:260px}}.account-context{display:flex;flex-direction:column;align-items:center;gap:8px;padding:14px 0;border-top:1px solid var(--ac-border);border-bottom:1px solid var(--ac-border)}.account-place{margin:0;color:var(--ac-text-muted);font-size:12px;text-align:center}.field-label{display:block;margin:18px 0 6px;color:var(--ac-text-muted);font-size:12px;letter-spacing:.04em;text-transform:uppercase}.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}.context-actions{margin-top:24px}.launcher-notice{display:flex;gap:10px;margin-bottom:14px;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}\n"], dependencies: [{ 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$2.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$2.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$1.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: ListboxModule }, { kind: "component", type: i7.Listbox, selector: "p-listbox, p-listBox, p-list-box", inputs: ["hostName", "id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "ariaLabel", "selectOnFocus", "searchLocale", "focusOnHover", "filterMessage", "filterFields", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "scrollHeight", "tabindex", "multiple", "styleClass", "listStyle", "listStyleClass", "readonly", "checkbox", "filter", "filterBy", "filterMatchMode", "filterLocale", "metaKeySelection", "dataKey", "showToggleAll", "optionLabel", "optionValue", "optionGroupChildren", "optionGroupLabel", "optionDisabled", "ariaFilterLabel", "filterPlaceHolder", "emptyFilterMessage", "emptyMessage", "group", "options", "filterValue", "selectAll", "striped", "highlightOnSelect", "checkmark", "dragdrop", "dropListData", "fluid"], outputs: ["onChange", "onClick", "onDblClick", "onFilter", "onFocus", "onBlur", "onSelectAllChange", "onLazyLoad", "onDrop"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i8.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: i1.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: TagModule }, { kind: "component", type: i3.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i4$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: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: NucleusLordicon, selector: "nucleus-lordicon", inputs: ["src", "trigger", "state", "size", "tone"] }, { kind: "component", type: NucleusMark, selector: "nucleus-mark", inputs: ["accent", "size"] }, { kind: "component", type: NucleusStarfield, selector: "nucleus-starfield" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1675
2001
  }
1676
2002
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusShell, decorators: [{
1677
2003
  type: Component,
@@ -1706,5 +2032,5 @@ function initialsOf(source) {
1706
2032
  * Generated bundle index. Do not edit.
1707
2033
  */
1708
2034
 
1709
- export { DEFAULT_THEME, NO_PERMISSIONS, NUCLEUS_CONFIG, NUCLEUS_DARK_SELECTOR, NUCLEUS_FORCE_BEARER, NUCLEUS_ICONS, NUCLEUS_LANGS, NUCLEUS_LOGOUT_PARAM, NUCLEUS_SKIP_AUTH, NucleusAuth, NucleusCard, NucleusCell, NucleusFeedback, NucleusForm, NucleusLanguage, NucleusList, NucleusLordicon, NucleusMark, NucleusPage, NucleusPreset, NucleusSessionAuth, NucleusShell, NucleusStarfield, NucleusTabs, SHELL_COPY, SessionService, THEMES, THEME_LABELS, ThemeService, UserSyncService, consumeNucleusLogout, findMenuByRoute, isNucleusConfigured, isThemePreference, loadLordicon, loadNucleusConfig, nucleusAuthInterceptor, nucleusLogoutUrl, ownsUrl, permissionsOf, provideNucleus, provideNucleusFeedback, provideNucleusTheme, resolveFieldSize, themeById };
2035
+ export { DEFAULT_THEME, EMPTY_GEO_VALUE, GEO_COPY, NO_PERMISSIONS, NUCLEUS_CONFIG, NUCLEUS_DARK_SELECTOR, NUCLEUS_FORCE_BEARER, NUCLEUS_ICONS, NUCLEUS_LANGS, NUCLEUS_LOGOUT_PARAM, NUCLEUS_SKIP_AUTH, NucleusAuth, NucleusCard, NucleusCell, NucleusFeedback, NucleusForm, NucleusGeo, NucleusGeoSelect, NucleusLanguage, NucleusList, NucleusLordicon, NucleusMark, NucleusPage, NucleusPreset, NucleusSessionAuth, NucleusShell, NucleusStarfield, NucleusTabs, SHELL_COPY, SessionService, THEMES, THEME_LABELS, ThemeService, UserSyncService, consumeNucleusLogout, findMenuByRoute, flagOf, geoCopyOf, isNucleusConfigured, isThemePreference, levelLabel, loadLordicon, loadNucleusConfig, nucleusAuthInterceptor, nucleusLogoutUrl, ownsUrl, permissionsOf, provideNucleus, provideNucleusFeedback, provideNucleusTheme, resolveFieldSize, themeById };
1710
2036
  //# sourceMappingURL=nucleus-suite-pe-core.mjs.map