@ssv/ngx.ux 2.1.2 → 3.0.0-dev.34

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 (79) hide show
  1. package/README.md +28 -114
  2. package/eslint.config.js +43 -0
  3. package/index.ts +1 -0
  4. package/jest.config.ts +21 -0
  5. package/ng-package.json +7 -0
  6. package/package.json +4 -30
  7. package/project.json +36 -0
  8. package/src/index.ts +4 -0
  9. package/src/internal/internal.model.ts +3 -0
  10. package/src/platform/window.ts +31 -0
  11. package/src/test-setup.ts +8 -0
  12. package/src/ux.module.ts +15 -0
  13. package/src/version.ts +1 -0
  14. package/src/viewport/index.ts +20 -0
  15. package/src/viewport/viewport-data/README.md +47 -0
  16. package/src/viewport/viewport-data/index.ts +3 -0
  17. package/src/viewport/viewport-data/viewport-data-matcher.spec.ts +227 -0
  18. package/src/viewport/viewport-data/viewport-data-matcher.ts +175 -0
  19. package/src/viewport/viewport-data/viewport-data.pipe.ts +51 -0
  20. package/src/viewport/viewport-data/viewport-data.service.ts +48 -0
  21. package/src/viewport/viewport-data/viewport-data.utils.spec.ts +228 -0
  22. package/src/viewport/viewport-data/viewport-data.utils.ts +137 -0
  23. package/src/viewport/viewport-matcher-var.directive.ts +85 -0
  24. package/src/viewport/viewport-matcher.directive.ts +170 -0
  25. package/src/viewport/viewport-server-size.service.ts +37 -0
  26. package/src/viewport/viewport.model.ts +54 -0
  27. package/src/viewport/viewport.module.ts +19 -0
  28. package/src/viewport/viewport.options.ts +74 -0
  29. package/src/viewport/viewport.service.ts +123 -0
  30. package/src/viewport/viewport.util.spec.ts +254 -0
  31. package/src/viewport/viewport.util.ts +152 -0
  32. package/tsconfig.json +28 -0
  33. package/tsconfig.lib.json +12 -0
  34. package/tsconfig.lib.prod.json +9 -0
  35. package/tsconfig.spec.json +11 -0
  36. package/LICENSE +0 -21
  37. package/config.d.ts +0 -7
  38. package/esm2020/config.mjs +0 -7
  39. package/esm2020/index.mjs +0 -5
  40. package/esm2020/internal/internal.model.mjs +0 -2
  41. package/esm2020/module.mjs +0 -65
  42. package/esm2020/platform/window.mjs +0 -30
  43. package/esm2020/ssv-ngx.ux.mjs +0 -5
  44. package/esm2020/version.mjs +0 -2
  45. package/esm2020/viewport/index.mjs +0 -9
  46. package/esm2020/viewport/viewport-data/index.mjs +0 -4
  47. package/esm2020/viewport/viewport-data/viewport-data-matcher.mjs +0 -108
  48. package/esm2020/viewport/viewport-data/viewport-data.pipe.mjs +0 -43
  49. package/esm2020/viewport/viewport-data/viewport-data.service.mjs +0 -37
  50. package/esm2020/viewport/viewport-data/viewport-data.utils.mjs +0 -100
  51. package/esm2020/viewport/viewport-matcher-var.directive.mjs +0 -63
  52. package/esm2020/viewport/viewport-matcher.directive.mjs +0 -131
  53. package/esm2020/viewport/viewport-server-size.service.mjs +0 -43
  54. package/esm2020/viewport/viewport.const.mjs +0 -17
  55. package/esm2020/viewport/viewport.model.mjs +0 -30
  56. package/esm2020/viewport/viewport.service.mjs +0 -66
  57. package/esm2020/viewport/viewport.util.mjs +0 -117
  58. package/fesm2015/ssv-ngx.ux.mjs +0 -826
  59. package/fesm2015/ssv-ngx.ux.mjs.map +0 -1
  60. package/fesm2020/ssv-ngx.ux.mjs +0 -820
  61. package/fesm2020/ssv-ngx.ux.mjs.map +0 -1
  62. package/index.d.ts +0 -4
  63. package/internal/internal.model.d.ts +0 -9
  64. package/module.d.ts +0 -19
  65. package/platform/window.d.ts +0 -13
  66. package/version.d.ts +0 -1
  67. package/viewport/index.d.ts +0 -8
  68. package/viewport/viewport-data/index.d.ts +0 -3
  69. package/viewport/viewport-data/viewport-data-matcher.d.ts +0 -32
  70. package/viewport/viewport-data/viewport-data.pipe.d.ts +0 -18
  71. package/viewport/viewport-data/viewport-data.service.d.ts +0 -20
  72. package/viewport/viewport-data/viewport-data.utils.d.ts +0 -21
  73. package/viewport/viewport-matcher-var.directive.d.ts +0 -25
  74. package/viewport/viewport-matcher.directive.d.ts +0 -33
  75. package/viewport/viewport-server-size.service.d.ts +0 -12
  76. package/viewport/viewport.const.d.ts +0 -5
  77. package/viewport/viewport.model.d.ts +0 -59
  78. package/viewport/viewport.service.d.ts +0 -37
  79. package/viewport/viewport.util.d.ts +0 -25
