last works for handle card sizing ...

This commit is contained in:
2026-08-29 17:22:55 +03:30
parent 921b9e09f8
commit 30f944123f
5 changed files with 231 additions and 61 deletions
@@ -0,0 +1,4 @@
export interface XSizeModel {
width?: number;
height?: number;
}
@@ -9,7 +9,7 @@
[class.fullscreen]="getValue(isFullscreen) | async"
>
<!-- Card Header -->
<mat-card-header class="x-header" *ngIf="getValue(showHeader) | async">
<mat-card-header #cardHeader class="x-header" *ngIf="getValue(showHeader) | async">
<!-- Avatar Image -->
<section
*ngIf="notEmptyValue(avatarUrl) | async"
@@ -57,6 +57,7 @@
<!-- Card Image -->
<img
mat-card-image
#cardImage
class="x-image"
[src]="getValue(imageUrl) | async"
*ngIf="notEmptyValue(imageUrl) | async"
@@ -64,18 +65,18 @@
/>
<!-- Card Content -->
<mat-card-content class="x-content" *ngIf="getValue(showContent) | async">
<mat-card-content #cardContent class="x-content" *ngIf="getValue(showContent) | async">
<ng-content></ng-content>
</mat-card-content>
<!-- Card Actions -->
<mat-card-actions class="x-actions" *ngIf="getValue(showActions) | async">
<mat-card-actions #cardActions class="x-actions" *ngIf="getValue(showActions) | async">
<ng-content select="[actions]"></ng-content>
</mat-card-actions>
<!-- Card Footer -->
<mat-card-footer
#footer
#cardFooter
class="x-footer"
*ngIf="getValue(showFooter) | async"
>
@@ -5,8 +5,9 @@ import {
} from './x-card.typings';
import { Subject, Subscription } from 'rxjs';
import { concatMap, map } from 'rxjs/operators';
import { nameof, isNullOrEmptyString } from 'x-framework-core';
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { XSizeModel } from '../classes/x-size.model.';
import { nameof, isNullOrEmptyString, isNullOrUndefined } from 'x-framework-core';
import { Component, ChangeDetectionStrategy, ElementRef, ViewChild } from '@angular/core';
@Component({
// tslint:disable-next-line:component-selector
@@ -21,17 +22,71 @@ export class XCardComponent extends XCardContainerComponent {
//
private ACTION_PROVIDER_SUBSCRIPTION: Subscription;
//
//#region Card Elements ....
private CARD_IMAGE: ElementRef<HTMLElement> = undefined;
private CARD_HEADER: ElementRef<HTMLElement> = undefined;
private CARD_FOOTER: ElementRef<HTMLElement> = undefined;
private CARD_CONTENT: ElementRef<HTMLElement> = undefined;
private CARD_ACTIONS: ElementRef<HTMLElement> = undefined;
@ViewChild('cardImage', { static: false })
set cardImage(v: ElementRef<HTMLElement>) {
this.CARD_IMAGE = v;
}
@ViewChild('cardHeader', { static: false })
set cardHeader(v: ElementRef<HTMLElement>) {
this.CARD_HEADER = v;
}
@ViewChild('cardFooter', { static: false })
set cardFooter(v: ElementRef<HTMLElement>) {
this.CARD_FOOTER = v;
}
@ViewChild('cardContent', { static: false })
set cardContent(v: ElementRef<HTMLElement>) {
this.CARD_CONTENT = v;
}
@ViewChild('cardActions', { static: false })
set cardActions(v: ElementRef<HTMLElement>) {
this.CARD_ACTIONS = v;
}
get cardImage() {
return this.CARD_IMAGE;
}
get cardHeader() {
return this.CARD_HEADER;
}
get cardFooter() {
return this.CARD_FOOTER;
}
get cardContent() {
return this.CARD_CONTENT;
}
get cardActions() {
return this.CARD_ACTIONS;
}
//#endregion
//
//#region Full Screen ...
private IS_FULLSCREEN: boolean = false;
public set isFullscreen(v: boolean) {
set isFullscreen(v: boolean) {
//
const isChanged = v != this.IS_FULLSCREEN;
//
this.IS_FULLSCREEN = v;
}
public get isFullscreen() {
get isFullscreen() {
return this.IS_FULLSCREEN;
}
//#endregion
@@ -167,6 +222,109 @@ export class XCardComponent extends XCardContainerComponent {
await this.enterFullscreen();
}
}
//
//#region Size Calculating ...
public calculateImageSize() {
//
let result: XSizeModel = undefined;
//
// Validate ...
if (isNullOrUndefined(this.CARD_IMAGE) || isNullOrUndefined(this.CARD_IMAGE.nativeElement)) {
return result;
}
//
result = {
width: this.CARD_IMAGE.nativeElement.offsetWidth,
height: this.CARD_IMAGE.nativeElement.offsetHeight
};
//
return result;
}
public calculateHeaderSize() {
//
let result: XSizeModel = undefined;
//
// Validate ...
if (isNullOrUndefined(this.CARD_HEADER) || isNullOrUndefined(this.CARD_HEADER.nativeElement)) {
return result;
}
//
result = {
width: this.CARD_HEADER.nativeElement.offsetWidth,
height: this.CARD_HEADER.nativeElement.offsetHeight
};
//
return result;
}
public calculateFooterSize() {
//
let result: XSizeModel = undefined;
//
// Validate ...
if (isNullOrUndefined(this.CARD_FOOTER) || isNullOrUndefined(this.CARD_FOOTER.nativeElement)) {
return result;
}
//
result = {
width: this.CARD_FOOTER.nativeElement.offsetWidth,
height: this.CARD_FOOTER.nativeElement.offsetHeight
};
//
return result;
}
public calculateContentSize() {
//
let result: XSizeModel = undefined;
//
// Validate ...
if (isNullOrUndefined(this.CARD_CONTENT) || isNullOrUndefined(this.CARD_CONTENT.nativeElement)) {
return result;
}
//
result = {
width: this.CARD_CONTENT.nativeElement.offsetWidth,
height: this.CARD_CONTENT.nativeElement.offsetHeight
};
//
return result;
}
public calculateActionsSize() {
//
let result: XSizeModel = undefined;
//
// Validate ...
if (isNullOrUndefined(this.CARD_ACTIONS) || isNullOrUndefined(this.CARD_ACTIONS.nativeElement)) {
return result;
}
//
result = {
width: this.CARD_ACTIONS.nativeElement.offsetWidth,
height: this.CARD_ACTIONS.nativeElement.offsetHeight
};
//
return result;
}
//#endregion
//#endregion
//
@@ -1,6 +1,7 @@
<!-- Component Template -->
<ng-container *ngIf="getValue(wrapWithCard) | async; else componentsRef">
<x-card
#chartCard
class="x-card"
[showActions]="true"
[color]="getValue(cardColor) | async"
@@ -30,7 +30,7 @@ import {
XChartContainerComponent,
XChartStoryboardBeatInfo,
} from './x-chart.typings';
import { Subscription } from 'rxjs';
import { fromEvent, Subject, Subscription } from 'rxjs';
import ApexCharts from 'apexcharts';
import {
XActionBarItem,
@@ -39,6 +39,8 @@ import {
} from '../x-action-bar/x-action-bar.typings';
import { XIconNames } from '../x-icon/x-icon.typings';
import { XCardAction } from '../x-card/x-card.typings';
import { debounceTime, takeUntil } from 'rxjs/operators';
import { XCardComponent } from '../x-card/x-card.component';
@Component({
selector: 'x-chart',
@@ -50,10 +52,10 @@ export class XChartComponent extends XChartContainerComponent {
//
//#region Props ...
//
private CHART_CONTAINER: ElementRef | undefined;
private CHART_CONTAINER: ElementRef = undefined;
@ViewChild('chartContainer', { static: false })
set chartContainer(el: ElementRef | undefined) {
set chartContainer(el: ElementRef) {
//
if (isNullOrUndefined(el)) {
//
@@ -71,17 +73,19 @@ export class XChartComponent extends XChartContainerComponent {
}
//
@HostListener('resize', ['$event'])
onResize(event: any) {
//
if (isNullOrUndefined(this.chartInstance)) {
return;
}
private CHART_CARD: ElementRef<XCardComponent> = undefined;
//
// TODO: Complete this ...
// this.chartInstance.updateOptions();
@ViewChild('chartCard', { static: false })
set chartCard(el: ElementRef<XCardComponent>) {
this.CHART_CARD = el;
}
get chartCard() {
return this.CHART_CARD;;
}
//
private RESIZE_SUBJECT = new Subject<Event>();
//
private CHART_OPTIONS: XChartOptions = null;
@@ -105,6 +109,7 @@ export class XChartComponent extends XChartContainerComponent {
//
await this.initializeComponent();
this.registerResizeHandler();
}
async onChange(changeKeys: string[]) {
@@ -337,6 +342,10 @@ export class XChartComponent extends XChartContainerComponent {
onDestroy() {
super.onDestroy();
//
this.RESIZE_SUBJECT.next();
this.RESIZE_SUBJECT.complete();
//
this.destroyComponent();
this.unregisterActionProvider();
@@ -658,7 +667,7 @@ export class XChartComponent extends XChartContainerComponent {
printWindow.document.close();
}
}
} catch (error) {}
} catch (error) { }
}
async handleToggleFullscreen() {
@@ -672,47 +681,8 @@ export class XChartComponent extends XChartContainerComponent {
}
//
// Handle Fullscreen Toggle using Card ...
this.cardActionProvider.next({ action: XCardAction.ToggleFullScreen });
//
return;
//
const chartWrapper = this.chartContainer.nativeElement;
const doc = document as any;
//
// Check if the chart wrapper is currently in fullscreen mode
const isFullscreen =
doc.fullscreenElement === chartWrapper ||
doc.msFullscreenElement === chartWrapper ||
doc.mozFullScreenElement === chartWrapper ||
doc.webkitFullscreenElement === chartWrapper;
if (!isFullscreen) {
//
// Enter Fullscreen
if (chartWrapper.requestFullscreen) {
await chartWrapper.requestFullscreen();
} else if (chartWrapper.webkitRequestFullscreen) {
await chartWrapper.webkitRequestFullscreen();
} else if (chartWrapper.mozRequestFullScreen) {
await chartWrapper.mozRequestFullScreen();
} else if (chartWrapper.msRequestFullscreen) {
await chartWrapper.msRequestFullscreen();
}
} else {
//
// Exit Fullscreen
if (doc.exitFullscreen) {
await doc.exitFullscreen();
} else if (doc.webkitExitFullscreen) {
await doc.webkitExitFullscreen();
} else if (doc.mozCancelFullScreen) {
await doc.mozCancelFullScreen();
} else if (doc.msExitFullscreen) {
await doc.msExitFullscreen();
}
}
}
//#endregion
@@ -2075,6 +2045,42 @@ export class XChartComponent extends XChartContainerComponent {
this.chartInstance = null;
}
private registerResizeHandler() {
//
fromEvent(window, 'resize')
.pipe(
debounceTime(200),
takeUntil(this.RESIZE_SUBJECT)
)
.subscribe(() => {
//
if (isNullOrUndefined(this.chartInstance) || isNullOrUndefined(this.chartCard) || isNullOrUndefined(this.chartCard.nativeElement) || !this.chartCard.nativeElement.isFullscreen) {
return;
}
//
var height = this.chartCard.nativeElement.calculateContentSize();
//
// Reading Height ...
this.CHART_OPTIONS = {
...this.CHART_OPTIONS,
chart: {
height: `${height}px`
}
};
//
// TODO:
// Only Apply when Full Screen Mode ...
// Add FullScreen Event Handler in XCard Component ...
console.log('chart resize: ', height);
//
this.chartInstance.updateOptions(this.CHART_OPTIONS, false, false);
});
}
private registerActionProvider() {
//
this.unregisterActionProvider();