integra-ng 20.1.8 → 20.1.10
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.
- package/fesm2022/integra-ng.mjs +785 -3
- package/fesm2022/integra-ng.mjs.map +1 -1
- package/index.d.ts +450 -2
- package/package.json +2 -1
package/fesm2022/integra-ng.mjs
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { EventEmitter, Output, Input, Component, ContentChildren, ElementRef, ViewChild, createComponent, Directive, Optional, Self, forwardRef, HostListener, ChangeDetectionStrategy, signal, inject, EnvironmentInjector, ApplicationRef, Injectable, input, computed, ViewEncapsulation } from '@angular/core';
|
|
2
|
+
import { EventEmitter, Output, Input, Component, ContentChildren, ElementRef, ViewChild, createComponent, Directive, Optional, Self, forwardRef, HostListener, ChangeDetectionStrategy, signal, inject, EnvironmentInjector, ApplicationRef, Injectable, input, computed, ViewEncapsulation, ViewChildren, Inject } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common';
|
|
4
|
-
import { NgClass, CommonModule, NgTemplateOutlet, NgIf, NgFor, NgStyle } from '@angular/common';
|
|
4
|
+
import { NgClass, CommonModule, NgTemplateOutlet, NgIf, NgFor, NgStyle, DOCUMENT } from '@angular/common';
|
|
5
5
|
import * as i2 from '@angular/forms';
|
|
6
6
|
import { FormsModule, NG_VALUE_ACCESSOR, NgControl } from '@angular/forms';
|
|
7
7
|
import { take } from 'rxjs/operators';
|
|
8
8
|
import { Subject, BehaviorSubject } from 'rxjs';
|
|
9
|
+
import { Chart, registerables } from 'chart.js';
|
|
10
|
+
import * as i1$1 from '@angular/platform-browser';
|
|
9
11
|
|
|
10
12
|
var lastId = 0;
|
|
11
13
|
function UniqueComponentId(prefix = 'i_id_') {
|
|
@@ -6806,6 +6808,434 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImpor
|
|
|
6806
6808
|
args: ['document:mouseup']
|
|
6807
6809
|
}] } });
|
|
6808
6810
|
|
|
6811
|
+
// Register all Chart.js components
|
|
6812
|
+
Chart.register(...registerables);
|
|
6813
|
+
/**
|
|
6814
|
+
* Chart Component
|
|
6815
|
+
*
|
|
6816
|
+
* A Chart.js-based chart component for displaying various chart types.
|
|
6817
|
+
* Supports multiple charts in a responsive grid layout.
|
|
6818
|
+
*
|
|
6819
|
+
* @example
|
|
6820
|
+
* ```html
|
|
6821
|
+
* <i-chart
|
|
6822
|
+
* [charts]="myCharts"
|
|
6823
|
+
* height="25rem">
|
|
6824
|
+
* </i-chart>
|
|
6825
|
+
* ```
|
|
6826
|
+
*
|
|
6827
|
+
* @example
|
|
6828
|
+
* ```typescript
|
|
6829
|
+
* myCharts: IChartData[] = [
|
|
6830
|
+
* {
|
|
6831
|
+
* chartId: 'sales-chart',
|
|
6832
|
+
* chartType: 'bar',
|
|
6833
|
+
* labels: ['Jan', 'Feb', 'Mar'],
|
|
6834
|
+
* dataSets: [{
|
|
6835
|
+
* label: 'Sales',
|
|
6836
|
+
* data: [100, 200, 150],
|
|
6837
|
+
* backgroundColors: ['--blue-500', '--green-500', '--orange-500']
|
|
6838
|
+
* }]
|
|
6839
|
+
* }
|
|
6840
|
+
* ];
|
|
6841
|
+
* ```
|
|
6842
|
+
*/
|
|
6843
|
+
class IChart {
|
|
6844
|
+
/**
|
|
6845
|
+
* Array of chart data objects to render
|
|
6846
|
+
*/
|
|
6847
|
+
charts = [];
|
|
6848
|
+
/**
|
|
6849
|
+
* Default height for charts
|
|
6850
|
+
* @default '20rem'
|
|
6851
|
+
*/
|
|
6852
|
+
height = '20rem';
|
|
6853
|
+
/**
|
|
6854
|
+
* Whether charts should be responsive
|
|
6855
|
+
* @default true
|
|
6856
|
+
*/
|
|
6857
|
+
responsive = true;
|
|
6858
|
+
/**
|
|
6859
|
+
* Reference to all canvas elements
|
|
6860
|
+
* @internal
|
|
6861
|
+
*/
|
|
6862
|
+
canvasElements;
|
|
6863
|
+
/**
|
|
6864
|
+
* Array of display configurations for each chart
|
|
6865
|
+
* @internal
|
|
6866
|
+
*/
|
|
6867
|
+
chartDisplays = [];
|
|
6868
|
+
/**
|
|
6869
|
+
* Chart.js instances for cleanup
|
|
6870
|
+
* @internal
|
|
6871
|
+
*/
|
|
6872
|
+
chartInstances = [];
|
|
6873
|
+
/**
|
|
6874
|
+
* Flag to track if component has initialized
|
|
6875
|
+
* @internal
|
|
6876
|
+
*/
|
|
6877
|
+
initialized = false;
|
|
6878
|
+
/**
|
|
6879
|
+
* Reference to pending animation frame for cleanup
|
|
6880
|
+
* @internal
|
|
6881
|
+
*/
|
|
6882
|
+
pendingAnimationFrame = null;
|
|
6883
|
+
ngAfterViewInit() {
|
|
6884
|
+
this.initialized = true;
|
|
6885
|
+
this.initializeCharts();
|
|
6886
|
+
}
|
|
6887
|
+
ngOnChanges(changes) {
|
|
6888
|
+
if (changes['charts'] && this.initialized) {
|
|
6889
|
+
this.destroyCharts();
|
|
6890
|
+
this.initializeCharts();
|
|
6891
|
+
}
|
|
6892
|
+
}
|
|
6893
|
+
ngOnDestroy() {
|
|
6894
|
+
this.cancelPendingInitialization();
|
|
6895
|
+
this.destroyCharts();
|
|
6896
|
+
}
|
|
6897
|
+
/**
|
|
6898
|
+
* Cancel any pending chart initialization
|
|
6899
|
+
* @internal
|
|
6900
|
+
*/
|
|
6901
|
+
cancelPendingInitialization() {
|
|
6902
|
+
if (this.pendingAnimationFrame !== null) {
|
|
6903
|
+
cancelAnimationFrame(this.pendingAnimationFrame);
|
|
6904
|
+
this.pendingAnimationFrame = null;
|
|
6905
|
+
}
|
|
6906
|
+
}
|
|
6907
|
+
/**
|
|
6908
|
+
* Initialize all charts
|
|
6909
|
+
* @internal
|
|
6910
|
+
*/
|
|
6911
|
+
initializeCharts() {
|
|
6912
|
+
this.chartDisplays = this.charts.map((chart) => this.transformToChartDisplay(chart));
|
|
6913
|
+
// Cancel any pending initialization
|
|
6914
|
+
this.cancelPendingInitialization();
|
|
6915
|
+
// Use requestAnimationFrame for proper timing after view update
|
|
6916
|
+
this.pendingAnimationFrame = requestAnimationFrame(() => {
|
|
6917
|
+
this.pendingAnimationFrame = null;
|
|
6918
|
+
this.canvasElements.forEach((canvasRef, index) => {
|
|
6919
|
+
const chartDisplay = this.chartDisplays[index];
|
|
6920
|
+
if (chartDisplay && canvasRef) {
|
|
6921
|
+
const chartInstance = this.createChartInstance(canvasRef.nativeElement, chartDisplay);
|
|
6922
|
+
this.chartInstances.push(chartInstance);
|
|
6923
|
+
}
|
|
6924
|
+
});
|
|
6925
|
+
});
|
|
6926
|
+
}
|
|
6927
|
+
/**
|
|
6928
|
+
* Destroy all chart instances
|
|
6929
|
+
* @internal
|
|
6930
|
+
*/
|
|
6931
|
+
destroyCharts() {
|
|
6932
|
+
this.chartInstances.forEach((chart) => {
|
|
6933
|
+
chart.destroy();
|
|
6934
|
+
});
|
|
6935
|
+
this.chartInstances = [];
|
|
6936
|
+
this.chartDisplays = [];
|
|
6937
|
+
}
|
|
6938
|
+
/**
|
|
6939
|
+
* Create a Chart.js instance
|
|
6940
|
+
* @internal
|
|
6941
|
+
*/
|
|
6942
|
+
createChartInstance(canvas, display) {
|
|
6943
|
+
const config = {
|
|
6944
|
+
type: display.type,
|
|
6945
|
+
data: display.data,
|
|
6946
|
+
options: display.options,
|
|
6947
|
+
};
|
|
6948
|
+
return new Chart(canvas, config);
|
|
6949
|
+
}
|
|
6950
|
+
/**
|
|
6951
|
+
* Transform IChartData to IChartDisplay
|
|
6952
|
+
* @internal
|
|
6953
|
+
*/
|
|
6954
|
+
transformToChartDisplay(chart) {
|
|
6955
|
+
const documentStyle = getComputedStyle(document.documentElement);
|
|
6956
|
+
const textColor = documentStyle.getPropertyValue('--text-color') || '#333';
|
|
6957
|
+
const textColorSecondary = documentStyle.getPropertyValue('--text-color-secondary') || '#666';
|
|
6958
|
+
const surfaceBorder = documentStyle.getPropertyValue('--surface-border') || '#ddd';
|
|
6959
|
+
const chartType = this.mapChartType(chart.chartType);
|
|
6960
|
+
const height = this.getChartHeight(chart.chartType);
|
|
6961
|
+
const options = this.getChartOptions(chart.chartType, textColor, textColorSecondary, surfaceBorder);
|
|
6962
|
+
const data = {
|
|
6963
|
+
labels: chart.labels,
|
|
6964
|
+
datasets: chart.dataSets.map((dataset) => this.transformDataset(dataset, documentStyle)),
|
|
6965
|
+
};
|
|
6966
|
+
return {
|
|
6967
|
+
type: chartType,
|
|
6968
|
+
data,
|
|
6969
|
+
options,
|
|
6970
|
+
height,
|
|
6971
|
+
};
|
|
6972
|
+
}
|
|
6973
|
+
/**
|
|
6974
|
+
* Map custom chart type strings to Chart.js types
|
|
6975
|
+
* @internal
|
|
6976
|
+
*/
|
|
6977
|
+
mapChartType(chartType) {
|
|
6978
|
+
const typeMap = {
|
|
6979
|
+
bar: 'bar',
|
|
6980
|
+
'bar-stack': 'bar',
|
|
6981
|
+
'bar-large': 'bar',
|
|
6982
|
+
'bar-horizontal': 'bar',
|
|
6983
|
+
pie: 'pie',
|
|
6984
|
+
doughnut: 'doughnut',
|
|
6985
|
+
line: 'line',
|
|
6986
|
+
scatter: 'scatter',
|
|
6987
|
+
bubble: 'bubble',
|
|
6988
|
+
polarArea: 'polarArea',
|
|
6989
|
+
radar: 'radar',
|
|
6990
|
+
};
|
|
6991
|
+
return typeMap[chartType] || 'bar';
|
|
6992
|
+
}
|
|
6993
|
+
/**
|
|
6994
|
+
* Get chart height based on chart type
|
|
6995
|
+
* @internal
|
|
6996
|
+
*/
|
|
6997
|
+
getChartHeight(chartType) {
|
|
6998
|
+
if (chartType === 'bar-large') {
|
|
6999
|
+
return '40rem';
|
|
7000
|
+
}
|
|
7001
|
+
return this.height;
|
|
7002
|
+
}
|
|
7003
|
+
/**
|
|
7004
|
+
* Get chart options based on chart type
|
|
7005
|
+
* @internal
|
|
7006
|
+
*/
|
|
7007
|
+
getChartOptions(chartType, textColor, textColorSecondary, surfaceBorder) {
|
|
7008
|
+
const baseOptions = {
|
|
7009
|
+
maintainAspectRatio: false,
|
|
7010
|
+
responsive: this.responsive,
|
|
7011
|
+
plugins: {
|
|
7012
|
+
legend: {
|
|
7013
|
+
labels: {
|
|
7014
|
+
color: textColor,
|
|
7015
|
+
},
|
|
7016
|
+
},
|
|
7017
|
+
},
|
|
7018
|
+
};
|
|
7019
|
+
switch (chartType) {
|
|
7020
|
+
case 'bar':
|
|
7021
|
+
return {
|
|
7022
|
+
...baseOptions,
|
|
7023
|
+
scales: this.getBarScales(textColorSecondary, surfaceBorder),
|
|
7024
|
+
};
|
|
7025
|
+
case 'bar-stack':
|
|
7026
|
+
return {
|
|
7027
|
+
...baseOptions,
|
|
7028
|
+
scales: this.getStackedBarScales(textColorSecondary, surfaceBorder),
|
|
7029
|
+
};
|
|
7030
|
+
case 'bar-large':
|
|
7031
|
+
return {
|
|
7032
|
+
...baseOptions,
|
|
7033
|
+
scales: this.getBarScales(textColorSecondary, surfaceBorder),
|
|
7034
|
+
};
|
|
7035
|
+
case 'bar-horizontal':
|
|
7036
|
+
return {
|
|
7037
|
+
...baseOptions,
|
|
7038
|
+
indexAxis: 'y',
|
|
7039
|
+
scales: this.getBarScales(textColorSecondary, surfaceBorder),
|
|
7040
|
+
};
|
|
7041
|
+
case 'pie':
|
|
7042
|
+
case 'doughnut':
|
|
7043
|
+
return {
|
|
7044
|
+
...baseOptions,
|
|
7045
|
+
plugins: {
|
|
7046
|
+
legend: {
|
|
7047
|
+
labels: {
|
|
7048
|
+
color: textColor,
|
|
7049
|
+
},
|
|
7050
|
+
position: 'bottom',
|
|
7051
|
+
},
|
|
7052
|
+
},
|
|
7053
|
+
};
|
|
7054
|
+
case 'line':
|
|
7055
|
+
return {
|
|
7056
|
+
...baseOptions,
|
|
7057
|
+
scales: this.getLineScales(textColorSecondary, surfaceBorder),
|
|
7058
|
+
};
|
|
7059
|
+
case 'radar':
|
|
7060
|
+
return {
|
|
7061
|
+
...baseOptions,
|
|
7062
|
+
plugins: {
|
|
7063
|
+
legend: {
|
|
7064
|
+
labels: {
|
|
7065
|
+
color: textColor,
|
|
7066
|
+
},
|
|
7067
|
+
},
|
|
7068
|
+
},
|
|
7069
|
+
scales: {
|
|
7070
|
+
r: {
|
|
7071
|
+
grid: {
|
|
7072
|
+
color: surfaceBorder,
|
|
7073
|
+
},
|
|
7074
|
+
pointLabels: {
|
|
7075
|
+
color: textColorSecondary,
|
|
7076
|
+
},
|
|
7077
|
+
},
|
|
7078
|
+
},
|
|
7079
|
+
};
|
|
7080
|
+
case 'polarArea':
|
|
7081
|
+
return {
|
|
7082
|
+
...baseOptions,
|
|
7083
|
+
scales: {
|
|
7084
|
+
r: {
|
|
7085
|
+
grid: {
|
|
7086
|
+
color: surfaceBorder,
|
|
7087
|
+
},
|
|
7088
|
+
},
|
|
7089
|
+
},
|
|
7090
|
+
};
|
|
7091
|
+
default:
|
|
7092
|
+
return baseOptions;
|
|
7093
|
+
}
|
|
7094
|
+
}
|
|
7095
|
+
/**
|
|
7096
|
+
* Get scales configuration for bar charts
|
|
7097
|
+
* @internal
|
|
7098
|
+
*/
|
|
7099
|
+
getBarScales(textColorSecondary, surfaceBorder) {
|
|
7100
|
+
return {
|
|
7101
|
+
x: {
|
|
7102
|
+
ticks: {
|
|
7103
|
+
color: textColorSecondary,
|
|
7104
|
+
},
|
|
7105
|
+
grid: {
|
|
7106
|
+
color: surfaceBorder,
|
|
7107
|
+
},
|
|
7108
|
+
},
|
|
7109
|
+
y: {
|
|
7110
|
+
ticks: {
|
|
7111
|
+
color: textColorSecondary,
|
|
7112
|
+
},
|
|
7113
|
+
grid: {
|
|
7114
|
+
color: surfaceBorder,
|
|
7115
|
+
},
|
|
7116
|
+
},
|
|
7117
|
+
};
|
|
7118
|
+
}
|
|
7119
|
+
/**
|
|
7120
|
+
* Get scales configuration for stacked bar charts
|
|
7121
|
+
* @internal
|
|
7122
|
+
*/
|
|
7123
|
+
getStackedBarScales(textColorSecondary, surfaceBorder) {
|
|
7124
|
+
return {
|
|
7125
|
+
x: {
|
|
7126
|
+
stacked: true,
|
|
7127
|
+
ticks: {
|
|
7128
|
+
color: textColorSecondary,
|
|
7129
|
+
},
|
|
7130
|
+
grid: {
|
|
7131
|
+
color: surfaceBorder,
|
|
7132
|
+
},
|
|
7133
|
+
},
|
|
7134
|
+
y: {
|
|
7135
|
+
stacked: true,
|
|
7136
|
+
ticks: {
|
|
7137
|
+
color: textColorSecondary,
|
|
7138
|
+
},
|
|
7139
|
+
grid: {
|
|
7140
|
+
color: surfaceBorder,
|
|
7141
|
+
},
|
|
7142
|
+
},
|
|
7143
|
+
};
|
|
7144
|
+
}
|
|
7145
|
+
/**
|
|
7146
|
+
* Get scales configuration for line charts
|
|
7147
|
+
* @internal
|
|
7148
|
+
*/
|
|
7149
|
+
getLineScales(textColorSecondary, surfaceBorder) {
|
|
7150
|
+
return {
|
|
7151
|
+
x: {
|
|
7152
|
+
ticks: {
|
|
7153
|
+
color: textColorSecondary,
|
|
7154
|
+
},
|
|
7155
|
+
grid: {
|
|
7156
|
+
color: surfaceBorder,
|
|
7157
|
+
},
|
|
7158
|
+
},
|
|
7159
|
+
y: {
|
|
7160
|
+
ticks: {
|
|
7161
|
+
color: textColorSecondary,
|
|
7162
|
+
},
|
|
7163
|
+
grid: {
|
|
7164
|
+
color: surfaceBorder,
|
|
7165
|
+
},
|
|
7166
|
+
},
|
|
7167
|
+
};
|
|
7168
|
+
}
|
|
7169
|
+
/**
|
|
7170
|
+
* Transform dataset with resolved colors
|
|
7171
|
+
* @internal
|
|
7172
|
+
*/
|
|
7173
|
+
transformDataset(dataset, documentStyle) {
|
|
7174
|
+
return {
|
|
7175
|
+
label: dataset.label,
|
|
7176
|
+
data: dataset.data,
|
|
7177
|
+
backgroundColor: dataset.backgroundColors.map((color) => {
|
|
7178
|
+
const resolvedColor = this.resolveColor(color, documentStyle);
|
|
7179
|
+
return this.addTransparency(resolvedColor);
|
|
7180
|
+
}),
|
|
7181
|
+
borderColor: dataset.backgroundColors.map((color) => this.resolveColor(color, documentStyle)),
|
|
7182
|
+
borderWidth: 1,
|
|
7183
|
+
};
|
|
7184
|
+
}
|
|
7185
|
+
/**
|
|
7186
|
+
* Resolve CSS variable to hex color or return as-is
|
|
7187
|
+
* @internal
|
|
7188
|
+
*/
|
|
7189
|
+
resolveColor(color, documentStyle) {
|
|
7190
|
+
if (color.startsWith('--')) {
|
|
7191
|
+
const resolvedColor = documentStyle.getPropertyValue(color).trim();
|
|
7192
|
+
return resolvedColor || color;
|
|
7193
|
+
}
|
|
7194
|
+
return color;
|
|
7195
|
+
}
|
|
7196
|
+
/**
|
|
7197
|
+
* Add transparency to a hex color
|
|
7198
|
+
* @internal
|
|
7199
|
+
*/
|
|
7200
|
+
addTransparency(color) {
|
|
7201
|
+
// If it's a hex color, add transparency
|
|
7202
|
+
if (color.startsWith('#')) {
|
|
7203
|
+
return color + 'bf'; // ~75% opacity
|
|
7204
|
+
}
|
|
7205
|
+
return color;
|
|
7206
|
+
}
|
|
7207
|
+
/**
|
|
7208
|
+
* Get the height style for a chart display
|
|
7209
|
+
* @param display - The chart display configuration
|
|
7210
|
+
* @returns The height CSS value
|
|
7211
|
+
*/
|
|
7212
|
+
getChartHeightStyle(display) {
|
|
7213
|
+
return display.height || this.height;
|
|
7214
|
+
}
|
|
7215
|
+
/**
|
|
7216
|
+
* Get the number of active chart instances (for testing)
|
|
7217
|
+
* @returns The count of active chart instances
|
|
7218
|
+
*/
|
|
7219
|
+
getChartInstanceCount() {
|
|
7220
|
+
return this.chartInstances.length;
|
|
7221
|
+
}
|
|
7222
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: IChart, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7223
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: IChart, isStandalone: true, selector: "i-chart", inputs: { charts: "charts", height: "height", responsive: "responsive" }, viewQueries: [{ propertyName: "canvasElements", predicate: ["chartCanvas"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"i-charts-container\">\n @for (chartDisplay of chartDisplays; track chartDisplay) {\n <div class=\"i-chart-item\" [style.height]=\"getChartHeightStyle(chartDisplay)\">\n <canvas #chartCanvas></canvas>\n </div>\n }\n</div>\n", styles: [".i-charts-container{display:flex;flex-wrap:wrap;width:100%;gap:4rem}.i-chart-item{flex:1 1 45%;min-width:300px;box-sizing:border-box}@media (max-width: 768px){.i-charts-container{flex-direction:column}.i-chart-item{width:100%}}\n"] });
|
|
7224
|
+
}
|
|
7225
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: IChart, decorators: [{
|
|
7226
|
+
type: Component,
|
|
7227
|
+
args: [{ selector: 'i-chart', standalone: true, imports: [], template: "<div class=\"i-charts-container\">\n @for (chartDisplay of chartDisplays; track chartDisplay) {\n <div class=\"i-chart-item\" [style.height]=\"getChartHeightStyle(chartDisplay)\">\n <canvas #chartCanvas></canvas>\n </div>\n }\n</div>\n", styles: [".i-charts-container{display:flex;flex-wrap:wrap;width:100%;gap:4rem}.i-chart-item{flex:1 1 45%;min-width:300px;box-sizing:border-box}@media (max-width: 768px){.i-charts-container{flex-direction:column}.i-chart-item{width:100%}}\n"] }]
|
|
7228
|
+
}], propDecorators: { charts: [{
|
|
7229
|
+
type: Input
|
|
7230
|
+
}], height: [{
|
|
7231
|
+
type: Input
|
|
7232
|
+
}], responsive: [{
|
|
7233
|
+
type: Input
|
|
7234
|
+
}], canvasElements: [{
|
|
7235
|
+
type: ViewChildren,
|
|
7236
|
+
args: ['chartCanvas']
|
|
7237
|
+
}] } });
|
|
7238
|
+
|
|
6809
7239
|
/**
|
|
6810
7240
|
* Service for broadcasting data update events across the application.
|
|
6811
7241
|
*
|
|
@@ -6866,6 +7296,358 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImpor
|
|
|
6866
7296
|
}]
|
|
6867
7297
|
}] });
|
|
6868
7298
|
|
|
7299
|
+
/**
|
|
7300
|
+
* Service for managing SEO meta tags dynamically.
|
|
7301
|
+
*
|
|
7302
|
+
* This service provides methods to update page titles, meta descriptions,
|
|
7303
|
+
* Open Graph tags, Twitter Cards, and other SEO-related meta tags.
|
|
7304
|
+
*
|
|
7305
|
+
* @example
|
|
7306
|
+
* ```typescript
|
|
7307
|
+
* import { SeoService } from 'integra-ng';
|
|
7308
|
+
*
|
|
7309
|
+
* export class MyComponent {
|
|
7310
|
+
* constructor(private seoService: SeoService) {
|
|
7311
|
+
* this.seoService.updateMetaTags({
|
|
7312
|
+
* title: 'My Page Title | My Site',
|
|
7313
|
+
* description: 'Description of my page for search engines.',
|
|
7314
|
+
* keywords: 'keyword1, keyword2, keyword3',
|
|
7315
|
+
* url: 'https://example.com/my-page',
|
|
7316
|
+
* image: 'https://example.com/og-image.png'
|
|
7317
|
+
* });
|
|
7318
|
+
* }
|
|
7319
|
+
* }
|
|
7320
|
+
* ```
|
|
7321
|
+
*/
|
|
7322
|
+
class SeoService {
|
|
7323
|
+
meta;
|
|
7324
|
+
title;
|
|
7325
|
+
constructor(meta, title) {
|
|
7326
|
+
this.meta = meta;
|
|
7327
|
+
this.title = title;
|
|
7328
|
+
}
|
|
7329
|
+
/**
|
|
7330
|
+
* Updates all SEO-related meta tags based on the provided configuration.
|
|
7331
|
+
*
|
|
7332
|
+
* @param config - The SEO configuration object
|
|
7333
|
+
*/
|
|
7334
|
+
updateMetaTags(config) {
|
|
7335
|
+
// Set document title
|
|
7336
|
+
this.title.setTitle(config.title);
|
|
7337
|
+
// Basic meta tags
|
|
7338
|
+
this.meta.updateTag({ name: 'description', content: config.description });
|
|
7339
|
+
if (config.keywords) {
|
|
7340
|
+
this.meta.updateTag({ name: 'keywords', content: config.keywords });
|
|
7341
|
+
}
|
|
7342
|
+
// Open Graph tags
|
|
7343
|
+
this.meta.updateTag({ property: 'og:title', content: config.title });
|
|
7344
|
+
this.meta.updateTag({
|
|
7345
|
+
property: 'og:description',
|
|
7346
|
+
content: config.description,
|
|
7347
|
+
});
|
|
7348
|
+
this.meta.updateTag({
|
|
7349
|
+
property: 'og:type',
|
|
7350
|
+
content: config.type || 'website',
|
|
7351
|
+
});
|
|
7352
|
+
if (config.url) {
|
|
7353
|
+
this.meta.updateTag({ property: 'og:url', content: config.url });
|
|
7354
|
+
// Also update canonical link
|
|
7355
|
+
this.updateCanonicalUrl(config.url);
|
|
7356
|
+
}
|
|
7357
|
+
if (config.image) {
|
|
7358
|
+
this.meta.updateTag({ property: 'og:image', content: config.image });
|
|
7359
|
+
}
|
|
7360
|
+
if (config.siteName) {
|
|
7361
|
+
this.meta.updateTag({
|
|
7362
|
+
property: 'og:site_name',
|
|
7363
|
+
content: config.siteName,
|
|
7364
|
+
});
|
|
7365
|
+
}
|
|
7366
|
+
// Twitter Card tags
|
|
7367
|
+
this.meta.updateTag({
|
|
7368
|
+
name: 'twitter:card',
|
|
7369
|
+
content: config.twitterCard || 'summary_large_image',
|
|
7370
|
+
});
|
|
7371
|
+
this.meta.updateTag({ name: 'twitter:title', content: config.title });
|
|
7372
|
+
this.meta.updateTag({
|
|
7373
|
+
name: 'twitter:description',
|
|
7374
|
+
content: config.description,
|
|
7375
|
+
});
|
|
7376
|
+
if (config.image) {
|
|
7377
|
+
this.meta.updateTag({ name: 'twitter:image', content: config.image });
|
|
7378
|
+
}
|
|
7379
|
+
if (config.url) {
|
|
7380
|
+
this.meta.updateTag({ property: 'twitter:url', content: config.url });
|
|
7381
|
+
}
|
|
7382
|
+
}
|
|
7383
|
+
/**
|
|
7384
|
+
* Sets only the page title.
|
|
7385
|
+
*
|
|
7386
|
+
* @param title - The title to set
|
|
7387
|
+
*/
|
|
7388
|
+
setTitle(title) {
|
|
7389
|
+
this.title.setTitle(title);
|
|
7390
|
+
}
|
|
7391
|
+
/**
|
|
7392
|
+
* Gets the current page title.
|
|
7393
|
+
*
|
|
7394
|
+
* @returns The current document title
|
|
7395
|
+
*/
|
|
7396
|
+
getTitle() {
|
|
7397
|
+
return this.title.getTitle();
|
|
7398
|
+
}
|
|
7399
|
+
/**
|
|
7400
|
+
* Sets only the meta description.
|
|
7401
|
+
*
|
|
7402
|
+
* @param description - The description to set (recommended: 150-160 characters)
|
|
7403
|
+
*/
|
|
7404
|
+
setDescription(description) {
|
|
7405
|
+
this.meta.updateTag({ name: 'description', content: description });
|
|
7406
|
+
}
|
|
7407
|
+
/**
|
|
7408
|
+
* Sets robots meta tag directives.
|
|
7409
|
+
*
|
|
7410
|
+
* @param content - The robots directive (e.g., 'index, follow', 'noindex, nofollow')
|
|
7411
|
+
*/
|
|
7412
|
+
setRobots(content) {
|
|
7413
|
+
this.meta.updateTag({ name: 'robots', content });
|
|
7414
|
+
}
|
|
7415
|
+
/**
|
|
7416
|
+
* Updates or creates the canonical URL link element.
|
|
7417
|
+
*
|
|
7418
|
+
* @param url - The canonical URL
|
|
7419
|
+
*/
|
|
7420
|
+
updateCanonicalUrl(url) {
|
|
7421
|
+
if (typeof document === 'undefined') {
|
|
7422
|
+
return;
|
|
7423
|
+
}
|
|
7424
|
+
let link = document.querySelector('link[rel="canonical"]');
|
|
7425
|
+
if (!link) {
|
|
7426
|
+
link = document.createElement('link');
|
|
7427
|
+
link.setAttribute('rel', 'canonical');
|
|
7428
|
+
document.head.appendChild(link);
|
|
7429
|
+
}
|
|
7430
|
+
link.setAttribute('href', url);
|
|
7431
|
+
}
|
|
7432
|
+
/**
|
|
7433
|
+
* Removes a specific meta tag by name or property.
|
|
7434
|
+
*
|
|
7435
|
+
* @param attrSelector - The attribute selector (e.g., "name='description'" or "property='og:title'")
|
|
7436
|
+
*/
|
|
7437
|
+
removeTag(attrSelector) {
|
|
7438
|
+
this.meta.removeTag(attrSelector);
|
|
7439
|
+
}
|
|
7440
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: SeoService, deps: [{ token: i1$1.Meta }, { token: i1$1.Title }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
7441
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: SeoService, providedIn: 'root' });
|
|
7442
|
+
}
|
|
7443
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: SeoService, decorators: [{
|
|
7444
|
+
type: Injectable,
|
|
7445
|
+
args: [{ providedIn: 'root' }]
|
|
7446
|
+
}], ctorParameters: () => [{ type: i1$1.Meta }, { type: i1$1.Title }] });
|
|
7447
|
+
|
|
7448
|
+
/**
|
|
7449
|
+
* Service for managing structured data (JSON-LD) for SEO.
|
|
7450
|
+
*
|
|
7451
|
+
* This service provides methods to insert and manage schema.org
|
|
7452
|
+
* structured data in the document head for improved search engine
|
|
7453
|
+
* visibility and rich search results.
|
|
7454
|
+
*
|
|
7455
|
+
* @example
|
|
7456
|
+
* ```typescript
|
|
7457
|
+
* import { StructuredDataService } from 'integra-ng';
|
|
7458
|
+
*
|
|
7459
|
+
* export class AppComponent {
|
|
7460
|
+
* constructor(private structuredDataService: StructuredDataService) {
|
|
7461
|
+
* // Insert organization schema
|
|
7462
|
+
* const orgSchema = this.structuredDataService.createOrganizationSchema({
|
|
7463
|
+
* name: 'My Company',
|
|
7464
|
+
* url: 'https://example.com',
|
|
7465
|
+
* logo: 'https://example.com/logo.png'
|
|
7466
|
+
* });
|
|
7467
|
+
* this.structuredDataService.insertSchema(orgSchema, 'organization-schema');
|
|
7468
|
+
* }
|
|
7469
|
+
* }
|
|
7470
|
+
* ```
|
|
7471
|
+
*/
|
|
7472
|
+
class StructuredDataService {
|
|
7473
|
+
document;
|
|
7474
|
+
constructor(document) {
|
|
7475
|
+
this.document = document;
|
|
7476
|
+
}
|
|
7477
|
+
/**
|
|
7478
|
+
* Inserts or updates a JSON-LD schema script in the document head.
|
|
7479
|
+
*
|
|
7480
|
+
* @param schema - The schema object to insert
|
|
7481
|
+
* @param id - Unique identifier for the script element (default: 'structured-data')
|
|
7482
|
+
*/
|
|
7483
|
+
insertSchema(schema, id = 'structured-data') {
|
|
7484
|
+
if (typeof this.document === 'undefined') {
|
|
7485
|
+
return;
|
|
7486
|
+
}
|
|
7487
|
+
let script = this.document.getElementById(id);
|
|
7488
|
+
if (!script) {
|
|
7489
|
+
script = this.document.createElement('script');
|
|
7490
|
+
script.id = id;
|
|
7491
|
+
script.type = 'application/ld+json';
|
|
7492
|
+
this.document.head.appendChild(script);
|
|
7493
|
+
}
|
|
7494
|
+
script.textContent = JSON.stringify(schema);
|
|
7495
|
+
}
|
|
7496
|
+
/**
|
|
7497
|
+
* Removes a schema script from the document.
|
|
7498
|
+
*
|
|
7499
|
+
* @param id - The identifier of the script element to remove
|
|
7500
|
+
*/
|
|
7501
|
+
removeSchema(id) {
|
|
7502
|
+
if (typeof this.document === 'undefined') {
|
|
7503
|
+
return;
|
|
7504
|
+
}
|
|
7505
|
+
const script = this.document.getElementById(id);
|
|
7506
|
+
if (script) {
|
|
7507
|
+
script.remove();
|
|
7508
|
+
}
|
|
7509
|
+
}
|
|
7510
|
+
/**
|
|
7511
|
+
* Creates an Organization schema object.
|
|
7512
|
+
*
|
|
7513
|
+
* @param config - Organization configuration
|
|
7514
|
+
* @returns A schema.org Organization object
|
|
7515
|
+
*/
|
|
7516
|
+
createOrganizationSchema(config) {
|
|
7517
|
+
const schema = {
|
|
7518
|
+
'@context': 'https://schema.org',
|
|
7519
|
+
'@type': 'Organization',
|
|
7520
|
+
name: config.name,
|
|
7521
|
+
url: config.url,
|
|
7522
|
+
};
|
|
7523
|
+
if (config.logo) {
|
|
7524
|
+
schema['logo'] = config.logo;
|
|
7525
|
+
}
|
|
7526
|
+
if (config.sameAs && config.sameAs.length > 0) {
|
|
7527
|
+
schema['sameAs'] = config.sameAs;
|
|
7528
|
+
}
|
|
7529
|
+
if (config.contactPoint) {
|
|
7530
|
+
schema['contactPoint'] = {
|
|
7531
|
+
'@type': 'ContactPoint',
|
|
7532
|
+
telephone: config.contactPoint.telephone,
|
|
7533
|
+
contactType: config.contactPoint.contactType,
|
|
7534
|
+
...(config.contactPoint.areaServed && {
|
|
7535
|
+
areaServed: config.contactPoint.areaServed,
|
|
7536
|
+
}),
|
|
7537
|
+
...(config.contactPoint.availableLanguage && {
|
|
7538
|
+
availableLanguage: config.contactPoint.availableLanguage,
|
|
7539
|
+
}),
|
|
7540
|
+
};
|
|
7541
|
+
}
|
|
7542
|
+
return schema;
|
|
7543
|
+
}
|
|
7544
|
+
/**
|
|
7545
|
+
* Creates a WebSite schema object.
|
|
7546
|
+
*
|
|
7547
|
+
* @param config - WebSite configuration
|
|
7548
|
+
* @returns A schema.org WebSite object
|
|
7549
|
+
*/
|
|
7550
|
+
createWebSiteSchema(config) {
|
|
7551
|
+
const schema = {
|
|
7552
|
+
'@context': 'https://schema.org',
|
|
7553
|
+
'@type': 'WebSite',
|
|
7554
|
+
name: config.name,
|
|
7555
|
+
url: config.url,
|
|
7556
|
+
};
|
|
7557
|
+
if (config.description) {
|
|
7558
|
+
schema['description'] = config.description;
|
|
7559
|
+
}
|
|
7560
|
+
if (config.potentialAction) {
|
|
7561
|
+
schema['potentialAction'] = {
|
|
7562
|
+
'@type': 'SearchAction',
|
|
7563
|
+
target: config.potentialAction.target,
|
|
7564
|
+
'query-input': config.potentialAction.queryInput,
|
|
7565
|
+
};
|
|
7566
|
+
}
|
|
7567
|
+
return schema;
|
|
7568
|
+
}
|
|
7569
|
+
/**
|
|
7570
|
+
* Creates a BreadcrumbList schema object.
|
|
7571
|
+
*
|
|
7572
|
+
* @param items - Array of breadcrumb items
|
|
7573
|
+
* @returns A schema.org BreadcrumbList object
|
|
7574
|
+
*/
|
|
7575
|
+
createBreadcrumbSchema(items) {
|
|
7576
|
+
return {
|
|
7577
|
+
'@context': 'https://schema.org',
|
|
7578
|
+
'@type': 'BreadcrumbList',
|
|
7579
|
+
itemListElement: items.map((item, index) => ({
|
|
7580
|
+
'@type': 'ListItem',
|
|
7581
|
+
position: index + 1,
|
|
7582
|
+
name: item.name,
|
|
7583
|
+
item: item.url,
|
|
7584
|
+
})),
|
|
7585
|
+
};
|
|
7586
|
+
}
|
|
7587
|
+
/**
|
|
7588
|
+
* Creates an Article schema object.
|
|
7589
|
+
*
|
|
7590
|
+
* @param config - Article configuration
|
|
7591
|
+
* @returns A schema.org Article object
|
|
7592
|
+
*/
|
|
7593
|
+
createArticleSchema(config) {
|
|
7594
|
+
const schema = {
|
|
7595
|
+
'@context': 'https://schema.org',
|
|
7596
|
+
'@type': 'Article',
|
|
7597
|
+
headline: config.headline,
|
|
7598
|
+
description: config.description,
|
|
7599
|
+
datePublished: config.datePublished,
|
|
7600
|
+
author: {
|
|
7601
|
+
'@type': 'Person',
|
|
7602
|
+
name: config.author.name,
|
|
7603
|
+
...(config.author.url && { url: config.author.url }),
|
|
7604
|
+
},
|
|
7605
|
+
};
|
|
7606
|
+
if (config.image) {
|
|
7607
|
+
schema['image'] = config.image;
|
|
7608
|
+
}
|
|
7609
|
+
if (config.dateModified) {
|
|
7610
|
+
schema['dateModified'] = config.dateModified;
|
|
7611
|
+
}
|
|
7612
|
+
return schema;
|
|
7613
|
+
}
|
|
7614
|
+
/**
|
|
7615
|
+
* Creates a SoftwareApplication schema object for the library.
|
|
7616
|
+
*
|
|
7617
|
+
* @param config - Application configuration
|
|
7618
|
+
* @returns A schema.org SoftwareApplication object
|
|
7619
|
+
*/
|
|
7620
|
+
createSoftwareApplicationSchema(config) {
|
|
7621
|
+
const schema = {
|
|
7622
|
+
'@context': 'https://schema.org',
|
|
7623
|
+
'@type': 'SoftwareApplication',
|
|
7624
|
+
name: config.name,
|
|
7625
|
+
description: config.description,
|
|
7626
|
+
applicationCategory: config.applicationCategory,
|
|
7627
|
+
};
|
|
7628
|
+
if (config.operatingSystem) {
|
|
7629
|
+
schema['operatingSystem'] = config.operatingSystem;
|
|
7630
|
+
}
|
|
7631
|
+
if (config.offers) {
|
|
7632
|
+
schema['offers'] = {
|
|
7633
|
+
'@type': 'Offer',
|
|
7634
|
+
price: config.offers.price,
|
|
7635
|
+
priceCurrency: config.offers.priceCurrency,
|
|
7636
|
+
};
|
|
7637
|
+
}
|
|
7638
|
+
return schema;
|
|
7639
|
+
}
|
|
7640
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: StructuredDataService, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
7641
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: StructuredDataService, providedIn: 'root' });
|
|
7642
|
+
}
|
|
7643
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: StructuredDataService, decorators: [{
|
|
7644
|
+
type: Injectable,
|
|
7645
|
+
args: [{ providedIn: 'root' }]
|
|
7646
|
+
}], ctorParameters: () => [{ type: Document, decorators: [{
|
|
7647
|
+
type: Inject,
|
|
7648
|
+
args: [DOCUMENT]
|
|
7649
|
+
}] }] });
|
|
7650
|
+
|
|
6869
7651
|
function ZIndexUtils() {
|
|
6870
7652
|
let zIndexes = [];
|
|
6871
7653
|
const generateZIndex = (key, baseZIndex) => {
|
|
@@ -6912,5 +7694,5 @@ var zindexutils = ZIndexUtils();
|
|
|
6912
7694
|
* Generated bundle index. Do not edit.
|
|
6913
7695
|
*/
|
|
6914
7696
|
|
|
6915
|
-
export { AbstractDialog, ConfirmationDialogComponent, ConfirmationDialogService, DataUpdateEventService, DialogService, EmptyStateComponent, EmptyStateTableComponent, IAccordion, IAccordionList, IButton, ICalendar, ICard, ICheckbox, IChip, IChipsComponent, IDialog, IDialogActions, IDialogBase, IInputText, IListbox, IMessage, IMultiSelect, IPanel, IRadioButton, ISelect, ITabPanel, ITable, ITabs, ITreeView, IWhisper, TooltipComponent, TooltipDirective, UniqueComponentId, WhisperService, ZIndexUtils, lastId };
|
|
7697
|
+
export { AbstractDialog, ConfirmationDialogComponent, ConfirmationDialogService, DataUpdateEventService, DialogService, EmptyStateComponent, EmptyStateTableComponent, IAccordion, IAccordionList, IButton, ICalendar, ICard, IChart, ICheckbox, IChip, IChipsComponent, IDialog, IDialogActions, IDialogBase, IInputText, IListbox, IMessage, IMultiSelect, IPanel, IRadioButton, ISelect, ITabPanel, ITable, ITabs, ITreeView, IWhisper, SeoService, StructuredDataService, TooltipComponent, TooltipDirective, UniqueComponentId, WhisperService, ZIndexUtils, lastId };
|
|
6916
7698
|
//# sourceMappingURL=integra-ng.mjs.map
|