angular-toolbox 1.2.3 → 1.3.1

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.
Files changed (35) hide show
  1. package/README.md +1 -1
  2. package/esm2022/lib/component/index.mjs +2 -1
  3. package/esm2022/lib/component/layout/border-layout/border-layout.component.mjs +125 -0
  4. package/esm2022/lib/component/layout/border-layout/util/border-layout-bounds-manager.mjs +211 -0
  5. package/esm2022/lib/component/layout/border-layout/util/border-layout-renderer.mjs +212 -0
  6. package/esm2022/lib/component/layout/border-layout/util/resize-method.mjs +9 -0
  7. package/esm2022/lib/component/layout/border-layout-container/border-layout-container.component.mjs +143 -0
  8. package/esm2022/lib/component/layout/index.mjs +3 -0
  9. package/esm2022/lib/framework/mock/http-monitoring-console/component/renderer/response-body-renderer/response-body-renderer.component.mjs +1 -1
  10. package/esm2022/lib/framework/mock/http-monitoring-console/component/renderer/response-preview-renderer/response-preview-renderer.component.mjs +1 -1
  11. package/esm2022/lib/model/business/ui/index.mjs +2 -1
  12. package/esm2022/lib/model/business/ui/layout/index.mjs +5 -0
  13. package/esm2022/lib/model/business/ui/layout/layout-constraints.mjs +9 -0
  14. package/esm2022/lib/model/business/ui/layout/layout-drag-event-type.enum.mjs +26 -0
  15. package/esm2022/lib/model/business/ui/layout/layout-drag.event.mjs +23 -0
  16. package/esm2022/lib/model/business/ui/layout/layout-region.mjs +35 -0
  17. package/esm2022/lib/model/service/version/angular-toolbox-version.service.mjs +4 -4
  18. package/fesm2022/angular-toolbox.mjs +2318 -1551
  19. package/fesm2022/angular-toolbox.mjs.map +1 -1
  20. package/lib/component/index.d.ts +1 -0
  21. package/lib/component/layout/border-layout/border-layout.component.d.ts +79 -0
  22. package/lib/component/layout/border-layout/util/border-layout-bounds-manager.d.ts +131 -0
  23. package/lib/component/layout/border-layout/util/border-layout-renderer.d.ts +87 -0
  24. package/lib/component/layout/border-layout/util/resize-method.d.ts +13 -0
  25. package/lib/component/layout/border-layout-container/border-layout-container.component.d.ts +104 -0
  26. package/lib/component/layout/index.d.ts +2 -0
  27. package/lib/framework/mock/http-monitoring-console/component/renderer/response-body-renderer/response-body-renderer.component.d.ts +1 -1
  28. package/lib/framework/mock/http-monitoring-console/component/renderer/response-preview-renderer/response-preview-renderer.component.d.ts +1 -1
  29. package/lib/model/business/ui/index.d.ts +1 -0
  30. package/lib/model/business/ui/layout/index.d.ts +4 -0
  31. package/lib/model/business/ui/layout/layout-constraints.d.ts +33 -0
  32. package/lib/model/business/ui/layout/layout-drag-event-type.enum.d.ts +24 -0
  33. package/lib/model/business/ui/layout/layout-drag.event.d.ts +33 -0
  34. package/lib/model/business/ui/layout/layout-region.d.ts +36 -0
  35. package/package.json +1 -1
@@ -1,10 +1,10 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, NgModule, EventEmitter, Component, Directive, Output, Input, HostListener, Inject, isDevMode, Optional, ChangeDetectionStrategy, Pipe, ViewEncapsulation, inject } from '@angular/core';
3
- import * as i1 from '@angular/router';
4
- import { RouterModule } from '@angular/router';
2
+ import { Injectable, NgModule, EventEmitter, Component, Inject, isDevMode, Optional, ChangeDetectionStrategy, Input, Pipe, Output, inject, ViewEncapsulation, HostBinding, HostListener, ViewChild, ContentChildren, Directive } from '@angular/core';
3
+ import { Observable, from, of } from 'rxjs';
5
4
  import * as i1$1 from '@angular/common';
6
5
  import { DOCUMENT, formatDate, CommonModule, DatePipe, NgStyle, XhrFactory } from '@angular/common';
7
- import { Observable, from, of } from 'rxjs';
6
+ import * as i1 from '@angular/router';
7
+ import { RouterModule } from '@angular/router';
8
8
  import * as i1$2 from '@angular/platform-browser';
9
9
  import { HttpContextToken, HttpHeaders, HttpContext, HttpParams, HttpRequest, HttpResponse, HttpStatusCode, HttpErrorResponse } from '@angular/common/http';
10
10
 
@@ -585,9 +585,9 @@ class AbstractVersionManager {
585
585
  */
586
586
  const LAYERS_VERSION_CONFIG = {
587
587
  major: 1,
588
- minor: 2,
589
- patch: 3,
590
- buildTimestamp: 1726052348239
588
+ minor: 3,
589
+ patch: 1,
590
+ buildTimestamp: 1726585120773
591
591
  };
592
592
  /**
593
593
  * The public service that exposes the current version of the Angular Toolbox library.
@@ -863,174 +863,141 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImpor
863
863
  * @license
864
864
  * Copyright Pascal ECHEMANN. All Rights Reserved.
865
865
  *
866
- * Use of this source code is governed by an MIT-style license that can be
867
- * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
866
+ * Use of this source code is governed by an MIT-style license that can be found in
867
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
868
868
  */
869
+ ;
869
870
 
870
871
  /**
871
872
  * @license
872
873
  * Copyright Pascal ECHEMANN. All Rights Reserved.
873
874
  *
874
- * Use of this source code is governed by an MIT-style license that can be
875
- * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
875
+ * Use of this source code is governed by an MIT-style license that can be found in
876
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
876
877
  */
878
+
877
879
  /**
878
- * @private
879
- * The base class for all directives that are responsible for navigation whithin ab Angular app.
880
+ * @license
881
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
882
+ *
883
+ * Use of this source code is governed by an MIT-style license that can be found in
884
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
880
885
  */
881
- class NavigationDirectiveBase {
886
+ /**
887
+ * The default provider for the `VersionService` configuration. You typically define
888
+ * the custom properties in the main `NgModule` declaration to initialize the application
889
+ * config:
890
+ *
891
+ * @NgModule({
892
+ * ...
893
+ * providers: [
894
+ * { provide: VERSION_CONFIG, useValue: { major: 1, minor: 2, patch: 12 } }
895
+ * ],
896
+ * ...
897
+ * });
898
+ */
899
+ const VERSION_CONFIG = {
882
900
  /**
883
- * @private
901
+ * Specifies the major number of this config.
884
902
  */
885
- constructor(elmRef, role) {
886
- this.elmRef = elmRef;
887
- const elm = elmRef.nativeElement;
888
- elm.role = role;
889
- elm.tabIndex = 0;
890
- }
891
- }
903
+ major: 0,
904
+ /**
905
+ * Specifies the minor number of this config.
906
+ */
907
+ minor: 0,
908
+ /**
909
+ * Specifies the patch number of this config.
910
+ */
911
+ patch: 0,
912
+ /**
913
+ * Specifies the timestamp that corresponds to the build date for this `Version` object.
914
+ * Default value is `NaN`.
915
+ */
916
+ buildTimestamp: NaN
917
+ };
892
918
 
893
919
  /**
894
920
  * @license
895
921
  * Copyright Pascal ECHEMANN. All Rights Reserved.
896
922
  *
897
- * Use of this source code is governed by an MIT-style license that can be
898
- * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
923
+ * Use of this source code is governed by an MIT-style license that can be found in
924
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
899
925
  */
926
+ ;
927
+
900
928
  /**
901
- * @private
929
+ * @license
930
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
931
+ *
932
+ * Use of this source code is governed by an MIT-style license that can be found in
933
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
902
934
  */
903
- const ENTER_KEY = 'Enter';
935
+
904
936
  /**
905
- * @private
937
+ * @license
938
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
939
+ *
940
+ * Use of this source code is governed by an MIT-style license that can be found in
941
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
906
942
  */
907
- const ROUTER_LINK_REF = 'ng-reflect-router-link';
908
943
  /**
909
- * An easy-to-use directive that enables keyboard navigation and provides support for keyboard "Enter" key events.
944
+ * Reference to the dark mode default storage key.
910
945
  */
911
- class ButtonRoleDirective extends NavigationDirectiveBase {
912
- /**
913
- * @private
914
- */
915
- onKeyup(event, value) {
916
- if (event.key !== ENTER_KEY)
917
- return;
918
- this.processEvent(event, value);
919
- }
946
+ const STORAGE_KEY = "dark-mode-key";
947
+ /**
948
+ * Reference to the dark mode default css property.
949
+ */
950
+ const CSS_PROP = "dark-mode";
951
+
952
+ /**
953
+ * @license
954
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
955
+ *
956
+ * Use of this source code is governed by an MIT-style license that can be found in
957
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
958
+ */
959
+ /**
960
+ * The default provider for the `DarkModeService` configuration. You typically define
961
+ * the custom properties in the main NgModule declaration to initialize the app dark mode:
962
+ *
963
+ * @NgModule({
964
+ * ...
965
+ * providers: [
966
+ * { provide: DARK_MODE_CONFIG, useValue: { enableDarkMode: true } }
967
+ * ],
968
+ * ...
969
+ * });
970
+ */
971
+ const DARK_MODE_CONFIG = {
920
972
  /**
921
- * @private
973
+ * Indicates whether the dark mode uses browser settings (`true`), or not (`false`).
974
+ * Default value is `false`.
922
975
  */
923
- onClick(event, value) {
924
- if (this.delegateClick === undefined)
925
- return;
926
- this.processEvent(event, value);
927
- }
976
+ darkModeEnabled: false,
928
977
  /**
929
- * @private
978
+ * Indicates whether the dark mode uses browser settings (`true`), or not (`false`).
979
+ * Default value is `false`.
930
980
  */
931
- constructor(elmRef, _router) {
932
- super(elmRef, BUTTON_ROLE);
933
- this._router = _router;
934
- /**
935
- * Dispatches events when the user presses the "Enter" key.
936
- */
937
- this.enter = new EventEmitter();
938
- /**
939
- * @private
940
- */
941
- this._routerLinkRef = null;
942
- }
981
+ detectBrowserSettings: false,
943
982
  /**
944
- * @private
983
+ * CSS property name used to set the dark mode look and feel.
984
+ * Default value is `'dark-mode'`.
945
985
  */
946
- ngAfterViewInit() {
947
- const elm = this.elmRef.nativeElement;
948
- this._routerLinkRef = elm.getAttribute(ROUTER_LINK_REF);
949
- }
986
+ cssProperty: CSS_PROP,
950
987
  /**
951
- * @private
988
+ * Reference to the key value used to persist the dark mode state to local storage.
989
+ * Default value is `'dark-mode-key'`.
952
990
  */
953
- processEvent(event, value) {
954
- event.preventDefault();
955
- event.stopImmediatePropagation();
956
- if (this._routerLinkRef) {
957
- this._router.navigate([this._routerLinkRef]);
958
- return;
959
- }
960
- this.elmRef.nativeElement.blur();
961
- this.enter.emit(value);
962
- }
963
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: ButtonRoleDirective, deps: [{ token: i0.ElementRef }, { token: i1.Router }], target: i0.ɵɵFactoryTarget.Directive }); }
964
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.0.3", type: ButtonRoleDirective, isStandalone: true, selector: "[buttonRole]", inputs: { delegateClick: "delegateClick" }, outputs: { enter: "enter" }, host: { listeners: { "keyup": "onKeyup($event,$event.target.value)", "click": "onClick($event,$event.target.value)" } }, providers: [
965
- RouterModule
966
- ], usesInheritance: true, ngImport: i0 }); }
967
- }
968
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: ButtonRoleDirective, decorators: [{
969
- type: Directive,
970
- args: [{
971
- selector: '[buttonRole]',
972
- providers: [
973
- RouterModule
974
- ],
975
- standalone: true
976
- }]
977
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1.Router }], propDecorators: { enter: [{
978
- type: Output
979
- }], delegateClick: [{
980
- type: Input
981
- }], onKeyup: [{
982
- type: HostListener,
983
- args: ['keyup', ["$event", "$event.target.value"]]
984
- }], onClick: [{
985
- type: HostListener,
986
- args: ['click', ["$event", "$event.target.value"]]
987
- }] } });
991
+ storageKey: STORAGE_KEY
992
+ };
988
993
 
989
994
  /**
990
995
  * @license
991
996
  * Copyright Pascal ECHEMANN. All Rights Reserved.
992
997
  *
993
- * Use of this source code is governed by an MIT-style license that can be
994
- * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
995
- */
996
- /**
997
- * An easy-to-use directive that enables keyboard navigation and provides support for navigating to an external URL.
998
+ * Use of this source code is governed by an MIT-style license that can be found in
999
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
998
1000
  */
999
- class NavigateToUrlDirective extends NavigationDirectiveBase {
1000
- /**
1001
- * @private
1002
- */
1003
- onClick() {
1004
- const HREF = this.href;
1005
- if (!HREF)
1006
- throw new ReferenceError("href attribute is not defined.");
1007
- this._document.defaultView.location.href = HREF;
1008
- }
1009
- /**
1010
- * @private
1011
- */
1012
- constructor(_document, elmRef) {
1013
- super(elmRef, LINK_ROLE);
1014
- this._document = _document;
1015
- }
1016
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: NavigateToUrlDirective, deps: [{ token: DOCUMENT }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
1017
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.0.3", type: NavigateToUrlDirective, isStandalone: true, selector: "[navigateToUrl]", inputs: { href: "href" }, host: { listeners: { "click": "onClick()" } }, usesInheritance: true, ngImport: i0 }); }
1018
- }
1019
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: NavigateToUrlDirective, decorators: [{
1020
- type: Directive,
1021
- args: [{
1022
- selector: '[navigateToUrl]',
1023
- standalone: true
1024
- }]
1025
- }], ctorParameters: () => [{ type: undefined, decorators: [{
1026
- type: Inject,
1027
- args: [DOCUMENT]
1028
- }] }, { type: i0.ElementRef }], propDecorators: { href: [{
1029
- type: Input
1030
- }], onClick: [{
1031
- type: HostListener,
1032
- args: ['click']
1033
- }] } });
1034
1001
 
1035
1002
  /**
1036
1003
  * @license
@@ -1039,142 +1006,70 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImpor
1039
1006
  * Use of this source code is governed by an MIT-style license that can be found in
1040
1007
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1041
1008
  */
1009
+
1042
1010
  /**
1043
- * @private
1044
- * An internal convenient object that defined default `ScrollIntoViewOptions` objects.
1011
+ * @license
1012
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
1013
+ *
1014
+ * Use of this source code is governed by an MIT-style license that can be found in
1015
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1045
1016
  */
1046
- const DEFAULT_SCROLL_BEHAVIOR = { behavior: "smooth", block: "start", inline: "nearest" };
1047
1017
 
1048
1018
  /**
1049
1019
  * @license
1050
1020
  * Copyright Pascal ECHEMANN. All Rights Reserved.
1051
1021
  *
1052
- * Use of this source code is governed by an MIT-style license that can be
1053
- * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1022
+ * Use of this source code is governed by an MIT-style license that can be found in
1023
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1054
1024
  */
1055
1025
  /**
1056
- * Provides functionality to activate anchor navigation through the native Angular router.
1026
+ * Specifies values used to activate, or deactivate, a feature for a browser window created by the `WindowService.open()` method.
1057
1027
  */
1058
- class AnchorLinklDirective extends NavigationDirectiveBase {
1028
+ var WindowFeatureState;
1029
+ (function (WindowFeatureState) {
1059
1030
  /**
1060
- * @private
1031
+ * The value used to activate a feature.
1061
1032
  */
1062
- onClick(event) {
1063
- event.preventDefault();
1064
- const HREF = this.href;
1065
- this._router.navigate([], { fragment: HREF.slice(1) });
1066
- this._document.querySelector(HREF).scrollIntoView(DEFAULT_SCROLL_BEHAVIOR);
1067
- }
1068
- /**
1069
- * @private
1070
- */
1071
- constructor(_document, elmRef, _router) {
1072
- super(elmRef, LINK_ROLE);
1073
- this._document = _document;
1074
- this._router = _router;
1075
- }
1033
+ WindowFeatureState["YES"] = "yes";
1076
1034
  /**
1077
- * @private
1035
+ * The value used to deactivate a feature.
1078
1036
  */
1079
- ngAfterViewInit() {
1080
- const HREF = this.href;
1081
- if (!HREF)
1082
- throw new ReferenceError("href attribute is not defined.");
1083
- }
1084
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AnchorLinklDirective, deps: [{ token: DOCUMENT }, { token: i0.ElementRef }, { token: i1.Router }], target: i0.ɵɵFactoryTarget.Directive }); }
1085
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.0.3", type: AnchorLinklDirective, isStandalone: true, selector: "[anchorLink]", inputs: { href: "href" }, host: { listeners: { "click": "onClick($event)" } }, usesInheritance: true, ngImport: i0 }); }
1086
- }
1087
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AnchorLinklDirective, decorators: [{
1088
- type: Directive,
1089
- args: [{
1090
- selector: '[anchorLink]',
1091
- standalone: true,
1092
- }]
1093
- }], ctorParameters: () => [{ type: undefined, decorators: [{
1094
- type: Inject,
1095
- args: [DOCUMENT]
1096
- }] }, { type: i0.ElementRef }, { type: i1.Router }], propDecorators: { href: [{
1097
- type: Input
1098
- }], onClick: [{
1099
- type: HostListener,
1100
- args: ['click', ['$event']]
1101
- }] } });
1037
+ WindowFeatureState["NO"] = "no";
1038
+ })(WindowFeatureState || (WindowFeatureState = {}));
1102
1039
 
1103
1040
  /**
1104
1041
  * @license
1105
1042
  * Copyright Pascal ECHEMANN. All Rights Reserved.
1106
1043
  *
1107
- * Use of this source code is governed by an MIT-style license that can be
1108
- * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1109
- */
1110
- /**
1111
- * @private
1044
+ * Use of this source code is governed by an MIT-style license that can be found in
1045
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1112
1046
  */
1113
- const CHILD_LIST_TYPE = "childList";
1114
1047
  /**
1115
- * Allows injection of any value into an HTML element container (`div`, `button`, etc...).
1116
- * A rendered event is emitted after the injected content has been rendered and is
1117
- * available for DOM manipulation.
1048
+ * Specifies the name of the browsing context the resource is being loaded into.
1118
1049
  */
1119
- class ContentRendererDirective {
1050
+ var WindowTarget;
1051
+ (function (WindowTarget) {
1120
1052
  /**
1121
- * @private
1053
+ * The current browsing context.
1122
1054
  */
1123
- constructor(_elmRef) {
1124
- this._elmRef = _elmRef;
1125
- /**
1126
- * Dispatches events when the content of the HTML element has been rendered.
1127
- */
1128
- this.rendered = new EventEmitter();
1129
- const nativeElement = this._elmRef.nativeElement;
1130
- this._observer = new MutationObserver((mutations) => {
1131
- mutations.forEach((mutation) => {
1132
- if (mutation.type === CHILD_LIST_TYPE)
1133
- this.rendered.emit(nativeElement);
1134
- });
1135
- });
1136
- }
1055
+ WindowTarget["SELF"] = "self";
1137
1056
  /**
1138
- * @private
1057
+ * Usually a new tab, but users can configure browsers to open a new window instead.
1139
1058
  */
1140
- ngOnDestroy() {
1141
- this._observer.disconnect();
1142
- }
1059
+ WindowTarget["BLANK"] = "_blank";
1143
1060
  /**
1144
- * @private
1061
+ * The parent browsing context of the current one. If no parent, behaves as `WindowTarget.SELF`.
1145
1062
  */
1146
- ngOnInit() {
1147
- this._observer.observe(this._elmRef.nativeElement, { attributes: false, childList: true, characterData: false });
1148
- }
1149
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: ContentRendererDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
1150
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.0.3", type: ContentRendererDirective, isStandalone: true, selector: "[contentRenderer]", outputs: { rendered: "rendered" }, ngImport: i0 }); }
1151
- }
1152
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: ContentRendererDirective, decorators: [{
1153
- type: Directive,
1154
- args: [{
1155
- selector: '[contentRenderer]',
1156
- standalone: true
1157
- }]
1158
- }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { rendered: [{
1159
- type: Output
1160
- }] } });
1161
-
1162
- /**
1163
- * @license
1164
- * Copyright Pascal ECHEMANN. All Rights Reserved.
1165
- *
1166
- * Use of this source code is governed by an MIT-style license that can be found in
1167
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1168
- */
1169
-
1170
- /**
1171
- * @license
1172
- * Copyright Pascal ECHEMANN. All Rights Reserved.
1173
- *
1174
- * Use of this source code is governed by an MIT-style license that can be found in
1175
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1176
- */
1177
- ;
1063
+ WindowTarget["PARENT"] = "_parent";
1064
+ /**
1065
+ * The topmost browsing context.
1066
+ */
1067
+ WindowTarget["TOP"] = "_top";
1068
+ /**
1069
+ * Allows embedded fenced frames to navigate the top-level frame.
1070
+ */
1071
+ WindowTarget["UNFENCED_TOP"] = "_unfencedTop";
1072
+ })(WindowTarget || (WindowTarget = {}));
1178
1073
 
1179
1074
  /**
1180
1075
  * @license
@@ -1192,45 +1087,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImpor
1192
1087
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1193
1088
  */
1194
1089
  /**
1195
- * The default provider for the `VersionService` configuration. You typically define
1196
- * the custom properties in the main `NgModule` declaration to initialize the application
1197
- * config:
1198
- *
1199
- * @NgModule({
1200
- * ...
1201
- * providers: [
1202
- * { provide: VERSION_CONFIG, useValue: { major: 1, minor: 2, patch: 12 } }
1203
- * ],
1204
- * ...
1205
- * });
1090
+ * The list of layout constraints that defines the regions of a `BorderLayout` container.
1206
1091
  */
1207
- const VERSION_CONFIG = {
1092
+ var LayoutRegion;
1093
+ (function (LayoutRegion) {
1208
1094
  /**
1209
- * Specifies the major number of this config.
1095
+ * The north layout constraint (top of container).
1210
1096
  */
1211
- major: 0,
1097
+ LayoutRegion["NORTH"] = "north";
1212
1098
  /**
1213
- * Specifies the minor number of this config.
1099
+ * The south layout constraint (bottom of container).
1214
1100
  */
1215
- minor: 0,
1101
+ LayoutRegion["SOUTH"] = "south";
1216
1102
  /**
1217
- * Specifies the patch number of this config.
1103
+ * The west layout constraint (left side of container).
1218
1104
  */
1219
- patch: 0,
1105
+ LayoutRegion["WEST"] = "west";
1220
1106
  /**
1221
- * Specifies the timestamp that corresponds to the build date for this `Version` object.
1222
- * Default value is `NaN`.
1107
+ * The east layout constraint (right side of container).
1223
1108
  */
1224
- buildTimestamp: NaN
1225
- };
1226
-
1227
- /**
1228
- * @license
1229
- * Copyright Pascal ECHEMANN. All Rights Reserved.
1230
- *
1231
- * Use of this source code is governed by an MIT-style license that can be found in
1232
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1233
- */
1109
+ LayoutRegion["EAST"] = "east";
1110
+ /**
1111
+ * The center layout constraint (middle of container).
1112
+ */
1113
+ LayoutRegion["CENTER"] = "center";
1114
+ })(LayoutRegion || (LayoutRegion = {}));
1234
1115
  ;
1235
1116
 
1236
1117
  /**
@@ -1240,22 +1121,21 @@ const VERSION_CONFIG = {
1240
1121
  * Use of this source code is governed by an MIT-style license that can be found in
1241
1122
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1242
1123
  */
1243
-
1244
- /**
1245
- * @license
1246
- * Copyright Pascal ECHEMANN. All Rights Reserved.
1247
- *
1248
- * Use of this source code is governed by an MIT-style license that can be found in
1249
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1250
- */
1251
- /**
1252
- * Reference to the dark mode default storage key.
1253
- */
1254
- const STORAGE_KEY = "dark-mode-key";
1255
1124
  /**
1256
- * Reference to the dark mode default css property.
1125
+ * The `LayoutDragEvent` class is an event that represents a drag interaction with a `BorderLayoutContainer`.
1257
1126
  */
1258
- const CSS_PROP = "dark-mode";
1127
+ class LayoutDragEvent {
1128
+ /**
1129
+ * Creates a new `LayoutDragEvent` instance.
1130
+ *
1131
+ * @param target The container that triggered this event.
1132
+ * @param type The type of this event.
1133
+ */
1134
+ constructor(target, type) {
1135
+ this.target = target;
1136
+ this.type = type;
1137
+ }
1138
+ }
1259
1139
 
1260
1140
  /**
1261
1141
  * @license
@@ -1265,39 +1145,23 @@ const CSS_PROP = "dark-mode";
1265
1145
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1266
1146
  */
1267
1147
  /**
1268
- * The default provider for the `DarkModeService` configuration. You typically define
1269
- * the custom properties in the main NgModule declaration to initialize the app dark mode:
1270
- *
1271
- * @NgModule({
1272
- * ...
1273
- * providers: [
1274
- * { provide: DARK_MODE_CONFIG, useValue: { enableDarkMode: true } }
1275
- * ],
1276
- * ...
1277
- * });
1148
+ * Defines the type of a `LayoutDragEvent` instance.
1278
1149
  */
