cps-ui-kit 22.0.1 → 22.1.0
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/cps-ui-kit.mjs +132 -132
- package/fesm2022/cps-ui-kit.mjs.map +1 -1
- package/package.json +1 -1
- package/types/cps-ui-kit.d.ts +18 -10
package/fesm2022/cps-ui-kit.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i2 from '@angular/common';
|
|
2
2
|
import { DOCUMENT, isPlatformBrowser, CommonModule, isPlatformServer, NgTemplateOutlet } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { inject, PLATFORM_ID, signal, Injectable, InjectionToken, ElementRef, Renderer2, HostAttributeToken, Input, ChangeDetectionStrategy, Component, EventEmitter, Output, input, computed, SecurityContext, Directive, Pipe, NgModule, effect, untracked, provideAppInitializer, makeEnvironmentProviders, ViewChild, Inject, ViewEncapsulation, Injector, ChangeDetectorRef, booleanAttribute, ContentChildren, ContentChild, HostBinding, Self, Optional,
|
|
4
|
+
import { inject, PLATFORM_ID, signal, Injectable, InjectionToken, ElementRef, Renderer2, HostAttributeToken, Input, ChangeDetectionStrategy, Component, EventEmitter, Output, input, computed, NgZone, SecurityContext, Directive, Pipe, NgModule, effect, untracked, provideAppInitializer, makeEnvironmentProviders, ViewChild, Inject, ViewEncapsulation, Injector, ChangeDetectorRef, booleanAttribute, ContentChildren, ContentChild, HostBinding, Self, Optional, contentChild, numberAttribute, HostListener, output, afterRenderEffect, forwardRef, ViewChildren, TemplateRef, viewChildren, viewChild, Host, model, RendererStyleFlags2, createComponent, createEnvironmentInjector, SkipSelf } from '@angular/core';
|
|
5
5
|
import * as i1$1 from '@angular/forms';
|
|
6
6
|
import { Validators, FormsModule, NgControl, NG_VALUE_ACCESSOR, FormBuilder, ReactiveFormsModule } from '@angular/forms';
|
|
7
7
|
import { Subject, takeUntil, debounceTime, distinctUntilChanged, take, catchError, of, Subscription, fromEvent } from 'rxjs';
|
|
@@ -661,6 +661,116 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
|
|
|
661
661
|
}, template: "<div\n aria-hidden=\"true\"\n class=\"cps-progress-linear\"\n data-testid=\"cps-progress-linear\"\n [style.max-width]=\"cvtWidth()\"\n [style.height]=\"cvtHeight()\"\n [style.border-radius]=\"cvtRadius()\"\n [style.background]=\"cssBgColor()\">\n <div\n class=\"cps-progress-linear-line inc\"\n data-testid=\"cps-progress-linear-inc\"\n [style.background]=\"cssColor()\"\n [style.opacity]=\"opacity()\"></div>\n <div\n class=\"cps-progress-linear-line dec\"\n data-testid=\"cps-progress-linear-dec\"\n [style.background]=\"cssColor()\"\n [style.opacity]=\"opacity()\"></div>\n</div>\n", styles: [":host{width:100%}:host .cps-progress-linear{position:relative;overflow-x:hidden}:host .cps-progress-linear-line{position:absolute;height:inherit;left:-5%;top:0}:host .cps-progress-linear .inc{animation:increase 2s infinite}:host .cps-progress-linear .dec{animation:decrease 2s .5s infinite}@media(prefers-reduced-motion:reduce){:host .cps-progress-linear .inc{animation-duration:6s!important;animation-iteration-count:infinite!important}:host .cps-progress-linear .dec{animation-duration:6s!important;animation-iteration-count:infinite!important}}@keyframes increase{0%{left:-5%;width:5%}to{left:130%;width:100%}}@keyframes decrease{0%{left:-80%;width:80%}to{left:110%;width:10%}}\n"] }]
|
|
662
662
|
}], propDecorators: { width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], bgColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "bgColor", required: false }] }], opacity: [{ type: i0.Input, args: [{ isSignal: true, alias: "opacity", required: false }] }], radius: [{ type: i0.Input, args: [{ isSignal: true, alias: "radius", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
|
|
663
663
|
|
|
664
|
+
/**
|
|
665
|
+
* Service for making accessible live-region announcements without relying on a
|
|
666
|
+
* specific component's live region. Creates two persistent hidden elements in
|
|
667
|
+
* document.body (one polite, one assertive) that screen readers monitor for
|
|
668
|
+
* content changes.
|
|
669
|
+
*/
|
|
670
|
+
class CpsLiveAnnouncerService {
|
|
671
|
+
constructor() {
|
|
672
|
+
this._document = inject(DOCUMENT);
|
|
673
|
+
this._ngZone = inject(NgZone);
|
|
674
|
+
this._platformId = inject(PLATFORM_ID);
|
|
675
|
+
this._isBrowser = isPlatformBrowser(this._platformId);
|
|
676
|
+
this._regions = {
|
|
677
|
+
polite: {
|
|
678
|
+
el: this._createElement('polite'),
|
|
679
|
+
writeTimer: undefined,
|
|
680
|
+
clearTimer: undefined
|
|
681
|
+
},
|
|
682
|
+
assertive: {
|
|
683
|
+
el: this._createElement('assertive'),
|
|
684
|
+
writeTimer: undefined,
|
|
685
|
+
clearTimer: undefined
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
/**
|
|
690
|
+
* Announces a message through the appropriate live region. Clears any
|
|
691
|
+
* existing text first so the same message can be re-announced, then writes
|
|
692
|
+
* the new text after `delayMs` so screen readers observe the content change.
|
|
693
|
+
* After `durationMs` the region is cleared automatically; pass `0` to keep
|
|
694
|
+
* the message indefinitely. Defaults to a next-tick write and 5000ms duration.
|
|
695
|
+
*/
|
|
696
|
+
announce(message, politeness = 'polite', durationMs = 5000, delayMs = 0) {
|
|
697
|
+
if (!this._isBrowser)
|
|
698
|
+
return;
|
|
699
|
+
this.clear(politeness);
|
|
700
|
+
const region = this._regions[politeness];
|
|
701
|
+
this._ngZone.runOutsideAngular(() => {
|
|
702
|
+
region.writeTimer = setTimeout(() => {
|
|
703
|
+
region.writeTimer = undefined;
|
|
704
|
+
region.el.textContent = message;
|
|
705
|
+
if (durationMs > 0) {
|
|
706
|
+
region.clearTimer = setTimeout(() => {
|
|
707
|
+
region.clearTimer = undefined;
|
|
708
|
+
region.el.textContent = '';
|
|
709
|
+
}, durationMs);
|
|
710
|
+
}
|
|
711
|
+
}, delayMs);
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
/**
|
|
715
|
+
* Clears the live region without making a new announcement.
|
|
716
|
+
*/
|
|
717
|
+
clear(politeness = 'polite') {
|
|
718
|
+
if (!this._isBrowser)
|
|
719
|
+
return;
|
|
720
|
+
const region = this._regions[politeness];
|
|
721
|
+
clearTimeout(region.writeTimer);
|
|
722
|
+
clearTimeout(region.clearTimer);
|
|
723
|
+
region.writeTimer = undefined;
|
|
724
|
+
region.clearTimer = undefined;
|
|
725
|
+
region.el.textContent = '';
|
|
726
|
+
}
|
|
727
|
+
ngOnDestroy() {
|
|
728
|
+
for (const region of Object.values(this._regions)) {
|
|
729
|
+
clearTimeout(region.writeTimer);
|
|
730
|
+
clearTimeout(region.clearTimer);
|
|
731
|
+
region.el.remove();
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
_createElement(politeness) {
|
|
735
|
+
const cls = `cps-${politeness}-live-announcer-element`;
|
|
736
|
+
if (this._isBrowser) {
|
|
737
|
+
const existing = this._document.body.querySelector(`.${cls}`);
|
|
738
|
+
if (existing)
|
|
739
|
+
return existing;
|
|
740
|
+
}
|
|
741
|
+
const el = this._document.createElement('div');
|
|
742
|
+
if (!this._isBrowser)
|
|
743
|
+
return el;
|
|
744
|
+
el.setAttribute('aria-live', politeness);
|
|
745
|
+
el.setAttribute('aria-atomic', 'true');
|
|
746
|
+
el.className = `cps-sr-only ${cls}`;
|
|
747
|
+
this._document.body.appendChild(el);
|
|
748
|
+
return el;
|
|
749
|
+
}
|
|
750
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: CpsLiveAnnouncerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
751
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: CpsLiveAnnouncerService, providedIn: 'root' }); }
|
|
752
|
+
}
|
|
753
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: CpsLiveAnnouncerService, decorators: [{
|
|
754
|
+
type: Injectable,
|
|
755
|
+
args: [{ providedIn: 'root' }]
|
|
756
|
+
}] });
|
|
757
|
+
/**
|
|
758
|
+
* Injection token for the live-announcer service.
|
|
759
|
+
*
|
|
760
|
+
* By default it resolves to the singleton {@link CpsLiveAnnouncerService}.
|
|
761
|
+
* Consumer applications can override it to supply a custom implementation or
|
|
762
|
+
* provide `null` to disable all live-region announcements.
|
|
763
|
+
*
|
|
764
|
+
* @example Disable announcements:
|
|
765
|
+
* ```typescript
|
|
766
|
+
* providers: [{ provide: CPS_LIVE_ANNOUNCER_SERVICE, useValue: null }]
|
|
767
|
+
* ```
|
|
768
|
+
*/
|
|
769
|
+
const CPS_LIVE_ANNOUNCER_SERVICE = new InjectionToken('CpsLiveAnnouncerService', {
|
|
770
|
+
providedIn: 'root',
|
|
771
|
+
factory: () => inject(CpsLiveAnnouncerService)
|
|
772
|
+
});
|
|
773
|
+
|
|
664
774
|
/**
|
|
665
775
|
* CpsTooltipDirective provides advisory information for a target element.
|
|
666
776
|
* @group Components
|
|
@@ -745,6 +855,7 @@ class CpsTooltipDirective {
|
|
|
745
855
|
this._document = inject(DOCUMENT);
|
|
746
856
|
this._platformId = inject(PLATFORM_ID);
|
|
747
857
|
this._domSanitizer = inject(DomSanitizer);
|
|
858
|
+
this._liveAnnouncer = inject(CPS_LIVE_ANNOUNCER_SERVICE);
|
|
748
859
|
this._onScrollDestroy = () => {
|
|
749
860
|
this._destroyTooltip(true);
|
|
750
861
|
};
|
|
@@ -890,7 +1001,7 @@ class CpsTooltipDirective {
|
|
|
890
1001
|
clearTimeout(this._hideTimeout);
|
|
891
1002
|
this._createTooltip();
|
|
892
1003
|
this._positionAndShow();
|
|
893
|
-
this.
|
|
1004
|
+
this._liveAnnouncer?.announce(this._popup?.textContent ?? '', 'assertive', 1000, 100);
|
|
894
1005
|
}
|
|
895
1006
|
}
|
|
896
1007
|
onDocumentClick(target) {
|
|
@@ -1028,20 +1139,6 @@ class CpsTooltipDirective {
|
|
|
1028
1139
|
_resolveAriaTarget() {
|
|
1029
1140
|
return this._document.activeElement ?? undefined;
|
|
1030
1141
|
}
|
|
1031
|
-
// aria-describedby is not read by SR on click trigger.
|
|
1032
|
-
// Use a self-removing live region. It must exist in DOM
|
|
1033
|
-
// before content is set, hence the 100ms delay.
|
|
1034
|
-
_announce(text) {
|
|
1035
|
-
const el = this._document.createElement('div');
|
|
1036
|
-
el.setAttribute('aria-live', 'assertive');
|
|
1037
|
-
el.setAttribute('aria-atomic', 'true');
|
|
1038
|
-
el.className = 'cps-sr-only';
|
|
1039
|
-
this._document.body.appendChild(el);
|
|
1040
|
-
setTimeout(() => {
|
|
1041
|
-
el.textContent = text;
|
|
1042
|
-
setTimeout(() => el.remove(), 1000);
|
|
1043
|
-
}, 100);
|
|
1044
|
-
}
|
|
1045
1142
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: CpsTooltipDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1046
1143
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.7", type: CpsTooltipDirective, isStandalone: true, selector: "[cpsTooltip]", inputs: { tooltip: { classPropertyName: "tooltip", publicName: "cpsTooltip", isSignal: true, isRequired: true, transformFunction: null }, tooltipOpenDelay: { classPropertyName: "tooltipOpenDelay", publicName: "tooltipOpenDelay", isSignal: true, isRequired: false, transformFunction: null }, tooltipCloseDelay: { classPropertyName: "tooltipCloseDelay", publicName: "tooltipCloseDelay", isSignal: true, isRequired: false, transformFunction: null }, tooltipOpenOn: { classPropertyName: "tooltipOpenOn", publicName: "tooltipOpenOn", isSignal: true, isRequired: false, transformFunction: null }, tooltipPosition: { classPropertyName: "tooltipPosition", publicName: "tooltipPosition", isSignal: true, isRequired: false, transformFunction: null }, tooltipPersistent: { classPropertyName: "tooltipPersistent", publicName: "tooltipPersistent", isSignal: true, isRequired: false, transformFunction: null }, tooltipDisabled: { classPropertyName: "tooltipDisabled", publicName: "tooltipDisabled", isSignal: true, isRequired: false, transformFunction: null }, tooltipMaxWidth: { classPropertyName: "tooltipMaxWidth", publicName: "tooltipMaxWidth", isSignal: true, isRequired: false, transformFunction: null }, tooltipContentClass: { classPropertyName: "tooltipContentClass", publicName: "tooltipContentClass", isSignal: true, isRequired: false, transformFunction: null }, tooltipOffset: { classPropertyName: "tooltipOffset", publicName: "tooltipOffset", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()", "focusin": "onFocus()", "focusout": "onFocusOut($event)", "keydown.tab": "onTabFromTrigger($event)", "click": "onClick()", "document:click": "onDocumentClick($event.target)", "window:resize": "onPageResize()" } }, ngImport: i0 }); }
|
|
1047
1144
|
}
|
|
@@ -5682,17 +5779,30 @@ class CpsFocusService {
|
|
|
5682
5779
|
el.addEventListener('blur', () => el.classList.remove('suppress-focus-visible'), { once: true });
|
|
5683
5780
|
}
|
|
5684
5781
|
/**
|
|
5685
|
-
* Focuses `el`,
|
|
5782
|
+
* Focuses `el`, optionally suppressing its focus ring and passing native
|
|
5783
|
+
* focus options through to `HTMLElement.focus`.
|
|
5686
5784
|
*
|
|
5687
|
-
*
|
|
5688
|
-
*
|
|
5689
|
-
*
|
|
5785
|
+
* @param el - The element to focus.
|
|
5786
|
+
* @param showFocusRing - Whether the focus ring should be shown. When false, adds
|
|
5787
|
+
* the suppress-focus-visible CSS class to the element before focusing and removes
|
|
5788
|
+
* it on the next blur event to keep the UI clean for pointer-initiated closes.
|
|
5789
|
+
* @param options - Native focus options, e.g. `{ preventScroll: true }`.
|
|
5790
|
+
*
|
|
5791
|
+
* @example
|
|
5792
|
+
* ```ts
|
|
5793
|
+
* focusService.focusElement(button, true, { preventScroll: true });
|
|
5794
|
+
* ```
|
|
5690
5795
|
*/
|
|
5691
|
-
focusElement(el, showFocusRing) {
|
|
5796
|
+
focusElement(el, showFocusRing, options) {
|
|
5692
5797
|
if (!showFocusRing) {
|
|
5693
5798
|
this.suppressNextFocusRing(el);
|
|
5694
5799
|
}
|
|
5695
|
-
|
|
5800
|
+
if (!options) {
|
|
5801
|
+
el.focus();
|
|
5802
|
+
}
|
|
5803
|
+
else {
|
|
5804
|
+
el.focus(options);
|
|
5805
|
+
}
|
|
5696
5806
|
}
|
|
5697
5807
|
/**
|
|
5698
5808
|
* Installs a Tab key focus trap on `container`.
|
|
@@ -22783,116 +22893,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
|
|
|
22783
22893
|
args: ['dropzoneButton']
|
|
22784
22894
|
}] } });
|
|
22785
22895
|
|
|
22786
|
-
/**
|
|
22787
|
-
* Service for making accessible live-region announcements without relying on a
|
|
22788
|
-
* specific component's live region. Creates two persistent hidden elements in
|
|
22789
|
-
* document.body (one polite, one assertive) that screen readers monitor for
|
|
22790
|
-
* content changes.
|
|
22791
|
-
*/
|
|
22792
|
-
class CpsLiveAnnouncerService {
|
|
22793
|
-
constructor() {
|
|
22794
|
-
this._document = inject(DOCUMENT);
|
|
22795
|
-
this._ngZone = inject(NgZone);
|
|
22796
|
-
this._platformId = inject(PLATFORM_ID);
|
|
22797
|
-
this._isBrowser = isPlatformBrowser(this._platformId);
|
|
22798
|
-
this._regions = {
|
|
22799
|
-
polite: {
|
|
22800
|
-
el: this._createElement('polite'),
|
|
22801
|
-
writeTimer: undefined,
|
|
22802
|
-
clearTimer: undefined
|
|
22803
|
-
},
|
|
22804
|
-
assertive: {
|
|
22805
|
-
el: this._createElement('assertive'),
|
|
22806
|
-
writeTimer: undefined,
|
|
22807
|
-
clearTimer: undefined
|
|
22808
|
-
}
|
|
22809
|
-
};
|
|
22810
|
-
}
|
|
22811
|
-
/**
|
|
22812
|
-
* Announces a message through the appropriate live region. Clears any
|
|
22813
|
-
* existing text first so the same message can be re-announced, then writes
|
|
22814
|
-
* the new text on the next tick so screen readers observe the content change.
|
|
22815
|
-
* After `duration` ms the region is cleared automatically; pass `0` to keep
|
|
22816
|
-
* the message indefinitely. Defaults to 5000ms.
|
|
22817
|
-
*/
|
|
22818
|
-
announce(message, politeness = 'polite', durationMs = 5000) {
|
|
22819
|
-
if (!this._isBrowser)
|
|
22820
|
-
return;
|
|
22821
|
-
this.clear(politeness);
|
|
22822
|
-
const region = this._regions[politeness];
|
|
22823
|
-
this._ngZone.runOutsideAngular(() => {
|
|
22824
|
-
region.writeTimer = setTimeout(() => {
|
|
22825
|
-
region.writeTimer = undefined;
|
|
22826
|
-
region.el.textContent = message;
|
|
22827
|
-
if (durationMs > 0) {
|
|
22828
|
-
region.clearTimer = setTimeout(() => {
|
|
22829
|
-
region.clearTimer = undefined;
|
|
22830
|
-
region.el.textContent = '';
|
|
22831
|
-
}, durationMs);
|
|
22832
|
-
}
|
|
22833
|
-
});
|
|
22834
|
-
});
|
|
22835
|
-
}
|
|
22836
|
-
/**
|
|
22837
|
-
* Clears the live region without making a new announcement.
|
|
22838
|
-
*/
|
|
22839
|
-
clear(politeness = 'polite') {
|
|
22840
|
-
if (!this._isBrowser)
|
|
22841
|
-
return;
|
|
22842
|
-
const region = this._regions[politeness];
|
|
22843
|
-
clearTimeout(region.writeTimer);
|
|
22844
|
-
clearTimeout(region.clearTimer);
|
|
22845
|
-
region.writeTimer = undefined;
|
|
22846
|
-
region.clearTimer = undefined;
|
|
22847
|
-
region.el.textContent = '';
|
|
22848
|
-
}
|
|
22849
|
-
ngOnDestroy() {
|
|
22850
|
-
for (const region of Object.values(this._regions)) {
|
|
22851
|
-
clearTimeout(region.writeTimer);
|
|
22852
|
-
clearTimeout(region.clearTimer);
|
|
22853
|
-
region.el.remove();
|
|
22854
|
-
}
|
|
22855
|
-
}
|
|
22856
|
-
_createElement(politeness) {
|
|
22857
|
-
const cls = `cps-${politeness}-live-announcer-element`;
|
|
22858
|
-
if (this._isBrowser) {
|
|
22859
|
-
const existing = this._document.body.querySelector(`.${cls}`);
|
|
22860
|
-
if (existing)
|
|
22861
|
-
return existing;
|
|
22862
|
-
}
|
|
22863
|
-
const el = this._document.createElement('div');
|
|
22864
|
-
if (!this._isBrowser)
|
|
22865
|
-
return el;
|
|
22866
|
-
el.setAttribute('aria-live', politeness);
|
|
22867
|
-
el.setAttribute('aria-atomic', 'true');
|
|
22868
|
-
el.className = `cps-sr-only ${cls}`;
|
|
22869
|
-
this._document.body.appendChild(el);
|
|
22870
|
-
return el;
|
|
22871
|
-
}
|
|
22872
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: CpsLiveAnnouncerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
22873
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: CpsLiveAnnouncerService, providedIn: 'root' }); }
|
|
22874
|
-
}
|
|
22875
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: CpsLiveAnnouncerService, decorators: [{
|
|
22876
|
-
type: Injectable,
|
|
22877
|
-
args: [{ providedIn: 'root' }]
|
|
22878
|
-
}] });
|
|
22879
|
-
/**
|
|
22880
|
-
* Injection token for the live-announcer service.
|
|
22881
|
-
*
|
|
22882
|
-
* By default it resolves to the singleton {@link CpsLiveAnnouncerService}.
|
|
22883
|
-
* Consumer applications can override it to supply a custom implementation or
|
|
22884
|
-
* provide `null` to disable all live-region announcements.
|
|
22885
|
-
*
|
|
22886
|
-
* @example Disable announcements:
|
|
22887
|
-
* ```typescript
|
|
22888
|
-
* providers: [{ provide: CPS_LIVE_ANNOUNCER_SERVICE, useValue: null }]
|
|
22889
|
-
* ```
|
|
22890
|
-
*/
|
|
22891
|
-
const CPS_LIVE_ANNOUNCER_SERVICE = new InjectionToken('CpsLiveAnnouncerService', {
|
|
22892
|
-
providedIn: 'root',
|
|
22893
|
-
factory: () => inject(CpsLiveAnnouncerService)
|
|
22894
|
-
});
|
|
22895
|
-
|
|
22896
22896
|
/**
|
|
22897
22897
|
* CpsLoaderComponent is a fetch data indicator.
|
|
22898
22898
|
* @group Components
|