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.
@@ -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