1279
- const DARK_MODE_CONFIG = {
1280
- /**
1281
- * Indicates whether the dark mode uses browser settings (`true`), or not (`false`).
1282
- * Default value is `false`.
1283
- */
1284
- darkModeEnabled: false,
1150
+ var LayoutDragEventType;
1151
+ (function (LayoutDragEventType) {
1285
1152
  /**
1286
- * Indicates whether the dark mode uses browser settings (`true`), or not (`false`).
1287
- * Default value is `false`.
1153
+ * Indicates that the dragging process is starting.
1288
1154
  */
1289
- detectBrowserSettings: false,
1155
+ LayoutDragEventType["DRAG_START"] = "dragstart";
1290
1156
  /**
1291
- * CSS property name used to set the dark mode look and feel.
1292
- * Default value is `'dark-mode'`.
1157
+ * Indicates that the dragging process stopped.
1293
1158
  */
1294
- cssProperty: CSS_PROP,
1159
+ LayoutDragEventType["DRAG_STOP"] = "dragstop";
1295
1160
  /**
1296
- * Reference to the key value used to persist the dark mode state to local storage.
1297
- * Default value is `'dark-mode-key'`.
1161
+ * Indicates that the user is dragging the container handle.
1298
1162
  */
1299
- storageKey: STORAGE_KEY
1300
- };
1163
+ LayoutDragEventType["DRAGGING"] = "dragging";
1164
+ })(LayoutDragEventType || (LayoutDragEventType = {}));
1301
1165
 
1302
1166
  /**
1303
1167
  * @license
@@ -1330,20 +1194,6 @@ const DARK_MODE_CONFIG = {
1330
1194
  * Use of this source code is governed by an MIT-style license that can be found in
1331
1195
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1332
1196
  */
1333
- /**
1334
- * Specifies values used to activate, or deactivate, a feature for a browser window created by the `WindowService.open()` method.
1335
- */
1336
- var WindowFeatureState;
1337
- (function (WindowFeatureState) {
1338
- /**
1339
- * The value used to activate a feature.
1340
- */
1341
- WindowFeatureState["YES"] = "yes";
1342
- /**
1343
- * The value used to deactivate a feature.
1344
- */
1345
- WindowFeatureState["NO"] = "no";
1346
- })(WindowFeatureState || (WindowFeatureState = {}));
1347
1197
 
1348
1198
  /**
1349
1199
  * @license
@@ -1352,32 +1202,6 @@ var WindowFeatureState;
1352
1202
  * Use of this source code is governed by an MIT-style license that can be found in
1353
1203
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1354
1204
  */
1355
- /**
1356
- * Specifies the name of the browsing context the resource is being loaded into.
1357
- */
1358
- var WindowTarget;
1359
- (function (WindowTarget) {
1360
- /**
1361
- * The current browsing context.
1362
- */
1363
- WindowTarget["SELF"] = "self";
1364
- /**
1365
- * Usually a new tab, but users can configure browsers to open a new window instead.
1366
- */
1367
- WindowTarget["BLANK"] = "_blank";
1368
- /**
1369
- * The parent browsing context of the current one. If no parent, behaves as `WindowTarget.SELF`.
1370
- */
1371
- WindowTarget["PARENT"] = "_parent";
1372
- /**
1373
- * The topmost browsing context.
1374
- */
1375
- WindowTarget["TOP"] = "_top";
1376
- /**
1377
- * Allows embedded fenced frames to navigate the top-level frame.
1378
- */
1379
- WindowTarget["UNFENCED_TOP"] = "_unfencedTop";
1380
- })(WindowTarget || (WindowTarget = {}));
1381
1205
 
1382
1206
  /**
1383
1207
  * @license
@@ -1442,51 +1266,11 @@ var WindowTarget;
1442
1266
  * Use of this source code is governed by an MIT-style license that can be found in
1443
1267
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1444
1268
  */
1445
-
1446
1269
  /**
1447
- * @license
1448
- * Copyright Pascal ECHEMANN. All Rights Reserved.
1449
- *
1450
- * Use of this source code is governed by an MIT-style license that can be found in
1451
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1270
+ * The markup interface for `Observable` object built from the Fetch API.
1452
1271
  */
1453
-
1454
- /**
1455
- * @license
1456
- * Copyright Pascal ECHEMANN. All Rights Reserved.
1457
- *
1458
- * Use of this source code is governed by an MIT-style license that can be found in
1459
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1460
- */
1461
-
1462
- /**
1463
- * @license
1464
- * Copyright Pascal ECHEMANN. All Rights Reserved.
1465
- *
1466
- * Use of this source code is governed by an MIT-style license that can be found in
1467
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1468
- */
1469
-
1470
- /**
1471
- * @license
1472
- * Copyright Pascal ECHEMANN. All Rights Reserved.
1473
- *
1474
- * Use of this source code is governed by an MIT-style license that can be found in
1475
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1476
- */
1477
-
1478
- /**
1479
- * @license
1480
- * Copyright Pascal ECHEMANN. All Rights Reserved.
1481
- *
1482
- * Use of this source code is governed by an MIT-style license that can be found in
1483
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1484
- */
1485
- /**
1486
- * The markup interface for `Observable` object built from the Fetch API.
1487
- */
1488
- class FetchClient extends Observable {
1489
- }
1272
+ class FetchClient extends Observable {
1273
+ }
1490
1274
 
1491
1275
  /**
1492
1276
  * @license
@@ -1994,6 +1778,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImpor
1994
1778
  args: [DOCUMENT]
1995
1779
  }] }] });
1996
1780
 
1781
+ /**
1782
+ * @license
1783
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
1784
+ *
1785
+ * Use of this source code is governed by an MIT-style license that can be found in
1786
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1787
+ */
1788
+ /**
1789
+ * @private
1790
+ * An internal convenient object that defined default `ScrollIntoViewOptions` objects.
1791
+ */
1792
+ const DEFAULT_SCROLL_BEHAVIOR = { behavior: "smooth", block: "start", inline: "nearest" };
1793
+
1997
1794
  /**
1998
1795
  * @license
1999
1796
  * Copyright Pascal ECHEMANN. All Rights Reserved.
@@ -6084,37 +5881,6 @@ class LogMetadataConverter {
6084
5881
  * Use of this source code is governed by an MIT-style license that can be found in
6085
5882
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6086
5883
  */
6087
- /**
6088
- * @private
6089
- * A utility class that converts `Log` objects into `AtxHttpLogDto` objects.
6090
- */
6091
- class LogConverter {
6092
- /**
6093
- * @private
6094
- * Converts a `object` object into an `AtxHttpLogDto` object.
6095
- *
6096
- * @param log The `Log` object to convert.
6097
- * @returns A new `AtxHttpLogDto` object.
6098
- */
6099
- static logToDto(log) {
6100
- return {
6101
- level: log.level,
6102
- timestamp: log.timestamp,
6103
- metadata: LogMetadataConverter.metadataToDto(log.metadata)
6104
- };
6105
- }
6106
- /**
6107
- * @private
6108
- * Converts an `AtxHttpLogDto` object into a `Log` object.
6109
- *
6110
- * @param dto The `AtxHttpLogDto` object to convert.
6111
- * @returns A new `Log` object.
6112
- */
6113
- static dtoToLog(dto) {
6114
- const level = dto.level;
6115
- return LogBuilder.build(HttpMockLoggingConstant.CALLER, LogMessageUtil.getMessageFromLevel(level), level, LogMetadataConverter.dtoToMetadata(dto.metadata));
6116
- }
6117
- }
6118
5884
 
6119
5885
  /**
6120
5886
  * @license
@@ -6124,24 +5890,43 @@ class LogConverter {
6124
5890
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6125
5891
  */
6126
5892
  /**
6127
- * @private
6128
- * A utility class that creates `HMFL` objects.
5893
+ * The definition function for the `@HttpMock` decorator.
5894
+ *
5895
+ * @param config The `HttpMockConfig` object used to initialize the HTTP Mocking Framework.
6129
5896
  */
