oip-common 0.1.6 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, inject, InjectionToken, signal, computed, effect, ChangeDetectorRef, Component, Input, PLATFORM_ID, HostBinding, EventEmitter, Output, ViewChild, Renderer2, SecurityContext, ChangeDetectionStrategy, Pipe } from '@angular/core';
2
+ import { Injectable, inject, InjectionToken, signal, computed, effect, ChangeDetectorRef, Component, Input, PLATFORM_ID, HostBinding, EventEmitter, Output, ViewChild, Renderer2, SecurityContext, ChangeDetectionStrategy, makeEnvironmentProviders, Pipe } from '@angular/core';
3
3
  import * as i2$6 from 'primeng/api';
4
4
  import { MessageService, ConfirmationService, PrimeIcons, SharedModule } from 'primeng/api';
5
5
  import { HttpErrorResponse, HttpClient as HttpClient$1, HttpHeaders } from '@angular/common/http';
@@ -934,11 +934,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
934
934
  type: Input
935
935
  }] } });
936
936
 
937
- const presets = {
938
- Aura,
939
- Lara,
940
- Nora
941
- };
937
+ const APP_THEME_PRESETS = new InjectionToken('APP_THEME_PRESETS', {
938
+ factory: () => []
939
+ });
940
+ const APP_THEME_PRESETS_MERGE_MODE = new InjectionToken('APP_THEME_PRESETS_MERGE_MODE', {
941
+ factory: () => 'mergeWithDefaults'
942
+ });
943
+
944
+ const DEFAULT_THEME_PRESETS = [
945
+ { id: 'Aura', label: 'Aura', preset: Aura },
946
+ { id: 'Lara', label: 'Lara', preset: Lara },
947
+ { id: 'Nora', label: 'Nora', preset: Nora }
948
+ ];
949
+ const PRIMARY_COLORS = [
950
+ 'emerald',
951
+ 'green',
952
+ 'lime',
953
+ 'orange',
954
+ 'amber',
955
+ 'yellow',
956
+ 'teal',
957
+ 'cyan',
958
+ 'sky',
959
+ 'blue',
960
+ 'indigo',
961
+ 'violet',
962
+ 'purple',
963
+ 'fuchsia',
964
+ 'pink',
965
+ 'rose'
966
+ ];
942
967
  class AppConfiguratorComponent {
943
968
  constructor() {
944
969
  this.router = inject(Router);
@@ -946,7 +971,14 @@ class AppConfiguratorComponent {
946
971
  this.layoutService = inject(LayoutService);
947
972
  this.platformId = inject(PLATFORM_ID);
948
973
  this.primeng = inject(PrimeNG);
949
- this.presets = Object.keys(presets);
974
+ this.injectedThemePresets = inject(APP_THEME_PRESETS);
975
+ this.themePresetMergeMode = inject(APP_THEME_PRESETS_MERGE_MODE);
976
+ this.themePresets = this.getThemePresets();
977
+ this.themePresetsMap = new Map(this.themePresets.map((theme) => [theme.id, theme]));
978
+ this.defaultThemePreset = this.themePresets[0] ?? DEFAULT_THEME_PRESETS[0];
979
+ this.fallbackPrimaryColors = (DEFAULT_THEME_PRESETS[0].preset
980
+ .primitive ?? {});
981
+ this.presets = this.themePresets.map((theme) => ({ label: theme.label ?? theme.id, value: theme.id }));
950
982
  this.showMenuModeButton = signal(!this.router.url.includes('auth'), ...(ngDevMode ? [{ debugName: "showMenuModeButton" }] : []));
951
983
  this.menuModeOptions = [
952
984
  { label: 'Static', value: 'static' },
@@ -1097,43 +1129,23 @@ class AppConfiguratorComponent {
1097
1129
  this.selectedPreset = computed(() => this.layoutService.layoutConfig().preset, ...(ngDevMode ? [{ debugName: "selectedPreset" }] : []));
1098
1130
  this.menuMode = computed(() => this.layoutService.layoutConfig().menuMode, ...(ngDevMode ? [{ debugName: "menuMode" }] : []));
1099
1131
  this.primaryColors = computed(() => {
1100
- const presetPalette = presets[this.layoutService.layoutConfig().preset].primitive;
1101
- const colors = [
1102
- 'emerald',
1103
- 'green',
1104
- 'lime',
1105
- 'orange',
1106
- 'amber',
1107
- 'yellow',
1108
- 'teal',
1109
- 'cyan',
1110
- 'sky',
1111
- 'blue',
1112
- 'indigo',
1113
- 'violet',
1114
- 'purple',
1115
- 'fuchsia',
1116
- 'pink',
1117
- 'rose'
1118
- ];
1119
- const palettes = [{ name: 'noir', palette: {} }];
1120
- colors.forEach((color) => {
1121
- palettes.push({
1122
- name: color,
1123
- palette: presetPalette?.[color]
1124
- });
1125
- });
1126
- return palettes;
1132
+ const activeThemePreset = this.getThemeById(this.layoutService.layoutConfig().preset);
1133
+ return this.getPrimaryColorOptions(activeThemePreset);
1127
1134
  }, ...(ngDevMode ? [{ debugName: "primaryColors" }] : []));
1135
+ this.surfaceColors = computed(() => {
1136
+ const activeThemePreset = this.getThemeById(this.layoutService.layoutConfig().preset);
1137
+ return this.getSurfaceColorOptions(activeThemePreset);
1138
+ }, ...(ngDevMode ? [{ debugName: "surfaceColors" }] : []));
1128
1139
  }
1129
1140
  ngOnInit() {
1130
1141
  if (isPlatformBrowser(this.platformId)) {
1131
- this.onPresetChange(this.layoutService.layoutConfig().preset);
1142
+ const presetId = this.ensureValidThemeId(this.layoutService.layoutConfig().preset);
1143
+ this.onPresetChange(presetId);
1132
1144
  }
1133
1145
  }
1134
1146
  getPresetExt() {
1135
1147
  const color = this.primaryColors().find((c) => c.name === this.selectedPrimaryColor()) || {};
1136
- const preset = this.layoutService.layoutConfig().preset;
1148
+ const preset = this.getThemeById(this.layoutService.layoutConfig().preset).id;
1137
1149
  if (color.name === 'noir') {
1138
1150
  return {
1139
1151
  semantic: {
@@ -1258,6 +1270,59 @@ class AppConfiguratorComponent {
1258
1270
  };
1259
1271
  }
1260
1272
  }
1273
+ getThemePresets() {
1274
+ const source = this.themePresetMergeMode === 'replaceDefaults' ? [] : [...DEFAULT_THEME_PRESETS];
1275
+ const result = [...source];
1276
+ for (const theme of this.injectedThemePresets ?? []) {
1277
+ if (!theme?.id || !theme?.preset) {
1278
+ continue;
1279
+ }
1280
+ const index = result.findIndex((item) => item.id === theme.id);
1281
+ if (index >= 0) {
1282
+ result[index] = theme;
1283
+ }
1284
+ else {
1285
+ result.push(theme);
1286
+ }
1287
+ }
1288
+ return result;
1289
+ }
1290
+ getThemeById(themeId) {
1291
+ return this.themePresetsMap.get(themeId ?? '') ?? this.defaultThemePreset;
1292
+ }
1293
+ getPrimaryColorOptions(activeThemePreset) {
1294
+ if (activeThemePreset.primaryColors) {
1295
+ return Object.entries(activeThemePreset.primaryColors)
1296
+ .filter((entry) => Boolean(entry[1]))
1297
+ .map(([name, palette]) => ({ name, palette }));
1298
+ }
1299
+ const presetPalette = (activeThemePreset.preset.primitive ?? {});
1300
+ const palettes = [{ name: 'noir', palette: {} }];
1301
+ PRIMARY_COLORS.forEach((color) => {
1302
+ palettes.push({
1303
+ name: color,
1304
+ palette: presetPalette[color] ?? this.fallbackPrimaryColors[color]
1305
+ });
1306
+ });
1307
+ return palettes;
1308
+ }
1309
+ getSurfaceColorOptions(activeThemePreset) {
1310
+ if (activeThemePreset.surfaceColors) {
1311
+ return Object.entries(activeThemePreset.surfaceColors)
1312
+ .filter((entry) => Boolean(entry[1]))
1313
+ .map(([name, palette]) => ({ name, palette }));
1314
+ }
1315
+ return this.surfaces;
1316
+ }
1317
+ ensureValidThemeId(themeId) {
1318
+ if (themeId && this.themePresetsMap.has(themeId)) {
1319
+ return themeId;
1320
+ }
1321
+ if (themeId && isPlatformBrowser(this.platformId)) {
1322
+ console.warn(`[AppConfigurator] Unknown theme preset "${themeId}", fallback to "${this.defaultThemePreset.id}".`);
1323
+ }
1324
+ return this.defaultThemePreset.id;
1325
+ }
1261
1326
  updateColors(event, type, color) {
1262
1327
  if (type === 'primary') {
1263
1328
  this.layoutService.layoutConfig.update((state) => ({
@@ -1283,12 +1348,20 @@ class AppConfiguratorComponent {
1283
1348
  }
1284
1349
  }
1285
1350
  onPresetChange(event) {
1351
+ const nextThemeId = this.ensureValidThemeId(event);
1352
+ const nextTheme = this.getThemeById(nextThemeId);
1353
+ const primaryColors = this.getPrimaryColorOptions(nextTheme);
1354
+ const surfaceColors = this.getSurfaceColorOptions(nextTheme);
1286
1355
  this.layoutService.layoutConfig.update((state) => ({
1287
1356
  ...state,
1288
- preset: event
1357
+ preset: nextThemeId,
1358
+ primary: primaryColors.some((color) => color.name === state.primary) ? state.primary : (primaryColors[0]?.name ?? state.primary),
1359
+ surface: nextTheme.surfaceColors && !surfaceColors.some((color) => color.name === state.surface)
1360
+ ? (surfaceColors[0]?.name ?? state.surface)
1361
+ : state.surface
1289
1362
  }));
1290
- const preset = presets[event];
1291
- const surfacePalette = this.surfaces.find((s) => s.name === this.selectedSurfaceColor())?.palette;
1363
+ const preset = nextTheme.preset;
1364
+ const surfacePalette = this.surfaceColors().find((s) => s.name === this.selectedSurfaceColor())?.palette;
1292
1365
  $t().preset(preset).preset(this.getPresetExt()).surfacePalette(surfacePalette).use({ useDefaultOptions: true });
1293
1366
  }
1294
1367
  onMenuModeChange(event) {
@@ -1298,73 +1371,75 @@ class AppConfiguratorComponent {
1298
1371
  }));
1299
1372
  }
1300
1373
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppConfiguratorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1301
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AppConfiguratorComponent, isStandalone: true, selector: "app-configurator", host: { classAttribute: "hidden absolute top-[3.25rem] right-0 w-72 p-4 bg-surface-0 dark:bg-surface-900 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]" }, ngImport: i0, template: `
1302
- <div class="flex flex-col gap-4">
1303
- <div>
1304
- <span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.primary' | translate }}</span>
1305
- <div class="pt-2 flex gap-2 flex-wrap justify-start">
1306
- @for (primaryColor of primaryColors(); track primaryColor.name) {
1307
- <button
1308
- class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
1309
- id="oip-app-configurator-primary-color-{{ primaryColor.name }}"
1310
- type="button"
1311
- [ngClass]="{
1312
- 'outline-primary': primaryColor.name === selectedPrimaryColor()
1313
- }"
1314
- [style]="{
1315
- 'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
1316
- }"
1317
- [title]="primaryColor.name"
1318
- (click)="updateColors($event, 'primary', primaryColor)"></button>
1319
- }
1320
- </div>
1321
- </div>
1322
- <div>
1323
- <span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.surface' | translate }}</span>
1324
- <div class="pt-2 flex gap-2 flex-wrap justify-start">
1325
- @for (surface of surfaces; track surface.name) {
1326
- <button
1327
- class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
1328
- id="oip-app-configurator-surface-color-{{ surface.name }}"
1329
- type="button"
1330
- [ngClass]="{
1331
- 'outline-primary': selectedSurfaceColor()
1332
- ? selectedSurfaceColor() === surface.name
1333
- : layoutService.layoutConfig().darkTheme
1334
- ? surface.name === 'zinc'
1335
- : surface.name === 'slate'
1336
- }"
1337
- [style]="{
1338
- 'background-color': surface?.name === 'noir' ? 'var(--text-color)' : surface?.palette?.['500']
1339
- }"
1340
- [title]="surface.name"
1341
- (click)="updateColors($event, 'surface', surface)"></button>
1342
- }
1343
- </div>
1344
- </div>
1345
- <div class="flex flex-col gap-2">
1346
- <span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.presets' | translate }}</span>
1347
- <p-selectButton
1348
- id="oip-app-configurator-preset-select-button"
1349
- size="small"
1350
- [allowEmpty]="false"
1351
- [ngModel]="selectedPreset()"
1352
- [options]="presets"
1353
- (ngModelChange)="onPresetChange($event)" />
1354
- </div>
1355
- @if (showMenuModeButton()) {
1356
- <div class="flex flex-col gap-2">
1357
- <span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.menuMode' | translate }}</span>
1358
- <p-selectButton
1359
- id="oip-app-configurator-menu-mode-select-button"
1360
- size="small"
1361
- [allowEmpty]="false"
1362
- [ngModel]="menuMode()"
1363
- [options]="menuModeOptions"
1364
- (ngModelChange)="onMenuModeChange($event)" />
1365
- </div>
1366
- }
1367
- </div>
1374
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AppConfiguratorComponent, isStandalone: true, selector: "app-configurator", host: { classAttribute: "hidden absolute top-[3.25rem] right-0 w-72 p-4 bg-surface-0 dark:bg-surface-900 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]" }, ngImport: i0, template: `
1375
+ <div class="flex flex-col gap-4">
1376
+ <div>
1377
+ <span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.primary' | translate }}</span>
1378
+ <div class="pt-2 flex gap-2 flex-wrap justify-start">
1379
+ @for (primaryColor of primaryColors(); track primaryColor.name) {
1380
+ <button
1381
+ class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
1382
+ id="oip-app-configurator-primary-color-{{ primaryColor.name }}"
1383
+ type="button"
1384
+ [ngClass]="{
1385
+ 'outline-primary': primaryColor.name === selectedPrimaryColor()
1386
+ }"
1387
+ [style]="{
1388
+ 'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
1389
+ }"
1390
+ [title]="primaryColor.name"
1391
+ (click)="updateColors($event, 'primary', primaryColor)"></button>
1392
+ }
1393
+ </div>
1394
+ </div>
1395
+ <div>
1396
+ <span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.surface' | translate }}</span>
1397
+ <div class="pt-2 flex gap-2 flex-wrap justify-start">
1398
+ @for (surface of surfaceColors(); track surface.name) {
1399
+ <button
1400
+ class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
1401
+ id="oip-app-configurator-surface-color-{{ surface.name }}"
1402
+ type="button"
1403
+ [ngClass]="{
1404
+ 'outline-primary': selectedSurfaceColor()
1405
+ ? selectedSurfaceColor() === surface.name
1406
+ : layoutService.layoutConfig().darkTheme
1407
+ ? surface.name === 'zinc'
1408
+ : surface.name === 'slate'
1409
+ }"
1410
+ [style]="{
1411
+ 'background-color': surface?.name === 'noir' ? 'var(--text-color)' : surface?.palette?.['500']
1412
+ }"
1413
+ [title]="surface.name"
1414
+ (click)="updateColors($event, 'surface', surface)"></button>
1415
+ }
1416
+ </div>
1417
+ </div>
1418
+ <div class="flex flex-col gap-2">
1419
+ <span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.presets' | translate }}</span>
1420
+ <p-selectButton
1421
+ id="oip-app-configurator-preset-select-button"
1422
+ size="small"
1423
+ [allowEmpty]="false"
1424
+ [ngModel]="selectedPreset()"
1425
+ [options]="presets"
1426
+ optionLabel="label"
1427
+ optionValue="value"
1428
+ (ngModelChange)="onPresetChange($event)" />
1429
+ </div>
1430
+ @if (showMenuModeButton()) {
1431
+ <div class="flex flex-col gap-2">
1432
+ <span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.menuMode' | translate }}</span>
1433
+ <p-selectButton
1434
+ id="oip-app-configurator-menu-mode-select-button"
1435
+ size="small"
1436
+ [allowEmpty]="false"
1437
+ [ngModel]="menuMode()"
1438
+ [options]="menuModeOptions"
1439
+ (ngModelChange)="onMenuModeChange($event)" />
1440
+ </div>
1441
+ }
1442
+ </div>
1368
1443
  `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: SelectButtonModule }, { kind: "component", type: i3.SelectButton, selector: "p-selectButton, p-selectbutton, p-select-button", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "styleClass", "ariaLabelledBy", "dataKey", "autofocus", "size", "fluid"], outputs: ["onOptionClick", "onChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
1369
1444
  }
1370
1445
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppConfiguratorComponent, decorators: [{
@@ -1373,73 +1448,75 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
1373
1448
  selector: 'app-configurator',
1374
1449
  standalone: true,
1375
1450
  imports: [CommonModule, FormsModule, SelectButtonModule, TranslatePipe],
1376
- template: `
1377
- <div class="flex flex-col gap-4">
1378
- <div>
1379
- <span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.primary' | translate }}</span>
1380
- <div class="pt-2 flex gap-2 flex-wrap justify-start">
1381
- @for (primaryColor of primaryColors(); track primaryColor.name) {
1382
- <button
1383
- class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
1384
- id="oip-app-configurator-primary-color-{{ primaryColor.name }}"
1385
- type="button"
1386
- [ngClass]="{
1387
- 'outline-primary': primaryColor.name === selectedPrimaryColor()
1388
- }"
1389
- [style]="{
1390
- 'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
1391
- }"
1392
- [title]="primaryColor.name"
1393
- (click)="updateColors($event, 'primary', primaryColor)"></button>
1394
- }
1395
- </div>
1396
- </div>
1397
- <div>
1398
- <span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.surface' | translate }}</span>
1399
- <div class="pt-2 flex gap-2 flex-wrap justify-start">
1400
- @for (surface of surfaces; track surface.name) {
1401
- <button
1402
- class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
1403
- id="oip-app-configurator-surface-color-{{ surface.name }}"
1404
- type="button"
1405
- [ngClass]="{
1406
- 'outline-primary': selectedSurfaceColor()
1407
- ? selectedSurfaceColor() === surface.name
1408
- : layoutService.layoutConfig().darkTheme
1409
- ? surface.name === 'zinc'
1410
- : surface.name === 'slate'
1411
- }"
1412
- [style]="{
1413
- 'background-color': surface?.name === 'noir' ? 'var(--text-color)' : surface?.palette?.['500']
1414
- }"
1415
- [title]="surface.name"
1416
- (click)="updateColors($event, 'surface', surface)"></button>
1417
- }
1418
- </div>
1419
- </div>
1420
- <div class="flex flex-col gap-2">
1421
- <span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.presets' | translate }}</span>
1422
- <p-selectButton
1423
- id="oip-app-configurator-preset-select-button"
1424
- size="small"
1425
- [allowEmpty]="false"
1426
- [ngModel]="selectedPreset()"
1427
- [options]="presets"
1428
- (ngModelChange)="onPresetChange($event)" />
1429
- </div>
1430
- @if (showMenuModeButton()) {
1431
- <div class="flex flex-col gap-2">
1432
- <span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.menuMode' | translate }}</span>
1433
- <p-selectButton
1434
- id="oip-app-configurator-menu-mode-select-button"
1435
- size="small"
1436
- [allowEmpty]="false"
1437
- [ngModel]="menuMode()"
1438
- [options]="menuModeOptions"
1439
- (ngModelChange)="onMenuModeChange($event)" />
1440
- </div>
1441
- }
1442
- </div>
1451
+ template: `
1452
+ <div class="flex flex-col gap-4">
1453
+ <div>
1454
+ <span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.primary' | translate }}</span>
1455
+ <div class="pt-2 flex gap-2 flex-wrap justify-start">
1456
+ @for (primaryColor of primaryColors(); track primaryColor.name) {
1457
+ <button
1458
+ class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
1459
+ id="oip-app-configurator-primary-color-{{ primaryColor.name }}"
1460
+ type="button"
1461
+ [ngClass]="{
1462
+ 'outline-primary': primaryColor.name === selectedPrimaryColor()
1463
+ }"
1464
+ [style]="{
1465
+ 'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
1466
+ }"
1467
+ [title]="primaryColor.name"
1468
+ (click)="updateColors($event, 'primary', primaryColor)"></button>
1469
+ }
1470
+ </div>
1471
+ </div>
1472
+ <div>
1473
+ <span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.surface' | translate }}</span>
1474
+ <div class="pt-2 flex gap-2 flex-wrap justify-start">
1475
+ @for (surface of surfaceColors(); track surface.name) {
1476
+ <button
1477
+ class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
1478
+ id="oip-app-configurator-surface-color-{{ surface.name }}"
1479
+ type="button"
1480
+ [ngClass]="{
1481
+ 'outline-primary': selectedSurfaceColor()
1482
+ ? selectedSurfaceColor() === surface.name
1483
+ : layoutService.layoutConfig().darkTheme
1484
+ ? surface.name === 'zinc'
1485
+ : surface.name === 'slate'
1486
+ }"
1487
+ [style]="{
1488
+ 'background-color': surface?.name === 'noir' ? 'var(--text-color)' : surface?.palette?.['500']
1489
+ }"
1490
+ [title]="surface.name"
1491
+ (click)="updateColors($event, 'surface', surface)"></button>
1492
+ }
1493
+ </div>
1494
+ </div>
1495
+ <div class="flex flex-col gap-2">
1496
+ <span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.presets' | translate }}</span>
1497
+ <p-selectButton
1498
+ id="oip-app-configurator-preset-select-button"
1499
+ size="small"
1500
+ [allowEmpty]="false"
1501
+ [ngModel]="selectedPreset()"
1502
+ [options]="presets"
1503
+ optionLabel="label"
1504
+ optionValue="value"
1505
+ (ngModelChange)="onPresetChange($event)" />
1506
+ </div>
1507
+ @if (showMenuModeButton()) {
1508
+ <div class="flex flex-col gap-2">
1509
+ <span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.menuMode' | translate }}</span>
1510
+ <p-selectButton
1511
+ id="oip-app-configurator-menu-mode-select-button"
1512
+ size="small"
1513
+ [allowEmpty]="false"
1514
+ [ngModel]="menuMode()"
1515
+ [options]="menuModeOptions"
1516
+ (ngModelChange)="onMenuModeChange($event)" />
1517
+ </div>
1518
+ }
1519
+ </div>
1443
1520
  `,
