Merge remote-tracking branch 'origin/v19' into v19

# Conflicts:
#	src/layout/appconfigurator.ts
#	src/layout/applayout.ts
This commit is contained in:
Çetin
2025-01-07 10:53:30 +03:00
6 changed files with 97 additions and 136 deletions

View File

@@ -4,7 +4,6 @@ import { FormsModule } from '@angular/forms';
import { $t, updatePreset, updateSurfacePalette } from '@primeng/themes';
import Aura from '@primeng/themes/aura';
import Lara from '@primeng/themes/lara';
import { ButtonModule } from 'primeng/button';
import { PrimeNG } from 'primeng/config';
import { SelectButtonModule } from 'primeng/selectbutton';
import { LayoutService } from '@/src/service/layout/layout.service';
@@ -17,55 +16,55 @@ const presets = {
@Component({
selector: 'app-configurator',
standalone: true,
imports: [CommonModule, FormsModule, ButtonModule, SelectButtonModule],
imports: [CommonModule, FormsModule, SelectButtonModule],
template: `
<div class="flex flex-col gap-4">
<div>
<span class="text-sm text-muted-color font-semibold">Primary</span>
<div class="pt-2 flex gap-2 flex-wrap justify-between">
@for (primaryColor of primaryColors(); track primaryColor.name) {
<button
type="button"
[title]="primaryColor.name"
(click)="updateColors($event, 'primary', primaryColor)"
[ngClass]="{ 'outline-primary': primaryColor.name === selectedPrimaryColor() }"
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
[style]="{
'background-color': primaryColor.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette['500']
}"
></button>
}
</div>
</div>
<div>
<span class="text-sm text-muted-color font-semibold">Surface</span>
<div class="pt-2 flex gap-2 flex-wrap justify-between">
@for (surface of surfaces; track surface.name) {
<button
type="button"
[title]="surface.name"
(click)="updateColors($event, 'surface', surface)"
[ngClass]="{ 'outline-primary': selectedSurfaceColor() ? selectedSurfaceColor() === surface.name : layoutService.layoutConfig().darkTheme ? surface.name === 'zinc' : surface.name === 'slate' }"
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
[style]="{
'background-color': surface.name === 'noir' ? 'var(--text-color)' : surface?.palette['500']
}"
></button>
}
</div>
</div>
<div class="flex flex-col gap-2">
<span class="text-sm text-muted-color font-semibold">Presets</span>
<p-selectbutton [options]="presets" [ngModel]="selectedPreset()" (ngModelChange)="onPresetChange($event)" [allowEmpty]="false" />
</div>
<div class="flex flex-col gap-2">
<span class="text-sm text-muted-color font-semibold">Menu Mode</span>
<p-selectbutton [ngModel]="menuMode()" (ngModelChange)="onMenuModeChange($event)" [options]="menuModeOptions" [allowEmpty]="false" />
<div class="flex flex-col gap-4">
<div>
<span class="text-sm text-muted-color font-semibold">Primary</span>
<div class="pt-2 flex gap-2 flex-wrap justify-between">
@for (primaryColor of primaryColors(); track primaryColor.name) {
<button
type="button"
[title]="primaryColor.name"
(click)="updateColors($event, 'primary', primaryColor)"
[ngClass]="{ 'outline-primary': primaryColor.name === selectedPrimaryColor() }"
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
[style]="{
'background-color': primaryColor.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette['500']
}"
></button>
}
</div>
</div>
<div>
<span class="text-sm text-muted-color font-semibold">Surface</span>
<div class="pt-2 flex gap-2 flex-wrap justify-between">
@for (surface of surfaces; track surface.name) {
<button
type="button"
[title]="surface.name"
(click)="updateColors($event, 'surface', surface)"
[ngClass]="{ 'outline-primary': selectedSurfaceColor() ? selectedSurfaceColor() === surface.name : layoutService.layoutConfig().darkTheme ? surface.name === 'zinc' : surface.name === 'slate' }"
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
[style]="{
'background-color': surface.name === 'noir' ? 'var(--text-color)' : surface?.palette['500']
}"
></button>
}
</div>
</div>
<div class="flex flex-col gap-2">
<span class="text-sm text-muted-color font-semibold">Presets</span>
<p-selectbutton [options]="presets" [ngModel]="selectedPreset()" (ngModelChange)="onPresetChange($event)" [allowEmpty]="false" size="small" />
</div>
<div class="flex flex-col gap-2">
<span class="text-sm text-muted-color font-semibold">Menu Mode</span>
<p-selectbutton [ngModel]="menuMode()" (ngModelChange)="onMenuModeChange($event)" [options]="menuModeOptions" [allowEmpty]="false" size="small" />
</div>
</div>
`,
host: {
class: 'hidden absolute top-[3.25rem] right-0 w-64 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)]',
class: 'hidden absolute top-[3.25rem] right-0 w-64 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)]'
}
})
export class AppConfigurator {

View File

@@ -4,21 +4,15 @@ import { CommonModule } from '@angular/common';
import { AppTopBar } from '@/src/layout/apptopbar';
import { AppSidebar } from '@/src/layout/appsidebar';
import { NavigationEnd, Router, RouterModule } from '@angular/router';
import { AppConfigurator } from '@/src/layout/appconfigurator';
import { AppFooter } from '@/src/layout/appfooter';
import { filter, Subscription } from 'rxjs';
import { LayoutService } from '@/src/service/layout/layout.service';
@Component({
selector: 'app-layout',
standalone:true,
imports: [
CommonModule,
ToastModule,
AppTopBar,
AppSidebar,
RouterModule,
AppFooter,
],
standalone: true,
imports: [CommonModule, ToastModule, AppTopBar, AppSidebar, RouterModule, AppFooter, AppConfigurator],
template: `<div class="layout-wrapper" [ngClass]="containerClass">
<app-topbar></app-topbar>
<div class="layout-sidebar">
@@ -30,9 +24,9 @@ import { LayoutService } from '@/src/service/layout/layout.service';
</div>
<app-footer></app-footer>
</div>
<app-configurator></app-configurator>
<div class="layout-mask animate-fadein"></div>
</div>
`,
</div> `
})
export class AppLayout {
overlayMenuOpenSubscription: Subscription;
@@ -45,23 +39,28 @@ export class AppLayout {
@ViewChild(AppTopBar) appTopBar!: AppTopBar;
constructor(public layoutService: LayoutService, public renderer: Renderer2, public router: Router) {
constructor(
public layoutService: LayoutService,
public renderer: Renderer2,
public router: Router
) {
this.overlayMenuOpenSubscription = this.layoutService.overlayOpen$.subscribe(() => {
if (!this.menuOutsideClickListener) {
this.menuOutsideClickListener = this.renderer.listen('document', 'click', event => {
const isOutsideClicked = !(this.appSidebar.el.nativeElement.isSameNode(event.target) || this.appSidebar.el.nativeElement.contains(event.target)
|| this.appTopBar.menuButton.nativeElement.isSameNode(event.target) || this.appTopBar.menuButton.nativeElement.contains(event.target));
if (isOutsideClicked) {
this.menuOutsideClickListener = this.renderer.listen('document', 'click', (event) => {
if (this.isOutsideClicked(event)) {
this.hideMenu();
}
});
}
if (!this.profileMenuOutsideClickListener) {
this.profileMenuOutsideClickListener = this.renderer.listen('document', 'click', event => {
const isOutsideClicked = !(this.appTopBar.menu.nativeElement.isSameNode(event.target) || this.appTopBar.menu.nativeElement.contains(event.target)
|| this.appTopBar.topbarMenuButton.nativeElement.isSameNode(event.target) || this.appTopBar.topbarMenuButton.nativeElement.contains(event.target));
this.profileMenuOutsideClickListener = this.renderer.listen('document', 'click', (event) => {
const isOutsideClicked = !(
this.appTopBar.menu.nativeElement.isSameNode(event.target) ||
this.appTopBar.menu.nativeElement.contains(event.target) ||
this.appTopBar.topbarMenuButton.nativeElement.isSameNode(event.target) ||
this.appTopBar.topbarMenuButton.nativeElement.contains(event.target)
);
if (isOutsideClicked) {
}
@@ -73,14 +72,20 @@ export class AppLayout {
}
});
this.router.events.pipe(filter(event => event instanceof NavigationEnd))
.subscribe(() => {
this.hideMenu();
});
this.router.events.pipe(filter((event) => event instanceof NavigationEnd)).subscribe(() => {
this.hideMenu();
});
}
isOutsideClicked(event) {
const sidebarEl = document.querySelector('.layout-sidebar');
const topbarEl = document.querySelector('.layout-menu-button');
return !(sidebarEl.isSameNode(event.target) || sidebarEl.contains(event.target) || topbarEl.isSameNode(event.target) || topbarEl.contains(event.target));
}
hideMenu() {
this.layoutService.layoutState.update((prev) => ({...prev, overlayMenuActive:false, staticMenuMobileActive: false, menuHoverActive: false}))
this.layoutService.layoutState.update((prev) => ({ ...prev, overlayMenuActive: false, staticMenuMobileActive: false, menuHoverActive: false }));
if (this.menuOutsideClickListener) {
this.menuOutsideClickListener();
this.menuOutsideClickListener = null;
@@ -91,8 +96,7 @@ export class AppLayout {
blockBodyScroll(): void {
if (document.body.classList) {
document.body.classList.add('blocked-scroll');
}
else {
} else {
document.body.className += ' blocked-scroll';
}
}
@@ -100,10 +104,8 @@ export class AppLayout {
unblockBodyScroll(): void {
if (document.body.classList) {
document.body.classList.remove('blocked-scroll');
}
else {
document.body.className = document.body.className.replace(new RegExp('(^|\\b)' +
'blocked-scroll'.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
} else {
document.body.className = document.body.className.replace(new RegExp('(^|\\b)' + 'blocked-scroll'.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
}
}
@@ -114,7 +116,7 @@ export class AppLayout {
'layout-static-inactive': this.layoutService.layoutState().staticMenuDesktopInactive && this.layoutService.layoutConfig().menuMode === 'static',
'layout-overlay-active': this.layoutService.layoutState().overlayMenuActive,
'layout-mobile-active': this.layoutService.layoutState().staticMenuMobileActive
}
};
}
ngOnDestroy() {