diff --git a/packages/core/css/system-classes.ts b/packages/core/css/system-classes.ts index 3c1edadcb9..a40e6a6607 100644 --- a/packages/core/css/system-classes.ts +++ b/packages/core/css/system-classes.ts @@ -6,6 +6,7 @@ export namespace CSSUtils { export const CLASS_PREFIX = 'ns-'; export const MODAL_ROOT_VIEW_CSS_CLASS = `${CLASS_PREFIX}${MODAL}`; export const ROOT_VIEW_CSS_CLASS = `${CLASS_PREFIX}${ROOT}`; + export const IgnoredCssDynamicAttributeTracking = new Set(); export function getSystemCssClasses(): string[] { return cssClasses; diff --git a/packages/core/ui/styling/css-selector.ts b/packages/core/ui/styling/css-selector.ts index b7c7ab5a41..3a105fc743 100644 --- a/packages/core/ui/styling/css-selector.ts +++ b/packages/core/ui/styling/css-selector.ts @@ -5,6 +5,7 @@ import { Trace } from '../../trace'; import { isNullOrUndefined } from '../../utils/types'; import * as ReworkCSS from '../../css'; +import { CSSUtils } from '../../css/system-classes'; /** * An interface describing the shape of a type on which the selectors may apply. @@ -1014,6 +1015,9 @@ export class SelectorsMatch implements ChangeAccumulator { public selectors: SelectorCore[]; public addAttribute(node: T, attribute: string): void { + if (CSSUtils.IgnoredCssDynamicAttributeTracking.has(attribute)) { + return; + } const deps: Changes = this.properties(node); if (!deps.attributes) { deps.attributes = new Set(); diff --git a/packages/core/ui/styling/style-scope.ts b/packages/core/ui/styling/style-scope.ts index a71ff6f9ec..c933383db6 100644 --- a/packages/core/ui/styling/style-scope.ts +++ b/packages/core/ui/styling/style-scope.ts @@ -22,6 +22,7 @@ import * as capm from './css-animation-parser'; import { sanitizeModuleName } from '../../utils/common'; import { resolveModuleName } from '../../module-name-resolver'; import { cleanupImportantFlags } from './css-utils'; +import { Observable, PropertyChangeData } from '../../data/observable'; let cssAnimationParserModule: typeof capm; function ensureCssAnimationParserModule() { @@ -418,6 +419,8 @@ export class CssState { _matchInvalid: boolean; _playsKeyframeAnimations: boolean; + private _dynamicUpdateListenerMap: Map void> = new Map(); + constructor(private viewRef: WeakRef) { this._onDynamicStateChangeHandler = () => this.updateDynamicState(); } @@ -650,9 +653,14 @@ export class CssState { const changeMap = this._match.changeMap; changeMap.forEach((changes, view) => { if (changes.attributes) { - changes.attributes.forEach((attribute) => { - view.addEventListener(attribute + 'Change', this._onDynamicStateChangeHandler); - }); + const attributes = changes.attributes; + const listener = (args: PropertyChangeData) => { + if (attributes.has(args.propertyName)) { + this._onDynamicStateChangeHandler(); + } + }; + this._dynamicUpdateListenerMap.set(view, listener); + view.addEventListener(Observable.propertyChangeEvent, listener); } if (changes.pseudoClasses) { changes.pseudoClasses.forEach((pseudoClass) => { @@ -669,10 +677,8 @@ export class CssState { private unsubscribeFromDynamicUpdates(): void { this._appliedChangeMap.forEach((changes, view) => { - if (changes.attributes) { - changes.attributes.forEach((attribute) => { - view.removeEventListener(attribute + 'Change', this._onDynamicStateChangeHandler); - }); + if (this._dynamicUpdateListenerMap.has(view)) { + view.removeEventListener(Observable.propertyChangeEvent, this._dynamicUpdateListenerMap.get(view)); } if (changes.pseudoClasses) { changes.pseudoClasses.forEach((pseudoClass) => { @@ -684,6 +690,7 @@ export class CssState { }); } }); + this._dynamicUpdateListenerMap.clear(); this._appliedChangeMap = CssState.emptyChangeMap; }