6130
- class HMFLBuilder {
6131
- /**
6132
- * @private
6133
- * Creates and returns a new `HMFL` object.
6134
- *
6135
- * @param logDtoList The list of serialized logs to include in the new `HMFL` object.
6136
- * @returns A new `HMFL` object.
6137
- */
6138
- static build(logDtoList) {
6139
- return {
6140
- logs: logDtoList,
6141
- timestamp: Date.now()
5897
+ const HttpMock = (config) => {
5898
+ return (constructor) => {
5899
+ const getMockService = (instance) => {
5900
+ return Object.values(instance).find((v) => {
5901
+ return (v.hasOwnProperty('type') && v.type === HTTP_MOCK_SERVICE);
5902
+ });
6142
5903
  };
6143
- }
6144
- }
5904
+ const ngOnInit = constructor.prototype.ngOnInit;
5905
+ const ngOnDestroy = constructor.prototype.ngOnDestroy;
5906
+ const uiid = config.id || Uuid.build();
5907
+ if (!ngOnDestroy)
5908
+ throw new ReferenceError("Component must implement the OnDestroy interface.");
5909
+ if (!ngOnInit)
5910
+ throw new ReferenceError("Component must implement the OnInit interface.");
5911
+ if (!config.id)
5912
+ config.id = uiid;
5913
+ constructor.prototype.ngOnInit = function () {
5914
+ const mockService = getMockService(this);
5915
+ if (!mockService)
5916
+ throw new ReferenceError("No provider found for HttpMockService.");
5917
+ mockService.addConfig(config);
5918
+ ngOnInit.call(this);
5919
+ };
5920
+ constructor.prototype.ngOnDestroy = function () {
5921
+ const mockService = getMockService(this);
5922
+ // An exception is already thrown by the ngOnInit() method when HttpMockService is not provided.
5923
+ // Following check statement prevents failure during Unit Testing:
5924
+ if (mockService)
5925
+ mockService.removeConfig(uiid);
5926
+ ngOnDestroy.call(this);
5927
+ };
5928
+ };
5929
+ };
6145
5930
 
6146
5931
  /**
6147
5932
  * @license
@@ -6151,152 +5936,134 @@ class HMFLBuilder {
6151
5936
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6152
5937
  */
6153
5938
  /**
6154
- * @private
6155
- */
6156
- const BLOB_TYPE = { type: 'application/json' };
6157
- /**
6158
- * @private
6159
- */
6160
- const UTF8 = "UTF-8";
6161
- /**
6162
- * @private
6163
- * The service responsible for exporting and importing `hmfl` log files.
5939
+ * A statefull builder for creating new `HttpHeaders` instances.
6164
5940
  */
6165
- class AtxLogIoService {
5941
+ class HttpHeadersMockBuilder {
5942
+ constructor() {
5943
+ /**
5944
+ * @private
5945
+ */
5946
+ this._headers = new HttpHeaders();
5947
+ }
6166
5948
  /**
6167
- * @private
5949
+ * Sets the `"Cache-Control"` property of the new `HttpHeaders` instance with the specified value.
5950
+ *
5951
+ * @param value The value used to set the `"Cache-Control"` property of the new `HttpHeaders` instance.
5952
+ * Default value is `"no-cache"`.
5953
+ *
5954
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
6168
5955
  */
6169
- constructor(_logger) {
6170
- this._logger = _logger;
5956
+ cacheControl(value = "no-cache") {
5957
+ this.setHeader("Cache-Control", value);
5958
+ return this;
6171
5959
  }
6172
5960
  /**
6173
- * @private
6174
- * Exports the specified logs into a hmfl file.
5961
+ * Sets the `"CContent-Type"` property of the new `HttpHeaders` instance with the specified value.
6175
5962
  *
6176
- * @param logs The logs to exports.
5963
+ * @param value The value used to set the `"Content-Type"` property of the new `HttpHeaders` instance.
5964
+ * Default value is `"application/json; charset=utf-8"`.
5965
+ *
5966
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
6177
5967
  */
6178
- exportFile(logs) {
6179
- const logDtoList = [];
6180
- let cursor = logs.length - 1;
6181
- for (; cursor >= 0; cursor--) {
6182
- const log = logs[cursor];
6183
- if (log.level !== LogLevel.CONFIG)
6184
- logDtoList.push(LogConverter.logToDto(log));
6185
- }
6186
- const exportData = HMFLBuilder.build(logDtoList);
6187
- const a = document.createElement("a");
6188
- const file = new Blob([JSON.stringify(exportData)], BLOB_TYPE);
6189
- const timeFmt = formatDate(exportData.timestamp, "MM/dd/yy-hh:mm-a", "en-US");
6190
- a.href = URL.createObjectURL(file);
6191
- a.download = `logs-${timeFmt}.hmfl`;
6192
- a.click();
5968
+ contentType(value = "application/json; charset=utf-8") {
5969
+ this.setHeader("Content-Type", value);
5970
+ return this;
6193
5971
  }
6194
5972
  /**
6195
- * @private
6196
- * Imports the logs loaded through the specified `FileList` object.
5973
+ * Sets the `"Priority"` property of the new `HttpHeaders` instance with the specified value.
6197
5974
  *
6198
- * @param fileList The logs to import.
5975
+ * @param value The value used to set the `"Priority"` property of the new `HttpHeaders` instance.
5976
+ * Default value is `"u=0, i"`.
5977
+ *
5978
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
6199
5979
  */
6200
- importFile(fileList) {
6201
- const logger = this._logger;
6202
- const files = fileList[0];
6203
- const killReader = this.killReader;
6204
- if (files) {
6205
- const reader = new FileReader();
6206
- reader.readAsText(files, UTF8);
6207
- reader.onload = () => {
6208
- const result = reader.result;
6209
- const resultLogData = JSON.parse(result);
6210
- const logs = resultLogData.logs;
6211
- let cursor = logs.length - 1;
6212
- for (; cursor >= 0; cursor--) {
6213
- const log = LogConverter.dtoToLog(logs[cursor]);
6214
- const metadata = log.metadata;
6215
- const level = log.level;
6216
- if (level === LogLevel.INFO)
6217
- logger.info(metadata);
6218
- else if (level === LogLevel.ERROR)
6219
- logger.error(metadata);
6220
- }
6221
- ;
6222
- killReader(reader);
6223
- };
6224
- reader.onerror = (e) => {
6225
- killReader(reader);
6226
- console.log(e);
6227
- };
6228
- }
5980
+ priority(value = "u=0, i") {
5981
+ this.setHeader("Priority", value);
5982
+ return this;
6229
5983
  }
6230
5984
  /**
6231
- * @private
5985
+ * Sets the `"User-Agent"` property of the new `HttpHeaders` instance with the specified value.
5986
+ *
5987
+ * @param value The value used to set the `"User-Agent"` property of the new `HttpHeaders` instance.
5988
+ * Default value is the navigator user agent.
5989
+ *
5990
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
6232
5991
  */
6233
- killReader(reader) {
6234
- reader.onload = null;
6235
- reader.onerror = null;
5992
+ userAgent(value = null) {
5993
+ this.setHeader("User-Agent", value || navigator.userAgent);
5994
+ return this;
6236
5995
  }
6237
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxLogIoService, deps: [{ token: HttpMockLoggingService }], target: i0.ɵɵFactoryTarget.Injectable }); }
6238
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxLogIoService }); }
6239
- }
6240
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxLogIoService, decorators: [{
6241
- type: Injectable
6242
- }], ctorParameters: () => [{ type: HttpMockLoggingService }] });
6243
-
6244
- /**
6245
- * @license
6246
- * Copyright Pascal ECHEMANN. All Rights Reserved.
6247
- *
6248
- * Use of this source code is governed by an MIT-style license that can be found in
6249
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6250
- */
6251
- /**
6252
- * @private
6253
- * An implementation of the `LogConnector` class that sends logs to the HTTP
6254
- * mocking console component.
6255
- */
6256
- class HttpMonitoringConsoleLogConnector {
6257
- constructor() {
6258
- /**
6259
- * @private
6260
- */
6261
- this.logs = [];
6262
- /**
6263
- * @private
6264
- */
6265
- this.change = new EventEmitter(true);
5996
+ /**
5997
+ * Sets the `"Accept-Language"` property of the new `HttpHeaders` instance with the specified value.
5998
+ *
5999
+ * @param value The value used to set the `"Accept-Language"` property of the new `HttpHeaders` instance.
6000
+ * Default value is the navigator language.
6001
+ *
6002
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
6003
+ */
6004
+ acceptLanguage(value = null) {
6005
+ this.setHeader("Accept-Language", value || navigator.language);
6006
+ return this;
6266
6007
  }
6267
6008
  /**
6268
- * @private
6009
+ * Sets the `"Accept"` property of the new `HttpHeaders` instance with the specified value.
6010
+ *
6011
+ * @param value The value used to set the `"Accept"` property of the new `HttpHeaders` instance.
6012
+ * Default value is `'*\/*'`.
6013
+ *
6014
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
6269
6015
  */
6270
- destroy() {
6271
- this.clearLogs();
6016
+ accept(value = "*/*") {
6017
+ this.setHeader("Accept", value);
6018
+ return this;
6272
6019
  }
6273
6020
  /**
6274
- * @private
6021
+ * Sets the `"Accept-Encoding"` property of the new `HttpHeaders` instance with the specified value.
6022
+ *
6023
+ * @param value The value used to set the `"Accept-Encoding"` property of the new `HttpHeaders` instance.
6024
+ * Default value is `"ngzip, deflate, br, zstd"`.
6025
+ *
6026
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
6275
6027
  */
6276
- init(logList) {
6277
- this.logs.push(...logList);
6028
+ acceptEncoding(value = "gzip, deflate, br, zstd") {
6029
+ this.setHeader("Accept-Encoding", value);
6030
+ return this;
6278
6031
  }
6279
6032
  /**
6280
- * @private
6033
+ * Sets or modifies a value of the new `HttpHeaders` instance.
6034
+ *
6035
+ * @param name The header name.
6036
+ * @param value The value or values to set or override for the given header.
6037
+ *
6038
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
6281
6039
  */
6282
- sendLog(log) {
6283
- const level = log.level;
6284
- if (level === LogLevel.INFO || level === LogLevel.ERROR)
6285
- this.logs.push(log);
6286
- this.change.emit(log);
6040
+ set(name, value) {
6041
+ this.setHeader(name, value);
6042
+ return this;
6287
6043
  }
6288
6044
  /**
6289
- * @private
6045
+ * Return a new `HttpHeaders` instance, built from the properties specified with the
6046
+ * `HttpHeadersMockBuilder` methods.
6047
+ *
6048
+ * @returns A new `HttpHeaders` instance.
6290
6049
  */
6291
- clearLogs() {
6292
- this.logs.length = 0;
6050
+ headers() {
6051
+ return this._headers;
6293
6052
  }
6294
6053
  /**
6295
6054
  * @private
6296
- * Not supported.
6297
6055
  */
6298
- copyLogs() { }
6056
+ setHeader(name, value) {
6057
+ const values = Array.isArray(value) ? value.join(", ") : value;
6058
+ this._headers = this._headers.set(name, values);
6059
+ }
6299
6060
  }
6061
+ /**
6062
+ * A utility function used to create new "chainable" `HttpHeadersMockBuilder` instances.
6063
+ *
6064
+ * @returns A new `HttpHeadersMockBuilder` instance;
6065
+ */
6066
+ const httpHeadersMock = () => new HttpHeadersMockBuilder();
6300
6067
 
6301
6068
  /**
6302
6069
  * @license
@@ -6307,83 +6074,64 @@ class HttpMonitoringConsoleLogConnector {
6307
6074
  */
6308
6075
  /**
6309
6076
  * @private
6310
- * The service that manages user interactions with an `AtxMonitoringConsoleComponent` instance.
6077
+ * Internal reference to a new line character.
6311
6078
  */
6312
- class AtxMonitoringConsoleController extends IdentifiableComponent {
6313
- /**
6314
- * @private
6315
- */
6316
- constructor(_logger, _state, _ioSvc, _subscribe, action) {
6317
- super("AtxMonitoringConsoleController");
6318
- this._logger = _logger;
6319
- this._state = _state;
6320
- this._ioSvc = _ioSvc;
6321
- this._subscribe = _subscribe;
6322
- const connector = new HttpMonitoringConsoleLogConnector();
6323
- const logs = this._logger.getLogs();
6324
- this.connector = connector;
6325
- this._subscribe.register(this, connector.change.subscribe((log) => this.addLog(log)))
6326
- .append(action.action.subscribe((action) => this.onAction(action)));
6327
- this.connector.init(logs);
6328
- this._state.init(logs);
6329
- this._logger.setLogConnector(connector);
6330
- }
6331
- /**
6332
- * @private
6333
- */
6334
- ngOnDestroy() {
6335
- this._subscribe.clearAll(this);
6336
- this._logger.setLogConnector(null);
6337
- this.connector.destroy();
6338
- this.connector = null;
6339
- }
6340
- /**
6341
- * @private
6342
- */
6343
- clearLogs() {
6344
- this._logger.clearLogs();
6345
- this._state.clearLogs();
6346
- }
6079
+ const CRLF = "\r\n";
6080
+ /**
6081
+ * @private
6082
+ * A set of static utilities for manipulating `HttpHeaders` objects.
6083
+ */
6084
+ class HttpHeadersUtil {
6347
6085
  /**
6348
6086
  * @private
6087
+ * Returns a string representation the the specified `HttpHeaders `object, compatible with the format
6088
+ * expected by the `XMLHttpRequest.getAllResponseHeaders()` method.
6089
+ *
6090
+ * @param headers The `HttpHeaders` object to format.
6091
+ *
6092
+ * @returns A string compatible with the format expected by the `XMLHttpRequest.getAllResponseHeaders()` method.
6349
6093
  */
6350
- exportLogs() {
6351
- this._ioSvc.exportFile(this._state.logs);
6094
+ static stringify(headers) {
6095
+ let result = EMPTY_STRING;
6096
+ if (!headers)
6097
+ return result;
6098
+ const keys = headers.keys();
6099
+ const last = keys.length - 1;
6100
+ keys.forEach((key, index) => {
6101
+ result += `${key}: ${headers.getAll(key)}${index !== last ? CRLF : EMPTY_STRING}`;
6102
+ });
6103
+ return result;
6352
6104
  }
6353
6105
  /**
6354
6106
  * @private
6107
+ * Returns a `HttpHeaders` object built from the string returns by the `XMLHttpRequest.getAllResponseHeaders()` method,
6108
+ * or `null` wheher `XMLHttpRequest.getAllResponseHeaders()` return `null`.
6109
+ *
6110
+ * @param value The string to turn into a `HttpHeaders `object.
6111
+ *
6112
+ * @returns A `HttpHeaders` object, or `null`.
6355
6113
  */
6356
- addLog(log) {
6357
- this._state.addLog(log);
6114
+ static encode(value) {
6115
+ if (value === null)
6116
+ return null;
6117
+ return new HttpHeaders(value);
6358
6118
  }
6359
6119
  /**
6360
6120
  * @private
6121
+ * Creates the default `HttpHeaders` object for a mocked HTTP request.
6122
+ *
6123
+ * @returns The default `HttpHeaders` object for a mocked HTTP request.
6361
6124
  */
6362
- onAction(action) {
6363
- switch (action.type) {
6364
- case AtxConsoleActionType.CLEAR_LOGS:
6365
- this.clearLogs();
6366
- break;
6367
- case AtxConsoleActionType.EXPORT_LOGS:
6368
- this.exportLogs();
6369
- break;
6370
- case AtxConsoleActionType.IMPORT_LOGS:
6371
- this._ioSvc.importFile(action.data);
6372
- break;
6373
- case AtxConsoleActionType.LOG_SELECT:
6374
- this._state.selectLog(action.data);
6375
- break;
6376
- case AtxConsoleActionType.CLOSE_DETAILS_PANEL:
6377
- this._state.selectLog(null);
6378
- break;
6379
- }
6125
+ static createDefaultRequestHeaders() {
6126
+ // "Accept" header is set by Angular framework when missing
6127
+ return httpHeadersMock().cacheControl()
6128
+ .acceptEncoding()
6129
+ .acceptLanguage()
6130
+ .priority()
6131
+ .userAgent()
6132
+ .headers();
6380
6133
  }
6381
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxMonitoringConsoleController, deps: [{ token: HttpMockLoggingService }, { token: AtxMonitoringConsoleState }, { token: AtxLogIoService }, { token: SubscriptionService }, { token: AtxUserActionService }], target: i0.ɵɵFactoryTarget.Injectable }); }
6382
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxMonitoringConsoleController }); }
6383
6134
  }
6384
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxMonitoringConsoleController, decorators: [{
6385
- type: Injectable
6386
- }], ctorParameters: () => [{ type: HttpMockLoggingService }, { type: AtxMonitoringConsoleState }, { type: AtxLogIoService }, { type: SubscriptionService }, { type: AtxUserActionService }] });
6387
6135
 
6388
6136
  /**
6389
6137
  * @license
@@ -6393,44 +6141,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImpor
6393
6141
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6394
6142
  */
6395
6143
  /**
6396
- * @private
6397
- * The main component used to layout the ATX monitoring console.
6144
+ * A convenient constant that represents the maximum value for a delayed HTTP response.
6398
6145
  */
6399
- class AtxMonitoringConsoleComponent {
6400
- /**
6401
- * @private
6402
- */
6403
- constructor(state,
6404
- //--> Conponent scope services:
6405
- _ctrl, _io, _input) {
6406
- this.state = state;
6407
- this._ctrl = _ctrl;
6408
- this._io = _io;
6409
- this._input = _input;
6410
- }
6411
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxMonitoringConsoleComponent, deps: [{ token: AtxMonitoringConsoleState }, { token: AtxMonitoringConsoleController }, { token: AtxLogIoService }, { token: AtxUserActionService }], target: i0.ɵɵFactoryTarget.Component }); }
6412
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.3", type: AtxMonitoringConsoleComponent, isStandalone: true, selector: "atx-http-monitoring-console", providers: [
6413
- AtxMonitoringConsoleState,
6414
- AtxLogIoService,
6415
- AtxMonitoringConsoleController,
6416
- AtxUserActionService
6417
- ], ngImport: i0, template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n<atx-console-menu/>\r\n<div id=\"log-list-vieport\">\r\n <div class=\"request-list-wrapper\" [class.reduced-request-list]=\"state.selectedLog\">\r\n <atx-request-list-renderer />\r\n </div>\r\n @if (state.selectedLog) {\r\n <div id=\"selected-log-viewport\">\r\n <atx-monitoring-console-details [log]=\"state.selectedLog\"/>\r\n </div>\r\n }\r\n</div>\r\n<atx-console-footer/>\r\n\r\n<svg id=\"icon-collection\">\r\n <symbol id=\"json-icon\" viewBox=\"0 0 16 16\">\r\n <path d=\"M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z\"/>\r\n <path d=\"M8.646 6.646a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L10.293 9 8.646 7.354a.5.5 0 0 1 0-.708m-1.292 0a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0 0 .708l2 2a.5.5 0 0 0 .708-.708L5.707 9l1.647-1.646a.5.5 0 0 0 0-.708\"/>\r\n </symbol>\r\n <symbol id=\"bin-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M5.526 13.09c.976 0 1.524-.79 1.524-2.205 0-1.412-.548-2.203-1.524-2.203-.978 0-1.526.79-1.526 2.203 0 1.415.548 2.206 1.526 2.206zm-.832-2.205c0-1.05.29-1.612.832-1.612.358 0 .607.247.733.721L4.7 11.137a7 7 0 0 1-.006-.252m.832 1.614c-.36 0-.606-.246-.732-.718l1.556-1.145q.005.12.005.249c0 1.052-.29 1.614-.829 1.614m5.329.501v-.595H9.73V8.772h-.69l-1.19.786v.688L8.986 9.5h.05v2.906h-1.18V13h3z\"/>\r\n <path d=\"M4 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zm0 1h8a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1\"/>\r\n </symbol>\r\n <symbol id=\"text-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M10.943 6H5.057L5 8h.5c.18-1.096.356-1.192 1.694-1.235l.293-.01v5.09c0 .47-.1.582-.898.655v.5H9.41v-.5c-.803-.073-.903-.184-.903-.654V6.755l.298.01c1.338.043 1.514.14 1.694 1.235h.5l-.057-2z\"/>\r\n <path d=\"M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z\"/>\r\n </symbol>\r\n <symbol id=\"empty-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z\"/>\r\n </symbol>\r\n <symbol id=\"blob-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M8.002 5.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0\"/>\r\n <path d=\"M12 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2M3 2a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v8l-2.083-2.083a.5.5 0 0 0-.76.063L8 11 5.835 9.7a.5.5 0 0 0-.611.076L3 12z\"/>\r\n </symbol>\r\n</svg>", styles: [":host{--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;--header-height: 26px;display:block}:host,table{padding:0;margin:0;font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:12px;color:#000;background-color:#fff}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)!important}th{height:var(--header-height)}.header-btn{margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}summary{-webkit-user-select:none;user-select:none}:host{position:relative;padding:0;margin:0;overflow:hidden}#log-list-vieport{position:absolute;display:flex;flex-direction:row;gap:6px;padding:6px;inset:36px 0 33px}#icon-collection{visibility:hidden;width:0;height:0}.request-list-wrapper{height:100%;flex-grow:1;overflow:hidden auto;border:1px solid var(--border-color)}.reduced-request-list{min-width:250px}#selected-log-viewport{height:100%;width:80%}atx-console-footer{position:absolute;width:100%;bottom:0}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"], dependencies: [{ kind: "component", type: AtxRequestDetailsComponent, selector: "atx-monitoring-console-details", inputs: ["log"] }, { kind: "component", type: AtxConsoleFooterComponent, selector: "atx-console-footer" }, { kind: "component", type: AtxConsoleMenuComponent, selector: "atx-console-menu" }, { kind: "component", type: AtxRequestListRendererComponent, selector: "atx-request-list-renderer" }], encapsulation: i0.ViewEncapsulation.ShadowDom }); }
6418
- }
6419
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxMonitoringConsoleComponent, decorators: [{
6420
- type: Component,
6421
- args: [{ selector: 'atx-http-monitoring-console', standalone: true, imports: [
6422
- AtxRequestDetailsComponent,
6423
- AtxConsoleFooterComponent,
6424
- AtxConsoleMenuComponent,
6425
- AtxIconRendererComponent,
6426
- AtxRequestListRendererComponent
6427
- ], providers: [
6428
- AtxMonitoringConsoleState,
6429
- AtxLogIoService,
6430
- AtxMonitoringConsoleController,
6431
- AtxUserActionService
6432
- ], encapsulation: ViewEncapsulation.ShadowDom, template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n<atx-console-menu/>\r\n<div id=\"log-list-vieport\">\r\n <div class=\"request-list-wrapper\" [class.reduced-request-list]=\"state.selectedLog\">\r\n <atx-request-list-renderer />\r\n </div>\r\n @if (state.selectedLog) {\r\n <div id=\"selected-log-viewport\">\r\n <atx-monitoring-console-details [log]=\"state.selectedLog\"/>\r\n </div>\r\n }\r\n</div>\r\n<atx-console-footer/>\r\n\r\n<svg id=\"icon-collection\">\r\n <symbol id=\"json-icon\" viewBox=\"0 0 16 16\">\r\n <path d=\"M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z\"/>\r\n <path d=\"M8.646 6.646a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L10.293 9 8.646 7.354a.5.5 0 0 1 0-.708m-1.292 0a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0 0 .708l2 2a.5.5 0 0 0 .708-.708L5.707 9l1.647-1.646a.5.5 0 0 0 0-.708\"/>\r\n </symbol>\r\n <symbol id=\"bin-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M5.526 13.09c.976 0 1.524-.79 1.524-2.205 0-1.412-.548-2.203-1.524-2.203-.978 0-1.526.79-1.526 2.203 0 1.415.548 2.206 1.526 2.206zm-.832-2.205c0-1.05.29-1.612.832-1.612.358 0 .607.247.733.721L4.7 11.137a7 7 0 0 1-.006-.252m.832 1.614c-.36 0-.606-.246-.732-.718l1.556-1.145q.005.12.005.249c0 1.052-.29 1.614-.829 1.614m5.329.501v-.595H9.73V8.772h-.69l-1.19.786v.688L8.986 9.5h.05v2.906h-1.18V13h3z\"/>\r\n <path d=\"M4 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zm0 1h8a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1\"/>\r\n </symbol>\r\n <symbol id=\"text-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M10.943 6H5.057L5 8h.5c.18-1.096.356-1.192 1.694-1.235l.293-.01v5.09c0 .47-.1.582-.898.655v.5H9.41v-.5c-.803-.073-.903-.184-.903-.654V6.755l.298.01c1.338.043 1.514.14 1.694 1.235h.5l-.057-2z\"/>\r\n <path d=\"M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z\"/>\r\n </symbol>\r\n <symbol id=\"empty-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z\"/>\r\n </symbol>\r\n <symbol id=\"blob-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M8.002 5.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0\"/>\r\n <path d=\"M12 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2M3 2a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v8l-2.083-2.083a.5.5 0 0 0-.76.063L8 11 5.835 9.7a.5.5 0 0 0-.611.076L3 12z\"/>\r\n </symbol>\r\n</svg>", styles: [":host{--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;--header-height: 26px;display:block}:host,table{padding:0;margin:0;font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:12px;color:#000;background-color:#fff}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)!important}th{height:var(--header-height)}.header-btn{margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}summary{-webkit-user-select:none;user-select:none}:host{position:relative;padding:0;margin:0;overflow:hidden}#log-list-vieport{position:absolute;display:flex;flex-direction:row;gap:6px;padding:6px;inset:36px 0 33px}#icon-collection{visibility:hidden;width:0;height:0}.request-list-wrapper{height:100%;flex-grow:1;overflow:hidden auto;border:1px solid var(--border-color)}.reduced-request-list{min-width:250px}#selected-log-viewport{height:100%;width:80%}atx-console-footer{position:absolute;width:100%;bottom:0}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }]
6433
- }], ctorParameters: () => [{ type: AtxMonitoringConsoleState }, { type: AtxMonitoringConsoleController }, { type: AtxLogIoService }, { type: AtxUserActionService }] });
6146
+ const HTTP_MOCK_MAX_DELAY = 10000;
6434
6147
 
6435
6148
  /**
6436
6149
  * @license
@@ -6442,515 +6155,128 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImpor
6442
6155
  /**
6443
6156
  * @private
6444
6157
  */
6445
- const NO = WindowFeatureState.NO;
6446
- /**
6447
- * @private
6448
- */
6449
- const FEATURES = {
6450
- left: 100,
6451
- top: 100,
6452
- width: 800,
6453
- height: 450,
6454
- directories: NO,
6455
- titlebar: NO,
6456
- scrollbars: NO,
6457
- toolbar: NO,
6458
- location: NO,
6459
- status: NO,
6460
- menubar: NO,
6461
- title: "HTTP Mocking Framework Console",
6462
- icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAABdJJREFUWEedl3tsU1Ucx7+/e/vYGNs6ZOrawSBsIgwQCC/jJhAgiIkkvkBgBJB2Q4eSoBHwFQaiTsBgdMRBMNEwum5/8EoQAQF5yQQhBB0ZOBSS6cIYsPa269rec8ztY33sru24Sf/o/Z3f93zuOb/f7/wO4WEea/sgQaNfAJmXkKPDyUG7mSjU4fWctr7KUdIO1fcyRYP+ZYCVADQVgADOAIcjKEFeEI6A8xqZ0X6UGV3JaMcHqOZa0eB6DuDKpC8APDVKNAogwsIhAXwvQajxGXKOYR7JvcGoAmhrXVMYKZPy+QAG9volvQFEOVArcWYjUdjtXW68GKsVBqhz5wvcW0IQFgE8P5nli96CxB4ENDHwGsbYHpQNblY8/ACiTbIBeDX0P7FUcERSK6CqxgFeL1ty54cADgOYnfTEoYEPD6AoHJQtprlBAMdOgMxqAMP6E3QEXHPwnuYIgFSRsGBYKqYbddh4ScJ1uy/u93DOt7PS3HI/gFDr+JiIKmI98vsTfp6WiuwUwrYmLzY1euCMjOcgQHaKgC1TMpCbJuLqPS9Wn7eDqfBG6nOOtazUVBlYgVr7MpDwXSzAOIOA87NSIQZD1XrLh8UNXeFhQYDKSRmYkK2F3cNQeroDbW7mHzM6SwOXj6PZoZqFC2WLyRqQtj2YKUJzVG3Nto3TYWWB1m9qcXEUHHLBE9CHkgX9OyXsmz3AH82X73rxboPdb1JWpbo4E2daPfjyqrOHtEwogtl0NgBQ635CJF+TGkCmFtg1UY9nskVk6wkHWnx47deuAARnGEYu7Cg2dLse+McNa3MnPhqfjpFZGhy67cZWNQBGeSgz3g4AVPN+osEpxUvDVBHYV5SCGY+JYQiZYbjQie1Fmb0G3MZLDpz8zxNjJ5/c0pSK9dN93YVIsEltFK/qAYiE2NnsxRsX3Via48Pign6qAL+3ebHmNzti45EDt5nFlKc4hQHqpEvEMS5u7gQhqsbr/RlRNFBAySCCEFPQPTLHsZYuVDW64JZV0oHojGw2FkcBiDbHfoDmJgII2d/K16ByrA7nWj0gAk7+24X6m27c62Jo72JQmzdC2ypbTAujV8Dm/IbAy5MBeO9JLTaN0cHHOM62evy/issOZGoJ9z0JCoASu4RKZjatjQGQ1hDweSKA9YVafFio8w/zMo6qP51Yd8GOMVlabJiQjm1/SDjaEht00aocWMkspqroLaiTFoKjJh7AF0/psHp4oCYoT8NdH2YebMNIgwafTEyHTiR/Bdx8xYEj8SAIc2Wz6WAUAKz2YlEQTqkBKDH29XgdVuSHJ7/WwTDtuAuCU8L30wzQh8ol4IfYcsWBn3qBkGU+Fityr8QA3B8iCtq/YwEU3eoJOiwdGp78lpPh2eNutLhkf0v20pAUlBemRbnGg5D7pQ3AIsP9aIBA+9UJcDGkpCHgh8l6zBus6Ra/4+aYerwTNyTlSA/3hC/mpWDlqJ4Qq851oPFB5MlIDtlizAgJRmWwYJNaCDCGjB+M0KJidCDglMfu5Zhxwo3LD4KHQUw/oECUj0oLFxcAO645Ybvp7tbghEZmNhWqAoi10nkQJoeMuybqsCS49EpBef4XN07dDZ1EgbMg3BUHvCIhlDQtP9uBv+wRpyHRYdlsnKMOYHPUA/RKyFiYIcD6tB7pWsKbF7vwY2vMsdpLRzT2EQ1GZWnRcMeDG5GT+4Vph2wxlqkCoE56XOR8I0DLlDZBLSOi3vWpJeNezulbpk+vwJKMdnWA0Ns90hhRxBYAs+JCJA1Ae2XO1qI093qsXtyLiVjvnMM530wc3UHTtxXgF2QI78BiPN3bhyS+mq0/oRFGTDITuNIzPpoMAAduEaP35dIcK4jiHg6JAUIz7m7PEDT6dUS0qvuK1mMLeAfn9BnTer7CsqHh3Iuzj8kDhERqOvNEUf4UhAXgjAJpSF7OeTVzuzbg7YI+3ZD7DhACqXNNEmXfVkiOdlnAGiw3qfaUiTLpf29zez9zLqGcAAAAAElFTkSuQmCC"
6463
- };
6158
+ const OK = "OK";
6464
6159
  /**
6465
- * Provides functionality to display the ATX monitoring console within a new window.
6160
+ * A statefull builder for creating new `HttpResponseMock` instances.
6466
6161
  */
6467
- class AtxHttpMockConsoleService {
6468
- /**
6469
- * @private
6470
- */
6471
- constructor(_windowSrv) {
6472
- this._windowSrv = _windowSrv;
6162
+ class HttpResponseMockBuilder {
6163
+ constructor() {
6473
6164
  /**
6474
6165
  * @private
6475
6166
  */
6476
- this._uuid = null;
6477
- }
6478
- /**
6479
- * Opens the ATX monitoring console within a new window and returns reference objects
6480
- * to control it.
6481
- */
6482
- open() {
6483
- if (this._uuid)
6484
- return;
6485
- this._uuid = this._windowSrv.open(AtxMonitoringConsoleComponent, FEATURES);
6486
- }
6487
- /**
6488
- * Closes the ATX monitoring console currently opened within a popup window.
6489
- */
6490
- close() {
6491
- if (!this._uuid)
6492
- return;
6493
- this._windowSrv.close(this._uuid);
6494
- this._uuid = null;
6495
- }
6496
- /**
6497
- * Returns reference to the opened popup window.
6498
- *
6499
- * @returns A `WindowRef` object, or undefined if the ATX monitoring console is not opened.
6500
- */
6501
- getWindowRef() {
6502
- if (!this._uuid)
6503
- return undefined;
6504
- return this._windowSrv.get(this._uuid);
6505
- }
6506
- /**
6507
- * @private
6508
- */
6509
- ngOnDestroy() {
6510
- this.close();
6511
- }
6512
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxHttpMockConsoleService, deps: [{ token: WindowService }], target: i0.ɵɵFactoryTarget.Injectable }); }
6513
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxHttpMockConsoleService, providedIn: 'root' }); }
6514
- }
6515
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxHttpMockConsoleService, decorators: [{
6516
- type: Injectable,
6517
- args: [{
6518
- providedIn: 'root'
6519
- }]
6520
- }], ctorParameters: () => [{ type: WindowService }] });
6521
-
6522
- /**
6523
- * @license
6524
- * Copyright Pascal ECHEMANN. All Rights Reserved.
6525
- *
6526
- * Use of this source code is governed by an MIT-style license that can be found in
6527
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6528
- */
6529
- /**
6530
- * A convenient high-level singleton that implements the `Logger` interface.
6531
- */
6532
- class LoggerService extends AbstractLogger {
6533
- /**
6534
- * @private
6535
- */
6536
- constructor(config) {
6537
- super();
6538
- if (config) {
6539
- const connector = config.logConnector;
6540
- if (connector)
6541
- this.setLogConnector(connector);
6542
- }
6543
- }
6544
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: LoggerService, deps: [{ token: ATX_LOGGER_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
6545
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: LoggerService, providedIn: 'root' }); }
6546
- }
6547
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: LoggerService, decorators: [{
6548
- type: Injectable,
6549
- args: [{
6550
- providedIn: 'root'
6551
- }]
6552
- }], ctorParameters: () => [{ type: undefined, decorators: [{
6553
- type: Inject,
6554
- args: [ATX_LOGGER_CONFIG]
6555
- }, {
6556
- type: Optional
6557
- }] }] });
6558
-
6559
- /**
6560
- * @license
6561
- * Copyright Pascal ECHEMANN. All Rights Reserved.
6562
- *
6563
- * Use of this source code is governed by an MIT-style license that can be found in
6564
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6565
- */
6566
- /**
6567
- * The definition function for the `@HttpMock` decorator.
6568
- *
6569
- * @param config The `HttpMockConfig` object used to initialize the HTTP Mocking Framework.
6570
- */
6571
- const HttpMock = (config) => {
6572
- return (constructor) => {
6573
- const getMockService = (instance) => {
6574
- return Object.values(instance).find((v) => {
6575
- return (v.hasOwnProperty('type') && v.type === HTTP_MOCK_SERVICE);
6576
- });
6577
- };
6578
- const ngOnInit = constructor.prototype.ngOnInit;
6579
- const ngOnDestroy = constructor.prototype.ngOnDestroy;
6580
- const uiid = config.id || Uuid.build();
6581
- if (!ngOnDestroy)
6582
- throw new ReferenceError("Component must implement the OnDestroy interface.");
6583
- if (!ngOnInit)
6584
- throw new ReferenceError("Component must implement the OnInit interface.");
6585
- if (!config.id)
6586
- config.id = uiid;
6587
- constructor.prototype.ngOnInit = function () {
6588
- const mockService = getMockService(this);
6589
- if (!mockService)
6590
- throw new ReferenceError("No provider found for HttpMockService.");
6591
- mockService.addConfig(config);
6592
- ngOnInit.call(this);
6593
- };
6594
- constructor.prototype.ngOnDestroy = function () {
6595
- const mockService = getMockService(this);
6596
- // An exception is already thrown by the ngOnInit() method when HttpMockService is not provided.
6597
- // Following check statement prevents failure during Unit Testing:
6598
- if (mockService)
6599
- mockService.removeConfig(uiid);
6600
- ngOnDestroy.call(this);
6167
+ this._response = {
6168
+ url: null,
6169
+ body: null,
6170
+ status: HttpStatusCode.Ok,
6171
+ statusText: OK,
6172
+ error: null,
6173
+ delay: 0
6601
6174
  };
6602
- };
6603
- };
6604
-
6605
- /**
6606
- * @license
6607
- * Copyright Pascal ECHEMANN. All Rights Reserved.
6608
- *
6609
- * Use of this source code is governed by an MIT-style license that can be found in
6610
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6611
- */
6612
- /**
6613
- * A statefull builder for creating new `HttpHeaders` instances.
6614
- */
6615
- class HttpHeadersMockBuilder {
6616
- constructor() {
6617
- /**
6618
- * @private
6619
- */
6620
- this._headers = new HttpHeaders();
6621
6175
  }
6622
6176
  /**
6623
- * Sets the `"Cache-Control"` property of the new `HttpHeaders` instance with the specified value.
6177
+ * Sets the body property of the new `HttpResponseMock` instance with the specified `body` value.
6624
6178
  *
6625
- * @param value The value used to set the `"Cache-Control"` property of the new `HttpHeaders` instance.
6626
- * Default value is `"no-cache"`.
6179
+ * @param body The value used to set the body property of the new `HttpResponseMock` instance.
6627
6180
  *
6628
6181
  * @returns A reference to this `HttpResponseMockBuilder` instance.
6629
6182
  */
6630
- cacheControl(value = "no-cache") {
6631
- this.setHeader("Cache-Control", value);
6183
+ body(body) {
6184
+ this._response.body = body;
6632
6185
  return this;
6633
6186
  }
6634
6187
  /**
6635
- * Sets the `"CContent-Type"` property of the new `HttpHeaders` instance with the specified value.
6188
+ * Sets the headers property of the new `HttpResponseMock` instance with the specified `headers` value.
6636
6189
  *
6637
- * @param value The value used to set the `"Content-Type"` property of the new `HttpHeaders` instance.
6638
- * Default value is `"application/json; charset=utf-8"`.
6190
+ * @param headers The value used to set the `headers` property of the new `HttpResponseMock` instance.
6639
6191
  *
6640
6192
  * @returns A reference to this `HttpResponseMockBuilder` instance.
6641
6193
  */
6642
- contentType(value = "application/json; charset=utf-8") {
6643
- this.setHeader("Content-Type", value);
6194
+ headers(headers) {
6195
+ this._response.headers = headers;
6644
6196
  return this;
6645
6197
  }
6646
6198
  /**
6647
- * Sets the `"Priority"` property of the new `HttpHeaders` instance with the specified value.
6648
- *
6649
- * @param value The value used to set the `"Priority"` property of the new `HttpHeaders` instance.
6650
- * Default value is `"u=0, i"`.
6199
+ * Add the list of HTTP headers generated by the `HttpHeadersUtil.createDefaultRequestHeaders()`
6200
+ * to the mock response.
6651
6201
  *
6652
6202
  * @returns A reference to this `HttpResponseMockBuilder` instance.
6653
6203
  */
6654
- priority(value = "u=0, i") {
6655
- this.setHeader("Priority", value);
6204
+ defaultHeaders() {
6205
+ const defaultHeaders = HttpHeadersUtil.createDefaultRequestHeaders();
6206
+ let headers = this._response.headers;
6207
+ if (headers) {
6208
+ const keys = defaultHeaders.keys();
6209
+ keys.forEach(key => headers?.append(key, defaultHeaders.get(key)));
6210
+ }
6211
+ else
6212
+ headers = defaultHeaders;
6213
+ this._response.headers = headers;
6656
6214
  return this;
6657
6215
  }
6658
6216
  /**
6659
- * Sets the `"User-Agent"` property of the new `HttpHeaders` instance with the specified value.
6217
+ * Sets the `status` property of the new `HttpResponseMock` instance with the specified `status` value.
6660
6218
  *
6661
- * @param value The value used to set the `"User-Agent"` property of the new `HttpHeaders` instance.
6662
- * Default value is the navigator user agent.
6219
+ * @param status The value used to set the `status` property of the new `HttpResponseMock` instance.
6663
6220
  *
6664
6221
  * @returns A reference to this `HttpResponseMockBuilder` instance.
6665
6222
  */
6666
- userAgent(value = null) {
6667
- this.setHeader("User-Agent", value || navigator.userAgent);
6223
+ status(status) {
6224
+ this._response.status = status;
6668
6225
  return this;
6669
6226
  }
6670
6227
  /**
6671
- * Sets the `"Accept-Language"` property of the new `HttpHeaders` instance with the specified value.
6228
+ * Sets the `statusText` property of the new `HttpResponseMock` instance with the specified `statusText` value.
6672
6229
  *
6673
- * @param value The value used to set the `"Accept-Language"` property of the new `HttpHeaders` instance.
6674
- * Default value is the navigator language.
6230
+ * @param statusText The value used to set the `statusText` property of the new `HttpResponseMock` instance.
6675
6231
  *
6676
6232
  * @returns A reference to this `HttpResponseMockBuilder` instance.
6677
6233
  */
6678
- acceptLanguage(value = null) {
6679
- this.setHeader("Accept-Language", value || navigator.language);
6234
+ statusText(statusText) {
6235
+ this._response.statusText = statusText;
6680
6236
  return this;
6681
6237
  }
6682
6238
  /**
6683
- * Sets the `"Accept"` property of the new `HttpHeaders` instance with the specified value.
6239
+ * Sets the `url` property of the new `HttpResponseMock` instance with the specified `url` value.
6684
6240
  *
6685
- * @param value The value used to set the `"Accept"` property of the new `HttpHeaders` instance.
6686
- * Default value is `'*\/*'`.
6241
+ * @param url The value used to set the `url` property of the new `HttpResponseMock` instance.
6687
6242
  *
6688
6243
  * @returns A reference to this `HttpResponseMockBuilder` instance.
6689
6244
  */
6690
- accept(value = "*/*") {
6691
- this.setHeader("Accept", value);
6245
+ url(url) {
6246
+ this._response.url = url;
6692
6247
  return this;
6693
6248
  }
6694
6249
  /**
6695
- * Sets the `"Accept-Encoding"` property of the new `HttpHeaders` instance with the specified value.
6696
- *
6697
- * @param value The value used to set the `"Accept-Encoding"` property of the new `HttpHeaders` instance.
6698
- * Default value is `"ngzip, deflate, br, zstd"`.
6699
- *
6700
- * @returns A reference to this `HttpResponseMockBuilder` instance.
6250
+ * @private
6251
+ * Overload implementation
6701
6252
  */
6702
- acceptEncoding(value = "gzip, deflate, br, zstd") {
6703
- this.setHeader("Accept-Encoding", value);
6253
+ delay(...arg) {
6254
+ if (arg.length <= 1) {
6255
+ let timer = arg[0] || NaN;
6256
+ if (isNaN(timer)) {
6257
+ this._response.delay = HTTP_MOCK_MAX_DELAY - Math.random() * HTTP_MOCK_MAX_DELAY;
6258
+ return this;
6259
+ }
6260
+ if (timer > HTTP_MOCK_MAX_DELAY) {
6261
+ this._response.delay = HTTP_MOCK_MAX_DELAY;
6262
+ return this;
6263
+ }
6264
+ if (timer < 0)
6265
+ timer = 0;
6266
+ this._response.delay = timer;
6267
+ return this;
6268
+ }
6269
+ let min = arg[0], max = arg[1];
6270
+ if (max > HTTP_MOCK_MAX_DELAY)
6271
+ max = HTTP_MOCK_MAX_DELAY;
6272
+ if (min < 0 || min > max)
6273
+ min = 0;
6274
+ this._response.delay = Math.floor(Math.random() * (max - min) + min);
6704
6275
  return this;
6705
6276
  }
6706
6277
  /**
6707
- * Sets or modifies a value of the new `HttpHeaders` instance.
6708
- *
6709
- * @param name The header name.
6710
- * @param value The value or values to set or override for the given header.
6711
- *
6712
- * @returns A reference to this `HttpResponseMockBuilder` instance.
6713
- */
6714
- set(name, value) {
6715
- this.setHeader(name, value);
6716
- return this;
6717
- }
6718
- /**
6719
- * Return a new `HttpHeaders` instance, built from the properties specified with the
6720
- * `HttpHeadersMockBuilder` methods.
6721
- *
6722
- * @returns A new `HttpHeaders` instance.
6723
- */
6724
- headers() {
6725
- return this._headers;
6726
- }
6727
- /**
6728
- * @private
6729
- */
6730
- setHeader(name, value) {
6731
- const values = Array.isArray(value) ? value.join(", ") : value;
6732
- this._headers = this._headers.set(name, values);
6733
- }
6734
- }
6735
- /**
6736
- * A utility function used to create new "chainable" `HttpHeadersMockBuilder` instances.
6737
- *
6738
- * @returns A new `HttpHeadersMockBuilder` instance;
6739
- */
6740
- const httpHeadersMock = () => new HttpHeadersMockBuilder();
6741
-
6742
- /**
6743
- * @license
6744
- * Copyright Pascal ECHEMANN. All Rights Reserved.
6745
- *
6746
- * Use of this source code is governed by an MIT-style license that can be found in
6747
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6748
- */
6749
- /**
6750
- * @private
6751
- * Internal reference to a new line character.
6752
- */
6753
- const CRLF = "\r\n";
6754
- /**
6755
- * @private
6756
- * A set of static utilities for manipulating `HttpHeaders` objects.
6757
- */
6758
- class HttpHeadersUtil {
6759
- /**
6760
- * @private
6761
- * Returns a string representation the the specified `HttpHeaders `object, compatible with the format
6762
- * expected by the `XMLHttpRequest.getAllResponseHeaders()` method.
6763
- *
6764
- * @param headers The `HttpHeaders` object to format.
6765
- *
6766
- * @returns A string compatible with the format expected by the `XMLHttpRequest.getAllResponseHeaders()` method.
6767
- */
6768
- static stringify(headers) {
6769
- let result = EMPTY_STRING;
6770
- if (!headers)
6771
- return result;
6772
- const keys = headers.keys();
6773
- const last = keys.length - 1;
6774
- keys.forEach((key, index) => {
6775
- result += `${key}: ${headers.getAll(key)}${index !== last ? CRLF : EMPTY_STRING}`;
6776
- });
6777
- return result;
6778
- }
6779
- /**
6780
- * @private
6781
- * Returns a `HttpHeaders` object built from the string returns by the `XMLHttpRequest.getAllResponseHeaders()` method,
6782
- * or `null` wheher `XMLHttpRequest.getAllResponseHeaders()` return `null`.
6783
- *
6784
- * @param value The string to turn into a `HttpHeaders `object.
6785
- *
6786
- * @returns A `HttpHeaders` object, or `null`.
6787
- */
6788
- static encode(value) {
6789
- if (value === null)
6790
- return null;
6791
- return new HttpHeaders(value);
6792
- }
6793
- /**
6794
- * @private
6795
- * Creates the default `HttpHeaders` object for a mocked HTTP request.
6796
- *
6797
- * @returns The default `HttpHeaders` object for a mocked HTTP request.
6798
- */
6799
- static createDefaultRequestHeaders() {
6800
- // "Accept" header is set by Angular framework when missing
6801
- return httpHeadersMock().cacheControl()
6802
- .acceptEncoding()
6803
- .acceptLanguage()
6804
- .priority()
6805
- .userAgent()
6806
- .headers();
6807
- }
6808
- }
6809
-
6810
- /**
6811
- * @license
6812
- * Copyright Pascal ECHEMANN. All Rights Reserved.
6813
- *
6814
- * Use of this source code is governed by an MIT-style license that can be found in
6815
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6816
- */
6817
- /**
6818
- * A convenient constant that represents the maximum value for a delayed HTTP response.
6819
- */
6820
- const HTTP_MOCK_MAX_DELAY = 10000;
6821
-
6822
- /**
6823
- * @license
6824
- * Copyright Pascal ECHEMANN. All Rights Reserved.
6825
- *
6826
- * Use of this source code is governed by an MIT-style license that can be found in
6827
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6828
- */
6829
- /**
6830
- * @private
6831
- */
6832
- const OK = "OK";
6833
- /**
6834
- * A statefull builder for creating new `HttpResponseMock` instances.
6835
- */
6836
- class HttpResponseMockBuilder {
6837
- constructor() {
6838
- /**
6839
- * @private
6840
- */
6841
- this._response = {
6842
- url: null,
6843
- body: null,
6844
- status: HttpStatusCode.Ok,
6845
- statusText: OK,
6846
- error: null,
6847
- delay: 0
6848
- };
6849
- }
6850
- /**
6851
- * Sets the body property of the new `HttpResponseMock` instance with the specified `body` value.
6852
- *
6853
- * @param body The value used to set the body property of the new `HttpResponseMock` instance.
6854
- *
6855
- * @returns A reference to this `HttpResponseMockBuilder` instance.
6856
- */
6857
- body(body) {
6858
- this._response.body = body;
6859
- return this;
6860
- }
6861
- /**
6862
- * Sets the headers property of the new `HttpResponseMock` instance with the specified `headers` value.
6863
- *
6864
- * @param headers The value used to set the `headers` property of the new `HttpResponseMock` instance.
6865
- *
6866
- * @returns A reference to this `HttpResponseMockBuilder` instance.
6867
- */
6868
- headers(headers) {
6869
- this._response.headers = headers;
6870
- return this;
6871
- }
6872
- /**
6873
- * Add the list of HTTP headers generated by the `HttpHeadersUtil.createDefaultRequestHeaders()`
6874
- * to the mock response.
6875
- *
6876
- * @returns A reference to this `HttpResponseMockBuilder` instance.
6877
- */
6878
- defaultHeaders() {
6879
- const defaultHeaders = HttpHeadersUtil.createDefaultRequestHeaders();
6880
- let headers = this._response.headers;
6881
- if (headers) {
6882
- const keys = defaultHeaders.keys();
6883
- keys.forEach(key => headers?.append(key, defaultHeaders.get(key)));
6884
- }
6885
- else
6886
- headers = defaultHeaders;
6887
- this._response.headers = headers;
6888
- return this;
6889
- }
6890
- /**
6891
- * Sets the `status` property of the new `HttpResponseMock` instance with the specified `status` value.
6892
- *
6893
- * @param status The value used to set the `status` property of the new `HttpResponseMock` instance.
6894
- *
6895
- * @returns A reference to this `HttpResponseMockBuilder` instance.
6896
- */
6897
- status(status) {
6898
- this._response.status = status;
6899
- return this;
6900
- }
6901
- /**
6902
- * Sets the `statusText` property of the new `HttpResponseMock` instance with the specified `statusText` value.
6903
- *
6904
- * @param statusText The value used to set the `statusText` property of the new `HttpResponseMock` instance.
6905
- *
6906
- * @returns A reference to this `HttpResponseMockBuilder` instance.
6907
- */
6908
- statusText(statusText) {
6909
- this._response.statusText = statusText;
6910
- return this;
6911
- }
6912
- /**
6913
- * Sets the `url` property of the new `HttpResponseMock` instance with the specified `url` value.
6914
- *
6915
- * @param url The value used to set the `url` property of the new `HttpResponseMock` instance.
6916
- *
6917
- * @returns A reference to this `HttpResponseMockBuilder` instance.
6918
- */
6919
- url(url) {
6920
- this._response.url = url;
6921
- return this;
6922
- }
6923
- /**
6924
- * @private
6925
- * Overload implementation
6926
- */
6927
- delay(...arg) {
6928
- if (arg.length <= 1) {
6929
- let timer = arg[0] || NaN;
6930
- if (isNaN(timer)) {
6931
- this._response.delay = HTTP_MOCK_MAX_DELAY - Math.random() * HTTP_MOCK_MAX_DELAY;
6932
- return this;
6933
- }
6934
- if (timer > HTTP_MOCK_MAX_DELAY) {
6935
- this._response.delay = HTTP_MOCK_MAX_DELAY;
6936
- return this;
6937
- }
6938
- if (timer < 0)
6939
- timer = 0;
6940
- this._response.delay = timer;
6941
- return this;
6942
- }
6943
- let min = arg[0], max = arg[1];
6944
- if (max > HTTP_MOCK_MAX_DELAY)
6945
- max = HTTP_MOCK_MAX_DELAY;
6946
- if (min < 0 || min > max)
6947
- min = 0;
6948
- this._response.delay = Math.floor(Math.random() * (max - min) + min);
6949
- return this;
6950
- }
6951
- /**
6952
- * Returns a new `HttpResponseMock` instance, built from the properties specified with the
6953
- * `HttpResponseMockBuilder` methods.
6278
+ * Returns a new `HttpResponseMock` instance, built from the properties specified with the
6279
+ * `HttpResponseMockBuilder` methods.
6954
6280
  *
6955
6281
  * @param error An optional value used to set the `error` property of the new `HttpResponseMock` instance.
6956
6282
  * The `error` parameter values take precedence over all other properties of the `HttpResponseMock`
@@ -7343,25 +6669,1016 @@ class XhrBase extends EventTargetImpl {
7343
6669
  }
7344
6670
  /**
7345
6671
  * @private
7346
- *
7347
- * XMLHTTPRequest API - Useless
6672
+ *
6673
+ * XMLHTTPRequest API - Useless
6674
+ */
6675
+ get responseXML() {
6676
+ return null;
6677
+ }
6678
+ /**
6679
+ * @private
6680
+ *
6681
+ * XMLHTTPRequest API - Useless
6682
+ */
6683
+ overrideMimeType(mime) { }
6684
+ /**
6685
+ * @private
6686
+ *
6687
+ * XMLHTTPRequest API - Useless
6688
+ */
6689
+ getResponseHeader(name) { return null; }
6690
+ }
6691
+
6692
+ /**
6693
+ * @license
6694
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
6695
+ *
6696
+ * Use of this source code is governed by an MIT-style license that can be found in
6697
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6698
+ */
6699
+ /**
6700
+ * @private
6701
+ * A static utility class for building `DataStorage` objects.
6702
+ */
6703
+ class DataStorageBuilder {
6704
+ /**
6705
+ * @private
6706
+ * Builds and returns a new `DataStorage` objects.
6707
+ *
6708
+ * @param httpResponse The `HttpResponseMock` to be stored by the framework.
6709
+ * @param data The data of the HTTP response to be stored by the framework.
6710
+ * @param metadata The metadata of the HTTP mock request to be stored by the framework.
6711
+ *
6712
+ * @returns A new `DataStorage` object.
6713
+ */
6714
+ static buildDataStorage(httpResponse, data, metadata) {
6715
+ // TODO: add support for different data types (string, Blob, etc.)
6716
+ const stringifiedData = data ? JSON.stringify(data) : EMPTY_STRING;
6717
+ return {
6718
+ httpResponse: httpResponse,
6719
+ loaded: 0,
6720
+ total: data ? new Blob([stringifiedData]).size : 0,
6721
+ data: data,
6722
+ stringifiedData: stringifiedData,
6723
+ requestMetadata: metadata
6724
+ };
6725
+ }
6726
+ }
6727
+
6728
+ /**
6729
+ * @license
6730
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
6731
+ *
6732
+ * Use of this source code is governed by an MIT-style license that can be found in
6733
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6734
+ */
6735
+ /**
6736
+ * @private
6737
+ * A static builder for creating `HttpMockLoggingMetadata` objects.
6738
+ */
6739
+ class HttpMockLoggingMetadataBuilder {
6740
+ /**
6741
+ * @private
6742
+ * Creates and returns a new `HttpMockLoggingMetadata` object.
6743
+ */
6744
+ static build(xhr, request, requestMetadata) {
6745
+ const responseInit = {
6746
+ body: xhr.response,
6747
+ status: xhr.status,
6748
+ statusText: xhr.statusText,
6749
+ url: xhr.responseURL,
6750
+ headers: HttpHeadersUtil.encode(xhr.getAllResponseHeaders())
6751
+ };
6752
+ const response = new HttpResponse(responseInit);
6753
+ return {
6754
+ request: request,
6755
+ response: response,
6756
+ requestMetadata: requestMetadata
6757
+ };
6758
+ }
6759
+ }
6760
+
6761
+ /**
6762
+ * @license
6763
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
6764
+ *
6765
+ * Use of this source code is governed by an MIT-style license that can be found in
6766
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6767
+ */
6768
+ /**
6769
+ * @private
6770
+ * A utility for managing HTTP responses delay.
6771
+ */
6772
+ class HttpMockResponseDelayUtil {
6773
+ /**
6774
+ * @private
6775
+ * A utility function that return a `ResponseDelay` object, depending on the timer parameters.
6776
+ *
6777
+ * @param timer The seed value used to create the `ResponseDelay` object.
6778
+ * @returns A `ResponseDelay` object.
6779
+ */
6780
+ static getResponseDelay(timer) {
6781
+ let duration = timer;
6782
+ if (timer < 0)
6783
+ duration = 0;
6784
+ if (timer > HTTP_MOCK_MAX_DELAY)
6785
+ duration = HTTP_MOCK_MAX_DELAY;
6786
+ return {
6787
+ stalled: Math.random() * duration,
6788
+ duration: duration
6789
+ };
6790
+ }
6791
+ }
6792
+
6793
+ /**
6794
+ * @license
6795
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
6796
+ *
6797
+ * Use of this source code is governed by an MIT-style license that can be found in
6798
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6799
+ */
6800
+ /**
6801
+ * @private
6802
+ * Intenal "onreadystatechange" event.
6803
+ */
6804
+ const READY_STATE_CHANGE_EVENT = new Event("onreadystatechange");
6805
+ /**
6806
+ * @private
6807
+ */
6808
+ const EVT_PROPS_CONFIG = { writable: false, value: this };
6809
+ /**
6810
+ * @private
6811
+ * A utility class used as delegate of `XMLHttpRequest` functionalities when
6812
+ * a HTTP request is intercepted by the Mocking Framework .
6813
+ */
6814
+ class DelegateXhr extends XhrBase {
6815
+ /**
6816
+ * Returns the response body content.
6817
+ *
6818
+ * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/response
6819
+ */
6820
+ get response() {
6821
+ return this._dataStorage?.data || null;
6822
+ }
6823
+ /**
6824
+ * Returns the numerical HTTP status code of the `XMLHttpRequest` response.
6825
+ *
6826
+ * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/status
6827
+ */
6828
+ get status() {
6829
+ return this._status;
6830
+ }
6831
+ /**
6832
+ * Returns a string containing the response status message as returned by the HTTP server.
6833
+ *
6834
+ * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/statusText
6835
+ */
6836
+ get statusText() {
6837
+ return this._statusText;
6838
+ }
6839
+ /**
6840
+ * Returns the state the `XMLHttpRequest` client is in.
6841
+ *
6842
+ * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/readyState
6843
+ */
6844
+ get readyState() {
6845
+ return this._readyState;
6846
+ }
6847
+ /**
6848
+ * Returns the serialized URL of the response or the empty string if the URL is `null`.
6849
+ *
6850
+ * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/responseURL
6851
+ */
6852
+ get responseURL() {
6853
+ return this._url;
6854
+ }
6855
+ /**
6856
+ * Returns the text received from a server following a request being sent.
6857
+ *
6858
+ * Throws an `InvalidStateError` DOMException if responseType is not the empty string or "text".
6859
+ *
6860
+ * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/responseText
6861
+ */
6862
+ get responseText() {
6863
+ return this._dataStorage?.stringifiedData || EMPTY_STRING;
6864
+ }
6865
+ /**
6866
+ * Returns an `XMLHttpRequestUpload` object that can be observed to monitor an upload progress.
6867
+ *
6868
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/upload
6869
+ */
6870
+ get upload() {
6871
+ return null;
6872
+ }
6873
+ /**
6874
+ * @private
6875
+ */
6876
+ open(method, url, async, username, password) {
6877
+ this._method = method;
6878
+ this._url = url;
6879
+ this.setReadyState(this.OPENED);
6880
+ }
6881
+ /**
6882
+ * Aborts the request if it has already been sent. When a request is aborted, its `readyState`
6883
+ * is changed to `XMLHttpRequest.UNSENT` and the request status code is set to `0`.
6884
+ */
6885
+ abort() {
6886
+ this._readyState = this.UNSENT;
6887
+ this._status = 0;
6888
+ this.eventDispatch("abort");
6889
+ }
6890
+ /**
6891
+ * Returns all the response headers, separated by CRLF, as a string, or returns `null`
6892
+ * if no response has been received.
6893
+ *
6894
+ * @returns All the response headers, separated by CRLF, as a string, or returns `null`
6895
+ * if no response has been received.
6896
+ */
6897
+ getAllResponseHeaders() {
6898
+ if (this._readyState < this.HEADERS_RECEIVED)
6899
+ return null;
6900
+ const respHeaders = this._dataStorage?.httpResponse.headers;
6901
+ if (respHeaders)
6902
+ return HttpHeadersUtil.stringify(respHeaders);
6903
+ return null;
6904
+ }
6905
+ /**
6906
+ * Sends the request to the server.
6907
+ *
6908
+ * @param body A body of data to be sent in the XHR request.
6909
+ */
6910
+ send(body) {
6911
+ const start = this.now();
6912
+ const request = this.buildHttpRequest(body);
6913
+ const rc = this._routeConfig;
6914
+ const httpResponseMock = rc.methodConfig.data(request, rc.parameters);
6915
+ const responseDelay = HttpMockResponseDelayUtil.getResponseDelay(httpResponseMock.delay || 0);
6916
+ const timer = responseDelay.duration;
6917
+ const requestMetadata = {
6918
+ start: start,
6919
+ stalled: responseDelay.stalled,
6920
+ duration: timer,
6921
+ url: new URL(this._url),
6922
+ id: Uuid.build()
6923
+ };
6924
+ const prefetchMetadata = {
6925
+ request: request,
6926
+ requestMetadata: requestMetadata
6927
+ };
6928
+ this._logger.prefetch(prefetchMetadata);
6929
+ this._loadSubscription = this.loadData(httpResponseMock).subscribe({
6930
+ next: (data) => {
6931
+ this.setDataStorage(httpResponseMock, requestMetadata, data);
6932
+ const error = this._dataStorage.httpResponse.error;
6933
+ setTimeout(() => {
6934
+ this.setReadyState(this.HEADERS_RECEIVED);
6935
+ if (error)
6936
+ return this.onError(request, error);
6937
+ this.setReadyState(this.LOADING);
6938
+ const response = this._dataStorage.httpResponse;
6939
+ if (!this._progressiveDownload) {
6940
+ this._statusText = response.statusText || EMPTY_STRING;
6941
+ this._status = response.status || 0;
6942
+ return this.onLoadComplete(request);
6943
+ }
6944
+ this.doProgressiveDownload(request);
6945
+ }, timer);
6946
+ },
6947
+ error: (err) => {
6948
+ this.setDataStorage(httpResponseMock, requestMetadata);
6949
+ this.onError(request, err);
6950
+ }
6951
+ });
6952
+ }
6953
+ /**
6954
+ * Sets the value of an HTTP request header.
6955
+ *
6956
+ * @param name The name of the header whose value is to be set.
6957
+ * @param value The value to set as the body of the header.
6958
+ */
6959
+ setRequestHeader(name, value) {
6960
+ this._requestHeaders = this._requestHeaders.set(name, value);
6961
+ }
6962
+ /**
6963
+ * @private
6964
+ */
6965
+ constructor(routeConfig, _logger) {
6966
+ super();
6967
+ this._logger = _logger;
6968
+ /**
6969
+ * @private
6970
+ * Indicates whether the progressive download is activated, or not.
6971
+ */
6972
+ this._progressiveDownload = false;
6973
+ /**
6974
+ * @private
6975
+ *
6976
+ * Internal storage for HTTP response `data`.
6977
+ */
6978
+ this._dataStorage = null;
6979
+ /**
6980
+ * @private
6981
+ *
6982
+ * Internal storage for the HTTP request `readyState`.
6983
+ */
6984
+ this._readyState = this.UNSENT;
6985
+ /**
6986
+ * @private
6987
+ *
6988
+ * Internal storage for the HTTP request `headers`.
6989
+ */
6990
+ this._requestHeaders = null;
6991
+ /**
6992
+ * @private
6993
+ *
6994
+ * Internal storage for the HTTP request `status`.
6995
+ */
6996
+ this._status = 0;
6997
+ /**
6998
+ * @private
6999
+ *
7000
+ * Internal storage for the HTTP request `statusText`.
7001
+ */
7002
+ this._statusText = EMPTY_STRING;
7003
+ /**
7004
+ * @private
7005
+ */
7006
+ this._loadSubscription = null;
7007
+ /**
7008
+ * Returns an an enumerated string value specifying the type of data contained in the response.
7009
+ *
7010
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType
7011
+ */
7012
+ this.responseType = EMPTY_STRING;
7013
+ this._routeConfig = routeConfig;
7014
+ // routeConfig.methodConfig.downloadManager
7015
+ this._progressiveDownload = false;
7016
+ this._requestHeaders = new HttpHeaders();
7017
+ }
7018
+ /**
7019
+ * @private
7020
+ * Internally used by the framework to delete a `DelegateXhr` instance.
7021
+ */
7022
+ destroy() {
7023
+ this._routeConfig = null;
7024
+ this._requestHeaders = null;
7025
+ this._dataStorage = null;
7026
+ if (this._loadSubscription) {
7027
+ this._loadSubscription.unsubscribe();
7028
+ this._loadSubscription = null;
7029
+ }
7030
+ }
7031
+ /**
7032
+ * @private
7033
+ */
7034
+ doProgressiveDownload(request) {
7035
+ const total = this._dataStorage.total;
7036
+ if (total <= 200) {
7037
+ console.warn("[Angular Toolbox]: Body content is too small for emulating progressive download! Minimum size is 200 octets.");
7038
+ return this.onLoadComplete(request);
7039
+ }
7040
+ // TODO: ameliorate the following process:
7041
+ const self = this;
7042
+ const chunckSize = Math.floor(total / 10);
7043
+ let cursor = 0;
7044
+ this._statusText = "Partial Content";
7045
+ this._status = HttpStatusCode.PartialContent;
7046
+ const idx = setInterval(() => {
7047
+ cursor += chunckSize;
7048
+ if (cursor > total) {
7049
+ cursor = total;
7050
+ clearInterval(idx);
7051
+ self.onLoadComplete(request);
7052
+ }
7053
+ else {
7054
+ this._dataStorage.loaded = cursor;
7055
+ self.dispatchProgressEvent();
7056
+ }
7057
+ }, 100);
7058
+ }
7059
+ finalizeRequestMetadata() {
7060
+ const ds = this._dataStorage;
7061
+ const metadata = ds.requestMetadata;
7062
+ const duration = this.now() - metadata.start;
7063
+ if (duration > metadata.duration)
7064
+ metadata.duration = duration;
7065
+ return metadata;
7066
+ }
7067
+ /**
7068
+ * @private
7069
+ */
7070
+ onLoadComplete(request) {
7071
+ this._dataStorage.loaded = this._dataStorage.total;
7072
+ this.setReadyState(this.DONE);
7073
+ this.dispatchProgressEvent("load");
7074
+ this._logger.info(this.buildMetadata(request));
7075
+ }
7076
+ /**
7077
+ * @private
7078
+ */
7079
+ onError(request, error) {
7080
+ this._status = error.status;
7081
+ this._statusText = error.statusText;
7082
+ this.setReadyState(this.DONE);
7083
+ this.dispatchProgressEvent("error");
7084
+ this._logger.error(this.buildMetadata(request));
7085
+ }
7086
+ /**
7087
+ * @private
7088
+ */
7089
+ buildMetadata(request) {
7090
+ return HttpMockLoggingMetadataBuilder.build(this, request, this.finalizeRequestMetadata());
7091
+ }
7092
+ /**
7093
+ * @private
7094
+ */
7095
+ eventDispatch(type) {
7096
+ const event = new Event(type);
7097
+ Object.defineProperty(event, 'target', EVT_PROPS_CONFIG);
7098
+ Object.defineProperty(event, 'currentTarget', EVT_PROPS_CONFIG);
7099
+ this.dispatchEvent(event);
7100
+ }
7101
+ /**
7102
+ * @private
7103
+ */
7104
+ dispatchProgressEvent(type = "progress") {
7105
+ const d = this._dataStorage;
7106
+ const event = new ProgressEventMock(type);
7107
+ event.loaded = d.loaded;
7108
+ event.total = d.total;
7109
+ this.dispatchEvent(event);
7110
+ }
7111
+ /**
7112
+ * @private
7113
+ */
7114
+ setReadyState(state) {
7115
+ this._readyState = state;
7116
+ const event = this.onreadystatechange;
7117
+ if (event)
7118
+ event.call(this, READY_STATE_CHANGE_EVENT);
7119
+ }
7120
+ /**
7121
+ * @private
7122
+ */
7123
+ loadData(httpResponseMock) {
7124
+ const responseBody = httpResponseMock.body;
7125
+ return (responseBody instanceof Observable) ? responseBody : of(responseBody);
7126
+ }
7127
+ /**
7128
+ * @private
7129
+ */
7130
+ setDataStorage(responseMock, requestMetadata, data = null) {
7131
+ this._dataStorage = DataStorageBuilder.buildDataStorage(responseMock, data, requestMetadata);
7132
+ }
7133
+ /**
7134
+ * @private
7135
+ */
7136
+ buildHttpRequest(body) {
7137
+ let params = new HttpParams();
7138
+ const it = this._routeConfig.searchParams.entries();
7139
+ for (const pair of it)
7140
+ params = params.set(pair[0], pair[1]);
7141
+ const init = {
7142
+ params: params,
7143
+ headers: this._requestHeaders,
7144
+ withCredentials: this.withCredentials,
7145
+ responseType: this.responseType,
7146
+ reportProgress: this.hasEventListener("progress")
7147
+ // context, transferCache: not used by Angular at this level of API
7148
+ };
7149
+ return new HttpRequest(this._method, this._url, body, init);
7150
+ }
7151
+ now() {
7152
+ return Date.now();
7153
+ }
7154
+ }
7155
+
7156
+ /**
7157
+ * @license
7158
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
7159
+ *
7160
+ * Use of this source code is governed by an MIT-style license that can be found in
7161
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
7162
+ */
7163
+ /**
7164
+ * @private
7165
+ * An error used as reference for unit testing.
7166
+ * Angular framework calls `XMLHttpRequest` method only after the `open()` method invokation.
7167
+ */
7168
+ const XHR_ERROR = (method) => {
7169
+ throw new Error(`Attempt to call ${method}() method before calling open().`);
7170
+ };
7171
+ /**
7172
+ * @private
7173
+ * A XHR proxy that is used by the Mocking Framework to apply HTTP call strategies.
7174
+ */
7175
+ class XhrProxyImpl extends XhrBase {
7176
+ /**
7177
+ * @private
7178
+ *
7179
+ * XMLHTTPRequest API
7180
+ */
7181
+ get response() {
7182
+ return this.XHR ? this.XHR.response : undefined;
7183
+ }
7184
+ /**
7185
+ * @private
7186
+ *
7187
+ * XMLHTTPRequest API
7188
+ */
7189
+ get status() {
7190
+ return this.XHR ? this.XHR.status : 0;
7191
+ }
7192
+ /**
7193
+ * @private
7194
+ *
7195
+ * XMLHTTPRequest API
7196
+ */
7197
+ get statusText() {
7198
+ return this.XHR ? this.XHR.statusText : EMPTY_STRING;
7199
+ }
7200
+ /**
7201
+ * @private
7202
+ *
7203
+ * XMLHTTPRequest API
7204
+ */
7205
+ get readyState() {
7206
+ return this.XHR ? this.XHR.readyState : this.UNSENT;
7207
+ }
7208
+ /**
7209
+ * @private
7210
+ *
7211
+ * XMLHTTPRequest API
7212
+ */
7213
+ get responseURL() {
7214
+ return this.XHR ? this.XHR.responseURL : EMPTY_STRING;
7215
+ }
7216
+ /**
7217
+ * @private
7218
+ *
7219
+ * XMLHTTPRequest API
7220
+ */
7221
+ get responseText() {
7222
+ return this.XHR ? this.XHR.responseText : EMPTY_STRING;
7223
+ }
7224
+ /**
7225
+ * @private
7226
+ *
7227
+ * XMLHTTPRequest API
7228
+ */
7229
+ get responseType() {
7230
+ return this.XHR ? this.XHR.responseType : EMPTY_STRING;
7231
+ }
7232
+ /**
7233
+ * @private
7234
+ *
7235
+ * XMLHTTPRequest API
7236
+ */
7237
+ set responseType(value) {
7238
+ if (!this.XHR)
7239
+ XHR_ERROR("responseType");
7240
+ this.XHR.responseType = value;
7241
+ }
7242
+ get upload() {
7243
+ return this.XHR.upload;
7244
+ }
7245
+ open(method, url, async, username, password) {
7246
+ const m = method.toString().toLowerCase();
7247
+ const parsedUrl = URL.canParse(url) ? new URL(url) : new URL(this._httpMockService.getAppOrigin() + url);
7248
+ const config = this._httpMockService.getRouteConfig(parsedUrl, m);
7249
+ if (this.XHR && this.XHR instanceof DelegateXhr)
7250
+ this.XHR.destroy();
7251
+ this.XHR = config ? new DelegateXhr(config, this._logger) : new XMLHttpRequest();
7252
+ this.XHR.withCredentials = this.withCredentials;
7253
+ this.XHR.open(m.toString(), parsedUrl.toString());
7254
+ }
7255
+ /**
7256
+ * @private
7257
+ *
7258
+ * XMLHTTPRequest API
7259
+ */
7260
+ abort() {
7261
+ if (this.XHR)
7262
+ return this.XHR.abort();
7263
+ XHR_ERROR("abort");
7264
+ }
7265
+ /**
7266
+ * @private
7267
+ *
7268
+ * XMLHTTPRequest API
7269
+ */
7270
+ getAllResponseHeaders() {
7271
+ return this.XHR ? this.XHR.getAllResponseHeaders() : null;
7272
+ }
7273
+ /**
7274
+ * @private
7275
+ *
7276
+ * XMLHTTPRequest API
7277
+ */
7278
+ addEventListener(type, listener, options) {
7279
+ if (this.XHR)
7280
+ return this.XHR.addEventListener(type, listener, options);
7281
+ XHR_ERROR("addEventListener");
7282
+ }
7283
+ /**
7284
+ * @private
7285
+ *
7286
+ * XMLHTTPRequest API
7287
+ */
7288
+ removeEventListener(type, listener, options) {
7289
+ if (this.XHR)
7290
+ return this.XHR.removeEventListener(type, listener, options);
7291
+ XHR_ERROR("removeEventListener");
7292
+ }
7293
+ /**
7294
+ * @private
7295
+ *
7296
+ * XMLHTTPRequest API
7297
+ */
7298
+ send(body) {
7299
+ if (this.XHR)
7300
+ return this.XHR.send(body);
7301
+ XHR_ERROR("send");
7302
+ }
7303
+ /**
7304
+ * @private
7305
+ *
7306
+ * XMLHTTPRequest API
7307
+ */
7308
+ setRequestHeader(name, value) {
7309
+ if (this.XHR)
7310
+ return this.XHR.setRequestHeader(name, value);
7311
+ XHR_ERROR("setRequestHeader");
7312
+ }
7313
+ /**
7314
+ * @private
7315
+ *
7316
+ * For Unit Testing only.
7317
+ */
7318
+ instanceOf(classRef) {
7319
+ return this.XHR instanceof classRef;
7320
+ }
7321
+ /**
7322
+ * @private
7323
+ */
7324
+ constructor(_httpMockService, _logger) {
7325
+ super();
7326
+ this._httpMockService = _httpMockService;
7327
+ this._logger = _logger;
7328
+ }
7329
+ }
7330
+
7331
+ /**
7332
+ * @license
7333
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
7334
+ *
7335
+ * Use of this source code is governed by an MIT-style license that can be found in
7336
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
7337
+ */
7338
+ /**
7339
+ * @private
7340
+ * The concrete implementation of the `XhrFactory` interface.
7341
+ */
7342
+ class XhrProxyFactoryImpl extends XhrFactory {
7343
+ /**
7344
+ * @private
7345
+ */
7346
+ constructor(_httpMockService, _logger) {
7347
+ super();
7348
+ this._httpMockService = _httpMockService;
7349
+ this._logger = _logger;
7350
+ }
7351
+ /**
7352
+ * @private
7353
+ */
7354
+ build() {
7355
+ return new XhrProxyImpl(this._httpMockService, this._logger);
7356
+ }
7357
+ }
7358
+
7359
+ /**
7360
+ * @license
7361
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
7362
+ *
7363
+ * Use of this source code is governed by an MIT-style license that can be found in
7364
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
7365
+ */
7366
+ /**
7367
+ * A factory function that creates and returns a new `XhrFactory` object.
7368
+ *
7369
+ * @returns A new `XhrFactory` object.
7370
+ */
7371
+ const httpMockFactory = () => {
7372
+ return new XhrProxyFactoryImpl(inject(HttpMockService), inject(HttpMockLoggingService));
7373
+ };
7374
+
7375
+ /**
7376
+ * @license
7377
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
7378
+ *
7379
+ * Use of this source code is governed by an MIT-style license that can be found in
7380
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
7381
+ */
7382
+ /**
7383
+ * @private
7384
+ * A utility class that converts `Log` objects into `AtxHttpLogDto` objects.
7385
+ */
7386
+ class LogConverter {
7387
+ /**
7388
+ * @private
7389
+ * Converts a `object` object into an `AtxHttpLogDto` object.
7390
+ *
7391
+ * @param log The `Log` object to convert.
7392
+ * @returns A new `AtxHttpLogDto` object.
7393
+ */
7394
+ static logToDto(log) {
7395
+ return {
7396
+ level: log.level,
7397
+ timestamp: log.timestamp,
7398
+ metadata: LogMetadataConverter.metadataToDto(log.metadata)
7399
+ };
7400
+ }
7401
+ /**
7402
+ * @private
7403
+ * Converts an `AtxHttpLogDto` object into a `Log` object.
7404
+ *
7405
+ * @param dto The `AtxHttpLogDto` object to convert.
7406
+ * @returns A new `Log` object.
7407
+ */
7408
+ static dtoToLog(dto) {
7409
+ const level = dto.level;
7410
+ return LogBuilder.build(HttpMockLoggingConstant.CALLER, LogMessageUtil.getMessageFromLevel(level), level, LogMetadataConverter.dtoToMetadata(dto.metadata));
7411
+ }
7412
+ }
7413
+
7414
+ /**
7415
+ * @license
7416
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
7417
+ *
7418
+ * Use of this source code is governed by an MIT-style license that can be found in
7419
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
7420
+ */
7421
+ /**
7422
+ * @private
7423
+ * A utility class that creates `HMFL` objects.
7424
+ */
7425
+ class HMFLBuilder {
7426
+ /**
7427
+ * @private
7428
+ * Creates and returns a new `HMFL` object.
7429
+ *
7430
+ * @param logDtoList The list of serialized logs to include in the new `HMFL` object.
7431
+ * @returns A new `HMFL` object.
7432
+ */
7433
+ static build(logDtoList) {
7434
+ return {
7435
+ logs: logDtoList,
7436
+ timestamp: Date.now()
7437
+ };
7438
+ }
7439
+ }
7440
+
7441
+ /**
7442
+ * @license
7443
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
7444
+ *
7445
+ * Use of this source code is governed by an MIT-style license that can be found in
7446
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
7447
+ */
7448
+ /**
7449
+ * @private
7450
+ */
7451
+ const BLOB_TYPE = { type: 'application/json' };
7452
+ /**
7453
+ * @private
7454
+ */
7455
+ const UTF8 = "UTF-8";
7456
+ /**
7457
+ * @private
7458
+ * The service responsible for exporting and importing `hmfl` log files.
7459
+ */
7460
+ class AtxLogIoService {
7461
+ /**
7462
+ * @private
7463
+ */
7464
+ constructor(_logger) {
7465
+ this._logger = _logger;
7466
+ }
7467
+ /**
7468
+ * @private
7469
+ * Exports the specified logs into a hmfl file.
7470
+ *
7471
+ * @param logs The logs to exports.
7472
+ */
7473
+ exportFile(logs) {
7474
+ const logDtoList = [];
7475
+ let cursor = logs.length - 1;
7476
+ for (; cursor >= 0; cursor--) {
7477
+ const log = logs[cursor];
7478
+ if (log.level !== LogLevel.CONFIG)
7479
+ logDtoList.push(LogConverter.logToDto(log));
7480
+ }
7481
+ const exportData = HMFLBuilder.build(logDtoList);
7482
+ const a = document.createElement("a");
7483
+ const file = new Blob([JSON.stringify(exportData)], BLOB_TYPE);
7484
+ const timeFmt = formatDate(exportData.timestamp, "MM/dd/yy-hh:mm-a", "en-US");
7485
+ a.href = URL.createObjectURL(file);
7486
+ a.download = `logs-${timeFmt}.hmfl`;
7487
+ a.click();
7488
+ }
7489
+ /**
7490
+ * @private
7491
+ * Imports the logs loaded through the specified `FileList` object.
7492
+ *
7493
+ * @param fileList The logs to import.
7494
+ */
7495
+ importFile(fileList) {
7496
+ const logger = this._logger;
7497
+ const files = fileList[0];
7498
+ const killReader = this.killReader;
7499
+ if (files) {
7500
+ const reader = new FileReader();
7501
+ reader.readAsText(files, UTF8);
7502
+ reader.onload = () => {
7503
+ const result = reader.result;
7504
+ const resultLogData = JSON.parse(result);
7505
+ const logs = resultLogData.logs;
7506
+ let cursor = logs.length - 1;
7507
+ for (; cursor >= 0; cursor--) {
7508
+ const log = LogConverter.dtoToLog(logs[cursor]);
7509
+ const metadata = log.metadata;
7510
+ const level = log.level;
7511
+ if (level === LogLevel.INFO)
7512
+ logger.info(metadata);
7513
+ else if (level === LogLevel.ERROR)
7514
+ logger.error(metadata);
7515
+ }
7516
+ ;
7517
+ killReader(reader);
7518
+ };
7519
+ reader.onerror = (e) => {
7520
+ killReader(reader);
7521
+ console.log(e);
7522
+ };
7523
+ }
7524
+ }
7525
+ /**
7526
+ * @private
7527
+ */
7528
+ killReader(reader) {
7529
+ reader.onload = null;
7530
+ reader.onerror = null;
7531
+ }
7532
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxLogIoService, deps: [{ token: HttpMockLoggingService }], target: i0.ɵɵFactoryTarget.Injectable }); }
7533
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxLogIoService }); }
7534
+ }
7535
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxLogIoService, decorators: [{
7536
+ type: Injectable
7537
+ }], ctorParameters: () => [{ type: HttpMockLoggingService }] });
7538
+
7539
+ /**
7540
+ * @license
7541
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
7542
+ *
7543
+ * Use of this source code is governed by an MIT-style license that can be found in
7544
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
7545
+ */
7546
+ /**
7547
+ * @private
7548
+ * An implementation of the `LogConnector` class that sends logs to the HTTP
7549
+ * mocking console component.
7550
+ */
7551
+ class HttpMonitoringConsoleLogConnector {
7552
+ constructor() {
7553
+ /**
7554
+ * @private
7555
+ */
7556
+ this.logs = [];
7557
+ /**
7558
+ * @private
7559
+ */
7560
+ this.change = new EventEmitter(true);
7561
+ }
7562
+ /**
7563
+ * @private
7564
+ */
7565
+ destroy() {
7566
+ this.clearLogs();
7567
+ }
7568
+ /**
7569
+ * @private
7570
+ */
7571
+ init(logList) {
7572
+ this.logs.push(...logList);
7573
+ }
7574
+ /**
7575
+ * @private
7576
+ */
7577
+ sendLog(log) {
7578
+ const level = log.level;
7579
+ if (level === LogLevel.INFO || level === LogLevel.ERROR)
7580
+ this.logs.push(log);
7581
+ this.change.emit(log);
7582
+ }
7583
+ /**
7584
+ * @private
7585
+ */
7586
+ clearLogs() {
7587
+ this.logs.length = 0;
7588
+ }
7589
+ /**
7590
+ * @private
7591
+ * Not supported.
7592
+ */
7593
+ copyLogs() { }
7594
+ }
7595
+
7596
+ /**
7597
+ * @license
7598
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
7599
+ *
7600
+ * Use of this source code is governed by an MIT-style license that can be found in
7601
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
7602
+ */
7603
+ /**
7604
+ * @private
7605
+ * The service that manages user interactions with an `AtxMonitoringConsoleComponent` instance.
7606
+ */
7607
+ class AtxMonitoringConsoleController extends IdentifiableComponent {
7608
+ /**
7609
+ * @private
7610
+ */
7611
+ constructor(_logger, _state, _ioSvc, _subscribe, action) {
7612
+ super("AtxMonitoringConsoleController");
7613
+ this._logger = _logger;
7614
+ this._state = _state;
7615
+ this._ioSvc = _ioSvc;
7616
+ this._subscribe = _subscribe;
7617
+ const connector = new HttpMonitoringConsoleLogConnector();
7618
+ const logs = this._logger.getLogs();
7619
+ this.connector = connector;
7620
+ this._subscribe.register(this, connector.change.subscribe((log) => this.addLog(log)))
7621
+ .append(action.action.subscribe((action) => this.onAction(action)));
7622
+ this.connector.init(logs);
7623
+ this._state.init(logs);
7624
+ this._logger.setLogConnector(connector);
7625
+ }
7626
+ /**
7627
+ * @private
7348
7628
  */
7349
- get responseXML() {
7350
- return null;
7629
+ ngOnDestroy() {
7630
+ this._subscribe.clearAll(this);
7631
+ this._logger.setLogConnector(null);
7632
+ this.connector.destroy();
7633
+ this.connector = null;
7351
7634
  }
7352
7635
  /**
7353
7636
  * @private
7354
- *
7355
- * XMLHTTPRequest API - Useless
7356
7637
  */
7357
- overrideMimeType(mime) { }
7638
+ clearLogs() {
7639
+ this._logger.clearLogs();
7640
+ this._state.clearLogs();
7641
+ }
7358
7642
  /**
7359
7643
  * @private
7360
- *
7361
- * XMLHTTPRequest API - Useless
7362
7644
  */
7363
- getResponseHeader(name) { return null; }
7645
+ exportLogs() {
7646
+ this._ioSvc.exportFile(this._state.logs);
7647
+ }
7648
+ /**
7649
+ * @private
7650
+ */
7651
+ addLog(log) {
7652
+ this._state.addLog(log);
7653
+ }
7654
+ /**
7655
+ * @private
7656
+ */
7657
+ onAction(action) {
7658
+ switch (action.type) {
7659
+ case AtxConsoleActionType.CLEAR_LOGS:
7660
+ this.clearLogs();
7661
+ break;
7662
+ case AtxConsoleActionType.EXPORT_LOGS:
7663
+ this.exportLogs();
7664
+ break;
7665
+ case AtxConsoleActionType.IMPORT_LOGS:
7666
+ this._ioSvc.importFile(action.data);
7667
+ break;
7668
+ case AtxConsoleActionType.LOG_SELECT:
7669
+ this._state.selectLog(action.data);
7670
+ break;
7671
+ case AtxConsoleActionType.CLOSE_DETAILS_PANEL:
7672
+ this._state.selectLog(null);
7673
+ break;
7674
+ }
7675
+ }
7676
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxMonitoringConsoleController, deps: [{ token: HttpMockLoggingService }, { token: AtxMonitoringConsoleState }, { token: AtxLogIoService }, { token: SubscriptionService }, { token: AtxUserActionService }], target: i0.ɵɵFactoryTarget.Injectable }); }
7677
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxMonitoringConsoleController }); }
7364
7678
  }
