@nucleus-suite-pe/core 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,7 @@ import { firstValueFrom, catchError, throwError, from, switchMap } from 'rxjs';
5
5
  import { definePreset } from '@primeuix/themes';
6
6
  import Lara from '@primeuix/themes/lara';
7
7
  import { providePrimeNG } from 'primeng/config';
8
- import * as i7 from '@angular/forms';
8
+ import * as i9 from '@angular/forms';
9
9
  import { FormsModule } from '@angular/forms';
10
10
  import { Router } from '@angular/router';
11
11
  import * as i1 from 'primeng/avatar';
@@ -18,7 +18,11 @@ import * as i4 from 'primeng/listbox';
18
18
  import { ListboxModule } from 'primeng/listbox';
19
19
  import * as i5 from 'primeng/popover';
20
20
  import { PopoverModule } from 'primeng/popover';
21
- import * as i6 from 'primeng/tooltip';
21
+ import * as i6 from 'primeng/select';
22
+ import { SelectModule } from 'primeng/select';
23
+ import * as i7 from 'primeng/tag';
24
+ import { TagModule } from 'primeng/tag';
25
+ import * as i8 from 'primeng/tooltip';
22
26
  import { TooltipModule } from 'primeng/tooltip';
23
27
 
24
28
  const NUCLEUS_CONFIG = new InjectionToken('NUCLEUS_CONFIG');
@@ -199,16 +203,21 @@ class SessionService {
199
203
  _access = signal(null, ...(ngDevMode ? [{ debugName: "_access" }] : /* istanbul ignore next */ []));
200
204
  _scope = signal(null, ...(ngDevMode ? [{ debugName: "_scope" }] : /* istanbul ignore next */ []));
201
205
  _apps = signal([], ...(ngDevMode ? [{ debugName: "_apps" }] : /* istanbul ignore next */ []));
206
+ _siteId = signal(null, ...(ngDevMode ? [{ debugName: "_siteId" }] : /* istanbul ignore next */ []));
202
207
  _loading = signal(false, ...(ngDevMode ? [{ debugName: "_loading" }] : /* istanbul ignore next */ []));
208
+ _switching = signal(false, ...(ngDevMode ? [{ debugName: "_switching" }] : /* istanbul ignore next */ []));
203
209
  _error = signal(null, ...(ngDevMode ? [{ debugName: "_error" }] : /* istanbul ignore next */ []));
204
210
  inFlight = false;
205
211
  loadedKey = null;
212
+ language = 'es';
206
213
  me = this._me.asReadonly();
207
214
  menu = this._menu.asReadonly();
208
215
  access = this._access.asReadonly();
209
216
  scope = this._scope.asReadonly();
210
217
  apps = this._apps.asReadonly();
218
+ siteId = this._siteId.asReadonly();
211
219
  loading = this._loading.asReadonly();
220
+ switching = this._switching.asReadonly();
212
221
  error = this._error.asReadonly();
213
222
  roleName = computed(() => this._access()?.roleName ?? null, ...(ngDevMode ? [{ debugName: "roleName" }] : /* istanbul ignore next */ []));
214
223
  siteName = computed(() => this._access()?.siteName ?? null, ...(ngDevMode ? [{ debugName: "siteName" }] : /* istanbul ignore next */ []));
@@ -218,6 +227,28 @@ class SessionService {
218
227
  return [];
219
228
  return [...me.ownedCompanies, ...me.sharedCompanies];
220
229
  }, ...(ngDevMode ? [{ debugName: "companies" }] : /* istanbul ignore next */ []));
230
+ companyOptions = computed(() => {
231
+ const me = this._me();
232
+ if (!me)
233
+ return [];
234
+ return [
235
+ ...me.ownedCompanies.map((company) => toOption(company, 'owner')),
236
+ ...me.sharedCompanies.map((company) => toOption(company, 'collaborator')),
237
+ ];
238
+ }, ...(ngDevMode ? [{ debugName: "companyOptions" }] : /* istanbul ignore next */ []));
239
+ companyId = computed(() => {
240
+ const siteId = this._siteId();
241
+ if (!siteId)
242
+ return this._me()?.profile.lastCompanyId ?? null;
243
+ const owner = this.companies().find((company) => company.myAccess.some((entry) => entry.siteId === siteId));
244
+ return owner?.id ?? this._me()?.profile.lastCompanyId ?? null;
245
+ }, ...(ngDevMode ? [{ debugName: "companyId" }] : /* istanbul ignore next */ []));
246
+ companyName = computed(() => {
247
+ const id = this.companyId();
248
+ if (!id)
249
+ return null;
250
+ return this.companyOptions().find((company) => company.id === id)?.name ?? null;
251
+ }, ...(ngDevMode ? [{ debugName: "companyName" }] : /* istanbul ignore next */ []));
221
252
  async load(language, force = false) {
222
253
  if (!isNucleusConfigured(this.config))
223
254
  return;
@@ -231,6 +262,7 @@ class SessionService {
231
262
  return;
232
263
  this.inFlight = true;
233
264
  this.loadedKey = key;
265
+ this.language = language;
234
266
  this._loading.set(true);
235
267
  this._error.set(null);
236
268
  try {
@@ -243,19 +275,8 @@ class SessionService {
243
275
  firstValueFrom(this.http.get(`${this.config.securityApiUrl}/apps`)),
244
276
  ]);
245
277
  this._me.set(me);
246
- this._apps.set(this.buildLauncher(me, catalog));
247
- const access = [...me.ownedCompanies, ...me.sharedCompanies]
248
- .flatMap((company) => company.myAccess)
249
- .find((entry) => entry.appId.toLowerCase() === this.config.appId);
250
- if (access) {
251
- this._access.set(access);
252
- this._scope.set('site');
253
- this._menu.set(await this.siteMenu(access.siteId, language));
254
- return;
255
- }
256
- this._access.set(null);
257
- this._scope.set('account');
258
- this._menu.set(await this.accountMenu(language));
278
+ this._apps.set(this.buildLauncher(catalog));
279
+ await this.resolveMenu(me, language);
259
280
  }
260
281
  catch (error) {
261
282
  this._menu.set([]);
@@ -270,13 +291,65 @@ class SessionService {
270
291
  reload(language) {
271
292
  return this.load(language, true);
272
293
  }
273
- buildLauncher(me, catalog) {
274
- const granted = new Set([...me.ownedCompanies, ...me.sharedCompanies]
294
+ sites(companyId) {
295
+ return firstValueFrom(this.http.get(`${this.config.securityApiUrl}/companies/${companyId}/sites`));
296
+ }
297
+ async accessibleSites(companyId) {
298
+ const company = this.companies().find((entry) => entry.id === companyId);
299
+ const all = await this.sites(companyId);
300
+ if (!company || company.isOwner)
301
+ return all;
302
+ const granted = new Set(company.myAccess.map((entry) => entry.siteId));
303
+ return all.filter((site) => granted.has(site.id));
304
+ }
305
+ async switchContext(companyId, siteId) {
306
+ if (this._switching())
307
+ return;
308
+ this._switching.set(true);
309
+ this._error.set(null);
310
+ try {
311
+ const profile = await firstValueFrom(this.http.put(`${this.config.securityApiUrl}/me/context`, {
312
+ companyId,
313
+ siteId,
314
+ }));
315
+ const me = this._me();
316
+ if (me) {
317
+ const updated = { ...me, profile };
318
+ this._me.set(updated);
319
+ this._siteId.set(siteId);
320
+ await this.resolveMenu(updated, this.language, siteId);
321
+ }
322
+ }
323
+ catch (error) {
324
+ this._error.set(describe(error));
325
+ console.error('[session] no se pudo cambiar de sede', error);
326
+ }
327
+ finally {
328
+ this._switching.set(false);
329
+ }
330
+ }
331
+ async resolveMenu(me, language, preferred) {
332
+ const entries = [...me.ownedCompanies, ...me.sharedCompanies]
275
333
  .flatMap((company) => company.myAccess)
276
- .map((entry) => entry.appId.toLowerCase()));
334
+ .filter((entry) => entry.appId.toLowerCase() === this.config.appId);
335
+ const wanted = preferred ?? me.profile.lastSiteId ?? null;
336
+ const access = entries.find((entry) => entry.siteId === wanted) ?? entries[0] ?? null;
337
+ if (access) {
338
+ this._access.set(access);
339
+ this._siteId.set(access.siteId);
340
+ this._scope.set('site');
341
+ this._menu.set(await this.siteMenu(access.siteId, language));
342
+ return;
343
+ }
344
+ this._access.set(null);
345
+ this._siteId.set(wanted);
346
+ this._scope.set('account');
347
+ this._menu.set(await this.accountMenu(language));
348
+ }
349
+ buildLauncher(catalog) {
277
350
  return catalog
278
351
  .filter((app) => app.id.toLowerCase() !== this.config.appId)
279
- .map((app) => ({ ...app, hasAccess: granted.has(app.id.toLowerCase()) }))
352
+ .slice()
280
353
  .sort((a, b) => a.sortOrder - b.sortOrder);
281
354
  }
282
355
  siteMenu(siteId, language) {
@@ -294,6 +367,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
294
367
  type: Injectable,
295
368
  args: [{ providedIn: 'root' }]
296
369
  }] });
370
+ function toOption(company, relation) {
371
+ return {
372
+ id: company.id,
373
+ name: company.tradeName ?? company.legalName,
374
+ relation,
375
+ };
376
+ }
297
377
  function describe(error) {
298
378
  if (error instanceof HttpErrorResponse) {
299
379
  const problem = error.error;
@@ -930,9 +1010,24 @@ const SHELL_COPY = {
930
1010
  accessLoading: 'Cargando accesos...',
931
1011
  accessEmpty: 'Sin accesos asignados',
932
1012
  accountScope: 'Mi cuenta',
933
- hintNoAccess: 'Sin acceso',
934
1013
  hintComingSoon: 'Próximamente',
935
1014
  hintNotDeployed: 'Sin publicar',
1015
+ switchSite: 'Cambiar sede',
1016
+ contextTitle: 'Compañía y sede',
1017
+ contextHint: 'Elige dónde quieres trabajar. El menú se carga según tu rol en la sede.',
1018
+ companyLabel: 'Compañía',
1019
+ companyPlaceholder: 'Selecciona una compañía',
1020
+ siteLabel: 'Sede',
1021
+ sitePlaceholder: 'Selecciona una sede',
1022
+ sitesLoading: 'Cargando sedes...',
1023
+ sitesEmpty: 'Esta compañía no tiene sedes a tu alcance',
1024
+ confirmSwitch: 'Cambiar',
1025
+ relationOwner: 'Propietario',
1026
+ relationCollaborator: 'Colaborador',
1027
+ noContext: 'Sin sede seleccionada',
1028
+ noCompanyTitle: 'Te falta una compañía',
1029
+ noCompanyHint: 'Para trabajar en las aplicaciones necesitas al menos una compañía con una sede, ' +
1030
+ 'propia o donde te hayan invitado. Puedes entrar igual, pero el menú saldrá vacío.',
936
1031
  },
937
1032
  en: {
938
1033
  navToggle: 'Show or hide the menu',
@@ -948,9 +1043,24 @@ const SHELL_COPY = {
948
1043
  accessLoading: 'Loading access...',
949
1044
  accessEmpty: 'No access granted',
950
1045
  accountScope: 'My account',
951
- hintNoAccess: 'No access',
952
1046
  hintComingSoon: 'Coming soon',
953
1047
  hintNotDeployed: 'Not deployed',
1048
+ switchSite: 'Switch site',
1049
+ contextTitle: 'Company and site',
1050
+ contextHint: 'Choose where you want to work. The menu loads from your role at that site.',
1051
+ companyLabel: 'Company',
1052
+ companyPlaceholder: 'Select a company',
1053
+ siteLabel: 'Site',
1054
+ sitePlaceholder: 'Select a site',
1055
+ sitesLoading: 'Loading sites...',
1056
+ sitesEmpty: 'This company has no sites available to you',
1057
+ confirmSwitch: 'Switch',
1058
+ relationOwner: 'Owner',
1059
+ relationCollaborator: 'Collaborator',
1060
+ noContext: 'No site selected',
1061
+ noCompanyTitle: 'You need a company',
1062
+ noCompanyHint: 'To work in the applications you need at least one company with a site, your own or ' +
1063
+ 'one you have been invited to. You can still open them, but the menu will be empty.',
954
1064
  },
955
1065
  };
956
1066
 
@@ -978,8 +1088,14 @@ class NucleusShell {
978
1088
  menuLoading = this.session.loading;
979
1089
  menuError = this.session.error;
980
1090
  launcherApps = this.session.apps;
1091
+ switching = this.session.switching;
981
1092
  sidebarOpen = signal(true, ...(ngDevMode ? [{ debugName: "sidebarOpen" }] : /* istanbul ignore next */ []));
982
1093
  settingsOpen = signal(false, ...(ngDevMode ? [{ debugName: "settingsOpen" }] : /* istanbul ignore next */ []));
1094
+ contextOpen = signal(false, ...(ngDevMode ? [{ debugName: "contextOpen" }] : /* istanbul ignore next */ []));
1095
+ companyChoice = signal(null, ...(ngDevMode ? [{ debugName: "companyChoice" }] : /* istanbul ignore next */ []));
1096
+ siteChoice = signal(null, ...(ngDevMode ? [{ debugName: "siteChoice" }] : /* istanbul ignore next */ []));
1097
+ siteOptions = signal([], ...(ngDevMode ? [{ debugName: "siteOptions" }] : /* istanbul ignore next */ []));
1098
+ sitesLoading = signal(false, ...(ngDevMode ? [{ debugName: "sitesLoading" }] : /* istanbul ignore next */ []));
983
1099
  auth = this.injector.get(NucleusAuth, null);
984
1100
  identity = computed(() => {
985
1101
  const me = this.session.me();
@@ -1001,15 +1117,26 @@ class NucleusShell {
1001
1117
  }, ...(ngDevMode ? [{ debugName: "identity" }] : /* istanbul ignore next */ []));
1002
1118
  initials = computed(() => initialsOf(this.identity()?.name ?? ''), ...(ngDevMode ? [{ debugName: "initials" }] : /* istanbul ignore next */ []));
1003
1119
  canSwitchAccount = computed(() => this.auth?.switchAccount !== undefined, ...(ngDevMode ? [{ debugName: "canSwitchAccount" }] : /* istanbul ignore next */ []));
1004
- accessCaption = computed(() => {
1120
+ hasCompany = computed(() => this.session.companies().length > 0, ...(ngDevMode ? [{ debugName: "hasCompany" }] : /* istanbul ignore next */ []));
1121
+ companyChoices = computed(() => {
1122
+ const t = this.copy();
1123
+ return this.session.companyOptions().map((company) => ({
1124
+ ...company,
1125
+ tag: company.relation === 'owner' ? t.relationOwner : t.relationCollaborator,
1126
+ }));
1127
+ }, ...(ngDevMode ? [{ debugName: "companyChoices" }] : /* istanbul ignore next */ []));
1128
+ contextCaption = computed(() => {
1005
1129
  const role = this.session.roleName();
1006
1130
  const site = this.session.siteName();
1131
+ const company = this.session.companyName();
1007
1132
  if (role && site)
1008
- return `${role} · ${site}`;
1133
+ return company ? `${company} · ${site}` : site;
1009
1134
  if (this.session.scope() === 'account')
1010
1135
  return this.copy().accountScope;
1011
- return '';
1012
- }, ...(ngDevMode ? [{ debugName: "accessCaption" }] : /* istanbul ignore next */ []));
1136
+ return this.copy().noContext;
1137
+ }, ...(ngDevMode ? [{ debugName: "contextCaption" }] : /* istanbul ignore next */ []));
1138
+ roleName = this.session.roleName;
1139
+ canConfirm = computed(() => this.companyChoice() !== null && this.siteChoice() !== null && !this.switching(), ...(ngDevMode ? [{ debugName: "canConfirm" }] : /* istanbul ignore next */ []));
1013
1140
  themeOptions = computed(() => [
1014
1141
  ...THEMES.map((theme) => ({
1015
1142
  value: theme.id,
@@ -1046,8 +1173,31 @@ class NucleusShell {
1046
1173
  isSelected(node) {
1047
1174
  return this.selectedMenuId() === node.id;
1048
1175
  }
1176
+ async openContext() {
1177
+ const companyId = this.session.companyId() ?? this.companyChoices()[0]?.id ?? null;
1178
+ this.companyChoice.set(companyId);
1179
+ this.siteChoice.set(this.session.siteId());
1180
+ this.contextOpen.set(true);
1181
+ if (companyId)
1182
+ await this.loadSites(companyId);
1183
+ }
1184
+ async onCompanyChange(companyId) {
1185
+ this.companyChoice.set(companyId);
1186
+ this.siteChoice.set(null);
1187
+ this.siteOptions.set([]);
1188
+ if (companyId)
1189
+ await this.loadSites(companyId);
1190
+ }
1191
+ async confirmSwitch() {
1192
+ const companyId = this.companyChoice();
1193
+ const siteId = this.siteChoice();
1194
+ if (!companyId || !siteId)
1195
+ return;
1196
+ await this.session.switchContext(companyId, siteId);
1197
+ this.contextOpen.set(false);
1198
+ }
1049
1199
  canOpen(app) {
1050
- return app.hasAccess && app.status === 1 && !!app.url;
1200
+ return app.status === 1 && !!app.url;
1051
1201
  }
1052
1202
  launch(app) {
1053
1203
  if (!this.canOpen(app))
@@ -1059,8 +1209,6 @@ class NucleusShell {
1059
1209
  }
1060
1210
  launchHint(app) {
1061
1211
  const t = this.copy();
1062
- if (!app.hasAccess)
1063
- return t.hintNoAccess;
1064
1212
  if (app.status !== 1)
1065
1213
  return t.hintComingSoon;
1066
1214
  if (!app.url)
@@ -1077,8 +1225,25 @@ class NucleusShell {
1077
1225
  if (landing)
1078
1226
  window.location.href = landing;
1079
1227
  }
1228
+ async loadSites(companyId) {
1229
+ this.sitesLoading.set(true);
1230
+ try {
1231
+ const sites = await this.session.accessibleSites(companyId);
1232
+ this.siteOptions.set(sites);
1233
+ if (!sites.some((site) => site.id === this.siteChoice())) {
1234
+ this.siteChoice.set(sites[0]?.id ?? null);
1235
+ }
1236
+ }
1237
+ catch (error) {
1238
+ this.siteOptions.set([]);
1239
+ console.error('[shell] no se pudieron cargar las sedes', error);
1240
+ }
1241
+ finally {
1242
+ this.sitesLoading.set(false);
1243
+ }
1244
+ }
1080
1245
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusShell, deps: [], target: i0.ɵɵFactoryTarget.Component });
1081
- 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 (!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-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 (accessCaption()) {\n <p class=\"access-caption\">{{ accessCaption() }}</p>\n }\n\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 @if (heading()) {\n <h1>{{ heading() }}</h1>\n }\n @if (lead()) {\n <p class=\"lead\">{{ lead() }}</p>\n }\n\n <ng-content />\n </main>\n</div>\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", 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}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}}\n"], dependencies: [{ kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i1.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.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: DrawerModule }, { kind: "component", type: i3.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: i4.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: i5.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6.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: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: NucleusMark, selector: "nucleus-mark", inputs: ["accent", "size"] }, { kind: "component", type: NucleusStarfield, selector: "nucleus-starfield" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1246
+ 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 @if (heading()) {\n <h1>{{ heading() }}</h1>\n }\n @if (lead()) {\n <p class=\"lead\">{{ lead() }}</p>\n }\n\n <ng-content />\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", 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}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}\n"], dependencies: [{ kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i1.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.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: DrawerModule }, { kind: "component", type: i3.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: i4.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: i5.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: i6.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: i7.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i8.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: i9.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i9.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: NucleusMark, selector: "nucleus-mark", inputs: ["accent", "size"] }, { kind: "component", type: NucleusStarfield, selector: "nucleus-starfield" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1082
1247
  }
1083
1248
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusShell, decorators: [{
1084
1249
  type: Component,
@@ -1088,11 +1253,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
1088
1253
  DrawerModule,
1089
1254
  ListboxModule,
1090
1255
  PopoverModule,
1256
+ SelectModule,
1257
+ TagModule,
1091
1258
  TooltipModule,
1092
1259
  FormsModule,
1093
1260
  NucleusMark,
1094
1261
  NucleusStarfield,
1095
- ], changeDetection: ChangeDetectionStrategy.OnPush, 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 (!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-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 (accessCaption()) {\n <p class=\"access-caption\">{{ accessCaption() }}</p>\n }\n\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 @if (heading()) {\n <h1>{{ heading() }}</h1>\n }\n @if (lead()) {\n <p class=\"lead\">{{ lead() }}</p>\n }\n\n <ng-content />\n </main>\n</div>\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", 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}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}}\n"] }]
1262
+ ], changeDetection: ChangeDetectionStrategy.OnPush, 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 @if (heading()) {\n <h1>{{ heading() }}</h1>\n }\n @if (lead()) {\n <p class=\"lead\">{{ lead() }}</p>\n }\n\n <ng-content />\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", 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}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}\n"] }]
1096
1263
  }], propDecorators: { brand: [{ type: i0.Input, args: [{ isSignal: true, alias: "brand", required: false }] }], heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: false }] }], lead: [{ type: i0.Input, args: [{ isSignal: true, alias: "lead", required: false }] }], navItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "navItems", required: false }] }], activeNavId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeNavId", required: false }] }], selectedMenuId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedMenuId", required: false }] }], navSelect: [{ type: i0.Output, args: ["navSelect"] }], menuSelect: [{ type: i0.Output, args: ["menuSelect"] }] } });
