feat: add logo image and RTL support styles
- Added logo image to assets. - Implemented RTL support styles in rtlSupport.scss for various components including breadcrumb, datatable, and tree node toggle button. chore: configure environment files for production, staging, and development - Created environment.prod.ts for production settings. - Created environment.staging.ts for staging settings. - Created environment.ts for local development settings. feat: define custom theme preset - Added presets.ts to define a custom theme preset using PrimeUIX with specific component styles and semantic colors. chore: set up proxy configuration for local development
This commit is contained in:
@@ -1,178 +1,189 @@
|
||||
import { Injectable, effect, signal, computed } from '@angular/core';
|
||||
import { Injectable, computed, effect, signal } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
export interface layoutConfig {
|
||||
preset?: string;
|
||||
primary?: string;
|
||||
surface?: string | undefined | null;
|
||||
darkTheme?: boolean;
|
||||
menuMode?: string;
|
||||
preset?: string;
|
||||
primary?: string;
|
||||
surface?: string | undefined | null;
|
||||
darkTheme?: boolean;
|
||||
menuMode?: string;
|
||||
}
|
||||
|
||||
interface LayoutState {
|
||||
staticMenuDesktopInactive?: boolean;
|
||||
overlayMenuActive?: boolean;
|
||||
configSidebarVisible?: boolean;
|
||||
staticMenuMobileActive?: boolean;
|
||||
menuHoverActive?: boolean;
|
||||
staticMenuDesktopInactive?: boolean;
|
||||
overlayMenuActive?: boolean;
|
||||
configSidebarVisible?: boolean;
|
||||
staticMenuMobileActive?: boolean;
|
||||
menuHoverActive?: boolean;
|
||||
}
|
||||
|
||||
interface MenuChangeEvent {
|
||||
key: string;
|
||||
routeEvent?: boolean;
|
||||
key: string;
|
||||
routeEvent?: boolean;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class LayoutService {
|
||||
_config: layoutConfig = {
|
||||
preset: 'Aura',
|
||||
primary: 'emerald',
|
||||
surface: null,
|
||||
darkTheme: false,
|
||||
menuMode: 'static'
|
||||
};
|
||||
_config: layoutConfig = {
|
||||
preset: 'Aura',
|
||||
primary: 'violet',
|
||||
surface: null,
|
||||
darkTheme: localStorage.getItem('isDarkTheme') === 'true',
|
||||
menuMode: 'static',
|
||||
};
|
||||
|
||||
_state: LayoutState = {
|
||||
staticMenuDesktopInactive: false,
|
||||
overlayMenuActive: false,
|
||||
configSidebarVisible: false,
|
||||
staticMenuMobileActive: false,
|
||||
menuHoverActive: false
|
||||
};
|
||||
_state: LayoutState = {
|
||||
staticMenuDesktopInactive: false,
|
||||
overlayMenuActive: false,
|
||||
configSidebarVisible: false,
|
||||
staticMenuMobileActive: false,
|
||||
menuHoverActive: false,
|
||||
};
|
||||
|
||||
layoutConfig = signal<layoutConfig>(this._config);
|
||||
layoutConfig = signal<layoutConfig>(this._config);
|
||||
|
||||
layoutState = signal<LayoutState>(this._state);
|
||||
layoutState = signal<LayoutState>(this._state);
|
||||
|
||||
private configUpdate = new Subject<layoutConfig>();
|
||||
private configUpdate = new Subject<layoutConfig>();
|
||||
|
||||
private overlayOpen = new Subject<any>();
|
||||
private overlayOpen = new Subject<any>();
|
||||
|
||||
private menuSource = new Subject<MenuChangeEvent>();
|
||||
private menuSource = new Subject<MenuChangeEvent>();
|
||||
|
||||
private resetSource = new Subject();
|
||||
private resetSource = new Subject();
|
||||
|
||||
menuSource$ = this.menuSource.asObservable();
|
||||
menuSource$ = this.menuSource.asObservable();
|
||||
|
||||
resetSource$ = this.resetSource.asObservable();
|
||||
resetSource$ = this.resetSource.asObservable();
|
||||
|
||||
configUpdate$ = this.configUpdate.asObservable();
|
||||
configUpdate$ = this.configUpdate.asObservable();
|
||||
|
||||
overlayOpen$ = this.overlayOpen.asObservable();
|
||||
overlayOpen$ = this.overlayOpen.asObservable();
|
||||
|
||||
theme = computed(() => (this.layoutConfig()?.darkTheme ? 'light' : 'dark'));
|
||||
theme = computed(() => (this.layoutConfig()?.darkTheme ? 'light' : 'dark'));
|
||||
|
||||
isSidebarActive = computed(() => this.layoutState().overlayMenuActive || this.layoutState().staticMenuMobileActive);
|
||||
isSidebarActive = computed(
|
||||
() => this.layoutState().overlayMenuActive || this.layoutState().staticMenuMobileActive,
|
||||
);
|
||||
|
||||
isDarkTheme = computed(() => this.layoutConfig().darkTheme);
|
||||
isDarkTheme = computed(() => this.layoutConfig().darkTheme);
|
||||
|
||||
getPrimary = computed(() => this.layoutConfig().primary);
|
||||
getPrimary = computed(() => this.layoutConfig().primary);
|
||||
|
||||
getSurface = computed(() => this.layoutConfig().surface);
|
||||
getSurface = computed(() => this.layoutConfig().surface);
|
||||
|
||||
isOverlay = computed(() => this.layoutConfig().menuMode === 'overlay');
|
||||
isOverlay = computed(() => this.layoutConfig().menuMode === 'overlay');
|
||||
|
||||
transitionComplete = signal<boolean>(false);
|
||||
transitionComplete = signal<boolean>(false);
|
||||
|
||||
private initialized = false;
|
||||
private initialized = false;
|
||||
|
||||
constructor() {
|
||||
effect(() => {
|
||||
const config = this.layoutConfig();
|
||||
if (config) {
|
||||
this.onConfigUpdate();
|
||||
}
|
||||
});
|
||||
constructor() {
|
||||
effect(() => {
|
||||
const config = this.layoutConfig();
|
||||
if (config) {
|
||||
this.onConfigUpdate();
|
||||
}
|
||||
});
|
||||
|
||||
effect(() => {
|
||||
const config = this.layoutConfig();
|
||||
effect(() => {
|
||||
const config = this.layoutConfig();
|
||||
|
||||
if (!this.initialized || !config) {
|
||||
this.initialized = true;
|
||||
return;
|
||||
}
|
||||
if (!this.initialized || !config) {
|
||||
this.initialized = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.handleDarkModeTransition(config);
|
||||
});
|
||||
this.handleDarkModeTransition(config);
|
||||
});
|
||||
}
|
||||
|
||||
private handleDarkModeTransition(config: layoutConfig): void {
|
||||
if ((document as any).startViewTransition) {
|
||||
this.startViewTransition(config);
|
||||
} else {
|
||||
this.toggleDarkMode(config);
|
||||
this.onTransitionEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private startViewTransition(config: layoutConfig): void {
|
||||
const transition = (document as any).startViewTransition(() => {
|
||||
this.toggleDarkMode(config);
|
||||
});
|
||||
|
||||
transition.ready
|
||||
.then(() => {
|
||||
this.onTransitionEnd();
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
toggleDarkMode(config?: layoutConfig): void {
|
||||
const _config = config || this.layoutConfig();
|
||||
if (_config.darkTheme) {
|
||||
document.documentElement.classList.add('app-dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('app-dark');
|
||||
}
|
||||
}
|
||||
|
||||
private onTransitionEnd() {
|
||||
this.transitionComplete.set(true);
|
||||
setTimeout(() => {
|
||||
this.transitionComplete.set(false);
|
||||
});
|
||||
}
|
||||
|
||||
onMenuToggle() {
|
||||
if (this.isOverlay()) {
|
||||
this.layoutState.update((prev) => ({
|
||||
...prev,
|
||||
overlayMenuActive: !this.layoutState().overlayMenuActive,
|
||||
}));
|
||||
|
||||
if (this.layoutState().overlayMenuActive) {
|
||||
this.overlayOpen.next(null);
|
||||
}
|
||||
}
|
||||
|
||||
private handleDarkModeTransition(config: layoutConfig): void {
|
||||
if ((document as any).startViewTransition) {
|
||||
this.startViewTransition(config);
|
||||
} else {
|
||||
this.toggleDarkMode(config);
|
||||
this.onTransitionEnd();
|
||||
}
|
||||
if (this.isDesktop()) {
|
||||
this.layoutState.update((prev) => ({
|
||||
...prev,
|
||||
staticMenuDesktopInactive: !this.layoutState().staticMenuDesktopInactive,
|
||||
}));
|
||||
} else {
|
||||
this.layoutState.update((prev) => ({
|
||||
...prev,
|
||||
staticMenuMobileActive: !this.layoutState().staticMenuMobileActive,
|
||||
}));
|
||||
|
||||
if (this.layoutState().staticMenuMobileActive) {
|
||||
this.overlayOpen.next(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private startViewTransition(config: layoutConfig): void {
|
||||
const transition = (document as any).startViewTransition(() => {
|
||||
this.toggleDarkMode(config);
|
||||
});
|
||||
isDesktop() {
|
||||
return window.innerWidth > 991;
|
||||
}
|
||||
|
||||
transition.ready
|
||||
.then(() => {
|
||||
this.onTransitionEnd();
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
isMobile() {
|
||||
return !this.isDesktop();
|
||||
}
|
||||
|
||||
toggleDarkMode(config?: layoutConfig): void {
|
||||
const _config = config || this.layoutConfig();
|
||||
if (_config.darkTheme) {
|
||||
document.documentElement.classList.add('app-dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('app-dark');
|
||||
}
|
||||
}
|
||||
onConfigUpdate() {
|
||||
this._config = { ...this.layoutConfig() };
|
||||
this.configUpdate.next(this.layoutConfig());
|
||||
}
|
||||
|
||||
private onTransitionEnd() {
|
||||
this.transitionComplete.set(true);
|
||||
setTimeout(() => {
|
||||
this.transitionComplete.set(false);
|
||||
});
|
||||
}
|
||||
onMenuStateChange(event: MenuChangeEvent) {
|
||||
this.menuSource.next(event);
|
||||
}
|
||||
|
||||
onMenuToggle() {
|
||||
if (this.isOverlay()) {
|
||||
this.layoutState.update((prev) => ({ ...prev, overlayMenuActive: !this.layoutState().overlayMenuActive }));
|
||||
|
||||
if (this.layoutState().overlayMenuActive) {
|
||||
this.overlayOpen.next(null);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isDesktop()) {
|
||||
this.layoutState.update((prev) => ({ ...prev, staticMenuDesktopInactive: !this.layoutState().staticMenuDesktopInactive }));
|
||||
} else {
|
||||
this.layoutState.update((prev) => ({ ...prev, staticMenuMobileActive: !this.layoutState().staticMenuMobileActive }));
|
||||
|
||||
if (this.layoutState().staticMenuMobileActive) {
|
||||
this.overlayOpen.next(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isDesktop() {
|
||||
return window.innerWidth > 991;
|
||||
}
|
||||
|
||||
isMobile() {
|
||||
return !this.isDesktop();
|
||||
}
|
||||
|
||||
onConfigUpdate() {
|
||||
this._config = { ...this.layoutConfig() };
|
||||
this.configUpdate.next(this.layoutConfig());
|
||||
}
|
||||
|
||||
onMenuStateChange(event: MenuChangeEvent) {
|
||||
this.menuSource.next(event);
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.resetSource.next(true);
|
||||
}
|
||||
reset() {
|
||||
this.resetSource.next(true);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user