7679
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxMonitoringConsoleController, decorators: [{
7680
+ type: Injectable
7681
+ }], ctorParameters: () => [{ type: HttpMockLoggingService }, { type: AtxMonitoringConsoleState }, { type: AtxLogIoService }, { type: SubscriptionService }, { type: AtxUserActionService }] });
7365
7682
 
7366
7683
  /**
7367
7684
  * @license
@@ -7372,32 +7689,43 @@ class XhrBase extends EventTargetImpl {
7372
7689
  */
7373
7690
  /**
7374
7691
  * @private
7375
- * A static utility class for building `DataStorage` objects.
7692
+ * The main component used to layout the ATX monitoring console.
7376
7693
  */
7377
- class DataStorageBuilder {
7694
+ class AtxMonitoringConsoleComponent {
7378
7695
  /**
7379
7696
  * @private
7380
- * Builds and returns a new `DataStorage` objects.
7381
- *
7382
- * @param httpResponse The `HttpResponseMock` to be stored by the framework.
7383
- * @param data The data of the HTTP response to be stored by the framework.
7384
- * @param metadata The metadata of the HTTP mock request to be stored by the framework.
7385
- *
7386
- * @returns A new `DataStorage` object.
7387
7697
  */
7388
- static buildDataStorage(httpResponse, data, metadata) {
7389
- // TODO: add support for different data types (string, Blob, etc.)
7390
- const stringifiedData = data ? JSON.stringify(data) : EMPTY_STRING;
7391
- return {
7392
- httpResponse: httpResponse,
7393
- loaded: 0,
7394
- total: data ? new Blob([stringifiedData]).size : 0,
7395
- data: data,
7396
- stringifiedData: stringifiedData,
7397
- requestMetadata: metadata
7398
- };
7698
+ constructor(state,
7699
+ //--> Conponent scope services:
7700
+ _ctrl, _io, _input) {
7701
+ this.state = state;
7702
+ this._ctrl = _ctrl;
7703
+ this._io = _io;
7704
+ this._input = _input;
7399
7705
  }
7706
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxMonitoringConsoleComponent, deps: [{ token: AtxMonitoringConsoleState }, { token: AtxMonitoringConsoleController }, { token: AtxLogIoService }, { token: AtxUserActionService }], target: i0.ɵɵFactoryTarget.Component }); }
7707
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.3", type: AtxMonitoringConsoleComponent, isStandalone: true, selector: "atx-http-monitoring-console", providers: [
7708
+ AtxMonitoringConsoleState,
7709
+ AtxLogIoService,
7710
+ AtxMonitoringConsoleController,
7711
+ AtxUserActionService
7712
+ ], ngImport: i0, template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n<atx-console-menu/>\r\n<div id=\"log-list-vieport\">\r\n <div class=\"request-list-wrapper\" [class.reduced-request-list]=\"state.selectedLog\">\r\n <atx-request-list-renderer />\r\n </div>\r\n @if (state.selectedLog) {\r\n <div id=\"selected-log-viewport\">\r\n <atx-monitoring-console-details [log]=\"state.selectedLog\"/>\r\n </div>\r\n }\r\n</div>\r\n<atx-console-footer/>\r\n\r\n<svg id=\"icon-collection\">\r\n <symbol id=\"json-icon\" viewBox=\"0 0 16 16\">\r\n <path d=\"M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z\"/>\r\n <path d=\"M8.646 6.646a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L10.293 9 8.646 7.354a.5.5 0 0 1 0-.708m-1.292 0a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0 0 .708l2 2a.5.5 0 0 0 .708-.708L5.707 9l1.647-1.646a.5.5 0 0 0 0-.708\"/>\r\n </symbol>\r\n <symbol id=\"bin-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M5.526 13.09c.976 0 1.524-.79 1.524-2.205 0-1.412-.548-2.203-1.524-2.203-.978 0-1.526.79-1.526 2.203 0 1.415.548 2.206 1.526 2.206zm-.832-2.205c0-1.05.29-1.612.832-1.612.358 0 .607.247.733.721L4.7 11.137a7 7 0 0 1-.006-.252m.832 1.614c-.36 0-.606-.246-.732-.718l1.556-1.145q.005.12.005.249c0 1.052-.29 1.614-.829 1.614m5.329.501v-.595H9.73V8.772h-.69l-1.19.786v.688L8.986 9.5h.05v2.906h-1.18V13h3z\"/>\r\n <path d=\"M4 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zm0 1h8a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1\"/>\r\n </symbol>\r\n <symbol id=\"text-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M10.943 6H5.057L5 8h.5c.18-1.096.356-1.192 1.694-1.235l.293-.01v5.09c0 .47-.1.582-.898.655v.5H9.41v-.5c-.803-.073-.903-.184-.903-.654V6.755l.298.01c1.338.043 1.514.14 1.694 1.235h.5l-.057-2z\"/>\r\n <path d=\"M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z\"/>\r\n </symbol>\r\n <symbol id=\"empty-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z\"/>\r\n </symbol>\r\n <symbol id=\"blob-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M8.002 5.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0\"/>\r\n <path d=\"M12 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2M3 2a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v8l-2.083-2.083a.5.5 0 0 0-.76.063L8 11 5.835 9.7a.5.5 0 0 0-.611.076L3 12z\"/>\r\n </symbol>\r\n</svg>", styles: [":host{--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;--header-height: 26px;display:block}:host,table{padding:0;margin:0;font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:12px;color:#000;background-color:#fff}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)!important}th{height:var(--header-height)}.header-btn{margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}summary{-webkit-user-select:none;user-select:none}:host{position:relative;padding:0;margin:0;overflow:hidden}#log-list-vieport{position:absolute;display:flex;flex-direction:row;gap:6px;padding:6px;inset:36px 0 33px}#icon-collection{visibility:hidden;width:0;height:0}.request-list-wrapper{height:100%;flex-grow:1;overflow:hidden auto;border:1px solid var(--border-color)}.reduced-request-list{min-width:250px}#selected-log-viewport{height:100%;width:80%}atx-console-footer{position:absolute;width:100%;bottom:0}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"], dependencies: [{ kind: "component", type: AtxRequestDetailsComponent, selector: "atx-monitoring-console-details", inputs: ["log"] }, { kind: "component", type: AtxConsoleFooterComponent, selector: "atx-console-footer" }, { kind: "component", type: AtxConsoleMenuComponent, selector: "atx-console-menu" }, { kind: "component", type: AtxRequestListRendererComponent, selector: "atx-request-list-renderer" }], encapsulation: i0.ViewEncapsulation.ShadowDom }); }
7400
7713
  }