1097
1264
  function initialsOf(source) {
1098
1265
  const parts = source.trim().split(/\s+/).filter(Boolean);
@@ -1 +1 @@
1
- {"version":3,"file":"nucleus-suite-pe-core.mjs","sources":["../../../projects/core/src/lib/config/nucleus-config.ts","../../../projects/core/src/lib/auth/nucleus-auth.ts","../../../projects/core/src/lib/auth/auth.context.ts","../../../projects/core/src/lib/auth/session-auth.service.ts","../../../projects/core/src/lib/auth/auth.interceptor.ts","../../../projects/core/src/lib/auth/user-sync.service.ts","../../../projects/core/src/lib/api/session.service.ts","../../../projects/core/src/lib/i18n/nucleus-language.ts","../../../projects/core/src/lib/theme/theme.ts","../../../projects/core/src/lib/theme/theme.service.ts","../../../projects/core/src/lib/theme/primeng-preset.ts","../../../projects/core/src/lib/theme/provide-theme.ts","../../../projects/core/src/lib/ui/nucleus-mark/nucleus-mark.ts","../../../projects/core/src/lib/ui/starfield/starfield.ts","../../../projects/core/src/lib/ui/shell/shell.copy.ts","../../../projects/core/src/lib/ui/shell/nucleus-shell.ts","../../../projects/core/src/lib/ui/shell/nucleus-shell.html","../../../projects/core/src/nucleus-suite-pe-core.ts"],"sourcesContent":["import { EnvironmentProviders, InjectionToken, makeEnvironmentProviders } from '@angular/core';\n\nexport interface NucleusConfig {\n readonly appId: string;\n readonly securityApiUrl: string;\n readonly appApiUrl: string | null;\n readonly landingUrl: string | null;\n}\n\nexport const NUCLEUS_CONFIG = new InjectionToken<NucleusConfig>('NUCLEUS_CONFIG');\n\nconst CONFIG_URL = 'config.json';\n\nexport function provideNucleus(config: NucleusConfig): EnvironmentProviders {\n return makeEnvironmentProviders([{ provide: NUCLEUS_CONFIG, useValue: normalize(config) }]);\n}\n\nexport async function loadNucleusConfig(url = CONFIG_URL): Promise<NucleusConfig> {\n const response = await fetch(url, { cache: 'no-store' });\n\n if (!response.ok) {\n throw new Error(`No se pudo cargar ${url}: HTTP ${response.status}`);\n }\n\n return normalize((await response.json()) as NucleusConfig);\n}\n\nexport function isNucleusConfigured(config: NucleusConfig): boolean {\n return config.securityApiUrl.length > 0 && config.appId.length > 0;\n}\n\nexport function ownsUrl(config: NucleusConfig, url: string): boolean {\n if (config.securityApiUrl.length > 0 && url.startsWith(config.securityApiUrl)) {\n return true;\n }\n\n return config.appApiUrl !== null && config.appApiUrl.length > 0 && url.startsWith(config.appApiUrl);\n}\n\nfunction normalize(config: NucleusConfig): NucleusConfig {\n return {\n appId: (config.appId ?? '').trim().toLowerCase(),\n securityApiUrl: trimSlash(config.securityApiUrl),\n appApiUrl: config.appApiUrl ? trimSlash(config.appApiUrl) : null,\n landingUrl: config.landingUrl ? trimSlash(config.landingUrl) : null,\n };\n}\n\nfunction trimSlash(value: string | null | undefined): string {\n return (value ?? '').trim().replace(/\\/+$/, '');\n}\n","import { Signal } from '@angular/core';\n\nexport interface NucleusIdentity {\n readonly uid: string;\n readonly provider: string;\n readonly providerUserId: string;\n readonly email: string | null;\n readonly displayName: string | null;\n readonly photoUrl: string | null;\n}\n\nexport abstract class NucleusAuth {\n abstract readonly user: Signal<NucleusIdentity | null>;\n\n abstract idToken(): Promise<string | null>;\n\n signOut?(): Promise<void>;\n\n switchAccount?(): Promise<void>;\n}\n","import { HttpContextToken } from '@angular/common/http';\n\nexport const NUCLEUS_FORCE_BEARER = new HttpContextToken<boolean>(() => false);\n\nexport const NUCLEUS_SKIP_AUTH = new HttpContextToken<boolean>(() => false);\n","import { HttpClient, HttpContext } from '@angular/common/http';\nimport { Injectable, Injector, computed, inject, signal } from '@angular/core';\nimport { firstValueFrom } from 'rxjs';\n\nimport { NUCLEUS_CONFIG, isNucleusConfigured } from '../config/nucleus-config';\nimport { NUCLEUS_FORCE_BEARER, NUCLEUS_SKIP_AUTH } from './auth.context';\nimport { NucleusAuth } from './nucleus-auth';\n\nconst SESSION_PATH = '/auth/session';\n\nconst LOGOUT_PATH = '/auth/logout';\n\nexport interface SessionTicket {\n readonly userId: string;\n readonly expiresAtUtc: string;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class NucleusSessionAuth {\n private readonly http = inject(HttpClient);\n private readonly config = inject(NUCLEUS_CONFIG);\n private readonly injector = inject(Injector);\n\n private readonly _ticket = signal<SessionTicket | null>(null);\n private readonly _failed = signal(false);\n\n private pending: Promise<boolean> | null = null;\n\n readonly ticket = this._ticket.asReadonly();\n\n readonly failed = this._failed.asReadonly();\n\n readonly established = computed(() => this._ticket() !== null);\n\n establish(force = false): Promise<boolean> {\n if (!force && this._ticket() !== null) return Promise.resolve(true);\n\n this.pending ??= this.request().finally(() => {\n this.pending = null;\n });\n\n return this.pending;\n }\n\n async clear(): Promise<void> {\n this._ticket.set(null);\n this._failed.set(false);\n\n if (!isNucleusConfigured(this.config)) return;\n\n try {\n await firstValueFrom(\n this.http.post(\n `${this.config.securityApiUrl}${LOGOUT_PATH}`,\n {},\n {\n withCredentials: true,\n context: new HttpContext().set(NUCLEUS_SKIP_AUTH, true),\n },\n ),\n );\n } catch (error) {\n console.error('[auth] no se pudo cerrar la sesión de cookie', error);\n }\n }\n\n private async request(): Promise<boolean> {\n if (!isNucleusConfigured(this.config)) return false;\n\n if (this.injector.get(NucleusAuth, null) === null) return false;\n\n try {\n const ticket = await firstValueFrom(\n this.http.post<SessionTicket>(\n `${this.config.securityApiUrl}${SESSION_PATH}`,\n {},\n {\n withCredentials: true,\n context: new HttpContext().set(NUCLEUS_FORCE_BEARER, true),\n },\n ),\n );\n\n this._ticket.set(ticket);\n this._failed.set(false);\n\n return true;\n } catch (error) {\n this._ticket.set(null);\n this._failed.set(true);\n console.error('[auth] no se pudo abrir la sesión de cookie', error);\n\n return false;\n }\n }\n}\n","import { HttpErrorResponse, HttpInterceptorFn } from '@angular/common/http';\nimport { inject } from '@angular/core';\nimport { catchError, from, switchMap, throwError } from 'rxjs';\n\nimport { NUCLEUS_CONFIG, ownsUrl } from '../config/nucleus-config';\nimport { NUCLEUS_FORCE_BEARER, NUCLEUS_SKIP_AUTH } from './auth.context';\nimport { NucleusAuth } from './nucleus-auth';\nimport { NucleusSessionAuth } from './session-auth.service';\n\nexport const nucleusAuthInterceptor: HttpInterceptorFn = (req, next) => {\n const config = inject(NUCLEUS_CONFIG);\n\n if (!ownsUrl(config, req.url) || req.context.get(NUCLEUS_SKIP_AUTH)) {\n return next(req);\n }\n\n const session = inject(NucleusSessionAuth);\n const auth = inject(NucleusAuth, { optional: true });\n\n const request = req.clone({ withCredentials: true });\n\n if (!req.context.get(NUCLEUS_FORCE_BEARER) && session.established()) {\n return next(request).pipe(\n catchError((error: unknown) => {\n if (!(error instanceof HttpErrorResponse) || error.status !== 401) {\n return throwError(() => error);\n }\n\n return from(session.establish(true)).pipe(\n switchMap((renewed) => (renewed ? next(request) : throwError(() => error))),\n );\n }),\n );\n }\n\n if (!auth) {\n return next(request);\n }\n\n return from(auth.idToken()).pipe(\n switchMap((token) =>\n next(token ? request.clone({ setHeaders: { Authorization: `Bearer ${token}` } }) : request),\n ),\n );\n};\n","import { HttpClient } from '@angular/common/http';\nimport { Injectable, inject, signal } from '@angular/core';\nimport { firstValueFrom } from 'rxjs';\n\nimport { NUCLEUS_CONFIG, isNucleusConfigured } from '../config/nucleus-config';\nimport { NucleusIdentity } from './nucleus-auth';\n\nconst AUTH_SYNC_PATH = '/auth/sync';\n\nexport interface AuthSyncRequest {\n readonly provider: string;\n readonly providerUserId: string;\n readonly email: string | null;\n readonly displayName: string | null;\n readonly photoUrl: string | null;\n}\n\nexport interface AppUser {\n readonly userId: string;\n readonly displayName: string | null;\n readonly photoUrl: string | null;\n readonly createdAt: string;\n readonly isNew: boolean;\n readonly profileCompleted: boolean;\n readonly hasCompanies: boolean;\n readonly isPlatformAdmin: boolean;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class UserSyncService {\n private readonly http = inject(HttpClient);\n private readonly config = inject(NUCLEUS_CONFIG);\n\n readonly appUser = signal<AppUser | null>(null);\n\n readonly failed = signal(false);\n\n async sync(session: NucleusIdentity, idToken: () => Promise<string | null>): Promise<void> {\n if (!isNucleusConfigured(this.config)) {\n console.info('[auth] sincronización omitida: securityApiUrl o appId vacíos en config.json');\n return;\n }\n\n const token = await idToken();\n\n if (!token) {\n this.failed.set(true);\n console.error('[auth] no hay ID token con el que autenticar la sincronización');\n return;\n }\n\n const body: AuthSyncRequest = {\n provider: session.provider,\n providerUserId: session.providerUserId,\n email: session.email,\n displayName: session.displayName,\n photoUrl: session.photoUrl,\n };\n\n try {\n const user = await firstValueFrom(\n this.http.post<AppUser>(`${this.config.securityApiUrl}${AUTH_SYNC_PATH}`, body),\n );\n\n this.appUser.set(user);\n this.failed.set(false);\n } catch (error) {\n this.failed.set(true);\n console.error('[auth] no se pudo sincronizar el usuario con el backend', error);\n }\n }\n}\n","import { HttpClient, HttpErrorResponse } from '@angular/common/http';\nimport { Injectable, computed, inject, signal } from '@angular/core';\nimport { firstValueFrom } from 'rxjs';\n\nimport { NucleusAuth } from '../auth/nucleus-auth';\nimport { NucleusSessionAuth } from '../auth/session-auth.service';\nimport { UserSyncService } from '../auth/user-sync.service';\nimport { NUCLEUS_CONFIG, isNucleusConfigured } from '../config/nucleus-config';\nimport { AccessScope, AppSummary, LauncherApp, MeResponse, MenuNode, SiteAccess } from './api.models';\n\n@Injectable({ providedIn: 'root' })\nexport class SessionService {\n private readonly http = inject(HttpClient);\n private readonly auth = inject(NucleusAuth, { optional: true });\n private readonly userSync = inject(UserSyncService);\n private readonly sessionAuth = inject(NucleusSessionAuth);\n private readonly config = inject(NUCLEUS_CONFIG);\n\n private readonly _me = signal<MeResponse | null>(null);\n private readonly _menu = signal<readonly MenuNode[]>([]);\n private readonly _access = signal<SiteAccess | null>(null);\n private readonly _scope = signal<AccessScope | null>(null);\n private readonly _apps = signal<readonly LauncherApp[]>([]);\n private readonly _loading = signal(false);\n private readonly _error = signal<string | null>(null);\n\n private inFlight = false;\n private loadedKey: string | null = null;\n\n readonly me = this._me.asReadonly();\n\n readonly menu = this._menu.asReadonly();\n\n readonly access = this._access.asReadonly();\n\n readonly scope = this._scope.asReadonly();\n\n readonly apps = this._apps.asReadonly();\n\n readonly loading = this._loading.asReadonly();\n\n readonly error = this._error.asReadonly();\n\n readonly roleName = computed(() => this._access()?.roleName ?? null);\n\n readonly siteName = computed(() => this._access()?.siteName ?? null);\n\n readonly companies = computed(() => {\n const me = this._me();\n if (!me) return [];\n return [...me.ownedCompanies, ...me.sharedCompanies];\n });\n\n async load(language: string, force = false): Promise<void> {\n if (!isNucleusConfigured(this.config)) return;\n\n const identity = this.auth?.user() ?? null;\n\n if (this.auth && !identity) return;\n\n const key = `${identity?.uid ?? 'cookie'}|${language}`;\n\n if (this.inFlight) return;\n if (!force && this.loadedKey === key) return;\n\n this.inFlight = true;\n this.loadedKey = key;\n\n this._loading.set(true);\n this._error.set(null);\n\n try {\n if (identity && this.auth) {\n await this.userSync.sync(identity, () => this.auth!.idToken());\n await this.sessionAuth.establish(force);\n }\n\n const [me, catalog] = await Promise.all([\n firstValueFrom(this.http.get<MeResponse>(`${this.config.securityApiUrl}/me`)),\n firstValueFrom(this.http.get<AppSummary[]>(`${this.config.securityApiUrl}/apps`)),\n ]);\n\n this._me.set(me);\n this._apps.set(this.buildLauncher(me, catalog));\n\n const access = [...me.ownedCompanies, ...me.sharedCompanies]\n .flatMap((company) => company.myAccess)\n .find((entry) => entry.appId.toLowerCase() === this.config.appId);\n\n if (access) {\n this._access.set(access);\n this._scope.set('site');\n this._menu.set(await this.siteMenu(access.siteId, language));\n return;\n }\n\n this._access.set(null);\n this._scope.set('account');\n this._menu.set(await this.accountMenu(language));\n } catch (error) {\n this._menu.set([]);\n this._error.set(describe(error));\n console.error('[session] no se pudo cargar la sesión del backend', error);\n } finally {\n this.inFlight = false;\n this._loading.set(false);\n }\n }\n\n reload(language: string): Promise<void> {\n return this.load(language, true);\n }\n\n private buildLauncher(me: MeResponse, catalog: readonly AppSummary[]): LauncherApp[] {\n const granted = new Set(\n [...me.ownedCompanies, ...me.sharedCompanies]\n .flatMap((company) => company.myAccess)\n .map((entry) => entry.appId.toLowerCase()),\n );\n\n return catalog\n .filter((app) => app.id.toLowerCase() !== this.config.appId)\n .map((app) => ({ ...app, hasAccess: granted.has(app.id.toLowerCase()) }))\n .sort((a, b) => a.sortOrder - b.sortOrder);\n }\n\n private siteMenu(siteId: string, language: string): Promise<MenuNode[]> {\n return firstValueFrom(\n this.http.get<MenuNode[]>(\n `${this.config.securityApiUrl}/sites/${siteId}/apps/${this.config.appId}/menu`,\n { params: { language } },\n ),\n );\n }\n\n private accountMenu(language: string): Promise<MenuNode[]> {\n return firstValueFrom(\n this.http.get<MenuNode[]>(`${this.config.securityApiUrl}/me/menu`, {\n params: { appId: this.config.appId, language },\n }),\n );\n }\n}\n\nfunction describe(error: unknown): string {\n if (error instanceof HttpErrorResponse) {\n const problem = error.error as { detail?: string; title?: string } | null;\n return problem?.detail ?? problem?.title ?? `HTTP ${error.status}`;\n }\n\n return 'Error desconocido';\n}\n","import { Injectable, effect, signal } from '@angular/core';\n\nexport type NucleusLang = 'es' | 'en';\n\nexport const NUCLEUS_LANGS: readonly NucleusLang[] = ['es', 'en'];\n\nconst STORAGE_KEY = 'nucleus_lang';\n\nfunction isLang(value: unknown): value is NucleusLang {\n return value === 'es' || value === 'en';\n}\n\nfunction readStored(): NucleusLang {\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (isLang(stored)) return stored;\n } catch {}\n\n return 'es';\n}\n\n@Injectable({ providedIn: 'root' })\nexport class NucleusLanguage {\n private readonly _lang = signal<NucleusLang>(readStored());\n\n readonly lang = this._lang.asReadonly();\n\n constructor() {\n effect(() => {\n const lang = this._lang();\n\n document.documentElement.lang = lang;\n\n try {\n localStorage.setItem(STORAGE_KEY, lang);\n } catch {}\n });\n }\n\n setLang(lang: NucleusLang): void {\n this._lang.set(lang);\n }\n}\n","export type ThemeId =\n | 'nucleus'\n | 'light'\n | 'dark'\n | 'bubblegum'\n | 'cool-breeze'\n | 'cool-slate'\n | 'icy-mint'\n | 'juicy-plum'\n | 'mango-paradise'\n | 'moonlight-glow'\n | 'mystical-forest'\n | 'silky-pink'\n | 'spicy-red'\n | 'sunny-day';\n\nexport type ThemePreference = ThemeId | 'system';\n\nexport interface ThemeTokens {\n readonly bg: string;\n\n readonly surface: string;\n\n readonly surfaceAlt: string;\n\n readonly text: string;\n\n readonly textMuted: string;\n\n readonly border: string;\n\n readonly accent: string;\n\n readonly onAccent: string;\n}\n\nexport interface Theme {\n readonly id: ThemeId;\n\n readonly scheme: 'light' | 'dark';\n\n readonly swatch: string;\n\n readonly starfield: boolean;\n readonly tokens: ThemeTokens;\n}\n\nexport const THEMES: readonly Theme[] = [\n {\n id: 'nucleus',\n scheme: 'dark',\n swatch: '#7c6cf5',\n starfield: true,\n tokens: {\n bg: '#050508',\n surface: '#0d0d15',\n surfaceAlt: '#16161f',\n text: '#ffffff',\n textMuted: 'rgba(255, 255, 255, 0.6)',\n border: 'rgba(255, 255, 255, 0.14)',\n accent: '#7c6cf5',\n onAccent: '#ffffff',\n },\n },\n {\n id: 'light',\n scheme: 'light',\n swatch: '#f5f5f5',\n starfield: false,\n tokens: {\n bg: '#ffffff',\n surface: '#f5f5f5',\n surfaceAlt: '#eeeeee',\n text: '#1e1e1e',\n textMuted: '#5a5a5a',\n border: '#cccedb',\n accent: '#0078d4',\n onAccent: '#ffffff',\n },\n },\n {\n id: 'dark',\n scheme: 'dark',\n swatch: '#1e1e1e',\n starfield: false,\n tokens: {\n bg: '#1e1e1e',\n surface: '#252526',\n surfaceAlt: '#2d2d30',\n text: '#f1f1f1',\n textMuted: '#a0a0a0',\n border: '#3f3f46',\n accent: '#0097fb',\n onAccent: '#ffffff',\n },\n },\n {\n id: 'bubblegum',\n scheme: 'light',\n swatch: '#f7b8d4',\n starfield: false,\n tokens: {\n bg: '#fff0f6',\n surface: '#ffe0ed',\n surfaceAlt: '#ffd0e4',\n text: '#3d1029',\n textMuted: '#8a4c6c',\n border: '#f0aac9',\n accent: '#d6337f',\n onAccent: '#ffffff',\n },\n },\n {\n id: 'cool-breeze',\n scheme: 'light',\n swatch: '#a8d5e8',\n starfield: false,\n tokens: {\n bg: '#eef7fb',\n surface: '#dcecf5',\n surfaceAlt: '#cbe2ef',\n text: '#102a38',\n textMuted: '#4a6b7d',\n border: '#a5c9db',\n accent: '#0f7ba8',\n onAccent: '#ffffff',\n },\n },\n {\n id: 'cool-slate',\n scheme: 'dark',\n swatch: '#3b4a5c',\n starfield: false,\n tokens: {\n bg: '#232b36',\n surface: '#2c3644',\n surfaceAlt: '#354152',\n text: '#e6ecf4',\n textMuted: '#9fb0c4',\n border: '#44546a',\n accent: '#5fa8e8',\n onAccent: '#0b1118',\n },\n },\n {\n id: 'icy-mint',\n scheme: 'light',\n swatch: '#c4ece5',\n starfield: false,\n tokens: {\n bg: '#f0fbf8',\n surface: '#dcf3ee',\n surfaceAlt: '#c9eae3',\n text: '#0d2f2a',\n textMuted: '#4a706a',\n border: '#a3d6cd',\n accent: '#0d8f7d',\n onAccent: '#ffffff',\n },\n },\n {\n id: 'juicy-plum',\n scheme: 'dark',\n swatch: '#6b3a7a',\n starfield: false,\n tokens: {\n bg: '#2a1633',\n surface: '#372042',\n surfaceAlt: '#452a52',\n text: '#f3e8f7',\n textMuted: '#b795c4',\n border: '#57366a',\n accent: '#c86dd7',\n onAccent: '#1a0d20',\n },\n },\n {\n id: 'mango-paradise',\n scheme: 'light',\n swatch: '#f7c48a',\n starfield: false,\n tokens: {\n bg: '#fff6ec',\n surface: '#ffe9d4',\n surfaceAlt: '#ffdcbc',\n text: '#3d2410',\n textMuted: '#8a5f38',\n border: '#f0c096',\n accent: '#e07314',\n onAccent: '#ffffff',\n },\n },\n {\n id: 'moonlight-glow',\n scheme: 'dark',\n swatch: '#1f3a5f',\n starfield: false,\n tokens: {\n bg: '#131f33',\n surface: '#1c2b45',\n surfaceAlt: '#243657',\n text: '#e3ecfa',\n textMuted: '#94a9c9',\n border: '#33496e',\n accent: '#6ea8f0',\n onAccent: '#0a1020',\n },\n },\n {\n id: 'mystical-forest',\n scheme: 'dark',\n swatch: '#1f4a2e',\n starfield: false,\n tokens: {\n bg: '#132419',\n surface: '#1b3223',\n surfaceAlt: '#24422e',\n text: '#e4f2e8',\n textMuted: '#93b7a0',\n border: '#325a41',\n accent: '#4caf70',\n onAccent: '#0a1610',\n },\n },\n {\n id: 'silky-pink',\n scheme: 'light',\n swatch: '#f3c2d6',\n starfield: false,\n tokens: {\n bg: '#fdf2f7',\n surface: '#fae3ed',\n surfaceAlt: '#f6d3e2',\n text: '#3a1626',\n textMuted: '#87566a',\n border: '#eeb4cb',\n accent: '#c14b82',\n onAccent: '#ffffff',\n },\n },\n {\n id: 'spicy-red',\n scheme: 'dark',\n swatch: '#8f1f24',\n starfield: false,\n tokens: {\n bg: '#2a1113',\n surface: '#3a181b',\n surfaceAlt: '#4a1f23',\n text: '#f8e6e7',\n textMuted: '#c79398',\n border: '#5f2a2f',\n accent: '#e8555e',\n onAccent: '#1a0809',\n },\n },\n {\n id: 'sunny-day',\n scheme: 'light',\n swatch: '#efe4b0',\n starfield: false,\n tokens: {\n bg: '#fdf9e8',\n surface: '#f7efd2',\n surfaceAlt: '#f0e5bd',\n text: '#332d10',\n textMuted: '#736a38',\n border: '#ddcf94',\n accent: '#a8860b',\n onAccent: '#ffffff',\n },\n },\n];\n\nexport const THEME_LABELS: Readonly<Record<ThemeId, string>> = {\n nucleus: 'Nucleus',\n light: 'Light',\n dark: 'Dark',\n bubblegum: 'Bubblegum',\n 'cool-breeze': 'Cool Breeze',\n 'cool-slate': 'Cool Slate',\n 'icy-mint': 'Icy Mint',\n 'juicy-plum': 'Juicy Plum',\n 'mango-paradise': 'Mango Paradise',\n 'moonlight-glow': 'Moonlight Glow',\n 'mystical-forest': 'Mystical Forest',\n 'silky-pink': 'Silky Pink',\n 'spicy-red': 'Spicy Red',\n 'sunny-day': 'Sunny Day',\n};\n\nexport const DEFAULT_THEME: ThemeId = 'nucleus';\n\nconst BY_ID = new Map(THEMES.map((theme) => [theme.id, theme]));\n\nexport function themeById(id: ThemeId): Theme {\n return BY_ID.get(id) ?? BY_ID.get(DEFAULT_THEME)!;\n}\n\nexport function isThemePreference(value: unknown): value is ThemePreference {\n return value === 'system' || (typeof value === 'string' && BY_ID.has(value as ThemeId));\n}\n","import { Injectable, computed, effect, signal } from '@angular/core';\n\nimport { DEFAULT_THEME, Theme, ThemePreference, isThemePreference, themeById } from './theme';\n\nconst STORAGE_KEY = 'nucleus_theme';\n\nfunction readStoredPreference(): ThemePreference {\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (isThemePreference(stored)) return stored;\n } catch {}\n return DEFAULT_THEME;\n}\n\nfunction prefersDark(): boolean {\n return globalThis.matchMedia?.('(prefers-color-scheme: dark)').matches ?? false;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class ThemeService {\n private readonly _preference = signal<ThemePreference>(readStoredPreference());\n\n private readonly systemDark = signal(prefersDark());\n\n readonly preference = this._preference.asReadonly();\n\n readonly theme = computed<Theme>(() => {\n const preference = this._preference();\n if (preference === 'system') return themeById(this.systemDark() ? 'dark' : 'light');\n return themeById(preference);\n });\n\n readonly starfield = computed(() => this.theme().starfield);\n\n constructor() {\n globalThis\n .matchMedia?.('(prefers-color-scheme: dark)')\n .addEventListener('change', (event) => this.systemDark.set(event.matches));\n\n effect(() => {\n const preference = this._preference();\n const theme = this.theme();\n\n this.applyToDom(theme);\n\n try {\n localStorage.setItem(STORAGE_KEY, preference);\n } catch {}\n });\n }\n\n setPreference(preference: ThemePreference): void {\n this._preference.set(preference);\n }\n\n private applyToDom(theme: Theme): void {\n const root = document.documentElement;\n\n for (const [name, value] of Object.entries(theme.tokens)) {\n root.style.setProperty(`--ac-${name.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)}`, value);\n }\n\n root.dataset['theme'] = theme.id;\n\n root.classList.toggle('ns-dark', theme.scheme === 'dark');\n\n root.style.colorScheme = theme.scheme;\n }\n}\n","import { definePreset } from '@primeuix/themes';\nimport Lara from '@primeuix/themes/lara';\n\nconst MASK = {\n background: 'rgba(0, 0, 0, 0.55)',\n color: 'var(--ac-text)',\n};\n\nconst SHADOW = '0 10px 40px rgba(0, 0, 0, 0.45)';\n\nconst PANEL = {\n background: 'var(--ac-surface)',\n borderColor: 'var(--ac-border)',\n color: 'var(--ac-text)',\n};\n\nconst schemeTokens = {\n primary: {\n color: 'var(--ac-accent)',\n contrastColor: 'var(--ac-on-accent)',\n hoverColor: 'color-mix(in srgb, var(--ac-accent) 85%, var(--ac-text))',\n activeColor: 'color-mix(in srgb, var(--ac-accent) 70%, var(--ac-text))',\n },\n highlight: {\n background: 'color-mix(in srgb, var(--ac-accent) 16%, transparent)',\n focusBackground: 'color-mix(in srgb, var(--ac-accent) 24%, transparent)',\n color: 'var(--ac-text)',\n focusColor: 'var(--ac-text)',\n },\n text: {\n color: 'var(--ac-text)',\n hoverColor: 'var(--ac-text)',\n mutedColor: 'var(--ac-text-muted)',\n hoverMutedColor: 'var(--ac-text)',\n },\n content: {\n background: 'var(--ac-surface)',\n hoverBackground: 'var(--ac-surface-alt)',\n borderColor: 'var(--ac-border)',\n color: 'var(--ac-text)',\n hoverColor: 'var(--ac-text)',\n },\n overlay: {\n select: {\n background: 'var(--ac-surface)',\n borderColor: 'var(--ac-border)',\n color: 'var(--ac-text)',\n },\n popover: {\n background: 'var(--ac-surface)',\n borderColor: 'var(--ac-border)',\n color: 'var(--ac-text)',\n },\n modal: {\n background: 'var(--ac-surface)',\n borderColor: 'var(--ac-border)',\n color: 'var(--ac-text)',\n },\n },\n formField: {\n background: 'var(--ac-bg)',\n disabledBackground: 'var(--ac-surface-alt)',\n filledBackground: 'var(--ac-surface-alt)',\n filledHoverBackground: 'var(--ac-surface-alt)',\n filledFocusBackground: 'var(--ac-surface-alt)',\n borderColor: 'var(--ac-border)',\n hoverBorderColor: 'var(--ac-accent)',\n focusBorderColor: 'var(--ac-accent)',\n color: 'var(--ac-text)',\n disabledColor: 'var(--ac-text-muted)',\n placeholderColor: 'var(--ac-text-muted)',\n floatLabelColor: 'var(--ac-text-muted)',\n floatLabelFocusColor: 'var(--ac-accent)',\n iconColor: 'var(--ac-text-muted)',\n },\n list: {\n option: {\n focusBackground: 'var(--ac-surface-alt)',\n selectedBackground: 'color-mix(in srgb, var(--ac-accent) 20%, transparent)',\n selectedFocusBackground: 'color-mix(in srgb, var(--ac-accent) 28%, transparent)',\n color: 'var(--ac-text)',\n focusColor: 'var(--ac-text)',\n selectedColor: 'var(--ac-text)',\n selectedFocusColor: 'var(--ac-text)',\n icon: {\n color: 'var(--ac-text-muted)',\n focusColor: 'var(--ac-text)',\n },\n },\n },\n navigation: {\n item: {\n focusBackground: 'var(--ac-surface-alt)',\n activeBackground: 'color-mix(in srgb, var(--ac-accent) 20%, transparent)',\n color: 'var(--ac-text)',\n focusColor: 'var(--ac-text)',\n activeColor: 'var(--ac-text)',\n icon: {\n color: 'var(--ac-text-muted)',\n focusColor: 'var(--ac-text)',\n activeColor: 'var(--ac-accent)',\n },\n },\n },\n};\n\nexport const NucleusPreset = definePreset(Lara, {\n semantic: {\n colorScheme: {\n light: { ...schemeTokens, mask: MASK },\n dark: { ...schemeTokens, mask: MASK },\n },\n },\n components: {\n drawer: { root: { ...PANEL, shadow: SHADOW } },\n popover: { root: { ...PANEL, shadow: SHADOW } },\n menu: { root: { ...PANEL, shadow: SHADOW } },\n listbox: { root: PANEL },\n },\n});\n","import { EnvironmentProviders } from '@angular/core';\nimport { providePrimeNG } from 'primeng/config';\n\nimport { NucleusPreset } from './primeng-preset';\n\nexport const NUCLEUS_DARK_SELECTOR = '.ns-dark';\n\nexport function provideNucleusTheme(): EnvironmentProviders {\n return providePrimeNG({\n theme: {\n preset: NucleusPreset,\n options: { darkModeSelector: NUCLEUS_DARK_SELECTOR },\n },\n });\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\n\nconst ORBIT = { rx: 78, ry: 196 } as const;\n\n@Component({\n selector: 'nucleus-mark',\n changeDetection: ChangeDetectionStrategy.OnPush,\n styles: `\n :host {\n display: block;\n }\n\n svg {\n display: block;\n }\n `,\n template: `\n <svg\n [attr.width]=\"size()\"\n [attr.height]=\"size()\"\n viewBox=\"-230 -230 460 460\"\n aria-hidden=\"true\"\n >\n @for (r of rotations; track $index) {\n <ellipse\n [attr.rx]=\"orbit.rx\"\n [attr.ry]=\"orbit.ry\"\n [attr.transform]=\"'rotate(' + r + ')'\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"18\"\n />\n }\n <circle r=\"42\" [attr.fill]=\"accent()\" />\n </svg>\n `,\n})\nexport class NucleusMark {\n readonly accent = input('#7C6CF5');\n readonly size = input(28);\n\n protected readonly orbit = ORBIT;\n protected readonly rotations = [0, 60, 120];\n}\n","import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nconst W = 1280;\nconst H = 720;\n\nconst STARS = Array.from({ length: 130 }, (_, i) => {\n const a = i * 2.399963;\n const big = i % 11 === 0;\n const sway = Math.sin(a * 1.7);\n const lift = Math.cos(a * 2.3);\n\n return {\n cx: +((Math.sin(a * 7.13) * 0.5 + 0.5) * W).toFixed(2),\n cy: +((Math.cos(a * 3.77) * 0.5 + 0.5) * H).toFixed(2),\n r: +((big ? 2.4 : 0.9) + (i % 4) * 0.5).toFixed(2),\n opacity: ((big ? 0.85 : 0.42) + (i % 5) * 0.09).toFixed(2),\n dx: `${(sway * 26).toFixed(1)}px`,\n dy: `${(lift * 18).toFixed(1)}px`,\n duration: `${(11 + (i % 9) * 1.7).toFixed(1)}s`,\n delay: `-${((i % 13) * 0.85).toFixed(2)}s`,\n };\n});\n\n@Component({\n selector: 'nucleus-starfield',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <svg\n [attr.viewBox]=\"'0 0 ' + W + ' ' + H\"\n preserveAspectRatio=\"xMidYMid slice\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <defs>\n <radialGradient id=\"ns-starfield-glow\" cx=\"50%\" cy=\"0%\" r=\"75%\">\n <stop offset=\"0%\" stop-color=\"var(--ac-accent)\" stop-opacity=\"0.18\" />\n <stop offset=\"70%\" stop-color=\"var(--ac-accent)\" stop-opacity=\"0\" />\n </radialGradient>\n </defs>\n\n <rect width=\"100%\" height=\"100%\" fill=\"url(#ns-starfield-glow)\" />\n\n @for (star of stars; track $index) {\n <circle\n [attr.cx]=\"star.cx\"\n [attr.cy]=\"star.cy\"\n [attr.r]=\"star.r\"\n [style.--o]=\"star.opacity\"\n [style.--dx]=\"star.dx\"\n [style.--dy]=\"star.dy\"\n [style.--dur]=\"star.duration\"\n [style.--delay]=\"star.delay\"\n fill=\"#ffffff\"\n />\n }\n </svg>\n `,\n styles: `\n :host {\n position: fixed;\n inset: 0;\n z-index: -1;\n display: block;\n pointer-events: none;\n background: var(--ac-bg);\n }\n\n svg {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n circle {\n opacity: var(--o);\n animation: ns-drift var(--dur) ease-in-out var(--delay) infinite alternate;\n }\n\n @keyframes ns-drift {\n from {\n transform: translate(0, 0);\n opacity: var(--o);\n }\n to {\n transform: translate(var(--dx), var(--dy));\n opacity: calc(var(--o) * 0.3);\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n circle {\n animation: none;\n }\n }\n `,\n})\nexport class NucleusStarfield {\n protected readonly W = W;\n protected readonly H = H;\n protected readonly stars = STARS;\n}\n","import { NucleusLang } from '../../i18n/nucleus-language';\n\nexport interface ShellCopy {\n readonly navToggle: string;\n readonly appsLauncher: string;\n readonly appsEmpty: string;\n readonly settingsTitle: string;\n readonly settingsTheme: string;\n readonly settingsThemeHint: string;\n readonly themeSystem: string;\n readonly signOut: string;\n readonly accountManage: string;\n readonly accountSwitch: string;\n readonly accessLoading: string;\n readonly accessEmpty: string;\n readonly accountScope: string;\n readonly hintNoAccess: string;\n readonly hintComingSoon: string;\n readonly hintNotDeployed: string;\n}\n\nexport const SHELL_COPY: Readonly<Record<NucleusLang, ShellCopy>> = {\n es: {\n navToggle: 'Mostrar u ocultar el menú',\n appsLauncher: 'Aplicaciones',\n appsEmpty: 'No hay otras aplicaciones',\n settingsTitle: 'Ajustes',\n settingsTheme: 'Tema',\n settingsThemeHint: 'Elige cómo se ve la suite en este dispositivo.',\n themeSystem: 'Del sistema',\n signOut: 'Cerrar sesión',\n accountManage: 'Gestionar mi cuenta',\n accountSwitch: 'Cambiar de cuenta',\n accessLoading: 'Cargando accesos...',\n accessEmpty: 'Sin accesos asignados',\n accountScope: 'Mi cuenta',\n hintNoAccess: 'Sin acceso',\n hintComingSoon: 'Próximamente',\n hintNotDeployed: 'Sin publicar',\n },\n en: {\n navToggle: 'Show or hide the menu',\n appsLauncher: 'Applications',\n appsEmpty: 'No other applications',\n settingsTitle: 'Settings',\n settingsTheme: 'Theme',\n settingsThemeHint: 'Choose how the suite looks on this device.',\n themeSystem: 'System',\n signOut: 'Sign out',\n accountManage: 'Manage my account',\n accountSwitch: 'Switch account',\n accessLoading: 'Loading access...',\n accessEmpty: 'No access granted',\n accountScope: 'My account',\n hintNoAccess: 'No access',\n hintComingSoon: 'Coming soon',\n hintNotDeployed: 'Not deployed',\n },\n};\n","import {\n ChangeDetectionStrategy,\n Component,\n Injector,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n untracked,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { Router } from '@angular/router';\nimport { AvatarModule } from 'primeng/avatar';\nimport { ButtonModule } from 'primeng/button';\nimport { DrawerModule } from 'primeng/drawer';\nimport { ListboxModule } from 'primeng/listbox';\nimport { PopoverModule } from 'primeng/popover';\nimport { TooltipModule } from 'primeng/tooltip';\n\nimport { LauncherApp, MenuNode } from '../../api/api.models';\nimport { SessionService } from '../../api/session.service';\nimport { NucleusAuth } from '../../auth/nucleus-auth';\nimport { NucleusSessionAuth } from '../../auth/session-auth.service';\nimport { NUCLEUS_CONFIG } from '../../config/nucleus-config';\nimport { NucleusLang, NucleusLanguage } from '../../i18n/nucleus-language';\nimport { THEMES, THEME_LABELS, ThemePreference } from '../../theme/theme';\nimport { ThemeService } from '../../theme/theme.service';\nimport { NucleusMark } from '../nucleus-mark/nucleus-mark';\nimport { NucleusStarfield } from '../starfield/starfield';\nimport { SHELL_COPY } from './shell.copy';\n\nexport interface ShellNavItem {\n readonly id: string;\n readonly icon: string;\n readonly label: string;\n}\n\ninterface ThemeOption {\n readonly value: ThemePreference;\n readonly label: string;\n readonly swatch: string | null;\n}\n\ninterface ShellIdentity {\n readonly name: string;\n readonly email: string;\n readonly photoUrl: string | null;\n}\n\n@Component({\n selector: 'nucleus-shell',\n imports: [\n AvatarModule,\n ButtonModule,\n DrawerModule,\n ListboxModule,\n PopoverModule,\n TooltipModule,\n FormsModule,\n NucleusMark,\n NucleusStarfield,\n ],\n templateUrl: './nucleus-shell.html',\n styleUrl: './nucleus-shell.css',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class NucleusShell {\n private readonly session = inject(SessionService);\n private readonly sessionAuth = inject(NucleusSessionAuth);\n private readonly themes = inject(ThemeService);\n private readonly language = inject(NucleusLanguage);\n private readonly config = inject(NUCLEUS_CONFIG);\n private readonly injector = inject(Injector);\n private readonly router = inject(Router);\n\n readonly brand = input('SUITE');\n readonly heading = input('');\n readonly lead = input('');\n readonly navItems = input<readonly ShellNavItem[]>([]);\n readonly activeNavId = input<string | null>(null);\n readonly selectedMenuId = input<string | null>(null);\n\n readonly navSelect = output<string>();\n readonly menuSelect = output<MenuNode>();\n\n protected readonly lang = this.language.lang;\n protected readonly copy = computed(() => SHELL_COPY[this.lang()]);\n\n protected readonly starfield = this.themes.starfield;\n protected readonly themePreference = this.themes.preference;\n\n protected readonly menu = this.session.menu;\n protected readonly menuLoading = this.session.loading;\n protected readonly menuError = this.session.error;\n protected readonly launcherApps = this.session.apps;\n\n protected readonly sidebarOpen = signal(true);\n protected readonly settingsOpen = signal(false);\n\n private readonly auth = this.injector.get(NucleusAuth, null);\n\n protected readonly identity = computed<ShellIdentity | null>(() => {\n const me = this.session.me();\n\n if (me) {\n return {\n name: me.displayName ?? me.userId,\n email: me.userId,\n photoUrl: me.photoUrl,\n };\n }\n\n const user = this.auth?.user() ?? null;\n\n if (!user) return null;\n\n return {\n name: user.displayName ?? user.email ?? user.providerUserId,\n email: user.email ?? user.providerUserId,\n photoUrl: user.photoUrl,\n };\n });\n\n protected readonly initials = computed(() => initialsOf(this.identity()?.name ?? ''));\n\n protected readonly canSwitchAccount = computed(() => this.auth?.switchAccount !== undefined);\n\n protected readonly accessCaption = computed(() => {\n const role = this.session.roleName();\n const site = this.session.siteName();\n\n if (role && site) return `${role} · ${site}`;\n if (this.session.scope() === 'account') return this.copy().accountScope;\n\n return '';\n });\n\n protected readonly themeOptions = computed<ThemeOption[]>(() => [\n ...THEMES.map((theme) => ({\n value: theme.id as ThemePreference,\n label: THEME_LABELS[theme.id],\n swatch: theme.swatch,\n })),\n { value: 'system', label: this.copy().themeSystem, swatch: null },\n ]);\n\n private readonly loadSession = effect(() => {\n const language = this.lang();\n const user = this.auth?.user() ?? null;\n\n if (this.auth && !user) return;\n\n untracked(() => void this.session.load(language));\n });\n\n protected setLang(lang: NucleusLang): void {\n this.language.setLang(lang);\n }\n\n protected toggleSidebar(): void {\n this.sidebarOpen.update((open) => !open);\n }\n\n protected selectTheme(preference: ThemePreference | null): void {\n if (preference) this.themes.setPreference(preference);\n }\n\n protected selectNav(id: string): void {\n this.navSelect.emit(id);\n }\n\n protected selectMenu(node: MenuNode): void {\n this.menuSelect.emit(node);\n\n if (node.route) void this.router.navigateByUrl(node.route);\n }\n\n protected isSelected(node: MenuNode): boolean {\n return this.selectedMenuId() === node.id;\n }\n\n protected canOpen(app: LauncherApp): boolean {\n return app.hasAccess && app.status === 1 && !!app.url;\n }\n\n protected launch(app: LauncherApp): void {\n if (!this.canOpen(app)) return;\n\n window.location.href = app.url as string;\n }\n\n protected appInitials(app: LauncherApp): string {\n return initialsOf(app.name);\n }\n\n protected launchHint(app: LauncherApp): string {\n const t = this.copy();\n\n if (!app.hasAccess) return t.hintNoAccess;\n if (app.status !== 1) return t.hintComingSoon;\n if (!app.url) return t.hintNotDeployed;\n\n return '';\n }\n\n protected async switchAccount(): Promise<void> {\n await this.auth?.switchAccount?.();\n }\n\n protected async signOut(): Promise<void> {\n await this.sessionAuth.clear();\n await this.auth?.signOut?.();\n\n const landing = this.config.landingUrl;\n\n if (landing) window.location.href = landing;\n }\n}\n\nfunction initialsOf(source: string): string {\n const parts = source.trim().split(/\\s+/).filter(Boolean);\n\n if (!parts.length) return '?';\n if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();\n\n return (parts[0][0] + parts[1][0]).toUpperCase();\n}\n","@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 (!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-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 (accessCaption()) {\n <p class=\"access-caption\">{{ accessCaption() }}</p>\n }\n\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 @if (heading()) {\n <h1>{{ heading() }}</h1>\n }\n @if (lead()) {\n <p class=\"lead\">{{ lead() }}</p>\n }\n\n <ng-content />\n </main>\n</div>\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 * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["STORAGE_KEY"],"mappings":"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"}
1
+ {"version":3,"file":"nucleus-suite-pe-core.mjs","sources":["../../../projects/core/src/lib/config/nucleus-config.ts","../../../projects/core/src/lib/auth/nucleus-auth.ts","../../../projects/core/src/lib/auth/auth.context.ts","../../../projects/core/src/lib/auth/session-auth.service.ts","../../../projects/core/src/lib/auth/auth.interceptor.ts","../../../projects/core/src/lib/auth/user-sync.service.ts","../../../projects/core/src/lib/api/session.service.ts","../../../projects/core/src/lib/i18n/nucleus-language.ts","../../../projects/core/src/lib/theme/theme.ts","../../../projects/core/src/lib/theme/theme.service.ts","../../../projects/core/src/lib/theme/primeng-preset.ts","../../../projects/core/src/lib/theme/provide-theme.ts","../../../projects/core/src/lib/ui/nucleus-mark/nucleus-mark.ts","../../../projects/core/src/lib/ui/starfield/starfield.ts","../../../projects/core/src/lib/ui/shell/shell.copy.ts","../../../projects/core/src/lib/ui/shell/nucleus-shell.ts","../../../projects/core/src/lib/ui/shell/nucleus-shell.html","../../../projects/core/src/nucleus-suite-pe-core.ts"],"sourcesContent":["import { EnvironmentProviders, InjectionToken, makeEnvironmentProviders } from '@angular/core';\n\nexport interface NucleusConfig {\n readonly appId: string;\n readonly securityApiUrl: string;\n readonly appApiUrl: string | null;\n readonly landingUrl: string | null;\n}\n\nexport const NUCLEUS_CONFIG = new InjectionToken<NucleusConfig>('NUCLEUS_CONFIG');\n\nconst CONFIG_URL = 'config.json';\n\nexport function provideNucleus(config: NucleusConfig): EnvironmentProviders {\n return makeEnvironmentProviders([{ provide: NUCLEUS_CONFIG, useValue: normalize(config) }]);\n}\n\nexport async function loadNucleusConfig(url = CONFIG_URL): Promise<NucleusConfig> {\n const response = await fetch(url, { cache: 'no-store' });\n\n if (!response.ok) {\n throw new Error(`No se pudo cargar ${url}: HTTP ${response.status}`);\n }\n\n return normalize((await response.json()) as NucleusConfig);\n}\n\nexport function isNucleusConfigured(config: NucleusConfig): boolean {\n return config.securityApiUrl.length > 0 && config.appId.length > 0;\n}\n\nexport function ownsUrl(config: NucleusConfig, url: string): boolean {\n if (config.securityApiUrl.length > 0 && url.startsWith(config.securityApiUrl)) {\n return true;\n }\n\n return config.appApiUrl !== null && config.appApiUrl.length > 0 && url.startsWith(config.appApiUrl);\n}\n\nfunction normalize(config: NucleusConfig): NucleusConfig {\n return {\n appId: (config.appId ?? '').trim().toLowerCase(),\n securityApiUrl: trimSlash(config.securityApiUrl),\n appApiUrl: config.appApiUrl ? trimSlash(config.appApiUrl) : null,\n landingUrl: config.landingUrl ? trimSlash(config.landingUrl) : null,\n };\n}\n\nfunction trimSlash(value: string | null | undefined): string {\n return (value ?? '').trim().replace(/\\/+$/, '');\n}\n","import { Signal } from '@angular/core';\n\nexport interface NucleusIdentity {\n readonly uid: string;\n readonly provider: string;\n readonly providerUserId: string;\n readonly email: string | null;\n readonly displayName: string | null;\n readonly photoUrl: string | null;\n}\n\nexport abstract class NucleusAuth {\n abstract readonly user: Signal<NucleusIdentity | null>;\n\n abstract idToken(): Promise<string | null>;\n\n signOut?(): Promise<void>;\n\n switchAccount?(): Promise<void>;\n}\n","import { HttpContextToken } from '@angular/common/http';\n\nexport const NUCLEUS_FORCE_BEARER = new HttpContextToken<boolean>(() => false);\n\nexport const NUCLEUS_SKIP_AUTH = new HttpContextToken<boolean>(() => false);\n","import { HttpClient, HttpContext } from '@angular/common/http';\nimport { Injectable, Injector, computed, inject, signal } from '@angular/core';\nimport { firstValueFrom } from 'rxjs';\n\nimport { NUCLEUS_CONFIG, isNucleusConfigured } from '../config/nucleus-config';\nimport { NUCLEUS_FORCE_BEARER, NUCLEUS_SKIP_AUTH } from './auth.context';\nimport { NucleusAuth } from './nucleus-auth';\n\nconst SESSION_PATH = '/auth/session';\n\nconst LOGOUT_PATH = '/auth/logout';\n\nexport interface SessionTicket {\n readonly userId: string;\n readonly expiresAtUtc: string;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class NucleusSessionAuth {\n private readonly http = inject(HttpClient);\n private readonly config = inject(NUCLEUS_CONFIG);\n private readonly injector = inject(Injector);\n\n private readonly _ticket = signal<SessionTicket | null>(null);\n private readonly _failed = signal(false);\n\n private pending: Promise<boolean> | null = null;\n\n readonly ticket = this._ticket.asReadonly();\n\n readonly failed = this._failed.asReadonly();\n\n readonly established = computed(() => this._ticket() !== null);\n\n establish(force = false): Promise<boolean> {\n if (!force && this._ticket() !== null) return Promise.resolve(true);\n\n this.pending ??= this.request().finally(() => {\n this.pending = null;\n });\n\n return this.pending;\n }\n\n async clear(): Promise<void> {\n this._ticket.set(null);\n this._failed.set(false);\n\n if (!isNucleusConfigured(this.config)) return;\n\n try {\n await firstValueFrom(\n this.http.post(\n `${this.config.securityApiUrl}${LOGOUT_PATH}`,\n {},\n {\n withCredentials: true,\n context: new HttpContext().set(NUCLEUS_SKIP_AUTH, true),\n },\n ),\n );\n } catch (error) {\n console.error('[auth] no se pudo cerrar la sesión de cookie', error);\n }\n }\n\n private async request(): Promise<boolean> {\n if (!isNucleusConfigured(this.config)) return false;\n\n if (this.injector.get(NucleusAuth, null) === null) return false;\n\n try {\n const ticket = await firstValueFrom(\n this.http.post<SessionTicket>(\n `${this.config.securityApiUrl}${SESSION_PATH}`,\n {},\n {\n withCredentials: true,\n context: new HttpContext().set(NUCLEUS_FORCE_BEARER, true),\n },\n ),\n );\n\n this._ticket.set(ticket);\n this._failed.set(false);\n\n return true;\n } catch (error) {\n this._ticket.set(null);\n this._failed.set(true);\n console.error('[auth] no se pudo abrir la sesión de cookie', error);\n\n return false;\n }\n }\n}\n","import { HttpErrorResponse, HttpInterceptorFn } from '@angular/common/http';\nimport { inject } from '@angular/core';\nimport { catchError, from, switchMap, throwError } from 'rxjs';\n\nimport { NUCLEUS_CONFIG, ownsUrl } from '../config/nucleus-config';\nimport { NUCLEUS_FORCE_BEARER, NUCLEUS_SKIP_AUTH } from './auth.context';\nimport { NucleusAuth } from './nucleus-auth';\nimport { NucleusSessionAuth } from './session-auth.service';\n\nexport const nucleusAuthInterceptor: HttpInterceptorFn = (req, next) => {\n const config = inject(NUCLEUS_CONFIG);\n\n if (!ownsUrl(config, req.url) || req.context.get(NUCLEUS_SKIP_AUTH)) {\n return next(req);\n }\n\n const session = inject(NucleusSessionAuth);\n const auth = inject(NucleusAuth, { optional: true });\n\n const request = req.clone({ withCredentials: true });\n\n if (!req.context.get(NUCLEUS_FORCE_BEARER) && session.established()) {\n return next(request).pipe(\n catchError((error: unknown) => {\n if (!(error instanceof HttpErrorResponse) || error.status !== 401) {\n return throwError(() => error);\n }\n\n return from(session.establish(true)).pipe(\n switchMap((renewed) => (renewed ? next(request) : throwError(() => error))),\n );\n }),\n );\n }\n\n if (!auth) {\n return next(request);\n }\n\n return from(auth.idToken()).pipe(\n switchMap((token) =>\n next(token ? request.clone({ setHeaders: { Authorization: `Bearer ${token}` } }) : request),\n ),\n );\n};\n","import { HttpClient } from '@angular/common/http';\nimport { Injectable, inject, signal } from '@angular/core';\nimport { firstValueFrom } from 'rxjs';\n\nimport { NUCLEUS_CONFIG, isNucleusConfigured } from '../config/nucleus-config';\nimport { NucleusIdentity } from './nucleus-auth';\n\nconst AUTH_SYNC_PATH = '/auth/sync';\n\nexport interface AuthSyncRequest {\n readonly provider: string;\n readonly providerUserId: string;\n readonly email: string | null;\n readonly displayName: string | null;\n readonly photoUrl: string | null;\n}\n\nexport interface AppUser {\n readonly userId: string;\n readonly displayName: string | null;\n readonly photoUrl: string | null;\n readonly createdAt: string;\n readonly isNew: boolean;\n readonly profileCompleted: boolean;\n readonly hasCompanies: boolean;\n readonly isPlatformAdmin: boolean;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class UserSyncService {\n private readonly http = inject(HttpClient);\n private readonly config = inject(NUCLEUS_CONFIG);\n\n readonly appUser = signal<AppUser | null>(null);\n\n readonly failed = signal(false);\n\n async sync(session: NucleusIdentity, idToken: () => Promise<string | null>): Promise<void> {\n if (!isNucleusConfigured(this.config)) {\n console.info('[auth] sincronización omitida: securityApiUrl o appId vacíos en config.json');\n return;\n }\n\n const token = await idToken();\n\n if (!token) {\n this.failed.set(true);\n console.error('[auth] no hay ID token con el que autenticar la sincronización');\n return;\n }\n\n const body: AuthSyncRequest = {\n provider: session.provider,\n providerUserId: session.providerUserId,\n email: session.email,\n displayName: session.displayName,\n photoUrl: session.photoUrl,\n };\n\n try {\n const user = await firstValueFrom(\n this.http.post<AppUser>(`${this.config.securityApiUrl}${AUTH_SYNC_PATH}`, body),\n );\n\n this.appUser.set(user);\n this.failed.set(false);\n } catch (error) {\n this.failed.set(true);\n console.error('[auth] no se pudo sincronizar el usuario con el backend', error);\n }\n }\n}\n","import { HttpClient, HttpErrorResponse } from '@angular/common/http';\nimport { Injectable, computed, inject, signal } from '@angular/core';\nimport { firstValueFrom } from 'rxjs';\n\nimport { NucleusAuth } from '../auth/nucleus-auth';\nimport { NucleusSessionAuth } from '../auth/session-auth.service';\nimport { UserSyncService } from '../auth/user-sync.service';\nimport { NUCLEUS_CONFIG, isNucleusConfigured } from '../config/nucleus-config';\nimport {\n AccessScope,\n AppSummary,\n CompanyOption,\n CompanySummary,\n LauncherApp,\n MeResponse,\n MenuNode,\n Site,\n SiteAccess,\n UserProfile,\n} from './api.models';\n\n@Injectable({ providedIn: 'root' })\nexport class SessionService {\n private readonly http = inject(HttpClient);\n private readonly auth = inject(NucleusAuth, { optional: true });\n private readonly userSync = inject(UserSyncService);\n private readonly sessionAuth = inject(NucleusSessionAuth);\n private readonly config = inject(NUCLEUS_CONFIG);\n\n private readonly _me = signal<MeResponse | null>(null);\n private readonly _menu = signal<readonly MenuNode[]>([]);\n private readonly _access = signal<SiteAccess | null>(null);\n private readonly _scope = signal<AccessScope | null>(null);\n private readonly _apps = signal<readonly LauncherApp[]>([]);\n private readonly _siteId = signal<string | null>(null);\n private readonly _loading = signal(false);\n private readonly _switching = signal(false);\n private readonly _error = signal<string | null>(null);\n\n private inFlight = false;\n private loadedKey: string | null = null;\n private language = 'es';\n\n readonly me = this._me.asReadonly();\n\n readonly menu = this._menu.asReadonly();\n\n readonly access = this._access.asReadonly();\n\n readonly scope = this._scope.asReadonly();\n\n readonly apps = this._apps.asReadonly();\n\n readonly siteId = this._siteId.asReadonly();\n\n readonly loading = this._loading.asReadonly();\n\n readonly switching = this._switching.asReadonly();\n\n readonly error = this._error.asReadonly();\n\n readonly roleName = computed(() => this._access()?.roleName ?? null);\n\n readonly siteName = computed(() => this._access()?.siteName ?? null);\n\n readonly companies = computed<readonly CompanySummary[]>(() => {\n const me = this._me();\n if (!me) return [];\n return [...me.ownedCompanies, ...me.sharedCompanies];\n });\n\n readonly companyOptions = computed<readonly CompanyOption[]>(() => {\n const me = this._me();\n if (!me) return [];\n\n return [\n ...me.ownedCompanies.map((company) => toOption(company, 'owner' as const)),\n ...me.sharedCompanies.map((company) => toOption(company, 'collaborator' as const)),\n ];\n });\n\n readonly companyId = computed(() => {\n const siteId = this._siteId();\n if (!siteId) return this._me()?.profile.lastCompanyId ?? null;\n\n const owner = this.companies().find((company) =>\n company.myAccess.some((entry) => entry.siteId === siteId),\n );\n\n return owner?.id ?? this._me()?.profile.lastCompanyId ?? null;\n });\n\n readonly companyName = computed(() => {\n const id = this.companyId();\n if (!id) return null;\n\n return this.companyOptions().find((company) => company.id === id)?.name ?? null;\n });\n\n async load(language: string, force = false): Promise<void> {\n if (!isNucleusConfigured(this.config)) return;\n\n const identity = this.auth?.user() ?? null;\n\n if (this.auth && !identity) return;\n\n const key = `${identity?.uid ?? 'cookie'}|${language}`;\n\n if (this.inFlight) return;\n if (!force && this.loadedKey === key) return;\n\n this.inFlight = true;\n this.loadedKey = key;\n this.language = language;\n\n this._loading.set(true);\n this._error.set(null);\n\n try {\n if (identity && this.auth) {\n await this.userSync.sync(identity, () => this.auth!.idToken());\n await this.sessionAuth.establish(force);\n }\n\n const [me, catalog] = await Promise.all([\n firstValueFrom(this.http.get<MeResponse>(`${this.config.securityApiUrl}/me`)),\n firstValueFrom(this.http.get<AppSummary[]>(`${this.config.securityApiUrl}/apps`)),\n ]);\n\n this._me.set(me);\n this._apps.set(this.buildLauncher(catalog));\n\n await this.resolveMenu(me, language);\n } catch (error) {\n this._menu.set([]);\n this._error.set(describe(error));\n console.error('[session] no se pudo cargar la sesión del backend', error);\n } finally {\n this.inFlight = false;\n this._loading.set(false);\n }\n }\n\n reload(language: string): Promise<void> {\n return this.load(language, true);\n }\n\n sites(companyId: string): Promise<Site[]> {\n return firstValueFrom(\n this.http.get<Site[]>(`${this.config.securityApiUrl}/companies/${companyId}/sites`),\n );\n }\n\n async accessibleSites(companyId: string): Promise<Site[]> {\n const company = this.companies().find((entry) => entry.id === companyId);\n const all = await this.sites(companyId);\n\n if (!company || company.isOwner) return all;\n\n const granted = new Set(company.myAccess.map((entry) => entry.siteId));\n\n return all.filter((site) => granted.has(site.id));\n }\n\n async switchContext(companyId: string, siteId: string): Promise<void> {\n if (this._switching()) return;\n\n this._switching.set(true);\n this._error.set(null);\n\n try {\n const profile = await firstValueFrom(\n this.http.put<UserProfile>(`${this.config.securityApiUrl}/me/context`, {\n companyId,\n siteId,\n }),\n );\n\n const me = this._me();\n\n if (me) {\n const updated: MeResponse = { ...me, profile };\n this._me.set(updated);\n this._siteId.set(siteId);\n await this.resolveMenu(updated, this.language, siteId);\n }\n } catch (error) {\n this._error.set(describe(error));\n console.error('[session] no se pudo cambiar de sede', error);\n } finally {\n this._switching.set(false);\n }\n }\n\n private async resolveMenu(me: MeResponse, language: string, preferred?: string): Promise<void> {\n const entries = [...me.ownedCompanies, ...me.sharedCompanies]\n .flatMap((company) => company.myAccess)\n .filter((entry) => entry.appId.toLowerCase() === this.config.appId);\n\n const wanted = preferred ?? me.profile.lastSiteId ?? null;\n\n const access = entries.find((entry) => entry.siteId === wanted) ?? entries[0] ?? null;\n\n if (access) {\n this._access.set(access);\n this._siteId.set(access.siteId);\n this._scope.set('site');\n this._menu.set(await this.siteMenu(access.siteId, language));\n return;\n }\n\n this._access.set(null);\n this._siteId.set(wanted);\n this._scope.set('account');\n this._menu.set(await this.accountMenu(language));\n }\n\n private buildLauncher(catalog: readonly AppSummary[]): LauncherApp[] {\n return catalog\n .filter((app) => app.id.toLowerCase() !== this.config.appId)\n .slice()\n .sort((a, b) => a.sortOrder - b.sortOrder);\n }\n\n private siteMenu(siteId: string, language: string): Promise<MenuNode[]> {\n return firstValueFrom(\n this.http.get<MenuNode[]>(\n `${this.config.securityApiUrl}/sites/${siteId}/apps/${this.config.appId}/menu`,\n { params: { language } },\n ),\n );\n }\n\n private accountMenu(language: string): Promise<MenuNode[]> {\n return firstValueFrom(\n this.http.get<MenuNode[]>(`${this.config.securityApiUrl}/me/menu`, {\n params: { appId: this.config.appId, language },\n }),\n );\n }\n}\n\nfunction toOption(company: CompanySummary, relation: 'owner' | 'collaborator'): CompanyOption {\n return {\n id: company.id,\n name: company.tradeName ?? company.legalName,\n relation,\n };\n}\n\nfunction describe(error: unknown): string {\n if (error instanceof HttpErrorResponse) {\n const problem = error.error as { detail?: string; title?: string } | null;\n return problem?.detail ?? problem?.title ?? `HTTP ${error.status}`;\n }\n\n return 'Error desconocido';\n}\n","import { Injectable, effect, signal } from '@angular/core';\n\nexport type NucleusLang = 'es' | 'en';\n\nexport const NUCLEUS_LANGS: readonly NucleusLang[] = ['es', 'en'];\n\nconst STORAGE_KEY = 'nucleus_lang';\n\nfunction isLang(value: unknown): value is NucleusLang {\n return value === 'es' || value === 'en';\n}\n\nfunction readStored(): NucleusLang {\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (isLang(stored)) return stored;\n } catch {}\n\n return 'es';\n}\n\n@Injectable({ providedIn: 'root' })\nexport class NucleusLanguage {\n private readonly _lang = signal<NucleusLang>(readStored());\n\n readonly lang = this._lang.asReadonly();\n\n constructor() {\n effect(() => {\n const lang = this._lang();\n\n document.documentElement.lang = lang;\n\n try {\n localStorage.setItem(STORAGE_KEY, lang);\n } catch {}\n });\n }\n\n setLang(lang: NucleusLang): void {\n this._lang.set(lang);\n }\n}\n","export type ThemeId =\n | 'nucleus'\n | 'light'\n | 'dark'\n | 'bubblegum'\n | 'cool-breeze'\n | 'cool-slate'\n | 'icy-mint'\n | 'juicy-plum'\n | 'mango-paradise'\n | 'moonlight-glow'\n | 'mystical-forest'\n | 'silky-pink'\n | 'spicy-red'\n | 'sunny-day';\n\nexport type ThemePreference = ThemeId | 'system';\n\nexport interface ThemeTokens {\n readonly bg: string;\n\n readonly surface: string;\n\n readonly surfaceAlt: string;\n\n readonly text: string;\n\n readonly textMuted: string;\n\n readonly border: string;\n\n readonly accent: string;\n\n readonly onAccent: string;\n}\n\nexport interface Theme {\n readonly id: ThemeId;\n\n readonly scheme: 'light' | 'dark';\n\n readonly swatch: string;\n\n readonly starfield: boolean;\n readonly tokens: ThemeTokens;\n}\n\nexport const THEMES: readonly Theme[] = [\n {\n id: 'nucleus',\n scheme: 'dark',\n swatch: '#7c6cf5',\n starfield: true,\n tokens: {\n bg: '#050508',\n surface: '#0d0d15',\n surfaceAlt: '#16161f',\n text: '#ffffff',\n textMuted: 'rgba(255, 255, 255, 0.6)',\n border: 'rgba(255, 255, 255, 0.14)',\n accent: '#7c6cf5',\n onAccent: '#ffffff',\n },\n },\n {\n id: 'light',\n scheme: 'light',\n swatch: '#f5f5f5',\n starfield: false,\n tokens: {\n bg: '#ffffff',\n surface: '#f5f5f5',\n surfaceAlt: '#eeeeee',\n text: '#1e1e1e',\n textMuted: '#5a5a5a',\n border: '#cccedb',\n accent: '#0078d4',\n onAccent: '#ffffff',\n },\n },\n {\n id: 'dark',\n scheme: 'dark',\n swatch: '#1e1e1e',\n starfield: false,\n tokens: {\n bg: '#1e1e1e',\n surface: '#252526',\n surfaceAlt: '#2d2d30',\n text: '#f1f1f1',\n textMuted: '#a0a0a0',\n border: '#3f3f46',\n accent: '#0097fb',\n onAccent: '#ffffff',\n },\n },\n {\n id: 'bubblegum',\n scheme: 'light',\n swatch: '#f7b8d4',\n starfield: false,\n tokens: {\n bg: '#fff0f6',\n surface: '#ffe0ed',\n surfaceAlt: '#ffd0e4',\n text: '#3d1029',\n textMuted: '#8a4c6c',\n border: '#f0aac9',\n accent: '#d6337f',\n onAccent: '#ffffff',\n },\n },\n {\n id: 'cool-breeze',\n scheme: 'light',\n swatch: '#a8d5e8',\n starfield: false,\n tokens: {\n bg: '#eef7fb',\n surface: '#dcecf5',\n surfaceAlt: '#cbe2ef',\n text: '#102a38',\n textMuted: '#4a6b7d',\n border: '#a5c9db',\n accent: '#0f7ba8',\n onAccent: '#ffffff',\n },\n },\n {\n id: 'cool-slate',\n scheme: 'dark',\n swatch: '#3b4a5c',\n starfield: false,\n tokens: {\n bg: '#232b36',\n surface: '#2c3644',\n surfaceAlt: '#354152',\n text: '#e6ecf4',\n textMuted: '#9fb0c4',\n border: '#44546a',\n accent: '#5fa8e8',\n onAccent: '#0b1118',\n },\n },\n {\n id: 'icy-mint',\n scheme: 'light',\n swatch: '#c4ece5',\n starfield: false,\n tokens: {\n bg: '#f0fbf8',\n surface: '#dcf3ee',\n surfaceAlt: '#c9eae3',\n text: '#0d2f2a',\n textMuted: '#4a706a',\n border: '#a3d6cd',\n accent: '#0d8f7d',\n onAccent: '#ffffff',\n },\n },\n {\n id: 'juicy-plum',\n scheme: 'dark',\n swatch: '#6b3a7a',\n starfield: false,\n tokens: {\n bg: '#2a1633',\n surface: '#372042',\n surfaceAlt: '#452a52',\n text: '#f3e8f7',\n textMuted: '#b795c4',\n border: '#57366a',\n accent: '#c86dd7',\n onAccent: '#1a0d20',\n },\n },\n {\n id: 'mango-paradise',\n scheme: 'light',\n swatch: '#f7c48a',\n starfield: false,\n tokens: {\n bg: '#fff6ec',\n surface: '#ffe9d4',\n surfaceAlt: '#ffdcbc',\n text: '#3d2410',\n textMuted: '#8a5f38',\n border: '#f0c096',\n accent: '#e07314',\n onAccent: '#ffffff',\n },\n },\n {\n id: 'moonlight-glow',\n scheme: 'dark',\n swatch: '#1f3a5f',\n starfield: false,\n tokens: {\n bg: '#131f33',\n surface: '#1c2b45',\n surfaceAlt: '#243657',\n text: '#e3ecfa',\n textMuted: '#94a9c9',\n border: '#33496e',\n accent: '#6ea8f0',\n onAccent: '#0a1020',\n },\n },\n {\n id: 'mystical-forest',\n scheme: 'dark',\n swatch: '#1f4a2e',\n starfield: false,\n tokens: {\n bg: '#132419',\n surface: '#1b3223',\n surfaceAlt: '#24422e',\n text: '#e4f2e8',\n textMuted: '#93b7a0',\n border: '#325a41',\n accent: '#4caf70',\n onAccent: '#0a1610',\n },\n },\n {\n id: 'silky-pink',\n scheme: 'light',\n swatch: '#f3c2d6',\n starfield: false,\n tokens: {\n bg: '#fdf2f7',\n surface: '#fae3ed',\n surfaceAlt: '#f6d3e2',\n text: '#3a1626',\n textMuted: '#87566a',\n border: '#eeb4cb',\n accent: '#c14b82',\n onAccent: '#ffffff',\n },\n },\n {\n id: 'spicy-red',\n scheme: 'dark',\n swatch: '#8f1f24',\n starfield: false,\n tokens: {\n bg: '#2a1113',\n surface: '#3a181b',\n surfaceAlt: '#4a1f23',\n text: '#f8e6e7',\n textMuted: '#c79398',\n border: '#5f2a2f',\n accent: '#e8555e',\n onAccent: '#1a0809',\n },\n },\n {\n id: 'sunny-day',\n scheme: 'light',\n swatch: '#efe4b0',\n starfield: false,\n tokens: {\n bg: '#fdf9e8',\n surface: '#f7efd2',\n surfaceAlt: '#f0e5bd',\n text: '#332d10',\n textMuted: '#736a38',\n border: '#ddcf94',\n accent: '#a8860b',\n onAccent: '#ffffff',\n },\n },\n];\n\nexport const THEME_LABELS: Readonly<Record<ThemeId, string>> = {\n nucleus: 'Nucleus',\n light: 'Light',\n dark: 'Dark',\n bubblegum: 'Bubblegum',\n 'cool-breeze': 'Cool Breeze',\n 'cool-slate': 'Cool Slate',\n 'icy-mint': 'Icy Mint',\n 'juicy-plum': 'Juicy Plum',\n 'mango-paradise': 'Mango Paradise',\n 'moonlight-glow': 'Moonlight Glow',\n 'mystical-forest': 'Mystical Forest',\n 'silky-pink': 'Silky Pink',\n 'spicy-red': 'Spicy Red',\n 'sunny-day': 'Sunny Day',\n};\n\nexport const DEFAULT_THEME: ThemeId = 'nucleus';\n\nconst BY_ID = new Map(THEMES.map((theme) => [theme.id, theme]));\n\nexport function themeById(id: ThemeId): Theme {\n return BY_ID.get(id) ?? BY_ID.get(DEFAULT_THEME)!;\n}\n\nexport function isThemePreference(value: unknown): value is ThemePreference {\n return value === 'system' || (typeof value === 'string' && BY_ID.has(value as ThemeId));\n}\n","import { Injectable, computed, effect, signal } from '@angular/core';\n\nimport { DEFAULT_THEME, Theme, ThemePreference, isThemePreference, themeById } from './theme';\n\nconst STORAGE_KEY = 'nucleus_theme';\n\nfunction readStoredPreference(): ThemePreference {\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (isThemePreference(stored)) return stored;\n } catch {}\n return DEFAULT_THEME;\n}\n\nfunction prefersDark(): boolean {\n return globalThis.matchMedia?.('(prefers-color-scheme: dark)').matches ?? false;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class ThemeService {\n private readonly _preference = signal<ThemePreference>(readStoredPreference());\n\n private readonly systemDark = signal(prefersDark());\n\n readonly preference = this._preference.asReadonly();\n\n readonly theme = computed<Theme>(() => {\n const preference = this._preference();\n if (preference === 'system') return themeById(this.systemDark() ? 'dark' : 'light');\n return themeById(preference);\n });\n\n readonly starfield = computed(() => this.theme().starfield);\n\n constructor() {\n globalThis\n .matchMedia?.('(prefers-color-scheme: dark)')\n .addEventListener('change', (event) => this.systemDark.set(event.matches));\n\n effect(() => {\n const preference = this._preference();\n const theme = this.theme();\n\n this.applyToDom(theme);\n\n try {\n localStorage.setItem(STORAGE_KEY, preference);\n } catch {}\n });\n }\n\n setPreference(preference: ThemePreference): void {\n this._preference.set(preference);\n }\n\n private applyToDom(theme: Theme): void {\n const root = document.documentElement;\n\n for (const [name, value] of Object.entries(theme.tokens)) {\n root.style.setProperty(`--ac-${name.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)}`, value);\n }\n\n root.dataset['theme'] = theme.id;\n\n root.classList.toggle('ns-dark', theme.scheme === 'dark');\n\n root.style.colorScheme = theme.scheme;\n }\n}\n","import { definePreset } from '@primeuix/themes';\nimport Lara from '@primeuix/themes/lara';\n\nconst MASK = {\n background: 'rgba(0, 0, 0, 0.55)',\n color: 'var(--ac-text)',\n};\n\nconst SHADOW = '0 10px 40px rgba(0, 0, 0, 0.45)';\n\nconst PANEL = {\n background: 'var(--ac-surface)',\n borderColor: 'var(--ac-border)',\n color: 'var(--ac-text)',\n};\n\nconst schemeTokens = {\n primary: {\n color: 'var(--ac-accent)',\n contrastColor: 'var(--ac-on-accent)',\n hoverColor: 'color-mix(in srgb, var(--ac-accent) 85%, var(--ac-text))',\n activeColor: 'color-mix(in srgb, var(--ac-accent) 70%, var(--ac-text))',\n },\n highlight: {\n background: 'color-mix(in srgb, var(--ac-accent) 16%, transparent)',\n focusBackground: 'color-mix(in srgb, var(--ac-accent) 24%, transparent)',\n color: 'var(--ac-text)',\n focusColor: 'var(--ac-text)',\n },\n text: {\n color: 'var(--ac-text)',\n hoverColor: 'var(--ac-text)',\n mutedColor: 'var(--ac-text-muted)',\n hoverMutedColor: 'var(--ac-text)',\n },\n content: {\n background: 'var(--ac-surface)',\n hoverBackground: 'var(--ac-surface-alt)',\n borderColor: 'var(--ac-border)',\n color: 'var(--ac-text)',\n hoverColor: 'var(--ac-text)',\n },\n overlay: {\n select: {\n background: 'var(--ac-surface)',\n borderColor: 'var(--ac-border)',\n color: 'var(--ac-text)',\n },\n popover: {\n background: 'var(--ac-surface)',\n borderColor: 'var(--ac-border)',\n color: 'var(--ac-text)',\n },\n modal: {\n background: 'var(--ac-surface)',\n borderColor: 'var(--ac-border)',\n color: 'var(--ac-text)',\n },\n },\n formField: {\n background: 'var(--ac-bg)',\n disabledBackground: 'var(--ac-surface-alt)',\n filledBackground: 'var(--ac-surface-alt)',\n filledHoverBackground: 'var(--ac-surface-alt)',\n filledFocusBackground: 'var(--ac-surface-alt)',\n borderColor: 'var(--ac-border)',\n hoverBorderColor: 'var(--ac-accent)',\n focusBorderColor: 'var(--ac-accent)',\n color: 'var(--ac-text)',\n disabledColor: 'var(--ac-text-muted)',\n placeholderColor: 'var(--ac-text-muted)',\n floatLabelColor: 'var(--ac-text-muted)',\n floatLabelFocusColor: 'var(--ac-accent)',\n iconColor: 'var(--ac-text-muted)',\n },\n list: {\n option: {\n focusBackground: 'var(--ac-surface-alt)',\n selectedBackground: 'color-mix(in srgb, var(--ac-accent) 20%, transparent)',\n selectedFocusBackground: 'color-mix(in srgb, var(--ac-accent) 28%, transparent)',\n color: 'var(--ac-text)',\n focusColor: 'var(--ac-text)',\n selectedColor: 'var(--ac-text)',\n selectedFocusColor: 'var(--ac-text)',\n icon: {\n color: 'var(--ac-text-muted)',\n focusColor: 'var(--ac-text)',\n },\n },\n },\n navigation: {\n item: {\n focusBackground: 'var(--ac-surface-alt)',\n activeBackground: 'color-mix(in srgb, var(--ac-accent) 20%, transparent)',\n color: 'var(--ac-text)',\n focusColor: 'var(--ac-text)',\n activeColor: 'var(--ac-text)',\n icon: {\n color: 'var(--ac-text-muted)',\n focusColor: 'var(--ac-text)',\n activeColor: 'var(--ac-accent)',\n },\n },\n },\n};\n\nexport const NucleusPreset = definePreset(Lara, {\n semantic: {\n colorScheme: {\n light: { ...schemeTokens, mask: MASK },\n dark: { ...schemeTokens, mask: MASK },\n },\n },\n components: {\n drawer: { root: { ...PANEL, shadow: SHADOW } },\n popover: { root: { ...PANEL, shadow: SHADOW } },\n menu: { root: { ...PANEL, shadow: SHADOW } },\n listbox: { root: PANEL },\n },\n});\n","import { EnvironmentProviders } from '@angular/core';\nimport { providePrimeNG } from 'primeng/config';\n\nimport { NucleusPreset } from './primeng-preset';\n\nexport const NUCLEUS_DARK_SELECTOR = '.ns-dark';\n\nexport function provideNucleusTheme(): EnvironmentProviders {\n return providePrimeNG({\n theme: {\n preset: NucleusPreset,\n options: { darkModeSelector: NUCLEUS_DARK_SELECTOR },\n },\n });\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\n\nconst ORBIT = { rx: 78, ry: 196 } as const;\n\n@Component({\n selector: 'nucleus-mark',\n changeDetection: ChangeDetectionStrategy.OnPush,\n styles: `\n :host {\n display: block;\n }\n\n svg {\n display: block;\n }\n `,\n template: `\n <svg\n [attr.width]=\"size()\"\n [attr.height]=\"size()\"\n viewBox=\"-230 -230 460 460\"\n aria-hidden=\"true\"\n >\n @for (r of rotations; track $index) {\n <ellipse\n [attr.rx]=\"orbit.rx\"\n [attr.ry]=\"orbit.ry\"\n [attr.transform]=\"'rotate(' + r + ')'\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"18\"\n />\n }\n <circle r=\"42\" [attr.fill]=\"accent()\" />\n </svg>\n `,\n})\nexport class NucleusMark {\n readonly accent = input('#7C6CF5');\n readonly size = input(28);\n\n protected readonly orbit = ORBIT;\n protected readonly rotations = [0, 60, 120];\n}\n","import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nconst W = 1280;\nconst H = 720;\n\nconst STARS = Array.from({ length: 130 }, (_, i) => {\n const a = i * 2.399963;\n const big = i % 11 === 0;\n const sway = Math.sin(a * 1.7);\n const lift = Math.cos(a * 2.3);\n\n return {\n cx: +((Math.sin(a * 7.13) * 0.5 + 0.5) * W).toFixed(2),\n cy: +((Math.cos(a * 3.77) * 0.5 + 0.5) * H).toFixed(2),\n r: +((big ? 2.4 : 0.9) + (i % 4) * 0.5).toFixed(2),\n opacity: ((big ? 0.85 : 0.42) + (i % 5) * 0.09).toFixed(2),\n dx: `${(sway * 26).toFixed(1)}px`,\n dy: `${(lift * 18).toFixed(1)}px`,\n duration: `${(11 + (i % 9) * 1.7).toFixed(1)}s`,\n delay: `-${((i % 13) * 0.85).toFixed(2)}s`,\n };\n});\n\n@Component({\n selector: 'nucleus-starfield',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <svg\n [attr.viewBox]=\"'0 0 ' + W + ' ' + H\"\n preserveAspectRatio=\"xMidYMid slice\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <defs>\n <radialGradient id=\"ns-starfield-glow\" cx=\"50%\" cy=\"0%\" r=\"75%\">\n <stop offset=\"0%\" stop-color=\"var(--ac-accent)\" stop-opacity=\"0.18\" />\n <stop offset=\"70%\" stop-color=\"var(--ac-accent)\" stop-opacity=\"0\" />\n </radialGradient>\n </defs>\n\n <rect width=\"100%\" height=\"100%\" fill=\"url(#ns-starfield-glow)\" />\n\n @for (star of stars; track $index) {\n <circle\n [attr.cx]=\"star.cx\"\n [attr.cy]=\"star.cy\"\n [attr.r]=\"star.r\"\n [style.--o]=\"star.opacity\"\n [style.--dx]=\"star.dx\"\n [style.--dy]=\"star.dy\"\n [style.--dur]=\"star.duration\"\n [style.--delay]=\"star.delay\"\n fill=\"#ffffff\"\n />\n }\n </svg>\n `,\n styles: `\n :host {\n position: fixed;\n inset: 0;\n z-index: -1;\n display: block;\n pointer-events: none;\n background: var(--ac-bg);\n }\n\n svg {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n circle {\n opacity: var(--o);\n animation: ns-drift var(--dur) ease-in-out var(--delay) infinite alternate;\n }\n\n @keyframes ns-drift {\n from {\n transform: translate(0, 0);\n opacity: var(--o);\n }\n to {\n transform: translate(var(--dx), var(--dy));\n opacity: calc(var(--o) * 0.3);\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n circle {\n animation: none;\n }\n }\n `,\n})\nexport class NucleusStarfield {\n protected readonly W = W;\n protected readonly H = H;\n protected readonly stars = STARS;\n}\n","import { NucleusLang } from '../../i18n/nucleus-language';\n\nexport interface ShellCopy {\n readonly navToggle: string;\n readonly appsLauncher: string;\n readonly appsEmpty: string;\n readonly settingsTitle: string;\n readonly settingsTheme: string;\n readonly settingsThemeHint: string;\n readonly themeSystem: string;\n readonly signOut: string;\n readonly accountManage: string;\n readonly accountSwitch: string;\n readonly accessLoading: string;\n readonly accessEmpty: string;\n readonly accountScope: string;\n readonly hintComingSoon: string;\n readonly hintNotDeployed: string;\n readonly switchSite: string;\n readonly contextTitle: string;\n readonly contextHint: string;\n readonly companyLabel: string;\n readonly companyPlaceholder: string;\n readonly siteLabel: string;\n readonly sitePlaceholder: string;\n readonly sitesLoading: string;\n readonly sitesEmpty: string;\n readonly confirmSwitch: string;\n readonly relationOwner: string;\n readonly relationCollaborator: string;\n readonly noContext: string;\n readonly noCompanyTitle: string;\n readonly noCompanyHint: string;\n}\n\nexport const SHELL_COPY: Readonly<Record<NucleusLang, ShellCopy>> = {\n es: {\n navToggle: 'Mostrar u ocultar el menú',\n appsLauncher: 'Aplicaciones',\n appsEmpty: 'No hay otras aplicaciones',\n settingsTitle: 'Ajustes',\n settingsTheme: 'Tema',\n settingsThemeHint: 'Elige cómo se ve la suite en este dispositivo.',\n themeSystem: 'Del sistema',\n signOut: 'Cerrar sesión',\n accountManage: 'Gestionar mi cuenta',\n accountSwitch: 'Cambiar de cuenta',\n accessLoading: 'Cargando accesos...',\n accessEmpty: 'Sin accesos asignados',\n accountScope: 'Mi cuenta',\n hintComingSoon: 'Próximamente',\n hintNotDeployed: 'Sin publicar',\n switchSite: 'Cambiar sede',\n contextTitle: 'Compañía y sede',\n contextHint: 'Elige dónde quieres trabajar. El menú se carga según tu rol en la sede.',\n companyLabel: 'Compañía',\n companyPlaceholder: 'Selecciona una compañía',\n siteLabel: 'Sede',\n sitePlaceholder: 'Selecciona una sede',\n sitesLoading: 'Cargando sedes...',\n sitesEmpty: 'Esta compañía no tiene sedes a tu alcance',\n confirmSwitch: 'Cambiar',\n relationOwner: 'Propietario',\n relationCollaborator: 'Colaborador',\n noContext: 'Sin sede seleccionada',\n noCompanyTitle: 'Te falta una compañía',\n noCompanyHint:\n 'Para trabajar en las aplicaciones necesitas al menos una compañía con una sede, ' +\n 'propia o donde te hayan invitado. Puedes entrar igual, pero el menú saldrá vacío.',\n },\n en: {\n navToggle: 'Show or hide the menu',\n appsLauncher: 'Applications',\n appsEmpty: 'No other applications',\n settingsTitle: 'Settings',\n settingsTheme: 'Theme',\n settingsThemeHint: 'Choose how the suite looks on this device.',\n themeSystem: 'System',\n signOut: 'Sign out',\n accountManage: 'Manage my account',\n accountSwitch: 'Switch account',\n accessLoading: 'Loading access...',\n accessEmpty: 'No access granted',\n accountScope: 'My account',\n hintComingSoon: 'Coming soon',\n hintNotDeployed: 'Not deployed',\n switchSite: 'Switch site',\n contextTitle: 'Company and site',\n contextHint: 'Choose where you want to work. The menu loads from your role at that site.',\n companyLabel: 'Company',\n companyPlaceholder: 'Select a company',\n siteLabel: 'Site',\n sitePlaceholder: 'Select a site',\n sitesLoading: 'Loading sites...',\n sitesEmpty: 'This company has no sites available to you',\n confirmSwitch: 'Switch',\n relationOwner: 'Owner',\n relationCollaborator: 'Collaborator',\n noContext: 'No site selected',\n noCompanyTitle: 'You need a company',\n noCompanyHint:\n 'To work in the applications you need at least one company with a site, your own or ' +\n 'one you have been invited to. You can still open them, but the menu will be empty.',\n },\n};\n","import {\n ChangeDetectionStrategy,\n Component,\n Injector,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n untracked,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { Router } from '@angular/router';\nimport { AvatarModule } from 'primeng/avatar';\nimport { ButtonModule } from 'primeng/button';\nimport { DrawerModule } from 'primeng/drawer';\nimport { ListboxModule } from 'primeng/listbox';\nimport { PopoverModule } from 'primeng/popover';\nimport { SelectModule } from 'primeng/select';\nimport { TagModule } from 'primeng/tag';\nimport { TooltipModule } from 'primeng/tooltip';\n\nimport { CompanyOption, LauncherApp, MenuNode, Site } from '../../api/api.models';\nimport { SessionService } from '../../api/session.service';\nimport { NucleusAuth } from '../../auth/nucleus-auth';\nimport { NucleusSessionAuth } from '../../auth/session-auth.service';\nimport { NUCLEUS_CONFIG } from '../../config/nucleus-config';\nimport { NucleusLang, NucleusLanguage } from '../../i18n/nucleus-language';\nimport { THEMES, THEME_LABELS, ThemePreference } from '../../theme/theme';\nimport { ThemeService } from '../../theme/theme.service';\nimport { NucleusMark } from '../nucleus-mark/nucleus-mark';\nimport { NucleusStarfield } from '../starfield/starfield';\nimport { SHELL_COPY } from './shell.copy';\n\nexport interface ShellNavItem {\n readonly id: string;\n readonly icon: string;\n readonly label: string;\n}\n\ninterface ThemeOption {\n readonly value: ThemePreference;\n readonly label: string;\n readonly swatch: string | null;\n}\n\ninterface CompanyChoice extends CompanyOption {\n readonly tag: string;\n}\n\ninterface ShellIdentity {\n readonly name: string;\n readonly email: string;\n readonly photoUrl: string | null;\n}\n\n@Component({\n selector: 'nucleus-shell',\n imports: [\n AvatarModule,\n ButtonModule,\n DrawerModule,\n ListboxModule,\n PopoverModule,\n SelectModule,\n TagModule,\n TooltipModule,\n FormsModule,\n NucleusMark,\n NucleusStarfield,\n ],\n templateUrl: './nucleus-shell.html',\n styleUrl: './nucleus-shell.css',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class NucleusShell {\n private readonly session = inject(SessionService);\n private readonly sessionAuth = inject(NucleusSessionAuth);\n private readonly themes = inject(ThemeService);\n private readonly language = inject(NucleusLanguage);\n private readonly config = inject(NUCLEUS_CONFIG);\n private readonly injector = inject(Injector);\n private readonly router = inject(Router);\n\n readonly brand = input('SUITE');\n readonly heading = input('');\n readonly lead = input('');\n readonly navItems = input<readonly ShellNavItem[]>([]);\n readonly activeNavId = input<string | null>(null);\n readonly selectedMenuId = input<string | null>(null);\n\n readonly navSelect = output<string>();\n readonly menuSelect = output<MenuNode>();\n\n protected readonly lang = this.language.lang;\n protected readonly copy = computed(() => SHELL_COPY[this.lang()]);\n\n protected readonly starfield = this.themes.starfield;\n protected readonly themePreference = this.themes.preference;\n\n protected readonly menu = this.session.menu;\n protected readonly menuLoading = this.session.loading;\n protected readonly menuError = this.session.error;\n protected readonly launcherApps = this.session.apps;\n protected readonly switching = this.session.switching;\n\n protected readonly sidebarOpen = signal(true);\n protected readonly settingsOpen = signal(false);\n protected readonly contextOpen = signal(false);\n\n protected readonly companyChoice = signal<string | null>(null);\n protected readonly siteChoice = signal<string | null>(null);\n protected readonly siteOptions = signal<Site[]>([]);\n protected readonly sitesLoading = signal(false);\n\n private readonly auth = this.injector.get(NucleusAuth, null);\n\n protected readonly identity = computed<ShellIdentity | null>(() => {\n const me = this.session.me();\n\n if (me) {\n return {\n name: me.displayName ?? me.userId,\n email: me.userId,\n photoUrl: me.photoUrl,\n };\n }\n\n const user = this.auth?.user() ?? null;\n\n if (!user) return null;\n\n return {\n name: user.displayName ?? user.email ?? user.providerUserId,\n email: user.email ?? user.providerUserId,\n photoUrl: user.photoUrl,\n };\n });\n\n protected readonly initials = computed(() => initialsOf(this.identity()?.name ?? ''));\n\n protected readonly canSwitchAccount = computed(() => this.auth?.switchAccount !== undefined);\n\n protected readonly hasCompany = computed(() => this.session.companies().length > 0);\n\n protected readonly companyChoices = computed<CompanyChoice[]>(() => {\n const t = this.copy();\n\n return this.session.companyOptions().map((company) => ({\n ...company,\n tag: company.relation === 'owner' ? t.relationOwner : t.relationCollaborator,\n }));\n });\n\n protected readonly contextCaption = computed(() => {\n const role = this.session.roleName();\n const site = this.session.siteName();\n const company = this.session.companyName();\n\n if (role && site) return company ? `${company} · ${site}` : site;\n if (this.session.scope() === 'account') return this.copy().accountScope;\n\n return this.copy().noContext;\n });\n\n protected readonly roleName = this.session.roleName;\n\n protected readonly canConfirm = computed(\n () => this.companyChoice() !== null && this.siteChoice() !== null && !this.switching(),\n );\n\n protected readonly themeOptions = computed<ThemeOption[]>(() => [\n ...THEMES.map((theme) => ({\n value: theme.id as ThemePreference,\n label: THEME_LABELS[theme.id],\n swatch: theme.swatch,\n })),\n { value: 'system', label: this.copy().themeSystem, swatch: null },\n ]);\n\n private readonly loadSession = effect(() => {\n const language = this.lang();\n const user = this.auth?.user() ?? null;\n\n if (this.auth && !user) return;\n\n untracked(() => void this.session.load(language));\n });\n\n protected setLang(lang: NucleusLang): void {\n this.language.setLang(lang);\n }\n\n protected toggleSidebar(): void {\n this.sidebarOpen.update((open) => !open);\n }\n\n protected selectTheme(preference: ThemePreference | null): void {\n if (preference) this.themes.setPreference(preference);\n }\n\n protected selectNav(id: string): void {\n this.navSelect.emit(id);\n }\n\n protected selectMenu(node: MenuNode): void {\n this.menuSelect.emit(node);\n\n if (node.route) void this.router.navigateByUrl(node.route);\n }\n\n protected isSelected(node: MenuNode): boolean {\n return this.selectedMenuId() === node.id;\n }\n\n protected async openContext(): Promise<void> {\n const companyId = this.session.companyId() ?? this.companyChoices()[0]?.id ?? null;\n\n this.companyChoice.set(companyId);\n this.siteChoice.set(this.session.siteId());\n this.contextOpen.set(true);\n\n if (companyId) await this.loadSites(companyId);\n }\n\n protected async onCompanyChange(companyId: string | null): Promise<void> {\n this.companyChoice.set(companyId);\n this.siteChoice.set(null);\n this.siteOptions.set([]);\n\n if (companyId) await this.loadSites(companyId);\n }\n\n protected async confirmSwitch(): Promise<void> {\n const companyId = this.companyChoice();\n const siteId = this.siteChoice();\n\n if (!companyId || !siteId) return;\n\n await this.session.switchContext(companyId, siteId);\n\n this.contextOpen.set(false);\n }\n\n protected canOpen(app: LauncherApp): boolean {\n return app.status === 1 && !!app.url;\n }\n\n protected launch(app: LauncherApp): void {\n if (!this.canOpen(app)) return;\n\n window.location.href = app.url as string;\n }\n\n protected appInitials(app: LauncherApp): string {\n return initialsOf(app.name);\n }\n\n protected launchHint(app: LauncherApp): string {\n const t = this.copy();\n\n if (app.status !== 1) return t.hintComingSoon;\n if (!app.url) return t.hintNotDeployed;\n\n return '';\n }\n\n protected async switchAccount(): Promise<void> {\n await this.auth?.switchAccount?.();\n }\n\n protected async signOut(): Promise<void> {\n await this.sessionAuth.clear();\n await this.auth?.signOut?.();\n\n const landing = this.config.landingUrl;\n\n if (landing) window.location.href = landing;\n }\n\n private async loadSites(companyId: string): Promise<void> {\n this.sitesLoading.set(true);\n\n try {\n const sites = await this.session.accessibleSites(companyId);\n\n this.siteOptions.set(sites);\n\n if (!sites.some((site) => site.id === this.siteChoice())) {\n this.siteChoice.set(sites[0]?.id ?? null);\n }\n } catch (error) {\n this.siteOptions.set([]);\n console.error('[shell] no se pudieron cargar las sedes', error);\n } finally {\n this.sitesLoading.set(false);\n }\n }\n}\n\nfunction initialsOf(source: string): string {\n const parts = source.trim().split(/\\s+/).filter(Boolean);\n\n if (!parts.length) return '?';\n if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();\n\n return (parts[0][0] + parts[1][0]).toUpperCase();\n}\n","@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 @if (heading()) {\n <h1>{{ heading() }}</h1>\n }\n @if (lead()) {\n <p class=\"lead\">{{ lead() }}</p>\n }\n\n <ng-content />\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 * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["STORAGE_KEY"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nucleus-suite-pe/core",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Capa compartida de la suite Nucleus: sesión única, permisos, tema y marco de aplicación para Angular.",
5
5
  "keywords": [
6
6
  "angular",
@@ -25,7 +25,8 @@
25
25
  "primeng": "^21.0.0",
26
26
  "@primeuix/themes": "^3.0.0",
27
27
  "@angular/router": "^21.2.0",
28
- "@angular/forms": "^21.2.0"
28
+ "@angular/forms": "^21.2.0",
29
+ "primeicons": "^8.0.0"
29
30
  },
30
31
  "dependencies": {
31
32
  "tslib": "^2.3.0"
@@ -1,9 +1,9 @@
1
1
  import * as _angular_core from '@angular/core';
2
2
  import { InjectionToken, EnvironmentProviders, Signal } from '@angular/core';
3
3
  import { HttpContextToken, HttpInterceptorFn } from '@angular/common/http';
4
- import * as _nucleus_suite_pe_core from '@nucleus-suite-pe/core';
5
4
  import * as _primeuix_themes from '@primeuix/themes';
6
5
  import * as _primeuix_themes_types_base from '@primeuix/themes/types/base';
6
+ import * as _nucleus_suite_pe_core from '@nucleus-suite-pe/core';
7
7
 
8
8
  interface NucleusConfig {
9
9
  readonly appId: string;
@@ -125,8 +125,25 @@ interface UserProfile {
125
125
  readonly language: string | null;
126
126
  readonly timeZone: string | null;
127
127
  readonly themePreference: string | null;
128
+ readonly lastCompanyId: string | null;
129
+ readonly lastSiteId: string | null;
128
130
  readonly completedAtUtc: string | null;
129
131
  }
132
+ interface Site {
133
+ readonly id: string;
134
+ readonly companyId: string;
135
+ readonly name: string;
136
+ readonly address: string | null;
137
+ readonly city: string | null;
138
+ readonly phone: string | null;
139
+ readonly isMain: boolean;
140
+ }
141
+ type CompanyRelation = 'owner' | 'collaborator';
142
+ interface CompanyOption {
143
+ readonly id: string;
144
+ readonly name: string;
145
+ readonly relation: CompanyRelation;
146
+ }
130
147
  interface Subscription {
131
148
  readonly planName: string;
132
149
  readonly status: number;
@@ -159,9 +176,7 @@ interface AppSummary {
159
176
  readonly status: number;
160
177
  readonly sortOrder: number;
161
178
  }
162
- interface LauncherApp extends AppSummary {
163
- readonly hasAccess: boolean;
164
- }
179
+ type LauncherApp = AppSummary;
165
180
 
166
181
  declare class SessionService {
167
182
  private readonly http;
@@ -174,22 +189,34 @@ declare class SessionService {
174
189
  private readonly _access;
175
190
  private readonly _scope;
176
191
  private readonly _apps;
192
+ private readonly _siteId;
177
193
  private readonly _loading;
194
+ private readonly _switching;
178
195
  private readonly _error;
179
196
  private inFlight;
180
197
  private loadedKey;
198
+ private language;
181
199
  readonly me: _angular_core.Signal<MeResponse | null>;
182
200
  readonly menu: _angular_core.Signal<readonly MenuNode[]>;
183
201
  readonly access: _angular_core.Signal<SiteAccess | null>;
184
202
  readonly scope: _angular_core.Signal<AccessScope | null>;
185
- readonly apps: _angular_core.Signal<readonly LauncherApp[]>;
203
+ readonly apps: _angular_core.Signal<readonly AppSummary[]>;
204
+ readonly siteId: _angular_core.Signal<string | null>;
186
205
  readonly loading: _angular_core.Signal<boolean>;
206
+ readonly switching: _angular_core.Signal<boolean>;
187
207
  readonly error: _angular_core.Signal<string | null>;
188
208
  readonly roleName: _angular_core.Signal<string | null>;
189
209
  readonly siteName: _angular_core.Signal<string | null>;
190
- readonly companies: _angular_core.Signal<_nucleus_suite_pe_core.CompanySummary[]>;
210
+ readonly companies: _angular_core.Signal<readonly CompanySummary[]>;
211
+ readonly companyOptions: _angular_core.Signal<readonly CompanyOption[]>;
212
+ readonly companyId: _angular_core.Signal<string | null>;
213
+ readonly companyName: _angular_core.Signal<string | null>;
191
214
  load(language: string, force?: boolean): Promise<void>;
192
215
  reload(language: string): Promise<void>;
216
+ sites(companyId: string): Promise<Site[]>;
217
+ accessibleSites(companyId: string): Promise<Site[]>;
218
+ switchContext(companyId: string, siteId: string): Promise<void>;
219
+ private resolveMenu;
193
220
  private buildLauncher;
194
221
  private siteMenu;
195
222
  private accountMenu;
@@ -294,9 +321,23 @@ interface ShellCopy {
294
321
  readonly accessLoading: string;
295
322
  readonly accessEmpty: string;
296
323
  readonly accountScope: string;
297
- readonly hintNoAccess: string;
298
324
  readonly hintComingSoon: string;
299
325
  readonly hintNotDeployed: string;
326
+ readonly switchSite: string;
327
+ readonly contextTitle: string;
328
+ readonly contextHint: string;
329
+ readonly companyLabel: string;
330
+ readonly companyPlaceholder: string;
331
+ readonly siteLabel: string;
332
+ readonly sitePlaceholder: string;
333
+ readonly sitesLoading: string;
334
+ readonly sitesEmpty: string;
335
+ readonly confirmSwitch: string;
336
+ readonly relationOwner: string;
337
+ readonly relationCollaborator: string;
338
+ readonly noContext: string;
339
+ readonly noCompanyTitle: string;
340
+ readonly noCompanyHint: string;
300
341
  }
301
342
  declare const SHELL_COPY: Readonly<Record<NucleusLang, ShellCopy>>;
302
343
 
@@ -310,6 +351,9 @@ interface ThemeOption {
310
351
  readonly label: string;
311
352
  readonly swatch: string | null;
312
353
  }
354
+ interface CompanyChoice extends CompanyOption {
355
+ readonly tag: string;
356
+ }
313
357
  interface ShellIdentity {
314
358
  readonly name: string;
315
359
  readonly email: string;
@@ -338,14 +382,24 @@ declare class NucleusShell {
338
382
  protected readonly menu: _angular_core.Signal<readonly MenuNode[]>;
339
383
  protected readonly menuLoading: _angular_core.Signal<boolean>;
340
384
  protected readonly menuError: _angular_core.Signal<string | null>;
341
- protected readonly launcherApps: _angular_core.Signal<readonly LauncherApp[]>;
385
+ protected readonly launcherApps: _angular_core.Signal<readonly _nucleus_suite_pe_core.AppSummary[]>;
386
+ protected readonly switching: _angular_core.Signal<boolean>;
342
387
  protected readonly sidebarOpen: _angular_core.WritableSignal<boolean>;
343
388
  protected readonly settingsOpen: _angular_core.WritableSignal<boolean>;
389
+ protected readonly contextOpen: _angular_core.WritableSignal<boolean>;
390
+ protected readonly companyChoice: _angular_core.WritableSignal<string | null>;
391
+ protected readonly siteChoice: _angular_core.WritableSignal<string | null>;
392
+ protected readonly siteOptions: _angular_core.WritableSignal<Site[]>;
393
+ protected readonly sitesLoading: _angular_core.WritableSignal<boolean>;
344
394
  private readonly auth;
345
395
  protected readonly identity: _angular_core.Signal<ShellIdentity | null>;
346
396
  protected readonly initials: _angular_core.Signal<string>;
347
397
  protected readonly canSwitchAccount: _angular_core.Signal<boolean>;
348
- protected readonly accessCaption: _angular_core.Signal<string>;
398
+ protected readonly hasCompany: _angular_core.Signal<boolean>;
399
+ protected readonly companyChoices: _angular_core.Signal<CompanyChoice[]>;
400
+ protected readonly contextCaption: _angular_core.Signal<string>;
401
+ protected readonly roleName: _angular_core.Signal<string | null>;
402
+ protected readonly canConfirm: _angular_core.Signal<boolean>;
349
403
  protected readonly themeOptions: _angular_core.Signal<ThemeOption[]>;
350
404
  private readonly loadSession;
351
405
  protected setLang(lang: NucleusLang): void;
@@ -354,15 +408,19 @@ declare class NucleusShell {
354
408
  protected selectNav(id: string): void;
355
409
  protected selectMenu(node: MenuNode): void;
356
410
  protected isSelected(node: MenuNode): boolean;
411
+ protected openContext(): Promise<void>;
412
+ protected onCompanyChange(companyId: string | null): Promise<void>;
413
+ protected confirmSwitch(): Promise<void>;
357
414
  protected canOpen(app: LauncherApp): boolean;
358
415
  protected launch(app: LauncherApp): void;
359
416
  protected appInitials(app: LauncherApp): string;
360
417
  protected launchHint(app: LauncherApp): string;
361
418
  protected switchAccount(): Promise<void>;
362
419
  protected signOut(): Promise<void>;
420
+ private loadSites;
363
421
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<NucleusShell, never>;
364
422
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<NucleusShell, "nucleus-shell", never, { "brand": { "alias": "brand"; "required": false; "isSignal": true; }; "heading": { "alias": "heading"; "required": false; "isSignal": true; }; "lead": { "alias": "lead"; "required": false; "isSignal": true; }; "navItems": { "alias": "navItems"; "required": false; "isSignal": true; }; "activeNavId": { "alias": "activeNavId"; "required": false; "isSignal": true; }; "selectedMenuId": { "alias": "selectedMenuId"; "required": false; "isSignal": true; }; }, { "navSelect": "navSelect"; "menuSelect": "menuSelect"; }, never, ["*"], true, never>;
365
423
  }
366
424
 
367
425
  export { DEFAULT_THEME, NUCLEUS_CONFIG, NUCLEUS_DARK_SELECTOR, NUCLEUS_FORCE_BEARER, NUCLEUS_LANGS, NUCLEUS_SKIP_AUTH, NucleusAuth, NucleusLanguage, NucleusMark, NucleusPreset, NucleusSessionAuth, NucleusShell, NucleusStarfield, SHELL_COPY, SessionService, THEMES, THEME_LABELS, ThemeService, UserSyncService, isNucleusConfigured, isThemePreference, loadNucleusConfig, nucleusAuthInterceptor, ownsUrl, provideNucleus, provideNucleusTheme, themeById };
368
- export type { AccessScope, AppSummary, AppUser, AuthSyncRequest, CompanySummary, LauncherApp, MeResponse, MenuNode, NucleusConfig, NucleusIdentity, NucleusLang, SessionTicket, ShellCopy, ShellNavItem, SiteAccess, Subscription, Theme, ThemeId, ThemePreference, ThemeTokens, UserProfile };
426
+ export type { AccessScope, AppSummary, AppUser, AuthSyncRequest, CompanyOption, CompanyRelation, CompanySummary, LauncherApp, MeResponse, MenuNode, NucleusConfig, NucleusIdentity, NucleusLang, SessionTicket, ShellCopy, ShellNavItem, Site, SiteAccess, Subscription, Theme, ThemeId, ThemePreference, ThemeTokens, UserProfile };