+34
-13
@@ -464,14 +464,35 @@ (function (global, factory) { | ||
| const makeCssVars = (theme = {}, prefix = '--') => { | ||
| return Object.keys(theme).reduce((acc, key) => { | ||
| const value = theme[key]; | ||
| if (isObject(value)) { | ||
| Object.assign(acc, makeCssVars(value, `${prefix}-${key}`)); | ||
| } else if (typeof value !== 'undefined' && value !== null) { | ||
| acc[`${prefix}-${key}`] = value; | ||
| } | ||
| return acc; | ||
| }, {}); | ||
| /** | ||
| * Flattens a nested theme object into a map of CSS variable names to values. | ||
| * Nested keys are joined with `-` (e.g. `{ colors: { primary: 'blue' } }` → `--prefix-colors-primary`). | ||
| * @private | ||
| * @param {Object} [theme={}] - Nested theme object. | ||
| * @param {string|null} [prefix] - Prefix for variable names (e.g. `fun` → `--fun-key`). Omit or pass `null`/`''` for no prefix. | ||
| * @returns {Object} Map of CSS variable names (e.g. `--fun-color`) to values. | ||
| */ | ||
| const makeCssVars = (theme = {}, prefix) => { | ||
| function build(theme, nameAcc) { | ||
| return Object.keys(theme).reduce((acc, key) => { | ||
| const value = theme[key]; | ||
| const name = nameAcc ? `${nameAcc}-${key}` : prefix ? `--${prefix}-${key}` : `--${key}`; | ||
| if (isObject(value)) { | ||
| Object.assign(acc, build(value, name)); | ||
| } else if (typeof value !== 'undefined' && value !== null) { | ||
| acc[name] = value; | ||
| } | ||
| return acc; | ||
| }, {}); | ||
| } | ||
| return build(theme); | ||
| }; | ||
| /** | ||
| * Returns keys that differ between two objects, with each side’s value. | ||
| * @private | ||
| * @param {Object} left - First object. | ||
| * @param {Object} right - Second object. | ||
| * @returns {{ left: Object, right: Object }} Objects containing only the differing keys and their values per side. | ||
| */ | ||
| const getDiff = (left, right) => { | ||
@@ -512,4 +533,4 @@ return Object.keys(left).reduce((acc, key) => { | ||
| * | ||
| * @param {String} [options.cssVarsPrefix] - The prefix for the generated CSS variables. Default is `fun`. | ||
| * For example, a key `color` in the theme will generate a CSS variable like `--fun-color`. | ||
| * @param {String|null} [options.cssVarsPrefix] - Prefix for the generated CSS variables. Defaults to `StyleSheet.prefix`. | ||
| * Pass `null` or `''` to generate variables without a prefix (e.g. `--color` instead of `--fun-color`). | ||
| * | ||
@@ -560,3 +581,3 @@ * @param {Function} [options.createStyleSheet] - A function used to create a new StyleSheet instance. | ||
| const colorScheme = options.colorScheme || 'light dark'; | ||
| const prefix = `--${options.cssVarsPrefix || StyleSheet.prefix}`; | ||
| const prefix = 'cssVarsPrefix' in options ? options.cssVarsPrefix : StyleSheet.prefix; | ||
@@ -563,0 +584,0 @@ let styles; |
@@ -1,2 +0,2 @@ | ||
| !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).CSSFUN={})}(this,(function(e){"use strict";const t=e=>null!==e&&"object"==typeof e&&!Array.isArray(e),s=["prefix","generateUid","generateClassName","shouldAttachToDOM","attributes","renderers"];class r{constructor(e,t={}){this.styles=e,this.classes={},s.forEach((e=>{e in t&&(this[e]=t[e])})),this.renderers||(this.renderers=[this.renderStyles,this.parseStyles]),this.prefix||(this.prefix=r.prefix),this.uid=this.generateUid();let i=0;Object.keys(e).forEach((e=>{e.match(r.classRegex)&&(this.classes[e]=this.generateClassName(e,++i))}))}generateUid(){const e=JSON.stringify(this.styles);let t=2166136261;for(let s=0;s<e.length;s++)t^=e.charCodeAt(s),t=16777619*t>>>0;return t.toString(36)}generateClassName(e,t){return`${this.prefix[0]}-${this.uid}-${t}`}render(){const e=this.renderers.map((e=>("string"==typeof e?this[e]:e).bind(this)));return e.reduce(((e,t)=>(...s)=>e(t(...s))))(this.styles)}renderStyles(e,s=1){return Object.keys(e).reduce(((r,i)=>{const n=e[i];if(t(n)){if(Object.keys(n).length>0){const e=this.renderStyles(n,s+1);r.push(`${i}{${e}}`)}}else null!=n&&r.push(`${i}:${n};`);return r}),[]).join("")}parseStyles(e,s,i,n){const l=e=>e in this.classes?`.${this.classes[e]}`:e,c=e=>n&&i?`${i} ${e}`:e.match(r.globalPrefixRegex)?`${i?`${i} `:""}${e.replace(r.globalPrefixRegex,"")}`:l(e).replace(r.referenceRegex,((e,t)=>l(t))).replace(r.nestedRegex,i);return Object.keys(e).reduce(((n,l)=>{const h=e[l];if(t(h))if(l.match(r.globalRegex))Object.assign(s||n,this.parseStyles(h,n,i,!0));else if((l.match(r.nestedRegex)||l.match(r.globalPrefixRegex))&&s){const e=c(l);s[e]={},Object.assign(s[e],this.parseStyles(h,s,e))}else{const e=c(l);n[e]={};const t=e.match(/@/)?[]:[n,e];Object.assign(n[e],this.parseStyles(h,...t))}else null!=h&&(n[l.match(/-/)?l:(o=l,o.replace(/([A-Z])/g,(e=>`-${e[0].toLowerCase()}`)))]=h);var o;return n}),{})}getAttributes(){const e=Object.assign({},this.attributes);return e[`data-${this.prefix}-uid`]=this.uid,e}toString(){const e=this.getAttributes();return`<style${Object.keys(e).map((t=>` ${t}="${e[t]}"`)).join("")}>${this.render()}</style>`}shouldAttachToDOM(){return"undefined"!=typeof document&&!document.querySelector(`style[data-${this.prefix}-uid="${this.uid}"]`)}attach(){if(r.registry.some((({uid:e})=>e===this.uid))||r.registry.push(this),this.shouldAttachToDOM()){this.el=document.createElement("style");const e=this.getAttributes();Object.keys(e).forEach((t=>{this.el.setAttribute(t,e[t])})),this.el.textContent=this.render(),document.head.appendChild(this.el)}return this}destroy(){const e=r.registry.indexOf(this);return e>-1&&r.registry.splice(e,1),this.el&&(this.el.parentNode&&this.el.parentNode.removeChild(this.el),this.el=null),this}static toString(){return r.registry.join("")}static toCSS(){return r.registry.map((e=>e.render())).join("")}static destroy(){r.registry.slice().forEach((e=>e.destroy()))}}r.classRegex=/^\w+$/,r.globalRegex=/^@global$/,r.globalPrefixRegex=/^@global\s+/,r.referenceRegex=/\$(\w+)/g,r.nestedRegex=/&/g,r.prefix="fun",r.indent=" ",r.registry=[],r.debug=!1;const i=(e,t)=>new r(e,t).attach(),n=(e={},s="--")=>Object.keys(e).reduce(((r,i)=>{const l=e[i];return t(l)?Object.assign(r,n(l,`${s}-${i}`)):null!=l&&(r[`${s}-${i}`]=l),r}),{});e.StyleSheet=r,e.createTheme=(e={},t={})=>{const s=t.colorScheme||"light dark",l=`--${t.cssVarsPrefix||r.prefix}`;let c;if("light dark"===s){const t={light:n(e.light,l),dark:n(e.dark,l)},s=(h=t.light,o=t.dark,Object.keys(h).reduce(((e,t)=>(h[t]!==o[t]&&(e.left[t]=h[t],e.right[t]=o[t]),e)),{left:{},right:{}}));c={root:{":where(&)":Object.assign({colorScheme:"light"},t.light),':where([data-color-scheme="dark"] &)':Object.assign({colorScheme:"dark"},s.right)},"@media (prefers-color-scheme: dark)":{":where($root)":Object.assign({colorScheme:"dark"},s.right),':where([data-color-scheme="light"] $root)':Object.assign({colorScheme:"light"},s.left)}}}else c={root:{":where(&)":Object.assign({colorScheme:s},n(e[s],l))}};var h,o;return(t.createStyleSheet||i)(c,t.styleSheetOptions)},e.css=i})); | ||
| !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).CSSFUN={})}(this,function(e){"use strict";const t=e=>null!==e&&"object"==typeof e&&!Array.isArray(e),s=["prefix","generateUid","generateClassName","shouldAttachToDOM","attributes","renderers"];class r{constructor(e,t={}){this.styles=e,this.classes={},s.forEach(e=>{e in t&&(this[e]=t[e])}),this.renderers||(this.renderers=[this.renderStyles,this.parseStyles]),this.prefix||(this.prefix=r.prefix),this.uid=this.generateUid();let i=0;Object.keys(e).forEach(e=>{e.match(r.classRegex)&&(this.classes[e]=this.generateClassName(e,++i))})}generateUid(){const e=JSON.stringify(this.styles);let t=2166136261;for(let s=0;s<e.length;s++)t^=e.charCodeAt(s),t=16777619*t>>>0;return t.toString(36)}generateClassName(e,t){return`${this.prefix[0]}-${this.uid}-${t}`}render(){const e=this.renderers.map(e=>("string"==typeof e?this[e]:e).bind(this));return e.reduce((e,t)=>(...s)=>e(t(...s)))(this.styles)}renderStyles(e,s=1){return Object.keys(e).reduce((r,i)=>{const n=e[i];if(t(n)){if(Object.keys(n).length>0){const e=this.renderStyles(n,s+1);r.push(`${i}{${e}}`)}}else null!=n&&r.push(`${i}:${n};`);return r},[]).join("")}parseStyles(e,s,i,n){const c=e=>e in this.classes?`.${this.classes[e]}`:e,l=e=>n&&i?`${i} ${e}`:e.match(r.globalPrefixRegex)?`${i?`${i} `:""}${e.replace(r.globalPrefixRegex,"")}`:c(e).replace(r.referenceRegex,(e,t)=>c(t)).replace(r.nestedRegex,i);return Object.keys(e).reduce((n,c)=>{const h=e[c];if(t(h))if(c.match(r.globalRegex))Object.assign(s||n,this.parseStyles(h,n,i,!0));else if((c.match(r.nestedRegex)||c.match(r.globalPrefixRegex))&&s){const e=l(c);s[e]={},Object.assign(s[e],this.parseStyles(h,s,e))}else{const e=l(c);n[e]={};const t=e.match(/@/)?[]:[n,e];Object.assign(n[e],this.parseStyles(h,...t))}else null!=h&&(n[c.match(/-/)?c:(o=c,o.replace(/([A-Z])/g,e=>`-${e[0].toLowerCase()}`))]=h);var o;return n},{})}getAttributes(){const e=Object.assign({},this.attributes);return e[`data-${this.prefix}-uid`]=this.uid,e}toString(){const e=this.getAttributes();return`<style${Object.keys(e).map(t=>` ${t}="${e[t]}"`).join("")}>${this.render()}</style>`}shouldAttachToDOM(){return"undefined"!=typeof document&&!document.querySelector(`style[data-${this.prefix}-uid="${this.uid}"]`)}attach(){if(r.registry.some(({uid:e})=>e===this.uid)||r.registry.push(this),this.shouldAttachToDOM()){this.el=document.createElement("style");const e=this.getAttributes();Object.keys(e).forEach(t=>{this.el.setAttribute(t,e[t])}),this.el.textContent=this.render(),document.head.appendChild(this.el)}return this}destroy(){const e=r.registry.indexOf(this);return e>-1&&r.registry.splice(e,1),this.el&&(this.el.parentNode&&this.el.parentNode.removeChild(this.el),this.el=null),this}static toString(){return r.registry.join("")}static toCSS(){return r.registry.map(e=>e.render()).join("")}static destroy(){r.registry.slice().forEach(e=>e.destroy())}}r.classRegex=/^\w+$/,r.globalRegex=/^@global$/,r.globalPrefixRegex=/^@global\s+/,r.referenceRegex=/\$(\w+)/g,r.nestedRegex=/&/g,r.prefix="fun",r.indent=" ",r.registry=[],r.debug=!1;const i=(e,t)=>new r(e,t).attach(),n=(e={},s)=>function e(r,i){return Object.keys(r).reduce((n,c)=>{const l=r[c],h=i?`${i}-${c}`:s?`--${s}-${c}`:`--${c}`;return t(l)?Object.assign(n,e(l,h)):null!=l&&(n[h]=l),n},{})}(e);e.StyleSheet=r,e.createTheme=(e={},t={})=>{const s=t.colorScheme||"light dark",c="cssVarsPrefix"in t?t.cssVarsPrefix:r.prefix;let l;if("light dark"===s){const t={light:n(e.light,c),dark:n(e.dark,c)},s=(h=t.light,o=t.dark,Object.keys(h).reduce((e,t)=>(h[t]!==o[t]&&(e.left[t]=h[t],e.right[t]=o[t]),e),{left:{},right:{}}));l={root:{":where(&)":Object.assign({colorScheme:"light"},t.light),':where([data-color-scheme="dark"] &)':Object.assign({colorScheme:"dark"},s.right)},"@media (prefers-color-scheme: dark)":{":where($root)":Object.assign({colorScheme:"dark"},s.right),':where([data-color-scheme="light"] $root)':Object.assign({colorScheme:"light"},s.left)}}}else l={root:{":where(&)":Object.assign({colorScheme:s},n(e[s],c))}};var h,o;return(t.createStyleSheet||i)(l,t.styleSheetOptions)},e.css=i}); | ||
| //# sourceMappingURL=cssfun.min.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"cssfun.min.js","sources":["../src/utils/isObject.js","../src/StyleSheet.js","../src/utils/dev.js","../src/css.js","../src/createTheme.js"],"sourcesContent":["/**\n * Check if a value is an object.\n * @param {any} value - The value to check.\n * @returns {boolean} True if the value is an object, false otherwise.\n * @module\n * @private\n */\nconst isObject = value =>\n value !== null && typeof value === 'object' && !Array.isArray(value);\n\nexport default isObject;\n","import isObject from './utils/isObject.js';\nimport __DEV__ from './utils/dev.js';\n\nconst camelizedToDashed = str => str.replace(/([A-Z])/g, (g) => `-${g[0].toLowerCase()}`);\nconst compose = fns => fns.reduce((f, g) => (...args) => f(g(...args)));\n\nconst styleSheetOptions = ['prefix', 'generateUid', 'generateClassName', 'shouldAttachToDOM', 'attributes', 'renderers'];\n\n/**\n * The StyleSheet class is responsible for creating and managing a CSS stylesheet.\n * It takes a styles object and an optional options object as input, processes the styles, \n * and generates a CSS stylesheet that can be attached to the DOM, destroyed, or \n * rendered as a string for server-side rendering.\n * \n * @module\n * @class\n * @param {Object} styles - The styles object. This is an object where keys represent \n * CSS selectors and values are style objects. The styles object is processed through \n * the renderers to generate the final CSS string. It is stored in the instance as `this.styles`.\n * @param {Object} [options={}] - Configuration options. The following options are assigned to the instance (`this`):\n * `prefix`, `generateUid`, `generateClassName`, `shouldAttachToDOM`, `attributes`, `renderers`.\n * @param {String} [options.prefix='fun'] - Prefix for generating unique identifiers and data attributes.\n * @param {Function} [options.generateUid] - Custom function to generate the unique identifier.\n * @param {Function} [options.generateClassName] - Custom function to generate unique class names.\n * @param {Object} [options.attributes] - Attributes to be added to the `<style>` element.\n * @param {Array} [options.renderers=['parseStyles', 'renderStyles']] - Array of renderer functions or method names.\n * Renderers are composed in sequence. Strings or functions are automatically bound to `this`.\n * @param {Function} [options.shouldAttachToDOM] - Custom function to determine whether the StyleSheet should be added to the DOM.\n * \n * @example\n * // Create a new StyleSheet instance with a styles object.\n * const instance = new StyleSheet({\n * root: {\n * color: 'black'\n * }\n * });\n * \n * // Attach the StyleSheet instance to the DOM.\n * instance.attach();\n * \n * // Retrieve the generated classes object from the instance.\n * const { classes } = instance;\n * \n * // Use the generated class name in your component.\n * function Header() {\n * return <h1 className={classes.root}>Hello World</h1>;\n * }\n * \n * @property {Object} classes - Object mapping original class names to generated unique class names.\n * @property {Object} styles - The original styles object provided to the instance.\n * @property {String} uid - Unique identifier for the StyleSheet instance, generated using `this.generateUid`.\n * @property {String} prefix - Prefix for generating unique identifiers. Set via options or subclass.\n * @property {Object} attributes - Attributes to be added to the `<style>` element. Set via options or subclass.\n * @property {Array} renderers - Array of renderer functions or method names used to process the styles object. Set via options or subclass.\n * @property {HTMLElement} el - Reference to the `<style>` element in the DOM. Created when the instance is attached to the DOM.\n */\nclass StyleSheet {\n constructor(styles, options = {}) {\n // Styles object.\n this.styles = styles;\n // Original class names object.\n this.classes = {};\n // Set options on the instance.\n styleSheetOptions.forEach(key => {\n if (key in options) this[key] = options[key];\n });\n // Set default renderers.\n if (!this.renderers) this.renderers = [this.renderStyles, this.parseStyles];\n // Set default prefix.\n if (!this.prefix) this.prefix = StyleSheet.prefix;\n // Generate the `StyleSheet` unique identifier.\n this.uid = this.generateUid();\n // Generate class names. Only generate class names for top-level selectors.\n let counter = 0;\n Object.keys(styles).forEach(selector => {\n if (selector.match(StyleSheet.classRegex)) {\n this.classes[selector] = this.generateClassName(selector, ++counter);\n }\n });\n }\n\n /**\n * Generate a stable unique identifier.\n * May be overridden by `options.generateUid`.\n * @returns {String} The unique identifier.\n */\n generateUid() {\n const styles = JSON.stringify(this.styles);\n // FNV-1a 32-bit offset basis.\n let hash = 2166136261;\n for (let i = 0; i < styles.length; i++) {\n // XOR with the byte value.\n hash ^= styles.charCodeAt(i);\n // Multiply by FNV prime and ensure 32-bit unsigned integer.\n hash = (hash * 16777619) >>> 0;\n }\n // Convert the hash to a shorter base-36 string.\n return hash.toString(36);\n }\n\n /**\n * Generate a unique class name.\n * Transform local selectors that are classes to unique class names\n * to be used as class names in the styles object.\n * May be overridden by `options.generateClassName` or by extending the class.\n * @param {String} className - The class name.\n * @param {Number} index - The index of the class name.\n * @returns {String} The unique class name.\n */\n generateClassName(className, index) {\n return __DEV__ && StyleSheet.debug ?\n `${this.prefix}-${this.uid}-${className}` :\n `${this.prefix[0]}-${this.uid}-${index}`;\n }\n\n /**\n * Apply the renderers to the styles object.\n * It will return a string ready to be added to the style element.\n * @returns {String} The styles object as a string.\n */\n render() {\n const renderers = this.renderers.map(\n renderer => (typeof renderer === 'string' ? this[renderer] : renderer).bind(this)\n );\n\n return compose(renderers)(this.styles);\n }\n\n /**\n * Render the styles object as a string.\n * Its one of the default renderers.\n * It will return a string ready to be added to the `style` element.\n * @param {Object} styles - The styles object.\n * @param {Number} level - The level of indentation. Used for debugging.\n * @returns {String} The styles object as a string.\n * @private\n */\n renderStyles(styles, level = 1) {\n return Object.keys(styles).reduce((acc, key) => {\n const value = styles[key];\n let indent = '', nl = '', whitespace = '';\n // Format the CSS string.\n if (__DEV__ && StyleSheet.debug) {\n indent = StyleSheet.indent.repeat(level);\n nl = '\\n';\n whitespace = ' ';\n }\n // Add the styles to the accumulator recursively.\n if (isObject(value)) {\n if (Object.keys(value).length > 0) {\n const renderedStyles = this.renderStyles(value, level + 1);\n // Add rules to the accumulator.\n acc.push(`${indent}${key}${whitespace}{${nl}${renderedStyles}${indent}}${nl}`);\n }\n } else if (typeof value !== 'undefined' && value !== null) {\n // Add the style to the accumulator.\n acc.push(`${indent}${key}:${whitespace}${value};${nl}`);\n }\n\n return acc;\n }, []).join('');\n }\n\n /**\n * Parse the styles object and transform it. \n * Expand nested styles, parse global styles, generate selectors, replace selector references \n * and convert camelized keys to dashed-case.\n * Its one of the default renderers.\n * It will return an object ready to be rendered as string by `renderStyles`.\n * @param {Object} styles - The styles object.\n * @param {Object} parent - The parent object. Used for nested styles.\n * @param {String} parentSelector - The parent selector. Used for nested styles.\n * @param {Boolean} isGlobal - If true, the styles are global styles.\n * @returns {Object} The styles object.\n * @private\n */\n parseStyles(styles, parent, parentSelector, isGlobal) {\n const fromClasses = selector => selector in this.classes ? `.${this.classes[selector]}` : selector;\n // Parse the key and generate a selector.\n const generateKey = key => {\n if (isGlobal && parentSelector) {\n // Nested global selectors.\n return `${parentSelector} ${key}`;\n }\n if (key.match(StyleSheet.globalPrefixRegex)) {\n // Global prefix and nested global prefix.\n return `${parentSelector ? `${parentSelector} ` : ''}${key.replace(StyleSheet.globalPrefixRegex, '')}`;\n }\n // Nested, references and replace class names with created ones.\n return fromClasses(key)\n .replace(StyleSheet.referenceRegex, (match, ref) => fromClasses(ref))\n .replace(StyleSheet.nestedRegex, parentSelector);\n };\n\n const result = Object.keys(styles).reduce((acc, key) => {\n const value = styles[key];\n // Parse styles recursively.\n if (isObject(value)) {\n if (key.match(StyleSheet.globalRegex)) {\n // Global and nested global styles.\n Object.assign(parent || acc, this.parseStyles(value, acc, parentSelector, true));\n } else if ((key.match(StyleSheet.nestedRegex) || key.match(StyleSheet.globalPrefixRegex)) && parent) {\n const selector = generateKey(key);\n parent[selector] = {};\n // Nested global prefix and nested styles with reference.\n Object.assign(parent[selector], this.parseStyles(value, parent, selector));\n } else {\n const selector = generateKey(key);\n acc[selector] = {};\n // Don't expand at-rules.\n const args = selector.match(/@/) ? [] : [acc, selector];\n // Regular styles.\n Object.assign(acc[selector], this.parseStyles(value, ...args));\n }\n } else if (typeof value !== 'undefined' && value !== null) {\n // Add style rules.\n // Convert camelCase to dashed-case.\n // Only convert if the key doesn't already contain a dash.\n // Allows css vars to contain camelCase parts between dashes.\n acc[key.match(/-/) ? key : camelizedToDashed(key)] = value;\n }\n\n return acc;\n }, {});\n\n return result;\n }\n\n /**\n * Get the attributes object.\n * The attributes object will be used to set the attributes on the style element.\n * The attributes object will be merged with the `this.attributes` object.\n * The `data-fun-uid` attribute will be added to the attributes object.\n * @returns {Object} The attributes object.\n * @private\n */\n getAttributes() {\n const attributes = Object.assign({}, this.attributes);\n attributes[`data-${this.prefix}-uid`] = this.uid;\n return attributes;\n }\n\n /**\n * Render the StyleSheet as a style element string.\n * Used for server-side rendering.\n * @returns {String} The instance as a string.\n */\n toString() {\n const attributes = this.getAttributes();\n const attributesHtml = Object.keys(attributes).map(key => ` ${key}=\"${attributes[key]}\"`).join('');\n const nl = (__DEV__ && StyleSheet.debug) ? '\\n' : '';\n return `<style${attributesHtml}>${nl}${this.render()}</style>${nl}`;\n }\n\n /**\n * Check if the StyleSheet should be added to the DOM.\n * By default, it returns true if running in a browser environment and no style element\n * with the same `data-fun-uid` attribute exists in the DOM.\n * This prevents duplicate style elements and ensures proper behavior for server-side rendering.\n * May be overridden by `options.shouldAttachToDOM`.\n * @returns {Boolean} True if the StyleSheet should be added to the DOM, false otherwise.\n */\n shouldAttachToDOM() {\n return typeof document !== 'undefined' && !document.querySelector(`style[data-${this.prefix}-uid=\"${this.uid}\"]`);\n }\n\n /**\n * Add the instance to the registry and if we are in the browser, \n * attach it to the DOM.\n * @returns {StyleSheet} The instance.\n */\n attach() {\n // Add the instance to the registry if it's not already there.\n if (!StyleSheet.registry.some(({ uid }) => uid === this.uid)) {\n StyleSheet.registry.push(this);\n }\n // If we're in the browser and the style element doesn't exist, create it.\n if (this.shouldAttachToDOM()) {\n // Create the style element.\n this.el = document.createElement('style');\n\n const attributes = this.getAttributes();\n // Set the attributes on the style element.\n Object.keys(attributes).forEach(key => {\n this.el.setAttribute(key, attributes[key]);\n });\n // Render the styles and set the text content of the style element.\n this.el.textContent = this.render();\n // Append the style element to the head.\n document.head.appendChild(this.el);\n }\n\n return this;\n }\n\n /**\n * Destroy the instance and remove it from the registry and \n * from the DOM, if it's present.\n * @returns {StyleSheet} The instance.\n */\n destroy() {\n const index = StyleSheet.registry.indexOf(this);\n // Remove the instance from the registry.\n if (index > -1) {\n StyleSheet.registry.splice(index, 1);\n }\n\n if (this.el) {\n // Remove the style element from the DOM.\n if (this.el.parentNode) {\n this.el.parentNode.removeChild(this.el);\n }\n // Remove the reference to the style element.\n this.el = null;\n }\n\n return this;\n }\n\n /**\n * Render all instances in the registry as a string, including the style tags.\n * Can be used to insert style tags in an HTML template for server-side rendering.\n * @returns {string} All instances in the registry as a string.\n * @static\n */\n static toString() {\n return StyleSheet.registry.join('');\n }\n\n /**\n * Render all instances in the registry as CSS string.\n * Can be used to generate an external CSS file.\n * @returns {string} All instances in the registry rendered as CSS string.\n * @static\n */\n static toCSS() {\n return StyleSheet.registry.map(instance => instance.render()).join('');\n }\n\n /**\n * Destroy all instances in the registry and remove them from \n * it and from the DOM.\n * @static\n */\n static destroy() {\n StyleSheet.registry.slice().forEach(instance => instance.destroy());\n }\n}\n\n/**\n * Regular expressions to match class names.\n * @static\n * @private\n */\nStyleSheet.classRegex = /^\\w+$/;\n\n/**\n * Regular expression to match global styles.\n * @static\n * @private\n */\nStyleSheet.globalRegex = /^@global$/;\n\n/**\n * Regular expression to match global styles with a prefix.\n * @static\n * @private\n */\nStyleSheet.globalPrefixRegex = /^@global\\s+/;\n\n/**\n * Regular expression to match references to other class names.\n * @static\n * @private\n */\nStyleSheet.referenceRegex = /\\$(\\w+)/g;\n\n/**\n * Regular expression to match nested styles.\n * @static\n * @private\n */\nStyleSheet.nestedRegex = /&/g;\n\n/**\n * @static\n * @property {String} prefix - The class prefix. Used to generate unique class names.\n * @default fun\n */\nStyleSheet.prefix = 'fun';\n\n/**\n * @static\n * @property {String} indent - The indent string. Used to format text when debug is enabled. \n * @default ' '\n */\nStyleSheet.indent = ' ';\n\n/**\n * @static\n * @property {Array} registry - The registry array. StyleSheet instances \n * will be added to this array.\n */\nStyleSheet.registry = [];\n\n/**\n * @static\n * @property {Boolean} debug - The debug flag. If true, the styles will be formatted with\n * indentation and new lines.\n * @default __DEV__\n */\nStyleSheet.debug = __DEV__;\n\nexport default StyleSheet;\n","/**\n * Development mode flag.\n * This will be replaced during build:\n * - ESM/CJS: replaced with process.env.NODE_ENV !== 'production'\n * - UMD dev: replaced with true\n * - UMD prod: replaced with false\n * @type {boolean}\n * @module\n * @private\n */\nconst __DEV__ = true;\n\nexport default __DEV__;\n","import StyleSheet from './StyleSheet.js';\n\n/**\n * Creates and attaches a new StyleSheet instance to the DOM.\n * \n * @module\n * @function\n * @param {Object} styles - An object containing CSS rules. Keys represent selectors, and values represent style objects.\n * @param {Object} [options] - Optional configuration for the StyleSheet instance. Includes options like `prefix`, `renderers`, and more.\n * @returns {StyleSheet} The created StyleSheet instance. Use the `classes` property to access the generated class names.\n * \n * @example\n * // Create styles for a link component.\n * const { classes } = css({\n * link : {\n * color : 'blue',\n * '&:hover' : {\n * textDecoration : 'underline'\n * }\n * }\n * });\n * \n * // Use the generated `link` class in a component.\n * const Link = ({ label, href }) => <a className={classes.link} href={href}>{label}</a>;\n */\nconst css = (styles, options) => new StyleSheet(styles, options).attach();\n\nexport default css;\n","import css from './css.js';\nimport StyleSheet from './StyleSheet.js';\nimport isObject from './utils/isObject.js';\n\nconst makeCssVars = (theme = {}, prefix = '--') => {\n return Object.keys(theme).reduce((acc, key) => {\n const value = theme[key];\n if (isObject(value)) {\n Object.assign(acc, makeCssVars(value, `${prefix}-${key}`));\n } else if (typeof value !== 'undefined' && value !== null) {\n acc[`${prefix}-${key}`] = value;\n }\n return acc;\n }, {});\n};\n\nconst getDiff = (left, right) => {\n return Object.keys(left).reduce((acc, key) => {\n if (left[key] !== right[key]) {\n acc.left[key] = left[key];\n acc.right[key] = right[key];\n }\n return acc;\n }, { left : {}, right : {} });\n};\n\n/**\n * The `createTheme` function generates a theme StyleSheet instance with CSS variables \n * based on the provided themes and options. It supports multiple color schemes, \n * including `light`, `dark`, `light dark`, and `normal`. \n * \n * The `themes` object defines the styles for these color schemes. Each key in the object \n * corresponds to a color scheme (`light`, `dark`, `normal`), and its value is an object \n * containing key-value pairs that will be converted into CSS variables. Nested keys are \n * concatenated with `-` to form the variable name. For example, `{ light : { colors : { primary : 'blue' } } }` \n * generates `--fun-colors-primary : blue`.\n * \n * @module\n * @function\n * @param {Object} themes - An object defining styles for color schemes (`light`, `dark`, `normal`). \n * Each key corresponds to a color scheme, and its value is an object of key-value pairs converted \n * to CSS variables. Nested keys are concatenated with `-` to form variable names.\n * \n * @param {Object} [options] - An optional object to customize the theme generation. It includes options \n * for selecting color schemes, customizing CSS variable prefixes, and controlling StyleSheet creation.\n * \n * @param {String} [options.colorScheme] - Specifies the color scheme(s) to use. Possible values are: \n * `light` (uses the `light` theme only), `dark` (uses the `dark` theme only), `light dark` (default, \n * supports both `light` and `dark` themes, adapting to system preferences; can override system \n * preference with `data-color-scheme` set to `light` or `dark`), and `normal` (uses the `normal` theme only).\n * \n * @param {String} [options.cssVarsPrefix] - The prefix for the generated CSS variables. Default is `fun`. \n * For example, a key `color` in the theme will generate a CSS variable like `--fun-color`.\n * \n * @param {Function} [options.createStyleSheet] - A function used to create a new StyleSheet instance. \n * By default, it uses the `css` function.\n * \n * @param {Object} [options.styleSheetOptions] - Options to pass when creating the StyleSheet instance. \n * Default is `system`.\n * \n * @returns {StyleSheet} The theme StyleSheet instance. Use `classes.root` to get the theme class name. \n * Apply this class to the element you want to theme. The CSS variables will be available for all \n * its descendants.\n * \n * @example\n * // Create a theme with light and dark color schemes and apply it to the entire page.\n * const theme = createTheme({\n * light : {\n * colorPrimary : 'black',\n * backgroundLevel1 : 'white'\n * },\n * dark : {\n * colorPrimary : 'white',\n * backgroundLevel1 : 'black'\n * }\n * });\n * \n * // Add the `root` class (the theme class) to the body element.\n * // This will apply the theme to the entire page.\n * document.body.classList.add(theme.classes.root);\n * \n * // Add some styles using the theme CSS variables.\n * const { classes } = css({\n * button : {\n * color : 'var(--fun-colorPrimary)', // Use the CSS variable generated from the theme.\n * backgroundColor : 'var(--fun-backgroundLevel1)'\n * }\n * });\n * \n * // Add the `button` class to a button component.\n * // The button will use the CSS variables defined in the theme for its styles.\n * // Once the theme is applied, the button will automatically update its styles.\n * // If the system color scheme changes (e.g., from light to dark), the button will \n * // dynamically update to reflect the new theme without requiring additional code.\n * const Button = ({ label }) => <button className={classes.button}>{label}</button>;\n */\nconst createTheme = (themes = {}, options = {}) => {\n const colorScheme = options.colorScheme || 'light dark';\n const prefix = `--${options.cssVarsPrefix || StyleSheet.prefix}`;\n\n let styles;\n\n if (colorScheme === 'light dark') {\n const cssVars = {\n light : makeCssVars(themes.light, prefix),\n dark : makeCssVars(themes.dark, prefix)\n };\n\n const diff = getDiff(cssVars.light, cssVars.dark);\n\n styles = {\n root : {\n ':where(&)' : Object.assign({ colorScheme : 'light' }, cssVars.light),\n ':where([data-color-scheme=\"dark\"] &)' : Object.assign({ colorScheme : 'dark' }, diff.right),\n },\n '@media (prefers-color-scheme: dark)' : {\n ':where($root)' : Object.assign({ colorScheme : 'dark' }, diff.right),\n ':where([data-color-scheme=\"light\"] $root)' : Object.assign({ colorScheme : 'light' }, diff.left)\n }\n };\n } else {\n styles = {\n root : {\n ':where(&)' : Object.assign({ colorScheme }, makeCssVars(themes[colorScheme], prefix))\n }\n };\n }\n\n return (options.createStyleSheet || css)(styles, options.styleSheetOptions);\n};\n\nexport default createTheme;\n"],"names":["isObject","value","Array","isArray","styleSheetOptions","StyleSheet","constructor","styles","options","this","classes","forEach","key","renderers","renderStyles","parseStyles","prefix","uid","generateUid","counter","Object","keys","selector","match","classRegex","generateClassName","JSON","stringify","hash","i","length","charCodeAt","toString","className","index","render","map","renderer","bind","reduce","f","g","args","compose","level","acc","renderedStyles","push","join","parent","parentSelector","isGlobal","fromClasses","generateKey","globalPrefixRegex","replace","referenceRegex","ref","nestedRegex","globalRegex","assign","str","toLowerCase","getAttributes","attributes","shouldAttachToDOM","document","querySelector","attach","registry","some","el","createElement","setAttribute","textContent","head","appendChild","destroy","indexOf","splice","parentNode","removeChild","toCSS","instance","slice","indent","debug","css","makeCssVars","theme","themes","colorScheme","cssVarsPrefix","cssVars","light","dark","diff","left","right","root","createStyleSheet"],"mappings":"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"} | ||
| {"version":3,"file":"cssfun.min.js","sources":["../src/utils/isObject.js","../src/StyleSheet.js","../src/utils/dev.js","../src/css.js","../src/createTheme.js"],"sourcesContent":["/**\n * Check if a value is an object.\n * @param {any} value - The value to check.\n * @returns {boolean} True if the value is an object, false otherwise.\n * @module\n * @private\n */\nconst isObject = value =>\n value !== null && typeof value === 'object' && !Array.isArray(value);\n\nexport default isObject;\n","import isObject from './utils/isObject.js';\nimport __DEV__ from './utils/dev.js';\n\nconst camelizedToDashed = str => str.replace(/([A-Z])/g, (g) => `-${g[0].toLowerCase()}`);\nconst compose = fns => fns.reduce((f, g) => (...args) => f(g(...args)));\n\nconst styleSheetOptions = ['prefix', 'generateUid', 'generateClassName', 'shouldAttachToDOM', 'attributes', 'renderers'];\n\n/**\n * The StyleSheet class is responsible for creating and managing a CSS stylesheet.\n * It takes a styles object and an optional options object as input, processes the styles, \n * and generates a CSS stylesheet that can be attached to the DOM, destroyed, or \n * rendered as a string for server-side rendering.\n * \n * @module\n * @class\n * @param {Object} styles - The styles object. This is an object where keys represent \n * CSS selectors and values are style objects. The styles object is processed through \n * the renderers to generate the final CSS string. It is stored in the instance as `this.styles`.\n * @param {Object} [options={}] - Configuration options. The following options are assigned to the instance (`this`):\n * `prefix`, `generateUid`, `generateClassName`, `shouldAttachToDOM`, `attributes`, `renderers`.\n * @param {String} [options.prefix='fun'] - Prefix for generating unique identifiers and data attributes.\n * @param {Function} [options.generateUid] - Custom function to generate the unique identifier.\n * @param {Function} [options.generateClassName] - Custom function to generate unique class names.\n * @param {Object} [options.attributes] - Attributes to be added to the `<style>` element.\n * @param {Array} [options.renderers=['parseStyles', 'renderStyles']] - Array of renderer functions or method names.\n * Renderers are composed in sequence. Strings or functions are automatically bound to `this`.\n * @param {Function} [options.shouldAttachToDOM] - Custom function to determine whether the StyleSheet should be added to the DOM.\n * \n * @example\n * // Create a new StyleSheet instance with a styles object.\n * const instance = new StyleSheet({\n * root: {\n * color: 'black'\n * }\n * });\n * \n * // Attach the StyleSheet instance to the DOM.\n * instance.attach();\n * \n * // Retrieve the generated classes object from the instance.\n * const { classes } = instance;\n * \n * // Use the generated class name in your component.\n * function Header() {\n * return <h1 className={classes.root}>Hello World</h1>;\n * }\n * \n * @property {Object} classes - Object mapping original class names to generated unique class names.\n * @property {Object} styles - The original styles object provided to the instance.\n * @property {String} uid - Unique identifier for the StyleSheet instance, generated using `this.generateUid`.\n * @property {String} prefix - Prefix for generating unique identifiers. Set via options or subclass.\n * @property {Object} attributes - Attributes to be added to the `<style>` element. Set via options or subclass.\n * @property {Array} renderers - Array of renderer functions or method names used to process the styles object. Set via options or subclass.\n * @property {HTMLElement} el - Reference to the `<style>` element in the DOM. Created when the instance is attached to the DOM.\n */\nclass StyleSheet {\n constructor(styles, options = {}) {\n // Styles object.\n this.styles = styles;\n // Original class names object.\n this.classes = {};\n // Set options on the instance.\n styleSheetOptions.forEach(key => {\n if (key in options) this[key] = options[key];\n });\n // Set default renderers.\n if (!this.renderers) this.renderers = [this.renderStyles, this.parseStyles];\n // Set default prefix.\n if (!this.prefix) this.prefix = StyleSheet.prefix;\n // Generate the `StyleSheet` unique identifier.\n this.uid = this.generateUid();\n // Generate class names. Only generate class names for top-level selectors.\n let counter = 0;\n Object.keys(styles).forEach(selector => {\n if (selector.match(StyleSheet.classRegex)) {\n this.classes[selector] = this.generateClassName(selector, ++counter);\n }\n });\n }\n\n /**\n * Generate a stable unique identifier.\n * May be overridden by `options.generateUid`.\n * @returns {String} The unique identifier.\n */\n generateUid() {\n const styles = JSON.stringify(this.styles);\n // FNV-1a 32-bit offset basis.\n let hash = 2166136261;\n for (let i = 0; i < styles.length; i++) {\n // XOR with the byte value.\n hash ^= styles.charCodeAt(i);\n // Multiply by FNV prime and ensure 32-bit unsigned integer.\n hash = (hash * 16777619) >>> 0;\n }\n // Convert the hash to a shorter base-36 string.\n return hash.toString(36);\n }\n\n /**\n * Generate a unique class name.\n * Transform local selectors that are classes to unique class names\n * to be used as class names in the styles object.\n * May be overridden by `options.generateClassName` or by extending the class.\n * @param {String} className - The class name.\n * @param {Number} index - The index of the class name.\n * @returns {String} The unique class name.\n */\n generateClassName(className, index) {\n return __DEV__ && StyleSheet.debug ?\n `${this.prefix}-${this.uid}-${className}` :\n `${this.prefix[0]}-${this.uid}-${index}`;\n }\n\n /**\n * Apply the renderers to the styles object.\n * It will return a string ready to be added to the style element.\n * @returns {String} The styles object as a string.\n */\n render() {\n const renderers = this.renderers.map(\n renderer => (typeof renderer === 'string' ? this[renderer] : renderer).bind(this)\n );\n\n return compose(renderers)(this.styles);\n }\n\n /**\n * Render the styles object as a string.\n * Its one of the default renderers.\n * It will return a string ready to be added to the `style` element.\n * @param {Object} styles - The styles object.\n * @param {Number} level - The level of indentation. Used for debugging.\n * @returns {String} The styles object as a string.\n * @private\n */\n renderStyles(styles, level = 1) {\n return Object.keys(styles).reduce((acc, key) => {\n const value = styles[key];\n let indent = '', nl = '', whitespace = '';\n // Format the CSS string.\n if (__DEV__ && StyleSheet.debug) {\n indent = StyleSheet.indent.repeat(level);\n nl = '\\n';\n whitespace = ' ';\n }\n // Add the styles to the accumulator recursively.\n if (isObject(value)) {\n if (Object.keys(value).length > 0) {\n const renderedStyles = this.renderStyles(value, level + 1);\n // Add rules to the accumulator.\n acc.push(`${indent}${key}${whitespace}{${nl}${renderedStyles}${indent}}${nl}`);\n }\n } else if (typeof value !== 'undefined' && value !== null) {\n // Add the style to the accumulator.\n acc.push(`${indent}${key}:${whitespace}${value};${nl}`);\n }\n\n return acc;\n }, []).join('');\n }\n\n /**\n * Parse the styles object and transform it. \n * Expand nested styles, parse global styles, generate selectors, replace selector references \n * and convert camelized keys to dashed-case.\n * Its one of the default renderers.\n * It will return an object ready to be rendered as string by `renderStyles`.\n * @param {Object} styles - The styles object.\n * @param {Object} parent - The parent object. Used for nested styles.\n * @param {String} parentSelector - The parent selector. Used for nested styles.\n * @param {Boolean} isGlobal - If true, the styles are global styles.\n * @returns {Object} The styles object.\n * @private\n */\n parseStyles(styles, parent, parentSelector, isGlobal) {\n const fromClasses = selector => selector in this.classes ? `.${this.classes[selector]}` : selector;\n // Parse the key and generate a selector.\n const generateKey = key => {\n if (isGlobal && parentSelector) {\n // Nested global selectors.\n return `${parentSelector} ${key}`;\n }\n if (key.match(StyleSheet.globalPrefixRegex)) {\n // Global prefix and nested global prefix.\n return `${parentSelector ? `${parentSelector} ` : ''}${key.replace(StyleSheet.globalPrefixRegex, '')}`;\n }\n // Nested, references and replace class names with created ones.\n return fromClasses(key)\n .replace(StyleSheet.referenceRegex, (match, ref) => fromClasses(ref))\n .replace(StyleSheet.nestedRegex, parentSelector);\n };\n\n const result = Object.keys(styles).reduce((acc, key) => {\n const value = styles[key];\n // Parse styles recursively.\n if (isObject(value)) {\n if (key.match(StyleSheet.globalRegex)) {\n // Global and nested global styles.\n Object.assign(parent || acc, this.parseStyles(value, acc, parentSelector, true));\n } else if ((key.match(StyleSheet.nestedRegex) || key.match(StyleSheet.globalPrefixRegex)) && parent) {\n const selector = generateKey(key);\n parent[selector] = {};\n // Nested global prefix and nested styles with reference.\n Object.assign(parent[selector], this.parseStyles(value, parent, selector));\n } else {\n const selector = generateKey(key);\n acc[selector] = {};\n // Don't expand at-rules.\n const args = selector.match(/@/) ? [] : [acc, selector];\n // Regular styles.\n Object.assign(acc[selector], this.parseStyles(value, ...args));\n }\n } else if (typeof value !== 'undefined' && value !== null) {\n // Add style rules.\n // Convert camelCase to dashed-case.\n // Only convert if the key doesn't already contain a dash.\n // Allows css vars to contain camelCase parts between dashes.\n acc[key.match(/-/) ? key : camelizedToDashed(key)] = value;\n }\n\n return acc;\n }, {});\n\n return result;\n }\n\n /**\n * Get the attributes object.\n * The attributes object will be used to set the attributes on the style element.\n * The attributes object will be merged with the `this.attributes` object.\n * The `data-fun-uid` attribute will be added to the attributes object.\n * @returns {Object} The attributes object.\n * @private\n */\n getAttributes() {\n const attributes = Object.assign({}, this.attributes);\n attributes[`data-${this.prefix}-uid`] = this.uid;\n return attributes;\n }\n\n /**\n * Render the StyleSheet as a style element string.\n * Used for server-side rendering.\n * @returns {String} The instance as a string.\n */\n toString() {\n const attributes = this.getAttributes();\n const attributesHtml = Object.keys(attributes).map(key => ` ${key}=\"${attributes[key]}\"`).join('');\n const nl = (__DEV__ && StyleSheet.debug) ? '\\n' : '';\n return `<style${attributesHtml}>${nl}${this.render()}</style>${nl}`;\n }\n\n /**\n * Check if the StyleSheet should be added to the DOM.\n * By default, it returns true if running in a browser environment and no style element\n * with the same `data-fun-uid` attribute exists in the DOM.\n * This prevents duplicate style elements and ensures proper behavior for server-side rendering.\n * May be overridden by `options.shouldAttachToDOM`.\n * @returns {Boolean} True if the StyleSheet should be added to the DOM, false otherwise.\n */\n shouldAttachToDOM() {\n return typeof document !== 'undefined' && !document.querySelector(`style[data-${this.prefix}-uid=\"${this.uid}\"]`);\n }\n\n /**\n * Add the instance to the registry and if we are in the browser, \n * attach it to the DOM.\n * @returns {StyleSheet} The instance.\n */\n attach() {\n // Add the instance to the registry if it's not already there.\n if (!StyleSheet.registry.some(({ uid }) => uid === this.uid)) {\n StyleSheet.registry.push(this);\n }\n // If we're in the browser and the style element doesn't exist, create it.\n if (this.shouldAttachToDOM()) {\n // Create the style element.\n this.el = document.createElement('style');\n\n const attributes = this.getAttributes();\n // Set the attributes on the style element.\n Object.keys(attributes).forEach(key => {\n this.el.setAttribute(key, attributes[key]);\n });\n // Render the styles and set the text content of the style element.\n this.el.textContent = this.render();\n // Append the style element to the head.\n document.head.appendChild(this.el);\n }\n\n return this;\n }\n\n /**\n * Destroy the instance and remove it from the registry and \n * from the DOM, if it's present.\n * @returns {StyleSheet} The instance.\n */\n destroy() {\n const index = StyleSheet.registry.indexOf(this);\n // Remove the instance from the registry.\n if (index > -1) {\n StyleSheet.registry.splice(index, 1);\n }\n\n if (this.el) {\n // Remove the style element from the DOM.\n if (this.el.parentNode) {\n this.el.parentNode.removeChild(this.el);\n }\n // Remove the reference to the style element.\n this.el = null;\n }\n\n return this;\n }\n\n /**\n * Render all instances in the registry as a string, including the style tags.\n * Can be used to insert style tags in an HTML template for server-side rendering.\n * @returns {string} All instances in the registry as a string.\n * @static\n */\n static toString() {\n return StyleSheet.registry.join('');\n }\n\n /**\n * Render all instances in the registry as CSS string.\n * Can be used to generate an external CSS file.\n * @returns {string} All instances in the registry rendered as CSS string.\n * @static\n */\n static toCSS() {\n return StyleSheet.registry.map(instance => instance.render()).join('');\n }\n\n /**\n * Destroy all instances in the registry and remove them from \n * it and from the DOM.\n * @static\n */\n static destroy() {\n StyleSheet.registry.slice().forEach(instance => instance.destroy());\n }\n}\n\n/**\n * Regular expressions to match class names.\n * @static\n * @private\n */\nStyleSheet.classRegex = /^\\w+$/;\n\n/**\n * Regular expression to match global styles.\n * @static\n * @private\n */\nStyleSheet.globalRegex = /^@global$/;\n\n/**\n * Regular expression to match global styles with a prefix.\n * @static\n * @private\n */\nStyleSheet.globalPrefixRegex = /^@global\\s+/;\n\n/**\n * Regular expression to match references to other class names.\n * @static\n * @private\n */\nStyleSheet.referenceRegex = /\\$(\\w+)/g;\n\n/**\n * Regular expression to match nested styles.\n * @static\n * @private\n */\nStyleSheet.nestedRegex = /&/g;\n\n/**\n * @static\n * @property {String} prefix - The class prefix. Used to generate unique class names.\n * @default fun\n */\nStyleSheet.prefix = 'fun';\n\n/**\n * @static\n * @property {String} indent - The indent string. Used to format text when debug is enabled. \n * @default ' '\n */\nStyleSheet.indent = ' ';\n\n/**\n * @static\n * @property {Array} registry - The registry array. StyleSheet instances \n * will be added to this array.\n */\nStyleSheet.registry = [];\n\n/**\n * @static\n * @property {Boolean} debug - The debug flag. If true, the styles will be formatted with\n * indentation and new lines.\n * @default __DEV__\n */\nStyleSheet.debug = __DEV__;\n\nexport default StyleSheet;\n","/**\n * Development mode flag.\n * This will be replaced during build:\n * - ESM/CJS: replaced with process.env.NODE_ENV !== 'production'\n * - UMD dev: replaced with true\n * - UMD prod: replaced with false\n * @type {boolean}\n * @module\n * @private\n */\nconst __DEV__ = true;\n\nexport default __DEV__;\n","import StyleSheet from './StyleSheet.js';\n\n/**\n * Creates and attaches a new StyleSheet instance to the DOM.\n * \n * @module\n * @function\n * @param {Object} styles - An object containing CSS rules. Keys represent selectors, and values represent style objects.\n * @param {Object} [options] - Optional configuration for the StyleSheet instance. Includes options like `prefix`, `renderers`, and more.\n * @returns {StyleSheet} The created StyleSheet instance. Use the `classes` property to access the generated class names.\n * \n * @example\n * // Create styles for a link component.\n * const { classes } = css({\n * link : {\n * color : 'blue',\n * '&:hover' : {\n * textDecoration : 'underline'\n * }\n * }\n * });\n * \n * // Use the generated `link` class in a component.\n * const Link = ({ label, href }) => <a className={classes.link} href={href}>{label}</a>;\n */\nconst css = (styles, options) => new StyleSheet(styles, options).attach();\n\nexport default css;\n","import css from './css.js';\nimport StyleSheet from './StyleSheet.js';\nimport isObject from './utils/isObject.js';\n\n/**\n * Flattens a nested theme object into a map of CSS variable names to values.\n * Nested keys are joined with `-` (e.g. `{ colors: { primary: 'blue' } }` → `--prefix-colors-primary`).\n * @private\n * @param {Object} [theme={}] - Nested theme object.\n * @param {string|null} [prefix] - Prefix for variable names (e.g. `fun` → `--fun-key`). Omit or pass `null`/`''` for no prefix.\n * @returns {Object} Map of CSS variable names (e.g. `--fun-color`) to values.\n */\nconst makeCssVars = (theme = {}, prefix) => {\n function build(theme, nameAcc) {\n return Object.keys(theme).reduce((acc, key) => {\n const value = theme[key];\n const name = nameAcc ? `${nameAcc}-${key}` : prefix ? `--${prefix}-${key}` : `--${key}`;\n\n if (isObject(value)) {\n Object.assign(acc, build(value, name));\n } else if (typeof value !== 'undefined' && value !== null) {\n acc[name] = value;\n }\n\n return acc;\n }, {});\n }\n return build(theme);\n};\n\n/**\n * Returns keys that differ between two objects, with each side’s value.\n * @private\n * @param {Object} left - First object.\n * @param {Object} right - Second object.\n * @returns {{ left: Object, right: Object }} Objects containing only the differing keys and their values per side.\n */\nconst getDiff = (left, right) => {\n return Object.keys(left).reduce((acc, key) => {\n if (left[key] !== right[key]) {\n acc.left[key] = left[key];\n acc.right[key] = right[key];\n }\n return acc;\n }, { left : {}, right : {} });\n};\n\n/**\n * The `createTheme` function generates a theme StyleSheet instance with CSS variables \n * based on the provided themes and options. It supports multiple color schemes, \n * including `light`, `dark`, `light dark`, and `normal`. \n * \n * The `themes` object defines the styles for these color schemes. Each key in the object \n * corresponds to a color scheme (`light`, `dark`, `normal`), and its value is an object \n * containing key-value pairs that will be converted into CSS variables. Nested keys are \n * concatenated with `-` to form the variable name. For example, `{ light : { colors : { primary : 'blue' } } }` \n * generates `--fun-colors-primary : blue`.\n * \n * @module\n * @function\n * @param {Object} themes - An object defining styles for color schemes (`light`, `dark`, `normal`). \n * Each key corresponds to a color scheme, and its value is an object of key-value pairs converted \n * to CSS variables. Nested keys are concatenated with `-` to form variable names.\n * \n * @param {Object} [options] - An optional object to customize the theme generation. It includes options \n * for selecting color schemes, customizing CSS variable prefixes, and controlling StyleSheet creation.\n * \n * @param {String} [options.colorScheme] - Specifies the color scheme(s) to use. Possible values are: \n * `light` (uses the `light` theme only), `dark` (uses the `dark` theme only), `light dark` (default, \n * supports both `light` and `dark` themes, adapting to system preferences; can override system \n * preference with `data-color-scheme` set to `light` or `dark`), and `normal` (uses the `normal` theme only).\n * \n * @param {String|null} [options.cssVarsPrefix] - Prefix for the generated CSS variables. Defaults to `StyleSheet.prefix`.\n * Pass `null` or `''` to generate variables without a prefix (e.g. `--color` instead of `--fun-color`).\n * \n * @param {Function} [options.createStyleSheet] - A function used to create a new StyleSheet instance. \n * By default, it uses the `css` function.\n * \n * @param {Object} [options.styleSheetOptions] - Options to pass when creating the StyleSheet instance. \n * Default is `system`.\n * \n * @returns {StyleSheet} The theme StyleSheet instance. Use `classes.root` to get the theme class name. \n * Apply this class to the element you want to theme. The CSS variables will be available for all \n * its descendants.\n * \n * @example\n * // Create a theme with light and dark color schemes and apply it to the entire page.\n * const theme = createTheme({\n * light : {\n * colorPrimary : 'black',\n * backgroundLevel1 : 'white'\n * },\n * dark : {\n * colorPrimary : 'white',\n * backgroundLevel1 : 'black'\n * }\n * });\n * \n * // Add the `root` class (the theme class) to the body element.\n * // This will apply the theme to the entire page.\n * document.body.classList.add(theme.classes.root);\n * \n * // Add some styles using the theme CSS variables.\n * const { classes } = css({\n * button : {\n * color : 'var(--fun-colorPrimary)', // Use the CSS variable generated from the theme.\n * backgroundColor : 'var(--fun-backgroundLevel1)'\n * }\n * });\n * \n * // Add the `button` class to a button component.\n * // The button will use the CSS variables defined in the theme for its styles.\n * // Once the theme is applied, the button will automatically update its styles.\n * // If the system color scheme changes (e.g., from light to dark), the button will \n * // dynamically update to reflect the new theme without requiring additional code.\n * const Button = ({ label }) => <button className={classes.button}>{label}</button>;\n */\nconst createTheme = (themes = {}, options = {}) => {\n const colorScheme = options.colorScheme || 'light dark';\n const prefix = 'cssVarsPrefix' in options ? options.cssVarsPrefix : StyleSheet.prefix;\n\n let styles;\n\n if (colorScheme === 'light dark') {\n const cssVars = {\n light : makeCssVars(themes.light, prefix),\n dark : makeCssVars(themes.dark, prefix)\n };\n\n const diff = getDiff(cssVars.light, cssVars.dark);\n\n styles = {\n root : {\n ':where(&)' : Object.assign({ colorScheme : 'light' }, cssVars.light),\n ':where([data-color-scheme=\"dark\"] &)' : Object.assign({ colorScheme : 'dark' }, diff.right),\n },\n '@media (prefers-color-scheme: dark)' : {\n ':where($root)' : Object.assign({ colorScheme : 'dark' }, diff.right),\n ':where([data-color-scheme=\"light\"] $root)' : Object.assign({ colorScheme : 'light' }, diff.left)\n }\n };\n } else {\n styles = {\n root : {\n ':where(&)' : Object.assign({ colorScheme }, makeCssVars(themes[colorScheme], prefix))\n }\n };\n }\n\n return (options.createStyleSheet || css)(styles, options.styleSheetOptions);\n};\n\nexport default createTheme;\n"],"names":["isObject","value","Array","isArray","styleSheetOptions","StyleSheet","constructor","styles","options","this","classes","forEach","key","renderers","renderStyles","parseStyles","prefix","uid","generateUid","counter","Object","keys","selector","match","classRegex","generateClassName","JSON","stringify","hash","i","length","charCodeAt","toString","className","index","render","map","renderer","bind","reduce","f","g","args","compose","level","acc","renderedStyles","push","join","parent","parentSelector","isGlobal","fromClasses","generateKey","globalPrefixRegex","replace","referenceRegex","ref","nestedRegex","globalRegex","assign","str","toLowerCase","getAttributes","attributes","shouldAttachToDOM","document","querySelector","attach","registry","some","el","createElement","setAttribute","textContent","head","appendChild","destroy","indexOf","splice","parentNode","removeChild","toCSS","instance","slice","indent","debug","css","makeCssVars","theme","build","nameAcc","name","themes","colorScheme","cssVarsPrefix","cssVars","light","dark","diff","left","right","root","createStyleSheet"],"mappings":"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"} |
+34
-13
@@ -6,14 +6,35 @@ import StyleSheet from './StyleSheet.js'; | ||
| const makeCssVars = (theme = {}, prefix = '--') => { | ||
| return Object.keys(theme).reduce((acc, key) => { | ||
| const value = theme[key]; | ||
| if (isObject(value)) { | ||
| Object.assign(acc, makeCssVars(value, `${prefix}-${key}`)); | ||
| } else if (typeof value !== 'undefined' && value !== null) { | ||
| acc[`${prefix}-${key}`] = value; | ||
| } | ||
| return acc; | ||
| }, {}); | ||
| /** | ||
| * Flattens a nested theme object into a map of CSS variable names to values. | ||
| * Nested keys are joined with `-` (e.g. `{ colors: { primary: 'blue' } }` → `--prefix-colors-primary`). | ||
| * @private | ||
| * @param {Object} [theme={}] - Nested theme object. | ||
| * @param {string|null} [prefix] - Prefix for variable names (e.g. `fun` → `--fun-key`). Omit or pass `null`/`''` for no prefix. | ||
| * @returns {Object} Map of CSS variable names (e.g. `--fun-color`) to values. | ||
| */ | ||
| const makeCssVars = (theme = {}, prefix) => { | ||
| function build(theme, nameAcc) { | ||
| return Object.keys(theme).reduce((acc, key) => { | ||
| const value = theme[key]; | ||
| const name = nameAcc ? `${nameAcc}-${key}` : prefix ? `--${prefix}-${key}` : `--${key}`; | ||
| if (isObject(value)) { | ||
| Object.assign(acc, build(value, name)); | ||
| } else if (typeof value !== 'undefined' && value !== null) { | ||
| acc[name] = value; | ||
| } | ||
| return acc; | ||
| }, {}); | ||
| } | ||
| return build(theme); | ||
| }; | ||
| /** | ||
| * Returns keys that differ between two objects, with each side’s value. | ||
| * @private | ||
| * @param {Object} left - First object. | ||
| * @param {Object} right - Second object. | ||
| * @returns {{ left: Object, right: Object }} Objects containing only the differing keys and their values per side. | ||
| */ | ||
| const getDiff = (left, right) => { | ||
@@ -54,4 +75,4 @@ return Object.keys(left).reduce((acc, key) => { | ||
| * | ||
| * @param {String} [options.cssVarsPrefix] - The prefix for the generated CSS variables. Default is `fun`. | ||
| * For example, a key `color` in the theme will generate a CSS variable like `--fun-color`. | ||
| * @param {String|null} [options.cssVarsPrefix] - Prefix for the generated CSS variables. Defaults to `StyleSheet.prefix`. | ||
| * Pass `null` or `''` to generate variables without a prefix (e.g. `--color` instead of `--fun-color`). | ||
| * | ||
@@ -102,3 +123,3 @@ * @param {Function} [options.createStyleSheet] - A function used to create a new StyleSheet instance. | ||
| const colorScheme = options.colorScheme || 'light dark'; | ||
| const prefix = `--${options.cssVarsPrefix || StyleSheet.prefix}`; | ||
| const prefix = 'cssVarsPrefix' in options ? options.cssVarsPrefix : StyleSheet.prefix; | ||
@@ -105,0 +126,0 @@ let styles; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"createTheme.js","sources":["../src/createTheme.js"],"sourcesContent":["import css from './css.js';\nimport StyleSheet from './StyleSheet.js';\nimport isObject from './utils/isObject.js';\n\nconst makeCssVars = (theme = {}, prefix = '--') => {\n return Object.keys(theme).reduce((acc, key) => {\n const value = theme[key];\n if (isObject(value)) {\n Object.assign(acc, makeCssVars(value, `${prefix}-${key}`));\n } else if (typeof value !== 'undefined' && value !== null) {\n acc[`${prefix}-${key}`] = value;\n }\n return acc;\n }, {});\n};\n\nconst getDiff = (left, right) => {\n return Object.keys(left).reduce((acc, key) => {\n if (left[key] !== right[key]) {\n acc.left[key] = left[key];\n acc.right[key] = right[key];\n }\n return acc;\n }, { left : {}, right : {} });\n};\n\n/**\n * The `createTheme` function generates a theme StyleSheet instance with CSS variables \n * based on the provided themes and options. It supports multiple color schemes, \n * including `light`, `dark`, `light dark`, and `normal`. \n * \n * The `themes` object defines the styles for these color schemes. Each key in the object \n * corresponds to a color scheme (`light`, `dark`, `normal`), and its value is an object \n * containing key-value pairs that will be converted into CSS variables. Nested keys are \n * concatenated with `-` to form the variable name. For example, `{ light : { colors : { primary : 'blue' } } }` \n * generates `--fun-colors-primary : blue`.\n * \n * @module\n * @function\n * @param {Object} themes - An object defining styles for color schemes (`light`, `dark`, `normal`). \n * Each key corresponds to a color scheme, and its value is an object of key-value pairs converted \n * to CSS variables. Nested keys are concatenated with `-` to form variable names.\n * \n * @param {Object} [options] - An optional object to customize the theme generation. It includes options \n * for selecting color schemes, customizing CSS variable prefixes, and controlling StyleSheet creation.\n * \n * @param {String} [options.colorScheme] - Specifies the color scheme(s) to use. Possible values are: \n * `light` (uses the `light` theme only), `dark` (uses the `dark` theme only), `light dark` (default, \n * supports both `light` and `dark` themes, adapting to system preferences; can override system \n * preference with `data-color-scheme` set to `light` or `dark`), and `normal` (uses the `normal` theme only).\n * \n * @param {String} [options.cssVarsPrefix] - The prefix for the generated CSS variables. Default is `fun`. \n * For example, a key `color` in the theme will generate a CSS variable like `--fun-color`.\n * \n * @param {Function} [options.createStyleSheet] - A function used to create a new StyleSheet instance. \n * By default, it uses the `css` function.\n * \n * @param {Object} [options.styleSheetOptions] - Options to pass when creating the StyleSheet instance. \n * Default is `system`.\n * \n * @returns {StyleSheet} The theme StyleSheet instance. Use `classes.root` to get the theme class name. \n * Apply this class to the element you want to theme. The CSS variables will be available for all \n * its descendants.\n * \n * @example\n * // Create a theme with light and dark color schemes and apply it to the entire page.\n * const theme = createTheme({\n * light : {\n * colorPrimary : 'black',\n * backgroundLevel1 : 'white'\n * },\n * dark : {\n * colorPrimary : 'white',\n * backgroundLevel1 : 'black'\n * }\n * });\n * \n * // Add the `root` class (the theme class) to the body element.\n * // This will apply the theme to the entire page.\n * document.body.classList.add(theme.classes.root);\n * \n * // Add some styles using the theme CSS variables.\n * const { classes } = css({\n * button : {\n * color : 'var(--fun-colorPrimary)', // Use the CSS variable generated from the theme.\n * backgroundColor : 'var(--fun-backgroundLevel1)'\n * }\n * });\n * \n * // Add the `button` class to a button component.\n * // The button will use the CSS variables defined in the theme for its styles.\n * // Once the theme is applied, the button will automatically update its styles.\n * // If the system color scheme changes (e.g., from light to dark), the button will \n * // dynamically update to reflect the new theme without requiring additional code.\n * const Button = ({ label }) => <button className={classes.button}>{label}</button>;\n */\nconst createTheme = (themes = {}, options = {}) => {\n const colorScheme = options.colorScheme || 'light dark';\n const prefix = `--${options.cssVarsPrefix || StyleSheet.prefix}`;\n\n let styles;\n\n if (colorScheme === 'light dark') {\n const cssVars = {\n light : makeCssVars(themes.light, prefix),\n dark : makeCssVars(themes.dark, prefix)\n };\n\n const diff = getDiff(cssVars.light, cssVars.dark);\n\n styles = {\n root : {\n ':where(&)' : Object.assign({ colorScheme : 'light' }, cssVars.light),\n ':where([data-color-scheme=\"dark\"] &)' : Object.assign({ colorScheme : 'dark' }, diff.right),\n },\n '@media (prefers-color-scheme: dark)' : {\n ':where($root)' : Object.assign({ colorScheme : 'dark' }, diff.right),\n ':where([data-color-scheme=\"light\"] $root)' : Object.assign({ colorScheme : 'light' }, diff.left)\n }\n };\n } else {\n styles = {\n root : {\n ':where(&)' : Object.assign({ colorScheme }, makeCssVars(themes[colorScheme], prefix))\n }\n };\n }\n\n return (options.createStyleSheet || css)(styles, options.styleSheetOptions);\n};\n\nexport default createTheme;\n"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"createTheme.js","sources":["../src/createTheme.js"],"sourcesContent":["import css from './css.js';\nimport StyleSheet from './StyleSheet.js';\nimport isObject from './utils/isObject.js';\n\n/**\n * Flattens a nested theme object into a map of CSS variable names to values.\n * Nested keys are joined with `-` (e.g. `{ colors: { primary: 'blue' } }` → `--prefix-colors-primary`).\n * @private\n * @param {Object} [theme={}] - Nested theme object.\n * @param {string|null} [prefix] - Prefix for variable names (e.g. `fun` → `--fun-key`). Omit or pass `null`/`''` for no prefix.\n * @returns {Object} Map of CSS variable names (e.g. `--fun-color`) to values.\n */\nconst makeCssVars = (theme = {}, prefix) => {\n function build(theme, nameAcc) {\n return Object.keys(theme).reduce((acc, key) => {\n const value = theme[key];\n const name = nameAcc ? `${nameAcc}-${key}` : prefix ? `--${prefix}-${key}` : `--${key}`;\n\n if (isObject(value)) {\n Object.assign(acc, build(value, name));\n } else if (typeof value !== 'undefined' && value !== null) {\n acc[name] = value;\n }\n\n return acc;\n }, {});\n }\n return build(theme);\n};\n\n/**\n * Returns keys that differ between two objects, with each side’s value.\n * @private\n * @param {Object} left - First object.\n * @param {Object} right - Second object.\n * @returns {{ left: Object, right: Object }} Objects containing only the differing keys and their values per side.\n */\nconst getDiff = (left, right) => {\n return Object.keys(left).reduce((acc, key) => {\n if (left[key] !== right[key]) {\n acc.left[key] = left[key];\n acc.right[key] = right[key];\n }\n return acc;\n }, { left : {}, right : {} });\n};\n\n/**\n * The `createTheme` function generates a theme StyleSheet instance with CSS variables \n * based on the provided themes and options. It supports multiple color schemes, \n * including `light`, `dark`, `light dark`, and `normal`. \n * \n * The `themes` object defines the styles for these color schemes. Each key in the object \n * corresponds to a color scheme (`light`, `dark`, `normal`), and its value is an object \n * containing key-value pairs that will be converted into CSS variables. Nested keys are \n * concatenated with `-` to form the variable name. For example, `{ light : { colors : { primary : 'blue' } } }` \n * generates `--fun-colors-primary : blue`.\n * \n * @module\n * @function\n * @param {Object} themes - An object defining styles for color schemes (`light`, `dark`, `normal`). \n * Each key corresponds to a color scheme, and its value is an object of key-value pairs converted \n * to CSS variables. Nested keys are concatenated with `-` to form variable names.\n * \n * @param {Object} [options] - An optional object to customize the theme generation. It includes options \n * for selecting color schemes, customizing CSS variable prefixes, and controlling StyleSheet creation.\n * \n * @param {String} [options.colorScheme] - Specifies the color scheme(s) to use. Possible values are: \n * `light` (uses the `light` theme only), `dark` (uses the `dark` theme only), `light dark` (default, \n * supports both `light` and `dark` themes, adapting to system preferences; can override system \n * preference with `data-color-scheme` set to `light` or `dark`), and `normal` (uses the `normal` theme only).\n * \n * @param {String|null} [options.cssVarsPrefix] - Prefix for the generated CSS variables. Defaults to `StyleSheet.prefix`.\n * Pass `null` or `''` to generate variables without a prefix (e.g. `--color` instead of `--fun-color`).\n * \n * @param {Function} [options.createStyleSheet] - A function used to create a new StyleSheet instance. \n * By default, it uses the `css` function.\n * \n * @param {Object} [options.styleSheetOptions] - Options to pass when creating the StyleSheet instance. \n * Default is `system`.\n * \n * @returns {StyleSheet} The theme StyleSheet instance. Use `classes.root` to get the theme class name. \n * Apply this class to the element you want to theme. The CSS variables will be available for all \n * its descendants.\n * \n * @example\n * // Create a theme with light and dark color schemes and apply it to the entire page.\n * const theme = createTheme({\n * light : {\n * colorPrimary : 'black',\n * backgroundLevel1 : 'white'\n * },\n * dark : {\n * colorPrimary : 'white',\n * backgroundLevel1 : 'black'\n * }\n * });\n * \n * // Add the `root` class (the theme class) to the body element.\n * // This will apply the theme to the entire page.\n * document.body.classList.add(theme.classes.root);\n * \n * // Add some styles using the theme CSS variables.\n * const { classes } = css({\n * button : {\n * color : 'var(--fun-colorPrimary)', // Use the CSS variable generated from the theme.\n * backgroundColor : 'var(--fun-backgroundLevel1)'\n * }\n * });\n * \n * // Add the `button` class to a button component.\n * // The button will use the CSS variables defined in the theme for its styles.\n * // Once the theme is applied, the button will automatically update its styles.\n * // If the system color scheme changes (e.g., from light to dark), the button will \n * // dynamically update to reflect the new theme without requiring additional code.\n * const Button = ({ label }) => <button className={classes.button}>{label}</button>;\n */\nconst createTheme = (themes = {}, options = {}) => {\n const colorScheme = options.colorScheme || 'light dark';\n const prefix = 'cssVarsPrefix' in options ? options.cssVarsPrefix : StyleSheet.prefix;\n\n let styles;\n\n if (colorScheme === 'light dark') {\n const cssVars = {\n light : makeCssVars(themes.light, prefix),\n dark : makeCssVars(themes.dark, prefix)\n };\n\n const diff = getDiff(cssVars.light, cssVars.dark);\n\n styles = {\n root : {\n ':where(&)' : Object.assign({ colorScheme : 'light' }, cssVars.light),\n ':where([data-color-scheme=\"dark\"] &)' : Object.assign({ colorScheme : 'dark' }, diff.right),\n },\n '@media (prefers-color-scheme: dark)' : {\n ':where($root)' : Object.assign({ colorScheme : 'dark' }, diff.right),\n ':where([data-color-scheme=\"light\"] $root)' : Object.assign({ colorScheme : 'light' }, diff.left)\n }\n };\n } else {\n styles = {\n root : {\n ':where(&)' : Object.assign({ colorScheme }, makeCssVars(themes[colorScheme], prefix))\n }\n };\n }\n\n return (options.createStyleSheet || css)(styles, options.styleSheetOptions);\n};\n\nexport default createTheme;\n"],"names":[],"mappings":"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"} |
+34
-13
@@ -8,14 +8,35 @@ 'use strict'; | ||
| const makeCssVars = (theme = {}, prefix = '--') => { | ||
| return Object.keys(theme).reduce((acc, key) => { | ||
| const value = theme[key]; | ||
| if (utils_isObject(value)) { | ||
| Object.assign(acc, makeCssVars(value, `${prefix}-${key}`)); | ||
| } else if (typeof value !== 'undefined' && value !== null) { | ||
| acc[`${prefix}-${key}`] = value; | ||
| } | ||
| return acc; | ||
| }, {}); | ||
| /** | ||
| * Flattens a nested theme object into a map of CSS variable names to values. | ||
| * Nested keys are joined with `-` (e.g. `{ colors: { primary: 'blue' } }` → `--prefix-colors-primary`). | ||
| * @private | ||
| * @param {Object} [theme={}] - Nested theme object. | ||
| * @param {string|null} [prefix] - Prefix for variable names (e.g. `fun` → `--fun-key`). Omit or pass `null`/`''` for no prefix. | ||
| * @returns {Object} Map of CSS variable names (e.g. `--fun-color`) to values. | ||
| */ | ||
| const makeCssVars = (theme = {}, prefix) => { | ||
| function build(theme, nameAcc) { | ||
| return Object.keys(theme).reduce((acc, key) => { | ||
| const value = theme[key]; | ||
| const name = nameAcc ? `${nameAcc}-${key}` : prefix ? `--${prefix}-${key}` : `--${key}`; | ||
| if (utils_isObject(value)) { | ||
| Object.assign(acc, build(value, name)); | ||
| } else if (typeof value !== 'undefined' && value !== null) { | ||
| acc[name] = value; | ||
| } | ||
| return acc; | ||
| }, {}); | ||
| } | ||
| return build(theme); | ||
| }; | ||
| /** | ||
| * Returns keys that differ between two objects, with each side’s value. | ||
| * @private | ||
| * @param {Object} left - First object. | ||
| * @param {Object} right - Second object. | ||
| * @returns {{ left: Object, right: Object }} Objects containing only the differing keys and their values per side. | ||
| */ | ||
| const getDiff = (left, right) => { | ||
@@ -56,4 +77,4 @@ return Object.keys(left).reduce((acc, key) => { | ||
| * | ||
| * @param {String} [options.cssVarsPrefix] - The prefix for the generated CSS variables. Default is `fun`. | ||
| * For example, a key `color` in the theme will generate a CSS variable like `--fun-color`. | ||
| * @param {String|null} [options.cssVarsPrefix] - Prefix for the generated CSS variables. Defaults to `StyleSheet.prefix`. | ||
| * Pass `null` or `''` to generate variables without a prefix (e.g. `--color` instead of `--fun-color`). | ||
| * | ||
@@ -104,3 +125,3 @@ * @param {Function} [options.createStyleSheet] - A function used to create a new StyleSheet instance. | ||
| const colorScheme = options.colorScheme || 'light dark'; | ||
| const prefix = `--${options.cssVarsPrefix || StyleSheet.prefix}`; | ||
| const prefix = 'cssVarsPrefix' in options ? options.cssVarsPrefix : StyleSheet.prefix; | ||
@@ -107,0 +128,0 @@ let styles; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"createTheme.cjs","sources":["../src/createTheme.js"],"sourcesContent":["import css from './css.js';\nimport StyleSheet from './StyleSheet.js';\nimport isObject from './utils/isObject.js';\n\nconst makeCssVars = (theme = {}, prefix = '--') => {\n return Object.keys(theme).reduce((acc, key) => {\n const value = theme[key];\n if (isObject(value)) {\n Object.assign(acc, makeCssVars(value, `${prefix}-${key}`));\n } else if (typeof value !== 'undefined' && value !== null) {\n acc[`${prefix}-${key}`] = value;\n }\n return acc;\n }, {});\n};\n\nconst getDiff = (left, right) => {\n return Object.keys(left).reduce((acc, key) => {\n if (left[key] !== right[key]) {\n acc.left[key] = left[key];\n acc.right[key] = right[key];\n }\n return acc;\n }, { left : {}, right : {} });\n};\n\n/**\n * The `createTheme` function generates a theme StyleSheet instance with CSS variables \n * based on the provided themes and options. It supports multiple color schemes, \n * including `light`, `dark`, `light dark`, and `normal`. \n * \n * The `themes` object defines the styles for these color schemes. Each key in the object \n * corresponds to a color scheme (`light`, `dark`, `normal`), and its value is an object \n * containing key-value pairs that will be converted into CSS variables. Nested keys are \n * concatenated with `-` to form the variable name. For example, `{ light : { colors : { primary : 'blue' } } }` \n * generates `--fun-colors-primary : blue`.\n * \n * @module\n * @function\n * @param {Object} themes - An object defining styles for color schemes (`light`, `dark`, `normal`). \n * Each key corresponds to a color scheme, and its value is an object of key-value pairs converted \n * to CSS variables. Nested keys are concatenated with `-` to form variable names.\n * \n * @param {Object} [options] - An optional object to customize the theme generation. It includes options \n * for selecting color schemes, customizing CSS variable prefixes, and controlling StyleSheet creation.\n * \n * @param {String} [options.colorScheme] - Specifies the color scheme(s) to use. Possible values are: \n * `light` (uses the `light` theme only), `dark` (uses the `dark` theme only), `light dark` (default, \n * supports both `light` and `dark` themes, adapting to system preferences; can override system \n * preference with `data-color-scheme` set to `light` or `dark`), and `normal` (uses the `normal` theme only).\n * \n * @param {String} [options.cssVarsPrefix] - The prefix for the generated CSS variables. Default is `fun`. \n * For example, a key `color` in the theme will generate a CSS variable like `--fun-color`.\n * \n * @param {Function} [options.createStyleSheet] - A function used to create a new StyleSheet instance. \n * By default, it uses the `css` function.\n * \n * @param {Object} [options.styleSheetOptions] - Options to pass when creating the StyleSheet instance. \n * Default is `system`.\n * \n * @returns {StyleSheet} The theme StyleSheet instance. Use `classes.root` to get the theme class name. \n * Apply this class to the element you want to theme. The CSS variables will be available for all \n * its descendants.\n * \n * @example\n * // Create a theme with light and dark color schemes and apply it to the entire page.\n * const theme = createTheme({\n * light : {\n * colorPrimary : 'black',\n * backgroundLevel1 : 'white'\n * },\n * dark : {\n * colorPrimary : 'white',\n * backgroundLevel1 : 'black'\n * }\n * });\n * \n * // Add the `root` class (the theme class) to the body element.\n * // This will apply the theme to the entire page.\n * document.body.classList.add(theme.classes.root);\n * \n * // Add some styles using the theme CSS variables.\n * const { classes } = css({\n * button : {\n * color : 'var(--fun-colorPrimary)', // Use the CSS variable generated from the theme.\n * backgroundColor : 'var(--fun-backgroundLevel1)'\n * }\n * });\n * \n * // Add the `button` class to a button component.\n * // The button will use the CSS variables defined in the theme for its styles.\n * // Once the theme is applied, the button will automatically update its styles.\n * // If the system color scheme changes (e.g., from light to dark), the button will \n * // dynamically update to reflect the new theme without requiring additional code.\n * const Button = ({ label }) => <button className={classes.button}>{label}</button>;\n */\nconst createTheme = (themes = {}, options = {}) => {\n const colorScheme = options.colorScheme || 'light dark';\n const prefix = `--${options.cssVarsPrefix || StyleSheet.prefix}`;\n\n let styles;\n\n if (colorScheme === 'light dark') {\n const cssVars = {\n light : makeCssVars(themes.light, prefix),\n dark : makeCssVars(themes.dark, prefix)\n };\n\n const diff = getDiff(cssVars.light, cssVars.dark);\n\n styles = {\n root : {\n ':where(&)' : Object.assign({ colorScheme : 'light' }, cssVars.light),\n ':where([data-color-scheme=\"dark\"] &)' : Object.assign({ colorScheme : 'dark' }, diff.right),\n },\n '@media (prefers-color-scheme: dark)' : {\n ':where($root)' : Object.assign({ colorScheme : 'dark' }, diff.right),\n ':where([data-color-scheme=\"light\"] $root)' : Object.assign({ colorScheme : 'light' }, diff.left)\n }\n };\n } else {\n styles = {\n root : {\n ':where(&)' : Object.assign({ colorScheme }, makeCssVars(themes[colorScheme], prefix))\n }\n };\n }\n\n return (options.createStyleSheet || css)(styles, options.styleSheetOptions);\n};\n\nexport default createTheme;\n"],"names":["isObject"],"mappings":"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"} | ||
| {"version":3,"file":"createTheme.cjs","sources":["../src/createTheme.js"],"sourcesContent":["import css from './css.js';\nimport StyleSheet from './StyleSheet.js';\nimport isObject from './utils/isObject.js';\n\n/**\n * Flattens a nested theme object into a map of CSS variable names to values.\n * Nested keys are joined with `-` (e.g. `{ colors: { primary: 'blue' } }` → `--prefix-colors-primary`).\n * @private\n * @param {Object} [theme={}] - Nested theme object.\n * @param {string|null} [prefix] - Prefix for variable names (e.g. `fun` → `--fun-key`). Omit or pass `null`/`''` for no prefix.\n * @returns {Object} Map of CSS variable names (e.g. `--fun-color`) to values.\n */\nconst makeCssVars = (theme = {}, prefix) => {\n function build(theme, nameAcc) {\n return Object.keys(theme).reduce((acc, key) => {\n const value = theme[key];\n const name = nameAcc ? `${nameAcc}-${key}` : prefix ? `--${prefix}-${key}` : `--${key}`;\n\n if (isObject(value)) {\n Object.assign(acc, build(value, name));\n } else if (typeof value !== 'undefined' && value !== null) {\n acc[name] = value;\n }\n\n return acc;\n }, {});\n }\n return build(theme);\n};\n\n/**\n * Returns keys that differ between two objects, with each side’s value.\n * @private\n * @param {Object} left - First object.\n * @param {Object} right - Second object.\n * @returns {{ left: Object, right: Object }} Objects containing only the differing keys and their values per side.\n */\nconst getDiff = (left, right) => {\n return Object.keys(left).reduce((acc, key) => {\n if (left[key] !== right[key]) {\n acc.left[key] = left[key];\n acc.right[key] = right[key];\n }\n return acc;\n }, { left : {}, right : {} });\n};\n\n/**\n * The `createTheme` function generates a theme StyleSheet instance with CSS variables \n * based on the provided themes and options. It supports multiple color schemes, \n * including `light`, `dark`, `light dark`, and `normal`. \n * \n * The `themes` object defines the styles for these color schemes. Each key in the object \n * corresponds to a color scheme (`light`, `dark`, `normal`), and its value is an object \n * containing key-value pairs that will be converted into CSS variables. Nested keys are \n * concatenated with `-` to form the variable name. For example, `{ light : { colors : { primary : 'blue' } } }` \n * generates `--fun-colors-primary : blue`.\n * \n * @module\n * @function\n * @param {Object} themes - An object defining styles for color schemes (`light`, `dark`, `normal`). \n * Each key corresponds to a color scheme, and its value is an object of key-value pairs converted \n * to CSS variables. Nested keys are concatenated with `-` to form variable names.\n * \n * @param {Object} [options] - An optional object to customize the theme generation. It includes options \n * for selecting color schemes, customizing CSS variable prefixes, and controlling StyleSheet creation.\n * \n * @param {String} [options.colorScheme] - Specifies the color scheme(s) to use. Possible values are: \n * `light` (uses the `light` theme only), `dark` (uses the `dark` theme only), `light dark` (default, \n * supports both `light` and `dark` themes, adapting to system preferences; can override system \n * preference with `data-color-scheme` set to `light` or `dark`), and `normal` (uses the `normal` theme only).\n * \n * @param {String|null} [options.cssVarsPrefix] - Prefix for the generated CSS variables. Defaults to `StyleSheet.prefix`.\n * Pass `null` or `''` to generate variables without a prefix (e.g. `--color` instead of `--fun-color`).\n * \n * @param {Function} [options.createStyleSheet] - A function used to create a new StyleSheet instance. \n * By default, it uses the `css` function.\n * \n * @param {Object} [options.styleSheetOptions] - Options to pass when creating the StyleSheet instance. \n * Default is `system`.\n * \n * @returns {StyleSheet} The theme StyleSheet instance. Use `classes.root` to get the theme class name. \n * Apply this class to the element you want to theme. The CSS variables will be available for all \n * its descendants.\n * \n * @example\n * // Create a theme with light and dark color schemes and apply it to the entire page.\n * const theme = createTheme({\n * light : {\n * colorPrimary : 'black',\n * backgroundLevel1 : 'white'\n * },\n * dark : {\n * colorPrimary : 'white',\n * backgroundLevel1 : 'black'\n * }\n * });\n * \n * // Add the `root` class (the theme class) to the body element.\n * // This will apply the theme to the entire page.\n * document.body.classList.add(theme.classes.root);\n * \n * // Add some styles using the theme CSS variables.\n * const { classes } = css({\n * button : {\n * color : 'var(--fun-colorPrimary)', // Use the CSS variable generated from the theme.\n * backgroundColor : 'var(--fun-backgroundLevel1)'\n * }\n * });\n * \n * // Add the `button` class to a button component.\n * // The button will use the CSS variables defined in the theme for its styles.\n * // Once the theme is applied, the button will automatically update its styles.\n * // If the system color scheme changes (e.g., from light to dark), the button will \n * // dynamically update to reflect the new theme without requiring additional code.\n * const Button = ({ label }) => <button className={classes.button}>{label}</button>;\n */\nconst createTheme = (themes = {}, options = {}) => {\n const colorScheme = options.colorScheme || 'light dark';\n const prefix = 'cssVarsPrefix' in options ? options.cssVarsPrefix : StyleSheet.prefix;\n\n let styles;\n\n if (colorScheme === 'light dark') {\n const cssVars = {\n light : makeCssVars(themes.light, prefix),\n dark : makeCssVars(themes.dark, prefix)\n };\n\n const diff = getDiff(cssVars.light, cssVars.dark);\n\n styles = {\n root : {\n ':where(&)' : Object.assign({ colorScheme : 'light' }, cssVars.light),\n ':where([data-color-scheme=\"dark\"] &)' : Object.assign({ colorScheme : 'dark' }, diff.right),\n },\n '@media (prefers-color-scheme: dark)' : {\n ':where($root)' : Object.assign({ colorScheme : 'dark' }, diff.right),\n ':where([data-color-scheme=\"light\"] $root)' : Object.assign({ colorScheme : 'light' }, diff.left)\n }\n };\n } else {\n styles = {\n root : {\n ':where(&)' : Object.assign({ colorScheme }, makeCssVars(themes[colorScheme], prefix))\n }\n };\n }\n\n return (options.createStyleSheet || css)(styles, options.styleSheetOptions);\n};\n\nexport default createTheme;\n"],"names":["isObject"],"mappings":"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"} |
+7
-8
| { | ||
| "name": "cssfun", | ||
| "version": "0.0.13", | ||
| "version": "0.0.14", | ||
| "description": "Near-zero runtime CSS-in-JS library", | ||
@@ -28,3 +28,3 @@ "type": "module", | ||
| "prepare": "npm run clean && npm run test && npm run build", | ||
| "clean": "rimraf lib dist es", | ||
| "clean": "node -e \"const fs=require('fs');['lib','dist','es'].forEach(d=>fs.rmSync(d,{recursive:true,force:true}))\"", | ||
| "test": "mocha --require jsdom-global/register --reporter nyan test/*.js", | ||
@@ -59,14 +59,13 @@ "posttest": "npm run lint", | ||
| "@rollup/plugin-replace": "^6.0.3", | ||
| "@rollup/plugin-terser": "^0.4.4", | ||
| "@rollup/plugin-terser": "^1.0.0", | ||
| "chai": "^6.0.1", | ||
| "eslint": "^9.34.0", | ||
| "glob": "^13.0.0", | ||
| "glob": "^13.0.6", | ||
| "globals": "^16.3.0", | ||
| "jsdoc-to-markdown": "^9.1.2", | ||
| "jsdom": "^26.1.0", | ||
| "jsdom": "^29.0.1", | ||
| "jsdom-global": "3.0.2", | ||
| "mocha": "^11.7.1", | ||
| "rimraf": "^6.0.1", | ||
| "rollup": "^4.48.1" | ||
| "mocha": "^11.7.5", | ||
| "rollup": "^4.60.1" | ||
| } | ||
| } |
+75
-17
| <p align="center"> | ||
| <picture> | ||
| <source media="(prefers-color-scheme: dark)" srcset="https://cdn.jsdelivr.net/gh/8tentaculos/cssfun@v0.0.13/docs/logo-dark.svg"> | ||
| <img alt="CSSFUN" src="https://cdn.jsdelivr.net/gh/8tentaculos/cssfun@v0.0.13/docs/logo.svg"> | ||
| <source media="(prefers-color-scheme: dark)" srcset="https://cdn.jsdelivr.net/gh/8tentaculos/cssfun@v0.0.14/docs/logo-dark.svg"> | ||
| <img alt="CSSFUN" src="https://cdn.jsdelivr.net/gh/8tentaculos/cssfun@v0.0.14/docs/logo.svg"> | ||
| </picture> | ||
@@ -14,6 +14,6 @@ </p> | ||
| [](https://www.npmjs.com/package/cssfun) | ||
| [](https://unpkg.com/cssfun/dist/cssfun.min.js) | ||
| [](https://www.npmjs.com/package/cssfun) | ||
| [](https://www.jsdelivr.com/package/npm/cssfun) | ||
| [](https://www.npmjs.com/package/cssfun) | ||
| [](https://unpkg.com/cssfun/dist/cssfun.min.js) | ||
| [](https://www.npmjs.com/package/cssfun) | ||
| [](https://www.jsdelivr.com/package/npm/cssfun) | ||
@@ -91,14 +91,50 @@ ## Key Features | ||
| ## Class Name Generation | ||
| When you call `css()`, **CSSFUN** automatically generates unique, scoped class names for each top-level selector in your styles object. These class names are created **at module initialization**, ensuring near-zero runtime overhead. | ||
| ### How Classes Are Generated | ||
| 1. **When**: Classes are generated immediately when `css()` is called, during the StyleSheet instance creation. | ||
| 2. **Which selectors**: Only top-level selectors that match valid class name patterns (alphanumeric characters, no special characters) get generated classes. | ||
| 3. **Format**: The format differs between development and production modes: | ||
| **Development Mode** (readable, for debugging): | ||
| ``` | ||
| {prefix}-{uid}-{className} | ||
| ``` | ||
| Example: `.fun-9qkk9s-button` (prefix `fun` + unique ID `9qkk9s` + original class name `button`) | ||
| **Production Mode** (optimized, smaller bundle): | ||
| ``` | ||
| {prefix[0]}-{uid}-{index} | ||
| ``` | ||
| Example: `.f-9qkk9s-1` (first letter of prefix `f` + unique ID `9qkk9s` + sequential index `1`) | ||
| 4. **Access**: Generated class names are available via the `classes` object returned by `css()`: | ||
| ```javascript | ||
| const { classes } = css({ | ||
| button: { color: 'red' }, | ||
| link: { color: 'blue' } | ||
| }); | ||
| // classes.button → "fun-9qkk9s-button" (dev) or "f-9qkk9s-1" (prod) | ||
| // classes.link → "fun-9qkk9s-link" (dev) or "f-9qkk9s-2" (prod) | ||
| ``` | ||
| > **Note**: All examples in this documentation show class names in **development mode** for clarity. | ||
| > In **production**, class names are automatically optimized for smaller bundle size. | ||
| > You can customize class name generation via [`options.generateClassName`](/docs/api.md#new-stylesheetstyles-options) or by [extending the class](/docs/api.md#stylesheet__generateclassname). | ||
| ## Renderers | ||
| Renderers are functions that transform style objects into CSS strings. | ||
| Renderers are functions that transform style objects into CSS strings. They are applied in sequence, with each renderer receiving the output of the previous one. | ||
| **CSSFUN** uses two built-in renderers by default: | ||
| 1. **`parseStyles`**: Transforms the style object (expands nested selectors, replaces class references, converts camelCase to dashed-case, handles global styles) | ||
| 2. **`renderStyles`**: Converts the processed object into a CSS string | ||
| The final renderer in the chain outputs the CSS string that gets injected into the DOM. | ||
| These are the built-in renderers transformations: | ||
| > **Note**: All examples below show class names generated in **development mode**. | ||
| > In **production**, class names are optimized for smaller bundle size: | ||
| > - **Development**: `.fun-9qkk9s-root { color: red; }` (full prefix + class name) | ||
| > - **Production**: `.f-9qkk9s-1{color:red;}` (first letter of prefix + index) | ||
| > | ||
| > Customize via [`options.generateClassName`](/docs/api.md#new-stylesheetstyles-options) or by [extending the class](/docs/api.md#stylesheet__generateclassname). | ||
| #### Camelized keys will be transformed to dashed keys | ||
@@ -109,3 +145,5 @@ | ||
| root : { | ||
| backgroundColor : 'black' | ||
| backgroundColor : 'black', | ||
| fontSize : '16px', | ||
| paddingTop : '10px' | ||
| } | ||
@@ -121,2 +159,4 @@ }).toString(); | ||
| background-color: black; | ||
| font-size: 16px; | ||
| padding-top: 10px; | ||
| } | ||
@@ -311,4 +351,16 @@ </style> | ||
| When composed, the first renderer receives the styles object, and the final one outputs the | ||
| resulting CSS string. | ||
| resulting CSS string. The renderers are applied in sequence: each renderer receives the output | ||
| of the previous one. | ||
| **Example flow:** | ||
| ``` | ||
| Input styles object | ||
| ↓ | ||
| [parseStyles] → Transforms object (expands nested, replaces references, converts camelCase) | ||
| ↓ | ||
| [renderStyles] → Converts object to CSS string | ||
| ↓ | ||
| Output CSS string | ||
| ``` | ||
| ### Custom Renderers | ||
@@ -322,4 +374,6 @@ | ||
| By default, [`StyleSheet`](/docs/api.md#stylesheet) are rendered using the built-in renderers: `[this.renderStyles, this.parseStyles]`. | ||
| By default, [`StyleSheet`](/docs/api.md#stylesheet) instances are rendered using the built-in renderers: `[this.renderStyles, this.parseStyles]`. | ||
| **Note:** The order matters! Renderers are composed, so they execute in reverse order. With `[renderStyles, parseStyles]`, `parseStyles` executes first (transforms the object), then `renderStyles` (converts to CSS string). | ||
| ## Themes | ||
@@ -483,2 +537,6 @@ | ||
| ## Working with LLMs | ||
| For those working with LLMs, there is an [AI Agents reference guide](/docs/AGENTS.md) that provides API patterns, style syntax, theme management, and best practices, optimized for LLM context. You can share this guide with AI assistants to help them understand **CSSFUN**'s architecture and styling APIs. | ||
| ## Examples | ||
@@ -485,0 +543,0 @@ |
+34
-13
@@ -5,14 +5,35 @@ import css from './css.js'; | ||
| const makeCssVars = (theme = {}, prefix = '--') => { | ||
| return Object.keys(theme).reduce((acc, key) => { | ||
| const value = theme[key]; | ||
| if (isObject(value)) { | ||
| Object.assign(acc, makeCssVars(value, `${prefix}-${key}`)); | ||
| } else if (typeof value !== 'undefined' && value !== null) { | ||
| acc[`${prefix}-${key}`] = value; | ||
| } | ||
| return acc; | ||
| }, {}); | ||
| /** | ||
| * Flattens a nested theme object into a map of CSS variable names to values. | ||
| * Nested keys are joined with `-` (e.g. `{ colors: { primary: 'blue' } }` → `--prefix-colors-primary`). | ||
| * @private | ||
| * @param {Object} [theme={}] - Nested theme object. | ||
| * @param {string|null} [prefix] - Prefix for variable names (e.g. `fun` → `--fun-key`). Omit or pass `null`/`''` for no prefix. | ||
| * @returns {Object} Map of CSS variable names (e.g. `--fun-color`) to values. | ||
| */ | ||
| const makeCssVars = (theme = {}, prefix) => { | ||
| function build(theme, nameAcc) { | ||
| return Object.keys(theme).reduce((acc, key) => { | ||
| const value = theme[key]; | ||
| const name = nameAcc ? `${nameAcc}-${key}` : prefix ? `--${prefix}-${key}` : `--${key}`; | ||
| if (isObject(value)) { | ||
| Object.assign(acc, build(value, name)); | ||
| } else if (typeof value !== 'undefined' && value !== null) { | ||
| acc[name] = value; | ||
| } | ||
| return acc; | ||
| }, {}); | ||
| } | ||
| return build(theme); | ||
| }; | ||
| /** | ||
| * Returns keys that differ between two objects, with each side’s value. | ||
| * @private | ||
| * @param {Object} left - First object. | ||
| * @param {Object} right - Second object. | ||
| * @returns {{ left: Object, right: Object }} Objects containing only the differing keys and their values per side. | ||
| */ | ||
| const getDiff = (left, right) => { | ||
@@ -53,4 +74,4 @@ return Object.keys(left).reduce((acc, key) => { | ||
| * | ||
| * @param {String} [options.cssVarsPrefix] - The prefix for the generated CSS variables. Default is `fun`. | ||
| * For example, a key `color` in the theme will generate a CSS variable like `--fun-color`. | ||
| * @param {String|null} [options.cssVarsPrefix] - Prefix for the generated CSS variables. Defaults to `StyleSheet.prefix`. | ||
| * Pass `null` or `''` to generate variables without a prefix (e.g. `--color` instead of `--fun-color`). | ||
| * | ||
@@ -101,3 +122,3 @@ * @param {Function} [options.createStyleSheet] - A function used to create a new StyleSheet instance. | ||
| const colorScheme = options.colorScheme || 'light dark'; | ||
| const prefix = `--${options.cssVarsPrefix || StyleSheet.prefix}`; | ||
| const prefix = 'cssVarsPrefix' in options ? options.cssVarsPrefix : StyleSheet.prefix; | ||
@@ -104,0 +125,0 @@ let styles; |
Sorry, the diff of this file is too big to display
381140
4.48%12
-7.69%2333
3.37%554
11.69%