7714
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxMonitoringConsoleComponent, decorators: [{
7715
+ type: Component,
7716
+ args: [{ selector: 'atx-http-monitoring-console', standalone: true, imports: [
7717
+ AtxRequestDetailsComponent,
7718
+ AtxConsoleFooterComponent,
7719
+ AtxConsoleMenuComponent,
7720
+ AtxIconRendererComponent,
7721
+ AtxRequestListRendererComponent
7722
+ ], providers: [
7723
+ AtxMonitoringConsoleState,
7724
+ AtxLogIoService,
7725
+ AtxMonitoringConsoleController,
7726
+ AtxUserActionService
7727
+ ], encapsulation: ViewEncapsulation.ShadowDom, template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n<atx-console-menu/>\r\n<div id=\"log-list-vieport\">\r\n <div class=\"request-list-wrapper\" [class.reduced-request-list]=\"state.selectedLog\">\r\n <atx-request-list-renderer />\r\n </div>\r\n @if (state.selectedLog) {\r\n <div id=\"selected-log-viewport\">\r\n <atx-monitoring-console-details [log]=\"state.selectedLog\"/>\r\n </div>\r\n }\r\n</div>\r\n<atx-console-footer/>\r\n\r\n<svg id=\"icon-collection\">\r\n <symbol id=\"json-icon\" viewBox=\"0 0 16 16\">\r\n <path d=\"M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z\"/>\r\n <path d=\"M8.646 6.646a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L10.293 9 8.646 7.354a.5.5 0 0 1 0-.708m-1.292 0a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0 0 .708l2 2a.5.5 0 0 0 .708-.708L5.707 9l1.647-1.646a.5.5 0 0 0 0-.708\"/>\r\n </symbol>\r\n <symbol id=\"bin-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M5.526 13.09c.976 0 1.524-.79 1.524-2.205 0-1.412-.548-2.203-1.524-2.203-.978 0-1.526.79-1.526 2.203 0 1.415.548 2.206 1.526 2.206zm-.832-2.205c0-1.05.29-1.612.832-1.612.358 0 .607.247.733.721L4.7 11.137a7 7 0 0 1-.006-.252m.832 1.614c-.36 0-.606-.246-.732-.718l1.556-1.145q.005.12.005.249c0 1.052-.29 1.614-.829 1.614m5.329.501v-.595H9.73V8.772h-.69l-1.19.786v.688L8.986 9.5h.05v2.906h-1.18V13h3z\"/>\r\n <path d=\"M4 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zm0 1h8a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1\"/>\r\n </symbol>\r\n <symbol id=\"text-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M10.943 6H5.057L5 8h.5c.18-1.096.356-1.192 1.694-1.235l.293-.01v5.09c0 .47-.1.582-.898.655v.5H9.41v-.5c-.803-.073-.903-.184-.903-.654V6.755l.298.01c1.338.043 1.514.14 1.694 1.235h.5l-.057-2z\"/>\r\n <path d=\"M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z\"/>\r\n </symbol>\r\n <symbol id=\"empty-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z\"/>\r\n </symbol>\r\n <symbol id=\"blob-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M8.002 5.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0\"/>\r\n <path d=\"M12 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2M3 2a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v8l-2.083-2.083a.5.5 0 0 0-.76.063L8 11 5.835 9.7a.5.5 0 0 0-.611.076L3 12z\"/>\r\n </symbol>\r\n</svg>", styles: [":host{--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;--header-height: 26px;display:block}:host,table{padding:0;margin:0;font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:12px;color:#000;background-color:#fff}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)!important}th{height:var(--header-height)}.header-btn{margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}summary{-webkit-user-select:none;user-select:none}:host{position:relative;padding:0;margin:0;overflow:hidden}#log-list-vieport{position:absolute;display:flex;flex-direction:row;gap:6px;padding:6px;inset:36px 0 33px}#icon-collection{visibility:hidden;width:0;height:0}.request-list-wrapper{height:100%;flex-grow:1;overflow:hidden auto;border:1px solid var(--border-color)}.reduced-request-list{min-width:250px}#selected-log-viewport{height:100%;width:80%}atx-console-footer{position:absolute;width:100%;bottom:0}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }]
7728
+ }], ctorParameters: () => [{ type: AtxMonitoringConsoleState }, { type: AtxMonitoringConsoleController }, { type: AtxLogIoService }, { type: AtxUserActionService }] });
7401
7729
 
7402
7730
  /**
7403
7731
  * @license
@@ -7408,29 +7736,83 @@ class DataStorageBuilder {
7408
7736
  */
7409
7737
  /**
7410
7738
  * @private
7411
- * A static builder for creating `HttpMockLoggingMetadata` objects.
7412
7739
  */
7413
- class HttpMockLoggingMetadataBuilder {
7740
+ const NO = WindowFeatureState.NO;
7741
+ /**
7742
+ * @private
7743
+ */
7744
+ const FEATURES = {
7745
+ left: 100,
7746
+ top: 100,
7747
+ width: 800,
7748
+ height: 450,
7749
+ directories: NO,
7750
+ titlebar: NO,
7751
+ scrollbars: NO,
7752
+ toolbar: NO,
7753
+ location: NO,
7754
+ status: NO,
7755
+ menubar: NO,
7756
+ title: "HTTP Mocking Framework Console",
7757
+ icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAABdJJREFUWEedl3tsU1Ucx7+/e/vYGNs6ZOrawSBsIgwQCC/jJhAgiIkkvkBgBJB2Q4eSoBHwFQaiTsBgdMRBMNEwum5/8EoQAQF5yQQhBB0ZOBSS6cIYsPa269rec8ztY33sru24Sf/o/Z3f93zuOb/f7/wO4WEea/sgQaNfAJmXkKPDyUG7mSjU4fWctr7KUdIO1fcyRYP+ZYCVADQVgADOAIcjKEFeEI6A8xqZ0X6UGV3JaMcHqOZa0eB6DuDKpC8APDVKNAogwsIhAXwvQajxGXKOYR7JvcGoAmhrXVMYKZPy+QAG9volvQFEOVArcWYjUdjtXW68GKsVBqhz5wvcW0IQFgE8P5nli96CxB4ENDHwGsbYHpQNblY8/ACiTbIBeDX0P7FUcERSK6CqxgFeL1ty54cADgOYnfTEoYEPD6AoHJQtprlBAMdOgMxqAMP6E3QEXHPwnuYIgFSRsGBYKqYbddh4ScJ1uy/u93DOt7PS3HI/gFDr+JiIKmI98vsTfp6WiuwUwrYmLzY1euCMjOcgQHaKgC1TMpCbJuLqPS9Wn7eDqfBG6nOOtazUVBlYgVr7MpDwXSzAOIOA87NSIQZD1XrLh8UNXeFhQYDKSRmYkK2F3cNQeroDbW7mHzM6SwOXj6PZoZqFC2WLyRqQtj2YKUJzVG3Nto3TYWWB1m9qcXEUHHLBE9CHkgX9OyXsmz3AH82X73rxboPdb1JWpbo4E2daPfjyqrOHtEwogtl0NgBQ635CJF+TGkCmFtg1UY9nskVk6wkHWnx47deuAARnGEYu7Cg2dLse+McNa3MnPhqfjpFZGhy67cZWNQBGeSgz3g4AVPN+osEpxUvDVBHYV5SCGY+JYQiZYbjQie1Fmb0G3MZLDpz8zxNjJ5/c0pSK9dN93YVIsEltFK/qAYiE2NnsxRsX3Via48Pign6qAL+3ebHmNzti45EDt5nFlKc4hQHqpEvEMS5u7gQhqsbr/RlRNFBAySCCEFPQPTLHsZYuVDW64JZV0oHojGw2FkcBiDbHfoDmJgII2d/K16ByrA7nWj0gAk7+24X6m27c62Jo72JQmzdC2ypbTAujV8Dm/IbAy5MBeO9JLTaN0cHHOM62evy/issOZGoJ9z0JCoASu4RKZjatjQGQ1hDweSKA9YVafFio8w/zMo6qP51Yd8GOMVlabJiQjm1/SDjaEht00aocWMkspqroLaiTFoKjJh7AF0/psHp4oCYoT8NdH2YebMNIgwafTEyHTiR/Bdx8xYEj8SAIc2Wz6WAUAKz2YlEQTqkBKDH29XgdVuSHJ7/WwTDtuAuCU8L30wzQh8ol4IfYcsWBn3qBkGU+Fityr8QA3B8iCtq/YwEU3eoJOiwdGp78lpPh2eNutLhkf0v20pAUlBemRbnGg5D7pQ3AIsP9aIBA+9UJcDGkpCHgh8l6zBus6Ra/4+aYerwTNyTlSA/3hC/mpWDlqJ4Qq851oPFB5MlIDtlizAgJRmWwYJNaCDCGjB+M0KJidCDglMfu5Zhxwo3LD4KHQUw/oECUj0oLFxcAO645Ybvp7tbghEZmNhWqAoi10nkQJoeMuybqsCS49EpBef4XN07dDZ1EgbMg3BUHvCIhlDQtP9uBv+wRpyHRYdlsnKMOYHPUA/RKyFiYIcD6tB7pWsKbF7vwY2vMsdpLRzT2EQ1GZWnRcMeDG5GT+4Vph2wxlqkCoE56XOR8I0DLlDZBLSOi3vWpJeNezulbpk+vwJKMdnWA0Ns90hhRxBYAs+JCJA1Ae2XO1qI093qsXtyLiVjvnMM530wc3UHTtxXgF2QI78BiPN3bhyS+mq0/oRFGTDITuNIzPpoMAAduEaP35dIcK4jiHg6JAUIz7m7PEDT6dUS0qvuK1mMLeAfn9BnTer7CsqHh3Iuzj8kDhERqOvNEUf4UhAXgjAJpSF7OeTVzuzbg7YI+3ZD7DhACqXNNEmXfVkiOdlnAGiw3qfaUiTLpf29zez9zLqGcAAAAAElFTkSuQmCC"
7758
+ };
7759
+ /**
7760
+ * Provides functionality to display the ATX monitoring console within a new window.
7761
+ */
7762
+ class AtxHttpMockConsoleService {
7414
7763
  /**
7415
7764
  * @private
7416
- * Creates and returns a new `HttpMockLoggingMetadata` object.
7417
7765
  */
7418
- static build(xhr, request, requestMetadata) {
7419
- const responseInit = {
7420
- body: xhr.response,
7421
- status: xhr.status,
7422
- statusText: xhr.statusText,
7423
- url: xhr.responseURL,
7424
- headers: HttpHeadersUtil.encode(xhr.getAllResponseHeaders())
7425
- };
7426
- const response = new HttpResponse(responseInit);
7427
- return {
7428
- request: request,
7429
- response: response,
7430
- requestMetadata: requestMetadata
7431
- };
7766
+ constructor(_windowSrv) {
7767
+ this._windowSrv = _windowSrv;
7768
+ /**
7769
+ * @private
7770
+ */
7771
+ this._uuid = null;
7772
+ }
7773
+ /**
7774
+ * Opens the ATX monitoring console within a new window and returns reference objects
7775
+ * to control it.
7776
+ */
7777
+ open() {
7778
+ if (this._uuid)
7779
+ return;
7780
+ this._uuid = this._windowSrv.open(AtxMonitoringConsoleComponent, FEATURES);
7432
7781
  }
7782
+ /**
7783
+ * Closes the ATX monitoring console currently opened within a popup window.
7784
+ */
7785
+ close() {
7786
+ if (!this._uuid)
7787
+ return;
7788
+ this._windowSrv.close(this._uuid);
7789
+ this._uuid = null;
7790
+ }
7791
+ /**
7792
+ * Returns reference to the opened popup window.
7793
+ *
7794
+ * @returns A `WindowRef` object, or undefined if the ATX monitoring console is not opened.
7795
+ */
7796
+ getWindowRef() {
7797
+ if (!this._uuid)
7798
+ return undefined;
7799
+ return this._windowSrv.get(this._uuid);
7800
+ }
7801
+ /**
7802
+ * @private
7803
+ */
7804
+ ngOnDestroy() {
7805
+ this.close();
7806
+ }
7807
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxHttpMockConsoleService, deps: [{ token: WindowService }], target: i0.ɵɵFactoryTarget.Injectable }); }
7808
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxHttpMockConsoleService, providedIn: 'root' }); }
7433
7809
  }
