@nativescript/core 8.8.0-next-06-28-2024-9719558748 → 8.8.0-next-07-01-2024-9747811047

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 (57) 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.ios.js +1 -1
  5. package/application/application.ios.js.map +1 -1
  6. package/css/reworkcss.d.ts +15 -1
  7. package/css-mediaquery/index.d.ts +27 -0
  8. package/css-mediaquery/index.js +118 -0
  9. package/css-mediaquery/index.js.map +1 -0
  10. package/globals/index.js +2 -0
  11. package/globals/index.js.map +1 -1
  12. package/media-query-list/index.d.ts +21 -0
  13. package/media-query-list/index.js +169 -0
  14. package/media-query-list/index.js.map +1 -0
  15. package/package.json +1 -1
  16. package/platform/{index.android.d.ts → device/index.android.d.ts} +1 -16
  17. package/platform/{index.android.js → device/index.android.js} +4 -47
  18. package/platform/device/index.android.js.map +1 -0
  19. package/platform/device/index.d.ts +70 -0
  20. package/platform/{index.ios.d.ts → device/index.ios.d.ts} +1 -14
  21. package/platform/{index.ios.js → device/index.ios.js} +1 -34
  22. package/platform/device/index.ios.js.map +1 -0
  23. package/platform/index.d.ts +2 -118
  24. package/platform/index.js +4 -0
  25. package/platform/index.js.map +1 -0
  26. package/platform/screen/index.android.d.ts +16 -0
  27. package/platform/screen/index.android.js +41 -0
  28. package/platform/screen/index.android.js.map +1 -0
  29. package/platform/screen/index.d.ts +48 -0
  30. package/platform/screen/index.ios.d.ts +15 -0
  31. package/platform/screen/index.ios.js +35 -0
  32. package/platform/screen/index.ios.js.map +1 -0
  33. package/platforms/android/widgets-release.aar +0 -0
  34. package/trace/index.d.ts +1 -0
  35. package/trace/index.js +2 -1
  36. package/trace/index.js.map +1 -1
  37. package/ui/animation/keyframe-animation.d.ts +3 -0
  38. package/ui/animation/keyframe-animation.js +4 -2
  39. package/ui/animation/keyframe-animation.js.map +1 -1
  40. package/ui/core/view/index.android.js.map +1 -1
  41. package/ui/layouts/grid-layout/grid-layout-common.d.ts +7 -2
  42. package/ui/layouts/grid-layout/grid-layout-common.js +32 -6
  43. package/ui/layouts/grid-layout/grid-layout-common.js.map +1 -1
  44. package/ui/layouts/grid-layout/index.android.d.ts +9 -3
  45. package/ui/layouts/grid-layout/index.android.js +65 -38
  46. package/ui/layouts/grid-layout/index.android.js.map +1 -1
  47. package/ui/page/index.android.js +5 -2
  48. package/ui/page/index.android.js.map +1 -1
  49. package/ui/styling/css-selector.d.ts +25 -9
  50. package/ui/styling/css-selector.js +108 -20
  51. package/ui/styling/css-selector.js.map +1 -1
  52. package/ui/styling/style-scope.js +275 -131
  53. package/ui/styling/style-scope.js.map +1 -1
  54. package/ui/tab-view/index.android.js +8 -4
  55. package/ui/tab-view/index.android.js.map +1 -1
  56. package/platform/index.android.js.map +0 -1
  57. 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';
