UNPKG

react-style-stringify

Version:

A utility for converting React CSSProperties and style maps into CSS strings, designed to simplify the management of inline styles in HTML email templates and React projects.

1 lines 11 kB
{"version":3,"sources":["../src/helpers.ts","../src/stringifyStyleDeclaration.ts","../src/stringifyStyleRule.ts","../src/stringify-react-styles.ts"],"sourcesContent":["import unitless from \"@emotion/unitless\";\nimport { CSSUnit, CSSUnitMap } from \"./types\";\n\nconst DEFAULT_UNIT = \"px\";\n\nexport const isCSSPropertyValue = (value: unknown): value is number | string =>\n typeof value === \"number\" || typeof value === \"string\";\n\nexport function camelToKebab(str: string) {\n return str.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);\n}\n\nexport function trimCssSelector(selector: string) {\n return selector\n .replace(/\\s*([+~>])\\s*/g, \"$1\")\n .replace(/\\s{2,}/g, \" \")\n .trim();\n}\n\nexport function applyCssUnits<T extends string = string>(\n property: T,\n value: string | number,\n unit: CSSUnit | CSSUnitMap<T> = DEFAULT_UNIT\n) {\n if (typeof value !== \"string\" && typeof value !== \"number\") {\n throw new Error(\n \"Invalid input: value of 'cssProperties' must be string or number.\"\n );\n }\n\n const isUnitless = unitless[property] === 1;\n\n if (typeof value === \"string\" || value === 0 || isUnitless) {\n return `${value}`;\n }\n\n const resolvedUnit =\n (typeof unit === \"string\" ? unit : unit[property]) || DEFAULT_UNIT;\n\n return `${value}${resolvedUnit}`;\n}\n","import { StringifyOptions } from \"./types\";\nimport { applyCssUnits, camelToKebab, isCSSPropertyValue } from \"./helpers\";\n\nexport type StyleDeclaration = Record<string, string | number>;\n\n/**\n * Converts a StyleDeclaration object into a CSS string.\n *\n * @param {object} styleDeclaration - An object representing a CSS declaration block, where keys are camelCased CSS property names and values are the corresponding CSS values (strings or numbers).\n * @param {StringifyOptions<T>} [options] - Optional configuration object:\n * - `important` — If set to `true`, appends `!important` to each CSS declaration.\n * - `unit` — A CSS unit or a map of property keys to units:\n * - If a string is provided (e.g. `'em'`), it will be used as the unit for all numeric properties.\n * - If a map is provided (e.g. `{ width: 'rem' }`), the unit will be applied per numeric property.\n * - If a property has a numeric value and no specific unit is defined in the map, `'px'` will be used by default.\n *\n * @returns {string} A formatted CSS string where:\n * - Keys are converted from camelCase to kebab-case.\n * - Units are added to numeric values as specified, or `'px'` by default.\n * - Each declaration ends with a semicolon.\n * - `!important` is appended if the `important` flag is set.\n *\n * @throws {TypeError} Throws if the `styleDeclaration` argument is not a non-null object.\n */\nexport function stringifyStyleDeclaration<T extends object = StyleDeclaration>(\n styleDeclaration: T,\n options?: StringifyOptions<T>\n): string {\n if (typeof styleDeclaration !== \"object\" || styleDeclaration === null) {\n throw new TypeError(\n `[stringifyStyleDeclaration]: Expected 'styleDeclaration' to be a non-null object, but received ${styleDeclaration} (type:${typeof styleDeclaration}).`\n );\n }\n\n const importantSuffix = options?.important ? \"!important\" : \"\";\n\n return Object.entries(styleDeclaration)\n .filter(([_, value]) => isCSSPropertyValue(value))\n .map(\n ([property, value]) =>\n `${camelToKebab(property)}:${applyCssUnits(\n property,\n value,\n options?.unit\n )}${importantSuffix};`\n )\n .join(\"\");\n}\n","import {\n stringifyStyleDeclaration,\n type StyleDeclaration,\n} from \"./stringifyStyleDeclaration\";\nimport { trimCssSelector } from \"./helpers\";\nimport { type StringifyOptions } from \"./types\";\n\nexport type StyleRule<T extends object = StyleDeclaration> = Record<string, T>;\n\n/**\n * Converts a style rule object into a CSS string.\n *\n * @template T - The type representing CSS property keys and values used in the style declarations.\n *\n * @param {StyleRule<T>} styleRule - An object where keys are CSS selectors and values are style declarations\n * (objects mapping CSS properties to values).\n * @param {StringifyOptions<T>} [options] - Optional settings controlling how declarations are stringified,\n * such as appending `!important` or units.\n *\n *\n * @returns {string} A CSS string where each selector and its corresponding declarations are formatted properly.\n * Empty declarations are skipped.\n *\n * @throws {TypeError} Throws if the `styleRule` argument is not a non-null object.\n */\nexport function stringifyStyleRule<T extends object = StyleDeclaration>(\n styleRule: StyleRule<T>,\n options?: StringifyOptions<T>\n): string {\n if (typeof styleRule !== \"object\" || styleRule === null) {\n throw new TypeError(\n `[stringifyStyleRule]: Expected 'styleRule' to be a non-null object, but received ${styleRule} (type:${typeof styleRule}).`\n );\n }\n\n return Object.entries(styleRule)\n .reduce<string[]>((result, [selector, declaration]) => {\n if (Object.keys(declaration).length > 0) {\n result.push(\n `${trimCssSelector(selector)}{${stringifyStyleDeclaration<T>(\n declaration,\n options\n )}}`\n );\n }\n return result;\n }, [])\n .join(\"\");\n}\n","import { type CSSProperties } from \"react\";\nimport { type StringifyOptions } from \"./types\";\nimport { stringifyStyleDeclaration } from \"./stringifyStyleDeclaration\";\nimport { stringifyStyleRule } from \"./stringifyStyleRule\";\n\n/**\n * Converts a CSSProperties object into a CSS string.\n *\n * @param {CSSProperties} cssProperties - An object representing CSS declarations, where keys are camelCased property names and values are the corresponding CSS values.\n * - CSSProperties type comes from `@types/react` and is commonly used for inline styles in React components.\n *\n * @param {StringifyOptions | boolean} [optionsOrImportant=false] - Either a boolean indicating whether to append `!important` to each property,\n * or an object with more detailed formatting options:\n * - `important` (boolean): If true, appends `!important` to each property.\n * - `unit` (object | string): A unit (like `'em'`, `'%'`, etc.) to apply to numeric values, or a map of per-property units.\n * If a unit is not provided, `'px'` is used by default for numeric values (except for unitless properties).\n *\n * @returns {string} A formatted CSS string where each property is converted to kebab-case, units are added where necessary,\n * and `!important` is appended if specified.\n *\n * @throws {TypeError} Throws if `cssProperties` is not a non-null object.\n */\nexport function stringifyCSSProperties(\n cssProperties: CSSProperties,\n optionsOrImportant: StringifyOptions<CSSProperties> | boolean = false\n): string {\n if (typeof cssProperties !== \"object\" || cssProperties === null) {\n throw new TypeError(\n `[stringifyCSSProperties]: Expected 'cssProperties' to be a non-null object, but received ${cssProperties} (type:${typeof cssProperties}).`\n );\n }\n\n const options =\n typeof optionsOrImportant === \"boolean\"\n ? {\n important: optionsOrImportant,\n }\n : optionsOrImportant;\n\n return stringifyStyleDeclaration<CSSProperties>(cssProperties, options);\n}\n\nexport type StyleMap = Record<string, CSSProperties>;\n\n/**\n * Converts a `StyleMap` (a map of CSS selectors to React `CSSProperties`) into a string of CSS rules.\n *\n * @param {StyleMap} styleMap - An object where keys are CSS selectors and values are React-style `CSSProperties` objects (camelCased CSS declarations).\n * @param {StringifyOptions | boolean} [optionsOrImportant=false] - Either a boolean flag to apply `!important` to all declarations, or an options object that may include `important` and per-property unit definitions.\n *\n * @returns {string} A formatted CSS string where each selector is followed by its corresponding declarations.\n * Properties are converted to kebab-case and numeric values are suffixed with appropriate units unless the property is unitless.\n *\n * @throws {TypeError} Throws if `cssProperties` is not a non-null object.\n */\nexport function stringifyStyleMap(\n styleMap: StyleMap,\n optionsOrImportant: StringifyOptions<CSSProperties> | boolean = false\n): string {\n if (typeof styleMap !== \"object\" || styleMap === null) {\n throw new TypeError(\n `[stringifyStyleMap]: Expected 'styleMap' to be a non-null object, but received ${styleMap} (type:${typeof styleMap}).`\n );\n }\n\n const options =\n typeof optionsOrImportant === \"boolean\"\n ? {\n important: optionsOrImportant,\n }\n : optionsOrImportant;\n\n return stringifyStyleRule<CSSProperties>(styleMap, options);\n}\n"],"mappings":";AAAA,OAAO,cAAc;AAGrB,IAAM,eAAe;AAEd,IAAM,qBAAqB,CAAC,UACjC,OAAO,UAAU,YAAY,OAAO,UAAU;AAEzC,SAAS,aAAa,KAAa;AACxC,SAAO,IAAI,QAAQ,UAAU,CAAC,UAAU,IAAI,MAAM,YAAY,CAAC,EAAE;AACnE;AAEO,SAAS,gBAAgB,UAAkB;AAChD,SAAO,SACJ,QAAQ,kBAAkB,IAAI,EAC9B,QAAQ,WAAW,GAAG,EACtB,KAAK;AACV;AAEO,SAAS,cACd,UACA,OACA,OAAgC,cAChC;AACA,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAU;AAC1D,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,SAAS,QAAQ,MAAM;AAE1C,MAAI,OAAO,UAAU,YAAY,UAAU,KAAK,YAAY;AAC1D,WAAO,GAAG,KAAK;AAAA,EACjB;AAEA,QAAM,gBACH,OAAO,SAAS,WAAW,OAAO,KAAK,QAAQ,MAAM;AAExD,SAAO,GAAG,KAAK,GAAG,YAAY;AAChC;;;AChBO,SAAS,0BACd,kBACA,SACQ;AACR,MAAI,OAAO,qBAAqB,YAAY,qBAAqB,MAAM;AACrE,UAAM,IAAI;AAAA,MACR,kGAAkG,gBAAgB,UAAU,OAAO,gBAAgB;AAAA,IACrJ;AAAA,EACF;AAEA,QAAM,kBAAkB,SAAS,YAAY,eAAe;AAE5D,SAAO,OAAO,QAAQ,gBAAgB,EACnC,OAAO,CAAC,CAAC,GAAG,KAAK,MAAM,mBAAmB,KAAK,CAAC,EAChD;AAAA,IACC,CAAC,CAAC,UAAU,KAAK,MACf,GAAG,aAAa,QAAQ,CAAC,IAAI;AAAA,MAC3B;AAAA,MACA;AAAA,MACA,SAAS;AAAA,IACX,CAAC,GAAG,eAAe;AAAA,EACvB,EACC,KAAK,EAAE;AACZ;;;ACtBO,SAAS,mBACd,WACA,SACQ;AACR,MAAI,OAAO,cAAc,YAAY,cAAc,MAAM;AACvD,UAAM,IAAI;AAAA,MACR,oFAAoF,SAAS,UAAU,OAAO,SAAS;AAAA,IACzH;AAAA,EACF;AAEA,SAAO,OAAO,QAAQ,SAAS,EAC5B,OAAiB,CAAC,QAAQ,CAAC,UAAU,WAAW,MAAM;AACrD,QAAI,OAAO,KAAK,WAAW,EAAE,SAAS,GAAG;AACvC,aAAO;AAAA,QACL,GAAG,gBAAgB,QAAQ,CAAC,IAAI;AAAA,UAC9B;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO;AAAA,EACT,GAAG,CAAC,CAAC,EACJ,KAAK,EAAE;AACZ;;;AC1BO,SAAS,uBACd,eACA,qBAAgE,OACxD;AACR,MAAI,OAAO,kBAAkB,YAAY,kBAAkB,MAAM;AAC/D,UAAM,IAAI;AAAA,MACR,4FAA4F,aAAa,UAAU,OAAO,aAAa;AAAA,IACzI;AAAA,EACF;AAEA,QAAM,UACJ,OAAO,uBAAuB,YAC1B;AAAA,IACE,WAAW;AAAA,EACb,IACA;AAEN,SAAO,0BAAyC,eAAe,OAAO;AACxE;AAeO,SAAS,kBACd,UACA,qBAAgE,OACxD;AACR,MAAI,OAAO,aAAa,YAAY,aAAa,MAAM;AACrD,UAAM,IAAI;AAAA,MACR,kFAAkF,QAAQ,UAAU,OAAO,QAAQ;AAAA,IACrH;AAAA,EACF;AAEA,QAAM,UACJ,OAAO,uBAAuB,YAC1B;AAAA,IACE,WAAW;AAAA,EACb,IACA;AAEN,SAAO,mBAAkC,UAAU,OAAO;AAC5D;","names":[]}