btv-base-controls 0.1.21 → 0.1.23

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 (136) hide show
  1. package/.browserslistrc +16 -0
  2. package/README.md +24 -24
  3. package/karma.conf.js +44 -0
  4. package/ng-package.json +7 -0
  5. package/package.json +10 -24
  6. package/src/assets/icon/state-icons.png +0 -0
  7. package/src/assets/theme/wmGlobals.scss +181 -0
  8. package/src/lib/basic.module.ts +48 -0
  9. package/src/lib/blink-message/blink-message.component.html +1 -0
  10. package/src/lib/blink-message/blink-message.component.scss +4 -0
  11. package/src/lib/blink-message/blink-message.component.ts +54 -0
  12. package/src/lib/btv-icon-button/btv-counter-button.html +18 -0
  13. package/src/lib/btv-icon-button/btv-counter-button.ts +34 -0
  14. package/src/lib/btv-icon-button/btv-icon-button.component.ts +62 -0
  15. package/src/lib/btv-icon-button/btv-icon-button.html +14 -0
  16. package/src/lib/btv-icon-button/btv-icon-button.scss +125 -0
  17. package/src/lib/btv-icon-button/index.ts +1 -0
  18. package/src/lib/btv-progress/btv-progress.component.ts +65 -0
  19. package/src/lib/btv-progress/btv-progress.html +11 -0
  20. package/src/lib/btv-progress/btv-progress.scss +24 -0
  21. package/src/lib/btv-search/btv-search.component.ts +78 -0
  22. package/src/lib/btv-search/btv-search.html +15 -0
  23. package/src/lib/btv-search/btv-search.scss +97 -0
  24. package/src/lib/btv-search/index.ts +1 -0
  25. package/src/lib/busy-indicator/busy-indicator.component.ts +13 -0
  26. package/src/lib/busy-indicator/busy-indicator.html +6 -0
  27. package/src/lib/busy-indicator/busy-indicator.scss +86 -0
  28. package/src/lib/custom-tool-tip/custom-tool-tip.component.html +9 -0
  29. package/src/lib/custom-tool-tip/custom-tool-tip.component.scss +47 -0
  30. package/src/lib/custom-tool-tip/custom-tool-tip.component.ts +44 -0
  31. package/src/lib/custom-tool-tip/tool-tip-renderer.directive.ts +111 -0
  32. package/src/lib/illustration/illustration.component.html +412 -0
  33. package/src/lib/illustration/illustration.component.scss +48 -0
  34. package/src/lib/illustration/illustration.component.ts +21 -0
  35. package/src/lib/wm-avatar/avatar.component.ts +179 -0
  36. package/src/lib/wm-avatar/avatar.html +13 -0
  37. package/src/lib/wm-avatar/avatar.scss +3 -0
  38. package/src/lib/wm-back-btn/wm-back-btn.component.ts +19 -0
  39. package/src/lib/wm-back-btn/wm-back-btn.html +7 -0
  40. package/src/lib/wm-back-btn/wm-back-btn.scss +51 -0
  41. package/src/lib/wm-beta-text/wm-beta-text.component.html +1 -0
  42. package/src/lib/wm-beta-text/wm-beta-text.component.scss +44 -0
  43. package/src/lib/wm-beta-text/wm-beta-text.component.ts +14 -0
  44. package/src/lib/wm-info/info-models.ts +22 -0
  45. package/src/lib/wm-info/wm-info.component.ts +238 -0
  46. package/src/lib/wm-info/wm-info.html +19 -0
  47. package/src/lib/wm-info/wm-info.scss +64 -0
  48. package/src/lib/wm-info-card/wm-info-card.component.ts +14 -0
  49. package/src/lib/wm-info-card/wm-info-card.html +13 -0
  50. package/src/lib/wm-info-card/wm-info-card.scss +56 -0
  51. package/src/lib/wm-no-content/wm-no-content.component.ts +17 -0
  52. package/src/lib/wm-no-content/wm-no-content.html +13 -0
  53. package/src/lib/wm-no-content/wm-no-content.scss +60 -0
  54. package/src/lib/wm-panel-bar/wm-panel-bar.component.ts +59 -0
  55. package/src/lib/wm-panel-bar/wm-panel-bar.html +37 -0
  56. package/src/lib/wm-panel-bar/wm-panel-bar.scss +114 -0
  57. package/src/lib/wm-scalable-div/scalable-div.component.ts +106 -0
  58. package/src/lib/wm-scalable-div/scalable-div.html +1 -0
  59. package/src/lib/wm-scalable-div/scalable-div.scss +11 -0
  60. package/src/lib/wm-spinner/wm-spinner.component.ts +129 -0
  61. package/src/lib/wm-spinner/wm-spinner.html +37 -0
  62. package/src/lib/wm-spinner/wm-spinner.scss +72 -0
  63. package/src/lib/wm-state-icon/wm-state-icon.component.html +4 -0
  64. package/src/lib/wm-state-icon/wm-state-icon.component.scss +26 -0
  65. package/src/lib/wm-state-icon/wm-state-icon.component.ts +18 -0
  66. package/src/lib/wm-tag/wm-tag.component.html +8 -0
  67. package/src/lib/wm-tag/wm-tag.component.scss +48 -0
  68. package/src/lib/wm-tag/wm-tag.component.ts +17 -0
  69. package/src/lib/wm-tamplate-image/wm-template-image.component.ts +56 -0
  70. package/src/lib/wm-tamplate-image/wm-template-image.html +3 -0
  71. package/src/lib/wm-tamplate-image/wm-template-image.scss +31 -0
  72. package/src/lib/wm-toggle/wm-toggle.component.ts +20 -0
  73. package/src/lib/wm-toggle/wm-toggle.html +5 -0
  74. package/src/lib/wm-toggle/wm-toggle.scss +33 -0
  75. package/src/models/guidExtension.ts +16 -0
  76. package/src/public-api.ts +29 -0
  77. package/src/test.ts +15 -0
  78. package/tsconfig.lib.json +15 -0
  79. package/tsconfig.lib.prod.json +10 -0
  80. package/tsconfig.spec.json +17 -0
  81. package/esm2022/btv-base-controls.mjs +0 -5
  82. package/esm2022/lib/basic.module.mjs +0 -64
  83. package/esm2022/lib/blink-message/blink-message.component.mjs +0 -54
  84. package/esm2022/lib/btv-icon-button/btv-counter-button.mjs +0 -47
  85. package/esm2022/lib/btv-icon-button/btv-icon-button.component.mjs +0 -89
  86. package/esm2022/lib/btv-progress/btv-progress.component.mjs +0 -71
  87. package/esm2022/lib/btv-search/btv-search.component.mjs +0 -82
  88. package/esm2022/lib/busy-indicator/busy-indicator.component.mjs +0 -16
  89. package/esm2022/lib/custom-tool-tip/custom-tool-tip.component.mjs +0 -34
  90. package/esm2022/lib/custom-tool-tip/tool-tip-renderer.directive.mjs +0 -113
  91. package/esm2022/lib/illustration/illustration.component.mjs +0 -17
  92. package/esm2022/lib/wm-avatar/avatar.component.mjs +0 -175
  93. package/esm2022/lib/wm-back-btn/wm-back-btn.component.mjs +0 -26
  94. package/esm2022/lib/wm-beta-text/wm-beta-text.component.mjs +0 -19
  95. package/esm2022/lib/wm-info/info-models.mjs +0 -13
  96. package/esm2022/lib/wm-info/wm-info.component.mjs +0 -237
  97. package/esm2022/lib/wm-info-card/wm-info-card.component.mjs +0 -23
  98. package/esm2022/lib/wm-no-content/wm-no-content.component.mjs +0 -30
  99. package/esm2022/lib/wm-panel-bar/wm-panel-bar.component.mjs +0 -78
  100. package/esm2022/lib/wm-scalable-div/scalable-div.component.mjs +0 -105
  101. package/esm2022/lib/wm-spinner/wm-spinner.component.mjs +0 -135
  102. package/esm2022/lib/wm-state-icon/wm-state-icon.component.mjs +0 -18
  103. package/esm2022/lib/wm-tag/wm-tag.component.mjs +0 -28
  104. package/esm2022/lib/wm-tamplate-image/wm-template-image.component.mjs +0 -71
  105. package/esm2022/lib/wm-toggle/wm-toggle.component.mjs +0 -31
  106. package/esm2022/models/guidExtension.mjs +0 -15
  107. package/esm2022/public-api.mjs +0 -28
  108. package/fesm2022/btv-base-controls.mjs +0 -1496
  109. package/fesm2022/btv-base-controls.mjs.map +0 -1
  110. package/index.d.ts +0 -5
  111. package/lib/basic.module.d.ts +0 -33
  112. package/lib/blink-message/blink-message.component.d.ts +0 -20
  113. package/lib/btv-icon-button/btv-counter-button.d.ts +0 -12
  114. package/lib/btv-icon-button/btv-icon-button.component.d.ts +0 -30
  115. package/lib/btv-progress/btv-progress.component.d.ts +0 -20
  116. package/lib/btv-search/btv-search.component.d.ts +0 -31
  117. package/lib/busy-indicator/busy-indicator.component.d.ts +0 -7
  118. package/lib/custom-tool-tip/custom-tool-tip.component.d.ts +0 -35
  119. package/lib/custom-tool-tip/tool-tip-renderer.directive.d.ts +0 -49
  120. package/lib/illustration/illustration.component.d.ts +0 -10
  121. package/lib/wm-avatar/avatar.component.d.ts +0 -63
  122. package/lib/wm-back-btn/wm-back-btn.component.d.ts +0 -10
  123. package/lib/wm-beta-text/wm-beta-text.component.d.ts +0 -7
  124. package/lib/wm-info/info-models.d.ts +0 -20
  125. package/lib/wm-info/wm-info.component.d.ts +0 -34
  126. package/lib/wm-info-card/wm-info-card.component.d.ts +0 -9
  127. package/lib/wm-no-content/wm-no-content.component.d.ts +0 -11
  128. package/lib/wm-panel-bar/wm-panel-bar.component.d.ts +0 -25
  129. package/lib/wm-scalable-div/scalable-div.component.d.ts +0 -24
  130. package/lib/wm-spinner/wm-spinner.component.d.ts +0 -37
  131. package/lib/wm-state-icon/wm-state-icon.component.d.ts +0 -9
  132. package/lib/wm-tag/wm-tag.component.d.ts +0 -10
  133. package/lib/wm-tamplate-image/wm-template-image.component.d.ts +0 -49
  134. package/lib/wm-toggle/wm-toggle.component.d.ts +0 -11
  135. package/models/guidExtension.d.ts +0 -5
  136. package/public-api.d.ts +0 -24
