@teipublisher/pb-components 1.43.0 → 1.43.1

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.
package/src/theming.js CHANGED
@@ -8,14 +8,29 @@ import { waitOnce } from "./pb-mixin.js";
8
8
  const themeMap = new Map();
9
9
 
10
10
  /**
11
- * Load a CSS stylesheet from the given URL and return
11
+ * Load one or more CSS stylesheet from the given URL and return
12
12
  * a CSSStyleSheet. The returned stylesheet can be assigned
13
13
  * to `adoptedStyleSheets`.
14
14
  *
15
- * @param {string} url absolute URL
15
+ * @param {string[]} urls absolute URL
16
16
  * @returns {Promise<CSSStyleSheet|null>} constructed CSSStyleSheet or null
17
17
  */
18
- export function loadStylesheet(url) {
18
+ export async function loadStylesheets(urls) {
19
+ const output = [];
20
+ for(let url of urls) {
21
+ const css = await loadResource(url);
22
+ if (css) {
23
+ output.push(css);
24
+ }
25
+ }
26
+ if (output.length > 0) {
27
+ const sheet = new CSSStyleSheet();
28
+ return sheet.replace(output.join(''));
29
+ }
30
+ return null;
31
+ }
32
+
33
+ function loadResource(url) {
19
34
  return fetch(url)
20
35
  .then(response => {
21
36
  if (response.ok) {
@@ -25,11 +40,7 @@ export function loadStylesheet(url) {
25
40
  return null;
26
41
  })
27
42
  .then(text => {
28
- if (text) {
29
- const stylesheet = new CSSStyleSheet();
30
- return stylesheet.replace(text);
31
- }
32
- return null;
43
+ return text;
33
44
  })
34
45
  .catch(error => {
35
46
  console.error('<theming> Error loading stylesheet %s: %o', url, error);
@@ -62,21 +73,45 @@ export function importStyles(elem) {
62
73
  const prefixRegex = new RegExp(`^(${selectors})\\b`);
63
74
  let adoptedSheet = null;
64
75
  const rules = theme.cssRules;
76
+ const newCSS = copyStyles(rules, prefixRegex, []);
77
+ if (newCSS.length > 0) {
78
+ adoptedSheet = new CSSStyleSheet();
79
+ adoptedSheet.replaceSync(newCSS.join(''));
80
+ }
81
+ console.log('<theming> caching stylesheet for %s', selectors);
82
+ themeMap.set(selectors, adoptedSheet);
83
+ return adoptedSheet;
84
+ }
85
+
86
+ /**
87
+ * Recursively copy matching styles from the theme CSS
88
+ * to create a new CSS stylesheet having all styles required
89
+ * by the component.
90
+ *
91
+ * @param {CSSRule[]} rules
92
+ * @param {RegExp} prefixRegex
93
+ * @param {string[]} output
94
+ * @returns {string[]}
95
+ */
96
+ function copyStyles(rules, prefixRegex, output) {
65
97
  for (let i = 0; i < rules.length; i++) {
66
98
  const rule = rules[i];
67
99
  if (rule instanceof CSSStyleRule) {
68
100
  if (prefixRegex.test(rule.selectorText)) {
69
- const selector = rule.cssText.replace(prefixRegex, `:host($1) `);
70
- if (!adoptedSheet) {
71
- adoptedSheet = new CSSStyleSheet();
72
- }
73
- adoptedSheet.insertRule(selector);
101
+ const css = rule.cssText.replace(prefixRegex, `:host($1) `);
102
+ output.push(css);
74
103
  }
104
+ } else if (rule instanceof CSSMediaRule) {
105
+ output.push(`\n@media ${rule.conditionText} {\n`);
106
+ copyStyles(rule.cssRules, prefixRegex, output);
107
+ output.push('\n}\n');
108
+ } else if (rule instanceof CSSFontFaceRule) {
109
+ // not allowed in constructed stylesheets
110
+ } else {
111
+ output.push(rule.cssText);
75
112
  }
76
113
  }
77
- console.log('<theming> caching stylesheet for %s', selectors);
78
- themeMap.set(selectors, adoptedSheet);
79
- return adoptedSheet;
114
+ return output;
80
115
  }
81
116
 
82
117
  /**