@nativescript/core 8.8.0-embed.0 → 8.8.0-embed.1-next-07-01-2024-9752585063

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 (121) hide show
  1. package/application/application-common.d.ts +2 -1
  2. package/application/application-common.js +21 -7
  3. package/application/application-common.js.map +1 -1
  4. package/application/application.android.d.ts +1 -1
  5. package/application/application.android.js +1 -1
  6. package/application/application.android.js.map +1 -1
  7. package/application/application.ios.d.ts +1 -1
  8. package/application/application.ios.js +2 -2
  9. package/application/application.ios.js.map +1 -1
  10. package/config/config.interface.d.ts +6 -0
  11. package/css/parser.d.ts +0 -38
  12. package/css/parser.js +0 -108
  13. package/css/parser.js.map +1 -1
  14. package/css/reworkcss.d.ts +15 -1
  15. package/css/system-classes.d.ts +1 -0
  16. package/css/system-classes.js +1 -0
  17. package/css/system-classes.js.map +1 -1
  18. package/css-mediaquery/index.d.ts +27 -0
  19. package/css-mediaquery/index.js +118 -0
  20. package/css-mediaquery/index.js.map +1 -0
  21. package/globals/index.js +2 -0
  22. package/globals/index.js.map +1 -1
  23. package/media-query-list/index.d.ts +21 -0
  24. package/media-query-list/index.js +169 -0
  25. package/media-query-list/index.js.map +1 -0
  26. package/package.json +2 -1
  27. package/platform/{index.android.d.ts → device/index.android.d.ts} +1 -16
  28. package/platform/{index.android.js → device/index.android.js} +4 -47
  29. package/platform/device/index.android.js.map +1 -0
  30. package/platform/device/index.d.ts +70 -0
  31. package/platform/{index.ios.d.ts → device/index.ios.d.ts} +1 -14
  32. package/platform/{index.ios.js → device/index.ios.js} +1 -34
  33. package/platform/device/index.ios.js.map +1 -0
  34. package/platform/index.d.ts +2 -118
  35. package/platform/index.js +4 -0
  36. package/platform/index.js.map +1 -0
  37. package/platform/screen/index.android.d.ts +16 -0
  38. package/platform/screen/index.android.js +41 -0
  39. package/platform/screen/index.android.js.map +1 -0
  40. package/platform/screen/index.d.ts +48 -0
  41. package/platform/screen/index.ios.d.ts +15 -0
  42. package/platform/screen/index.ios.js +35 -0
  43. package/platform/screen/index.ios.js.map +1 -0
  44. package/platforms/android/widgets-release.aar +0 -0
  45. package/profiling/index.js.map +1 -1
  46. package/trace/index.d.ts +1 -0
  47. package/trace/index.js +2 -1
  48. package/trace/index.js.map +1 -1
  49. package/ui/action-bar/index.android.d.ts +0 -2
  50. package/ui/action-bar/index.android.js +0 -26
  51. package/ui/action-bar/index.android.js.map +1 -1
  52. package/ui/activity-indicator/index.android.js +3 -2
  53. package/ui/activity-indicator/index.android.js.map +1 -1
  54. package/ui/animation/keyframe-animation.d.ts +3 -0
  55. package/ui/animation/keyframe-animation.js +4 -2
  56. package/ui/animation/keyframe-animation.js.map +1 -1
  57. package/ui/builder/index.js.map +1 -1
  58. package/ui/builder/xml2ui.js.map +1 -1
  59. package/ui/button/index.android.d.ts +0 -2
  60. package/ui/button/index.android.js +0 -26
  61. package/ui/button/index.android.js.map +1 -1
  62. package/ui/core/view/index.android.d.ts +1 -1
  63. package/ui/core/view/index.android.js +49 -45
  64. package/ui/core/view/index.android.js.map +1 -1
  65. package/ui/core/view/view-common.d.ts +1 -1
  66. package/ui/core/view/view-common.js.map +1 -1
  67. package/ui/core/view/view-helper/index.android.d.ts +7 -0
  68. package/ui/core/view/view-helper/index.android.js +53 -0
  69. package/ui/core/view/view-helper/index.android.js.map +1 -1
  70. package/ui/core/view/view-helper/index.d.ts +10 -0
  71. package/ui/core/view/view-helper/index.ios.d.ts +1 -0
  72. package/ui/core/view/view-helper/index.ios.js +1 -0
  73. package/ui/core/view/view-helper/index.ios.js.map +1 -1
  74. package/ui/core/view-base/index.d.ts +7 -0
  75. package/ui/core/view-base/index.js +11 -2
  76. package/ui/core/view-base/index.js.map +1 -1
  77. package/ui/frame/fragment.d.ts +5 -0
  78. package/ui/frame/fragment.ios.d.ts +3 -0
  79. package/ui/frame/fragment.ios.js +4 -0
  80. package/ui/frame/fragment.ios.js.map +1 -0
  81. package/ui/frame/index.android.d.ts +1 -1
  82. package/ui/frame/index.android.js +2 -2
  83. package/ui/frame/index.android.js.map +1 -1
  84. package/ui/index.d.ts +1 -1
  85. package/ui/index.js +1 -1
  86. package/ui/index.js.map +1 -1
  87. package/ui/layouts/grid-layout/grid-layout-common.d.ts +7 -2
  88. package/ui/layouts/grid-layout/grid-layout-common.js +32 -6
  89. package/ui/layouts/grid-layout/grid-layout-common.js.map +1 -1
  90. package/ui/layouts/grid-layout/index.android.d.ts +9 -3
  91. package/ui/layouts/grid-layout/index.android.js +65 -38
  92. package/ui/layouts/grid-layout/index.android.js.map +1 -1
  93. package/ui/list-picker/index.android.js.map +1 -1
  94. package/ui/page/index.android.js +5 -2
  95. package/ui/page/index.android.js.map +1 -1
  96. package/ui/progress/index.android.js +5 -4
  97. package/ui/progress/index.android.js.map +1 -1
  98. package/ui/segmented-bar/index.android.js +4 -13
  99. package/ui/segmented-bar/index.android.js.map +1 -1
  100. package/ui/slider/index.android.js +7 -4
  101. package/ui/slider/index.android.js.map +1 -1
  102. package/ui/styling/css-selector.d.ts +88 -32
  103. package/ui/styling/css-selector.js +484 -130
  104. package/ui/styling/css-selector.js.map +1 -1
  105. package/ui/styling/font-common.js.map +1 -1
  106. package/ui/styling/style-properties.js +1 -1
  107. package/ui/styling/style-properties.js.map +1 -1
  108. package/ui/styling/style-scope.js +288 -138
  109. package/ui/styling/style-scope.js.map +1 -1
  110. package/ui/switch/index.android.js +7 -6
  111. package/ui/switch/index.android.js.map +1 -1
  112. package/ui/tab-view/index.android.js +10 -14
  113. package/ui/tab-view/index.android.js.map +1 -1
  114. package/ui/transition/page-transition.android.d.ts +2 -1
  115. package/ui/transition/page-transition.android.js +11 -4
  116. package/ui/transition/page-transition.android.js.map +1 -1
  117. package/ui/utils.d.ts +5 -1
  118. package/ui/utils.ios.d.ts +1 -10
  119. package/ui/utils.ios.js.map +1 -1
  120. package/platform/index.android.js.map +0 -1
  121. package/platform/index.ios.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { unsetValue, _evaluateCssVariableExpression, _evaluateCssCalcExpression, isCssVariable, isCssVariableExpression, isCssCalcExpression } from '../core/properties';