1444
1521
  host: {
1445
1522
  class: 'hidden absolute top-[3.25rem] right-0 w-72 p-4 bg-surface-0 dark:bg-surface-900 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]'
@@ -6060,6 +6137,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
6060
6137
  type: Injectable
6061
6138
  }] });
6062
6139
 
6140
+ function provideAppThemes(themes, options) {
6141
+ const mode = options?.mode ?? 'mergeWithDefaults';
6142
+ return makeEnvironmentProviders([
6143
+ { provide: APP_THEME_PRESETS, useValue: themes },
6144
+ { provide: APP_THEME_PRESETS_MERGE_MODE, useValue: mode }
6145
+ ]);
6146
+ }
6147
+ function mergeWithDefaults(themes) {
6148
+ return provideAppThemes(themes, { mode: 'mergeWithDefaults' });
6149
+ }
6150
+ function replaceDefaults(themes) {
6151
+ return provideAppThemes(themes, { mode: 'replaceDefaults' });
6152
+ }
6153
+
6063
6154
  const langIntercept = (req, next) => {
6064
6155
  const layoutService = inject(LayoutService);
6065
6156
  const lang = layoutService.language() ? layoutService.language() : 'en';
@@ -6132,5 +6223,5 @@ const httpLoaderAuthFactory = (httpClient) => {
6132
6223
  * Generated bundle index. Do not edit.
6133
6224
  */
6134
6225
 
6135
- export { AppConfiguratorComponent, AppFloatingConfiguratorComponent, AppLayoutComponent, AppModulesComponent, AppTopbar, AuthGuardService, BaseDataService, BaseModuleComponent, ConfigComponent, ContentType, DEFAULT_OIP_FRONTEND_CONFIG, DbMigrationComponent, DiscussionComponent, ErrorComponent, FooterComponent, HttpClient, KeycloakSecurityService, L10nService, LOGO_COMPONENT_TOKEN, LayoutService, LogoComponent, LogoService, MenuComponent, MenuService, MsgService, NotfoundComponent, NotificationService, OIP_FRONTEND_CONFIG, ProfileComponent, SecurePipe, SecurityComponent, SecurityDataService, SecurityService, SecurityStorageService, SidebarComponent, TableFilterService, TopBarService, UnauthorizedComponent, UserService, httpLoaderAuthFactory, langIntercept, provideLogoComponent };
6226
+ export { APP_THEME_PRESETS, APP_THEME_PRESETS_MERGE_MODE, AppConfiguratorComponent, AppFloatingConfiguratorComponent, AppLayoutComponent, AppModulesComponent, AppTopbar, AuthGuardService, BaseDataService, BaseModuleComponent, ConfigComponent, ContentType, DEFAULT_OIP_FRONTEND_CONFIG, DbMigrationComponent, DiscussionComponent, ErrorComponent, FooterComponent, HttpClient, KeycloakSecurityService, L10nService, LOGO_COMPONENT_TOKEN, LayoutService, LogoComponent, LogoService, MenuComponent, MenuService, MsgService, NotfoundComponent, NotificationService, OIP_FRONTEND_CONFIG, ProfileComponent, SecurePipe, SecurityComponent, SecurityDataService, SecurityService, SecurityStorageService, SidebarComponent, TableFilterService, TopBarService, UnauthorizedComponent, UserService, httpLoaderAuthFactory, langIntercept, mergeWithDefaults, provideAppThemes, provideLogoComponent, replaceDefaults };
6136
6227
  //# sourceMappingURL=oip-common.mjs.map