@dugararchit/flex-layout 13.0.0-dugararchit

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 (226) hide show
  1. package/README.md +7 -0
  2. package/_private-utils/angular-flex-layout-_private-utils.d.ts +5 -0
  3. package/_private-utils/auto-prefixer.d.ts +24 -0
  4. package/_private-utils/index.d.ts +10 -0
  5. package/_private-utils/layout-validator.d.ts +32 -0
  6. package/_private-utils/object-extend.d.ts +15 -0
  7. package/_private-utils/package.json +10 -0
  8. package/_private-utils/testing/angular-flex-layout-_private-utils-testing.d.ts +5 -0
  9. package/_private-utils/testing/custom-matchers.d.ts +65 -0
  10. package/_private-utils/testing/dom-tools.d.ts +47 -0
  11. package/_private-utils/testing/helpers.d.ts +24 -0
  12. package/_private-utils/testing/index.d.ts +10 -0
  13. package/_private-utils/testing/package.json +10 -0
  14. package/angular-flex-layout-13.0.0-beta.38.tgz +0 -0
  15. package/angular-flex-layout.d.ts +5 -0
  16. package/core/README.md +25 -0
  17. package/core/add-alias.d.ts +14 -0
  18. package/core/angular-flex-layout-core.d.ts +5 -0
  19. package/core/base/base2.d.ts +60 -0
  20. package/core/base/index.d.ts +8 -0
  21. package/core/basis-validator/basis-validator.d.ts +13 -0
  22. package/core/breakpoints/break-point-registry.d.ts +42 -0
  23. package/core/breakpoints/break-point.d.ts +14 -0
  24. package/core/breakpoints/break-points-token.d.ts +14 -0
  25. package/core/breakpoints/breakpoint-tools.d.ts +19 -0
  26. package/core/breakpoints/data/break-points.d.ts +12 -0
  27. package/core/breakpoints/data/orientation-break-points.d.ts +23 -0
  28. package/core/breakpoints/index.d.ts +12 -0
  29. package/core/browser-provider.d.ts +24 -0
  30. package/core/match-media/index.d.ts +9 -0
  31. package/core/match-media/match-media.d.ts +59 -0
  32. package/core/match-media/mock/mock-match-media.d.ts +92 -0
  33. package/core/media-change.d.ts +30 -0
  34. package/core/media-marshaller/media-marshaller.d.ts +123 -0
  35. package/core/media-marshaller/print-hook.d.ts +95 -0
  36. package/core/media-observer/index.d.ts +8 -0
  37. package/core/media-observer/media-observer.d.ts +115 -0
  38. package/core/media-trigger/index.d.ts +8 -0
  39. package/core/media-trigger/media-trigger.d.ts +73 -0
  40. package/core/module.d.ts +11 -0
  41. package/core/multiply/multiplier.d.ts +5 -0
  42. package/core/package.json +10 -0
  43. package/core/public-api.d.ts +25 -0
  44. package/core/sass/_layout-bp.scss +76 -0
  45. package/core/style-builder/style-builder.d.ts +21 -0
  46. package/core/style-utils/style-utils.d.ts +53 -0
  47. package/core/stylesheet-map/index.d.ts +8 -0
  48. package/core/stylesheet-map/stylesheet-map.d.ts +24 -0
  49. package/core/tokens/breakpoint-token.d.ts +10 -0
  50. package/core/tokens/index.d.ts +10 -0
  51. package/core/tokens/library-config.d.ts +26 -0
  52. package/core/tokens/server-token.d.ts +15 -0
  53. package/core/utils/array.d.ts +9 -0
  54. package/core/utils/index.d.ts +9 -0
  55. package/core/utils/sort.d.ts +15 -0
  56. package/esm2020/_private-utils/angular-flex-layout-_private-utils.mjs +5 -0
  57. package/esm2020/_private-utils/auto-prefixer.mjs +65 -0
  58. package/esm2020/_private-utils/index.mjs +11 -0
  59. package/esm2020/_private-utils/layout-validator.mjs +83 -0
  60. package/esm2020/_private-utils/object-extend.mjs +30 -0
  61. package/esm2020/_private-utils/testing/angular-flex-layout-_private-utils-testing.mjs +5 -0
  62. package/esm2020/_private-utils/testing/custom-matchers.mjs +201 -0
  63. package/esm2020/_private-utils/testing/dom-tools.mjs +101 -0
  64. package/esm2020/_private-utils/testing/helpers.mjs +43 -0
  65. package/esm2020/_private-utils/testing/index.mjs +11 -0
  66. package/esm2020/angular-flex-layout.mjs +5 -0
  67. package/esm2020/core/add-alias.mjs +23 -0
  68. package/esm2020/core/angular-flex-layout-core.mjs +5 -0
  69. package/esm2020/core/base/base2.mjs +131 -0
  70. package/esm2020/core/base/index.mjs +9 -0
  71. package/esm2020/core/basis-validator/basis-validator.mjs +48 -0
  72. package/esm2020/core/breakpoints/break-point-registry.mjs +76 -0
  73. package/esm2020/core/breakpoints/break-point.mjs +2 -0
  74. package/esm2020/core/breakpoints/break-points-token.mjs +30 -0
  75. package/esm2020/core/breakpoints/breakpoint-tools.mjs +53 -0
  76. package/esm2020/core/breakpoints/data/break-points.mjs +78 -0
  77. package/esm2020/core/breakpoints/data/orientation-break-points.mjs +40 -0
  78. package/esm2020/core/breakpoints/index.mjs +13 -0
  79. package/esm2020/core/browser-provider.mjs +41 -0
  80. package/esm2020/core/match-media/index.mjs +10 -0
  81. package/esm2020/core/match-media/match-media.mjs +186 -0
  82. package/esm2020/core/match-media/mock/mock-match-media.mjs +224 -0
  83. package/esm2020/core/media-change.mjs +25 -0
  84. package/esm2020/core/media-marshaller/media-marshaller.mjs +317 -0
  85. package/esm2020/core/media-marshaller/print-hook.mjs +265 -0
  86. package/esm2020/core/media-observer/index.mjs +9 -0
  87. package/esm2020/core/media-observer/media-observer.mjs +195 -0
  88. package/esm2020/core/media-trigger/index.mjs +9 -0
  89. package/esm2020/core/media-trigger/media-trigger.mjs +188 -0
  90. package/esm2020/core/module.mjs +27 -0
  91. package/esm2020/core/multiply/multiplier.mjs +16 -0
  92. package/esm2020/core/public-api.mjs +26 -0
  93. package/esm2020/core/style-builder/style-builder.mjs +15 -0
  94. package/esm2020/core/style-utils/style-utils.mjs +174 -0
  95. package/esm2020/core/stylesheet-map/index.mjs +9 -0
  96. package/esm2020/core/stylesheet-map/stylesheet-map.mjs +59 -0
  97. package/esm2020/core/tokens/breakpoint-token.mjs +13 -0
  98. package/esm2020/core/tokens/index.mjs +11 -0
  99. package/esm2020/core/tokens/library-config.mjs +30 -0
  100. package/esm2020/core/tokens/server-token.mjs +19 -0
  101. package/esm2020/core/utils/array.mjs +12 -0
  102. package/esm2020/core/utils/index.mjs +10 -0
  103. package/esm2020/core/utils/sort.mjs +20 -0
  104. package/esm2020/extended/angular-flex-layout-extended.mjs +5 -0
  105. package/esm2020/extended/class/class.mjs +88 -0
  106. package/esm2020/extended/img-src/img-src.mjs +106 -0
  107. package/esm2020/extended/module.mjs +45 -0
  108. package/esm2020/extended/public-api.mjs +13 -0
  109. package/esm2020/extended/show-hide/show-hide.mjs +176 -0
  110. package/esm2020/extended/style/style-transforms.mjs +76 -0
  111. package/esm2020/extended/style/style.mjs +130 -0
  112. package/esm2020/flex/angular-flex-layout-flex.mjs +5 -0
  113. package/esm2020/flex/flex/flex.mjs +291 -0
  114. package/esm2020/flex/flex-align/flex-align.mjs +80 -0
  115. package/esm2020/flex/flex-fill/flex-fill.mjs +50 -0
  116. package/esm2020/flex/flex-offset/flex-offset.mjs +121 -0
  117. package/esm2020/flex/flex-order/flex-order.mjs +66 -0
  118. package/esm2020/flex/layout/layout.mjs +86 -0
  119. package/esm2020/flex/layout-align/layout-align.mjs +194 -0
  120. package/esm2020/flex/layout-gap/layout-gap.mjs +282 -0
  121. package/esm2020/flex/module.mjs +62 -0
  122. package/esm2020/flex/public-api.mjs +17 -0
  123. package/esm2020/grid/align-columns/align-columns.mjs +137 -0
  124. package/esm2020/grid/align-rows/align-rows.mjs +119 -0
  125. package/esm2020/grid/angular-flex-layout-grid.mjs +5 -0
  126. package/esm2020/grid/area/area.mjs +67 -0
  127. package/esm2020/grid/areas/areas.mjs +86 -0
  128. package/esm2020/grid/auto/auto.mjs +89 -0
  129. package/esm2020/grid/column/column.mjs +67 -0
  130. package/esm2020/grid/columns/columns.mjs +96 -0
  131. package/esm2020/grid/gap/gap.mjs +85 -0
  132. package/esm2020/grid/grid-align/grid-align.mjs +111 -0
  133. package/esm2020/grid/module.mjs +73 -0
  134. package/esm2020/grid/public-api.mjs +20 -0
  135. package/esm2020/grid/row/row.mjs +67 -0
  136. package/esm2020/grid/rows/rows.mjs +96 -0
  137. package/esm2020/module.mjs +64 -0
  138. package/esm2020/public-api.mjs +20 -0
  139. package/esm2020/server/angular-flex-layout-server.mjs +5 -0
  140. package/esm2020/server/module.mjs +22 -0
  141. package/esm2020/server/public-api.mjs +10 -0
  142. package/esm2020/server/server-match-media.mjs +151 -0
  143. package/esm2020/server/server-provider.mjs +140 -0
  144. package/esm2020/version.mjs +11 -0
  145. package/extended/README.md +18 -0
  146. package/extended/angular-flex-layout-extended.d.ts +5 -0
  147. package/extended/class/class.d.ts +38 -0
  148. package/extended/img-src/img-src.d.ts +51 -0
  149. package/extended/module.d.ts +16 -0
  150. package/extended/package.json +10 -0
  151. package/extended/public-api.d.ts +12 -0
  152. package/extended/show-hide/show-hide.d.ts +61 -0
  153. package/extended/style/style-transforms.d.ts +36 -0
  154. package/extended/style/style.d.ts +45 -0
  155. package/fesm2015/angular-flex-layout-_private-utils-testing.mjs +357 -0
  156. package/fesm2015/angular-flex-layout-_private-utils-testing.mjs.map +1 -0
  157. package/fesm2015/angular-flex-layout-_private-utils.mjs +193 -0
  158. package/fesm2015/angular-flex-layout-_private-utils.mjs.map +1 -0
  159. package/fesm2015/angular-flex-layout-core.mjs +2331 -0
  160. package/fesm2015/angular-flex-layout-core.mjs.map +1 -0
  161. package/fesm2015/angular-flex-layout-extended.mjs +621 -0
  162. package/fesm2015/angular-flex-layout-extended.mjs.map +1 -0
  163. package/fesm2015/angular-flex-layout-flex.mjs +1206 -0
  164. package/fesm2015/angular-flex-layout-flex.mjs.map +1 -0
  165. package/fesm2015/angular-flex-layout-grid.mjs +1047 -0
  166. package/fesm2015/angular-flex-layout-grid.mjs.map +1 -0
  167. package/fesm2015/angular-flex-layout-server.mjs +324 -0
  168. package/fesm2015/angular-flex-layout-server.mjs.map +1 -0
  169. package/fesm2015/angular-flex-layout.mjs +94 -0
  170. package/fesm2015/angular-flex-layout.mjs.map +1 -0
  171. package/fesm2020/angular-flex-layout-_private-utils-testing.mjs +357 -0
  172. package/fesm2020/angular-flex-layout-_private-utils-testing.mjs.map +1 -0
  173. package/fesm2020/angular-flex-layout-_private-utils.mjs +192 -0
  174. package/fesm2020/angular-flex-layout-_private-utils.mjs.map +1 -0
  175. package/fesm2020/angular-flex-layout-core.mjs +2304 -0
  176. package/fesm2020/angular-flex-layout-core.mjs.map +1 -0
  177. package/fesm2020/angular-flex-layout-extended.mjs +612 -0
  178. package/fesm2020/angular-flex-layout-extended.mjs.map +1 -0
  179. package/fesm2020/angular-flex-layout-flex.mjs +1198 -0
  180. package/fesm2020/angular-flex-layout-flex.mjs.map +1 -0
  181. package/fesm2020/angular-flex-layout-grid.mjs +1047 -0
  182. package/fesm2020/angular-flex-layout-grid.mjs.map +1 -0
  183. package/fesm2020/angular-flex-layout-server.mjs +322 -0
  184. package/fesm2020/angular-flex-layout-server.mjs.map +1 -0
  185. package/fesm2020/angular-flex-layout.mjs +92 -0
  186. package/fesm2020/angular-flex-layout.mjs.map +1 -0
  187. package/flex/README.md +19 -0
  188. package/flex/angular-flex-layout-flex.d.ts +5 -0
  189. package/flex/flex/flex.d.ts +59 -0
  190. package/flex/flex-align/flex-align.d.ts +32 -0
  191. package/flex/flex-fill/flex-fill.d.ts +33 -0
  192. package/flex/flex-offset/flex-offset.d.ts +44 -0
  193. package/flex/flex-order/flex-order.d.ts +34 -0
  194. package/flex/layout/layout.d.ts +43 -0
  195. package/flex/layout-align/layout-align.d.ts +49 -0
  196. package/flex/layout-gap/layout-gap.d.ts +65 -0
  197. package/flex/module.d.ts +21 -0
  198. package/flex/package.json +10 -0
  199. package/flex/public-api.d.ts +16 -0
  200. package/grid/README.md +19 -0
  201. package/grid/align-columns/align-columns.d.ts +39 -0
  202. package/grid/align-rows/align-rows.d.ts +39 -0
  203. package/grid/angular-flex-layout-grid.d.ts +5 -0
  204. package/grid/area/area.d.ts +34 -0
  205. package/grid/areas/areas.d.ts +41 -0
  206. package/grid/auto/auto.d.ts +41 -0
  207. package/grid/column/column.d.ts +34 -0
  208. package/grid/columns/columns.d.ts +43 -0
  209. package/grid/gap/gap.d.ts +42 -0
  210. package/grid/grid-align/grid-align.d.ts +37 -0
  211. package/grid/module.d.ts +23 -0
  212. package/grid/package.json +10 -0
  213. package/grid/public-api.d.ts +19 -0
  214. package/grid/row/row.d.ts +34 -0
  215. package/grid/rows/rows.d.ts +43 -0
  216. package/module.d.ts +30 -0
  217. package/package.json +100 -0
  218. package/public-api.d.ts +18 -0
  219. package/server/README.md +23 -0
  220. package/server/angular-flex-layout-server.d.ts +5 -0
  221. package/server/module.d.ts +6 -0
  222. package/server/package.json +10 -0
  223. package/server/public-api.d.ts +9 -0
  224. package/server/server-match-media.d.ts +61 -0
  225. package/server/server-provider.d.ts +44 -0
  226. package/version.d.ts +10 -0
