Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion labs/gb/styles/adopt-styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,15 @@ function adopt(
stylesheets: CSSStyleSheet[],
): node is DocumentOrShadowRoot {
if (node && 'adoptedStyleSheets' in node) {
const unadopted = stylesheets.filter(
(stylesheet) => !node.adoptedStyleSheets.includes(stylesheet),
);
if (!unadopted.length) {
// All styles are already adopted.
return true;
}
node.adoptedStyleSheets = Array.from(
new Set([...node.adoptedStyleSheets, ...stylesheets]),
new Set([...node.adoptedStyleSheets, ...unadopted]),
);
return true;
}
Expand Down
34 changes: 34 additions & 0 deletions labs/gb/styles/adopt-styles_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,40 @@ describe('adoptStyles()', () => {
.toContain(sheet);
});

it('should not duplicate stylesheets if already adopted', () => {
adoptStyles(document, sheet);
adoptStyles(document, sheet);

expect(document.adoptedStyleSheets)
.withContext('document.adoptedStyleSheets')
.toHaveSize(1);
});

it('should only adopt new stylesheets when given an array that includes adopted sheets', () => {
const alreadyAdopted = new CSSStyleSheet();
adoptStyles(document, alreadyAdopted);
adoptStyles(document, [sheet, alreadyAdopted]);

expect(document.adoptedStyleSheets)
.withContext('document.adoptedStyleSheets')
.toHaveSize(2);
});

it('should not mutate adoptedStyleSheets if the sheets are already adopted', () => {
adoptStyles(document, sheet);
const previousAdoptedStyleSheets = document.adoptedStyleSheets;
const previousSize = previousAdoptedStyleSheets.length;

adoptStyles(document, sheet);

expect(document.adoptedStyleSheets)
.withContext('document.adoptedStyleSheets')
.toBe(previousAdoptedStyleSheets);
expect(document.adoptedStyleSheets)
.withContext('document.adoptedStyleSheets')
.toHaveSize(previousSize);
});

it("should adopt to an Element's document", () => {
const element = document.createElement('div');
adoptStyles(element, sheet);
Expand Down
3 changes: 3 additions & 0 deletions labs/gb/styles/icon/md-icon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import {type CSSResultOrNative} from 'lit';
import {customElement} from 'lit/decorators.js';
import {Icon as IconBase} from '../../../../icon/internal/icon.js';
import {adoptStyles} from '../adopt-styles.js';

import iconStyles from './md-icon.css' with {type: 'css'}; // github-only
// import iconStyles from './md-icon.cssresult.js'; // google3-only
Expand All @@ -27,6 +28,8 @@ export class Icon extends IconBase {

override connectedCallback() {
super.connectedCallback();
// Adopt stylesheet to ensure global CSS @property variables are registered.
adoptStyles(this, iconStyles);
this.classList.add('md-icon');
}
}
Loading