7810
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxHttpMockConsoleService, decorators: [{
7811
+ type: Injectable,
7812
+ args: [{
7813
+ providedIn: 'root'
7814
+ }]
7815
+ }], ctorParameters: () => [{ type: WindowService }] });
7434
7816
 
7435
7817
  /**
7436
7818
  * @license
@@ -7440,29 +7822,34 @@ class HttpMockLoggingMetadataBuilder {
7440
7822
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
7441
7823
  */
7442
7824
  /**
7443
- * @private
7444
- * A utility for managing HTTP responses delay.
7825
+ * A convenient high-level singleton that implements the `Logger` interface.
7445
7826
  */
7446
- class HttpMockResponseDelayUtil {
7827
+ class LoggerService extends AbstractLogger {
7447
7828
  /**
7448
7829
  * @private
7449
- * A utility function that return a `ResponseDelay` object, depending on the timer parameters.
7450
- *
7451
- * @param timer The seed value used to create the `ResponseDelay` object.
7452
- * @returns A `ResponseDelay` object.
7453
7830
  */
7454
- static getResponseDelay(timer) {
7455
- let duration = timer;
7456
- if (timer < 0)
7457
- duration = 0;
7458
- if (timer > HTTP_MOCK_MAX_DELAY)
7459
- duration = HTTP_MOCK_MAX_DELAY;
7460
- return {
7461
- stalled: Math.random() * duration,
7462
- duration: duration
7463
- };
7831
+ constructor(config) {
7832
+ super();
7833
+ if (config) {
7834
+ const connector = config.logConnector;
7835
+ if (connector)
7836
+ this.setLogConnector(connector);
7837
+ }
7464
7838
  }
7839
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: LoggerService, deps: [{ token: ATX_LOGGER_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
7840
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: LoggerService, providedIn: 'root' }); }
7465
7841
  }
7842
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: LoggerService, decorators: [{
7843
+ type: Injectable,
7844
+ args: [{
7845
+ providedIn: 'root'
7846
+ }]
7847
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
7848
+ type: Inject,
7849
+ args: [ATX_LOGGER_CONFIG]
7850
+ }, {
7851
+ type: Optional
7852
+ }] }] });
7466
7853
 
7467
7854
  /**
7468
7855
  * @license
@@ -7471,359 +7858,346 @@ class HttpMockResponseDelayUtil {
7471
7858
  * Use of this source code is governed by an MIT-style license that can be found in
7472
7859
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
7473
7860
  */
7474
- /**
7475
- * @private
7476
- * Intenal "onreadystatechange" event.
7477
- */
7478
- const READY_STATE_CHANGE_EVENT = new Event("onreadystatechange");
7479
7861
  /**
7480
7862
  * @private
7481
7863
  */
7482
- const EVT_PROPS_CONFIG = { writable: false, value: this };
7864
+ const PX = "px";
7483
7865
  /**
7484
- * @private
7485
- * A utility class used as delegate of `XMLHttpRequest` functionalities when
7486
- * a HTTP request is intercepted by the Mocking Framework .
7866
+ * A container that defines the region of a `BorderLayout` component instance.
7487
7867
  */