@@ -35,6 +35,18 @@ try {
35
35
  catch (e) {
36
36
  //
37
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/;
38
50
  /**
39
51
  * Evaluate css-variable and css-calc expressions
40
52
  */
@@ -54,34 +66,27 @@ function evaluateCssExpressions(view, property, value) {
54
66
  return value;
55
67
  }
56
68
  export function mergeCssSelectors() {
57
- applicationCssSelectors = applicationSelectors.slice();
58
- applicationCssSelectors.push(...applicationAdditionalSelectors);
59
- applicationCssSelectorVersion++;
69
+ mergedApplicationCssSelectors = applicationCssSelectors.slice();
70
+ mergedApplicationCssSelectors.push(...applicationAdditionalSelectors);
71
+ }
72
+ export function mergeCssKeyframes() {
73
+ mergedApplicationCssKeyframes = applicationCssKeyframes.slice();
74
+ mergedApplicationCssKeyframes.push(...applicationAdditionalKeyframes);
60
75
  }
61
- let applicationCssSelectors = [];
62
- let applicationCssSelectorVersion = 0;
63
- let applicationSelectors = [];
64
- const tagToScopeTag = new Map();
65
- let currentScopeTag = null;
66
- const applicationAdditionalSelectors = [];
67
- const applicationKeyframes = {};
68
- const animationsSymbol = Symbol('animations');
69
- const kebabCasePattern = /-([a-z])/g;
70
- const pattern = /('|")(.*?)\1/;
71
76
  class CSSSource {
72
- constructor(_ast, _url, _file, _keyframes, _source) {
77
+ constructor(_ast, _url, _file, _source) {
73
78
  this._ast = _ast;
74
79
  this._url = _url;
75
80
  this._file = _file;
76
- this._keyframes = _keyframes;
77
81
  this._source = _source;
78
82
  this._selectors = [];
83
+ this._keyframes = [];
79
84
  this.parse();
80
85
  }
81
- static fromDetect(cssOrAst, keyframes, fileName) {
86
+ static fromDetect(cssOrAst, fileName) {
82
87
  if (typeof cssOrAst === 'string') {
83
88
  // raw-loader
84
- return CSSSource.fromSource(cssOrAst, keyframes, fileName);
89
+ return CSSSource.fromSource(cssOrAst, fileName);
85
90
  }
86
91
  else if (typeof cssOrAst === 'object') {
87
92
  if (cssOrAst.default) {
@@ -89,13 +94,13 @@ class CSSSource {
89
94
  }
90
95
  if (cssOrAst.type === 'stylesheet' && cssOrAst.stylesheet && cssOrAst.stylesheet.rules) {
91
96
  // css-loader
92
- return CSSSource.fromAST(cssOrAst, keyframes, fileName);
97
+ return CSSSource.fromAST(cssOrAst, fileName);
93
98
  }
94
99
  }
95
100
  // css2json-loader
96
- return CSSSource.fromSource(cssOrAst.toString(), keyframes, fileName);
101
+ return CSSSource.fromSource(cssOrAst.toString(), fileName);
97
102
  }
98
- static fromURI(uri, keyframes) {
103
+ static fromURI(uri) {
99
104
  // webpack modules require all file paths to be relative to /app folder
100
105
  const appRelativeUri = CSSSource.pathRelativeToApp(uri);
101
106
  const sanitizedModuleName = sanitizeModuleName(appRelativeUri);
@@ -103,7 +108,7 @@ class CSSSource {
103
108
  try {
104
109
  const cssOrAst = global.loadModule(resolvedModuleName, true);
105
110
  if (cssOrAst) {
106
- return CSSSource.fromDetect(cssOrAst, keyframes, resolvedModuleName);
111
+ return CSSSource.fromDetect(cssOrAst, resolvedModuleName);
107
112
  }
108
113
  }
109
114
  catch (e) {
@@ -111,7 +116,7 @@ class CSSSource {
111
116
  Trace.write(`Could not load CSS from ${uri}: ${e}`, Trace.categories.Error, Trace.messageType.warn);
112
117
  }
113
118
  }
114
- return CSSSource.fromFile(appRelativeUri, keyframes);
119
+ return CSSSource.fromFile(appRelativeUri);
115
120
  }
116
121
  static pathRelativeToApp(uri) {
117
122
  if (!uri.startsWith('/')) {
@@ -122,39 +127,42 @@ class CSSSource {
122
127
  Trace.write(`${uri} does not start with ${appPath}`, Trace.categories.Error, Trace.messageType.error);
123
128
  return uri;
124
129
  }
125
- const relativeUri = `.${uri.substr(appPath.length)}`;
130
+ const relativeUri = `.${uri.substring(appPath.length)}`;
126
131
  return relativeUri;
127
132
  }
128
- static fromFile(url, keyframes) {
133
+ static fromFile(url) {
129
134
  // .scss, .sass, etc. css files in vanilla app are usually compiled to .css so we will try to load a compiled file first.
130
135
  const cssFileUrl = url.replace(/\..\w+$/, '.css');
131
136
  if (cssFileUrl !== url) {
132
137
  const cssFile = CSSSource.resolveCSSPathFromURL(cssFileUrl);
133
138
  if (cssFile) {
134
- return new CSSSource(undefined, url, cssFile, keyframes, undefined);
139
+ return new CSSSource(undefined, url, cssFile, undefined);
135
140
  }
136
141
  }
137
142
  const file = CSSSource.resolveCSSPathFromURL(url);
138
- return new CSSSource(undefined, url, file, keyframes, undefined);
143
+ return new CSSSource(undefined, url, file, undefined);
139
144
  }
140
- static fromFileImport(url, keyframes, importSource) {
145
+ static fromFileImport(url, importSource) {
141
146
  const file = CSSSource.resolveCSSPathFromURL(url, importSource);
142
- return new CSSSource(undefined, url, file, keyframes, undefined);
147
+ return new CSSSource(undefined, url, file, undefined);
143
148
  }
144
149
  static resolveCSSPathFromURL(url, importSource) {
145
150
  const app = knownFolders.currentApp().path;
146
151
  const file = resolveFileNameFromUrl(url, app, File.exists, importSource);
147
152
  return file;
148
153
  }
149
- static fromSource(source, keyframes, url) {
150
- return new CSSSource(undefined, url, undefined, keyframes, source);
154
+ static fromSource(source, url) {
155
+ return new CSSSource(undefined, url, undefined, source);
151
156
  }
152
- static fromAST(ast, keyframes, url) {
153
- return new CSSSource(ast, url, undefined, keyframes, undefined);
157
+ static fromAST(ast, url) {
158
+ return new CSSSource(ast, url, undefined, undefined);
154
159
  }
155
160
  get selectors() {
156
161
  return this._selectors;
157
162
  }
163
+ get keyframes() {
164
+ return this._keyframes;
165
+ }
158
166
  get source() {
159
167
  return this._source;
160
168
  }
@@ -174,7 +182,7 @@ class CSSSource {
174
182
  }
175
183
  }
176
184
  if (this._ast) {
177
- this.createSelectors();
185
+ this.createSelectorsAndKeyframes();
178
186
  }
179
187
  else {
180
188
  this._selectors = [];
@@ -207,42 +215,23 @@ class CSSSource {
207
215
  }
208
216
  }
209
217
  }
210
- createSelectors() {
218
+ createSelectorsAndKeyframes() {
211
219
  if (this._ast) {
212
- this._selectors = [...this.createSelectorsFromImports(), ...this.createSelectorsFromSyntaxTree()];
213
- }
214
- }
215
- createSelectorsFromImports() {
216
- const imports = this._ast['stylesheet']['rules'].filter((r) => r.type === 'import');
217
- const urlFromImportObject = (importObject) => {
218
- const importItem = importObject['import'];
219
- const urlMatch = importItem && importItem.match(pattern);
220
- return urlMatch && urlMatch[2];
221
- };
222
- const sourceFromImportObject = (importObject) => importObject['position'] && importObject['position']['source'];
223
- const toUrlSourcePair = (importObject) => ({
224
- url: urlFromImportObject(importObject),
225
- source: sourceFromImportObject(importObject),
226
- });
227
- const getCssFile = ({ url, source }) => (source ? CSSSource.fromFileImport(url, this._keyframes, source) : CSSSource.fromURI(url, this._keyframes));
228
- const cssFiles = imports
229
- .map(toUrlSourcePair)
230
- .filter(({ url }) => !!url)
231
- .map(getCssFile);
232
- const selectors = cssFiles.map((file) => (file && file.selectors) || []);
233
- return selectors.reduce((acc, val) => acc.concat(val), []);
234
- }
235
- createSelectorsFromSyntaxTree() {
236
- const nodes = this._ast.stylesheet.rules;
237
- nodes.filter(isKeyframe).forEach((node) => (this._keyframes[node.name] = node));
238
- const rulesets = fromAstNodes(nodes);
239
- if (rulesets && rulesets.length) {
240
- ensureCssAnimationParserModule();
241
- rulesets.forEach((rule) => {
242
- rule[animationsSymbol] = cssAnimationParserModule.CssAnimationParser.keyframeAnimationsFromCSSDeclarations(rule.declarations);
243
- });
244
- }
245
- 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
+ }
246
235
  }
247
236
  toString() {
248
237
  return this._file || this._url || '(in-memory)';
@@ -271,53 +260,147 @@ __decorate([
271
260
  __metadata("design:type", Function),
272
261
  __metadata("design:paramtypes", []),
273
262
  __metadata("design:returntype", void 0)
274
- ], CSSSource.prototype, "createSelectors", null);
263
+ ], CSSSource.prototype, "createSelectorsAndKeyframes", null);
275
264
  __decorate([
276
265
  profile,
277
266
  __metadata("design:type", Function),
278
267
  __metadata("design:paramtypes", [String, String]),
279
268
  __metadata("design:returntype", String)
280
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
+ }
281
319
  export function removeTaggedAdditionalCSS(tag) {
282
- let changed = false;
320
+ let selectorsChanged = false;
321
+ let keyframesChanged = false;
322
+ let updated = false;
283
323
  for (let i = 0; i < applicationAdditionalSelectors.length; i++) {
284
324
  if (applicationAdditionalSelectors[i].tag === tag) {
285
325
  applicationAdditionalSelectors.splice(i, 1);
286
326
  i--;
287
- changed = true;
327
+ selectorsChanged = true;
288
328
  }
289
329
  }
290
- 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) {
291
338
  mergeCssSelectors();
339
+ updated = true;
340
+ }
341
+ if (keyframesChanged) {
342
+ mergeCssKeyframes();
343
+ updated = true;
292
344
  }
293
- return changed;
345
+ if (updated) {
346
+ applicationCssSelectorVersion++;
347
+ }
348
+ return updated;
294
349
  }
295
350
  export function addTaggedAdditionalCSS(cssText, tag) {
296
- const parsed = CSSSource.fromDetect(cssText, applicationKeyframes, undefined).selectors;
351
+ const { selectors, keyframes } = CSSSource.fromDetect(cssText, undefined);
297
352
  const tagScope = currentScopeTag || (tag && tagToScopeTag.has(tag) && tagToScopeTag.get(tag)) || null;
298
353
  if (tagScope && tag) {
299
354
  tagToScopeTag.set(tag, tagScope);
300
355
  }
301
- let changed = false;
302
- if (parsed && parsed.length) {
303
- changed = true;
356
+ let selectorsChanged = false;
357
+ let keyframesChanged = false;
358
+ let updated = false;
359
+ if (selectors && selectors.length) {
360
+ selectorsChanged = true;
304
361
  if (tag != null || tagScope != null) {
305
- for (let i = 0; i < parsed.length; i++) {
306
- parsed[i].tag = tag;
307
- 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;
308
365
  }
309
366
  }
310
- applicationAdditionalSelectors.push(...parsed);
367
+ applicationAdditionalSelectors.push(...selectors);
311
368
  mergeCssSelectors();
369
+ updated = true;
312
370
  }
313
- 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;
314
387
  }
315
388
  const onCssChanged = profile('"style-scope".onCssChanged', (args) => {
316
389
  if (args.cssText) {
317
- const parsed = CSSSource.fromSource(args.cssText, applicationKeyframes, args.cssFile).selectors;
318
- if (parsed) {
319
- applicationAdditionalSelectors.push(...parsed);
390
+ const { selectors, keyframes } = CSSSource.fromSource(args.cssText, args.cssFile);
391
+ let updated = false;
392
+ if (selectors) {
393
+ applicationAdditionalSelectors.push(...selectors);
320
394
  mergeCssSelectors();
395
+ updated = true;
396
+ }
397
+ if (keyframes) {
398
+ applicationAdditionalKeyframes.push(...keyframes);
399
+ mergeCssKeyframes();
400
+ updated = true;
401
+ }
402
+ if (updated) {
403
+ applicationCssSelectorVersion++;
321
404
  }
322
405
  }
323
406
  else if (args.cssFile) {
@@ -329,16 +412,28 @@ function onLiveSync(args) {
329
412
  }
330
413
  const loadCss = profile(`"style-scope".loadCss`, (cssModule) => {
331
414
  if (!cssModule) {
332
- return undefined;
415
+ return;
333
416
  }
334
417
  // safely remove "./" as global CSS should be resolved relative to app folder
335
418
  if (cssModule.startsWith('./')) {
336
- cssModule = cssModule.substr(2);
419
+ cssModule = cssModule.substring(2);
337
420
  }
338
- const result = CSSSource.fromURI(cssModule, applicationKeyframes).selectors;
339
- if (result.length > 0) {
340
- 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;
341
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++;
342
437
  }
343
438
  });
344
439
  global.NativeScriptGlobals.events.on('cssChanged', onCssChanged);
@@ -407,7 +502,7 @@ export class CssState {
407
502
  updateMatch() {
408
503
  const view = this.viewRef.get();
409
504
  if (view && view._styleScope) {
410
- this._match = view._styleScope.matchSelectors(view);
505
+ this._match = view._styleScope.matchSelectors(view) ?? CssState.emptyMatch;
411
506
  this._appliedSelectorsVersion = view._styleScope.getSelectorsVersion();
412
507
  }
413
508
  else {
@@ -422,12 +517,12 @@ export class CssState {
422
517
  return;
423
518
  }
424
519
  const matchingSelectors = this._match.selectors.filter((sel) => (sel.dynamic ? sel.match(view) : true));
425
- if (!matchingSelectors || matchingSelectors.length === 0) {
426
- // Ideally we should return here if there are no matching selectors, however
427
- // if there are property removals, returning here would not remove them
428
- // this is seen in STYLE test in automated.
429
- // return;
430
- }
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
+ // }
431
526
  view._batchUpdate(() => {
432
527
  this.stopKeyframeAnimations();
433
528
  this.setPropertyValues(matchingSelectors);
@@ -437,7 +532,7 @@ export class CssState {
437
532
  playKeyframeAnimations(matchingSelectors) {
438
533
  const animations = [];
439
534
  matchingSelectors.forEach((selector) => {
440
- const ruleAnimations = selector.ruleset[animationsSymbol];
535
+ const ruleAnimations = selector.ruleset?.[animationsSymbol];
441
536
  if (ruleAnimations) {
442
537
  ensureKeyframeAnimationModule();
443
538
  for (const animationInfo of ruleAnimations) {
@@ -648,10 +743,10 @@ export class StyleScope {
648
743
  constructor() {
649
744
  this._css = '';
650
745
  this._localCssSelectors = [];
746
+ this._localCssKeyframes = [];
651
747
  this._localCssSelectorVersion = 0;
652
748
  this._localCssSelectorsAppliedVersion = 0;
653
749
  this._applicationCssSelectorsAppliedVersion = 0;
654
- this._keyframes = new Map();
655
750
  this._cssFiles = [];
656
751
  }
657
752
  get css() {
@@ -672,17 +767,19 @@ export class StyleScope {
672
767
  }
673
768
  this._cssFiles.push(cssFileName);
674
769
  currentScopeTag = cssFileName;
675
- const cssSelectors = CSSSource.fromURI(cssFileName, this._keyframes);
770
+ const cssFile = CSSSource.fromURI(cssFileName);
676
771
  currentScopeTag = null;
677
- this._css = cssSelectors.source;
678
- this._localCssSelectors = cssSelectors.selectors;
772
+ this._css = cssFile.source;
773
+ this._localCssSelectors = cssFile.selectors;
774
+ this._localCssKeyframes = cssFile.keyframes;
679
775
  this._localCssSelectorVersion++;
680
776
  this.ensureSelectors();
681
777
  }
682
778
  setCss(cssString, cssFileName) {
683
779
  this._css = cssString;
684
- const cssFile = CSSSource.fromSource(cssString, this._keyframes, cssFileName);
780
+ const cssFile = CSSSource.fromSource(cssString, cssFileName);
685
781
  this._localCssSelectors = cssFile.selectors;
782
+ this._localCssKeyframes = cssFile.keyframes;
686
783
  this._localCssSelectorVersion++;
687
784
  this.ensureSelectors();
688
785
  }
@@ -694,22 +791,23 @@ export class StyleScope {
694
791
  this._cssFiles.push(cssFileName);
695
792
  currentScopeTag = cssFileName;
696
793
  }
697
- 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);
698
795
  currentScopeTag = null;
699
- this._css = this._css + parsedCssSelectors.source;
700
- this._localCssSelectors.push(...parsedCssSelectors.selectors);
796
+ this._css = this._css + cssFile.source;
797
+ this._localCssSelectors.push(...cssFile.selectors);
798
+ this._localCssKeyframes.push(...cssFile.keyframes);
701
799
  this._localCssSelectorVersion++;
702
800
  this.ensureSelectors();
703
801
  }
704
802
  getKeyframeAnimationWithName(animationName) {
705
- const cssKeyframes = this._keyframes[animationName];
706
- if (!cssKeyframes) {
707
- return;
803
+ if (!this._mergedCssKeyframes) {
804
+ return null;
708
805
  }
806
+ const keyframeRule = this.findKeyframeRule(animationName);
709
807
  ensureKeyframeAnimationModule();
710
808
  const animation = new keyframeAnimationModule.KeyframeAnimationInfo();
711
809
  ensureCssAnimationParserModule();
712
- animation.keyframes = cssAnimationParserModule.CssAnimationParser.keyframesArrayFromCSS(cssKeyframes.keyframes);
810
+ animation.keyframes = keyframeRule ? cssAnimationParserModule.CssAnimationParser.keyframesArrayFromCSS(keyframeRule.keyframes) : null;
713
811
  return animation;
714
812
  }
715
813
  ensureSelectors() {
@@ -729,46 +827,61 @@ export class StyleScope {
729
827
  }
730
828
  _createSelectors() {
731
829
  const toMerge = [];
732
- 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));
733
833
  this._applicationCssSelectorsAppliedVersion = applicationCssSelectorVersion;
734
- toMerge.push(this._localCssSelectors);
834
+ toMerge.push(...this._localCssSelectors);
835
+ toMergeKeyframes.push(...this._localCssKeyframes);
735
836
  this._localCssSelectorsAppliedVersion = this._localCssSelectorVersion;
736
- for (const keyframe in applicationKeyframes) {
737
- this._keyframes[keyframe] = applicationKeyframes[keyframe];
738
- }
739
837
  if (toMerge.length > 0) {
740
- this._mergedCssSelectors = toMerge.reduce((merged, next) => merged.concat(next || []), []);
741
- this._applyKeyframesOnSelectors();
742
- this._selectors = new SelectorsMap(this._mergedCssSelectors);
838
+ this._mergedCssSelectors = toMerge;
839
+ this._selectorScope = new StyleSheetSelectorScope(this._mergedCssSelectors);
743
840
  }
841
+ else {
842
+ this._mergedCssSelectors = null;
843
+ this._selectorScope = null;
844
+ }
845
+ this._mergedCssKeyframes = toMergeKeyframes.length > 0 ? toMergeKeyframes : null;
744
846
  }
745
847
  // HACK: This @profile decorator creates a circular dependency
746
848
  // HACK: because the function parameter type is evaluated with 'typeof'
747
849
  matchSelectors(view) {
850
+ let match;
748
851
  // should be (view: ViewBase): SelectorsMatch<ViewBase>
749
852
  this.ensureSelectors();
750
- 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;
751
862
  }
752
863
  query(node) {
753
864
  this.ensureSelectors();
754
- return this._selectors.query(node).selectors;
865
+ const match = this.matchSelectors(node);
866
+ return match ? match.selectors : [];
755
867
  }
756
868
  getSelectorsVersion() {
757
869
  // The counters can only go up. So we can return just appVersion + localVersion
758
870
  // The 100000 * appVersion is just for easier debugging
759
871
  return 100000 * this._applicationCssSelectorsAppliedVersion + this._localCssSelectorsAppliedVersion;
760
872
  }
761
- _applyKeyframesOnSelectors() {
762
- for (let i = this._mergedCssSelectors.length - 1; i >= 0; i--) {
763
- 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;
764
879
  const animations = ruleset[animationsSymbol];
765
- if (animations !== undefined && animations.length) {
880
+ if (animations != null && animations.length) {
766
881
  ensureCssAnimationParserModule();
767
882
  for (const animation of animations) {
768
- const cssKeyframe = this._keyframes[animation.name];
769
- if (cssKeyframe !== undefined) {
770
- animation.keyframes = cssAnimationParserModule.CssAnimationParser.keyframesArrayFromCSS(cssKeyframe.keyframes);
771
- }
883
+ const keyframeRule = this.findKeyframeRule(animation.name);
884
+ animation.keyframes = keyframeRule ? cssAnimationParserModule.CssAnimationParser.keyframesArrayFromCSS(keyframeRule.keyframes) : null;
772
885
  }
773
886
  }
774
887
  }
@@ -776,6 +889,31 @@ export class StyleScope {
776
889
  getAnimations(ruleset) {
777
890
  return ruleset[animationsSymbol];
778
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
+ }
779
917
  }
780
918
  __decorate([
781
919
  profile,
@@ -813,7 +951,7 @@ export function resolveFileNameFromUrl(url, appDirectory, fileExists, importSour
813
951
  }
814
952
  if (!isAbsolutePath) {
815
953
  if (fileName[0] === '~' && fileName[1] !== '/' && fileName[1] !== '"') {
816
- fileName = fileName.substr(1);
954
+ fileName = fileName.substring(1);
817
955
  }
818
956
  if (importSource) {
819
957
  const importFile = resolveFilePathFromImport(importSource, fileName);
@@ -842,7 +980,7 @@ function resolveFilePathFromImport(importSource, fileName) {
842
980
  }
843
981
  export const applyInlineStyle = profile(function applyInlineStyle(view, styleStr) {
844
982
  const localStyle = `local { ${styleStr} }`;
845
- const inlineRuleSet = CSSSource.fromSource(localStyle, new Map()).selectors;
983
+ const inlineRuleSet = CSSSource.fromSource(localStyle).selectors;
846
984
  // Reset unscoped css-variables
847
985
  view.style.resetUnscopedCssVariables();
848
986
  // Set all the css-variables first, so we can be sure they are up-to-date
@@ -882,7 +1020,13 @@ function isCurrentDirectory(uriPart) {
882
1020
  function isParentDirectory(uriPart) {
883
1021
  return uriPart === '..';
884
1022
  }
1023
+ function isMedia(node) {
1024
+ return node.type === 'media';
1025
+ }
885
1026
  function isKeyframe(node) {
886
1027
  return node.type === 'keyframes';
887
1028
  }
1029
+ function isRule(node) {
1030
+ return node.type === 'rule';
1031
+ }
888
1032
  //# sourceMappingURL=style-scope.js.map