7 Commits
8 changed files with 1567 additions and 340 deletions
@@ -0,0 +1,4 @@
export interface XSizeModel {
width?: number;
height?: number;
}
@@ -9,7 +9,7 @@
[class.fullscreen]="getValue(isFullscreen) | async" [class.fullscreen]="getValue(isFullscreen) | async"
> >
<!-- Card Header --> <!-- 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 --> <!-- Avatar Image -->
<section <section
*ngIf="notEmptyValue(avatarUrl) | async" *ngIf="notEmptyValue(avatarUrl) | async"
@@ -57,6 +57,7 @@
<!-- Card Image --> <!-- Card Image -->
<img <img
mat-card-image mat-card-image
#cardImage
class="x-image" class="x-image"
[src]="getValue(imageUrl) | async" [src]="getValue(imageUrl) | async"
*ngIf="notEmptyValue(imageUrl) | async" *ngIf="notEmptyValue(imageUrl) | async"
@@ -64,18 +65,18 @@
/> />
<!-- Card Content --> <!-- 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> <ng-content></ng-content>
</mat-card-content> </mat-card-content>
<!-- Card Actions --> <!-- 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> <ng-content select="[actions]"></ng-content>
</mat-card-actions> </mat-card-actions>
<!-- Card Footer --> <!-- Card Footer -->
<mat-card-footer <mat-card-footer
#footer #cardFooter
class="x-footer" class="x-footer"
*ngIf="getValue(showFooter) | async" *ngIf="getValue(showFooter) | async"
> >
@@ -19,7 +19,6 @@
&:fullscreen { &:fullscreen {
border-radius: 0; border-radius: 0;
background-color: var(--full-screen-bg, #ffffff);
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
@@ -54,7 +53,7 @@
height: var(--height, inherit); height: var(--height, inherit);
} }
.x-card.page-card { .x-card.page-card:not(.fullscreen) {
@include push-auto(); @include push-auto();
@include applyWidthHeight(); @include applyWidthHeight();
@include m-tb($d-l); @include m-tb($d-l);
@@ -5,8 +5,18 @@ import {
} from './x-card.typings'; } from './x-card.typings';
import { Subject, Subscription } from 'rxjs'; import { Subject, Subscription } from 'rxjs';
import { concatMap, map } from 'rxjs/operators'; import { concatMap, map } from 'rxjs/operators';
import { nameof, isNullOrEmptyString } from 'x-framework-core'; import { XSizeModel } from '../classes/x-size.model.';
import { Component, ChangeDetectionStrategy } from '@angular/core'; import {
nameof,
isNullOrEmptyString,
isNullOrUndefined,
} from 'x-framework-core';
import {
Component,
ChangeDetectionStrategy,
ElementRef,
ViewChild,
} from '@angular/core';
@Component({ @Component({
// tslint:disable-next-line:component-selector // tslint:disable-next-line:component-selector
@@ -22,22 +32,107 @@ export class XCardComponent extends XCardContainerComponent {
private ACTION_PROVIDER_SUBSCRIPTION: Subscription; private ACTION_PROVIDER_SUBSCRIPTION: Subscription;
// //
// Full Screen ... //#region Card Elements ....
private IS_FULLSCREEN: boolean = false; private CARD_IMAGE: ElementRef<HTMLElement> = undefined;
public set isFullscreen(v: boolean) { private CARD_HEADER: ElementRef<HTMLElement> = undefined;
// private CARD_FOOTER: ElementRef<HTMLElement> = undefined;
const isChanged = v != this.IS_FULLSCREEN; private CARD_CONTENT: ElementRef<HTMLElement> = undefined;
private CARD_ACTIONS: ElementRef<HTMLElement> = undefined;
// @ViewChild('cardImage', { static: false })
this.IS_FULLSCREEN = v; set cardImage(v: ElementRef<HTMLElement>) {
this.CARD_IMAGE = v;
} }
public get isFullscreen() {
return this.IS_FULLSCREEN; @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 //#endregion
//
//#region Full Screen ...
//
private IS_FULLSCREEN: boolean = false;
set isFullscreen(v: boolean) {
//
const isChanged = v != this.IS_FULLSCREEN;
if (isChanged) {
//
this.actionProvider.next({
action: XCardAction.FullScreenToggled,
payload: v,
});
}
//
this.IS_FULLSCREEN = v;
}
get isFullscreen() {
return this.IS_FULLSCREEN;
}
//#endregion
//#endregion
// //
//#region LifeCycles ... //#region LifeCycles ...
onInit() {
super.onInit();
//
// Listen for fullscreen change events (handles ESC key and browser UI)
document.addEventListener('fullscreenchange', this.fullscreenChangeHandler);
document.addEventListener(
'webkitfullscreenchange',
this.fullscreenChangeHandler,
);
document.addEventListener(
'mozfullscreenchange',
this.fullscreenChangeHandler,
);
document.addEventListener(
'MSFullscreenChange',
this.fullscreenChangeHandler,
);
}
onChange(changeKeys: string[]) { onChange(changeKeys: string[]) {
super.onChange(changeKeys); super.onChange(changeKeys);
@@ -58,6 +153,24 @@ export class XCardComponent extends XCardContainerComponent {
// //
this.unregisterActionProvider(); this.unregisterActionProvider();
//
document.removeEventListener(
'fullscreenchange',
this.fullscreenChangeHandler,
);
document.removeEventListener(
'webkitfullscreenchange',
this.fullscreenChangeHandler,
);
document.removeEventListener(
'mozfullscreenchange',
this.fullscreenChangeHandler,
);
document.removeEventListener(
'MSFullscreenChange',
this.fullscreenChangeHandler,
);
} }
registerViewHandlers() { registerViewHandlers() {
@@ -149,6 +262,124 @@ export class XCardComponent extends XCardContainerComponent {
await this.enterFullscreen(); 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 //#endregion
// //
@@ -211,6 +442,22 @@ export class XCardComponent extends XCardContainerComponent {
} }
//#endregion //#endregion
//
//#region Fullscreen ...
private fullscreenChangeHandler = () => {
//
const isFullscreen = !!(
document.fullscreenElement ||
(document as any).webkitFullscreenElement ||
(document as any).mozFullScreenElement ||
(document as any).msFullscreenElement
);
//
this.isFullscreen = isFullscreen;
this.detectChanges();
};
private canUseFullscreen(): boolean { private canUseFullscreen(): boolean {
return !!( return !!(
document.fullscreenEnabled || document.fullscreenEnabled ||
@@ -220,4 +467,5 @@ export class XCardComponent extends XCardContainerComponent {
); );
} }
//#endregion //#endregion
//#endregion
} }
@@ -33,16 +33,19 @@ import { X_FRAMEWORK_COMPONENTS_CONFIG } from '../tokens/x-injectable-tokens';
import { XFrameworkComponentsConfig } from '../config/x-framework-components.config'; import { XFrameworkComponentsConfig } from '../config/x-framework-components.config';
export enum XCardAction { export enum XCardAction {
//
Refresh = 'refresh', Refresh = 'refresh',
//
ExitFullScreen = 'exit_full_screen', ExitFullScreen = 'exit_full_screen',
EnterFullScreen = 'enter_full_screen', EnterFullScreen = 'enter_full_screen',
ToggleFullScreen = 'toggle_full_screen', ToggleFullScreen = 'toggle_full_screen',
//
FullScreenToggled = 'full_screen_toggled',
} }
export type XCardActionIdentifier = XCardAction | string; export type XCardActionIdentifier = XCardAction | string;
export interface XCardActionModel export interface XCardActionModel extends XBaseActionModel<XCardActionIdentifier> {}
extends XBaseActionModel<XCardActionIdentifier> {}
// //
//#region Container ... //#region Container ...
@@ -190,7 +193,7 @@ export abstract class XCardContainerComponent
public ruler: ViewportRuler, public ruler: ViewportRuler,
public zone: NgZone, public zone: NgZone,
public changeDetector: ChangeDetectorRef, public changeDetector: ChangeDetectorRef,
protected propertyProvider: XCardContainer protected propertyProvider: XCardContainer,
) { ) {
super( super(
config, config,
@@ -199,7 +202,7 @@ export abstract class XCardContainerComponent
renderer, renderer,
ruler, ruler,
zone, zone,
changeDetector changeDetector,
); );
} }
//#endregion //#endregion
@@ -207,37 +210,37 @@ export abstract class XCardContainerComponent
// //
//#region Abstract ... //#region Abstract ...
public extractProps( public extractProps(
container?: IXCardContainer container?: IXCardContainer,
): Observable<IXCardContainer> { ): Observable<IXCardContainer> {
return forkJoin({ return forkJoin({
// //
cssClass: this.getArrayValue( cssClass: this.getArrayValue(
container ? container.cssClass : this.cssClass container ? container.cssClass : this.cssClass,
), ),
// //
color: this.getValue(container ? container.color : this.color), color: this.getValue(container ? container.color : this.color),
foregroundColor: this.getValue( foregroundColor: this.getValue(
container ? container.foregroundColor : this.foregroundColor container ? container.foregroundColor : this.foregroundColor,
), ),
// //
showHeader: this.getValue( showHeader: this.getValue(
container ? container.showHeader : this.showHeader container ? container.showHeader : this.showHeader,
), ),
title: this.getValue(container ? container.title : this.title), title: this.getValue(container ? container.title : this.title),
subTitle: this.getValue(container ? container.subTitle : this.subTitle), subTitle: this.getValue(container ? container.subTitle : this.subTitle),
avatarUrl: this.getValue( avatarUrl: this.getValue(
container ? container.avatarUrl : this.avatarUrl container ? container.avatarUrl : this.avatarUrl,
), ),
avatarTemplate: this.getValue( avatarTemplate: this.getValue(
container ? container.avatarTemplate : this.avatarTemplate container ? container.avatarTemplate : this.avatarTemplate,
), ),
// //
imageUrl: this.getValue(container ? container.imageUrl : this.imageUrl), imageUrl: this.getValue(container ? container.imageUrl : this.imageUrl),
imageDescription: this.getValue( imageDescription: this.getValue(
container ? container.imageDescription : this.imageDescription container ? container.imageDescription : this.imageDescription,
), ),
// //
@@ -245,13 +248,13 @@ export abstract class XCardContainerComponent
// //
showContent: this.getValue( showContent: this.getValue(
container ? container.showContent : this.showContent container ? container.showContent : this.showContent,
), ),
showActions: this.getValue( showActions: this.getValue(
container ? container.showActions : this.showActions container ? container.showActions : this.showActions,
), ),
showFooter: this.getValue( showFooter: this.getValue(
container ? container.showFooter : this.showFooter container ? container.showFooter : this.showFooter,
), ),
}).pipe( }).pipe(
map((data) => { map((data) => {
@@ -264,7 +267,7 @@ export abstract class XCardContainerComponent
? container.actionProvider ? container.actionProvider
: this.actionProvider, : this.actionProvider,
}; };
}) }),
); );
} }
//#endregion //#endregion
@@ -288,8 +291,7 @@ type TXComponentCardContainer = {
}; };
export interface IXComponentCardContainer export interface IXComponentCardContainer
extends TXComponentCardContainer, extends TXComponentCardContainer, IXBaseComponentContainer {
IXBaseComponentContainer {
isInPage: XStandardType<boolean>; isInPage: XStandardType<boolean>;
wrapWithCard: XStandardType<boolean>; wrapWithCard: XStandardType<boolean>;
} }
@@ -403,7 +405,7 @@ export abstract class XComponentCardContainerComponent
public ruler: ViewportRuler, public ruler: ViewportRuler,
public zone: NgZone, public zone: NgZone,
public changeDetector: ChangeDetectorRef, public changeDetector: ChangeDetectorRef,
protected propertyProvider: XComponentCardContainer protected propertyProvider: XComponentCardContainer,
) { ) {
super( super(
config, config,
@@ -412,7 +414,7 @@ export abstract class XComponentCardContainerComponent
renderer, renderer,
ruler, ruler,
zone, zone,
changeDetector changeDetector,
); );
} }
//#endregion //#endregion
@@ -420,34 +422,34 @@ export abstract class XComponentCardContainerComponent
// //
//#region Abstract ... //#region Abstract ...
public extractProps( public extractProps(
container?: IXComponentCardContainer container?: IXComponentCardContainer,
): Observable<IXComponentCardContainer> { ): Observable<IXComponentCardContainer> {
return forkJoin({ return forkJoin({
// //
isInPage: this.getValue(container ? container.isInPage : this.isInPage), isInPage: this.getValue(container ? container.isInPage : this.isInPage),
wrapWithCard: this.getValue( wrapWithCard: this.getValue(
container ? container.wrapWithCard : this.wrapWithCard container ? container.wrapWithCard : this.wrapWithCard,
), ),
cardCssClass: this.getValue( cardCssClass: this.getValue(
container ? container.cardCssClass : this.cardCssClass container ? container.cardCssClass : this.cardCssClass,
), ),
cardColor: this.getValue( cardColor: this.getValue(
container ? container.cardColor : this.cardColor container ? container.cardColor : this.cardColor,
), ),
cardForegroundColor: this.getValue( cardForegroundColor: this.getValue(
container ? container.cardForegroundColor : this.cardForegroundColor container ? container.cardForegroundColor : this.cardForegroundColor,
), ),
cardTitle: this.getValue( cardTitle: this.getValue(
container ? container.cardTitle : this.cardTitle container ? container.cardTitle : this.cardTitle,
), ),
cardSubTitle: this.getValue( cardSubTitle: this.getValue(
container ? container.cardSubTitle : this.cardSubTitle container ? container.cardSubTitle : this.cardSubTitle,
), ),
cardShowFooter: this.getValue( cardShowFooter: this.getValue(
container ? container.cardShowFooter : this.cardShowFooter container ? container.cardShowFooter : this.cardShowFooter,
), ),
cardShowActions: this.getValue( cardShowActions: this.getValue(
container ? container.cardShowActions : this.cardShowActions container ? container.cardShowActions : this.cardShowActions,
), ),
}).pipe( }).pipe(
map((data) => { map((data) => {
@@ -460,7 +462,7 @@ export abstract class XComponentCardContainerComponent
? container.cardActionProvider ? container.cardActionProvider
: this.cardActionProvider, : this.cardActionProvider,
}; };
}) }),
); );
} }
//#endregion //#endregion
@@ -1,8 +1,10 @@
<!-- Component Template --> <!-- Component Template -->
<ng-container *ngIf="getValue(wrapWithCard) | async; else componentsRef"> <ng-container *ngIf="getValue(wrapWithCard) | async; else componentsRef">
<x-card <x-card
#chartCard
class="x-card" class="x-card"
[showActions]="true" [showActions]="true"
[actionProvider]="cardActionProvider"
[color]="getValue(cardColor) | async" [color]="getValue(cardColor) | async"
[ngClass]="getValue(cssClass) | async" [ngClass]="getValue(cssClass) | async"
[isInPage]="getValue(isInPage) | async" [isInPage]="getValue(isInPage) | async"
@@ -41,6 +43,7 @@
> >
<!-- Toolbar --> <!-- Toolbar -->
<x-action-bar <x-action-bar
#chartActionBar
[color]="actionBarColor" [color]="actionBarColor"
[cssClass]="actionBarCssClass" [cssClass]="actionBarCssClass"
[actionProvider]="actionBarActionProvider" [actionProvider]="actionBarActionProvider"
File diff suppressed because it is too large Load Diff
@@ -13,6 +13,7 @@ import {
import { import {
XStandardType, XStandardType,
isValueInEnum, isValueInEnum,
getXColorValue,
XOneOrManyType, XOneOrManyType,
XColorIdentifier, XColorIdentifier,
XResourceIdentifier, XResourceIdentifier,
@@ -101,6 +102,41 @@ export type XChartXAxisAnnotations = XCahrtAxisBaseAnnotations & {
x2?: null | number | string; x2?: null | number | string;
}; };
export type XChartMarkerAnnotations = {
size?: number;
fillColor?: string;
strokeColor?: string;
strokeWidth?: number;
shape?: string;
offsetX?: number;
offsetY?: number;
cssClass?: string;
};
export type XChartTooltipAnnotations = {
enabled?: boolean;
/**
* Static tooltip content (HTML allowed; an array is joined with line
* breaks). Falls back to `label.text` when omitted.
*/
text?: string | string[];
/**
* Returns the tooltip markup (HTML). Takes precedence over `text`.
*/
formatter?: (opts: {
annotation: XChartPointAnnotations;
seriesIndex?: number;
id?: number | string;
w: any;
}) => string;
/**
* Tooltip theme. Falls back to the global `tooltip.theme`.
*/
theme?: 'light' | 'dark';
offsetX?: number;
offsetY?: number;
};
export type XChartPointAnnotations = { export type XChartPointAnnotations = {
id?: number | string; id?: number | string;
x?: number | string; x?: number | string;
@@ -115,16 +151,7 @@ export type XChartPointAnnotations = {
mouseEnter?: (annotation: XChartPointAnnotations, e: MouseEvent) => void; mouseEnter?: (annotation: XChartPointAnnotations, e: MouseEvent) => void;
mouseLeave?: (annotation: XChartPointAnnotations, e: MouseEvent) => void; mouseLeave?: (annotation: XChartPointAnnotations, e: MouseEvent) => void;
click?: (annotation: XChartPointAnnotations, e: MouseEvent) => void; click?: (annotation: XChartPointAnnotations, e: MouseEvent) => void;
marker?: { marker?: XChartMarkerAnnotations;
size?: number;
fillColor?: string;
strokeColor?: string;
strokeWidth?: number;
shape?: string;
offsetX?: number;
offsetY?: number;
cssClass?: string;
};
label?: XChartAnnotationLabel; label?: XChartAnnotationLabel;
image?: { image?: {
path?: string; path?: string;
@@ -137,29 +164,7 @@ export type XChartPointAnnotations = {
* Show a hover tooltip over the annotation marker, like a regular data * Show a hover tooltip over the annotation marker, like a regular data
* point. Useful for surfacing more detail than fits in the label. * point. Useful for surfacing more detail than fits in the label.
*/ */
tooltip?: { tooltip?: XChartTooltipAnnotations;
enabled?: boolean;
/**
* Static tooltip content (HTML allowed; an array is joined with line
* breaks). Falls back to `label.text` when omitted.
*/
text?: string | string[];
/**
* Returns the tooltip markup (HTML). Takes precedence over `text`.
*/
formatter?: (opts: {
annotation: XChartPointAnnotations;
seriesIndex?: number;
id?: number | string;
w: any;
}) => string;
/**
* Tooltip theme. Falls back to the global `tooltip.theme`.
*/
theme?: 'light' | 'dark';
offsetX?: number;
offsetY?: number;
};
/** /**
* Render arbitrary SVG markup at the annotation's position. Deprecated in * Render arbitrary SVG markup at the annotation's position. Deprecated in
* favor of `image`/`marker`, but still supported. * favor of `image`/`marker`, but still supported.
@@ -370,71 +375,71 @@ export type XChartAxisChartSeries = {
zIndex?: number; zIndex?: number;
parsing?: XChartParsing; parsing?: XChartParsing;
data: data:
| (number | null)[] | (number | null)[]
| { | {
/** /**
* A category label, a timestamp, or a `Date`. On a `datetime` axis all * A category label, a timestamp, or a `Date`. On a `datetime` axis all
* three keep millisecond resolution. * three keep millisecond resolution.
*/ */
x: string | number | Date; x: string | number | Date;
/** /**
* A plain value for most charts. For `candlestick`/`boxPlot`, the * A plain value for most charts. For `candlestick`/`boxPlot`, the
* summary array (`[O,H,L,C]` / `[min,Q1,median,Q3,max]`). For `violin`, an * summary array (`[O,H,L,C]` / `[min,Q1,median,Q3,max]`). For `violin`, an
* object carrying the precomputed density profile (`[value, weight]` pairs) * object carrying the precomputed density profile (`[value, weight]` pairs)
* plus the raw observations rendered as jitter. For a `scatter` strip plot * plus the raw observations rendered as jitter. For a `scatter` strip plot
* (`plotOptions.scatter.jitter`), the array of observations in this category. * (`plotOptions.scatter.jitter`), the array of observations in this category.
*/ */
y: y:
| number | number
| null | null
| number[] | number[]
| { density: [number, number][]; points?: number[] }; | { density: [number, number][]; points?: number[] };
/** /**
* Optional raw observations for a `boxPlot` data point, rendered as jitter * Optional raw observations for a `boxPlot` data point, rendered as jitter
* dots when `plotOptions.boxPlot.points.show` is enabled. * dots when `plotOptions.boxPlot.points.show` is enabled.
*/ */
points?: number[]; points?: number[];
fill?: XChartFill; fill?: XChartFill;
fillColor?: string; fillColor?: string;
strokeColor?: string; strokeColor?: string;
meta?: unknown; meta?: unknown;
/** /**
* A second metric that drives this point's COLOUR, independent of `y` * A second metric that drives this point's COLOUR, independent of `y`
* which drives its size (`treemap`). See * which drives its size (`treemap`). See
* `plotOptions.treemap.colorScale.colorValue` to read a different key. * `plotOptions.treemap.colorScale.colorValue` to read a different key.
*/ */
colorValue?: number; colorValue?: number;
/** /**
* Nested hierarchy: this point is a branch containing these children, * Nested hierarchy: this point is a branch containing these children,
* to any depth (`treemap`, `sunburst`). A branch normally omits `y` and * to any depth (`treemap`, `sunburst`). A branch normally omits `y` and
* takes the sum of its children instead. * takes the sum of its children instead.
*/ */
children?: XChartHierarchyNode[]; children?: XChartHierarchyNode[];
/** /**
* Drilldown target: the `id` of a `drilldown.series` entry. Clicking this * Drilldown target: the `id` of a `drilldown.series` entry. Clicking this
* point drills into that level. Requires the Drilldown feature. * point drills into that level. Requires the Drilldown feature.
*/ */
drilldown?: string | number; drilldown?: string | number;
goals?: { goals?: {
name?: string; name?: string;
value: number; value: number;
strokeHeight?: number; strokeHeight?: number;
strokeWidth?: number; strokeWidth?: number;
strokeColor?: string; strokeColor?: string;
strokeDashArray?: number; strokeDashArray?: number;
strokeLineCap?: 'butt' | 'square' | 'round'; strokeLineCap?: 'butt' | 'square' | 'round';
}[]; }[];
barHeightOffset?: number; barHeightOffset?: number;
columnWidthOffset?: number; columnWidthOffset?: number;
}[] }[]
| [number, number | null][] | [number, number | null][]
| [number, (number | null)[]][] | [number, (number | null)[]][]
| number[][] | number[][]
// A `children` hierarchy for the partition charts, where a branch carries no // A `children` hierarchy for the partition charts, where a branch carries no
// value of its own. Listed before the catch-all so authors get completion on // value of its own. Listed before the catch-all so authors get completion on
// the node shape instead of falling through to `Record<string, any>`. // the node shape instead of falling through to `Record<string, any>`.
| XChartHierarchyNode[] | XChartHierarchyNode[]
| Record<string, any>[]; | Record<string, any>[];
}[]; }[];
export type XChartNonAxisChartSeries = number[] | XChartAxisChartSeries; export type XChartNonAxisChartSeries = number[] | XChartAxisChartSeries;
@@ -931,11 +936,11 @@ export type XChartPlotOptions = {
* property, or an accessor to compute one. * property, or an accessor to compute one.
*/ */
colorValue?: colorValue?:
| string | string
| (( | ((
datum: any, datum: any,
opts: { seriesIndex: number; dataPointIndex: number; w: any }, opts: { seriesIndex: number; dataPointIndex: number; w: any },
) => number); ) => number);
/** /**
* Continuous interpolation between colour stops, for the metric above. * Continuous interpolation between colour stops, for the metric above.
* Active as soon as any datum carries a colour metric; `enabled: false` * Active as soon as any datum carries a colour metric; `enabled: false`
@@ -1068,13 +1073,13 @@ export type XChartPlotOptions = {
* 'custom': positions come from `positions`. * 'custom': positions come from `positions`.
*/ */
layout?: layout?:
| 'grouped' | 'grouped'
| 'packed' | 'packed'
| 'columns' | 'columns'
| 'grid' | 'grid'
| 'scatter' | 'scatter'
| 'arc' | 'arc'
| 'custom'; | 'custom';
/** /**
* `layout: 'custom'` only. The layout provider: either a function returning * `layout: 'custom'` only. The layout provider: either a function returning
* plot-pixel positions, or the name of one registered with * plot-pixel positions, or the name of one registered with
@@ -2102,19 +2107,19 @@ export interface XChartDrilldown {
/** Inline child levels referenced by data-point `drilldown` ids. */ /** Inline child levels referenced by data-point `drilldown` ids. */
series?: XChartDrilldownSeries[]; series?: XChartDrilldownSeries[];
breadcrumb?: breadcrumb?:
| false | false
| { | {
show?: boolean; show?: boolean;
position?: 'top-left' | 'top-right'; position?: 'top-left' | 'top-right';
separator?: string; separator?: string;
rootLabel?: string; rootLabel?: string;
offsetX?: number; offsetX?: number;
offsetY?: number; offsetY?: number;
formatter?( formatter?(
label: string, label: string,
opts: { index: number; depth: number }, opts: { index: number; depth: number },
): string; ): string;
}; };
animation?: { animation?: {
enabled?: boolean; enabled?: boolean;
/** /**
@@ -2163,11 +2168,11 @@ export interface XChartDrilldown {
* name, so the default ships no user-visible English. * name, so the default ships no user-visible English.
*/ */
loading?: loading?:
| false | false
| { | {
show?: boolean; show?: boolean;
text?: string; text?: string;
}; };
/** /**
* Cache levels resolved by `onDrillDown`, keyed by id, so drilling back down * Cache levels resolved by `onDrillDown`, keyed by id, so drilling back down
* a branch does not re-fetch. Default true. Clear it with the drilldown * a branch does not re-fetch. Default true. Clear it with the drilldown
@@ -2273,12 +2278,12 @@ export type XChartStates = {
export type XChartStroke = { export type XChartStroke = {
show?: boolean; show?: boolean;
curve?: curve?:
| 'smooth' | 'smooth'
| 'straight' | 'straight'
| 'stepline' | 'stepline'
| 'linestep' | 'linestep'
| 'monotoneCubic' | 'monotoneCubic'
| ('smooth' | 'straight' | 'stepline' | 'linestep' | 'monotoneCubic')[]; | ('smooth' | 'straight' | 'stepline' | 'linestep' | 'monotoneCubic')[];
lineCap?: 'butt' | 'square' | 'round'; lineCap?: 'butt' | 'square' | 'round';
colors?: string[]; colors?: string[];
width?: number | number[]; width?: number | number[];
@@ -2329,11 +2334,11 @@ export type XChartTheme = {
}; };
accessibility?: { accessibility?: {
colorBlindMode?: colorBlindMode?:
| 'deuteranopia' | 'deuteranopia'
| 'protanopia' | 'protanopia'
| 'tritanopia' | 'tritanopia'
| 'highContrast' | 'highContrast'
| ''; | '';
}; };
}; };
@@ -2362,14 +2367,14 @@ export type XChartTooltip = {
inverseOrder?: boolean; inverseOrder?: boolean;
arrow?: boolean; arrow?: boolean;
custom?: custom?:
| (( | ((
opts: XChartTooltipCustomOpts, opts: XChartTooltipCustomOpts,
) => string | number | Element | { nodeName: string }) ) => string | number | Element | { nodeName: string })
| Array< | Array<
( (
opts: XChartTooltipCustomOpts, opts: XChartTooltipCustomOpts,
) => string | number | Element | { nodeName: string } ) => string | number | Element | { nodeName: string }
>; >;
fillSeriesColor?: boolean; fillSeriesColor?: boolean;
theme?: 'light' | 'dark'; theme?: 'light' | 'dark';
cssClass?: string; cssClass?: string;
@@ -2407,6 +2412,8 @@ export type XChartTooltip = {
}; };
}; };
export type XChartColorType = Array<string | ((opts: XChartColorFormatterOpts) => string)>;
export interface XChartOptions { export interface XChartOptions {
annotations?: XChartAnnotations; annotations?: XChartAnnotations;
chart?: XChart; chart?: XChart;
@@ -2415,7 +2422,7 @@ export interface XChartOptions {
* named) or a function returning one per-datapoint. The list cycles when * named) or a function returning one per-datapoint. The list cycles when
* there are more series than colors. * there are more series than colors.
*/ */
colors?: Array<string | ((opts: XChartColorFormatterOpts) => string)>; colors?: XChartColorType;
dataLabels?: XChartDataLabels; dataLabels?: XChartDataLabels;
/** Opt-in drilldown navigation. Requires `import 'apexcharts/features/drilldown'`. */ /** Opt-in drilldown navigation. Requires `import 'apexcharts/features/drilldown'`. */
drilldown?: XChartDrilldown; drilldown?: XChartDrilldown;
@@ -2446,30 +2453,30 @@ export type XChart = {
width?: string | number; width?: string | number;
height?: string | number; height?: string | number;
type?: type?:
| 'line' | 'line'
| 'area' | 'area'
| 'bar' | 'bar'
| 'pie' | 'pie'
| 'donut' | 'donut'
| 'radialBar' | 'radialBar'
| 'scatter' | 'scatter'
| 'bubble' | 'bubble'
| 'heatmap' | 'heatmap'
| 'candlestick' | 'candlestick'
| 'boxPlot' | 'boxPlot'
| 'violin' | 'violin'
| 'histogram' | 'histogram'
| 'radar' | 'radar'
| 'polarArea' | 'polarArea'
| 'rangeBar' | 'rangeBar'
| 'rangeArea' | 'rangeArea'
| 'treemap' | 'treemap'
| 'unit' | 'unit'
| 'waffle' | 'waffle'
| 'sunburst' | 'sunburst'
| 'funnel' | 'funnel'
| 'pyramid' | 'pyramid'
| 'gauge'; | 'gauge';
/** /**
* Internal — populated when `type` is a first-class alias (`'funnel'`, * Internal — populated when `type` is a first-class alias (`'funnel'`,
* `'pyramid'`, `'gauge'`, `'waffle'`, `'histogram'`). The original requested * `'pyramid'`, `'gauge'`, `'waffle'`, `'histogram'`). The original requested
@@ -2752,9 +2759,9 @@ export type XChart = {
dimension?: (row: any) => any; dimension?: (row: any) => any;
/** FILTER mode: reduction over a bucket's rows. @default 'count' */ /** FILTER mode: reduction over a bucket's rows. @default 'count' */
reduce?: reduce?:
| 'count' | 'count'
| { sum?: string; avg?: string; min?: string; max?: string } | { sum?: string; avg?: string; min?: string; max?: string }
| ((rows: any[]) => number); | ((rows: any[]) => number);
/** /**
* FILTER mode: bucket kind. Else inferred: `bins` present => 'range', a * FILTER mode: bucket kind. Else inferred: `bins` present => 'range', a
* heatmap chart => 'matrix' (2D), otherwise 'category'. * heatmap chart => 'matrix' (2D), otherwise 'category'.
@@ -2872,21 +2879,21 @@ export type XChart = {
| 'yline' | 'yline'
| 'measure' | 'measure'
| { | {
id?: string; id?: string;
label?: string; label?: string;
icon?: string; icon?: string;
onClick?: ( onClick?: (
chart: ApexCharts, chart: ApexCharts,
context: { context: {
x: any; x: any;
y: any; y: any;
seriesIndex: number | null; seriesIndex: number | null;
dataPointIndex: number | null; dataPointIndex: number | null;
clientX: number; clientX: number;
clientY: number; clientY: number;
}, },
) => void; ) => void;
} }
>; >;
/** Override the built-in item labels. */ /** Override the built-in item labels. */
labels?: { labels?: {
@@ -3225,7 +3232,7 @@ export enum XChartAction {
export type XChartActionIdentifier = XChartAction | string; export type XChartActionIdentifier = XChartAction | string;
export interface XChartActionModel extends XBaseActionModel<XChartActionIdentifier> {} export interface XChartActionModel extends XBaseActionModel<XChartActionIdentifier> { }
export type XChartSeriesType = XChartAxisChartSeries | XChartNonAxisChartSeries; export type XChartSeriesType = XChartAxisChartSeries | XChartNonAxisChartSeries;
@@ -3323,6 +3330,18 @@ export interface IXChartContainer extends TXChartContainer {
series: XStandardType<XChartSeriesType>; series: XStandardType<XChartSeriesType>;
type: XStandardType<XChartTypeIdentifier>; type: XStandardType<XChartTypeIdentifier>;
//
stroke: XStandardType<XChartStroke>;
colors: XStandardType<XChartColorType>;
//
xAxis: XStandardType<XChartXAxis>;
yAxis: XStandardType<XOneOrManyType<XChartYAxis>>;
//
tooltip: XStandardType<XChartTooltip>;
annotations: XStandardType<XChartAnnotations>;
// //
title: XStandardType<XResourceIdentifier>; title: XStandardType<XResourceIdentifier>;
titleAlign: XStandardType<XChartTextAlignIdentifier>; titleAlign: XStandardType<XChartTextAlignIdentifier>;
@@ -3460,8 +3479,7 @@ export interface IXChartContainer extends TXChartContainer {
}) })
export class XChartContainer export class XChartContainer
extends XBaseContainer extends XBaseContainer
implements Readonly<IXChartContainer> implements Readonly<IXChartContainer> {
{
// //
readonly actionProvider = new Subject<XChartActionModel>(); readonly actionProvider = new Subject<XChartActionModel>();
readonly cssClass: XStandardType<XOneOrManyType<string>>; readonly cssClass: XStandardType<XOneOrManyType<string>>;
@@ -3471,7 +3489,22 @@ export class XChartContainer
readonly options: XStandardType<XChartOptions>; readonly options: XStandardType<XChartOptions>;
readonly zoomStep: XStandardType<number> = 0.125; readonly zoomStep: XStandardType<number> = 0.125;
readonly series: XStandardType<XChartSeriesType>; readonly series: XStandardType<XChartSeriesType>;
//
readonly stroke: XStandardType<XChartStroke> = {
width: 3,
curve: 'smooth'
};
readonly type: XStandardType<XChartTypeIdentifier> = XChartType.Line; readonly type: XStandardType<XChartTypeIdentifier> = XChartType.Line;
readonly colors: XStandardType<XChartColorType> = [getXColorValue(XColorWithBrightness.PrimaryShade)];
//
readonly xAxis: XStandardType<XChartXAxis>;
readonly yAxis: XStandardType<XOneOrManyType<XChartYAxis>>;
//
readonly tooltip: XStandardType<XChartTooltip>;
readonly annotations: XStandardType<XChartAnnotations>;
// //
readonly title: XStandardType<XResourceIdentifier>; readonly title: XStandardType<XResourceIdentifier>;
@@ -3671,8 +3704,7 @@ export class XChartContainer
@Component({ template: `` }) @Component({ template: `` })
export abstract class XChartContainerComponent export abstract class XChartContainerComponent
extends XBaseContainerComponent extends XBaseContainerComponent
implements IXChartContainer implements IXChartContainer {
{
// //
//#region Props ... //#region Props ...
@Input() @Input()
@@ -3698,6 +3730,24 @@ export abstract class XChartContainerComponent
@Input() @Input()
zoomStep: XStandardType<number> = this.propertyProvider.zoomStep; zoomStep: XStandardType<number> = this.propertyProvider.zoomStep;
@Input()
xAxis: XStandardType<XChartXAxis> = this.propertyProvider.xAxis;
@Input()
yAxis: XStandardType<XOneOrManyType<XChartYAxis>> = this.propertyProvider.yAxis;
@Input()
colors: XStandardType<XChartColorType> = this.propertyProvider.colors;
@Input()
stroke: XStandardType<XChartStroke> = this.propertyProvider.stroke;
@Input()
tooltip: XStandardType<XChartTooltip> = this.propertyProvider.tooltip;
@Input()
annotations: XStandardType<XChartAnnotations> = this.propertyProvider.annotations;
@Input() @Input()
defaultActionBarItemColor: XStandardType<XColorIdentifier> = defaultActionBarItemColor: XStandardType<XColorIdentifier> =
this.propertyProvider.defaultActionBarItemColor; this.propertyProvider.defaultActionBarItemColor;
@@ -4030,10 +4080,22 @@ export abstract class XChartContainerComponent
// //
type: this.getValue(container ? container.type : this.type), type: this.getValue(container ? container.type : this.type),
options: this.getValue(container ? container.options : this.options),
series: this.getValue(container ? container.series : this.series), series: this.getValue(container ? container.series : this.series),
options: this.getValue(container ? container.options : this.options),
zoomStep: this.getValue(container ? container.zoomStep : this.zoomStep), zoomStep: this.getValue(container ? container.zoomStep : this.zoomStep),
//
stroke: this.getValue(container ? container.stroke : this.stroke),
colors: this.getArrayValue(container ? container.colors : this.colors),
//
xAxis: this.getValue(container ? container.xAxis : this.xAxis),
yAxis: this.getValue(container ? container.yAxis : this.yAxis),
//
tooltip: this.getValue(container ? container.tooltip : this.tooltip),
annotations: this.getValue(container ? container.annotations : this.annotations),
// //
title: this.getValue(container ? container.title : this.title), title: this.getValue(container ? container.title : this.title),
titleAlign: this.getValue( titleAlign: this.getValue(