@@ -0,0 +1,13 @@
1
+ <div class="wm-info-card flex-row">
2
+ <div class="info-icon" *ngIf="!useCustomIcon">
3
+ <div class="icon-bg"></div>
4
+ <img class="info-svg" src="{{'./assets/icon/svg/' + icon + '.svg'}}" alt="type" />
5
+ </div>
6
+ <div class="info-icon" *ngIf="useCustomIcon">
7
+ <ng-content select="[wmCustomIcon]"></ng-content>
8
+ </div>
9
+ <div class="flex-col info-content">
10
+ <div class="info-card-value text-hidden" title="{{value}}">{{value}}</div>
11
+ <div class="info-card-label text-hidden" title="{{label}}">{{label}}</div>
12
+ </div>
13
+ </div>
@@ -0,0 +1,56 @@
1
+ @import './../../assets/theme/wmGlobals.scss';
2
+ .wm-info-card {
3
+ background: var(--pageBackgroundColor);
4
+ width: 100%;
5
+ height: 100px;
6
+ margin-right: 18px;
7
+ padding: 25px;
8
+ border-radius: 4px;
9
+ box-sizing: border-box;
10
+ }
11
+ .info-icon {
12
+ display: inline-flex;
13
+ width: 48px;
14
+ height: 48px;
15
+ border: 1px solid transparent;
16
+ border-radius: 50%;
17
+ margin: auto 18px auto 0;
18
+ flex-shrink: 0;
19
+ position: relative;
20
+ overflow: hidden;
21
+ }
22
+
23
+ .icon-bg {
24
+ width: 100%;
25
+ height: 100%;
26
+ position: absolute;
27
+ background-color: var(--strongFontColor);
28
+ opacity: 0.05;
29
+ }
30
+ .info-svg {
31
+ margin: auto;
32
+ width: 24px;
33
+ height: 24px;
34
+ z-index: 1;
35
+ }
36
+
37
+ .info-content {
38
+ justify-content: center;
39
+ flex-grow: 1;
40
+ flex-shrink: 1;
41
+ overflow: hidden;
42
+ }
43
+
44
+ .info-card-value {
45
+ color: var(--strongFontColor);
46
+ line-height: 20px;
47
+ font-size: 22px;
48
+ width: 100%;
49
+ height: 20px;
50
+ margin-bottom: 2px;
51
+ }
52
+
53
+ .info-card-label {
54
+ color: var(--disabledTextColor);
55
+ font-size: 14px;
56
+ }
@@ -0,0 +1,17 @@
1
+ import { Component, Input, ChangeDetectionStrategy } from '@angular/core';
2
+ import { IIllustrationId } from '../illustration/illustration.component';
3
+
4
+ @Component({
5
+ selector: 'wm-no-content',
6
+ styleUrls: ['./wm-no-content.scss'],
7
+ templateUrl: './wm-no-content.html',
8
+ changeDetection: ChangeDetectionStrategy.OnPush
9
+ })
10
+
11
+ export class WmNoContentComponent {
12
+ @Input() icon: IIllustrationId = '';
13
+ @Input() label: string = '';
14
+ @Input() description: string = '';
15
+ @Input() useFooter: boolean = true;
16
+ @Input() additionContent: boolean = false;
17
+ }
@@ -0,0 +1,13 @@
1
+ <div>
2
+ <wm-illustration [illustrationId]="icon" class="illustration">
3
+ </wm-illustration>
4
+ <div class="no-content-body" *ngIf="(label || description)">
5
+ <div class="no-content-label" *ngIf="label" [innerHTML]="label"></div>
6
+ <div class="no-content-desc" *ngIf="description"> {{description}}</div>
7
+ <div class="no-content-desc" *ngIf="additionContent">
8
+ <ng-content select="[additionContent]"></ng-content>
9
+ </div>
10
+ </div>
11
+ <div class="no-foot" *ngIf="useFooter">
12
+ <ng-content></ng-content>
13
+ </div>
@@ -0,0 +1,60 @@
1
+ @import './../../assets/theme/wmGlobals.scss';
2
+
3
+ :host {
4
+ display: flex;
5
+ flex-direction: column;
6
+ width: 100%;
7
+ height: 100%;
8
+
9
+ margin: auto;
10
+ text-align: center;
11
+ box-sizing: border-box;
12
+ padding: 0px 10px;
13
+ justify-content: center;
14
+ }
15
+
16
+ .illustration {
17
+ min-width: 260px;
18
+ max-width: 520px;
19
+ margin: auto;
20
+ }
21
+
22
+ .no-content-wrap * {
23
+ box-sizing: inherit;
24
+ }
25
+
26
+ .img-wrap {
27
+ width: 120px;
28
+ height: 120px;
29
+ margin: 0px auto;
30
+ background-repeat: no-repeat;
31
+ cursor: default;
32
+ }
33
+
34
+ .no-content-body {
35
+ width: 100%;
36
+ padding: 12px 0px;
37
+ overflow-y: hidden;
38
+ cursor: default;
39
+ }
40
+
41
+ .no-content-label {
42
+ color: var(--disabledFontColor);
43
+ font-size: $fontSize + 4;
44
+ padding-top: 12px;
45
+ }
46
+
47
+ .no-content-desc {
48
+ color: var(--mediumFontColor);
49
+ font-size: $fontSize + 2;
50
+ word-break: break-word;
51
+ padding-top: 12px;
52
+ }
53
+
54
+ .no-foot {
55
+ width: 100%;
56
+ height: 64px;
57
+ display: flex;
58
+ justify-content: center;
59
+ padding: 12px 0px;
60
+ }
@@ -0,0 +1,59 @@
1
+ import { Component, EventEmitter, Input, Output } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'wm-panel-bar',
5
+ styleUrls: ['wm-panel-bar.scss'],
6
+ templateUrl: './wm-panel-bar.html'
7
+ })
8
+ export class WmPanelBarComponent {
9
+ @Input() label: string;
10
+ @Input() labelClasses: 'pb-label' | 'brand-label' = 'pb-label';
11
+ @Input() openedLabel: string;
12
+
13
+ @Input() width: string;
14
+ @Input() height: string;
15
+ @Input() maxHeight: string = 'unset';
16
+ @Input() maxWidth: string = 'unset';
17
+
18
+
19
+ private _open: boolean= false;
20
+
21
+ @Input() set open(value: boolean) {
22
+ if (value === this._open) return;
23
+ this._open = value;
24
+ }
25
+
26
+ get open(): boolean {
27
+ return this._open;
28
+ }
29
+ @Input() collapseText: string = 'Collapse';
30
+ @Input() expandText: string = 'Expand';
31
+ @Output() openChange: EventEmitter<boolean> = new EventEmitter<boolean>();
32
+ directionBottom: boolean = true;
33
+ directionLeft: boolean = false;
34
+
35
+ private _direction: 'bottom' | 'left' = 'bottom';
36
+ get direction() { return this._direction; }
37
+ @Input() set direction(val) {
38
+ if (val !== 'bottom' && val !== 'left') {
39
+ val = 'bottom';
40
+ }
41
+ this._direction = val;
42
+ switch (val) {
43
+ case 'left':
44
+ this.directionLeft = true;
45
+ this.directionBottom = false;
46
+ break;
47
+ default:
48
+ this.directionBottom = true;
49
+ this.directionLeft = false;
50
+ break;
51
+ }
52
+ }
53
+
54
+
55
+ onClick() {
56
+ this.open = !this.open;
57
+ this.openChange.emit(this.open);
58
+ }
59
+ }
@@ -0,0 +1,37 @@
1
+ <div *ngIf="directionBottom" class="wm-panel-bar drb flex-col"
2
+ [ngStyle]="{'max-width': maxWidth, 'max-height': maxHeight}">
3
+ <div class="pb-header align-center flex-row">
4
+ <div class={{labelClasses}} *ngIf="label">{{label}}</div>
5
+ <ng-content select="[headerLabel]"></ng-content>
6
+ <div class="pb-header-content flex-row">
7
+ <ng-content select="[headerContent]"></ng-content>
8
+ <div class="ex-button" (click)="onClick()">
9
+ <span>{{ (open ? collapseText : expandText)}}</span>
10
+ <wm-template-image class="bar-arrow" [ngClass]="{'bar-open-bottom': open}" icon="arrow-down">
11
+ </wm-template-image>
12
+ </div>
13
+ </div>
14
+ </div>
15
+ <div class="flex-row pb-content pb-vertical" [ngStyle]="{'height': !open ? '0px': ''}"
16
+ [ngClass]="{'pb-vertical-visible': open}">
17
+ <ng-container *ngTemplateOutlet="body"></ng-container>
18
+ </div>
19
+ </div>
20
+
21
+ <div *ngIf="!directionBottom" class="wm-panel-bar flex-col drl" [ngClass]="{'pb-drl-open': open}"
22
+ [ngStyle]="{'max-width': maxWidth, 'max-height': maxHeight}">
23
+ <div class="ex-panel flex-row ex-panel-drl" (click)="onClick()">
24
+ <wm-template-image class="bar-arrow arrow-left" [ngClass]="{'bar-open-left': open}" icon="arrow-left">
25
+ </wm-template-image>
26
+ <div class="preview-label" *ngIf="!open">{{label}}</div>
27
+ <div class="preview-label" *ngIf="open">{{openedLabel || label}}</div>
28
+
29
+ </div>
30
+ <div class="flex-col pb-content pb-horizontal-visible" *ngIf="open">
31
+ <ng-container *ngTemplateOutlet="body"></ng-container>
32
+ </div>
33
+ </div>
34
+
35
+ <ng-template #body>
36
+ <ng-content></ng-content>
37
+ </ng-template>
@@ -0,0 +1,114 @@
1
+ @import './../../assets/theme/wmGlobals.scss';
2
+
3
+ .wm-panel-bar {
4
+ border-radius: 4px;
5
+ background: var(--pageBackgroundColor);
6
+ flex-shrink: 0;
7
+ overflow: hidden;
8
+ direction: ltr;
9
+ }
10
+
11
+
12
+
13
+ .ex-button {
14
+ display: inline-flex;
15
+ color: var(--mediumFontColor);
16
+ letter-spacing: 0;
17
+ cursor: pointer;
18
+ background: transparent;
19
+ border: none;
20
+ @include flexJA(flex-end, center);
21
+ width: 86px;
22
+ margin-left: 8px;
23
+ }
24
+
25
+ .pb-header {
26
+ width: 100%;
27
+ flex-shrink: 0;
28
+ min-height: 48px;
29
+ font-size: $fontSize;
30
+ box-sizing: border-box;
31
+ padding: 4px 16px;
32
+ }
33
+
34
+ .pb-label {
35
+ font-weight: bold;
36
+ color: var(--strongFontColor);
37
+ letter-spacing: 1.2px;
38
+ line-height: 16px;
39
+ margin-right: 12px;
40
+ flex-shrink: 1;
41
+ white-space: nowrap;
42
+ overflow: hidden;
43
+ text-overflow: ellipsis;
44
+ }
45
+
46
+ .brand-label {
47
+ @extend .pb-label;
48
+ color: var(--brandColor);
49
+ }
50
+
51
+ .pb-header-content {
52
+ align-items: center;
53
+ margin-left: auto;
54
+ }
55
+
56
+ .bar-open-left,
57
+ .bar-open-right {
58
+ transform: rotate3d(0, 1, 0, -180deg);
59
+ }
60
+
61
+ .drb {
62
+ box-shadow: 0 0 1px 0 rgba(10, 22, 70, 0.06), 0 1px 1px 0 rgba(10, 22, 70, 0.10);
63
+ }
64
+
65
+ .drr {
66
+ flex-direction: row-reverse;
67
+ }
68
+
69
+ .pb-drl-open {
70
+ width: 100%;
71
+ }
72
+
73
+ .pb-vertical {
74
+ height: 0;
75
+ }
76
+
77
+ .pb-content {
78
+ direction: ltr;
79
+ visibility: hidden;
80
+ overflow: auto;
81
+ }
82
+
83
+ .pb-vertical-visible {
84
+ visibility: visible;
85
+ height: 100%;
86
+ max-height: calc(100% - 48px);
87
+ }
88
+
89
+ .pb-horizontal-visible {
90
+ visibility: visible;
91
+ width: 100%;
92
+ }
93
+
94
+ .ex-panel {
95
+ height: 40px;
96
+ width: auto;;
97
+ min-width: 1px;
98
+ max-width: 100%;
99
+ flex-shrink: 0;
100
+ cursor: pointer;
101
+ background: transparent;
102
+ border-radius: 4px;
103
+ box-shadow: 1px 1px 2px 2px rgba(10, 22, 70, 0.06);
104
+ justify-content: flex-start;
105
+ }
106
+
107
+ .arrow-left {
108
+ margin: auto 0px;
109
+ }
110
+
111
+ .preview-label {
112
+ align-items: center;
113
+ margin: auto 4px;
114
+ }
@@ -0,0 +1,106 @@
1
+ import { AfterViewInit, Component, ElementRef, EventEmitter, Input, ViewChild, OnDestroy, NgZone, ChangeDetectorRef } from '@angular/core';
2
+ import { interval, Subscription } from 'rxjs';
3
+
4
+ @Component({
5
+ selector: 'wm-scalable-div',
6
+ styleUrls: ['./scalable-div.scss'],
7
+ templateUrl: './scalable-div.html'
8
+ })
9
+ export class ScalableDivComponent implements AfterViewInit, OnDestroy {
10
+
11
+ @Input() divClass: string;
12
+ @ViewChild('divEl', { static: true }) divEl: ElementRef;
13
+ isCalculated: boolean = false;
14
+ firstObservable: Subscription;
15
+
16
+ private _text: string | number;
17
+ public get text(): string | number { return this._text; }
18
+ @Input() public set text(value: string | number) {
19
+ this._text = value;
20
+ this.recalculateWidth();
21
+ }
22
+
23
+ constructor(private _zone: NgZone, private _change: ChangeDetectorRef) {
24
+
25
+ }
26
+
27
+ public ngAfterViewInit() {
28
+ this._zone.runOutsideAngular(() => {
29
+ this.firstObservable = interval(500).subscribe(it => {
30
+ if (this.isCalculated) {
31
+ this.firstObservable.unsubscribe();
32
+ return;
33
+ }
34
+ this.recalculateWidth();
35
+ this._change.detectChanges();
36
+ });
37
+ });
38
+ }
39
+
40
+ ngOnDestroy(): void {
41
+ if (!this.firstObservable) return;
42
+ this.firstObservable.unsubscribe();
43
+ this.firstObservable = undefined;
44
+ }
45
+
46
+ private getNumberFromFontSize(fontSize: string): number {
47
+ const numberSize = Number(fontSize.substr(0, fontSize.length - 2));
48
+ return numberSize;
49
+ }
50
+
51
+ private getFontSizeDim(fontSize: string): string {
52
+ let num: number;
53
+ let dimLength: number = 0;
54
+ while (!num) {
55
+ dimLength = dimLength + 1;
56
+ num = Number(fontSize.substr(0, fontSize.length - dimLength));
57
+ }
58
+ return fontSize.substr(fontSize.length - dimLength, dimLength);
59
+ }
60
+
61
+ private divWidth(text: string, font: string, padding: string) {
62
+ const f = font || '12px arial';
63
+ const o = document.createElement('div');
64
+ o.innerHTML = text;
65
+ o.style.position = 'absolute';
66
+ o.style.visibility = 'hidden';
67
+ o.style['text-align'] = 'center';
68
+ o.style.font = f;
69
+ o.style.padding = padding;
70
+ document.body.appendChild(o);
71
+ const w = o.clientWidth;
72
+ document.body.removeChild(o);
73
+ return w;
74
+ }
75
+
76
+ public recalculateWidth() {
77
+ if (!this.divEl) return;
78
+ const divTag = this.divEl.nativeElement;
79
+ if ((<any>divTag).clientWidth === 0) return;
80
+ this.isCalculated = true;
81
+ this.doRecalculateWidth(divTag);
82
+ }
83
+
84
+ private doRecalculateWidth(divTag: HTMLElement) {
85
+ divTag.style.fontSize = '';
86
+ const style = window.getComputedStyle(divTag);
87
+ const availableWidth = divTag.offsetParent.clientWidth;
88
+ const sizeDim = this.getFontSizeDim(style.fontSize);
89
+ const text = divTag.textContent;
90
+ let font = style.font;
91
+ let textWidth = this.divWidth(text, font, style.padding);
92
+ const needChange: boolean = availableWidth < textWidth;
93
+ let numberSize = this.getNumberFromFontSize(style.fontSize);
94
+ let stringSize = numberSize.toString() + sizeDim;
95
+ while (textWidth - availableWidth > 1) {
96
+ numberSize = numberSize - 1;
97
+ const oldString = stringSize;
98
+ stringSize = numberSize.toString() + sizeDim;
99
+ font = font.replace(oldString, stringSize);
100
+ textWidth = this.divWidth(text, font, style.padding);
101
+ }
102
+ if (needChange) divTag.style.fontSize = stringSize;
103
+ }
104
+
105
+
106
+ }
@@ -0,0 +1 @@
1
+ <div #divEl [ngClass]="divClass">{{text}}<div>
@@ -0,0 +1,11 @@
1
+ @import './../../assets/theme/wmGlobals.scss';
2
+
3
+ :host {
4
+ font-size: $fontSize * 3;
5
+ color: var(--strongFontColor);
6
+ font-family: $fontFamily;
7
+ font-weight: bold;
8
+ padding: 0px 8px;
9
+ text-align: center;
10
+ margin: auto;
11
+ }
@@ -0,0 +1,129 @@
1
+ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, NgZone, OnDestroy, OnInit } from '@angular/core';
2
+ import { Subscription, timer } from 'rxjs';
3
+ import { Guid } from '../../models/guidExtension';
4
+ import { InfoType } from '../wm-info/info-models';
5
+
6
+ @Component({
7
+ selector: 'wm-spinner',
8
+ styleUrls: ['./wm-spinner.scss'],
9
+ templateUrl: './wm-spinner.html',
10
+ changeDetection: ChangeDetectionStrategy.OnPush
11
+ })
12
+ export class SpinnerComponent implements OnInit, OnDestroy {
13
+
14
+ private uid = Guid.newGuid();
15
+
16
+ private _longMessageTimeSubscription: Subscription;
17
+ private _showOverlayTimerSubscription: Subscription;
18
+ private _startDate;
19
+ private _initialized = false;
20
+ public isOverlayVisible = false;
21
+ public isOverlayContrast = false;
22
+ public minTimeOfVisibilityMs = 500;
23
+ public showDelay = 250;
24
+
25
+ @Input() public delay = false;
26
+ @Input() public longMessageDelay = 12500;
27
+ @Input() public message: string = 'Waiting for data from server';
28
+ @Input() public messageTakesLong = 'Request is taking a bit longer than expected';
29
+ @Input() public messageBottomWait: string = 'Please Wait';
30
+ @Input() public detailInfoMessage: string;
31
+ @Input() public infoType: InfoType = InfoType.Error;
32
+
33
+ private _showSpinner: boolean;
34
+ public get showSpinner() { return this._showSpinner; }
35
+ @Input() public set showSpinner(value: boolean) {
36
+ // tslint:disable-next-line:triple-equals we should treat bool false and bool undefined as same. The same for all other cases.
37
+ if (this._showSpinner == value) return;
38
+ this._showSpinner = value;
39
+ this.unsubscribeTimers();
40
+
41
+ if (value) {
42
+ console.log('spinner started', this.uid);
43
+ // block UI, keep it light
44
+ this.isOverlayVisible = true;
45
+ this.subscribeTimers();
46
+ this.detectChanges();
47
+ } else {
48
+ this.stopShowingProgress();
49
+ }
50
+ }
51
+
52
+ constructor(private zone: NgZone, private change: ChangeDetectorRef) {
53
+ }
54
+
55
+ ngOnInit(): void {
56
+ this._initialized = true;
57
+ }
58
+
59
+ ngOnDestroy(): void {
60
+ console.log('destroy');
61
+ this.unsubscribeTimers();
62
+ }
63
+
64
+ private subscribeTimers() {
65
+ this.zone.runOutsideAngular(() => {
66
+ // show long wait message after few configured seconds
67
+ const longMessageTimer = timer(this.longMessageDelay);
68
+ this._longMessageTimeSubscription = longMessageTimer.subscribe(t => {
69
+ this.message = this.messageTakesLong;
70
+ this.change.detectChanges();
71
+ this._longMessageTimeSubscription.unsubscribe();
72
+ });
73
+
74
+ // draw overlay message after few configured seconds
75
+ if (!this.delay) {
76
+ this.startShowingProgress();
77
+ return;
78
+ }
79
+ const showAfterDelayTimer = timer(this.showDelay);
80
+ this._showOverlayTimerSubscription = showAfterDelayTimer.subscribe(t => {
81
+ if (this.showSpinner) this.startShowingProgress();
82
+ this.change.detectChanges();
83
+ this._showOverlayTimerSubscription.unsubscribe();
84
+ });
85
+ });
86
+ }
87
+
88
+ private unsubscribeTimers() {
89
+ if (this._longMessageTimeSubscription) this._longMessageTimeSubscription.unsubscribe();
90
+ if (this._showOverlayTimerSubscription) this._showOverlayTimerSubscription.unsubscribe();
91
+ }
92
+
93
+ private stopShowingProgress() {
94
+ if (this._startDate) {
95
+ const now = new Date().getTime();
96
+ const duration = (now - this._startDate.getTime()); // ms
97
+ if (duration < this.minTimeOfVisibilityMs) {
98
+ this.zone.runOutsideAngular(() => {
99
+ // let it be at least one second.
100
+ console.log('remains', this.minTimeOfVisibilityMs - duration);
101
+ setTimeout(() => this.doStopProgress(), this.minTimeOfVisibilityMs - duration);
102
+ });
103
+ return;
104
+ }
105
+ }
106
+ this.doStopProgress();
107
+ }
108
+
109
+ private startShowingProgress() {
110
+ console.log('contrast spinner', this.uid);
111
+ this._startDate = new Date();
112
+ this.isOverlayContrast = true;
113
+ this.detectChanges();
114
+ }
115
+
116
+ private doStopProgress() {
117
+ console.log('spinner ended', this.uid);
118
+ this.isOverlayContrast = false;
119
+ this.isOverlayVisible = false;
120
+ this._startDate = undefined;
121
+ this.detectChanges();
122
+ }
123
+
124
+ private detectChanges() {
125
+ if (!this._initialized) return;
126
+ this.change.detectChanges();
127
+ }
128
+
129
+ }
@@ -0,0 +1,37 @@
1
+ <div class="spinner-wrap flex-col wh-100" *ngIf="isOverlayVisible">
2
+ <div class="spinner-bg wh-100" [ngClass]="{'invisible': !isOverlayContrast }"></div>
3
+ <div class="spinner-content inline-col marginXA align-center" [ngClass]="{'invisible': !isOverlayContrast }">
4
+ <div class="msg-wrap marginBottomX8">
5
+ <div style="display: flex">
6
+ <div class="msg">{{message}}</div>
7
+ <wm-info class="info" [type]="infoType" popupPosition="top-center"
8
+ [iconAsTemplate]="infoType===2" [useThemeForIconTemplate]="infoType===2"
9
+ *ngIf="detailInfoMessage" [header]="detailInfoMessage" style="margin-left: 4px"></wm-info>
10
+ </div>
11
+
12
+ <div class="msg">{{messageBottomWait}}</div>
13
+ </div>
14
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 168 168" id="loader">
15
+ <defs>
16
+ <linearGradient id="a" x1="38.078%" x2="4.941%" y1="8.411%" y2="16.987%">
17
+ <stop offset="0%" stop-color="var(--brandColor)" stop-opacity="0.1" />
18
+ <stop offset="61.554%" stop-color="var(--brandColor)" stop-opacity="0.4" />
19
+ <stop offset="100%" stop-color="var(--brandColor)" stop-opacity="0.5" />
20
+ </linearGradient>
21
+ <radialGradient id="b" cy="43.835%" r="54.9%" fx="50%" fy="43.835%"
22
+ gradientTransform="matrix(-.77913 .62687 -.6485 -.80602 1.174 .478)">
23
+ <stop offset="0%" stop-color="#FFF" />
24
+ <stop offset="100%" stop-color="var(--brandColor)" stop-opacity="0.5" />
25
+ </radialGradient>
26
+ </defs>
27
+ <g fill="none" fill-rule="evenodd">
28
+ <g transform="translate(10 10)">
29
+ <path stroke="url(#a)" stroke-linecap="round" stroke-width="19"
30
+ d="M16.198 27.79C6.062 40.453 0 56.518 0 74c0 40.87 33.13 74 74 74s74-33.13 74-74c0-24.611-12.014-46.416-30.498-59.87C105.292 5.244 90.258 0 74 0" />
31
+ <circle cx="16.5" cy="27.5" r="9.5" fill="url(#b)" />
32
+ </g>
33
+ </g>
34
+ </svg>
35
+ </div>
36
+
37
+ </div>