|
1 | 1 | import { isServer } from 'lit'; |
2 | 2 |
|
3 | | -function isStyleRule(rule: CSSRule): rule is CSSStyleRule { |
4 | | - return rule != null && 'style' in rule; |
5 | | -} |
6 | | - |
| 3 | +/** |
| 4 | + * Converts a CSS custom property name to a camelCase JavaScript key. |
| 5 | + * Removes leading '--' and converts kebab-case to camelCase. |
| 6 | + * @param key - The CSS variable name (e.g., '--my-color') |
| 7 | + * @returns The JavaScript key (e.g., 'myColor') |
| 8 | + */ |
7 | 9 | function cssKeyToJsKey(key: string): string { |
| 10 | + // Regex: matches '--' at start OR '-x' pattern to convert to camelCase |
8 | 11 | return key.replace(/^--|-./g, (match) => { |
9 | 12 | return match.startsWith('--') ? '' : match.charAt(1).toUpperCase(); |
10 | 13 | }); |
11 | 14 | } |
12 | 15 |
|
13 | | -function getAllCssVariableNames(): Set<string> { |
14 | | - const cssVars = new Set<string>(); |
15 | | - const styleSheets = Array.from(document.styleSheets); |
16 | | - |
17 | | - for (const sheet of styleSheets) { |
18 | | - let rules: CSSRuleList | undefined; |
19 | | - |
20 | | - // Potential CORS or access errors |
21 | | - try { |
22 | | - rules = sheet.cssRules; |
23 | | - } catch { |
24 | | - continue; |
25 | | - } |
26 | | - |
27 | | - if (!rules) { |
28 | | - continue; |
29 | | - } |
30 | | - |
31 | | - for (const rule of Array.from(rules)) { |
32 | | - if (isStyleRule(rule)) { |
33 | | - const length = rule.style.length; |
34 | | - |
35 | | - for (let i = 0; i < length; i++) { |
36 | | - const style = rule.style[i]; |
37 | | - |
38 | | - if (style.startsWith('--')) { |
39 | | - cssVars.add(style); |
40 | | - } |
41 | | - } |
42 | | - } |
43 | | - } |
44 | | - } |
45 | | - |
46 | | - return cssVars; |
47 | | -} |
48 | | - |
49 | | -function getElementCssVariables( |
50 | | - allCssVars: Set<string>, |
51 | | - element: HTMLElement, |
52 | | - pseudo?: string |
53 | | -): Record<string, string> { |
54 | | - const cssVars: Record<string, string> = {}; |
55 | | - const styles = getComputedStyle(element, pseudo); |
56 | | - |
57 | | - for (const key of allCssVars) { |
58 | | - const value = styles.getPropertyValue(key); |
| 16 | +function getCssVariables(): Record<string, string> { |
| 17 | + const rootStyles = getComputedStyle(document.documentElement); |
| 18 | + const result: Record<string, string> = {}; |
59 | 19 |
|
60 | | - if (value) { |
61 | | - cssVars[cssKeyToJsKey(key)] = value.trim(); |
| 20 | + for (const key of Array.from(rootStyles)) { |
| 21 | + if (key.startsWith('--')) { |
| 22 | + result[cssKeyToJsKey(key)] = rootStyles.getPropertyValue(key).trim(); |
62 | 23 | } |
63 | 24 | } |
64 | 25 |
|
65 | | - return cssVars; |
| 26 | + return result; |
66 | 27 | } |
67 | 28 |
|
| 29 | +/** |
| 30 | + * Retrieves all CSS custom properties from the document root element. |
| 31 | + * Property names are converted from kebab-case to camelCase. |
| 32 | + * |
| 33 | + * @returns An object mapping camelCase property names to their values. |
| 34 | + * Returns an empty object in SSR environments. |
| 35 | + * @example |
| 36 | + * // CSS: --my-primary-color: #ff0000; |
| 37 | + * // Returns: { myPrimaryColor: '#ff0000' } |
| 38 | + */ |
68 | 39 | export function getAllCssVariables(): Record<string, string> { |
69 | | - /* c8 ignore next 2 */ |
70 | | - return isServer |
71 | | - ? {} |
72 | | - : getElementCssVariables( |
73 | | - getAllCssVariableNames(), |
74 | | - document.documentElement |
75 | | - ); |
| 40 | + return isServer ? {} : getCssVariables(); |
76 | 41 | } |
0 commit comments