@@ -1,826 +0,0 @@
1
- import * as i0 from '@angular/core';
2
- import { InjectionToken, Injectable, Inject, Optional, Pipe, Directive, Input, NgModule } from '@angular/core';
3
- import { map, share, auditTime, startWith, distinctUntilChanged, shareReplay, tap, takeUntil, filter, pairwise } from 'rxjs/operators';
4
- import { fromEvent, of, Subscription, Subject, ReplaySubject, combineLatest } from 'rxjs';
5
-
6
- var ViewportDataMatchStrategy;
7
- (function (ViewportDataMatchStrategy) {
8
- /** Indicates that size should match exact or default. */
9
- ViewportDataMatchStrategy[ViewportDataMatchStrategy["exact"] = 0] = "exact";
10
- /** Indicates that size matches when exact match, first match smaller (down) or default. */
11
- ViewportDataMatchStrategy[ViewportDataMatchStrategy["smaller"] = 1] = "smaller";
12
- /** Indicates that size matches when exact match, first match larger (up) or default. */
13
- ViewportDataMatchStrategy[ViewportDataMatchStrategy["larger"] = 2] = "larger";
14
- /** Indicates that size matches when exact match, or it tries both smaller/larger (smaller is preferred) until match or default. */
15
- ViewportDataMatchStrategy[ViewportDataMatchStrategy["closestSmallerFirst"] = 3] = "closestSmallerFirst";
16
- /** Indicates that size matches when exact match, or it tries both larger/smaller (larger is preferred) until match or default. */
17
- ViewportDataMatchStrategy[ViewportDataMatchStrategy["closestLargerFirst"] = 4] = "closestLargerFirst";
18
- })(ViewportDataMatchStrategy || (ViewportDataMatchStrategy = {}));
19
- /**
20
- * Utility function to match data based on strategy and size.
21
- *
22
- * @param dataConfig Data config to generate rules based on.
23
- * @param sizeType Size type to get data for.
24
- * @param strategy Strategy to use when building rules.
25
- * @param sizeTypes Available size types ordered by index type. (Can be obtained from `ViewportService`)
26
- * @param sizeTypeMap Available size type map. (Can be obtained from `ViewportService`)
27
- * @returns Returns the matched data value.
28
- */
29
- function matchViewportData(dataConfig, sizeType, strategy, sizeTypes, sizeTypeMap) {
30
- const matchFn = matchStrategyHandlerMap$1[strategy];
31
- if (!matchFn) {
32
- throw Error(`matchViewportData: Viewport Data strategy not implemented. Strategy: '${strategy}'`);
33
- }
34
- const data = matchFn(dataConfig, sizeType, sizeTypes, sizeTypeMap);
35
- if (data !== undefined) {
36
- return data;
37
- }
38
- return dataConfig.default;
39
- }
40
- const matchStrategyHandlerMap$1 = {
41
- [ViewportDataMatchStrategy.exact]: matchWithExact,
42
- [ViewportDataMatchStrategy.larger]: matchWithLargerMatch,
43
- [ViewportDataMatchStrategy.smaller]: matchWithSmallerMatch,
44
- [ViewportDataMatchStrategy.closestSmallerFirst]: matchWithClosestSmallerFirstMatch,
45
- [ViewportDataMatchStrategy.closestLargerFirst]: matchWithClosestLargerFirstMatch,
46
- };
47
- function matchWithExact(dataConfig, currentSizeType) {
48
- return dataConfig[currentSizeType.name];
49
- }
50
- function matchWithLargerMatch(dataConfig, currentSizeType, sizeTypes) {
51
- let data = dataConfig[currentSizeType.name];
52
- if (data !== undefined) {
53
- return data;
54
- }
55
- const largestTypeIdx = sizeTypes[sizeTypes.length - 1].type;
56
- if (currentSizeType.type >= largestTypeIdx) {
57
- return undefined;
58
- }
59
- for (let index = currentSizeType.type; index < sizeTypes.length; index++) {
60
- const sizeType = sizeTypes[index];
61
- data = dataConfig[sizeType.name];
62
- if (data !== undefined) {
63
- return data;
64
- }
65
- }
66
- return undefined;
67
- }
68
- function matchWithSmallerMatch(dataConfig, currentSizeType, sizeTypes) {
69
- let data = dataConfig[currentSizeType.name];
70
- if (data !== undefined) {
71
- return data;
72
- }
73
- if (currentSizeType.type <= 0) {
74
- return undefined;
75
- }
76
- // eslint-disable-next-line for-direction
77
- for (let index = currentSizeType.type; index < sizeTypes.length; index--) {
78
- const sizeType = sizeTypes[index];
79
- data = dataConfig[sizeType.name];
80
- if (data !== undefined) {
81
- return data;
82
- }
83
- }
84
- return undefined;
85
- }
86
- function matchWithClosestSmallerFirstMatch(dataConfig, currentSizeType, sizeTypes) {
87
- return closestMatch(dataConfig, currentSizeType, sizeTypes, true);
88
- }
89
- function matchWithClosestLargerFirstMatch(dataConfig, currentSizeType, sizeTypes) {
90
- return closestMatch(dataConfig, currentSizeType, sizeTypes, false);
91
- }
92
- function closestMatch(dataConfig, currentSizeType, sizeTypes, isSmallerFirst) {
93
- let data = dataConfig[currentSizeType.name];
94
- if (data !== undefined) {
95
- return data;
96
- }
97
- let downIndex = currentSizeType.type;
98
- let upIndex = currentSizeType.type;
99
- // eslint-disable-next-line @typescript-eslint/prefer-for-of
100
- for (let index = 0; index < sizeTypes.length; index++) {
101
- for (const idx of isSmallerFirst ? [--downIndex, ++upIndex] : [++upIndex, --downIndex]) {
102
- const sizeType = sizeTypes[idx];
103
- if (sizeType) {
104
- data = dataConfig[sizeType.name];
105
- if (data !== undefined) {
106
- return data;
107
- }
108
- }
109
- }
110
- }
111
- return undefined;
112
- }
113
-
114
- /** Default viewport breakpoints. */
115
- const UX_VIEWPORT_DEFAULT_BREAKPOINTS = {
116
- xsmall: 450,
117
- small: 767,
118
- medium: 992,
119
- large: 1200,
120
- xlarge: 1500,
121
- xxlarge: 1920,
122
- xxlarge1: 2100,
123
- };
124
- const UX_VIEWPORT_DEFAULT_CONFIG = {
125
- resizePollingSpeed: 33,
126
- breakpoints: UX_VIEWPORT_DEFAULT_BREAKPOINTS,
127
- defaultDataMatchStrategy: ViewportDataMatchStrategy.smaller,
128
- };
129
-
130
- const UX_DEFAULT_CONFIG = {
131
- viewport: UX_VIEWPORT_DEFAULT_CONFIG,
132
- };
133
- const UX_CONFIG = new InjectionToken("@ssv/ngx.ux-config");
134
-
135
- /**
136
- * Utility function to generate rules based on strategies.
137
- *
138
- * @param dataConfig Data config to generate rules based on.
139
- * @param strategy Strategy to use when building rules.
140
- * @param sizeTypes Available size types ordered by index type. (Can be obtained from `ViewportService`)
141
- * @param sizeTypeMap Available size type map. (Can be obtained from `ViewportService`)
142
- * @returns Returns a collection of rules (ordered).
143
- */
144
- function generateViewportRulesRangeFromDataMatcher(dataConfig, strategy, sizeTypes, sizeTypeMap) {
145
- const ruleBuilderFn = matchStrategyHandlerMap[strategy];
146
- if (!ruleBuilderFn) {
147
- throw Error(`generateViewportRulesRangeFromDataMatcher: Viewport Data strategy not implemented. Strategy: '${strategy}'`);
148
- }
149
- let dataSizes = [];
150
- for (const key in dataConfig) {
151
- if (Object.prototype.hasOwnProperty.call(dataConfig, key)) {
152
- const data = dataConfig[key];
153
- if (data === undefined) {
154
- continue;
155
- }
156
- const size = sizeTypeMap[key];
157
- if (size) {
158
- dataSizes.push(size);
159
- }
160
- }
161
- }
162
- dataSizes = dataSizes.sort(({ type: typeA }, { type: typeB }) => typeA - typeB);
163
- const rules = [];
164
- if (dataConfig.default) {
165
- rules.push({ value: dataConfig.default, min: undefined, max: undefined });
166
- }
167
- let prevRule;
168
- for (let index = 0; index < dataSizes.length; index++) {
169
- const prevDataSize = dataSizes[index - 1];
170
- const nextDataSize = dataSizes[index + 1];
171
- const dataSize = dataSizes[index];
172
- const prevSize = sizeTypes[dataSize.type - 1];
173
- // const nextSize = sizeTypes[dataSize.type + 1];
174
- const data = dataConfig[dataSize.name];
175
- const rule = {
176
- value: data,
177
- min: undefined,
178
- max: undefined,
179
- };
180
- ruleBuilderFn(rule, dataSize, nextDataSize, prevDataSize, prevSize, prevRule, sizeTypes);
181
- prevRule = rule;
182
- rules.push(rule);
183
- }
184
- return rules;
185
- }
186
- const matchStrategyHandlerMap = {
187
- [ViewportDataMatchStrategy.exact]: (rule, dataSize, _nextDataSize, _prevDataSize, prevSize) => {
188
- rule.max = dataSize.widthThreshold;
189
- if (prevSize) {
190
- rule.min = prevSize.widthThreshold + 1;
191
- }
192
- },
193
- [ViewportDataMatchStrategy.smaller]: (rule, dataSize, nextDataSize, _prevDataSize, prevSize) => {
194
- if (nextDataSize) {
195
- rule.max = dataSize.widthThreshold;
196
- }
197
- if (prevSize) {
198
- rule.min = prevSize.widthThreshold + 1;
199
- }
200
- },
201
- [ViewportDataMatchStrategy.larger]: (rule, dataSize, _nextDataSize, prevDataSize) => {
202
- if (dataSize) {
203
- rule.max = dataSize.widthThreshold;
204
- }
205
- if (prevDataSize) {
206
- rule.min = prevDataSize.widthThreshold + 1;
207
- }
208
- },
209
- [ViewportDataMatchStrategy.closestSmallerFirst]: (rule, dataSize, nextDataSize, _prevDataSize, _prevSize, prevRule, sizeTypes) => {
210
- if (nextDataSize) {
211
- rule.max = calculateClosestWidthThreshold(nextDataSize, dataSize, sizeTypes, true);
212
- }
213
- if (prevRule === null || prevRule === void 0 ? void 0 : prevRule.max) {
214
- rule.min = prevRule.max + 1;
215
- }
216
- },
217
- [ViewportDataMatchStrategy.closestLargerFirst]: (rule, dataSize, nextDataSize, _prevDataSize, _prevSize, prevRule, sizeTypes) => {
218
- if (nextDataSize) {
219
- rule.max = calculateClosestWidthThreshold(nextDataSize, dataSize, sizeTypes, false);
220
- }
221
- if (prevRule === null || prevRule === void 0 ? void 0 : prevRule.max) {
222
- rule.min = prevRule.max + 1;
223
- }
224
- },
225
- };
226
- function calculateClosestWidthThreshold(nextDataSize, dataSize, sizeTypes, isSmallerPreferred) {
227
- const fn = isSmallerPreferred ? Math.ceil : Math.floor;
228
- // get closest between curr and next
229
- const diffIndex = fn((nextDataSize.type - dataSize.type - 1) / 2);
230
- const diffNextSize = sizeTypes[dataSize.type + diffIndex];
231
- return (diffNextSize || dataSize).widthThreshold;
232
- }
233
-
234
- /**
235
- * The indices of each breakpoint provided based on the `UX_VIEWPORT_DEFAULT_BREAKPOINTS`.
236
- * @see UX_VIEWPORT_DEFAULT_BREAKPOINTS
237
- */
238
- var ViewportSizeType;
239
- (function (ViewportSizeType) {
240
- ViewportSizeType[ViewportSizeType["xsmall"] = 0] = "xsmall";
241
- ViewportSizeType[ViewportSizeType["small"] = 1] = "small";
242
- ViewportSizeType[ViewportSizeType["medium"] = 2] = "medium";
243
- ViewportSizeType[ViewportSizeType["large"] = 3] = "large";
244
- ViewportSizeType[ViewportSizeType["xlarge"] = 4] = "xlarge";
245
- ViewportSizeType[ViewportSizeType["xxlarge"] = 5] = "xxlarge";
246
- ViewportSizeType[ViewportSizeType["xxlarge1"] = 6] = "xxlarge1";
247
- })(ViewportSizeType || (ViewportSizeType = {}));
248
- var ComparisonOperation;
249
- (function (ComparisonOperation) {
250
- ComparisonOperation["equals"] = "=";
251
- ComparisonOperation["notEquals"] = "<>";
252
- ComparisonOperation["lessThan"] = "<";
253
- ComparisonOperation["lessOrEqualThan"] = "<=";
254
- ComparisonOperation["greaterThan"] = ">";
255
- ComparisonOperation["greaterOrEqualThan"] = ">=";
256
- })(ComparisonOperation || (ComparisonOperation = {}));
257
- var DeviceType;
258
- (function (DeviceType) {
259
- DeviceType["desktop"] = "desktop";
260
- DeviceType["mobile"] = "mobile";
261
- DeviceType["tablet"] = "tablet";
262
- })(DeviceType || (DeviceType = {}));
263
-
264
- function isViewportSizeMatcherExpression(value) {
265
- if (typeof value !== "object" || !value) {
266
- return false;
267
- }
268
- const args = value;
269
- if (args.size && args.operation) {
270
- return true;
271
- }
272
- return false;
273
- }
274
- function isViewportSizeMatcherTupleExpression(arg) {
275
- if (!arg) {
276
- return false;
277
- }
278
- if (Array.isArray(arg)) {
279
- if (arg.length === 2) {
280
- const [op] = arg;
281
- return operations.includes(op);
282
- }
283
- }
284
- return false;
285
- }
286
- const operations = Object.values(ComparisonOperation);
287
- const COMPARISON_OPERATION_FUNC_MAPPING = {
288
- [ComparisonOperation.equals]: (a, b) => a === b,
289
- [ComparisonOperation.notEquals]: (a, b) => a !== b,
290
- [ComparisonOperation.lessThan]: (a, b) => a < b,
291
- [ComparisonOperation.lessOrEqualThan]: (a, b) => a <= b,
292
- [ComparisonOperation.greaterThan]: (a, b) => a > b,
293
- [ComparisonOperation.greaterOrEqualThan]: (a, b) => a >= b,
294
- };
295
- function isViewportConditionMatch(evaluateSize, conditions, viewportSizeTypeInfoRefs) {
296
- const isExcluded = match(conditions.sizeTypeExclude, evaluateSize.name, false);
297
- let isIncluded;
298
- let isExpressionTruthy;
299
- if (!isExcluded && conditions.expression) {
300
- const ref = viewportSizeTypeInfoRefs[conditions.expression.size];
301
- if (!ref) {
302
- throw new Error(`Viewport size type is invalid. Size type: '${conditions.expression.size}'`);
303
- }
304
- const expMatcher = COMPARISON_OPERATION_FUNC_MAPPING[conditions.expression.operation];
305
- isExpressionTruthy = expMatcher(evaluateSize.type, ref.type);
306
- }
307
- else {
308
- isIncluded = match(conditions.sizeType, evaluateSize.name, true);
309
- }
310
- const shouldRender = (isExpressionTruthy || isIncluded) && !isExcluded;
311
- // console.warn(">>> shouldRender", { evaluateSize, conditions, shouldRender });
312
- return !!shouldRender;
313
- }
314
- function match(value, targetValue, defaultValue) {
315
- if (!value) {
316
- return defaultValue;
317
- }
318
- return Array.isArray(value)
319
- ? value.includes(targetValue)
320
- : value === targetValue;
321
- }
322
- function getSizeTypeInfo(width, sizeTypes) {
323
- const lastEntryIndex = sizeTypes.length - 1;
324
- for (let idx = 0; idx < lastEntryIndex; idx++) {
325
- const viewportSizeTypeInfo = sizeTypes[idx];
326
- if (width <= viewportSizeTypeInfo.widthThreshold) {
327
- return viewportSizeTypeInfo;
328
- }
329
- }
330
- return sizeTypes[lastEntryIndex];
331
- }
332
- /**
333
- * Converts the breakpoints into a 2 dimensional array containing the name and width, and sorted from
334
- * smallest to largest.
335
- * @param breakpoints the breakpoints obtained from the config
336
- * @internal
337
- */
338
- function getSortedBreakpoints(breakpoints) {
339
- return Object.entries(breakpoints)
340
- .sort(([, widthA], [, widthB]) => widthA - widthB);
341
- }
342
- /**
343
- * A util function which generates the ViewportSizeTypeInfo.type for each breakpoint.
344
- * @param breakpoints the custom breakpoints
345
- */
346
- function generateViewportSizeType(breakpoints) {
347
- return Object.freeze(getSortedBreakpoints(breakpoints).reduce((dictionary, [name], index) => {
348
- dictionary[name] = index;
349
- dictionary[index] = name;
350
- return dictionary;
351
- }, {}));
352
- }
353
- /**
354
- * Pre-processes the given breakpoints into an ordered list from smallest to largest while generating
355
- * all the necessary information on the viewport.
356
- * @param breakpoints the breakpoints obtained from the config
357
- * @internal
358
- */
359
- function generateViewportSizeTypeInfoList(breakpoints) {
360
- return getSortedBreakpoints(breakpoints)
361
- .map(([name, width], index) => (Object.freeze({
362
- name,
363
- type: index,
364
- widthThreshold: width
365
- })));
366
- }
367
- /**
368
- * Converts the breakpoint list into a dictionary while using the name as key.
369
- * @param breakpointList the list of breakpoints
370
- * @internal
371
- */
372
- function generateViewportSizeTypeInfoRefs(breakpointList) {
373
- return Object.freeze(breakpointList.reduce((dictionary, breakpoint) => {
374
- dictionary[breakpoint.name] = breakpoint;
375
- dictionary[breakpoint.type] = breakpoint;
376
- return dictionary;
377
- }, {}));
378
- }
379
-
380
- const WINDOW = new InjectionToken("Window");
381
- class WindowRef {
382
- constructor(
383
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
384
- window) {
385
- this.window = window;
386
- }
387
- /** Window underlying native object. */
388
- get native() {
389
- return this.window;
390
- }
391
- /** Determines whether native element is supported or not. Generally `false` when executing in SSR. */
392
- get hasNative() {
393
- return !!this.native.window;
394
- }
395
- }
396
- WindowRef.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: WindowRef, deps: [{ token: WINDOW }], target: i0.ɵɵFactoryTarget.Injectable });
397
- WindowRef.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: WindowRef, providedIn: "root" });
398
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: WindowRef, decorators: [{
399
- type: Injectable,
400
- args: [{
401
- providedIn: "root",
402
- }]
403
- }], ctorParameters: function () {
404
- return [{ type: undefined, decorators: [{
405
- type: Inject,
406
- args: [WINDOW]
407
- }] }];
408
- } });
409
-
410
- // todo: make this configurable
411
- /** Viewport size for SSR. */
412
- const viewportSizeSSR = {
413
- [DeviceType.desktop]: {
414
- width: 1366,
415
- height: 768,
416
- },
417
- [DeviceType.tablet]: {
418
- width: 768,
419
- height: 1024,
420
- },
421
- [DeviceType.mobile]: {
422
- width: 414,
423
- height: 736,
424
- },
425
- };
426
- const UX_VIEWPORT_SSR_DEVICE = new InjectionToken("@ssv/ngx.ux-config/viewport/ssr-device");
427
- class ViewportServerSizeService {
428
- constructor(deviceType) {
429
- this.deviceType = deviceType;
430
- }
431
- get() {
432
- return viewportSizeSSR[this.deviceType] || viewportSizeSSR[DeviceType.desktop];
433
- }
434
- }
435
- ViewportServerSizeService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ViewportServerSizeService, deps: [{ token: UX_VIEWPORT_SSR_DEVICE, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
436
- ViewportServerSizeService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ViewportServerSizeService, providedIn: "root" });
437
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ViewportServerSizeService, decorators: [{
438
- type: Injectable,
439
- args: [{
440
- providedIn: "root",
441
- }]
442
- }], ctorParameters: function () {
443
- return [{ type: DeviceType, decorators: [{
444
- type: Optional
445
- }, {
446
- type: Inject,
447
- args: [UX_VIEWPORT_SSR_DEVICE]
448
- }] }];
449
- } });
450
-
451
- class ViewportService {
452
- constructor(windowRef, viewportServerSize, config) {
453
- this.windowRef = windowRef;
454
- this.viewportServerSize = viewportServerSize;
455
- this._sizeTypes = generateViewportSizeTypeInfoList(config.viewport.breakpoints);
456
- this._sizeTypeMap = generateViewportSizeTypeInfoRefs(this._sizeTypes);
457
- if (windowRef.hasNative) {
458
- this.resizeSnap$ = fromEvent(window, "resize").pipe(map(() => this.getViewportSize()), share());
459
- this.resize$ = this.resizeSnap$.pipe(auditTime(config.viewport.resizePollingSpeed), share());
460
- }
461
- else {
462
- this.resizeSnap$ = this.resize$ = of(viewportServerSize.get());
463
- }
464
- const size = this.getViewportSize();
465
- this._sizeTypeSnapshot = getSizeTypeInfo(size.width, this.sizeTypes);
466
- const sizeFn = (obs$) => obs$.pipe(startWith(size), distinctUntilChanged((a, b) => a.width === b.width && a.height === b.height), shareReplay(1));
467
- this.sizeSnap$ = sizeFn(this.resizeSnap$);
468
- this.size$ = sizeFn(this.resize$);
469
- const sizeTypeFn = (obs$) => obs$.pipe(distinctUntilChanged((a, b) => a.width === b.width), map(x => getSizeTypeInfo(x.width, this.sizeTypes)), distinctUntilChanged(), tap(x => this._sizeTypeSnapshot = x), shareReplay(1));
470
- this.sizeType$ = sizeTypeFn(this.size$);
471
- this.sizeTypeSnap$ = sizeTypeFn(this.sizeSnap$);
472
- }
473
- /** Viewport size type snapshot of the last value. (Prefer use `sizeType$` observable when possible.) */
474
- get sizeTypeSnapshot() { return this._sizeTypeSnapshot; }
475
- /** Size types refs of the generated viewport size type info. */
476
- get sizeTypeMap() { return this._sizeTypeMap; }
477
- /** Viewport size types list ordered by type, smallest to largest. */
478
- get sizeTypes() { return this._sizeTypes; }
479
- /** Returns the current viewport size */
480
- getViewportSize() {
481
- if (!this.windowRef.hasNative) {
482
- return this.viewportServerSize.get();
483
- }
484
- const ua = navigator.userAgent.toLowerCase();
485
- if (ua.indexOf("safari") !== -1 && ua.indexOf("chrome") === -1) { // safari subtracts the scrollbar width
486
- return {
487
- width: this.windowRef.native.document.documentElement.clientWidth,
488
- height: this.windowRef.native.document.documentElement.clientHeight,
489
- };
490
- }
491
- return {
492
- width: this.windowRef.native.innerWidth,
493
- height: this.windowRef.native.innerHeight,
494
- };
495
- }
496
- }
497
- ViewportService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ViewportService, deps: [{ token: WindowRef }, { token: ViewportServerSizeService }, { token: UX_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable });
498
- ViewportService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ViewportService, providedIn: "root" });
499
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ViewportService, decorators: [{
500
- type: Injectable,
501
- args: [{
502
- providedIn: "root",
503
- }]
504
- }], ctorParameters: function () {
505
- return [{ type: WindowRef }, { type: ViewportServerSizeService }, { type: undefined, decorators: [{
506
- type: Inject,
507
- args: [UX_CONFIG]
508
- }] }];
509
- } });
510
-
511
- class ViewportDataService {
512
- constructor(viewport, config) {
513
- this.viewport = viewport;
514
- this.config = config;
515
- }
516
- /** Get data for match. */
517
- get(dataConfig, strategy = this.config.viewport.defaultDataMatchStrategy, sizeType = this.viewport.sizeTypeSnapshot) {
518
- return matchViewportData(dataConfig, sizeType, strategy, this.viewport.sizeTypes, this.viewport.sizeTypeMap);
519
- }
520
- /** Get data for match as observable. */
521
- get$(dataConfig, strategy, throttle = true) {
522
- return (throttle ? this.viewport.sizeType$ : this.viewport.sizeTypeSnap$).pipe(map(sizeType => this.get(dataConfig, strategy, sizeType)), distinctUntilChanged());
523
- }
524
- /** Generate rules based on strategies for data. */
525
- generateRules(dataConfig, strategy = this.config.viewport.defaultDataMatchStrategy) {
526
- return generateViewportRulesRangeFromDataMatcher(dataConfig, strategy, this.viewport.sizeTypes, this.viewport.sizeTypeMap);
527
- }
528
- }
529
- ViewportDataService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ViewportDataService, deps: [{ token: ViewportService }, { token: UX_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable });
530
- ViewportDataService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ViewportDataService, providedIn: "root" });
531
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ViewportDataService, decorators: [{
532
- type: Injectable,
533
- args: [{
534
- providedIn: "root",
535
- }]
536
- }], ctorParameters: function () {
537
- return [{ type: ViewportService }, { type: undefined, decorators: [{
538
- type: Inject,
539
- args: [UX_CONFIG]
540
- }] }];
541
- } });
542
-
543
- /* eslint-disable @angular-eslint/no-pipe-impure */
544
- class ViewportDataPipe {
545
- constructor(viewportData, cdr) {
546
- this.viewportData = viewportData;
547
- this.cdr = cdr;
548
- this.markForTransform = true;
549
- this.data$$ = Subscription.EMPTY;
550
- }
551
- transform(data, strategy) {
552
- if (!this.markForTransform && data === this.data && strategy === this.strategy) {
553
- return this.value;
554
- }
555
- this.data = data;
556
- this.strategy = strategy;
557
- this.data$$.unsubscribe();
558
- this.data$$ = this.viewportData.get$(data, ViewportDataMatchStrategy[strategy]).pipe(tap(value => {
559
- this.markForTransform = true;
560
- this.value = value;
561
- this.cdr.markForCheck();
562
- })).subscribe();
563
- this.markForTransform = false;
564
- return this.value;
565
- }
566
- ngOnDestroy() {
567
- this.data$$.unsubscribe();
568
- }
569
- }
570
- ViewportDataPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ViewportDataPipe, deps: [{ token: ViewportDataService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Pipe });
571
- ViewportDataPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "15.2.9", ngImport: i0, type: ViewportDataPipe, name: "ssvViewportData", pure: false });
572
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ViewportDataPipe, decorators: [{
573
- type: Pipe,
574
- args: [{
575
- name: "ssvViewportData",
576
- pure: false
577
- }]
578
- }], ctorParameters: function () { return [{ type: ViewportDataService }, { type: i0.ChangeDetectorRef }]; } });
579
-
580
- const NAME_CAMEL = "ssvViewportMatcherVar";
581
- class SsvViewportMatcherVarContext {
582
- constructor($implicit = false) {
583
- this.$implicit = $implicit;
584
- }
585
- }
586
- class SsvViewportMatcherVarDirective {
587
- constructor(viewport, viewContainer, templateRef) {
588
- this.viewport = viewport;
589
- this.viewContainer = viewContainer;
590
- this.templateRef = templateRef;
591
- this._matchConditions = {};
592
- this._context = new SsvViewportMatcherVarContext();
593
- this._destroy$ = new Subject();
594
- this._update$ = new ReplaySubject(1);
595
- }
596
- set condition(value) {
597
- if (isViewportSizeMatcherExpression(value)) {
598
- this._matchConditions.expression = value;
599
- }
600
- else if (isViewportSizeMatcherTupleExpression(value)) {
601
- const [op, size] = value;
602
- this._matchConditions.expression = {
603
- operation: op,
604
- size
605
- };
606
- }
607
- else {
608
- this._matchConditions.sizeType = value;
609
- }
610
- this._update$.next();
611
- }
612
- ngOnInit() {
613
- this.updateView();
614
- combineLatest([this.viewport.sizeType$, this._update$]).pipe(map(([sizeType]) => isViewportConditionMatch(sizeType, this._matchConditions, this.viewport.sizeTypeMap)), tap(x => this._context.$implicit = x), tap(() => this._viewRef.markForCheck()), takeUntil(this._destroy$)).subscribe();
615
- }
616
- ngOnDestroy() {
617
- this._destroy$.next();
618
- this._destroy$.complete();
619
- }
620
- updateView() {
621
- this.viewContainer.clear();
622
- this._viewRef = this.viewContainer.createEmbeddedView(this.templateRef, this._context);
623
- }
624
- }
625
- SsvViewportMatcherVarDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SsvViewportMatcherVarDirective, deps: [{ token: ViewportService }, { token: i0.ViewContainerRef }, { token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
626
- SsvViewportMatcherVarDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.9", type: SsvViewportMatcherVarDirective, selector: "[ssvViewportMatcherVar]", inputs: { condition: ["ssvViewportMatcherVarWhen", "condition"] }, ngImport: i0 });
627
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SsvViewportMatcherVarDirective, decorators: [{
628
- type: Directive,
629
- args: [{
630
- selector: `[${NAME_CAMEL}]`,
631
- }]
632
- }], ctorParameters: function () { return [{ type: ViewportService }, { type: i0.ViewContainerRef }, { type: i0.TemplateRef }]; }, propDecorators: { condition: [{
633
- type: Input,
634
- args: [`${NAME_CAMEL}When`]
635
- }] } });
636
-
637
- class SsvViewportMatcherContext {
638
- constructor() {
639
- this.sizeType = null;
640
- this.sizeTypeExclude = null;
641
- }
642
- }
643
- class SsvViewportMatcherDirective {
644
- constructor(viewport, renderer, viewContainer, cdr, templateRef) {
645
- this.viewport = viewport;
646
- this.renderer = renderer;
647
- this.viewContainer = viewContainer;
648
- this.cdr = cdr;
649
- this._context = new SsvViewportMatcherContext();
650
- this._thenTemplateRef = null;
651
- this._elseTemplateRef = null;
652
- this._thenViewRef = null;
653
- this._elseViewRef = null;
654
- this.sizeType$$ = Subscription.EMPTY;
655
- this.cssClass$$ = Subscription.EMPTY;
656
- this._update$ = new Subject();
657
- this._thenTemplateRef = templateRef;
658
- }
659
- set ssvViewportMatcher(value) {
660
- if (isViewportSizeMatcherExpression(value)) {
661
- this._context.expression = value;
662
- }
663
- else if (isViewportSizeMatcherTupleExpression(value)) {
664
- const [op, size] = value;
665
- this._context.expression = {
666
- operation: op,
667
- size
668
- };
669
- }
670
- else {
671
- this._context.sizeType = value;
672
- }
673
- if (this.sizeInfo) {
674
- this._update$.next(this._context);
675
- }
676
- }
677
- set ssvViewportMatcherExclude(value) {
678
- this._context.sizeTypeExclude = value;
679
- if (this.sizeInfo) {
680
- this._update$.next(this._context);
681
- }
682
- }
683
- set ssvViewportMatcherElse(templateRef) {
684
- this._elseTemplateRef = templateRef;
685
- this._elseViewRef = null; // clear previous view if any.
686
- if (this.sizeInfo) {
687
- this._update$.next(this._context);
688
- }
689
- }
690
- ngOnInit() {
691
- // console.log("ssvViewportMatcher init");
692
- this._update$
693
- .pipe(
694
- // tap(x => console.log(">>> ssvViewportMatcher - update triggered", x)),
695
- filter(() => !!this.sizeInfo),
696
- // tap(x => console.log(">>> ssvViewportMatcher - updating...", x)),
697
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
698
- tap(() => this._updateView(this.sizeInfo)), tap(() => this.cdr.markForCheck()))
699
- .subscribe();
700
- this.sizeType$$ = this.viewport.sizeType$
701
- .pipe(
702
- // tap(x => console.log("ssvViewportMatcher - sizeType changed", x)),
703
- tap(x => this.sizeInfo = x), tap(() => this._update$.next(this._context)))
704
- .subscribe();
705
- this.cssClass$$ = this.viewport.sizeType$
706
- .pipe(startWith(undefined), filter(() => !!(this._thenViewRef || this._elseViewRef)), pairwise(), tap(([prev, curr]) => {
707
- var _a;
708
- const el = this._thenViewRef
709
- ? this._thenViewRef.rootNodes[0]
710
- : (_a = this._elseViewRef) === null || _a === void 0 ? void 0 : _a.rootNodes[0];
711
- if (!el.classList) {
712
- return;
713
- }
714
- if (prev) {
715
- this.renderer.removeClass(el, `ssv-vp-size--${prev.name}`);
716
- }
717
- this.renderer.addClass(el, `ssv-vp-size--${curr === null || curr === void 0 ? void 0 : curr.name}`);
718
- }))
719
- .subscribe();
720
- }
721
- ngOnDestroy() {
722
- this.cssClass$$.unsubscribe();
723
- this.sizeType$$.unsubscribe();
724
- this._update$.complete();
725
- }
726
- _updateView(sizeInfo) {
727
- if (isViewportConditionMatch(sizeInfo, this._context, this.viewport.sizeTypeMap)) {
728
- if (!this._thenViewRef) {
729
- this.viewContainer.clear();
730
- this._elseViewRef = null;
731
- if (this._thenTemplateRef) {
732
- this._thenViewRef = this.viewContainer.createEmbeddedView(this._thenTemplateRef, this._context);
733
- }
734
- }
735
- }
736
- else {
737
- if (!this._elseViewRef) {
738
- this.viewContainer.clear();
739
- this._thenViewRef = null;
740
- if (this._elseTemplateRef) {
741
- this._elseViewRef = this.viewContainer.createEmbeddedView(this._elseTemplateRef, this._context);
742
- }
743
- }
744
- }
745
- }
746
- }
747
- SsvViewportMatcherDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SsvViewportMatcherDirective, deps: [{ token: ViewportService }, { token: i0.Renderer2 }, { token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }, { token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
748
- SsvViewportMatcherDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.9", type: SsvViewportMatcherDirective, selector: "[ssvViewportMatcher]", inputs: { ssvViewportMatcher: "ssvViewportMatcher", ssvViewportMatcherExclude: "ssvViewportMatcherExclude", ssvViewportMatcherElse: "ssvViewportMatcherElse" }, exportAs: ["ssvViewportMatcher"], ngImport: i0 });
749
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SsvViewportMatcherDirective, decorators: [{
750
- type: Directive,
751
- args: [{
752
- selector: "[ssvViewportMatcher]",
753
- exportAs: "ssvViewportMatcher",
754
- }]
755
- }], ctorParameters: function () { return [{ type: ViewportService }, { type: i0.Renderer2 }, { type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }, { type: i0.TemplateRef }]; }, propDecorators: { ssvViewportMatcher: [{
756
- type: Input
757
- }], ssvViewportMatcherExclude: [{
758
- type: Input
759
- }], ssvViewportMatcherElse: [{
760
- type: Input
761
- }] } });
762
-
763
- /** @internal */
764
- const MODULE_CONFIG_DATA = new InjectionToken("@ssv/ngx.ux/configData");
765
- const components = [
766
- SsvViewportMatcherDirective,
767
- SsvViewportMatcherVarDirective,
768
- ViewportDataPipe,
769
- ];
770
- // todo: create module for Viewport
771
- class SsvUxModule {
772
- static forRoot(config) {
773
- return {
774
- ngModule: SsvUxModule,
775
- providers: [
776
- { provide: MODULE_CONFIG_DATA, useValue: config },
777
- ],
778
- };
779
- }
780
- }
781
- SsvUxModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SsvUxModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
782
- SsvUxModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.9", ngImport: i0, type: SsvUxModule, declarations: [SsvViewportMatcherDirective,
783
- SsvViewportMatcherVarDirective,
784
- ViewportDataPipe], exports: [SsvViewportMatcherDirective,
785
- SsvViewportMatcherVarDirective,
786
- ViewportDataPipe] });
787
- SsvUxModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SsvUxModule, providers: [
788
- { provide: UX_CONFIG, useFactory: _moduleConfigFactory, deps: [[MODULE_CONFIG_DATA, new Optional()]] },
789
- { provide: WINDOW, useFactory: _window },
790
- ] });
791
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SsvUxModule, decorators: [{
792
- type: NgModule,
793
- args: [{
794
- declarations: [components],
795
- providers: [
796
- { provide: UX_CONFIG, useFactory: _moduleConfigFactory, deps: [[MODULE_CONFIG_DATA, new Optional()]] },
797
- { provide: WINDOW, useFactory: _window },
798
- ],
799
- exports: [...components],
800
- }]
801
- }] });
802
- /** @internal */
803
- function _moduleConfigFactory(config) {
804
- if (!config) {
805
- return UX_DEFAULT_CONFIG;
806
- }
807
- const uxOptions = typeof config === "function" ? config() : config;
808
- const viewport = Object.assign(Object.assign({}, UX_DEFAULT_CONFIG.viewport), uxOptions.viewport); // breakpoints shouldn't be merged
809
- return { viewport };
810
- }
811
- /** @internal */
812
- function _window() {
813
- if (typeof window !== "undefined") {
814
- return window;
815
- }
816
- return {};
817
- }
818
-
819
- const VERSION = "2.1.2";
820
-
821
- /**
822
- * Generated bundle index. Do not edit.
823
- */
824
-
825
- export { ComparisonOperation, DeviceType, MODULE_CONFIG_DATA, SsvUxModule, SsvViewportMatcherContext, SsvViewportMatcherDirective, SsvViewportMatcherVarContext, SsvViewportMatcherVarDirective, UX_CONFIG, UX_DEFAULT_CONFIG, UX_VIEWPORT_DEFAULT_BREAKPOINTS, UX_VIEWPORT_SSR_DEVICE, VERSION, ViewportDataMatchStrategy, ViewportDataPipe, ViewportDataService, ViewportServerSizeService, ViewportService, ViewportSizeType, _moduleConfigFactory, _window, generateViewportSizeType };
826
- //# sourceMappingURL=ssv-ngx.ux.mjs.map