@@ -213,7 +213,7 @@ export default class ElementStyleObserver {
213
213
*/
214
214
updateTransitionProperties ( ) {
215
215
// Clear our own transition
216
- this . target . style . setProperty ( "--style-observer-transition" , "" ) ;
216
+ this . setProperty ( "--style-observer-transition" , "" ) ;
217
217
218
218
let transitionProperties = new Set (
219
219
getComputedStyle ( this . target ) . transitionProperty . split ( ", " ) ,
@@ -232,7 +232,7 @@ export default class ElementStyleObserver {
232
232
. map ( property => `${ property } 1ms step-start${ allowDiscrete } ` )
233
233
. join ( ", " ) ;
234
234
235
- this . target . style . setProperty ( "--style-observer-transition" , transition ) ;
235
+ this . setProperty ( "--style-observer-transition" , transition ) ;
236
236
}
237
237
238
238
/**
@@ -247,7 +247,7 @@ export default class ElementStyleObserver {
247
247
*/
248
248
updateTransition ( { firstTime } = { } ) {
249
249
const sot = "var(--style-observer-transition, --style-observer-noop)" ;
250
- const inlineTransition = this . target . style . transition ;
250
+ const inlineTransition = this . getProperty ( " transition" ) ;
251
251
let transition ;
252
252
253
253
// NOTE This code assumes that if there is an inline style, it takes precedence over other styles
@@ -260,7 +260,7 @@ export default class ElementStyleObserver {
260
260
if ( transition === undefined && ( firstTime || ! this . #inlineTransition) ) {
261
261
// Just update based on most current computed style
262
262
if ( inlineTransition . includes ( sot ) ) {
263
- this . target . style . transition = "" ;
263
+ this . setProperty ( " transition" , "" ) ;
264
264
}
265
265
266
266
transition = getComputedStyle ( this . target ) . transition ;
@@ -274,11 +274,85 @@ export default class ElementStyleObserver {
274
274
// transition: all, var(--style-observer-transition, all);
275
275
// so we can't just concatenate with whatever the existing value is
276
276
const prefix = transition ? transition + ", " : "" ;
277
- this . target . style . setProperty ( "transition" , prefix + sot ) ;
277
+ this . setProperty ( "transition" , prefix + sot ) ;
278
278
279
279
this . updateTransitionProperties ( ) ;
280
280
}
281
281
282
+ /**
283
+ * Whether the target has an open shadow root (and the modern adoptedStyleSheets API is supported).
284
+ * @type { boolean }
285
+ * @private
286
+ */
287
+ get _isHost ( ) {
288
+ return (
289
+ this . target . shadowRoot && ! Object . isFrozen ( this . target . shadowRoot . adoptedStyleSheets )
290
+ ) ;
291
+ }
292
+
293
+ /**
294
+ * Shadow style sheet. Only used if _isHost is true.
295
+ * @type { CSSStyleSheet | undefined }
296
+ * @private
297
+ */
298
+ _shadowSheet ;
299
+
300
+ /**
301
+ * Any styles we've set on the target, for any reason.
302
+ * @type { Record<string, string> }
303
+ * @private
304
+ */
305
+ _styles = { } ;
306
+
307
+ /**
308
+ * Set a CSS property on the target.
309
+ * @param {string } property
310
+ * @param {string } value
311
+ * @return {void }
312
+ */
313
+ setProperty ( property , value ) {
314
+ let inlineStyle = this . target . style ;
315
+ let style = inlineStyle ;
316
+ if ( this . _isHost ) {
317
+ // This has an open shadow root.
318
+ // We can use an adopted shadow style to avoid manipulating its style attribute
319
+ if ( ! this . _shadowSheet ) {
320
+ this . _shadowSheet = new CSSStyleSheet ( ) ;
321
+ this . _shadowSheet . insertRule ( `:host { }` ) ;
322
+ this . target . shadowRoot . adoptedStyleSheets . push ( this . _shadowSheet ) ;
323
+
324
+ if ( Object . keys ( this . _styles ) . length > 0 ) {
325
+ // It was previously not a host, so we need to port the properties over
326
+ for ( let property in this . _styles ) {
327
+ let value = this . _styles [ property ] ;
328
+ this . setProperty ( property , value ) ;
329
+
330
+ // Remove from inline style if it hasn't changed externally
331
+ if ( inlineStyle . getPropertyValue ( property ) === value ) {
332
+ inlineStyle . removeProperty ( property ) ;
333
+ }
334
+ }
335
+ }
336
+ }
337
+
338
+ style = this . _shadowSheet . cssRules [ 0 ] . style ;
339
+ }
340
+
341
+ style . setProperty ( property , value ) ;
342
+ // Store reserialized value for later comparison
343
+ this . _styles [ property ] = this . getProperty ( property ) ;
344
+ }
345
+
346
+ /**
347
+ * Get a CSS property from the target.
348
+ * @param {string } property
349
+ * @return {string }
350
+ */
351
+ getProperty ( property ) {
352
+ let style = this . _shadowSheet ?. cssRules [ 0 ] ?. style ?? this . target . style ;
353
+ return style . getPropertyValue ( property ) ;
354
+ }
355
+
282
356
/**
283
357
* Stop observing a target for changes to one or more CSS properties.
284
358
* @param { string | string[] } [properties] Properties to stop observing. Defaults to all observed properties.
0 commit comments