@@ -0,0 +1,2304 @@
1
+ import * as i0 from '@angular/core';
2
+ import { APP_BOOTSTRAP_LISTENER, PLATFORM_ID, NgModule, Injectable, InjectionToken, Inject, inject, Directive } from '@angular/core';
3
+ import { isPlatformBrowser, DOCUMENT, isPlatformServer } from '@angular/common';
4
+ import { BehaviorSubject, Observable, merge, Subject, asapScheduler, of, fromEvent } from 'rxjs';
5
+ import { applyCssPrefixes, extendObject, buildLayoutCSS } from '@angular/flex-layout/_private-utils';
6
+ import { filter, tap, map, debounceTime, switchMap, distinctUntilChanged, takeUntil, take } from 'rxjs/operators';
7
+
8
+ /**
9
+ * @license
10
+ * Copyright Google LLC All Rights Reserved.
11
+ *
12
+ * Use of this source code is governed by an MIT-style license that can be
13
+ * found in the LICENSE file at https://angular.io/license
14
+ */
15
+ /**
16
+ * Find all of the server-generated stylings, if any, and remove them
17
+ * This will be in the form of inline classes and the style block in the
18
+ * head of the DOM
19
+ */
20
+ function removeStyles(_document, platformId) {
21
+ return () => {
22
+ if (isPlatformBrowser(platformId)) {
23
+ const elements = Array.from(_document.querySelectorAll(`[class*=${CLASS_NAME}]`));
24
+ // RegExp constructor should only be used if passing a variable to the constructor.
25
+ // When using static regular expression it is more performant to use reg exp literal.
26
+ // This is also needed to provide Safari 9 compatibility, please see
27
+ // https://stackoverflow.com/questions/37919802 for more discussion.
28
+ const classRegex = /\bflex-layout-.+?\b/g;
29
+ elements.forEach(el => {
30
+ el.classList.contains(`${CLASS_NAME}ssr`) && el.parentNode ?
31
+ el.parentNode.removeChild(el) : el.className.replace(classRegex, '');
32
+ });
33
+ }
34
+ };
35
+ }
36
+ /**
37
+ * Provider to remove SSR styles on the browser
38
+ */
39
+ const BROWSER_PROVIDER = {
40
+ provide: APP_BOOTSTRAP_LISTENER,
41
+ useFactory: removeStyles,
42
+ deps: [DOCUMENT, PLATFORM_ID],
43
+ multi: true
44
+ };
45
+ const CLASS_NAME = 'flex-layout-';
46
+
47
+ /**
48
+ * @license
49
+ * Copyright Google LLC All Rights Reserved.
50
+ *
51
+ * Use of this source code is governed by an MIT-style license that can be
52
+ * found in the LICENSE file at https://angular.io/license
53
+ */
54
+ /**
55
+ * *****************************************************************
56
+ * Define module for common Angular Layout utilities
57
+ * *****************************************************************
58
+ */
59
+ class CoreModule {
60
+ }
61
+ CoreModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: CoreModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
62
+ CoreModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: CoreModule });
63
+ CoreModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: CoreModule, providers: [BROWSER_PROVIDER] });
64
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: CoreModule, decorators: [{
65
+ type: NgModule,
66
+ args: [{
67
+ providers: [BROWSER_PROVIDER]
68
+ }]
69
+ }] });
70
+
71
+ /**
72
+ * Class instances emitted [to observers] for each mql notification
73
+ */
74
+ class MediaChange {
75
+ /**
76
+ * @param matches whether the mediaQuery is currently activated
77
+ * @param mediaQuery e.g. (min-width: 600px) and (max-width: 959px)
78
+ * @param mqAlias e.g. gt-sm, md, gt-lg
79
+ * @param suffix e.g. GtSM, Md, GtLg
80
+ * @param priority the priority of activation for the given breakpoint
81
+ */
82
+ constructor(matches = false, mediaQuery = 'all', mqAlias = '', suffix = '', priority = 0) {
83
+ this.matches = matches;
84
+ this.mediaQuery = mediaQuery;
85
+ this.mqAlias = mqAlias;
86
+ this.suffix = suffix;
87
+ this.priority = priority;
88
+ this.property = '';
89
+ }
90
+ /** Create an exact copy of the MediaChange */
91
+ clone() {
92
+ return new MediaChange(this.matches, this.mediaQuery, this.mqAlias, this.suffix);
93
+ }
94
+ }
95
+
96
+ /**
97
+ * @license
98
+ * Copyright Google LLC All Rights Reserved.
99
+ *
100
+ * Use of this source code is governed by an MIT-style license that can be
101
+ * found in the LICENSE file at https://angular.io/license
102
+ */
103
+ /**
104
+ * Utility to emulate a CSS stylesheet
105
+ *
106
+ * This utility class stores all of the styles for a given HTML element
107
+ * as a readonly `stylesheet` map.
108
+ */
109
+ class StylesheetMap {
110
+ constructor() {
111
+ this.stylesheet = new Map();
112
+ }
113
+ /**
114
+ * Add an individual style to an HTML element
115
+ */
116
+ addStyleToElement(element, style, value) {
117
+ const stylesheet = this.stylesheet.get(element);
118
+ if (stylesheet) {
119
+ stylesheet.set(style, value);
120
+ }
121
+ else {
122
+ this.stylesheet.set(element, new Map([[style, value]]));
123
+ }
124
+ }
125
+ /**
126
+ * Clear the virtual stylesheet
127
+ */
128
+ clearStyles() {
129
+ this.stylesheet.clear();
130
+ }
131
+ /**
132
+ * Retrieve a given style for an HTML element
133
+ */
134
+ getStyleForElement(el, styleName) {
135
+ const styles = this.stylesheet.get(el);
136
+ let value = '';
137
+ if (styles) {
138
+ const style = styles.get(styleName);
139
+ if (typeof style === 'number' || typeof style === 'string') {
140
+ value = style + '';
141
+ }
142
+ }
143
+ return value;
144
+ }
145
+ }
146
+ StylesheetMap.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: StylesheetMap, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
147
+ StylesheetMap.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: StylesheetMap, providedIn: 'root' });
148
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: StylesheetMap, decorators: [{
149
+ type: Injectable,
150
+ args: [{ providedIn: 'root' }]
151
+ }] });
152
+
153
+ /**
154
+ * @license
155
+ * Copyright Google LLC All Rights Reserved.
156
+ *
157
+ * Use of this source code is governed by an MIT-style license that can be
158
+ * found in the LICENSE file at https://angular.io/license
159
+ */
160
+
161
+ /**
162
+ * @license
163
+ * Copyright Google LLC All Rights Reserved.
164
+ *
165
+ * Use of this source code is governed by an MIT-style license that can be
166
+ * found in the LICENSE file at https://angular.io/license
167
+ */
168
+ const DEFAULT_CONFIG = {
169
+ addFlexToParent: true,
170
+ addOrientationBps: false,
171
+ disableDefaultBps: false,
172
+ disableVendorPrefixes: false,
173
+ serverLoaded: false,
174
+ useColumnBasisZero: true,
175
+ printWithBreakpoints: [],
176
+ mediaTriggerAutoRestore: true,
177
+ ssrObserveBreakpoints: [],
178
+ // This is disabled by default because otherwise the multiplier would
179
+ // run for all users, regardless of whether they're using this feature.
180
+ // Instead, we disable it by default, which requires this ugly cast.
181
+ multiplier: undefined,
182
+ defaultUnit: 'px',
183
+ detectLayoutDisplay: false,
184
+ };
185
+ const LAYOUT_CONFIG = new InjectionToken('Flex Layout token, config options for the library', {
186
+ providedIn: 'root',
187
+ factory: () => DEFAULT_CONFIG
188
+ });
189
+
190
+ /**
191
+ * @license
192
+ * Copyright Google LLC All Rights Reserved.
193
+ *
194
+ * Use of this source code is governed by an MIT-style license that can be
195
+ * found in the LICENSE file at https://angular.io/license
196
+ */
197
+ /**
198
+ * Token that is provided to tell whether the FlexLayoutServerModule
199
+ * has been included in the bundle
200
+ *
201
+ * NOTE: This can be manually provided to disable styles when using SSR
202
+ */
203
+ const SERVER_TOKEN = new InjectionToken('FlexLayoutServerLoaded', {
204
+ providedIn: 'root',
205
+ factory: () => false
206
+ });
207
+
208
+ /**
209
+ * @license
210
+ * Copyright Google LLC All Rights Reserved.
211
+ *
212
+ * Use of this source code is governed by an MIT-style license that can be
213
+ * found in the LICENSE file at https://angular.io/license
214
+ */
215
+ const BREAKPOINT = new InjectionToken('Flex Layout token, collect all breakpoints into one provider', {
216
+ providedIn: 'root',
217
+ factory: () => null
218
+ });
219
+
220
+ /**
221
+ * @license
222
+ * Copyright Google LLC All Rights Reserved.
223
+ *
224
+ * Use of this source code is governed by an MIT-style license that can be
225
+ * found in the LICENSE file at https://angular.io/license
226
+ */
227
+
228
+ /**
229
+ * @license
230
+ * Copyright Google LLC All Rights Reserved.
231
+ *
232
+ * Use of this source code is governed by an MIT-style license that can be
233
+ * found in the LICENSE file at https://angular.io/license
234
+ */
235
+ /**
236
+ * For the specified MediaChange, make sure it contains the breakpoint alias
237
+ * and suffix (if available).
238
+ */
239
+ function mergeAlias(dest, source) {
240
+ dest = dest ? dest.clone() : new MediaChange();
241
+ if (source) {
242
+ dest.mqAlias = source.alias;
243
+ dest.mediaQuery = source.mediaQuery;
244
+ dest.suffix = source.suffix;
245
+ dest.priority = source.priority;
246
+ }
247
+ return dest;
248
+ }
249
+
250
+ /** A class that encapsulates CSS style generation for common directives */
251
+ class StyleBuilder {
252
+ constructor() {
253
+ /** Whether to cache the generated output styles */
254
+ this.shouldCache = true;
255
+ }
256
+ /**
257
+ * Run a side effect computation given the input string and the computed styles
258
+ * from the build task and the host configuration object
259
+ * NOTE: This should be a no-op unless an algorithm is provided in a subclass
260
+ */
261
+ sideEffect(_input, _styles, _parent) {
262
+ }
263
+ }
264
+
265
+ /**
266
+ * @license
267
+ * Copyright Google LLC All Rights Reserved.
268
+ *
269
+ * Use of this source code is governed by an MIT-style license that can be
270
+ * found in the LICENSE file at https://angular.io/license
271
+ */
272
+ class StyleUtils {
273
+ constructor(_serverStylesheet, _serverModuleLoaded, _platformId, layoutConfig) {
274
+ this._serverStylesheet = _serverStylesheet;
275
+ this._serverModuleLoaded = _serverModuleLoaded;
276
+ this._platformId = _platformId;
277
+ this.layoutConfig = layoutConfig;
278
+ }
279
+ /**
280
+ * Applies styles given via string pair or object map to the directive element
281
+ */
282
+ applyStyleToElement(element, style, value = null) {
283
+ let styles = {};
284
+ if (typeof style === 'string') {
285
+ styles[style] = value;
286
+ style = styles;
287
+ }
288
+ styles = this.layoutConfig.disableVendorPrefixes ? style : applyCssPrefixes(style);
289
+ this._applyMultiValueStyleToElement(styles, element);
290
+ }
291
+ /**
292
+ * Applies styles given via string pair or object map to the directive's element
293
+ */
294
+ applyStyleToElements(style, elements = []) {
295
+ const styles = this.layoutConfig.disableVendorPrefixes ? style : applyCssPrefixes(style);
296
+ elements.forEach(el => {
297
+ this._applyMultiValueStyleToElement(styles, el);
298
+ });
299
+ }
300
+ /**
301
+ * Determine the DOM element's Flexbox flow (flex-direction)
302
+ *
303
+ * Check inline style first then check computed (stylesheet) style
304
+ */
305
+ getFlowDirection(target) {
306
+ const query = 'flex-direction';
307
+ let value = this.lookupStyle(target, query);
308
+ const hasInlineValue = this.lookupInlineStyle(target, query) ||
309
+ (isPlatformServer(this._platformId) && this._serverModuleLoaded) ? value : '';
310
+ return [value || 'row', hasInlineValue];
311
+ }
312
+ hasWrap(target) {
313
+ const query = 'flex-wrap';
314
+ return this.lookupStyle(target, query) === 'wrap';
315
+ }
316
+ /**
317
+ * Find the DOM element's raw attribute value (if any)
318
+ */
319
+ lookupAttributeValue(element, attribute) {
320
+ return element.getAttribute(attribute) ?? '';
321
+ }
322
+ /**
323
+ * Find the DOM element's inline style value (if any)
324
+ */
325
+ lookupInlineStyle(element, styleName) {
326
+ return isPlatformBrowser(this._platformId) ?
327
+ element.style.getPropertyValue(styleName) : getServerStyle(element, styleName);
328
+ }
329
+ /**
330
+ * Determine the inline or inherited CSS style
331
+ * NOTE: platform-server has no implementation for getComputedStyle
332
+ */
333
+ lookupStyle(element, styleName, inlineOnly = false) {
334
+ let value = '';
335
+ if (element) {
336
+ let immediateValue = value = this.lookupInlineStyle(element, styleName);
337
+ if (!immediateValue) {
338
+ if (isPlatformBrowser(this._platformId)) {
339
+ if (!inlineOnly) {
340
+ value = getComputedStyle(element).getPropertyValue(styleName);
341
+ }
342
+ }
343
+ else {
344
+ if (this._serverModuleLoaded) {
345
+ value = this._serverStylesheet.getStyleForElement(element, styleName);
346
+ }
347
+ }
348
+ }
349
+ }
350
+ // Note: 'inline' is the default of all elements, unless UA stylesheet overrides;
351
+ // in which case getComputedStyle() should determine a valid value.
352
+ return value ? value.trim() : '';
353
+ }
354
+ /**
355
+ * Applies the styles to the element. The styles object map may contain an array of values
356
+ * Each value will be added as element style
357
+ * Keys are sorted to add prefixed styles (like -webkit-x) first, before the standard ones
358
+ */
359
+ _applyMultiValueStyleToElement(styles, element) {
360
+ Object.keys(styles).sort().forEach(key => {
361
+ const el = styles[key];
362
+ const values = Array.isArray(el) ? el : [el];
363
+ values.sort();
364
+ for (let value of values) {
365
+ value = value ? value + '' : '';
366
+ if (isPlatformBrowser(this._platformId) || !this._serverModuleLoaded) {
367
+ isPlatformBrowser(this._platformId) ?
368
+ element.style.setProperty(key, value) : setServerStyle(element, key, value);
369
+ }
370
+ else {
371
+ this._serverStylesheet.addStyleToElement(element, key, value);
372
+ }
373
+ }
374
+ });
375
+ }
376
+ }
377
+ StyleUtils.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: StyleUtils, deps: [{ token: StylesheetMap }, { token: SERVER_TOKEN }, { token: PLATFORM_ID }, { token: LAYOUT_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable });
378
+ StyleUtils.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: StyleUtils, providedIn: 'root' });
379
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: StyleUtils, decorators: [{
380
+ type: Injectable,
381
+ args: [{ providedIn: 'root' }]
382
+ }], ctorParameters: function () { return [{ type: StylesheetMap }, { type: undefined, decorators: [{
383
+ type: Inject,
384
+ args: [SERVER_TOKEN]
385
+ }] }, { type: Object, decorators: [{
386
+ type: Inject,
387
+ args: [PLATFORM_ID]
388
+ }] }, { type: undefined, decorators: [{
389
+ type: Inject,
390
+ args: [LAYOUT_CONFIG]
391
+ }] }]; } });
392
+ function getServerStyle(element, styleName) {
393
+ const styleMap = readStyleAttribute(element);
394
+ return styleMap[styleName] ?? '';
395
+ }
396
+ function setServerStyle(element, styleName, styleValue) {
397
+ styleName = styleName.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
398
+ const styleMap = readStyleAttribute(element);
399
+ styleMap[styleName] = styleValue ?? '';
400
+ writeStyleAttribute(element, styleMap);
401
+ }
402
+ function writeStyleAttribute(element, styleMap) {
403
+ let styleAttrValue = '';
404
+ for (const key in styleMap) {
405
+ const newValue = styleMap[key];
406
+ if (newValue) {
407
+ styleAttrValue += `${key}:${styleMap[key]};`;
408
+ }
409
+ }
410
+ element.setAttribute('style', styleAttrValue);
411
+ }
412
+ function readStyleAttribute(element) {
413
+ const styleMap = {};
414
+ const styleAttribute = element.getAttribute('style');
415
+ if (styleAttribute) {
416
+ const styleList = styleAttribute.split(/;+/g);
417
+ for (let i = 0; i < styleList.length; i++) {
418
+ const style = styleList[i].trim();
419
+ if (style.length > 0) {
420
+ const colonIndex = style.indexOf(':');
421
+ if (colonIndex === -1) {
422
+ throw new Error(`Invalid CSS style: ${style}`);
423
+ }
424
+ const name = style.substr(0, colonIndex).trim();
425
+ styleMap[name] = style.substr(colonIndex + 1).trim();
426
+ }
427
+ }
428
+ }
429
+ return styleMap;
430
+ }
431
+
432
+ /**
433
+ * @license
434
+ * Copyright Google LLC All Rights Reserved.
435
+ *
436
+ * Use of this source code is governed by an MIT-style license that can be
437
+ * found in the LICENSE file at https://angular.io/license
438
+ */
439
+ /** HOF to sort the breakpoints by descending priority */
440
+ function sortDescendingPriority(a, b) {
441
+ const priorityA = a ? a.priority || 0 : 0;
442
+ const priorityB = b ? b.priority || 0 : 0;
443
+ return priorityB - priorityA;
444
+ }
445
+ /** HOF to sort the breakpoints by ascending priority */
446
+ function sortAscendingPriority(a, b) {
447
+ const pA = a.priority || 0;
448
+ const pB = b.priority || 0;
449
+ return pA - pB;
450
+ }
451
+
452
+ /**
453
+ * @license
454
+ * Copyright Google LLC All Rights Reserved.
455
+ *
456
+ * Use of this source code is governed by an MIT-style license that can be
457
+ * found in the LICENSE file at https://angular.io/license
458
+ */
459
+ /**
460
+ * MediaMonitor configures listeners to mediaQuery changes and publishes an Observable facade to
461
+ * convert mediaQuery change callbacks to subscriber notifications. These notifications will be
462
+ * performed within the ng Zone to trigger change detections and component updates.
463
+ *
464
+ * NOTE: both mediaQuery activations and de-activations are announced in notifications
465
+ */
466
+ class MatchMedia {
467
+ constructor(_zone, _platformId, _document) {
468
+ this._zone = _zone;
469
+ this._platformId = _platformId;
470
+ this._document = _document;
471
+ /** Initialize source with 'all' so all non-responsive APIs trigger style updates */
472
+ this.source = new BehaviorSubject(new MediaChange(true));
473
+ this.registry = new Map();
474
+ this.pendingRemoveListenerFns = [];
475
+ this._observable$ = this.source.asObservable();
476
+ }
477
+ /**
478
+ * Publish list of all current activations
479
+ */
480
+ get activations() {
481
+ const results = [];
482
+ this.registry.forEach((mql, key) => {
483
+ if (mql.matches) {
484
+ results.push(key);
485
+ }
486
+ });
487
+ return results;
488
+ }
489
+ /**
490
+ * For the specified mediaQuery?
491
+ */
492
+ isActive(mediaQuery) {
493
+ const mql = this.registry.get(mediaQuery);
494
+ return mql?.matches ?? this.registerQuery(mediaQuery).some(m => m.matches);
495
+ }
496
+ /**
497
+ * External observers can watch for all (or a specific) mql changes.
498
+ * Typically used by the MediaQueryAdaptor; optionally available to components
499
+ * who wish to use the MediaMonitor as mediaMonitor$ observable service.
500
+ *
501
+ * Use deferred registration process to register breakpoints only on subscription
502
+ * This logic also enforces logic to register all mediaQueries BEFORE notify
503
+ * subscribers of notifications.
504
+ */
505
+ observe(mqList, filterOthers = false) {
506
+ if (mqList && mqList.length) {
507
+ const matchMedia$ = this._observable$.pipe(filter((change) => !filterOthers ? true : (mqList.indexOf(change.mediaQuery) > -1)));
508
+ const registration$ = new Observable((observer) => {
509
+ const matches = this.registerQuery(mqList);
510
+ if (matches.length) {
511
+ const lastChange = matches.pop();
512
+ matches.forEach((e) => {
513
+ observer.next(e);
514
+ });
515
+ this.source.next(lastChange); // last match is cached
516
+ }
517
+ observer.complete();
518
+ });
519
+ return merge(registration$, matchMedia$);
520
+ }
521
+ return this._observable$;
522
+ }
523
+ /**
524
+ * Based on the BreakPointRegistry provider, register internal listeners for each unique
525
+ * mediaQuery. Each listener emits specific MediaChange data to observers
526
+ */
527
+ registerQuery(mediaQuery) {
528
+ const list = Array.isArray(mediaQuery) ? mediaQuery : [mediaQuery];
529
+ const matches = [];
530
+ buildQueryCss(list, this._document);
531
+ list.forEach((query) => {
532
+ const onMQLEvent = (e) => {
533
+ this._zone.run(() => this.source.next(new MediaChange(e.matches, query)));
534
+ };
535
+ let mql = this.registry.get(query);
536
+ if (!mql) {
537
+ mql = this.buildMQL(query);
538
+ mql.addListener(onMQLEvent);
539
+ this.pendingRemoveListenerFns.push(() => mql.removeListener(onMQLEvent));
540
+ this.registry.set(query, mql);
541
+ }
542
+ if (mql.matches) {
543
+ matches.push(new MediaChange(true, query));
544
+ }
545
+ });
546
+ return matches;
547
+ }
548
+ ngOnDestroy() {
549
+ let fn;
550
+ while (fn = this.pendingRemoveListenerFns.pop()) {
551
+ fn();
552
+ }
553
+ }
554
+ /**
555
+ * Call window.matchMedia() to build a MediaQueryList; which
556
+ * supports 0..n listeners for activation/deactivation
557
+ */
558
+ buildMQL(query) {
559
+ return constructMql(query, isPlatformBrowser(this._platformId));
560
+ }
561
+ }
562
+ MatchMedia.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: MatchMedia, deps: [{ token: i0.NgZone }, { token: PLATFORM_ID }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
563
+ MatchMedia.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: MatchMedia, providedIn: 'root' });
564
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: MatchMedia, decorators: [{
565
+ type: Injectable,
566
+ args: [{ providedIn: 'root' }]
567
+ }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: Object, decorators: [{
568
+ type: Inject,
569
+ args: [PLATFORM_ID]
570
+ }] }, { type: undefined, decorators: [{
571
+ type: Inject,
572
+ args: [DOCUMENT]
573
+ }] }]; } });
574
+ /**
575
+ * Private global registry for all dynamically-created, injected style tags
576
+ * @see prepare(query)
577
+ */
578
+ const ALL_STYLES = {};
579
+ /**
580
+ * For Webkit engines that only trigger the MediaQueryList Listener
581
+ * when there is at least one CSS selector for the respective media query.
582
+ *
583
+ * @param mediaQueries
584
+ * @param _document
585
+ */
586
+ function buildQueryCss(mediaQueries, _document) {
587
+ const list = mediaQueries.filter(it => !ALL_STYLES[it]);
588
+ if (list.length > 0) {
589
+ const query = list.join(', ');
590
+ try {
591
+ const styleEl = _document.createElement('style');
592
+ styleEl.setAttribute('type', 'text/css');
593
+ if (!styleEl.styleSheet) {
594
+ const cssText = `
595
+ /*
596
+ @angular/flex-layout - workaround for possible browser quirk with mediaQuery listeners
597
+ see http://bit.ly/2sd4HMP
598
+ */
599
+ @media ${query} {.fx-query-test{ }}
600
+ `;
601
+ styleEl.appendChild(_document.createTextNode(cssText));
602
+ }
603
+ _document.head.appendChild(styleEl);
604
+ // Store in private global registry
605
+ list.forEach(mq => ALL_STYLES[mq] = styleEl);
606
+ }
607
+ catch (e) {
608
+ console.error(e);
609
+ }
610
+ }
611
+ }
612
+ function constructMql(query, isBrowser) {
613
+ const canListen = isBrowser && !!window.matchMedia('all').addListener;
614
+ return canListen ? window.matchMedia(query) : {
615
+ matches: query === 'all' || query === '',
616
+ media: query,
617
+ addListener: () => {
618
+ },
619
+ removeListener: () => {
620
+ },
621
+ onchange: null,
622
+ addEventListener() {
623
+ },
624
+ removeEventListener() {
625
+ },
626
+ dispatchEvent() {
627
+ return false;
628
+ }
629
+ };
630
+ }
631
+
632
+ /**
633
+ * NOTE: Smaller ranges have HIGHER priority since the match is more specific
634
+ */
635
+ const DEFAULT_BREAKPOINTS = [
636
+ {
637
+ alias: 'xs',
638
+ mediaQuery: 'screen and (min-width: 0px) and (max-width: 599.98px)',
639
+ priority: 1000,
640
+ },
641
+ {
642
+ alias: 'sm',
643
+ mediaQuery: 'screen and (min-width: 600px) and (max-width: 959.98px)',
644
+ priority: 900,
645
+ },
646
+ {
647
+ alias: 'md',
648
+ mediaQuery: 'screen and (min-width: 960px) and (max-width: 1279.98px)',
649
+ priority: 800,
650
+ },
651
+ {
652
+ alias: 'lg',
653
+ mediaQuery: 'screen and (min-width: 1280px) and (max-width: 1919.98px)',
654
+ priority: 700,
655
+ },
656
+ {
657
+ alias: 'xl',
658
+ mediaQuery: 'screen and (min-width: 1920px) and (max-width: 4999.98px)',
659
+ priority: 600,
660
+ },
661
+ {
662
+ alias: 'lt-sm',
663
+ overlapping: true,
664
+ mediaQuery: 'screen and (max-width: 599.98px)',
665
+ priority: 950,
666
+ },
667
+ {
668
+ alias: 'lt-md',
669
+ overlapping: true,
670
+ mediaQuery: 'screen and (max-width: 959.98px)',
671
+ priority: 850,
672
+ },
673
+ {
674
+ alias: 'lt-lg',
675
+ overlapping: true,
676
+ mediaQuery: 'screen and (max-width: 1279.98px)',
677
+ priority: 750,
678
+ },
679
+ {
680
+ alias: 'lt-xl',
681
+ overlapping: true,
682
+ priority: 650,
683
+ mediaQuery: 'screen and (max-width: 1919.98px)',
684
+ },
685
+ {
686
+ alias: 'gt-xs',
687
+ overlapping: true,
688
+ mediaQuery: 'screen and (min-width: 600px)',
689
+ priority: -950,
690
+ },
691
+ {
692
+ alias: 'gt-sm',
693
+ overlapping: true,
694
+ mediaQuery: 'screen and (min-width: 960px)',
695
+ priority: -850,
696
+ }, {
697
+ alias: 'gt-md',
698
+ overlapping: true,
699
+ mediaQuery: 'screen and (min-width: 1280px)',
700
+ priority: -750,
701
+ },
702
+ {
703
+ alias: 'gt-lg',
704
+ overlapping: true,
705
+ mediaQuery: 'screen and (min-width: 1920px)',
706
+ priority: -650,
707
+ }
708
+ ];
709
+
710
+ /**
711
+ * @license
712
+ * Copyright Google LLC All Rights Reserved.
713
+ *
714
+ * Use of this source code is governed by an MIT-style license that can be
715
+ * found in the LICENSE file at https://angular.io/license
716
+ */
717
+ /* tslint:disable */
718
+ const HANDSET_PORTRAIT = '(orientation: portrait) and (max-width: 599.98px)';
719
+ const HANDSET_LANDSCAPE = '(orientation: landscape) and (max-width: 959.98px)';
720
+ const TABLET_PORTRAIT = '(orientation: portrait) and (min-width: 600px) and (max-width: 839.98px)';
721
+ const TABLET_LANDSCAPE = '(orientation: landscape) and (min-width: 960px) and (max-width: 1279.98px)';
722
+ const WEB_PORTRAIT = '(orientation: portrait) and (min-width: 840px)';
723
+ const WEB_LANDSCAPE = '(orientation: landscape) and (min-width: 1280px)';
724
+ const ScreenTypes = {
725
+ 'HANDSET': `${HANDSET_PORTRAIT}, ${HANDSET_LANDSCAPE}`,
726
+ 'TABLET': `${TABLET_PORTRAIT} , ${TABLET_LANDSCAPE}`,
727
+ 'WEB': `${WEB_PORTRAIT}, ${WEB_LANDSCAPE} `,
728
+ 'HANDSET_PORTRAIT': `${HANDSET_PORTRAIT}`,
729
+ 'TABLET_PORTRAIT': `${TABLET_PORTRAIT} `,
730
+ 'WEB_PORTRAIT': `${WEB_PORTRAIT}`,
731
+ 'HANDSET_LANDSCAPE': `${HANDSET_LANDSCAPE}`,
732
+ 'TABLET_LANDSCAPE': `${TABLET_LANDSCAPE}`,
733
+ 'WEB_LANDSCAPE': `${WEB_LANDSCAPE}`
734
+ };
735
+ /**
736
+ * Extended Breakpoints for handset/tablets with landscape or portrait orientations
737
+ */
738
+ const ORIENTATION_BREAKPOINTS = [
739
+ { 'alias': 'handset', priority: 2000, 'mediaQuery': ScreenTypes.HANDSET },
740
+ { 'alias': 'handset.landscape', priority: 2000, 'mediaQuery': ScreenTypes.HANDSET_LANDSCAPE },
741
+ { 'alias': 'handset.portrait', priority: 2000, 'mediaQuery': ScreenTypes.HANDSET_PORTRAIT },
742
+ { 'alias': 'tablet', priority: 2100, 'mediaQuery': ScreenTypes.TABLET },
743
+ { 'alias': 'tablet.landscape', priority: 2100, 'mediaQuery': ScreenTypes.TABLET_LANDSCAPE },
744
+ { 'alias': 'tablet.portrait', priority: 2100, 'mediaQuery': ScreenTypes.TABLET_PORTRAIT },
745
+ { 'alias': 'web', priority: 2200, 'mediaQuery': ScreenTypes.WEB, overlapping: true },
746
+ { 'alias': 'web.landscape', priority: 2200, 'mediaQuery': ScreenTypes.WEB_LANDSCAPE, overlapping: true },
747
+ { 'alias': 'web.portrait', priority: 2200, 'mediaQuery': ScreenTypes.WEB_PORTRAIT, overlapping: true }
748
+ ];
749
+
750
+ const ALIAS_DELIMITERS = /(\.|-|_)/g;
751
+ function firstUpperCase(part) {
752
+ let first = part.length > 0 ? part.charAt(0) : '';
753
+ let remainder = (part.length > 1) ? part.slice(1) : '';
754
+ return first.toUpperCase() + remainder;
755
+ }
756
+ /**
757
+ * Converts snake-case to SnakeCase.
758
+ * @param name Text to UpperCamelCase
759
+ */
760
+ function camelCase(name) {
761
+ return name
762
+ .replace(ALIAS_DELIMITERS, '|')
763
+ .split('|')
764
+ .map(firstUpperCase)
765
+ .join('');
766
+ }
767
+ /**
768
+ * For each breakpoint, ensure that a Suffix is defined;
769
+ * fallback to UpperCamelCase the unique Alias value
770
+ */
771
+ function validateSuffixes(list) {
772
+ list.forEach((bp) => {
773
+ if (!bp.suffix) {
774
+ bp.suffix = camelCase(bp.alias); // create Suffix value based on alias
775
+ bp.overlapping = !!bp.overlapping; // ensure default value
776
+ }
777
+ });
778
+ return list;
779
+ }
780
+ /**
781
+ * Merge a custom breakpoint list with the default list based on unique alias values
782
+ * - Items are added if the alias is not in the default list
783
+ * - Items are merged with the custom override if the alias exists in the default list
784
+ */
785
+ function mergeByAlias(defaults, custom = []) {
786
+ const dict = {};
787
+ defaults.forEach(bp => {
788
+ dict[bp.alias] = bp;
789
+ });
790
+ // Merge custom breakpoints
791
+ custom.forEach((bp) => {
792
+ if (dict[bp.alias]) {
793
+ extendObject(dict[bp.alias], bp);
794
+ }
795
+ else {
796
+ dict[bp.alias] = bp;
797
+ }
798
+ });
799
+ return validateSuffixes(Object.keys(dict).map(k => dict[k]));
800
+ }
801
+
802
+ /**
803
+ * @license
804
+ * Copyright Google LLC All Rights Reserved.
805
+ *
806
+ * Use of this source code is governed by an MIT-style license that can be
807
+ * found in the LICENSE file at https://angular.io/license
808
+ */
809
+ /**
810
+ * Injection token unique to the flex-layout library.
811
+ * Use this token when build a custom provider (see below).
812
+ */
813
+ const BREAKPOINTS = new InjectionToken('Token (@angular/flex-layout) Breakpoints', {
814
+ providedIn: 'root',
815
+ factory: () => {
816
+ const breakpoints = inject(BREAKPOINT);
817
+ const layoutConfig = inject(LAYOUT_CONFIG);
818
+ const bpFlattenArray = [].concat.apply([], (breakpoints || [])
819
+ .map((v) => Array.isArray(v) ? v : [v]));
820
+ const builtIns = (layoutConfig.disableDefaultBps ? [] : DEFAULT_BREAKPOINTS)
821
+ .concat(layoutConfig.addOrientationBps ? ORIENTATION_BREAKPOINTS : []);
822
+ return mergeByAlias(builtIns, bpFlattenArray);
823
+ }
824
+ });
825
+
826
+ /**
827
+ * @license
828
+ * Copyright Google LLC All Rights Reserved.
829
+ *
830
+ * Use of this source code is governed by an MIT-style license that can be
831
+ * found in the LICENSE file at https://angular.io/license
832
+ */
833
+ /**
834
+ * Registry of 1..n MediaQuery breakpoint ranges
835
+ * This is published as a provider and may be overridden from custom, application-specific ranges
836
+ *
837
+ */
838
+ class BreakPointRegistry {
839
+ constructor(list) {
840
+ /**
841
+ * Memoized BreakPoint Lookups
842
+ */
843
+ this.findByMap = new Map();
844
+ this.items = [...list].sort(sortAscendingPriority);
845
+ }
846
+ /**
847
+ * Search breakpoints by alias (e.g. gt-xs)
848
+ */
849
+ findByAlias(alias) {
850
+ return !alias ? null : this.findWithPredicate(alias, (bp) => bp.alias === alias);
851
+ }
852
+ findByQuery(query) {
853
+ return this.findWithPredicate(query, (bp) => bp.mediaQuery === query);
854
+ }
855
+ /**
856
+ * Get all the breakpoints whose ranges could overlapping `normal` ranges;
857
+ * e.g. gt-sm overlaps md, lg, and xl
858
+ */
859
+ get overlappings() {
860
+ return this.items.filter(it => it.overlapping);
861
+ }
862
+ /**
863
+ * Get list of all registered (non-empty) breakpoint aliases
864
+ */
865
+ get aliases() {
866
+ return this.items.map(it => it.alias);
867
+ }
868
+ /**
869
+ * Aliases are mapped to properties using suffixes
870
+ * e.g. 'gt-sm' for property 'layout' uses suffix 'GtSm'
871
+ * for property layoutGtSM.
872
+ */
873
+ get suffixes() {
874
+ return this.items.map(it => it?.suffix ?? '');
875
+ }
876
+ /**
877
+ * Memoized lookup using custom predicate function
878
+ */
879
+ findWithPredicate(key, searchFn) {
880
+ let response = this.findByMap.get(key);
881
+ if (!response) {
882
+ response = this.items.find(searchFn) ?? null;
883
+ this.findByMap.set(key, response);
884
+ }
885
+ return response ?? null;
886
+ }
887
+ }
888
+ BreakPointRegistry.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: BreakPointRegistry, deps: [{ token: BREAKPOINTS }], target: i0.ɵɵFactoryTarget.Injectable });
889
+ BreakPointRegistry.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: BreakPointRegistry, providedIn: 'root' });
890
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: BreakPointRegistry, decorators: [{
891
+ type: Injectable,
892
+ args: [{ providedIn: 'root' }]
893
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
894
+ type: Inject,
895
+ args: [BREAKPOINTS]
896
+ }] }]; } });
897
+
898
+ /**
899
+ * @license
900
+ * Copyright Google LLC All Rights Reserved.
901
+ *
902
+ * Use of this source code is governed by an MIT-style license that can be
903
+ * found in the LICENSE file at https://angular.io/license
904
+ */
905
+ const PRINT = 'print';
906
+ const BREAKPOINT_PRINT = {
907
+ alias: PRINT,
908
+ mediaQuery: PRINT,
909
+ priority: 1000
910
+ };
911
+ /**
912
+ * PrintHook - Use to intercept print MediaQuery activations and force
913
+ * layouts to render with the specified print alias/breakpoint
914
+ *
915
+ * Used in MediaMarshaller and MediaObserver
916
+ */
917
+ class PrintHook {
918
+ constructor(breakpoints, layoutConfig, _document) {
919
+ this.breakpoints = breakpoints;
920
+ this.layoutConfig = layoutConfig;
921
+ this._document = _document;
922
+ // registeredBeforeAfterPrintHooks tracks if we registered the `beforeprint`
923
+ // and `afterprint` event listeners.
924
+ this.registeredBeforeAfterPrintHooks = false;
925
+ // isPrintingBeforeAfterEvent is used to track if we are printing from within
926
+ // a `beforeprint` event handler. This prevents the typical `stopPrinting`
927
+ // form `interceptEvents` so that printing is not stopped while the dialog
928
+ // is still open. This is an extension of the `isPrinting` property on
929
+ // browsers which support `beforeprint` and `afterprint` events.
930
+ this.isPrintingBeforeAfterEvent = false;
931
+ this.beforePrintEventListeners = [];
932
+ this.afterPrintEventListeners = [];
933
+ this.formerActivations = null;
934
+ // Is this service currently in print mode
935
+ this.isPrinting = false;
936
+ this.queue = new PrintQueue();
937
+ this.deactivations = [];
938
+ }
939
+ /** Add 'print' mediaQuery: to listen for matchMedia activations */
940
+ withPrintQuery(queries) {
941
+ return [...queries, PRINT];
942
+ }
943
+ /** Is the MediaChange event for any 'print' @media */
944
+ isPrintEvent(e) {
945
+ return e.mediaQuery.startsWith(PRINT);
946
+ }
947
+ /** What is the desired mqAlias to use while printing? */
948
+ get printAlias() {
949
+ return [...(this.layoutConfig.printWithBreakpoints ?? [])];
950
+ }
951
+ /** Lookup breakpoints associated with print aliases. */
952
+ get printBreakPoints() {
953
+ return this.printAlias
954
+ .map(alias => this.breakpoints.findByAlias(alias))
955
+ .filter(bp => bp !== null);
956
+ }
957
+ /** Lookup breakpoint associated with mediaQuery */
958
+ getEventBreakpoints({ mediaQuery }) {
959
+ const bp = this.breakpoints.findByQuery(mediaQuery);
960
+ const list = bp ? [...this.printBreakPoints, bp] : this.printBreakPoints;
961
+ return list.sort(sortDescendingPriority);
962
+ }
963
+ /** Update event with printAlias mediaQuery information */
964
+ updateEvent(event) {
965
+ let bp = this.breakpoints.findByQuery(event.mediaQuery);
966
+ if (this.isPrintEvent(event)) {
967
+ // Reset from 'print' to first (highest priority) print breakpoint
968
+ bp = this.getEventBreakpoints(event)[0];
969
+ event.mediaQuery = bp?.mediaQuery ?? '';
970
+ }
971
+ return mergeAlias(event, bp);
972
+ }
973
+ // registerBeforeAfterPrintHooks registers a `beforeprint` event hook so we can
974
+ // trigger print styles synchronously and apply proper layout styles.
975
+ // It is a noop if the hooks have already been registered or if the document's
976
+ // `defaultView` is not available.
977
+ registerBeforeAfterPrintHooks(target) {
978
+ // `defaultView` may be null when rendering on the server or in other contexts.
979
+ if (!this._document.defaultView || this.registeredBeforeAfterPrintHooks) {
980
+ return;
981
+ }
982
+ this.registeredBeforeAfterPrintHooks = true;
983
+ const beforePrintListener = () => {
984
+ // If we aren't already printing, start printing and update the styles as
985
+ // if there was a regular print `MediaChange`(from matchMedia).
986
+ if (!this.isPrinting) {
987
+ this.isPrintingBeforeAfterEvent = true;
988
+ this.startPrinting(target, this.getEventBreakpoints(new MediaChange(true, PRINT)));
989
+ target.updateStyles();
990
+ }
991
+ };
992
+ const afterPrintListener = () => {
993
+ // If we aren't already printing, start printing and update the styles as
994
+ // if there was a regular print `MediaChange`(from matchMedia).
995
+ this.isPrintingBeforeAfterEvent = false;
996
+ if (this.isPrinting) {
997
+ this.stopPrinting(target);
998
+ target.updateStyles();
999
+ }
1000
+ };
1001
+ // Could we have teardown logic to remove if there are no print listeners being used?
1002
+ this._document.defaultView.addEventListener('beforeprint', beforePrintListener);
1003
+ this._document.defaultView.addEventListener('afterprint', afterPrintListener);
1004
+ this.beforePrintEventListeners.push(beforePrintListener);
1005
+ this.afterPrintEventListeners.push(afterPrintListener);
1006
+ }
1007
+ /**
1008
+ * Prepare RxJS tap operator with partial application
1009
+ * @return pipeable tap predicate
1010
+ */
1011
+ interceptEvents(target) {
1012
+ return (event) => {
1013
+ if (this.isPrintEvent(event)) {
1014
+ if (event.matches && !this.isPrinting) {
1015
+ this.startPrinting(target, this.getEventBreakpoints(event));
1016
+ target.updateStyles();
1017
+ }
1018
+ else if (!event.matches && this.isPrinting && !this.isPrintingBeforeAfterEvent) {
1019
+ this.stopPrinting(target);
1020
+ target.updateStyles();
1021
+ }
1022
+ return;
1023
+ }
1024
+ this.collectActivations(target, event);
1025
+ };
1026
+ }
1027
+ /** Stop mediaChange event propagation in event streams */
1028
+ blockPropagation() {
1029
+ return (event) => {
1030
+ return !(this.isPrinting || this.isPrintEvent(event));
1031
+ };
1032
+ }
1033
+ /**
1034
+ * Save current activateBreakpoints (for later restore)
1035
+ * and substitute only the printAlias breakpoint
1036
+ */
1037
+ startPrinting(target, bpList) {
1038
+ this.isPrinting = true;
1039
+ this.formerActivations = target.activatedBreakpoints;
1040
+ target.activatedBreakpoints = this.queue.addPrintBreakpoints(bpList);
1041
+ }
1042
+ /** For any print de-activations, reset the entire print queue */
1043
+ stopPrinting(target) {
1044
+ target.activatedBreakpoints = this.deactivations;
1045
+ this.deactivations = [];
1046
+ this.formerActivations = null;
1047
+ this.queue.clear();
1048
+ this.isPrinting = false;
1049
+ }
1050
+ /**
1051
+ * To restore pre-Print Activations, we must capture the proper
1052
+ * list of breakpoint activations BEFORE print starts. OnBeforePrint()
1053
+ * is supported; so 'print' mediaQuery activations are used as a fallback
1054
+ * in browsers without `beforeprint` support.
1055
+ *
1056
+ * > But activated breakpoints are deactivated BEFORE 'print' activation.
1057
+ *
1058
+ * Let's capture all de-activations using the following logic:
1059
+ *
1060
+ * When not printing:
1061
+ * - clear cache when activating non-print breakpoint
1062
+ * - update cache (and sort) when deactivating
1063
+ *
1064
+ * When printing:
1065
+ * - sort and save when starting print
1066
+ * - restore as activatedTargets and clear when stop printing
1067
+ */
1068
+ collectActivations(target, event) {
1069
+ if (!this.isPrinting || this.isPrintingBeforeAfterEvent) {
1070
+ if (!this.isPrintingBeforeAfterEvent) {
1071
+ // Only clear deactivations if we aren't printing from a `beforeprint` event.
1072
+ // Otherwise, this will clear before `stopPrinting()` is called to restore
1073
+ // the pre-Print Activations.
1074
+ this.deactivations = [];
1075
+ return;
1076
+ }
1077
+ if (!event.matches) {
1078
+ const bp = this.breakpoints.findByQuery(event.mediaQuery);
1079
+ // Deactivating a breakpoint
1080
+ if (bp) {
1081
+ const hasFormerBp = this.formerActivations && this.formerActivations.includes(bp);
1082
+ const wasActivated = !this.formerActivations && target.activatedBreakpoints.includes(bp);
1083
+ const shouldDeactivate = hasFormerBp || wasActivated;
1084
+ if (shouldDeactivate) {
1085
+ this.deactivations.push(bp);
1086
+ this.deactivations.sort(sortDescendingPriority);
1087
+ }
1088
+ }
1089
+ }
1090
+ }
1091
+ }
1092
+ /** Teardown logic for the service. */
1093
+ ngOnDestroy() {
1094
+ if (this._document.defaultView) {
1095
+ this.beforePrintEventListeners.forEach(l => this._document.defaultView.removeEventListener('beforeprint', l));
1096
+ this.afterPrintEventListeners.forEach(l => this._document.defaultView.removeEventListener('afterprint', l));
1097
+ }
1098
+ }
1099
+ }
1100
+ PrintHook.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: PrintHook, deps: [{ token: BreakPointRegistry }, { token: LAYOUT_CONFIG }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
1101
+ PrintHook.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: PrintHook, providedIn: 'root' });
1102
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: PrintHook, decorators: [{
1103
+ type: Injectable,
1104
+ args: [{ providedIn: 'root' }]
1105
+ }], ctorParameters: function () { return [{ type: BreakPointRegistry }, { type: undefined, decorators: [{
1106
+ type: Inject,
1107
+ args: [LAYOUT_CONFIG]
1108
+ }] }, { type: undefined, decorators: [{
1109
+ type: Inject,
1110
+ args: [DOCUMENT]
1111
+ }] }]; } });
1112
+ // ************************************************************************
1113
+ // Internal Utility class 'PrintQueue'
1114
+ // ************************************************************************
1115
+ /**
1116
+ * Utility class to manage print breakpoints + activatedBreakpoints
1117
+ * with correct sorting WHILE printing
1118
+ */
1119
+ class PrintQueue {
1120
+ constructor() {
1121
+ /** Sorted queue with prioritized print breakpoints */
1122
+ this.printBreakpoints = [];
1123
+ }
1124
+ addPrintBreakpoints(bpList) {
1125
+ bpList.push(BREAKPOINT_PRINT);
1126
+ bpList.sort(sortDescendingPriority);
1127
+ bpList.forEach(bp => this.addBreakpoint(bp));
1128
+ return this.printBreakpoints;
1129
+ }
1130
+ /** Add Print breakpoint to queue */
1131
+ addBreakpoint(bp) {
1132
+ if (!!bp) {
1133
+ const bpInList = this.printBreakpoints.find(it => it.mediaQuery === bp.mediaQuery);
1134
+ if (bpInList === undefined) {
1135
+ // If this is a `printAlias` breakpoint, then append. If a true 'print' breakpoint,
1136
+ // register as highest priority in the queue
1137
+ this.printBreakpoints = isPrintBreakPoint(bp) ? [bp, ...this.printBreakpoints]
1138
+ : [...this.printBreakpoints, bp];
1139
+ }
1140
+ }
1141
+ }
1142
+ /** Restore original activated breakpoints and clear internal caches */
1143
+ clear() {
1144
+ this.printBreakpoints = [];
1145
+ }
1146
+ }
1147
+ // ************************************************************************
1148
+ // Internal Utility methods
1149
+ // ************************************************************************
1150
+ /** Only support intercept queueing if the Breakpoint is a print @media query */
1151
+ function isPrintBreakPoint(bp) {
1152
+ return bp?.mediaQuery.startsWith(PRINT) ?? false;
1153
+ }
1154
+
1155
+ /**
1156
+ * @license
1157
+ * Copyright Google LLC All Rights Reserved.
1158
+ *
1159
+ * Use of this source code is governed by an MIT-style license that can be
1160
+ * found in the LICENSE file at https://angular.io/license
1161
+ */
1162
+ /**
1163
+ * MediaMarshaller - register responsive values from directives and
1164
+ * trigger them based on media query events
1165
+ */
1166
+ class MediaMarshaller {
1167
+ constructor(matchMedia, breakpoints, hook) {
1168
+ this.matchMedia = matchMedia;
1169
+ this.breakpoints = breakpoints;
1170
+ this.hook = hook;
1171
+ this._useFallbacks = true;
1172
+ this._activatedBreakpoints = [];
1173
+ this.elementMap = new Map();
1174
+ this.elementKeyMap = new WeakMap();
1175
+ this.watcherMap = new WeakMap(); // special triggers to update elements
1176
+ this.updateMap = new WeakMap(); // callback functions to update styles
1177
+ this.clearMap = new WeakMap(); // callback functions to clear styles
1178
+ this.subject = new Subject();
1179
+ this.observeActivations();
1180
+ }
1181
+ get activatedAlias() {
1182
+ return this.activatedBreakpoints[0]?.alias ?? '';
1183
+ }
1184
+ set activatedBreakpoints(bps) {
1185
+ this._activatedBreakpoints = [...bps];
1186
+ }
1187
+ get activatedBreakpoints() {
1188
+ return [...this._activatedBreakpoints];
1189
+ }
1190
+ set useFallbacks(value) {
1191
+ this._useFallbacks = value;
1192
+ }
1193
+ /**
1194
+ * Update styles on breakpoint activates or deactivates
1195
+ * @param mc
1196
+ */
1197
+ onMediaChange(mc) {
1198
+ const bp = this.findByQuery(mc.mediaQuery);
1199
+ if (bp) {
1200
+ mc = mergeAlias(mc, bp);
1201
+ const bpIndex = this.activatedBreakpoints.indexOf(bp);
1202
+ if (mc.matches && bpIndex === -1) {
1203
+ this._activatedBreakpoints.push(bp);
1204
+ this._activatedBreakpoints.sort(sortDescendingPriority);
1205
+ this.updateStyles();
1206
+ }
1207
+ else if (!mc.matches && bpIndex !== -1) {
1208
+ // Remove the breakpoint when it's deactivated
1209
+ this._activatedBreakpoints.splice(bpIndex, 1);
1210
+ this._activatedBreakpoints.sort(sortDescendingPriority);
1211
+ this.updateStyles();
1212
+ }
1213
+ }
1214
+ }
1215
+ /**
1216
+ * initialize the marshaller with necessary elements for delegation on an element
1217
+ * @param element
1218
+ * @param key
1219
+ * @param updateFn optional callback so that custom bp directives don't have to re-provide this
1220
+ * @param clearFn optional callback so that custom bp directives don't have to re-provide this
1221
+ * @param extraTriggers other triggers to force style updates (e.g. layout, directionality, etc)
1222
+ */
1223
+ init(element, key, updateFn, clearFn, extraTriggers = []) {
1224
+ initBuilderMap(this.updateMap, element, key, updateFn);
1225
+ initBuilderMap(this.clearMap, element, key, clearFn);
1226
+ this.buildElementKeyMap(element, key);
1227
+ this.watchExtraTriggers(element, key, extraTriggers);
1228
+ }
1229
+ /**
1230
+ * get the value for an element and key and optionally a given breakpoint
1231
+ * @param element
1232
+ * @param key
1233
+ * @param bp
1234
+ */
1235
+ getValue(element, key, bp) {
1236
+ const bpMap = this.elementMap.get(element);
1237
+ if (bpMap) {
1238
+ const values = bp !== undefined ? bpMap.get(bp) : this.getActivatedValues(bpMap, key);
1239
+ if (values) {
1240
+ return values.get(key);
1241
+ }
1242
+ }
1243
+ return undefined;
1244
+ }
1245
+ /**
1246
+ * whether the element has values for a given key
1247
+ * @param element
1248
+ * @param key
1249
+ */
1250
+ hasValue(element, key) {
1251
+ const bpMap = this.elementMap.get(element);
1252
+ if (bpMap) {
1253
+ const values = this.getActivatedValues(bpMap, key);
1254
+ if (values) {
1255
+ return values.get(key) !== undefined || false;
1256
+ }
1257
+ }
1258
+ return false;
1259
+ }
1260
+ /**
1261
+ * Set the value for an input on a directive
1262
+ * @param element the element in question
1263
+ * @param key the type of the directive (e.g. flex, layout-gap, etc)
1264
+ * @param bp the breakpoint suffix (empty string = default)
1265
+ * @param val the value for the breakpoint
1266
+ */
1267
+ setValue(element, key, val, bp) {
1268
+ let bpMap = this.elementMap.get(element);
1269
+ if (!bpMap) {
1270
+ bpMap = new Map().set(bp, new Map().set(key, val));
1271
+ this.elementMap.set(element, bpMap);
1272
+ }
1273
+ else {
1274
+ const values = (bpMap.get(bp) ?? new Map()).set(key, val);
1275
+ bpMap.set(bp, values);
1276
+ this.elementMap.set(element, bpMap);
1277
+ }
1278
+ const value = this.getValue(element, key);
1279
+ if (value !== undefined) {
1280
+ this.updateElement(element, key, value);
1281
+ }
1282
+ }
1283
+ /** Track element value changes for a specific key */
1284
+ trackValue(element, key) {
1285
+ return this.subject
1286
+ .asObservable()
1287
+ .pipe(filter(v => v.element === element && v.key === key));
1288
+ }
1289
+ /** update all styles for all elements on the current breakpoint */
1290
+ updateStyles() {
1291
+ this.elementMap.forEach((bpMap, el) => {
1292
+ const keyMap = new Set(this.elementKeyMap.get(el));
1293
+ let valueMap = this.getActivatedValues(bpMap);
1294
+ if (valueMap) {
1295
+ valueMap.forEach((v, k) => {
1296
+ this.updateElement(el, k, v);
1297
+ keyMap.delete(k);
1298
+ });
1299
+ }
1300
+ keyMap.forEach(k => {
1301
+ valueMap = this.getActivatedValues(bpMap, k);
1302
+ if (valueMap) {
1303
+ const value = valueMap.get(k);
1304
+ this.updateElement(el, k, value);
1305
+ }
1306
+ else {
1307
+ this.clearElement(el, k);
1308
+ }
1309
+ });
1310
+ });
1311
+ }
1312
+ /**
1313
+ * clear the styles for a given element
1314
+ * @param element
1315
+ * @param key
1316
+ */
1317
+ clearElement(element, key) {
1318
+ const builders = this.clearMap.get(element);
1319
+ if (builders) {
1320
+ const clearFn = builders.get(key);
1321
+ if (!!clearFn) {
1322
+ clearFn();
1323
+ this.subject.next({ element, key, value: '' });
1324
+ }
1325
+ }
1326
+ }
1327
+ /**
1328
+ * update a given element with the activated values for a given key
1329
+ * @param element
1330
+ * @param key
1331
+ * @param value
1332
+ */
1333
+ updateElement(element, key, value) {
1334
+ const builders = this.updateMap.get(element);
1335
+ if (builders) {
1336
+ const updateFn = builders.get(key);
1337
+ if (!!updateFn) {
1338
+ updateFn(value);
1339
+ this.subject.next({ element, key, value });
1340
+ }
1341
+ }
1342
+ }
1343
+ /**
1344
+ * release all references to a given element
1345
+ * @param element
1346
+ */
1347
+ releaseElement(element) {
1348
+ const watcherMap = this.watcherMap.get(element);
1349
+ if (watcherMap) {
1350
+ watcherMap.forEach(s => s.unsubscribe());
1351
+ this.watcherMap.delete(element);
1352
+ }
1353
+ const elementMap = this.elementMap.get(element);
1354
+ if (elementMap) {
1355
+ elementMap.forEach((_, s) => elementMap.delete(s));
1356
+ this.elementMap.delete(element);
1357
+ }
1358
+ }
1359
+ /**
1360
+ * trigger an update for a given element and key (e.g. layout)
1361
+ * @param element
1362
+ * @param key
1363
+ */
1364
+ triggerUpdate(element, key) {
1365
+ const bpMap = this.elementMap.get(element);
1366
+ if (bpMap) {
1367
+ const valueMap = this.getActivatedValues(bpMap, key);
1368
+ if (valueMap) {
1369
+ if (key) {
1370
+ this.updateElement(element, key, valueMap.get(key));
1371
+ }
1372
+ else {
1373
+ valueMap.forEach((v, k) => this.updateElement(element, k, v));
1374
+ }
1375
+ }
1376
+ }
1377
+ }
1378
+ /** Cross-reference for HTMLElement with directive key */
1379
+ buildElementKeyMap(element, key) {
1380
+ let keyMap = this.elementKeyMap.get(element);
1381
+ if (!keyMap) {
1382
+ keyMap = new Set();
1383
+ this.elementKeyMap.set(element, keyMap);
1384
+ }
1385
+ keyMap.add(key);
1386
+ }
1387
+ /**
1388
+ * Other triggers that should force style updates:
1389
+ * - directionality
1390
+ * - layout changes
1391
+ * - mutationobserver updates
1392
+ */
1393
+ watchExtraTriggers(element, key, triggers) {
1394
+ if (triggers && triggers.length) {
1395
+ let watchers = this.watcherMap.get(element);
1396
+ if (!watchers) {
1397
+ watchers = new Map();
1398
+ this.watcherMap.set(element, watchers);
1399
+ }
1400
+ const subscription = watchers.get(key);
1401
+ if (!subscription) {
1402
+ const newSubscription = merge(...triggers).subscribe(() => {
1403
+ const currentValue = this.getValue(element, key);
1404
+ this.updateElement(element, key, currentValue);
1405
+ });
1406
+ watchers.set(key, newSubscription);
1407
+ }
1408
+ }
1409
+ }
1410
+ /** Breakpoint locator by mediaQuery */
1411
+ findByQuery(query) {
1412
+ return this.breakpoints.findByQuery(query);
1413
+ }
1414
+ /**
1415
+ * get the fallback breakpoint for a given element, starting with the current breakpoint
1416
+ * @param bpMap
1417
+ * @param key
1418
+ */
1419
+ getActivatedValues(bpMap, key) {
1420
+ for (let i = 0; i < this.activatedBreakpoints.length; i++) {
1421
+ const activatedBp = this.activatedBreakpoints[i];
1422
+ const valueMap = bpMap.get(activatedBp.alias);
1423
+ if (valueMap) {
1424
+ if (key === undefined || (valueMap.has(key) && valueMap.get(key) != null)) {
1425
+ return valueMap;
1426
+ }
1427
+ }
1428
+ }
1429
+ // On the server, we explicitly have an "all" section filled in to begin with.
1430
+ // So we don't need to aggressively find a fallback if no explicit value exists.
1431
+ if (!this._useFallbacks) {
1432
+ return undefined;
1433
+ }
1434
+ const lastHope = bpMap.get('');
1435
+ return (key === undefined || lastHope && lastHope.has(key)) ? lastHope : undefined;
1436
+ }
1437
+ /**
1438
+ * Watch for mediaQuery breakpoint activations
1439
+ */
1440
+ observeActivations() {
1441
+ const queries = this.breakpoints.items.map(bp => bp.mediaQuery);
1442
+ this.hook.registerBeforeAfterPrintHooks(this);
1443
+ this.matchMedia
1444
+ .observe(this.hook.withPrintQuery(queries))
1445
+ .pipe(tap(this.hook.interceptEvents(this)), filter(this.hook.blockPropagation()))
1446
+ .subscribe(this.onMediaChange.bind(this));
1447
+ }
1448
+ }
1449
+ MediaMarshaller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: MediaMarshaller, deps: [{ token: MatchMedia }, { token: BreakPointRegistry }, { token: PrintHook }], target: i0.ɵɵFactoryTarget.Injectable });
1450
+ MediaMarshaller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: MediaMarshaller, providedIn: 'root' });
1451
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: MediaMarshaller, decorators: [{
1452
+ type: Injectable,
1453
+ args: [{ providedIn: 'root' }]
1454
+ }], ctorParameters: function () { return [{ type: MatchMedia }, { type: BreakPointRegistry }, { type: PrintHook }]; } });
1455
+ function initBuilderMap(map, element, key, input) {
1456
+ if (input !== undefined) {
1457
+ const oldMap = map.get(element) ?? new Map();
1458
+ oldMap.set(key, input);
1459
+ map.set(element, oldMap);
1460
+ }
1461
+ }
1462
+
1463
+ /**
1464
+ * @license
1465
+ * Copyright Google LLC All Rights Reserved.
1466
+ *
1467
+ * Use of this source code is governed by an MIT-style license that can be
1468
+ * found in the LICENSE file at https://angular.io/license
1469
+ */
1470
+ class BaseDirective2 {
1471
+ constructor(elementRef, styleBuilder, styler, marshal) {
1472
+ this.elementRef = elementRef;
1473
+ this.styleBuilder = styleBuilder;
1474
+ this.styler = styler;
1475
+ this.marshal = marshal;
1476
+ this.DIRECTIVE_KEY = '';
1477
+ this.inputs = [];
1478
+ /** The most recently used styles for the builder */
1479
+ this.mru = {};
1480
+ this.destroySubject = new Subject();
1481
+ /** Cache map for style computation */
1482
+ this.styleCache = new Map();
1483
+ }
1484
+ /** Access to host element's parent DOM node */
1485
+ get parentElement() {
1486
+ return this.elementRef.nativeElement.parentElement;
1487
+ }
1488
+ /** Access to the HTMLElement for the directive */
1489
+ get nativeElement() {
1490
+ return this.elementRef.nativeElement;
1491
+ }
1492
+ /** Access to the activated value for the directive */
1493
+ get activatedValue() {
1494
+ return this.marshal.getValue(this.nativeElement, this.DIRECTIVE_KEY);
1495
+ }
1496
+ set activatedValue(value) {
1497
+ this.marshal.setValue(this.nativeElement, this.DIRECTIVE_KEY, value, this.marshal.activatedAlias);
1498
+ }
1499
+ /** For @Input changes */
1500
+ ngOnChanges(changes) {
1501
+ Object.keys(changes).forEach(key => {
1502
+ if (this.inputs.indexOf(key) !== -1) {
1503
+ const bp = key.split('.').slice(1).join('.');
1504
+ const val = changes[key].currentValue;
1505
+ this.setValue(val, bp);
1506
+ }
1507
+ });
1508
+ }
1509
+ ngOnDestroy() {
1510
+ this.destroySubject.next();
1511
+ this.destroySubject.complete();
1512
+ this.marshal.releaseElement(this.nativeElement);
1513
+ }
1514
+ /** Register with central marshaller service */
1515
+ init(extraTriggers = []) {
1516
+ this.marshal.init(this.elementRef.nativeElement, this.DIRECTIVE_KEY, this.updateWithValue.bind(this), this.clearStyles.bind(this), extraTriggers);
1517
+ }
1518
+ /** Add styles to the element using predefined style builder */
1519
+ addStyles(input, parent) {
1520
+ const builder = this.styleBuilder;
1521
+ const useCache = builder.shouldCache;
1522
+ let genStyles = this.styleCache.get(input);
1523
+ if (!genStyles || !useCache) {
1524
+ genStyles = builder.buildStyles(input, parent);
1525
+ if (useCache) {
1526
+ this.styleCache.set(input, genStyles);
1527
+ }
1528
+ }
1529
+ this.mru = { ...genStyles };
1530
+ this.applyStyleToElement(genStyles);
1531
+ builder.sideEffect(input, genStyles, parent);
1532
+ }
1533
+ /** Remove generated styles from an element using predefined style builder */
1534
+ clearStyles() {
1535
+ Object.keys(this.mru).forEach(k => {
1536
+ this.mru[k] = '';
1537
+ });
1538
+ this.applyStyleToElement(this.mru);
1539
+ this.mru = {};
1540
+ this.currentValue = undefined;
1541
+ }
1542
+ /** Force trigger style updates on DOM element */
1543
+ triggerUpdate() {
1544
+ this.marshal.triggerUpdate(this.nativeElement, this.DIRECTIVE_KEY);
1545
+ }
1546
+ /**
1547
+ * Determine the DOM element's Flexbox flow (flex-direction).
1548
+ *
1549
+ * Check inline style first then check computed (stylesheet) style.
1550
+ * And optionally add the flow value to element's inline style.
1551
+ */
1552
+ getFlexFlowDirection(target, addIfMissing = false) {
1553
+ if (target) {
1554
+ const [value, hasInlineValue] = this.styler.getFlowDirection(target);
1555
+ if (!hasInlineValue && addIfMissing) {
1556
+ const style = buildLayoutCSS(value);
1557
+ const elements = [target];
1558
+ this.styler.applyStyleToElements(style, elements);
1559
+ }
1560
+ return value.trim();
1561
+ }
1562
+ return 'row';
1563
+ }
1564
+ hasWrap(target) {
1565
+ return this.styler.hasWrap(target);
1566
+ }
1567
+ /** Applies styles given via string pair or object map to the directive element */
1568
+ applyStyleToElement(style, value, element = this.nativeElement) {
1569
+ this.styler.applyStyleToElement(element, style, value);
1570
+ }
1571
+ setValue(val, bp) {
1572
+ this.marshal.setValue(this.nativeElement, this.DIRECTIVE_KEY, val, bp);
1573
+ }
1574
+ updateWithValue(input) {
1575
+ if (this.currentValue !== input) {
1576
+ this.addStyles(input);
1577
+ this.currentValue = input;
1578
+ }
1579
+ }
1580
+ }
1581
+ BaseDirective2.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: BaseDirective2, deps: [{ token: i0.ElementRef }, { token: StyleBuilder }, { token: StyleUtils }, { token: MediaMarshaller }], target: i0.ɵɵFactoryTarget.Directive });
1582
+ BaseDirective2.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.0.2", type: BaseDirective2, usesOnChanges: true, ngImport: i0 });
1583
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: BaseDirective2, decorators: [{
1584
+ type: Directive
1585
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: StyleBuilder }, { type: StyleUtils }, { type: MediaMarshaller }]; } });
1586
+
1587
+ /**
1588
+ * @license
1589
+ * Copyright Google LLC All Rights Reserved.
1590
+ *
1591
+ * Use of this source code is governed by an MIT-style license that can be
1592
+ * found in the LICENSE file at https://angular.io/license
1593
+ */
1594
+
1595
+ /**
1596
+ * @license
1597
+ * Copyright Google LLC All Rights Reserved.
1598
+ *
1599
+ * Use of this source code is governed by an MIT-style license that can be
1600
+ * found in the LICENSE file at https://angular.io/license
1601
+ */
1602
+
1603
+ /**
1604
+ * @license
1605
+ * Copyright Google LLC All Rights Reserved.
1606
+ *
1607
+ * Use of this source code is governed by an MIT-style license that can be
1608
+ * found in the LICENSE file at https://angular.io/license
1609
+ */
1610
+ /**
1611
+ * MockMatchMedia mocks calls to the Window API matchMedia with a build of a simulated
1612
+ * MockMediaQueryListener. Methods are available to simulate an activation of a mediaQuery
1613
+ * range and to clearAll mediaQuery listeners.
1614
+ */
1615
+ class MockMatchMedia extends MatchMedia {
1616
+ constructor(_zone, _platformId, _document, _breakpoints) {
1617
+ super(_zone, _platformId, _document);
1618
+ this._breakpoints = _breakpoints;
1619
+ this.autoRegisterQueries = true; // Used for testing BreakPoint registrations
1620
+ this.useOverlaps = false; // Allow fallback to overlapping mediaQueries
1621
+ }
1622
+ /** Easy method to clear all listeners for all mediaQueries */
1623
+ clearAll() {
1624
+ this.registry.forEach((mql) => {
1625
+ mql.destroy();
1626
+ });
1627
+ this.registry.clear();
1628
+ this.useOverlaps = false;
1629
+ }
1630
+ /** Feature to support manual, simulated activation of a mediaQuery. */
1631
+ activate(mediaQuery, useOverlaps = this.useOverlaps) {
1632
+ mediaQuery = this._validateQuery(mediaQuery);
1633
+ if (useOverlaps || !this.isActive(mediaQuery)) {
1634
+ this._deactivateAll();
1635
+ this._registerMediaQuery(mediaQuery);
1636
+ this._activateWithOverlaps(mediaQuery, useOverlaps);
1637
+ }
1638
+ return this.hasActivated;
1639
+ }
1640
+ /** Converts an optional mediaQuery alias to a specific, valid mediaQuery */
1641
+ _validateQuery(queryOrAlias) {
1642
+ const bp = this._breakpoints.findByAlias(queryOrAlias);
1643
+ return bp?.mediaQuery ?? queryOrAlias;
1644
+ }
1645
+ /**
1646
+ * Manually onMediaChange any overlapping mediaQueries to simulate
1647
+ * similar functionality in the window.matchMedia()
1648
+ */
1649
+ _activateWithOverlaps(mediaQuery, useOverlaps) {
1650
+ if (useOverlaps) {
1651
+ const bp = this._breakpoints.findByQuery(mediaQuery);
1652
+ const alias = bp?.alias ?? 'unknown';
1653
+ // Simulate activation of overlapping lt-<XXX> ranges
1654
+ switch (alias) {
1655
+ case 'lg':
1656
+ this._activateByAlias(['lt-xl']);
1657
+ break;
1658
+ case 'md':
1659
+ this._activateByAlias(['lt-xl', 'lt-lg']);
1660
+ break;
1661
+ case 'sm':
1662
+ this._activateByAlias(['lt-xl', 'lt-lg', 'lt-md']);
1663
+ break;
1664
+ case 'xs':
1665
+ this._activateByAlias(['lt-xl', 'lt-lg', 'lt-md', 'lt-sm']);
1666
+ break;
1667
+ }
1668
+ // Simulate activation of overlapping gt-<xxxx> mediaQuery ranges
1669
+ switch (alias) {
1670
+ case 'xl':
1671
+ this._activateByAlias(['gt-lg', 'gt-md', 'gt-sm', 'gt-xs']);
1672
+ break;
1673
+ case 'lg':
1674
+ this._activateByAlias(['gt-md', 'gt-sm', 'gt-xs']);
1675
+ break;
1676
+ case 'md':
1677
+ this._activateByAlias(['gt-sm', 'gt-xs']);
1678
+ break;
1679
+ case 'sm':
1680
+ this._activateByAlias(['gt-xs']);
1681
+ break;
1682
+ }
1683
+ }
1684
+ // Activate last since the responsiveActivation is watching *this* mediaQuery
1685
+ return this._activateByQuery(mediaQuery);
1686
+ }
1687
+ /**
1688
+ *
1689
+ */
1690
+ _activateByAlias(aliases) {
1691
+ const activate = (alias) => {
1692
+ const bp = this._breakpoints.findByAlias(alias);
1693
+ this._activateByQuery(bp?.mediaQuery ?? alias);
1694
+ };
1695
+ aliases.forEach(activate);
1696
+ }
1697
+ /**
1698
+ *
1699
+ */
1700
+ _activateByQuery(mediaQuery) {
1701
+ if (!this.registry.has(mediaQuery) && this.autoRegisterQueries) {
1702
+ this._registerMediaQuery(mediaQuery);
1703
+ }
1704
+ const mql = this.registry.get(mediaQuery);
1705
+ if (mql && !this.isActive(mediaQuery)) {
1706
+ this.registry.set(mediaQuery, mql.activate());
1707
+ }
1708
+ return this.hasActivated;
1709
+ }
1710
+ /** Deactivate all current MQLs and reset the buffer */
1711
+ _deactivateAll() {
1712
+ this.registry.forEach((it) => {
1713
+ it.deactivate();
1714
+ });
1715
+ return this;
1716
+ }
1717
+ /** Insure the mediaQuery is registered with MatchMedia */
1718
+ _registerMediaQuery(mediaQuery) {
1719
+ if (!this.registry.has(mediaQuery) && this.autoRegisterQueries) {
1720
+ this.registerQuery(mediaQuery);
1721
+ }
1722
+ }
1723
+ /**
1724
+ * Call window.matchMedia() to build a MediaQueryList; which
1725
+ * supports 0..n listeners for activation/deactivation
1726
+ */
1727
+ buildMQL(query) {
1728
+ return new MockMediaQueryList(query);
1729
+ }
1730
+ get hasActivated() {
1731
+ return this.activations.length > 0;
1732
+ }
1733
+ }
1734
+ MockMatchMedia.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: MockMatchMedia, deps: [{ token: i0.NgZone }, { token: PLATFORM_ID }, { token: DOCUMENT }, { token: BreakPointRegistry }], target: i0.ɵɵFactoryTarget.Injectable });
1735
+ MockMatchMedia.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: MockMatchMedia });
1736
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: MockMatchMedia, decorators: [{
1737
+ type: Injectable
1738
+ }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: Object, decorators: [{
1739
+ type: Inject,
1740
+ args: [PLATFORM_ID]
1741
+ }] }, { type: undefined, decorators: [{
1742
+ type: Inject,
1743
+ args: [DOCUMENT]
1744
+ }] }, { type: BreakPointRegistry }]; } });
1745
+ /**
1746
+ * Special internal class to simulate a MediaQueryList and
1747
+ * - supports manual activation to simulate mediaQuery matching
1748
+ * - manages listeners
1749
+ */
1750
+ class MockMediaQueryList {
1751
+ constructor(_mediaQuery) {
1752
+ this._mediaQuery = _mediaQuery;
1753
+ this._isActive = false;
1754
+ this._listeners = [];
1755
+ this.onchange = null;
1756
+ }
1757
+ get matches() {
1758
+ return this._isActive;
1759
+ }
1760
+ get media() {
1761
+ return this._mediaQuery;
1762
+ }
1763
+ /**
1764
+ * Destroy the current list by deactivating the
1765
+ * listeners and clearing the internal list
1766
+ */
1767
+ destroy() {
1768
+ this.deactivate();
1769
+ this._listeners = [];
1770
+ }
1771
+ /** Notify all listeners that 'matches === TRUE' */
1772
+ activate() {
1773
+ if (!this._isActive) {
1774
+ this._isActive = true;
1775
+ this._listeners.forEach((callback) => {
1776
+ const cb = callback;
1777
+ cb.call(this, { matches: this.matches, media: this.media });
1778
+ });
1779
+ }
1780
+ return this;
1781
+ }
1782
+ /** Notify all listeners that 'matches === false' */
1783
+ deactivate() {
1784
+ if (this._isActive) {
1785
+ this._isActive = false;
1786
+ this._listeners.forEach((callback) => {
1787
+ const cb = callback;
1788
+ cb.call(this, { matches: this.matches, media: this.media });
1789
+ });
1790
+ }
1791
+ return this;
1792
+ }
1793
+ /** Add a listener to our internal list to activate later */
1794
+ addListener(listener) {
1795
+ if (this._listeners.indexOf(listener) === -1) {
1796
+ this._listeners.push(listener);
1797
+ }
1798
+ if (this._isActive) {
1799
+ const cb = listener;
1800
+ cb.call(this, { matches: this.matches, media: this.media });
1801
+ }
1802
+ }
1803
+ /** Don't need to remove listeners in the testing environment */
1804
+ removeListener(_) {
1805
+ }
1806
+ addEventListener(_, __, ___) {
1807
+ }
1808
+ removeEventListener(_, __, ___) {
1809
+ }
1810
+ dispatchEvent(_) {
1811
+ return false;
1812
+ }
1813
+ }
1814
+ /**
1815
+ * Pre-configured provider for MockMatchMedia
1816
+ */
1817
+ const MockMatchMediaProvider = {
1818
+ provide: MatchMedia,
1819
+ useClass: MockMatchMedia
1820
+ };
1821
+
1822
+ /**
1823
+ * @license
1824
+ * Copyright Google LLC All Rights Reserved.
1825
+ *
1826
+ * Use of this source code is governed by an MIT-style license that can be
1827
+ * found in the LICENSE file at https://angular.io/license
1828
+ */
1829
+
1830
+ /**
1831
+ * @license
1832
+ * Copyright Google LLC All Rights Reserved.
1833
+ *
1834
+ * Use of this source code is governed by an MIT-style license that can be
1835
+ * found in the LICENSE file at https://angular.io/license
1836
+ */
1837
+ /** Wraps the provided value in an array, unless the provided value is an array. */
1838
+ function coerceArray(value) {
1839
+ return Array.isArray(value) ? value : [value];
1840
+ }
1841
+
1842
+ /**
1843
+ * @license
1844
+ * Copyright Google LLC All Rights Reserved.
1845
+ *
1846
+ * Use of this source code is governed by an MIT-style license that can be
1847
+ * found in the LICENSE file at https://angular.io/license
1848
+ */
1849
+ /**
1850
+ * MediaObserver enables applications to listen for 1..n mediaQuery activations and to determine
1851
+ * if a mediaQuery is currently activated.
1852
+ *
1853
+ * Since a breakpoint change will first deactivate 1...n mediaQueries and then possibly activate
1854
+ * 1..n mediaQueries, the MediaObserver will debounce notifications and report ALL *activations*
1855
+ * in 1 event notification. The reported activations will be sorted in descending priority order.
1856
+ *
1857
+ * This class uses the BreakPoint Registry to inject alias information into the raw MediaChange
1858
+ * notification. For custom mediaQuery notifications, alias information will not be injected and
1859
+ * those fields will be ''.
1860
+ *
1861
+ * Note: Developers should note that only mediaChange activations (not de-activations)
1862
+ * are announced by the MediaObserver.
1863
+ *
1864
+ * @usage
1865
+ *
1866
+ * // RxJS
1867
+ * import { filter } from 'rxjs/operators';
1868
+ * import { MediaObserver } from '@angular/flex-layout';
1869
+ *
1870
+ * @Component({ ... })
1871
+ * export class AppComponent {
1872
+ * status: string = '';
1873
+ *
1874
+ * constructor(mediaObserver: MediaObserver) {
1875
+ * const media$ = mediaObserver.asObservable().pipe(
1876
+ * filter((changes: MediaChange[]) => true) // silly noop filter
1877
+ * );
1878
+ *
1879
+ * media$.subscribe((changes: MediaChange[]) => {
1880
+ * let status = '';
1881
+ * changes.forEach( change => {
1882
+ * status += `'${change.mqAlias}' = (${change.mediaQuery}) <br/>` ;
1883
+ * });
1884
+ * this.status = status;
1885
+ * });
1886
+ *
1887
+ * }
1888
+ * }
1889
+ */
1890
+ class MediaObserver {
1891
+ constructor(breakpoints, matchMedia, hook) {
1892
+ this.breakpoints = breakpoints;
1893
+ this.matchMedia = matchMedia;
1894
+ this.hook = hook;
1895
+ /** Filter MediaChange notifications for overlapping breakpoints */
1896
+ this.filterOverlaps = false;
1897
+ this.destroyed$ = new Subject();
1898
+ this._media$ = this.watchActivations();
1899
+ this.media$ = this._media$.pipe(filter((changes) => changes.length > 0), map((changes) => changes[0]));
1900
+ }
1901
+ /**
1902
+ * Completes the active subject, signalling to all complete for all
1903
+ * MediaObserver subscribers
1904
+ */
1905
+ ngOnDestroy() {
1906
+ this.destroyed$.next();
1907
+ this.destroyed$.complete();
1908
+ }
1909
+ // ************************************************
1910
+ // Public Methods
1911
+ // ************************************************
1912
+ /**
1913
+ * Observe changes to current activation 'list'
1914
+ */
1915
+ asObservable() {
1916
+ return this._media$;
1917
+ }
1918
+ /**
1919
+ * Allow programmatic query to determine if one or more media query/alias match
1920
+ * the current viewport size.
1921
+ * @param value One or more media queries (or aliases) to check.
1922
+ * @returns Whether any of the media queries match.
1923
+ */
1924
+ isActive(value) {
1925
+ const aliases = splitQueries(coerceArray(value));
1926
+ return aliases.some(alias => {
1927
+ const query = toMediaQuery(alias, this.breakpoints);
1928
+ return query !== null && this.matchMedia.isActive(query);
1929
+ });
1930
+ }
1931
+ // ************************************************
1932
+ // Internal Methods
1933
+ // ************************************************
1934
+ /**
1935
+ * Register all the mediaQueries registered in the BreakPointRegistry
1936
+ * This is needed so subscribers can be auto-notified of all standard, registered
1937
+ * mediaQuery activations
1938
+ */
1939
+ watchActivations() {
1940
+ const queries = this.breakpoints.items.map(bp => bp.mediaQuery);
1941
+ return this.buildObservable(queries);
1942
+ }
1943
+ /**
1944
+ * Only pass/announce activations (not de-activations)
1945
+ *
1946
+ * Since multiple-mediaQueries can be activation in a cycle,
1947
+ * gather all current activations into a single list of changes to observers
1948
+ *
1949
+ * Inject associated (if any) alias information into the MediaChange event
1950
+ * - Exclude mediaQuery activations for overlapping mQs. List bounded mQ ranges only
1951
+ * - Exclude print activations that do not have an associated mediaQuery
1952
+ *
1953
+ * NOTE: the raw MediaChange events [from MatchMedia] do not
1954
+ * contain important alias information; as such this info
1955
+ * must be injected into the MediaChange
1956
+ */
1957
+ buildObservable(mqList) {
1958
+ const hasChanges = (changes) => {
1959
+ const isValidQuery = (change) => (change.mediaQuery.length > 0);
1960
+ return (changes.filter(isValidQuery).length > 0);
1961
+ };
1962
+ const excludeOverlaps = (changes) => {
1963
+ return !this.filterOverlaps ? changes : changes.filter(change => {
1964
+ const bp = this.breakpoints.findByQuery(change.mediaQuery);
1965
+ return bp?.overlapping ?? true;
1966
+ });
1967
+ };
1968
+ const ignoreDuplicates = (previous, current) => {
1969
+ if (previous.length !== current.length) {
1970
+ return false;
1971
+ }
1972
+ const previousMqs = previous.map(mc => mc.mediaQuery);
1973
+ const currentMqs = new Set(current.map(mc => mc.mediaQuery));
1974
+ const difference = new Set(previousMqs.filter(mq => !currentMqs.has(mq)));
1975
+ return difference.size === 0;
1976
+ };
1977
+ /**
1978
+ */
1979
+ return this.matchMedia
1980
+ .observe(this.hook.withPrintQuery(mqList))
1981
+ .pipe(filter((change) => change.matches), debounceTime(0, asapScheduler), switchMap(_ => of(this.findAllActivations())), map(excludeOverlaps), filter(hasChanges), distinctUntilChanged(ignoreDuplicates), takeUntil(this.destroyed$));
1982
+ }
1983
+ /**
1984
+ * Find all current activations and prepare single list of activations
1985
+ * sorted by descending priority.
1986
+ */
1987
+ findAllActivations() {
1988
+ const mergeMQAlias = (change) => {
1989
+ const bp = this.breakpoints.findByQuery(change.mediaQuery);
1990
+ return mergeAlias(change, bp);
1991
+ };
1992
+ const replaceWithPrintAlias = (change) => {
1993
+ return this.hook.isPrintEvent(change) ? this.hook.updateEvent(change) : change;
1994
+ };
1995
+ return this.matchMedia
1996
+ .activations
1997
+ .map(query => new MediaChange(true, query))
1998
+ .map(replaceWithPrintAlias)
1999
+ .map(mergeMQAlias)
2000
+ .sort(sortDescendingPriority);
2001
+ }
2002
+ }
2003
+ MediaObserver.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: MediaObserver, deps: [{ token: BreakPointRegistry }, { token: MatchMedia }, { token: PrintHook }], target: i0.ɵɵFactoryTarget.Injectable });
2004
+ MediaObserver.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: MediaObserver, providedIn: 'root' });
2005
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: MediaObserver, decorators: [{
2006
+ type: Injectable,
2007
+ args: [{ providedIn: 'root' }]
2008
+ }], ctorParameters: function () { return [{ type: BreakPointRegistry }, { type: MatchMedia }, { type: PrintHook }]; } });
2009
+ /**
2010
+ * Find associated breakpoint (if any)
2011
+ */
2012
+ function toMediaQuery(query, locator) {
2013
+ const bp = locator.findByAlias(query) ?? locator.findByQuery(query);
2014
+ return bp?.mediaQuery ?? null;
2015
+ }
2016
+ /**
2017
+ * Split each query string into separate query strings if two queries are provided as comma
2018
+ * separated.
2019
+ */
2020
+ function splitQueries(queries) {
2021
+ return queries.map((query) => query.split(','))
2022
+ .reduce((a1, a2) => a1.concat(a2))
2023
+ .map(query => query.trim());
2024
+ }
2025
+
2026
+ /**
2027
+ * @license
2028
+ * Copyright Google LLC All Rights Reserved.
2029
+ *
2030
+ * Use of this source code is governed by an MIT-style license that can be
2031
+ * found in the LICENSE file at https://angular.io/license
2032
+ */
2033
+
2034
+ /**
2035
+ * @license
2036
+ * Copyright Google LLC All Rights Reserved.
2037
+ *
2038
+ * Use of this source code is governed by an MIT-style license that can be
2039
+ * found in the LICENSE file at https://angular.io/license
2040
+ */
2041
+ /**
2042
+ * Class
2043
+ */
2044
+ class MediaTrigger {
2045
+ constructor(breakpoints, matchMedia, layoutConfig, _platformId, _document) {
2046
+ this.breakpoints = breakpoints;
2047
+ this.matchMedia = matchMedia;
2048
+ this.layoutConfig = layoutConfig;
2049
+ this._platformId = _platformId;
2050
+ this._document = _document;
2051
+ this.hasCachedRegistryMatches = false;
2052
+ this.originalActivations = [];
2053
+ this.originalRegistry = new Map();
2054
+ }
2055
+ /**
2056
+ * Manually activate range of breakpoints
2057
+ * @param list array of mediaQuery or alias strings
2058
+ */
2059
+ activate(list) {
2060
+ list = list.map(it => it.trim()); // trim queries
2061
+ this.saveActivations();
2062
+ this.deactivateAll();
2063
+ this.setActivations(list);
2064
+ this.prepareAutoRestore();
2065
+ }
2066
+ /**
2067
+ * Restore original, 'real' breakpoints and emit events
2068
+ * to trigger stream notification
2069
+ */
2070
+ restore() {
2071
+ if (this.hasCachedRegistryMatches) {
2072
+ const extractQuery = (change) => change.mediaQuery;
2073
+ const list = this.originalActivations.map(extractQuery);
2074
+ try {
2075
+ this.deactivateAll();
2076
+ this.restoreRegistryMatches();
2077
+ this.setActivations(list);
2078
+ }
2079
+ finally {
2080
+ this.originalActivations = [];
2081
+ if (this.resizeSubscription) {
2082
+ this.resizeSubscription.unsubscribe();
2083
+ }
2084
+ }
2085
+ }
2086
+ }
2087
+ // ************************************************
2088
+ // Internal Methods
2089
+ // ************************************************
2090
+ /**
2091
+ * Whenever window resizes, immediately auto-restore original
2092
+ * activations (if we are simulating activations)
2093
+ */
2094
+ prepareAutoRestore() {
2095
+ const isBrowser = isPlatformBrowser(this._platformId) && this._document;
2096
+ const enableAutoRestore = isBrowser && this.layoutConfig.mediaTriggerAutoRestore;
2097
+ if (enableAutoRestore) {
2098
+ const resize$ = fromEvent(window, 'resize').pipe(take(1));
2099
+ this.resizeSubscription = resize$.subscribe(this.restore.bind(this));
2100
+ }
2101
+ }
2102
+ /**
2103
+ * Notify all matchMedia subscribers of de-activations
2104
+ *
2105
+ * Note: we must force 'matches' updates for
2106
+ * future matchMedia::activation lookups
2107
+ */
2108
+ deactivateAll() {
2109
+ const list = this.currentActivations;
2110
+ this.forceRegistryMatches(list, false);
2111
+ this.simulateMediaChanges(list, false);
2112
+ }
2113
+ /**
2114
+ * Cache current activations as sorted, prioritized list of MediaChanges
2115
+ */
2116
+ saveActivations() {
2117
+ if (!this.hasCachedRegistryMatches) {
2118
+ const toMediaChange = (query) => new MediaChange(true, query);
2119
+ const mergeMQAlias = (change) => {
2120
+ const bp = this.breakpoints.findByQuery(change.mediaQuery);
2121
+ return mergeAlias(change, bp);
2122
+ };
2123
+ this.originalActivations = this.currentActivations
2124
+ .map(toMediaChange)
2125
+ .map(mergeMQAlias)
2126
+ .sort(sortDescendingPriority);
2127
+ this.cacheRegistryMatches();
2128
+ }
2129
+ }
2130
+ /**
2131
+ * Force set manual activations for specified mediaQuery list
2132
+ */
2133
+ setActivations(list) {
2134
+ if (!!this.originalRegistry) {
2135
+ this.forceRegistryMatches(list, true);
2136
+ }
2137
+ this.simulateMediaChanges(list);
2138
+ }
2139
+ /**
2140
+ * For specified mediaQuery list manually simulate activations or deactivations
2141
+ */
2142
+ simulateMediaChanges(queries, matches = true) {
2143
+ const toMediaQuery = (query) => {
2144
+ const locator = this.breakpoints;
2145
+ const bp = locator.findByAlias(query) || locator.findByQuery(query);
2146
+ return bp ? bp.mediaQuery : query;
2147
+ };
2148
+ const emitChangeEvent = (query) => this.emitChangeEvent(matches, query);
2149
+ queries.map(toMediaQuery).forEach(emitChangeEvent);
2150
+ }
2151
+ /**
2152
+ * Replace current registry with simulated registry...
2153
+ * Note: this is required since MediaQueryList::matches is 'readOnly'
2154
+ */
2155
+ forceRegistryMatches(queries, matches) {
2156
+ const registry = new Map();
2157
+ queries.forEach(query => {
2158
+ registry.set(query, { matches });
2159
+ });
2160
+ this.matchMedia.registry = registry;
2161
+ }
2162
+ /**
2163
+ * Save current MatchMedia::registry items.
2164
+ */
2165
+ cacheRegistryMatches() {
2166
+ const target = this.originalRegistry;
2167
+ target.clear();
2168
+ this.matchMedia.registry.forEach((value, key) => {
2169
+ target.set(key, value);
2170
+ });
2171
+ this.hasCachedRegistryMatches = true;
2172
+ }
2173
+ /**
2174
+ * Restore original, 'true' registry
2175
+ */
2176
+ restoreRegistryMatches() {
2177
+ const target = this.matchMedia.registry;
2178
+ target.clear();
2179
+ this.originalRegistry.forEach((value, key) => {
2180
+ target.set(key, value);
2181
+ });
2182
+ this.originalRegistry.clear();
2183
+ this.hasCachedRegistryMatches = false;
2184
+ }
2185
+ /**
2186
+ * Manually emit a MediaChange event via the MatchMedia to MediaMarshaller and MediaObserver
2187
+ */
2188
+ emitChangeEvent(matches, query) {
2189
+ this.matchMedia.source.next(new MediaChange(matches, query));
2190
+ }
2191
+ get currentActivations() {
2192
+ return this.matchMedia.activations;
2193
+ }
2194
+ }
2195
+ MediaTrigger.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: MediaTrigger, deps: [{ token: BreakPointRegistry }, { token: MatchMedia }, { token: LAYOUT_CONFIG }, { token: PLATFORM_ID }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
2196
+ MediaTrigger.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: MediaTrigger, providedIn: 'root' });
2197
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: MediaTrigger, decorators: [{
2198
+ type: Injectable,
2199
+ args: [{ providedIn: 'root' }]
2200
+ }], ctorParameters: function () { return [{ type: BreakPointRegistry }, { type: MatchMedia }, { type: undefined, decorators: [{
2201
+ type: Inject,
2202
+ args: [LAYOUT_CONFIG]
2203
+ }] }, { type: Object, decorators: [{
2204
+ type: Inject,
2205
+ args: [PLATFORM_ID]
2206
+ }] }, { type: undefined, decorators: [{
2207
+ type: Inject,
2208
+ args: [DOCUMENT]
2209
+ }] }]; } });
2210
+
2211
+ /**
2212
+ * @license
2213
+ * Copyright Google LLC All Rights Reserved.
2214
+ *
2215
+ * Use of this source code is governed by an MIT-style license that can be
2216
+ * found in the LICENSE file at https://angular.io/license
2217
+ */
2218
+
2219
+ /**
2220
+ * @license
2221
+ * Copyright Google LLC All Rights Reserved.
2222
+ *
2223
+ * Use of this source code is governed by an MIT-style license that can be
2224
+ * found in the LICENSE file at https://angular.io/license
2225
+ */
2226
+
2227
+ /**
2228
+ * @license
2229
+ * Copyright Google LLC All Rights Reserved.
2230
+ *
2231
+ * Use of this source code is governed by an MIT-style license that can be
2232
+ * found in the LICENSE file at https://angular.io/license
2233
+ */
2234
+ /**
2235
+ * The flex API permits 3 or 1 parts of the value:
2236
+ * - `flex-grow flex-shrink flex-basis`, or
2237
+ * - `flex-basis`
2238
+ */
2239
+ function validateBasis(basis, grow = '1', shrink = '1') {
2240
+ let parts = [grow, shrink, basis];
2241
+ let j = basis.indexOf('calc');
2242
+ if (j > 0) {
2243
+ parts[2] = _validateCalcValue(basis.substring(j).trim());
2244
+ let matches = basis.substr(0, j).trim().split(' ');
2245
+ if (matches.length == 2) {
2246
+ parts[0] = matches[0];
2247
+ parts[1] = matches[1];
2248
+ }
2249
+ }
2250
+ else if (j == 0) {
2251
+ parts[2] = _validateCalcValue(basis.trim());
2252
+ }
2253
+ else {
2254
+ let matches = basis.split(' ');
2255
+ parts = (matches.length === 3) ? matches : [
2256
+ grow, shrink, basis
2257
+ ];
2258
+ }
2259
+ return parts;
2260
+ }
2261
+ /**
2262
+ * Calc expressions require whitespace before & after any expression operators
2263
+ * This is a simple, crude whitespace padding solution.
2264
+ * - '3 3 calc(15em + 20px)'
2265
+ * - calc(100% / 7 * 2)
2266
+ * - 'calc(15em + 20px)'
2267
+ * - 'calc(15em+20px)'
2268
+ * - '37px'
2269
+ * = '43%'
2270
+ */
2271
+ function _validateCalcValue(calc) {
2272
+ return calc.replace(/[\s]/g, '').replace(/[\/\*\+\-]/g, ' $& ');
2273
+ }
2274
+
2275
+ const MULTIPLIER_SUFFIX = 'x';
2276
+ function multiply(value, multiplier) {
2277
+ if (multiplier === undefined) {
2278
+ return value;
2279
+ }
2280
+ const transformValue = (possibleValue) => {
2281
+ const numberValue = +(possibleValue.slice(0, -MULTIPLIER_SUFFIX.length));
2282
+ if (value.endsWith(MULTIPLIER_SUFFIX) && !isNaN(numberValue)) {
2283
+ return `${numberValue * multiplier.value}${multiplier.unit}`;
2284
+ }
2285
+ return value;
2286
+ };
2287
+ return value.includes(' ') ?
2288
+ value.split(' ').map(transformValue).join(' ') : transformValue(value);
2289
+ }
2290
+
2291
+ /**
2292
+ * @license
2293
+ * Copyright Google LLC All Rights Reserved.
2294
+ *
2295
+ * Use of this source code is governed by an MIT-style license that can be
2296
+ * found in the LICENSE file at https://angular.io/license
2297
+ */
2298
+
2299
+ /**
2300
+ * Generated bundle index. Do not edit.
2301
+ */
2302
+
2303
+ export { BREAKPOINT, BREAKPOINTS, BREAKPOINT_PRINT, BROWSER_PROVIDER, BaseDirective2, BreakPointRegistry, CLASS_NAME, CoreModule, DEFAULT_BREAKPOINTS, DEFAULT_CONFIG, LAYOUT_CONFIG, MediaChange, MediaMarshaller, MediaObserver, MediaTrigger, ORIENTATION_BREAKPOINTS, PrintHook, SERVER_TOKEN, ScreenTypes, StyleBuilder, StyleUtils, StylesheetMap, coerceArray, mergeAlias, removeStyles, sortAscendingPriority, sortDescendingPriority, validateBasis, MatchMedia as ɵMatchMedia, MockMatchMedia as ɵMockMatchMedia, MockMatchMediaProvider as ɵMockMatchMediaProvider, multiply as ɵmultiply };
2304
+ //# sourceMappingURL=angular-flex-layout-core.mjs.map