All files / packages/design-system-2/.storybook/decorators apply-theme-stylesheets.ts

96.55% Statements 28/29
100% Branches 12/12
80% Functions 4/5
100% Lines 26/26

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 651x         1x                         15x     15x 19x 19x 4x       15x     15x 37x   37x 15x     22x 22x 22x     22x 7x   22x 22x   40x 22x       22x 22x 4x   18x       15x    
export const PEARL_STYLESHEET = {
  ID: 'pearl-theme',
  HREF: 'css/slds2.theme.pearl.css',
} as const;
 
const LINK_CLASS = 'slds-theme-link';
 
/**
 * Loads an array of theme CSS paths as <link> elements in <head>.
 * Removes any previously managed theme links that are no longer needed.
 * New links are inserted before Pearl, so Pearl wins the cascade.
 * Returns a promise that resolves once every new stylesheet has loaded.
 *
 * @param {string[]} hrefs CSS paths to load (served from Storybook staticDirs).
 * @returns {Promise<void>}
 */
export function applyThemeStylesheets(hrefs: string[]) {
  // Find all existing `theme` links.
  const existing = document.querySelectorAll(`link.${LINK_CLASS}`);
 
  // Remove links that are no longer needed.
  for (const link of existing) {
    const href = link.getAttribute('href');
    if (!href || !hrefs.includes(href)) {
      link.remove();
    }
  }
 
  const loadPromises: Array<Promise<void>> = [];
 
  // For each href, reuse or create a <link>. Place links before Pearl.
  for (const href of hrefs) {
    const existingLink = document.querySelector<HTMLLinkElement>(`link.${LINK_CLASS}[href="${href}"]`);
 
    if (existingLink) {
      continue; // jump to the next href
    }
 
    const link = document.createElement('link');
    link.rel = 'stylesheet';
    link.className = LINK_CLASS;
 
    // Assign id to Pearl
    if (href === PEARL_STYLESHEET.HREF) {
      link.id = PEARL_STYLESHEET.ID;
    }
    link.setAttribute('href', href);
    loadPromises.push(
      new Promise((resolve) => {
        link.onload = () => resolve();
        link.onerror = () => resolve();
      }),
    );
 
    const pearl = document.getElementById(PEARL_STYLESHEET.ID);
    if (pearl) {
      pearl.before(link); // Pearl theme must come last
    } else {
      document.head.appendChild(link);
    }
  }
 
  return loadPromises.length > 0 ? Promise.all(loadPromises).then(() => undefined) : Promise.resolve();
}