2
- import { SelectorsMap, SelectorsMatch, fromAstNodes } from './css-selector';
2
+ import { StyleSheetSelectorScope, SelectorsMatch, fromAstNode, MEDIA_QUERY_SEPARATOR, matchMediaQueryString } from './css-selector';
3
3
  import { Trace } from '../../trace';
4
4
  import { File, knownFolders, path } from '../../file-system';
5
5
  import { Application } from '../../application';
@@ -13,6 +13,7 @@ function ensureKeyframeAnimationModule() {
13
13
  import { sanitizeModuleName } from '../../utils/common';
14
14
  import { resolveModuleName } from '../../module-name-resolver';
15
15
  import { cleanupImportantFlags } from './css-utils';
16
+ import { Observable } from '../../data/observable';
16
17
  let cssAnimationParserModule;
17
18
  function ensureCssAnimationParserModule() {
18
19
  if (!cssAnimationParserModule) {
@@ -34,6 +35,18 @@ try {
34
35
  catch (e) {
35
36
  //
36
37
  }
38
+ let mergedApplicationCssSelectors = [];
39
+ let applicationCssSelectors = [];
40
+ const applicationAdditionalSelectors = [];
41
+ let mergedApplicationCssKeyframes = [];
42
+ let applicationCssKeyframes = [];
43
+ const applicationAdditionalKeyframes = [];
44
+ let applicationCssSelectorVersion = 0;
45
+ const tagToScopeTag = new Map();
46
+ let currentScopeTag = null;
47
+ const animationsSymbol = Symbol('animations');
48
+ const kebabCasePattern = /-([a-z])/g;
49
+ const pattern = /('|")(.*?)\1/;
37
50
  /**
38
51
  * Evaluate css-variable and css-calc expressions
39
52
  */
@@ -53,34 +66,27 @@ function evaluateCssExpressions(view, property, value) {
53
66
  return value;
54
67
  }
55
68
  export function mergeCssSelectors() {
56
- applicationCssSelectors = applicationSelectors.slice();
57
- applicationCssSelectors.push(...applicationAdditionalSelectors);
58
- applicationCssSelectorVersion++;
69
+ mergedApplicationCssSelectors = applicationCssSelectors.slice();
70
+ mergedApplicationCssSelectors.push(...applicationAdditionalSelectors);
71
+ }
72
+ export function mergeCssKeyframes() {
73
+ mergedApplicationCssKeyframes = applicationCssKeyframes.slice();
74
+ mergedApplicationCssKeyframes.push(...applicationAdditionalKeyframes);
59
75
  }
60
- let applicationCssSelectors = [];
61
- let applicationCssSelectorVersion = 0;
62
- let applicationSelectors = [];
63
- const tagToScopeTag = new Map();
64
- let currentScopeTag = null;
65
- const applicationAdditionalSelectors = [];
66
- const applicationKeyframes = {};
67
- const animationsSymbol = Symbol('animations');
68
- const kebabCasePattern = /-([a-z])/g;
69
- const pattern = /('|")(.*?)\1/;
70
76
  class CSSSource {
71
- constructor(_ast, _url, _file, _keyframes, _source) {
77
+ constructor(_ast, _url, _file, _source) {
72
78
  this._ast = _ast;
73
79
  this._url = _url;
74
80
  this._file = _file;
75
- this._keyframes = _keyframes;
76
81
  this._source = _source;
77
82
  this._selectors = [];
83
+ this._keyframes = [];
78
84
  this.parse();
79
85
  }
80
- static fromDetect(cssOrAst, keyframes, fileName) {
86
+ static fromDetect(cssOrAst, fileName) {
81
87
  if (typeof cssOrAst === 'string') {
82
88
  // raw-loader
83
- return CSSSource.fromSource(cssOrAst, keyframes, fileName);
89
+ return CSSSource.fromSource(cssOrAst, fileName);
84
90
  }
85
91
  else if (typeof cssOrAst === 'object') {
86
92
  if (cssOrAst.default) {
@@ -88,13 +94,13 @@ class CSSSource {
88
94
  }
89
95
  if (cssOrAst.type === 'stylesheet' && cssOrAst.stylesheet && cssOrAst.stylesheet.rules) {
90
96
  // css-loader
91
- return CSSSource.fromAST(cssOrAst, keyframes, fileName);
97
+ return CSSSource.fromAST(cssOrAst, fileName);
92
98
  }
93
99
  }
94
100
  // css2json-loader
95
- return CSSSource.fromSource(cssOrAst.toString(), keyframes, fileName);
101
+ return CSSSource.fromSource(cssOrAst.toString(), fileName);
96
102
  }
97
- static fromURI(uri, keyframes) {
103
+ static fromURI(uri) {
98
104
  // webpack modules require all file paths to be relative to /app folder
99
105
  const appRelativeUri = CSSSource.pathRelativeToApp(uri);
100
106
  const sanitizedModuleName = sanitizeModuleName(appRelativeUri);
@@ -102,7 +108,7 @@ class CSSSource {
102
108
  try {
103
109
  const cssOrAst = global.loadModule(resolvedModuleName, true);
104
110
  if (cssOrAst) {
105
- return CSSSource.fromDetect(cssOrAst, keyframes, resolvedModuleName);
111
+ return CSSSource.fromDetect(cssOrAst, resolvedModuleName);
106
112
  }
107
113
  }
108
114
  catch (e) {
@@ -110,7 +116,7 @@ class CSSSource {
110
116
  Trace.write(`Could not load CSS from ${uri}: ${e}`, Trace.categories.Error, Trace.messageType.warn);
111
117
  }
112
118
  }
113
- return CSSSource.fromFile(appRelativeUri, keyframes);
119
+ return CSSSource.fromFile(appRelativeUri);
114
120
  }
115
121
  static pathRelativeToApp(uri) {
116
122
  if (!uri.startsWith('/')) {
@@ -121,39 +127,42 @@ class CSSSource {
121
127
  Trace.write(`${uri} does not start with ${appPath}`, Trace.categories.Error, Trace.messageType.error);
122
128
  return uri;
123
129
  }
124
- const relativeUri = `.${uri.substr(appPath.length)}`;
130
+ const relativeUri = `.${uri.substring(appPath.length)}`;
125
131
  return relativeUri;
126
132
  }
127
- static fromFile(url, keyframes) {
133
+ static fromFile(url) {
128
134
  // .scss, .sass, etc. css files in vanilla app are usually compiled to .css so we will try to load a compiled file first.
129
135
  const cssFileUrl = url.replace(/\..\w+$/, '.css');
130
136
  if (cssFileUrl !== url) {
131
137
  const cssFile = CSSSource.resolveCSSPathFromURL(cssFileUrl);
132
138
  if (cssFile) {
133
- return new CSSSource(undefined, url, cssFile, keyframes, undefined);
139
+ return new CSSSource(undefined, url, cssFile, undefined);
134
140
  }
135
141
  }
136
142
  const file = CSSSource.resolveCSSPathFromURL(url);
137
- return new CSSSource(undefined, url, file, keyframes, undefined);
143
+ return new CSSSource(undefined, url, file, undefined);
138
144
  }
139
- static fromFileImport(url, keyframes, importSource) {
145
+ static fromFileImport(url, importSource) {
140
146
  const file = CSSSource.resolveCSSPathFromURL(url, importSource);
141
- return new CSSSource(undefined, url, file, keyframes, undefined);
147
+ return new CSSSource(undefined, url, file, undefined);
142
148
  }
143
149
  static resolveCSSPathFromURL(url, importSource) {
144
150
  const app = knownFolders.currentApp().path;
145
151
  const file = resolveFileNameFromUrl(url, app, File.exists, importSource);
146
152
  return file;
147
153
  }
148
- static fromSource(source, keyframes, url) {
149
- return new CSSSource(undefined, url, undefined, keyframes, source);
154
+ static fromSource(source, url) {
155
+ return new CSSSource(undefined, url, undefined, source);
150
156
  }
151
- static fromAST(ast, keyframes, url) {
152
- return new CSSSource(ast, url, undefined, keyframes, undefined);
157
+ static fromAST(ast, url) {
158
+ return new CSSSource(ast, url, undefined, undefined);
153
159
  }
154
160
  get selectors() {
155
161
  return this._selectors;
156
162
  }
163
+ get keyframes() {
164
+ return this._keyframes;
165
+ }
157
166
  get source() {
158
167
  return this._source;
159
168
  }
@@ -173,7 +182,7 @@ class CSSSource {
173
182
  }
174
183
  }
175
184
  if (this._ast) {
176
- this.createSelectors();
185
+ this.createSelectorsAndKeyframes();
177
186
  }
178
187
  else {
179
188
  this._selectors = [];
@@ -206,42 +215,23 @@ class CSSSource {
206
215
  }
207
216
  }
208
217
  }
209
- createSelectors() {
218
+ createSelectorsAndKeyframes() {
210
219
  if (this._ast) {
211
- this._selectors = [...this.createSelectorsFromImports(), ...this.createSelectorsFromSyntaxTree()];
212
- }
213
- }
214
- createSelectorsFromImports() {
215
- const imports = this._ast['stylesheet']['rules'].filter((r) => r.type === 'import');
216
- const urlFromImportObject = (importObject) => {
217
- const importItem = importObject['import'];
218
- const urlMatch = importItem && importItem.match(pattern);
219
- return urlMatch && urlMatch[2];
220
- };
221
- const sourceFromImportObject = (importObject) => importObject['position'] && importObject['position']['source'];
222
- const toUrlSourcePair = (importObject) => ({
223
- url: urlFromImportObject(importObject),
224
- source: sourceFromImportObject(importObject),
225
- });
226
- const getCssFile = ({ url, source }) => (source ? CSSSource.fromFileImport(url, this._keyframes, source) : CSSSource.fromURI(url, this._keyframes));
227
- const cssFiles = imports
228
- .map(toUrlSourcePair)
229
- .filter(({ url }) => !!url)
230
- .map(getCssFile);
231
- const selectors = cssFiles.map((file) => (file && file.selectors) || []);
232
- return selectors.reduce((acc, val) => acc.concat(val), []);
233
- }
234
- createSelectorsFromSyntaxTree() {
235
- const nodes = this._ast.stylesheet.rules;
236
- nodes.filter(isKeyframe).forEach((node) => (this._keyframes[node.name] = node));
237
- const rulesets = fromAstNodes(nodes);
238
- if (rulesets && rulesets.length) {
239
- ensureCssAnimationParserModule();
240
- rulesets.forEach((rule) => {
241
- rule[animationsSymbol] = cssAnimationParserModule.CssAnimationParser.keyframeAnimationsFromCSSDeclarations(rule.declarations);
242
- });
243
- }
244
- return rulesets;
220
+ const nodes = this._ast.stylesheet.rules;
221
+ const rulesets = [];
222
+ const keyframes = [];
223
+ // When css2json-loader is enabled, imports are handled there and removed from AST rules
224
+ populateRulesFromImports(nodes, rulesets, keyframes);
225
+ _populateRules(nodes, rulesets, keyframes);
226
+ if (rulesets && rulesets.length) {
227
+ ensureCssAnimationParserModule();
228
+ rulesets.forEach((rule) => {
229
+ rule[animationsSymbol] = cssAnimationParserModule.CssAnimationParser.keyframeAnimationsFromCSSDeclarations(rule.declarations);
230
+ });
231
+ }
232
+ this._selectors = rulesets;
233
+ this._keyframes = keyframes;
234
+ }
245
235
  }
246
236
  toString() {
247
237
  return this._file || this._url || '(in-memory)';
@@ -270,53 +260,147 @@ __decorate([
270
260
  __metadata("design:type", Function),
271
261
  __metadata("design:paramtypes", []),
272
262
  __metadata("design:returntype", void 0)
273
- ], CSSSource.prototype, "createSelectors", null);
263
+ ], CSSSource.prototype, "createSelectorsAndKeyframes", null);
274
264
  __decorate([
275
265
  profile,
276
266
  __metadata("design:type", Function),
277
267
  __metadata("design:paramtypes", [String, String]),
278
268
  __metadata("design:returntype", String)
279
269
  ], CSSSource, "resolveCSSPathFromURL", null);
270
+ function populateRulesFromImports(nodes, rulesets, keyframes) {
271
+ const imports = nodes.filter((r) => r.type === 'import');
272
+ if (!imports.length) {
273
+ return;
274
+ }
275
+ const urlFromImportObject = (importObject) => {
276
+ const importItem = importObject['import'];
277
+ const urlMatch = importItem && importItem.match(pattern);
278
+ return urlMatch && urlMatch[2];
279
+ };
280
+ const sourceFromImportObject = (importObject) => importObject['position'] && importObject['position']['source'];
281
+ const toUrlSourcePair = (importObject) => ({
282
+ url: urlFromImportObject(importObject),
283
+ source: sourceFromImportObject(importObject),
284
+ });
285
+ const getCssFile = ({ url, source }) => (source ? CSSSource.fromFileImport(url, source) : CSSSource.fromURI(url));
286
+ const cssFiles = imports
287
+ .map(toUrlSourcePair)
288
+ .filter(({ url }) => !!url)
289
+ .map(getCssFile);
290
+ for (const cssFile of cssFiles) {
291
+ if (cssFile) {
292
+ rulesets.push(...cssFile.selectors);
293
+ keyframes.push(...cssFile.keyframes);
294
+ }
295
+ }
296
+ }
297
+ export function _populateRules(nodes, rulesets, keyframes, mediaQueryString) {
298
+ for (const node of nodes) {
299
+ if (isKeyframe(node)) {
300
+ const keyframeRule = {
301
+ name: node.name,
302
+ keyframes: node.keyframes,
303
+ mediaQueryString: mediaQueryString,
304
+ };
305
+ keyframes.push(keyframeRule);
306
+ }
307
+ else if (isMedia(node)) {
308
+ // Media query is composite in the case of nested media queries
309
+ const compositeMediaQuery = mediaQueryString ? mediaQueryString + MEDIA_QUERY_SEPARATOR + node.media : node.media;
310
+ _populateRules(node.rules, rulesets, keyframes, compositeMediaQuery);
311
+ }
312
+ else if (isRule(node)) {
313
+ const ruleset = fromAstNode(node);
314
+ ruleset.mediaQueryString = mediaQueryString;
315
+ rulesets.push(ruleset);
316
+ }
317
+ }
318
+ }
280
319
  export function removeTaggedAdditionalCSS(tag) {
281
- let changed = false;
320
+ let selectorsChanged = false;
321
+ let keyframesChanged = false;
322
+ let updated = false;
282
323
  for (let i = 0; i < applicationAdditionalSelectors.length; i++) {
283
324
  if (applicationAdditionalSelectors[i].tag === tag) {
284
325
  applicationAdditionalSelectors.splice(i, 1);
285
326
  i--;
286
- changed = true;
327
+ selectorsChanged = true;
287
328
  }
288
329
  }
289
- if (changed) {
330
+ for (let i = 0; i < applicationAdditionalKeyframes.length; i++) {
331
+ if (applicationAdditionalKeyframes[i].tag === tag) {
332
+ applicationAdditionalKeyframes.splice(i, 1);
333
+ i--;
334
+ keyframesChanged = true;
335
+ }
336
+ }
337
+ if (selectorsChanged) {
290
338
  mergeCssSelectors();
339
+ updated = true;
340
+ }
341
+ if (keyframesChanged) {
342
+ mergeCssKeyframes();
343
+ updated = true;
344
+ }
345
+ if (updated) {
346
+ applicationCssSelectorVersion++;
291
347
  }
292
- return changed;
348
+ return updated;
293
349
  }
294
350
  export function addTaggedAdditionalCSS(cssText, tag) {
295
- const parsed = CSSSource.fromDetect(cssText, applicationKeyframes, undefined).selectors;
351
+ const { selectors, keyframes } = CSSSource.fromDetect(cssText, undefined);
296
352
  const tagScope = currentScopeTag || (tag && tagToScopeTag.has(tag) && tagToScopeTag.get(tag)) || null;
297
353
  if (tagScope && tag) {
298
354
  tagToScopeTag.set(tag, tagScope);
299
355
  }
300
- let changed = false;
301
- if (parsed && parsed.length) {
302
- changed = true;
356
+ let selectorsChanged = false;
357
+ let keyframesChanged = false;
358
+ let updated = false;
359
+ if (selectors && selectors.length) {
360
+ selectorsChanged = true;
303
361
  if (tag != null || tagScope != null) {
304
- for (let i = 0; i < parsed.length; i++) {
305
- parsed[i].tag = tag;
306
- parsed[i].scopedTag = tagScope;
362
+ for (let i = 0, length = selectors.length; i < length; i++) {
363
+ selectors[i].tag = tag;
364
+ selectors[i].scopedTag = tagScope;
307
365
  }
308
366
  }
309
- applicationAdditionalSelectors.push(...parsed);
367
+ applicationAdditionalSelectors.push(...selectors);
310
368
  mergeCssSelectors();
369
+ updated = true;
311
370
  }
312
- return changed;
371
+ if (keyframes && keyframes.length) {
372
+ keyframesChanged = true;
373
+ if (tag != null || tagScope != null) {
374
+ for (let i = 0, length = keyframes.length; i < length; i++) {
375
+ keyframes[i].tag = tag;
376
+ keyframes[i].scopedTag = tagScope;
377
+ }
378
+ }
379
+ applicationAdditionalKeyframes.push(...keyframes);
380
+ mergeCssKeyframes();
381
+ updated = true;
382
+ }
383
+ if (updated) {
384
+ applicationCssSelectorVersion++;
385
+ }
386
+ return updated;
313
387
  }
314
388
  const onCssChanged = profile('"style-scope".onCssChanged', (args) => {
315
389
  if (args.cssText) {
316
- const parsed = CSSSource.fromSource(args.cssText, applicationKeyframes, args.cssFile).selectors;
317
- if (parsed) {
318
- applicationAdditionalSelectors.push(...parsed);
390
+ const { selectors, keyframes } = CSSSource.fromSource(args.cssText, args.cssFile);
391
+ let updated = false;
392
+ if (selectors) {
393
+ applicationAdditionalSelectors.push(...selectors);
319
394
  mergeCssSelectors();
395
+ updated = true;
396
+ }
397
+ if (keyframes) {
398
+ applicationAdditionalKeyframes.push(...keyframes);
399
+ mergeCssKeyframes();
400
+ updated = true;
401
+ }
402
+ if (updated) {
403
+ applicationCssSelectorVersion++;
320
404
  }
321
405
  }
322
406
  else if (args.cssFile) {
@@ -328,16 +412,28 @@ function onLiveSync(args) {
328
412
  }
329
413
  const loadCss = profile(`"style-scope".loadCss`, (cssModule) => {
330
414
  if (!cssModule) {
331
- return undefined;
415
+ return;
332
416
  }
333
417
  // safely remove "./" as global CSS should be resolved relative to app folder
334
418
  if (cssModule.startsWith('./')) {
335
- cssModule = cssModule.substr(2);
419
+ cssModule = cssModule.substring(2);
336
420
  }
337
- const result = CSSSource.fromURI(cssModule, applicationKeyframes).selectors;
338
- if (result.length > 0) {
339
- applicationSelectors = result;
421
+ const { selectors, keyframes } = CSSSource.fromURI(cssModule);
422
+ let updated = false;
423
+ // Check for existing application css selectors too in case the app is undergoing a live-sync
424
+ if (selectors.length > 0 || applicationCssSelectors.length > 0) {
425
+ applicationCssSelectors = selectors;
340
426
  mergeCssSelectors();
427
+ updated = true;
428
+ }
429
+ // Check for existing application css keyframes too in case the app is undergoing a live-sync
430
+ if (keyframes.length > 0 || applicationCssKeyframes.length > 0) {
431
+ applicationCssKeyframes = keyframes;
432
+ mergeCssKeyframes();
433
+ updated = true;
434
+ }
435
+ if (updated) {
436
+ applicationCssSelectorVersion++;
341
437
  }
342
438
  });
343
439
  global.NativeScriptGlobals.events.on('cssChanged', onCssChanged);
@@ -365,6 +461,7 @@ export class CssState {
365
461
  constructor(viewRef) {
366
462
  this.viewRef = viewRef;
367
463
  this._appliedPropertyValues = CssState.emptyPropertyBag;
464
+ this._dynamicUpdateListenerMap = new Map();
368
465
  this._onDynamicStateChangeHandler = () => this.updateDynamicState();
369
466
  }
370
467
  /**
@@ -405,7 +502,7 @@ export class CssState {
405
502
  updateMatch() {
406
503
  const view = this.viewRef.get();
407
504
  if (view && view._styleScope) {
408
- this._match = view._styleScope.matchSelectors(view);
505
+ this._match = view._styleScope.matchSelectors(view) ?? CssState.emptyMatch;
409
506
  this._appliedSelectorsVersion = view._styleScope.getSelectorsVersion();
410
507
  }
411
508
  else {
@@ -420,12 +517,12 @@ export class CssState {
420
517
  return;
421
518
  }
422
519
  const matchingSelectors = this._match.selectors.filter((sel) => (sel.dynamic ? sel.match(view) : true));
423
- if (!matchingSelectors || matchingSelectors.length === 0) {
424
- // Ideally we should return here if there are no matching selectors, however
425
- // if there are property removals, returning here would not remove them
426
- // this is seen in STYLE test in automated.
427
- // return;
428
- }
520
+ // Ideally we should return here if there are no matching selectors, however
521
+ // if there are property removals, returning here would not remove them
522
+ // this is seen in STYLE test in automated.
523
+ // if (!matchingSelectors || matchingSelectors.length === 0) {
524
+ // return;
525
+ // }
429
526
  view._batchUpdate(() => {
430
527
  this.stopKeyframeAnimations();
431
528
  this.setPropertyValues(matchingSelectors);
@@ -435,7 +532,7 @@ export class CssState {
435
532
  playKeyframeAnimations(matchingSelectors) {
436
533
  const animations = [];
437
534
  matchingSelectors.forEach((selector) => {
438
- const ruleAnimations = selector.ruleset[animationsSymbol];
535
+ const ruleAnimations = selector.ruleset?.[animationsSymbol];
439
536
  if (ruleAnimations) {
440
537
  ensureKeyframeAnimationModule();
441
538
  for (const animationInfo of ruleAnimations) {
@@ -569,9 +666,14 @@ export class CssState {
569
666
  const changeMap = this._match.changeMap;
570
667
  changeMap.forEach((changes, view) => {
571
668
  if (changes.attributes) {
572
- changes.attributes.forEach((attribute) => {
573
- view.addEventListener(attribute + 'Change', this._onDynamicStateChangeHandler);
574
- });
669
+ const attributes = changes.attributes;
670
+ const listener = (args) => {
671
+ if (attributes.has(args.propertyName)) {
672
+ this._onDynamicStateChangeHandler();
673
+ }
674
+ };
675
+ this._dynamicUpdateListenerMap.set(view, listener);
676
+ view.addEventListener(Observable.propertyChangeEvent, listener);
575
677
  }
576
678
  if (changes.pseudoClasses) {
577
679
  changes.pseudoClasses.forEach((pseudoClass) => {
@@ -587,10 +689,8 @@ export class CssState {
587
689
  }
588
690
  unsubscribeFromDynamicUpdates() {
589
691
  this._appliedChangeMap.forEach((changes, view) => {
590
- if (changes.attributes) {
591
- changes.attributes.forEach((attribute) => {
592
- view.removeEventListener(attribute + 'Change', this._onDynamicStateChangeHandler);
593
- });
692
+ if (this._dynamicUpdateListenerMap.has(view)) {
693
+ view.removeEventListener(Observable.propertyChangeEvent, this._dynamicUpdateListenerMap.get(view));
594
694
  }
595
695
  if (changes.pseudoClasses) {
596
696
  changes.pseudoClasses.forEach((pseudoClass) => {
@@ -602,6 +702,7 @@ export class CssState {
602
702
  });
603
703
  }
604
704
  });
705
+ this._dynamicUpdateListenerMap.clear();
605
706
  this._appliedChangeMap = CssState.emptyChangeMap;
606
707
  }
607
708
  toString() {
@@ -642,10 +743,10 @@ export class StyleScope {
642
743
  constructor() {
643
744
  this._css = '';
644
745
  this._localCssSelectors = [];
746
+ this._localCssKeyframes = [];
645
747
  this._localCssSelectorVersion = 0;
646
748
  this._localCssSelectorsAppliedVersion = 0;
647
749
  this._applicationCssSelectorsAppliedVersion = 0;
648
- this._keyframes = new Map();
649
750
  this._cssFiles = [];
650
751
  }
651
752
  get css() {
@@ -666,17 +767,19 @@ export class StyleScope {
666
767
  }
667
768
  this._cssFiles.push(cssFileName);
668
769
  currentScopeTag = cssFileName;
669
- const cssSelectors = CSSSource.fromURI(cssFileName, this._keyframes);
770
+ const cssFile = CSSSource.fromURI(cssFileName);
670
771
  currentScopeTag = null;
671
- this._css = cssSelectors.source;
672
- this._localCssSelectors = cssSelectors.selectors;
772
+ this._css = cssFile.source;
773
+ this._localCssSelectors = cssFile.selectors;
774
+ this._localCssKeyframes = cssFile.keyframes;
673
775
  this._localCssSelectorVersion++;
674
776
  this.ensureSelectors();
675
777
  }
676
778
  setCss(cssString, cssFileName) {
677
779
  this._css = cssString;
678
- const cssFile = CSSSource.fromSource(cssString, this._keyframes, cssFileName);
780
+ const cssFile = CSSSource.fromSource(cssString, cssFileName);
679
781
  this._localCssSelectors = cssFile.selectors;
782
+ this._localCssKeyframes = cssFile.keyframes;
680
783
  this._localCssSelectorVersion++;
681
784
  this.ensureSelectors();
682
785
  }
@@ -688,22 +791,23 @@ export class StyleScope {
688
791
  this._cssFiles.push(cssFileName);
689
792
  currentScopeTag = cssFileName;
690
793
  }
691
- const parsedCssSelectors = cssString ? CSSSource.fromSource(cssString, this._keyframes, cssFileName) : CSSSource.fromURI(cssFileName, this._keyframes);
794
+ const cssFile = cssString ? CSSSource.fromSource(cssString, cssFileName) : CSSSource.fromURI(cssFileName);
692
795
  currentScopeTag = null;
693
- this._css = this._css + parsedCssSelectors.source;
694
- this._localCssSelectors.push(...parsedCssSelectors.selectors);
796
+ this._css = this._css + cssFile.source;
797
+ this._localCssSelectors.push(...cssFile.selectors);
798
+ this._localCssKeyframes.push(...cssFile.keyframes);
695
799
  this._localCssSelectorVersion++;
696
800
  this.ensureSelectors();
697
801
  }
698
802
  getKeyframeAnimationWithName(animationName) {
699
- const cssKeyframes = this._keyframes[animationName];
700
- if (!cssKeyframes) {
701
- return;
803
+ if (!this._mergedCssKeyframes) {
804
+ return null;
702
805
  }
806
+ const keyframeRule = this.findKeyframeRule(animationName);
703
807
  ensureKeyframeAnimationModule();
704
808
  const animation = new keyframeAnimationModule.KeyframeAnimationInfo();
705
809
  ensureCssAnimationParserModule();
706
- animation.keyframes = cssAnimationParserModule.CssAnimationParser.keyframesArrayFromCSS(cssKeyframes.keyframes);
810
+ animation.keyframes = keyframeRule ? cssAnimationParserModule.CssAnimationParser.keyframesArrayFromCSS(keyframeRule.keyframes) : null;
707
811
  return animation;
708
812
  }
709
813
  ensureSelectors() {
@@ -723,46 +827,61 @@ export class StyleScope {
723
827
  }
724
828
  _createSelectors() {
725
829
  const toMerge = [];
726
- toMerge.push(applicationCssSelectors.filter((v) => !v.scopedTag || this._cssFiles.indexOf(v.scopedTag) >= 0));
830
+ const toMergeKeyframes = [];
831
+ toMerge.push(...mergedApplicationCssSelectors.filter((v) => !v.scopedTag || this._cssFiles.indexOf(v.scopedTag) >= 0));
832
+ toMergeKeyframes.push(...mergedApplicationCssKeyframes.filter((v) => !v.scopedTag || this._cssFiles.indexOf(v.scopedTag) >= 0));
727
833
  this._applicationCssSelectorsAppliedVersion = applicationCssSelectorVersion;
728
- toMerge.push(this._localCssSelectors);
834
+ toMerge.push(...this._localCssSelectors);
835
+ toMergeKeyframes.push(...this._localCssKeyframes);
729
836
  this._localCssSelectorsAppliedVersion = this._localCssSelectorVersion;
730
- for (const keyframe in applicationKeyframes) {
731
- this._keyframes[keyframe] = applicationKeyframes[keyframe];
732
- }
733
837
  if (toMerge.length > 0) {
734
- this._mergedCssSelectors = toMerge.reduce((merged, next) => merged.concat(next || []), []);
735
- this._applyKeyframesOnSelectors();
736
- this._selectors = new SelectorsMap(this._mergedCssSelectors);
838
+ this._mergedCssSelectors = toMerge;
839
+ this._selectorScope = new StyleSheetSelectorScope(this._mergedCssSelectors);
737
840
  }
841
+ else {
842
+ this._mergedCssSelectors = null;
843
+ this._selectorScope = null;
844
+ }
845
+ this._mergedCssKeyframes = toMergeKeyframes.length > 0 ? toMergeKeyframes : null;
738
846
  }
739
847
  // HACK: This @profile decorator creates a circular dependency
740
848
  // HACK: because the function parameter type is evaluated with 'typeof'
741
849
  matchSelectors(view) {
850
+ let match;
742
851
  // should be (view: ViewBase): SelectorsMatch<ViewBase>
743
852
  this.ensureSelectors();
744
- return this._selectors.query(view);
853
+ if (this._selectorScope) {
854
+ match = this._selectorScope.query(view);
855
+ // Make sure to re-apply keyframes to matching selectors as a media query keyframe might be applicable at this point
856
+ this._applyKeyframesToSelectors(match.selectors);
857
+ }
858
+ else {
859
+ match = null;
860
+ }
861
+ return match;
745
862
  }
746
863
  query(node) {
747
864
  this.ensureSelectors();
748
- return this._selectors.query(node).selectors;
865
+ const match = this.matchSelectors(node);
866
+ return match ? match.selectors : [];
749
867
  }
750
868
  getSelectorsVersion() {
751
869
  // The counters can only go up. So we can return just appVersion + localVersion
752
870
  // The 100000 * appVersion is just for easier debugging
753
871
  return 100000 * this._applicationCssSelectorsAppliedVersion + this._localCssSelectorsAppliedVersion;
754
872
  }
755
- _applyKeyframesOnSelectors() {
756
- for (let i = this._mergedCssSelectors.length - 1; i >= 0; i--) {
757
- const ruleset = this._mergedCssSelectors[i];
873
+ _applyKeyframesToSelectors(selectors) {
874
+ if (!selectors?.length) {
875
+ return;
876
+ }
877
+ for (let i = selectors.length - 1; i >= 0; i--) {
878
+ const ruleset = selectors[i].ruleset;
758
879
  const animations = ruleset[animationsSymbol];
759
- if (animations !== undefined && animations.length) {
880
+ if (animations != null && animations.length) {
760
881
  ensureCssAnimationParserModule();
761
882
  for (const animation of animations) {
762
- const cssKeyframe = this._keyframes[animation.name];
763
- if (cssKeyframe !== undefined) {
764
- animation.keyframes = cssAnimationParserModule.CssAnimationParser.keyframesArrayFromCSS(cssKeyframe.keyframes);
765
- }
883
+ const keyframeRule = this.findKeyframeRule(animation.name);
884
+ animation.keyframes = keyframeRule ? cssAnimationParserModule.CssAnimationParser.keyframesArrayFromCSS(keyframeRule.keyframes) : null;
766
885
  }
767
886
  }
768
887
  }
@@ -770,6 +889,31 @@ export class StyleScope {
770
889
  getAnimations(ruleset) {
771
890
  return ruleset[animationsSymbol];
772
891
  }
892
+ findKeyframeRule(animationName) {
893
+ if (!this._mergedCssKeyframes) {
894
+ return null;
895
+ }
896
+ // Cache media query results to avoid validations of other identical queries
897
+ let validatedMediaQueries;
898
+ // Iterate in reverse order as the last usable keyframe rule matters the most
899
+ for (let i = this._mergedCssKeyframes.length - 1; i >= 0; i--) {
900
+ const rule = this._mergedCssKeyframes[i];
901
+ if (rule.name !== animationName) {
902
+ continue;
903
+ }
904
+ if (!rule.mediaQueryString) {
905
+ return rule;
906
+ }
907
+ if (!validatedMediaQueries) {
908
+ validatedMediaQueries = [];
909
+ }
910
+ const isMatchingAllQueries = matchMediaQueryString(rule.mediaQueryString, validatedMediaQueries);
911
+ if (isMatchingAllQueries) {
912
+ return rule;
913
+ }
914
+ }
915
+ return null;
916
+ }
773
917
  }
774
918
  __decorate([
775
919
  profile,
@@ -807,7 +951,7 @@ export function resolveFileNameFromUrl(url, appDirectory, fileExists, importSour
807
951
  }
808
952
  if (!isAbsolutePath) {
809
953
  if (fileName[0] === '~' && fileName[1] !== '/' && fileName[1] !== '"') {
810
- fileName = fileName.substr(1);
954
+ fileName = fileName.substring(1);
811
955
  }
812
956
  if (importSource) {
813
957
  const importFile = resolveFilePathFromImport(importSource, fileName);
@@ -836,7 +980,7 @@ function resolveFilePathFromImport(importSource, fileName) {
836
980
  }
837
981
  export const applyInlineStyle = profile(function applyInlineStyle(view, styleStr) {
838
982
  const localStyle = `local { ${styleStr} }`;
839
- const inlineRuleSet = CSSSource.fromSource(localStyle, new Map()).selectors;
983
+ const inlineRuleSet = CSSSource.fromSource(localStyle).selectors;
840
984
  // Reset unscoped css-variables
841
985
  view.style.resetUnscopedCssVariables();
842
986
  // Set all the css-variables first, so we can be sure they are up-to-date
@@ -876,7 +1020,13 @@ function isCurrentDirectory(uriPart) {
876
1020
  function isParentDirectory(uriPart) {
877
1021
  return uriPart === '..';
878
1022
  }
1023
+ function isMedia(node) {
1024
+ return node.type === 'media';
1025
+ }
879
1026
  function isKeyframe(node) {
880
1027
  return node.type === 'keyframes';
881
1028
  }
1029
+ function isRule(node) {
1030
+ return node.type === 'rule';
1031
+ }
882
1032
  //# sourceMappingURL=style-scope.js.map