7488
- class DelegateXhr extends XhrBase {
7868
+ class BorderLayoutContainer {
7489
7869
  /**
7490
- * Returns the response body content.
7491
- *
7492
- * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/response
7870
+ * Gets the CSS class associated with the region constraint of the `BorderLayoutContainer` object.
7493
7871
  */
7494
- get response() {
7495
- return this._dataStorage?.data || null;
7872
+ get class() {
7873
+ return this.region;
7496
7874
  }
7497
7875
  /**
7498
- * Returns the numerical HTTP status code of the `XMLHttpRequest` response.
7499
- *
7500
- * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/status
7876
+ * Gets or sets the constraints for this `BorderLayoutContainer` object.
7501
7877
  */
7502
- get status() {
7503
- return this._status;
7878
+ get constraints() {
7879
+ return this.atxConstraints;
7504
7880
  }
7505
- /**
7506
- * Returns a string containing the response status message as returned by the HTTP server.
7507
- *
7508
- * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/statusText
7509
- */
7510
- get statusText() {
7511
- return this._statusText;
7881
+ set constraints(constraints) {
7882
+ this.atxConstraints = constraints;
7883
+ this.region = constraints.region;
7884
+ if (constraints.resizable)
7885
+ this.initHandle();
7886
+ this.setSize(constraints.size);
7512
7887
  }
7513
7888
  /**
7514
- * Returns the state the `XMLHttpRequest` client is in.
7515
- *
7516
- * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/readyState
7889
+ * @private
7517
7890
  */
7518
- get readyState() {
7519
- return this._readyState;
7891
+ constructor(elRef) {
7892
+ this.elRef = elRef;
7893
+ /**
7894
+ * @private
7895
+ * Indicates to the parent `BorderLayout` instance that the user starts to resize this container.
7896
+ */
7897
+ this.resizeStart = new EventEmitter(false);
7898
+ /**
7899
+ * @private
7900
+ */
7901
+ this.selected = false;
7902
+ /**
7903
+ * @private
7904
+ */
7905
+ this.resizable = false;
7906
+ this.style = this.elRef.nativeElement.style;
7520
7907
  }
7521
7908
  /**
7522
- * Returns the serialized URL of the response or the empty string if the URL is `null`.
7909
+ * Sets the size of this container depending on the specified region.
7523
7910
  *
7524
- * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/responseURL
7911
+ * @param size The new size for this container, in pixels.
7525
7912
  */
7526
- get responseURL() {
7527
- return this._url;
7913
+ setSize(size) {
7914
+ const r = this.region;
7915
+ if (r === LayoutRegion.CENTER)
7916
+ return;
7917
+ if (r === LayoutRegion.NORTH || r === LayoutRegion.SOUTH) {
7918
+ this.size = size ? size : 50;
7919
+ this.style.height = this.size + PX;
7920
+ return;
7921
+ }
7922
+ if (r === LayoutRegion.EAST || r === LayoutRegion.WEST) {
7923
+ this.size = size ? size : 100;
7924
+ this.style.width = this.size + PX;
7925
+ }
7528
7926
  }
7529
7927
  /**
7530
- * Returns the text received from a server following a request being sent.
7531
- *
7532
- * Throws an `InvalidStateError` DOMException if responseType is not the empty string or "text".
7928
+ * Returns the size of the container, in pixels.
7533
7929
  *
7534
- * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/responseText
7930
+ * @returns The size of the container.
7535
7931
  */
7536
- get responseText() {
7537
- return this._dataStorage?.stringifiedData || EMPTY_STRING;
7932
+ getSize() {
7933
+ return this.size;
7538
7934
  }
7539
7935
  /**
7540
- * Returns an `XMLHttpRequestUpload` object that can be observed to monitor an upload progress.
7936
+ * Sets the left-hand side position of this container.
7541
7937
  *
7542
- * @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/upload
7543
- */
7544
- get upload() {
7545
- return null;
7546
- }
7547
- /**
7548
- * @private
7938
+ * @param position The left-hand side position of this container, in pixels.
7549
7939
  */
7550
- open(method, url, async, username, password) {
7551
- this._method = method;
7552
- this._url = url;
7553
- this.setReadyState(this.OPENED);
7940
+ setLeftPos(position) {
7941
+ this.style.left = position + PX;
7554
7942
  }
7555
7943
  /**
7556
- * Aborts the request if it has already been sent. When a request is aborted, its `readyState`
7557
- * is changed to `XMLHttpRequest.UNSENT` and the request status code is set to `0`.
7944
+ * Sets the right-hand side position of this container.
7945
+ *
7946
+ * @param position The right-hand side position of this container, in pixels.
7558
7947
  */
7559
- abort() {
7560
- this._readyState = this.UNSENT;
7561
- this._status = 0;
7562
- this.eventDispatch("abort");
7948
+ setRightPos(position) {
7949
+ this.style.right = position + PX;
7563
7950
  }
7564
7951
  /**
7565
- * Returns all the response headers, separated by CRLF, as a string, or returns `null`
7566
- * if no response has been received.
7952
+ * Sets the top position of this container.
7567
7953
  *
7568
- * @returns All the response headers, separated by CRLF, as a string, or returns `null`
7569
- * if no response has been received.
7954
+ * @param position The top position of this container, in pixels.
7570
7955
  */
7571
- getAllResponseHeaders() {
7572
- if (this._readyState < this.HEADERS_RECEIVED)
7573
- return null;
7574
- const respHeaders = this._dataStorage?.httpResponse.headers;
7575
- if (respHeaders)
7576
- return HttpHeadersUtil.stringify(respHeaders);
7577
- return null;
7956
+ setTopPos(position) {
7957
+ this.style.top = position + PX;
7578
7958
  }
7579
7959
  /**
7580
- * Sends the request to the server.
7960
+ * Sets the bottom position of this container.
7581
7961
  *
7582
- * @param body A body of data to be sent in the XHR request.
7962
+ * @param position The bottom position of this container, in pixels.
7583
7963
  */
7584
- send(body) {
7585
- const start = this.now();
7586
- const request = this.buildHttpRequest(body);
7587
- const rc = this._routeConfig;
7588
- const httpResponseMock = rc.methodConfig.data(request, rc.parameters);
7589
- const responseDelay = HttpMockResponseDelayUtil.getResponseDelay(httpResponseMock.delay || 0);
7590
- const timer = responseDelay.duration;
7591
- const requestMetadata = {
7592
- start: start,
7593
- stalled: responseDelay.stalled,
7594
- duration: timer,
7595
- url: new URL(this._url),
7596
- id: Uuid.build()
7597
- };
7598
- const prefetchMetadata = {
7599
- request: request,
7600
- requestMetadata: requestMetadata
7601
- };
7602
- this._logger.prefetch(prefetchMetadata);
7603
- this._loadSubscription = this.loadData(httpResponseMock).subscribe({
7604
- next: (data) => {
7605
- this.setDataStorage(httpResponseMock, requestMetadata, data);
7606
- const error = this._dataStorage.httpResponse.error;
7607
- setTimeout(() => {
7608
- this.setReadyState(this.HEADERS_RECEIVED);
7609
- if (error)
7610
- return this.onError(request, error);
7611
- this.setReadyState(this.LOADING);
7612
- const response = this._dataStorage.httpResponse;
7613
- if (!this._progressiveDownload) {
7614
- this._statusText = response.statusText || EMPTY_STRING;
7615
- this._status = response.status || 0;
7616
- return this.onLoadComplete(request);
7617
- }
7618
- this.doProgressiveDownload(request);
7619
- }, timer);
7620
- },
7621
- error: (err) => {
7622
- this.setDataStorage(httpResponseMock, requestMetadata);
7623
- this.onError(request, err);
7624
- }
7625
- });
7964
+ setBottomPos(position) {
7965
+ this.style.bottom = position + PX;
7626
7966
  }
7627
7967
  /**
7628
- * Sets the value of an HTTP request header.
7629
- *
7630
- * @param name The name of the header whose value is to be set.
7631
- * @param value The value to set as the body of the header.
7968
+ * @private
7632
7969
  */
7633
- setRequestHeader(name, value) {
7634
- this._requestHeaders = this._requestHeaders.set(name, value);
7970
+ resizetart() {
7971
+ this.resizeStart.emit(this);
7635
7972
  }
7636
7973
  /**
7637
7974
  * @private
7638
7975
  */
7639
- constructor(routeConfig, _logger) {
7640
- super();
7641
- this._logger = _logger;
7642
- /**
7643
- * @private
7644
- * Indicates whether the progressive download is activated, or not.
7645
- */
7646
- this._progressiveDownload = false;
7647
- /**
7648
- * @private
7649
- *
7650
- * Internal storage for HTTP response `data`.
7651
- */
7652
- this._dataStorage = null;
7653
- /**
7654
- * @private
7655
- *
7656
- * Internal storage for the HTTP request `readyState`.
7657
- */
7658
- this._readyState = this.UNSENT;
7659
- /**
7660
- * @private
7661
- *
7662
- * Internal storage for the HTTP request `headers`.
7663
- */
7664
- this._requestHeaders = null;
7976
+ initHandle() {
7977
+ if (this.region === LayoutRegion.CENTER)
7978
+ return;
7979
+ this.resizable = true;
7980
+ }
7981
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: BorderLayoutContainer, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
7982
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.3", type: BorderLayoutContainer, isStandalone: true, selector: "atx-border-layout-container", inputs: { constraints: "constraints" }, host: { properties: { "class": "this.class" } }, ngImport: i0, template: "<!--\n * LICENSE\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n-->\n\n<ng-content></ng-content>\n@if (resizable) {\n <div class=\"atx-handle\" [class.atx-handle-selected]=\"selected\" (mousedown)=\"resizetart()\"></div>\n}\n", styles: [":host{box-sizing:border-box;padding:0;margin:0}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }); }
7983
+ }
7984
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: BorderLayoutContainer, decorators: [{
7985
+ type: Component,
7986
+ args: [{ selector: 'atx-border-layout-container', standalone: true, template: "<!--\n * LICENSE\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n-->\n\n<ng-content></ng-content>\n@if (resizable) {\n <div class=\"atx-handle\" [class.atx-handle-selected]=\"selected\" (mousedown)=\"resizetart()\"></div>\n}\n", styles: [":host{box-sizing:border-box;padding:0;margin:0}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }]
7987
+ }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { class: [{
7988
+ type: HostBinding,
7989
+ args: ['class']
7990
+ }], constraints: [{
7991
+ type: Input
7992
+ }] } });
7993
+
7994
+ /**
7995
+ * @license
7996
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
7997
+ *
7998
+ * Use of this source code is governed by an MIT-style license that can be found in
7999
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
8000
+ */
8001
+ /**
8002
+ * @private
8003
+ * A utility class that computes the size of all border layout containers.
8004
+ */
8005
+ class BorderLayoutBoundsManager {
8006
+ constructor() {
7665
8007
  /**
7666
8008
  * @private
7667
- *
7668
- * Internal storage for the HTTP request `status`.
8009
+ * The container top position when the user starts to drag the handle.
7669
8010
  */
7670
- this._status = 0;
8011
+ this.topPos = 0;
7671
8012
  /**
7672
8013
  * @private
7673
- *
7674
- * Internal storage for the HTTP request `statusText`.
8014
+ * The container left position when the user starts to drag the handle.
7675
8015
  */
7676
- this._statusText = EMPTY_STRING;
8016
+ this.leftPos = 0;
7677
8017
  /**
7678
8018
  * @private
8019
+ * The bounds of the center container.
7679
8020
  */
7680
- this._loadSubscription = null;
7681
- /**
7682
- * Returns an an enumerated string value specifying the type of data contained in the response.
7683
- *
7684
- * @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType
7685
- */
7686
- this.responseType = EMPTY_STRING;
7687
- this._routeConfig = routeConfig;
7688
- // routeConfig.methodConfig.downloadManager
7689
- this._progressiveDownload = false;
7690
- this._requestHeaders = new HttpHeaders();
8021
+ this.bounds = new DOMRect();
7691
8022
  }
7692
8023
  /**
7693
- * @private
7694
- * Internally used by the framework to delete a `DelegateXhr` instance.
8024
+ * Makes this object elligible for garbage collection.
7695
8025
  */
7696
8026
  destroy() {
7697
- this._routeConfig = null;
7698
- this._requestHeaders = null;
7699
- this._dataStorage = null;
7700
- if (this._loadSubscription) {
7701
- this._loadSubscription.unsubscribe();
7702
- this._loadSubscription = null;
7703
- }
8027
+ this.bounds = null;
8028
+ }
8029
+ /**
8030
+ * Returns a rectangle that represents the bounds currently computed by this object.
8031
+ *
8032
+ * @returns The bounds currently computed by this object.
8033
+ */
8034
+ getBounds() {
8035
+ return this.bounds;
8036
+ }
8037
+ /**
8038
+ * Sets the top-left hand corner position before each bounds computaion.
8039
+ *
8040
+ * @param x The x position of the main container, in pixels, before computaion.
8041
+ * @param y The y position of the main container, in pixels, before computaion.
8042
+ */
8043
+ setOrigin(x, y) {
8044
+ this.leftPos = x;
8045
+ this.topPos = y;
7704
8046
  }
7705
8047
  /**
7706
8048
  * @private
8049
+ * For test purpose only.
7707
8050
  */
7708
- doProgressiveDownload(request) {
7709
- const total = this._dataStorage.total;
7710
- if (total <= 200) {
7711
- console.warn("[Angular Toolbox]: Body content is too small for emulating progressive download! Minimum size is 200 octets.");
7712
- return this.onLoadComplete(request);
7713
- }
7714
- // TODO: ameliorate the following process:
7715
- const self = this;
7716
- const chunckSize = Math.floor(total / 10);
7717
- let cursor = 0;
7718
- this._statusText = "Partial Content";
7719
- this._status = HttpStatusCode.PartialContent;
7720
- const idx = setInterval(() => {
7721
- cursor += chunckSize;
7722
- if (cursor > total) {
7723
- cursor = total;
7724
- clearInterval(idx);
7725
- self.onLoadComplete(request);
7726
- }
7727
- else {
7728
- this._dataStorage.loaded = cursor;
7729
- self.dispatchProgressEvent();
7730
- }
7731
- }, 100);
8051
+ getOrigin() {
8052
+ return { x: this.leftPos, y: this.topPos };
7732
8053
  }
7733
- finalizeRequestMetadata() {
7734
- const ds = this._dataStorage;
7735
- const metadata = ds.requestMetadata;
7736
- const duration = this.now() - metadata.start;
7737
- if (duration > metadata.duration)
7738
- metadata.duration = duration;
7739
- return metadata;
8054
+ /**
8055
+ * Computes the size of a "north" container.
8056
+ *
8057
+ * @param event The mouse event that triggered the computation of the container size.
8058
+ * @param width The width of the main container.
8059
+ * @param height The height of the main container.
8060
+ * @param minSize The minimum size of the container for which to compute the size.
8061
+ * @param maxSize The maximum size of the container for which to compute the size.
8062
+ *
8063
+ * @returns The size of a "north" container.
8064
+ */
8065
+ northResize(event, width, height, minSize, maxSize) {
8066
+ const size = event.clientY - this.topPos;
8067
+ if (maxSize && size > maxSize)
8068
+ return this.setY(maxSize);
8069
+ if (minSize && size < minSize)
8070
+ return this.setY(minSize);
8071
+ return this.setY(size);
7740
8072
  }
7741
8073
  /**
7742
8074
  * @private
7743
8075
  */
7744
- onLoadComplete(request) {
7745
- this._dataStorage.loaded = this._dataStorage.total;
7746
- this.setReadyState(this.DONE);
7747
- this.dispatchProgressEvent("load");
7748
- this._logger.info(this.buildMetadata(request));
8076
+ setY(y) {
8077
+ this.bounds.y = y;
8078
+ return y;
7749
8079
  }
7750
8080
  /**
7751
- * @private
8081
+ * Computes the size of a "south" container.
8082
+ *
8083
+ * @param event The mouse event that triggered the computation of the container size.
8084
+ * @param width The width of the main container.
8085
+ * @param height The height of the main container.
8086
+ * @param minSize The minimum size of the container for which to compute the size.
8087
+ * @param maxSize The maximum size of the container for which to compute the size.
8088
+ *
8089
+ * @returns The size of a "south" container.
7752
8090
  */
7753
- onError(request, error) {
7754
- this._status = error.status;
7755
- this._statusText = error.statusText;
7756
- this.setReadyState(this.DONE);
7757
- this.dispatchProgressEvent("error");
7758
- this._logger.error(this.buildMetadata(request));
8091
+ southResize(event, width, height, minSize, maxSize) {
8092
+ const size = height - (event.clientY - this.topPos);
8093
+ if (maxSize && size > maxSize)
8094
+ return this.setHeight(maxSize);
8095
+ if (minSize && size < minSize)
8096
+ return this.setHeight(minSize);
8097
+ return this.setHeight(size);
7759
8098
  }
7760
8099
  /**
7761
8100
  * @private
7762
8101
  */
7763
- buildMetadata(request) {
7764
- return HttpMockLoggingMetadataBuilder.build(this, request, this.finalizeRequestMetadata());
8102
+ setHeight(height) {
8103
+ this.bounds.height = height;
8104
+ return height;
7765
8105
  }
7766
8106
  /**
7767
- * @private
8107
+ * Computes the size of a "west" container.
8108
+ *
8109
+ * @param event The mouse event that triggered the computation of the container size.
8110
+ * @param width The width of the main container.
8111
+ * @param height The height of the main container.
8112
+ * @param minSize The minimum size of the container for which to compute the size.
8113
+ * @param maxSize The maximum size of the container for which to compute the size.
8114
+ *
8115
+ * @returns The size of a "west" container.
7768
8116
  */
7769
- eventDispatch(type) {
7770
- const event = new Event(type);
7771
- Object.defineProperty(event, 'target', EVT_PROPS_CONFIG);
7772
- Object.defineProperty(event, 'currentTarget', EVT_PROPS_CONFIG);
7773
- this.dispatchEvent(event);
8117
+ westResize(event, width, height, minSize, maxSize) {
8118
+ const size = event.clientX - this.leftPos;
8119
+ if (maxSize && size > maxSize)
8120
+ return this.setX(maxSize);
8121
+ if (minSize && size < minSize)
8122
+ return this.setX(minSize);
8123
+ return this.setX(size);
7774
8124
  }
7775
8125
  /**
7776
8126
  * @private
7777
8127
  */
7778
- dispatchProgressEvent(type = "progress") {
7779
- const d = this._dataStorage;
7780
- const event = new ProgressEventMock(type);
7781
- event.loaded = d.loaded;
7782
- event.total = d.total;
7783
- this.dispatchEvent(event);
8128
+ setX(x) {
8129
+ this.bounds.x = x;
8130
+ return x;
7784
8131
  }
7785
8132
  /**
7786
- * @private
8133
+ * Computes the size of a "east" container.
8134
+ *
8135
+ * @param event The mouse event that triggered the computation of the container size.
8136
+ * @param width The width of the main container.
8137
+ * @param height The height of the main container.
8138
+ * @param minSize The minimum size of the container for which to compute the size.
8139
+ * @param maxSize The maximum size of the container for which to compute the size.
8140
+ *
8141
+ * @returns The size of a "east" container.
7787
8142
  */
7788
- setReadyState(state) {
7789
- this._readyState = state;
7790
- const event = this.onreadystatechange;
7791
- if (event)
7792
- event.call(this, READY_STATE_CHANGE_EVENT);
8143
+ eastResize(event, width, height, minSize, maxSize) {
8144
+ const size = width - (event.clientX - this.leftPos);
8145
+ if (maxSize && size > maxSize)
8146
+ return this.setWidth(maxSize);
8147
+ if (minSize && size < minSize)
8148
+ return this.setWidth(minSize);
8149
+ return this.setWidth(size);
7793
8150
  }
7794
8151
  /**
7795
8152
  * @private
7796
8153
  */
7797
- loadData(httpResponseMock) {
7798
- const responseBody = httpResponseMock.body;
7799
- return (responseBody instanceof Observable) ? responseBody : of(responseBody);
8154
+ setWidth(width) {
8155
+ this.bounds.width = width;
8156
+ return width;
7800
8157
  }
7801
8158
  /**
7802
- * @private
8159
+ * Invoked after each `BorderLayoutContainer` registration to initialize the center container bounds.
8160
+ *
8161
+ * @param container A `BorderLayoutContainer` instance added to the main container.
7803
8162
  */
7804
- setDataStorage(responseMock, requestMetadata, data = null) {
7805
- this._dataStorage = DataStorageBuilder.buildDataStorage(responseMock, data, requestMetadata);
8163
+ initBounds(container) {
8164
+ const r = container.constraints.region;
8165
+ if (r === LayoutRegion.NORTH) {
8166
+ this.bounds.y = container.getSize();
8167
+ return;
8168
+ }
8169
+ if (r === LayoutRegion.SOUTH) {
8170
+ this.bounds.height = container.getSize();
8171
+ return;
8172
+ }
8173
+ if (r === LayoutRegion.WEST) {
8174
+ this.bounds.x = container.getSize();
8175
+ return;
8176
+ }
8177
+ if (r === LayoutRegion.EAST)
8178
+ this.bounds.width = container.getSize();
7806
8179
  }
7807
8180
  /**
7808
- * @private
8181
+ * Returns the method used to compute the size of a container, depending on the specified region.
8182
+ *
8183
+ * @param region The region associated with the container for which to compute the size.
8184
+ *
8185
+ * @returns The method used to compute the size of a container.
7809
8186
  */
7810
- buildHttpRequest(body) {
7811
- let params = new HttpParams();
7812
- const it = this._routeConfig.searchParams.entries();
7813
- for (const pair of it)
7814
- params = params.set(pair[0], pair[1]);
7815
- const init = {
7816
- params: params,
7817
- headers: this._requestHeaders,
7818
- withCredentials: this.withCredentials,
7819
- responseType: this.responseType,
7820
- reportProgress: this.hasEventListener("progress")
7821
- // context, transferCache: not used by Angular at this level of API
7822
- };
7823
- return new HttpRequest(this._method, this._url, body, init);
7824
- }
7825
- now() {
7826
- return Date.now();
8187
+ getResizeMethod(region) {
8188
+ let method = this.southResize;
8189
+ switch (region) {
8190
+ case LayoutRegion.NORTH:
8191
+ method = this.northResize;
8192
+ break;
8193
+ case LayoutRegion.WEST:
8194
+ method = this.westResize;
8195
+ break;
8196
+ case LayoutRegion.EAST:
8197
+ method = this.eastResize;
8198
+ break;
8199
+ }
8200
+ return method.bind(this);
7827
8201
  }
7828
8202
  }
7829
8203
 
@@ -7836,215 +8210,608 @@ class DelegateXhr extends XhrBase {
7836
8210
  */
7837
8211
  /**
7838
8212
  * @private
7839
- * An error used as reference for unit testing.
7840
- * Angular framework calls `XMLHttpRequest` method only after the `open()` method invokation.
7841
8213
  */
7842
- const XHR_ERROR = (method) => {
7843
- throw new Error(`Attempt to call ${method}() method before calling open().`);
7844
- };
8214
+ const MOUSEMOVE = "mousemove";
7845
8215
  /**
7846
8216
  * @private
7847
- * A XHR proxy that is used by the Mocking Framework to apply HTTP call strategies.
7848
8217
  */
7849
- class XhrProxyImpl extends XhrBase {
8218
+ const MOUSEUP = "mouseup";
8219
+ /**
8220
+ * @private
8221
+ */
8222
+ const REGION_ERR_MSG = "A container with the same identifier has already been registered: ";
8223
+ /**
8224
+ * @private
8225
+ */
8226
+ const LAYOUT_ERR_MSG = "No layout container has been registered.";
8227
+ /**
8228
+ * @private
8229
+ * A controller object responsible for handling user actions on a `BorderLayout` container.
8230
+ */
8231
+ class BorderLayoutRenderer extends IdentifiableComponent {
7850
8232
  /**
7851
8233
  * @private
8234
+ */
8235
+ constructor(subscribeSvc) {
8236
+ super();
8237
+ this.subscribeSvc = subscribeSvc;
8238
+ /**
8239
+ * Emits events each time the user starts, or stops dragging handle.
8240
+ */
8241
+ this.userAction = new EventEmitter(false);
8242
+ /**
8243
+ * @private
8244
+ */
8245
+ this.containerList = [];
8246
+ this.boundsManager = new BorderLayoutBoundsManager();
8247
+ }
8248
+ /**
8249
+ * Add the list `BorderLayoutContainer` objects associated with the main container to this controller.
7852
8250
  *
7853
- * XMLHTTPRequest API
8251
+ * @param containers the list `BorderLayoutContainer` objects associated with the main container.
7854
8252
  */
7855
- get response() {
7856
- return this.XHR ? this.XHR.response : undefined;
8253
+ addContainers(containers) {
8254
+ let regionValidator = EMPTY_STRING;
8255
+ containers.forEach(container => {
8256
+ const constraints = container.constraints;
8257
+ const r = constraints.region;
8258
+ if (regionValidator.indexOf(r) !== -1)
8259
+ throw new SyntaxError(REGION_ERR_MSG + r);
8260
+ regionValidator += r;
8261
+ if (constraints.resizable) {
8262
+ this.subscribeSvc.register(this, container.resizeStart.subscribe(container => this.resizeEnter(container)));
8263
+ }
8264
+ this.boundsManager.initBounds(container);
8265
+ if (r === LayoutRegion.NORTH || r === LayoutRegion.SOUTH)
8266
+ return;
8267
+ this.containerList.push(container);
8268
+ });
7857
8269
  }
8270
+ ;
7858
8271
  /**
7859
- * @private
8272
+ * Sets the reference to the HTML container associated with the main container.
7860
8273
  *
7861
- * XMLHTTPRequest API
8274
+ * @param lytContainer The reference to the HTML container associated with the main container.
7862
8275
  */
7863
- get status() {
7864
- return this.XHR ? this.XHR.status : 0;
8276
+ setLayoutContainer(lytContainer) {
8277
+ this.lytContainerElm = lytContainer;
7865
8278
  }
8279
+ ;
7866
8280
  /**
7867
8281
  * @private
8282
+ * For test purpose only.
8283
+ * Returns the reference to the internal `BorderLayoutBoundsManager` instance.
8284
+ */
8285
+ getBoundsManager() {
8286
+ return this.boundsManager;
8287
+ }
8288
+ /**
8289
+ * Makes this object elligible for garbage collection.
8290
+ */
8291
+ destroy() {
8292
+ this.subscribeSvc.clearAll(this);
8293
+ this.containerList.length = 0;
8294
+ this.containerList = null;
8295
+ this.lytContainerElm = null;
8296
+ this.boundsManager.destroy();
8297
+ this.boundsManager = null;
8298
+ }
8299
+ /**
8300
+ * Forces the layout of all `BorderLayoutContainer` objects associated with the main container.
8301
+ */
8302
+ paint() {
8303
+ this.checkLytContainer();
8304
+ this.render(this.lytContainerElm.offsetWidth);
8305
+ }
8306
+ /**
8307
+ * Resizes the specified region of the associated container.
7868
8308
  *
7869
- * XMLHTTPRequest API
8309
+ * @param region The region to resize.
8310
+ * @param size The new size of the region to resize.
8311
+ *
8312
+ * @returns `true` whether the specified region has been resized; `false` otherwise.
7870
8313
  */
7871
- get statusText() {
7872
- return this.XHR ? this.XHR.statusText : EMPTY_STRING;
8314
+ resizeRegion(region, size) {
8315
+ if (region === LayoutRegion.CENTER)
8316
+ return false;
8317
+ const container = this.containerList.find((c) => {
8318
+ return c.constraints.region === region;
8319
+ });
8320
+ if (!container)
8321
+ return false;
8322
+ container.setSize(size);
8323
+ this.boundsManager.initBounds(container);
8324
+ this.paint();
8325
+ return true;
7873
8326
  }
7874
8327
  /**
7875
8328
  * @private
7876
- *
7877
- * XMLHTTPRequest API
7878
8329
  */
7879
- get readyState() {
7880
- return this.XHR ? this.XHR.readyState : this.UNSENT;
8330
+ resizeEnter(container) {
8331
+ this.checkLytContainer();
8332
+ const lytNativeElm = this.lytContainerElm;
8333
+ const width = lytNativeElm.offsetWidth;
8334
+ const height = lytNativeElm.offsetHeight;
8335
+ const bounds = lytNativeElm.getBoundingClientRect();
8336
+ const constraints = container.constraints;
8337
+ const region = constraints.region;
8338
+ const minSize = constraints.minSize;
8339
+ const maxSize = constraints.maxSize;
8340
+ let size = 0;
8341
+ this.boundsManager.setOrigin(bounds.x, bounds.y);
8342
+ let resizeMethod = this.boundsManager.getResizeMethod(region);
8343
+ container.selected = true;
8344
+ const onMoveHandler = (event) => {
8345
+ event.preventDefault();
8346
+ event.stopPropagation();
8347
+ size = resizeMethod(event, width, height, minSize, maxSize);
8348
+ container.setSize(size);
8349
+ this.render(width);
8350
+ this.fireEvent(container, LayoutDragEventType.DRAGGING);
8351
+ };
8352
+ const onStopHandler = (event) => {
8353
+ event.preventDefault();
8354
+ event.stopPropagation();
8355
+ lytNativeElm.removeEventListener(MOUSEMOVE, onMoveHandler);
8356
+ lytNativeElm.removeEventListener(MOUSEUP, onStopHandler);
8357
+ container.selected = false;
8358
+ size = resizeMethod(event, width, height, minSize, maxSize);
8359
+ container.setSize(size);
8360
+ this.render(width);
8361
+ this.fireEvent(container, LayoutDragEventType.DRAG_STOP);
8362
+ };
8363
+ lytNativeElm.addEventListener(MOUSEMOVE, onMoveHandler);
8364
+ lytNativeElm.addEventListener(MOUSEUP, onStopHandler);
8365
+ this.fireEvent(container, LayoutDragEventType.DRAG_START);
7881
8366
  }
7882
8367
  /**
7883
8368
  * @private
7884
- *
7885
- * XMLHTTPRequest API
7886
8369
  */
7887
- get responseURL() {
7888
- return this.XHR ? this.XHR.responseURL : EMPTY_STRING;
8370
+ fireEvent(target, type) {
8371
+ const evt = new LayoutDragEvent(target, type);
8372
+ this.userAction.emit(evt);
7889
8373
  }
7890
8374
  /**
7891
8375
  * @private
7892
- *
7893
- * XMLHTTPRequest API
7894
8376
  */
7895
- get responseText() {
7896
- return this.XHR ? this.XHR.responseText : EMPTY_STRING;
8377
+ render(width) {
8378
+ const bounds = this.boundsManager.getBounds();
8379
+ const top = bounds.top;
8380
+ const bottom = bounds.bottom;
8381
+ const left = bounds.left;
8382
+ const right = bounds.right;
8383
+ this.containerList.forEach((cont) => {
8384
+ const r = cont.constraints.region;
8385
+ if (r === LayoutRegion.WEST) {
8386
+ cont.setTopPos(top);
8387
+ cont.setRightPos(width - left);
8388
+ cont.setBottomPos(bottom - top);
8389
+ return;
8390
+ }
8391
+ if (r === LayoutRegion.CENTER) {
8392
+ cont.setTopPos(top);
8393
+ cont.setLeftPos(left);
8394
+ cont.setRightPos(right - left);
8395
+ cont.setBottomPos(bottom - top);
8396
+ return;
8397
+ }
8398
+ if (r === LayoutRegion.EAST) {
8399
+ cont.setTopPos(top);
8400
+ cont.setLeftPos(width - (right - left));
8401
+ cont.setBottomPos(bottom - top);
8402
+ }
8403
+ });
8404
+ }
8405
+ checkLytContainer() {
8406
+ if (!this.lytContainerElm)
8407
+ throw new ReferenceError(LAYOUT_ERR_MSG);
7897
8408
  }
8409
+ }
8410
+
8411
+ /**
8412
+ * @license
8413
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
8414
+ *
8415
+ * Use of this source code is governed by an MIT-style license that can be found in
8416
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
8417
+ */
8418
+ /**
8419
+ * A border layout lays out a container, arranging and resizing its components to fit in five regions: north, south, east, west, and center.
8420
+ * Each region is defined by a `BorderLayoutContainer` instance, and is identified by a corresponding constant: `NORTH`, `SOUTH`, `EAST`, `WEST`, and `CENTER`.
8421
+ */
8422
+ class BorderLayout extends IdentifiableComponent {
7898
8423
  /**
7899
8424
  * @private
7900
- *
7901
- * XMLHTTPRequest API
7902
8425
  */
7903
- get responseType() {
7904
- return this.XHR ? this.XHR.responseType : EMPTY_STRING;
8426
+ onResize() {
8427
+ this.paint();
7905
8428
  }
7906
8429
  /**
7907
8430
  * @private
7908
- *
7909
- * XMLHTTPRequest API
7910
8431
  */
7911
- set responseType(value) {
7912
- if (!this.XHR)
7913
- XHR_ERROR("responseType");
7914
- this.XHR.responseType = value;
8432
+ set __containers__(containers) {
8433
+ this.renderer.addContainers(containers);
7915
8434
  }
7916
- get upload() {
7917
- return this.XHR.upload;
8435
+ ;
8436
+ /**
8437
+ * @private
8438
+ */
8439
+ constructor(subscribeSvc) {
8440
+ super();
8441
+ this.subscribeSvc = subscribeSvc;
8442
+ /**
8443
+ * Emits events each time the user starts dragging a region handle.
8444
+ */
8445
+ this.dragStart = new EventEmitter(false);
8446
+ /**
8447
+ * Emits events each time the user stops dragging a region handle.
8448
+ */
8449
+ this.dragStop = new EventEmitter(false);
8450
+ /**
8451
+ * Emits events each time the user is dragging a region handle.
8452
+ */
8453
+ this.dragging = new EventEmitter(false);
8454
+ this.renderer = new BorderLayoutRenderer(subscribeSvc);
8455
+ subscribeSvc.register(this, this.renderer.userAction.subscribe((event) => {
8456
+ event.layout = this;
8457
+ if (event.type === LayoutDragEventType.DRAGGING) {
8458
+ this.dragging.emit(event);
8459
+ return;
8460
+ }
8461
+ if (event.type === LayoutDragEventType.DRAG_START) {
8462
+ this.dragStart.emit(event);
8463
+ return;
8464
+ }
8465
+ this.dragStop.emit(event);
8466
+ }));
7918
8467
  }
7919
- open(method, url, async, username, password) {
7920
- const m = method.toString().toLowerCase();
7921
- const parsedUrl = URL.canParse(url) ? new URL(url) : new URL(this._httpMockService.getAppOrigin() + url);
7922
- const config = this._httpMockService.getRouteConfig(parsedUrl, m);
7923
- if (this.XHR && this.XHR instanceof DelegateXhr)
7924
- this.XHR.destroy();
7925
- this.XHR = config ? new DelegateXhr(config, this._logger) : new XMLHttpRequest();
7926
- this.XHR.withCredentials = this.withCredentials;
7927
- this.XHR.open(m.toString(), parsedUrl.toString());
8468
+ /**
8469
+ * @private
8470
+ * For test purpose only.
8471
+ */
8472
+ getRenderer() {
8473
+ return this.renderer;
8474
+ }
8475
+ /**
8476
+ * @private
8477
+ */
8478
+ ngOnDestroy() {
8479
+ this.subscribeSvc.clearAll(this);
8480
+ this.renderer.destroy();
7928
8481
  }
7929
8482
  /**
7930
8483
  * @private
8484
+ */
8485
+ ngAfterViewInit() {
8486
+ this.renderer.setLayoutContainer(this.layoutContainer.nativeElement);
8487
+ this.paint();
8488
+ }
8489
+ /**
8490
+ * Forces the container to be redrawn.
8491
+ */
8492
+ paint() {
8493
+ this.renderer.paint();
8494
+ }
8495
+ /**
8496
+ * Resizes the specified region.
7931
8497
  *
7932
- * XMLHTTPRequest API
8498
+ * @param region The region to resize.
8499
+ * @param size The new size of the region to resize.
8500
+ *
8501
+ * @returns `true` whether the specified region has been resized; `false` otherwise.
7933
8502
  */
7934
- abort() {
7935
- if (this.XHR)
7936
- return this.XHR.abort();
7937
- XHR_ERROR("abort");
8503
+ resizeRegion(region, size) {
8504
+ this.renderer.resizeRegion(region, size);
8505
+ }
8506
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: BorderLayout, deps: [{ token: SubscriptionService }], target: i0.ɵɵFactoryTarget.Component }); }
8507
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.0.3", type: BorderLayout, isStandalone: true, selector: "atx-border-layout", outputs: { dragStart: "dragStart", dragStop: "dragStop", dragging: "dragging" }, host: { listeners: { "window:resize": "onResize()" } }, queries: [{ propertyName: "__containers__", predicate: BorderLayoutContainer }], viewQueries: [{ propertyName: "layoutContainer", first: true, predicate: ["atxLayoutContainer"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<!--\n * LICENSE\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n-->\n\n<div #atxLayoutContainer class=\"atx-border-layout\">\n <ng-content></ng-content>\n</div>", styles: [".atx-border-layout{position:relative;height:100%;width:100%;-webkit-user-select:none;user-select:none;overflow:hidden}.atx-border-layout,.atx-border-layout *{box-sizing:border-box}.atx-border-layout .content{height:100%;width:100%;overflow:auto}.atx-border-layout .drag{position:absolute;border:2px solid black}:host ::ng-deep .atx-handle{position:absolute}:host ::ng-deep .atx-handle:hover,:host ::ng-deep .atx-handle.atx-handle-selected{background-color:var(--atx-handle-color, #469afa)}:host ::ng-deep .north{position:absolute;z-index:10;top:0;left:0;right:0}:host ::ng-deep .north .atx-handle{left:0;right:0;bottom:0;height:4px;cursor:ns-resize}:host ::ng-deep .west{position:absolute;z-index:5;left:0;height:unset!important}:host ::ng-deep .west .atx-handle{right:0;bottom:0;top:0;width:4px;cursor:ew-resize}:host ::ng-deep .east{position:absolute;z-index:5;right:0;height:unset!important}:host ::ng-deep .east .atx-handle{left:0;bottom:0;top:0;width:4px;cursor:ew-resize}:host ::ng-deep .south{position:absolute;z-index:10;bottom:0;left:0;right:0}:host ::ng-deep .south .atx-handle{left:0;right:0;top:0;height:4px;cursor:ns-resize}:host ::ng-deep .center{position:absolute}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }); }
8508
+ }
8509
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: BorderLayout, decorators: [{
8510
+ type: Component,
8511
+ args: [{ selector: 'atx-border-layout', standalone: true, template: "<!--\n * LICENSE\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n-->\n\n<div #atxLayoutContainer class=\"atx-border-layout\">\n <ng-content></ng-content>\n</div>", styles: [".atx-border-layout{position:relative;height:100%;width:100%;-webkit-user-select:none;user-select:none;overflow:hidden}.atx-border-layout,.atx-border-layout *{box-sizing:border-box}.atx-border-layout .content{height:100%;width:100%;overflow:auto}.atx-border-layout .drag{position:absolute;border:2px solid black}:host ::ng-deep .atx-handle{position:absolute}:host ::ng-deep .atx-handle:hover,:host ::ng-deep .atx-handle.atx-handle-selected{background-color:var(--atx-handle-color, #469afa)}:host ::ng-deep .north{position:absolute;z-index:10;top:0;left:0;right:0}:host ::ng-deep .north .atx-handle{left:0;right:0;bottom:0;height:4px;cursor:ns-resize}:host ::ng-deep .west{position:absolute;z-index:5;left:0;height:unset!important}:host ::ng-deep .west .atx-handle{right:0;bottom:0;top:0;width:4px;cursor:ew-resize}:host ::ng-deep .east{position:absolute;z-index:5;right:0;height:unset!important}:host ::ng-deep .east .atx-handle{left:0;bottom:0;top:0;width:4px;cursor:ew-resize}:host ::ng-deep .south{position:absolute;z-index:10;bottom:0;left:0;right:0}:host ::ng-deep .south .atx-handle{left:0;right:0;top:0;height:4px;cursor:ns-resize}:host ::ng-deep .center{position:absolute}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }]
8512
+ }], ctorParameters: () => [{ type: SubscriptionService }], propDecorators: { dragStart: [{
8513
+ type: Output
8514
+ }], dragStop: [{
8515
+ type: Output
8516
+ }], dragging: [{
8517
+ type: Output
8518
+ }], onResize: [{
8519
+ type: HostListener,
8520
+ args: ["window:resize"]
8521
+ }], layoutContainer: [{
8522
+ type: ViewChild,
8523
+ args: ["atxLayoutContainer"]
8524
+ }], __containers__: [{
8525
+ type: ContentChildren,
8526
+ args: [BorderLayoutContainer]
8527
+ }] } });
8528
+
8529
+ /**
8530
+ * @license
8531
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
8532
+ *
8533
+ * Use of this source code is governed by an MIT-style license that can be
8534
+ * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
8535
+ */
8536
+
8537
+ /**
8538
+ * @license
8539
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
8540
+ *
8541
+ * Use of this source code is governed by an MIT-style license that can be
8542
+ * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
8543
+ */
8544
+ /**
8545
+ * @private
8546
+ * The base class for all directives that are responsible for navigation whithin ab Angular app.
8547
+ */
8548
+ class NavigationDirectiveBase {
8549
+ /**
8550
+ * @private
8551
+ */
8552
+ constructor(elmRef, role) {
8553
+ this.elmRef = elmRef;
8554
+ const elm = elmRef.nativeElement;
8555
+ elm.role = role;
8556
+ elm.tabIndex = 0;
7938
8557
  }
8558
+ }
8559
+
8560
+ /**
8561
+ * @license
8562
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
8563
+ *
8564
+ * Use of this source code is governed by an MIT-style license that can be
8565
+ * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
8566
+ */
8567
+ /**
8568
+ * @private
8569
+ */
8570
+ const ENTER_KEY = 'Enter';
8571
+ /**
8572
+ * @private
8573
+ */
8574
+ const ROUTER_LINK_REF = 'ng-reflect-router-link';
8575
+ /**
8576
+ * An easy-to-use directive that enables keyboard navigation and provides support for keyboard "Enter" key events.
8577
+ */
8578
+ class ButtonRoleDirective extends NavigationDirectiveBase {
7939
8579
  /**
7940
8580
  * @private
7941
- *
7942
- * XMLHTTPRequest API
7943
8581
  */
7944
- getAllResponseHeaders() {
7945
- return this.XHR ? this.XHR.getAllResponseHeaders() : null;
8582
+ onKeyup(event, value) {
8583
+ if (event.key !== ENTER_KEY)
8584
+ return;
8585
+ this.processEvent(event, value);
7946
8586
  }
7947
8587
  /**
7948
8588
  * @private
7949
- *
7950
- * XMLHTTPRequest API
7951
8589
  */
7952
- addEventListener(type, listener, options) {
7953
- if (this.XHR)
7954
- return this.XHR.addEventListener(type, listener, options);
7955
- XHR_ERROR("addEventListener");
8590
+ onClick(event, value) {
8591
+ if (this.delegateClick === undefined)
8592
+ return;
8593
+ this.processEvent(event, value);
7956
8594
  }
7957
8595
  /**
7958
8596
  * @private
7959
- *
7960
- * XMLHTTPRequest API
7961
8597
  */
7962
- removeEventListener(type, listener, options) {
7963
- if (this.XHR)
7964
- return this.XHR.removeEventListener(type, listener, options);
7965
- XHR_ERROR("removeEventListener");
8598
+ constructor(elmRef, _router) {
8599
+ super(elmRef, BUTTON_ROLE);
8600
+ this._router = _router;
8601
+ /**
8602
+ * Dispatches events when the user presses the "Enter" key.
8603
+ */
8604
+ this.enter = new EventEmitter();
8605
+ /**
8606
+ * @private
8607
+ */
8608
+ this._routerLinkRef = null;
7966
8609
  }
7967
8610
  /**
7968
8611
  * @private
7969
- *
7970
- * XMLHTTPRequest API
7971
8612
  */
7972
- send(body) {
7973
- if (this.XHR)
7974
- return this.XHR.send(body);
7975
- XHR_ERROR("send");
8613
+ ngAfterViewInit() {
8614
+ const elm = this.elmRef.nativeElement;
8615
+ this._routerLinkRef = elm.getAttribute(ROUTER_LINK_REF);
7976
8616
  }
7977
8617
  /**
7978
8618
  * @private
7979
- *
7980
- * XMLHTTPRequest API
7981
8619
  */
7982
- setRequestHeader(name, value) {
7983
- if (this.XHR)
7984
- return this.XHR.setRequestHeader(name, value);
7985
- XHR_ERROR("setRequestHeader");
8620
+ processEvent(event, value) {
8621
+ event.preventDefault();
8622
+ event.stopImmediatePropagation();
8623
+ if (this._routerLinkRef) {
8624
+ this._router.navigate([this._routerLinkRef]);
8625
+ return;
8626
+ }
8627
+ this.elmRef.nativeElement.blur();
8628
+ this.enter.emit(value);
7986
8629
  }
8630
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: ButtonRoleDirective, deps: [{ token: i0.ElementRef }, { token: i1.Router }], target: i0.ɵɵFactoryTarget.Directive }); }
8631
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.0.3", type: ButtonRoleDirective, isStandalone: true, selector: "[buttonRole]", inputs: { delegateClick: "delegateClick" }, outputs: { enter: "enter" }, host: { listeners: { "keyup": "onKeyup($event,$event.target.value)", "click": "onClick($event,$event.target.value)" } }, providers: [
8632
+ RouterModule
8633
+ ], usesInheritance: true, ngImport: i0 }); }
8634
+ }
8635
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: ButtonRoleDirective, decorators: [{
8636
+ type: Directive,
8637
+ args: [{
8638
+ selector: '[buttonRole]',
8639
+ providers: [
8640
+ RouterModule
8641
+ ],
8642
+ standalone: true
8643
+ }]
8644
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1.Router }], propDecorators: { enter: [{
8645
+ type: Output
8646
+ }], delegateClick: [{
8647
+ type: Input
8648
+ }], onKeyup: [{
8649
+ type: HostListener,
8650
+ args: ['keyup', ["$event", "$event.target.value"]]
8651
+ }], onClick: [{
8652
+ type: HostListener,
8653
+ args: ['click', ["$event", "$event.target.value"]]
8654
+ }] } });
8655
+
8656
+ /**
8657
+ * @license
8658
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
8659
+ *
8660
+ * Use of this source code is governed by an MIT-style license that can be
8661
+ * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
8662
+ */
8663
+ /**
8664
+ * An easy-to-use directive that enables keyboard navigation and provides support for navigating to an external URL.
8665
+ */
8666
+ class NavigateToUrlDirective extends NavigationDirectiveBase {
7987
8667
  /**
7988
8668
  * @private
7989
- *
7990
- * For Unit Testing only.
7991
8669
  */
7992
- instanceOf(classRef) {
7993
- return this.XHR instanceof classRef;
8670
+ onClick() {
8671
+ const HREF = this.href;
8672
+ if (!HREF)
8673
+ throw new ReferenceError("href attribute is not defined.");
8674
+ this._document.defaultView.location.href = HREF;
7994
8675
  }
7995
8676
  /**
7996
8677
  * @private
7997
8678
  */
7998
- constructor(_httpMockService, _logger) {
7999
- super();
8000
- this._httpMockService = _httpMockService;
8001
- this._logger = _logger;
8679
+ constructor(_document, elmRef) {
8680
+ super(elmRef, LINK_ROLE);
8681
+ this._document = _document;
8002
8682
  }
8683
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: NavigateToUrlDirective, deps: [{ token: DOCUMENT }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
8684
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.0.3", type: NavigateToUrlDirective, isStandalone: true, selector: "[navigateToUrl]", inputs: { href: "href" }, host: { listeners: { "click": "onClick()" } }, usesInheritance: true, ngImport: i0 }); }
8003
8685
  }
8686
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: NavigateToUrlDirective, decorators: [{
8687
+ type: Directive,
8688
+ args: [{
8689
+ selector: '[navigateToUrl]',
8690
+ standalone: true
8691
+ }]
8692
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
8693
+ type: Inject,
8694
+ args: [DOCUMENT]
8695
+ }] }, { type: i0.ElementRef }], propDecorators: { href: [{
8696
+ type: Input
8697
+ }], onClick: [{
8698
+ type: HostListener,
8699
+ args: ['click']
8700
+ }] } });
8004
8701
 
8005
8702
  /**
8006
8703
  * @license
8007
8704
  * Copyright Pascal ECHEMANN. All Rights Reserved.
8008
8705
  *
8009
- * Use of this source code is governed by an MIT-style license that can be found in
8010
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
8706
+ * Use of this source code is governed by an MIT-style license that can be
8707
+ * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
8011
8708
  */
8012
8709
  /**
8013
- * @private
8014
- * The concrete implementation of the `XhrFactory` interface.
8710
+ * Provides functionality to activate anchor navigation through the native Angular router.
8015
8711
  */
8016
- class XhrProxyFactoryImpl extends XhrFactory {
8712
+ class AnchorLinklDirective extends NavigationDirectiveBase {
8017
8713
  /**
8018
8714
  * @private
8019
8715
  */
8020
- constructor(_httpMockService, _logger) {
8021
- super();
8022
- this._httpMockService = _httpMockService;
8023
- this._logger = _logger;
8716
+ onClick(event) {
8717
+ event.preventDefault();
8718
+ const HREF = this.href;
8719
+ this._router.navigate([], { fragment: HREF.slice(1) });
8720
+ this._document.querySelector(HREF).scrollIntoView(DEFAULT_SCROLL_BEHAVIOR);
8024
8721
  }
8025
8722
  /**
8026
8723
  * @private
8027
8724
  */
8028
- build() {
8029
- return new XhrProxyImpl(this._httpMockService, this._logger);
8725
+ constructor(_document, elmRef, _router) {
8726
+ super(elmRef, LINK_ROLE);
8727
+ this._document = _document;
8728
+ this._router = _router;
8729
+ }
8730
+ /**
8731
+ * @private
8732
+ */
8733
+ ngAfterViewInit() {
8734
+ const HREF = this.href;
8735
+ if (!HREF)
8736
+ throw new ReferenceError("href attribute is not defined.");
8030
8737
  }
8738
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AnchorLinklDirective, deps: [{ token: DOCUMENT }, { token: i0.ElementRef }, { token: i1.Router }], target: i0.ɵɵFactoryTarget.Directive }); }
8739
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.0.3", type: AnchorLinklDirective, isStandalone: true, selector: "[anchorLink]", inputs: { href: "href" }, host: { listeners: { "click": "onClick($event)" } }, usesInheritance: true, ngImport: i0 }); }
8031
8740
  }
8741
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AnchorLinklDirective, decorators: [{
8742
+ type: Directive,
8743
+ args: [{
8744
+ selector: '[anchorLink]',
8745
+ standalone: true,
8746
+ }]
8747
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
8748
+ type: Inject,
8749
+ args: [DOCUMENT]
8750
+ }] }, { type: i0.ElementRef }, { type: i1.Router }], propDecorators: { href: [{
8751
+ type: Input
8752
+ }], onClick: [{
8753
+ type: HostListener,
8754
+ args: ['click', ['$event']]
8755
+ }] } });
8032
8756
 
8033
8757
  /**
8034
8758
  * @license
8035
8759
  * Copyright Pascal ECHEMANN. All Rights Reserved.
8036
8760
  *
8037
- * Use of this source code is governed by an MIT-style license that can be found in
8038
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
8761
+ * Use of this source code is governed by an MIT-style license that can be
8762
+ * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
8039
8763
  */
8040
8764
  /**
8041
- * A factory function that creates and returns a new `XhrFactory` object.
8042
- *
8043
- * @returns A new `XhrFactory` object.
8765
+ * @private
8044
8766
  */
8045
- const httpMockFactory = () => {
8046
- return new XhrProxyFactoryImpl(inject(HttpMockService), inject(HttpMockLoggingService));
8047
- };
8767
+ const CHILD_LIST_TYPE = "childList";
8768
+ /**
8769
+ * Allows injection of any value into an HTML element container (`div`, `button`, etc...).
8770
+ * A rendered event is emitted after the injected content has been rendered and is
8771
+ * available for DOM manipulation.
8772
+ */
8773
+ class ContentRendererDirective {
8774
+ /**
8775
+ * @private
8776
+ */
8777
+ constructor(_elmRef) {
8778
+ this._elmRef = _elmRef;
8779
+ /**
8780
+ * Dispatches events when the content of the HTML element has been rendered.
8781
+ */
8782
+ this.rendered = new EventEmitter();
8783
+ const nativeElement = this._elmRef.nativeElement;
8784
+ this._observer = new MutationObserver((mutations) => {
8785
+ mutations.forEach((mutation) => {
8786
+ if (mutation.type === CHILD_LIST_TYPE)
8787
+ this.rendered.emit(nativeElement);
8788
+ });
8789
+ });
8790
+ }
8791
+ /**
8792
+ * @private
8793
+ */
8794
+ ngOnDestroy() {
8795
+ this._observer.disconnect();
8796
+ }
8797
+ /**
8798
+ * @private
8799
+ */
8800
+ ngOnInit() {
8801
+ this._observer.observe(this._elmRef.nativeElement, { attributes: false, childList: true, characterData: false });
8802
+ }
8803
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: ContentRendererDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
8804
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.0.3", type: ContentRendererDirective, isStandalone: true, selector: "[contentRenderer]", outputs: { rendered: "rendered" }, ngImport: i0 }); }
8805
+ }
8806
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: ContentRendererDirective, decorators: [{
8807
+ type: Directive,
8808
+ args: [{
8809
+ selector: '[contentRenderer]',
8810
+ standalone: true
8811
+ }]
8812
+ }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { rendered: [{
8813
+ type: Output
8814
+ }] } });
8048
8815
 
8049
8816
  /**
8050
8817
  * @license
@@ -8061,5 +8828,5 @@ const httpMockFactory = () => {
8061
8828
  * Generated bundle index. Do not edit.
8062
8829
  */
8063
8830
 
8064
- export { APP_PRIDGE_REF, ATX_LOGGER_CONFIG, AbstractLogger, AbstractSubscriptionManager, AbstractVersionManager, AbstractWindowService, AnchorLinklDirective, AngularToolboxLogoComponent, AngularToolboxModule, AngularToolboxVersionService, AppBridgeError, AppBridgeService, ArrayList, ArrayListEvent, ArrayListEventType, AtxHttpMockConsoleService, AtxMonitoringConsoleComponent, BIGINT, BOOLEAN, BUTTON_ROLE, ButtonRoleDirective, CSS_PROP, ConsoleLogConnector, ContentRendererDirective, DARK_MODE_CONFIG, DEFAULT_LOG_CONNECTOR, DarkModeService, DefaultLogConnector, EMPTY_STRING, FEATURES, FUNCTION, FetchClient, FetchClientBuilder, FetchClientResponseType, HTTP_MOCKING_FRAMEWORK_CONFIG, HTTP_MOCK_MAX_DELAY, HTTP_MOCK_SERVICE, HtmlLogConnector, HttpHeadersMockBuilder, HttpMock, HttpMockLoggingService, HttpMockProductionPolicy, HttpMockService, HttpMockServiceError, HttpResponseMockBuilder, IdentifiableComponent, IntegrityError, LINK_ROLE, LOG_CONFIG_STRING, LOG_ERROR_STRING, LOG_INFO_STRING, LOG_WARNING_STRING, LogBuilder, LogImpl, LogLevel, LogUtil, LoggerService, NUMBER, NavigateToUrlDirective, OBJECT, STORAGE_KEY, STRING, SYMBOL, SafeHtmlPipe, ScrollService, SubscriptionError, SubscriptionService, UNDEFINED, Uuid, VERSION_CONFIG, VersionService, VersionUtil, WindowFeatureState, WindowService, WindowTarget, httpHeadersMock, httpMockFactory, httpResponseMock };
8831
+ export { APP_PRIDGE_REF, ATX_LOGGER_CONFIG, AbstractLogger, AbstractSubscriptionManager, AbstractVersionManager, AbstractWindowService, AnchorLinklDirective, AngularToolboxLogoComponent, AngularToolboxModule, AngularToolboxVersionService, AppBridgeError, AppBridgeService, ArrayList, ArrayListEvent, ArrayListEventType, AtxHttpMockConsoleService, AtxMonitoringConsoleComponent, BIGINT, BOOLEAN, BUTTON_ROLE, BorderLayout, BorderLayoutContainer, ButtonRoleDirective, CSS_PROP, ConsoleLogConnector, ContentRendererDirective, DARK_MODE_CONFIG, DEFAULT_LOG_CONNECTOR, DarkModeService, DefaultLogConnector, EMPTY_STRING, FEATURES, FUNCTION, FetchClient, FetchClientBuilder, FetchClientResponseType, HTTP_MOCKING_FRAMEWORK_CONFIG, HTTP_MOCK_MAX_DELAY, HTTP_MOCK_SERVICE, HtmlLogConnector, HttpHeadersMockBuilder, HttpMock, HttpMockLoggingService, HttpMockProductionPolicy, HttpMockService, HttpMockServiceError, HttpResponseMockBuilder, IdentifiableComponent, IntegrityError, LINK_ROLE, LOG_CONFIG_STRING, LOG_ERROR_STRING, LOG_INFO_STRING, LOG_WARNING_STRING, LayoutDragEvent, LayoutDragEventType, LayoutRegion, LogBuilder, LogImpl, LogLevel, LogUtil, LoggerService, NUMBER, NavigateToUrlDirective, OBJECT, STORAGE_KEY, STRING, SYMBOL, SafeHtmlPipe, ScrollService, SubscriptionError, SubscriptionService, UNDEFINED, Uuid, VERSION_CONFIG, VersionService, VersionUtil, WindowFeatureState, WindowService, WindowTarget, httpHeadersMock, httpMockFactory, httpResponseMock };
8065
8832
  //# sourceMappingURL=angular-toolbox.mjs.map