esm-styles 0.2.8 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -73,13 +73,14 @@ export default {
73
73
  outputPath: 'css',
74
74
  sourceFilesSuffix: '.styles.mjs',
75
75
 
76
- // Input files and their layers (order of layers matters)
76
+ // Input floors (replaces layers parameter)
77
77
  floors: [
78
78
  { source: 'defaults', layer: 'defaults' }, // wrap in layer 'defaults'
79
79
  { source: 'components', layer: 'components' }, // wrap in layer 'components'
80
80
  { source: 'layout', layer: 'layout' }, // wrap in layer 'layout'
81
81
  { source: 'basic' }, // stay out of any layer
82
82
  { source: 'more-layout', layer: 'layout' }, // wrap in layer 'layout'
83
+ { source: 'special', outputPath: 'alt' }, // output to custom path
83
84
  ],
84
85
 
85
86
  // Output
@@ -149,7 +150,8 @@ export default {
149
150
  | `sourcePath` | Directory inside `basePath` containing source style files |
150
151
  | `outputPath` | Directory inside `basePath` where output CSS files will be written |
151
152
  | `sourceFilesSuffix` | Suffix for source style files (default: `.styles.mjs`) |
152
- | `layers` | Array of layer names, defining the order of CSS specificity |
153
+ | `floors` | Array of floor configurations, defining sources, layers, and output paths |
154
+ | `importFloors` | Array of floor names to include in the main CSS file |
153
155
  | `mainCssFile` | Name of the output CSS file that imports all layer and variable files |
154
156
  | `globalVariables` | Name of the file containing global CSS variables |
155
157
  | `globalRootSelector` | Root selector for CSS variables (default: `:root`) |
@@ -316,9 +318,13 @@ Use commas to target multiple selectors:
316
318
  }
317
319
  ```
318
320
 
319
- ## Layers
321
+ ## Floors and Layers
320
322
 
321
- ESM Styles supports @layer directives:
323
+ ESM Styles supports @layer directives through its floors configuration system.
324
+
325
+ ### Inline Layers
326
+
327
+ You can still use inline @layer directives in your styles:
322
328
 
323
329
  ```js
324
330
  {
@@ -333,43 +339,88 @@ ESM Styles supports @layer directives:
333
339
  }
334
340
  ```
335
341
 
336
- Your configuration can define multiple layer files that will be automatically wrapped in their respective layer directives:
342
+ ### Floors Configuration
343
+
344
+ The floors system replaces the old layers configuration and provides more flexibility:
345
+
346
+ ```js
347
+ floors: [
348
+ { source: 'defaults', layer: 'defaults' },
349
+ { source: 'components', layer: 'components' },
350
+ { source: 'layout', layer: 'layout' },
351
+ { source: 'utilities' }, // No layer wrapper
352
+ { source: 'overrides', outputPath: 'special' }, // Custom output path
353
+ ]
354
+ ```
355
+
356
+ Each floor can:
357
+
358
+ - **source**: Name of the source file (required)
359
+ - **layer**: CSS layer name to wrap the styles in (optional)
360
+ - **outputPath**: Custom output directory for this floor's CSS (optional)
361
+
362
+ ### Floor Examples
337
363
 
338
364
  ```js
339
365
  // defaults.styles.mjs
340
366
  export default {
341
- // Base styles
367
+ // Base styles - will be wrapped in @layer defaults
342
368
  }
343
369
 
344
370
  // components.styles.mjs
345
371
  export default {
346
- // Component styles
372
+ // Component styles - will be wrapped in @layer components
347
373
  }
348
374
 
349
- // layout.styles.mjs
375
+ // utilities.styles.mjs
350
376
  export default {
351
- // Layout styles
377
+ // Utility styles - no layer wrapper
352
378
  }
353
379
  ```
354
380
 
355
- The build process generates:
381
+ ### Build Output
382
+
383
+ The build process generates CSS files based on your floors configuration:
356
384
 
357
385
  ```css
386
+ /* styles.css (main file) */
358
387
  @layer defaults, components, layout;
359
388
 
389
+ @import url('./defaults.css');
390
+ @import url('./components.css');
391
+ @import url('./layout.css');
392
+ @import url('./utilities.css'); /* no layer */
393
+
394
+ /* Files with custom outputPath go to their specified directories */
395
+ ```
396
+
397
+ Each layered CSS file has its content wrapped in the appropriate layer:
398
+
399
+ ```css
400
+ /* defaults.css */
360
401
  @layer defaults {
361
- /* defaults.css content */
402
+ /* defaults styles content */
362
403
  }
363
404
 
405
+ /* components.css */
364
406
  @layer components {
365
- /* components.css content */
407
+ /* components styles content */
366
408
  }
367
409
 
368
- @layer layout {
369
- /* layout.css content */
370
- }
410
+ /* utilities.css (no layer) */
411
+ /* utilities styles content directly, no layer wrapper */
371
412
  ```
372
413
 
414
+ ### Import Control
415
+
416
+ Use `importFloors` to control which floors are included in the main CSS file:
417
+
418
+ ```js
419
+ importFloors: ['defaults', 'components', 'layout'], // utilities excluded from main CSS
420
+ ```
421
+
422
+ This allows you to generate standalone CSS files that can be imported separately or conditionally.
423
+
373
424
  ## Media Queries
374
425
 
375
426
  ### Standard Media Queries
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "esm-styles",
3
- "version": "0.2.8",
3
+ "version": "0.3.1",
4
4
  "description": "A library for working with ESM styles",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,14 +0,0 @@
1
- /**
2
- * Main function for converting JavaScript objects to CSS
3
- */
4
- import { CssStyles, MediaQueries, MediaPrefixes, AutoConfig } from './types/index.js';
5
- /**
6
- * Converts a JavaScript style object to CSS string
7
- * @param object - The JavaScript object to convert to CSS
8
- * @param mediaQueries - Media query definitions (e.g., { 'phone': '(max-width: 499px)' })
9
- * @param mediaPrefixes - Media prefix definitions (e.g., { 'dark': ':root.dark' })
10
- * @param auto - Auto mode configuration (e.g., { 'dark': [':root.auto', 'screen and (prefers-color-scheme: dark)'] })
11
- * @returns CSS string
12
- */
13
- export declare function getCss(object: CssStyles, mediaQueries?: MediaQueries, mediaPrefixes?: MediaPrefixes, auto?: AutoConfig): string;
14
- export default getCss;
@@ -1,260 +0,0 @@
1
- /**
2
- * Main function for converting JavaScript objects to CSS
3
- */
4
- import { traverseObject, determineNodeType } from './utils/traversal.js';
5
- import { indent } from './utils/common.js';
6
- import { obj2css, prettifyCss } from './utils/obj2css.js';
7
- import { joinSelectors, cartesianSelectors } from './utils/selectors.js';
8
- import { formatContentValue } from './utils/content.js';
9
- import { jsKeyToCssKey } from './utils/common.js';
10
- import { processMediaQueries } from './utils/media.js';
11
- /**
12
- * Converts a JavaScript style object to CSS string
13
- * @param object - The JavaScript object to convert to CSS
14
- * @param mediaQueries - Media query definitions (e.g., { 'phone': '(max-width: 499px)' })
15
- * @param mediaPrefixes - Media prefix definitions (e.g., { 'dark': ':root.dark' })
16
- * @param auto - Auto mode configuration (e.g., { 'dark': [':root.auto', 'screen and (prefers-color-scheme: dark)'] })
17
- * @returns CSS string
18
- */
19
- export function getCss(object, mediaQueries = {}, mediaPrefixes = {}, auto) {
20
- // Initialize various objects to collect different types of CSS rules
21
- let cssStyle = {};
22
- const layerStatements = [];
23
- let layerObject = {};
24
- let containerObject = {};
25
- const mediaObject = {};
26
- let prefixObject = {};
27
- // Process the object by traversing it and handling different node types
28
- traverseObject(object, (node, path, _, __) => {
29
- if (!path)
30
- return node;
31
- const nodeType = determineNodeType(node, path);
32
- const pathParts = path.split('\\');
33
- const key = pathParts.pop() || '';
34
- // Skip processing media query nodes that are nested within selectors
35
- // as they will be handled separately in the media query section
36
- const isNestedMediaQuery = pathParts.some((part) => part.startsWith('@media ') ||
37
- (part.startsWith('@') &&
38
- mediaQueries[part.replace(/^@\s*/, '')] !== undefined));
39
- switch (nodeType) {
40
- case 'selector': {
41
- // Skip if this is inside a media query - it will be handled separately
42
- if (isNestedMediaQuery) {
43
- break;
44
- }
45
- // Handle CSS property-value pairs
46
- const selector = joinSelectors(pathParts);
47
- // Create cartesian product of selectors for comma-separated parts
48
- if (pathParts.some((part) => part.includes(','))) {
49
- const classPaths = pathParts.map((part) => part.split(',').map((p) => p.trim()));
50
- const allPaths = cartesianSelectors(classPaths);
51
- // Apply the property-value to each selector
52
- allPaths.forEach((selectorPath) => {
53
- const cssKey = jsKeyToCssKey(key);
54
- let value = node;
55
- // Special handling for content property
56
- if (cssKey === 'content') {
57
- value = formatContentValue(value);
58
- }
59
- // Create the CSS object and merge it
60
- const cssObject = {
61
- [selectorPath]: { [cssKey]: value },
62
- };
63
- cssStyle = mergeDeep(cssStyle, cssObject);
64
- });
65
- }
66
- else {
67
- // Simple case - no commas in selectors
68
- const cssKey = jsKeyToCssKey(key);
69
- let value = node;
70
- // Special handling for content property
71
- if (cssKey === 'content') {
72
- value = formatContentValue(value);
73
- }
74
- // Create the CSS object and merge it
75
- const cssObject = {
76
- [selector]: { [cssKey]: value },
77
- };
78
- cssStyle = mergeDeep(cssStyle, cssObject);
79
- }
80
- break;
81
- }
82
- case 'layer statement': {
83
- // Handle @layer statements
84
- const statement = `${key}${node ? ' ' + node : ''};`;
85
- if (!layerStatements.includes(statement)) {
86
- layerStatements.push(statement);
87
- }
88
- break;
89
- }
90
- case 'layer block': {
91
- // Handle @layer blocks
92
- const selector = joinSelectors(pathParts);
93
- const object = { [key]: { [selector]: node } };
94
- layerObject = mergeDeep(layerObject, object);
95
- break;
96
- }
97
- case 'container query block': {
98
- // Handle @container queries
99
- const selector = joinSelectors(pathParts);
100
- const object = { [key]: { [selector]: node } };
101
- containerObject = mergeDeep(containerObject, object);
102
- break;
103
- }
104
- case 'media query or prefix': {
105
- // Handle media queries and prefixes
106
- const selector = joinSelectors(pathParts);
107
- const name = key.replace(/^@\s*/, '');
108
- if (mediaPrefixes[name]) {
109
- // Handle media prefix
110
- const prefix = mediaPrefixes[name];
111
- const rules = selector ? { ['& ' + selector]: node } : node;
112
- const mediaPrefixObject = { [prefix]: rules };
113
- prefixObject = mergeDeep(prefixObject, mediaPrefixObject);
114
- }
115
- else {
116
- // Handle media query
117
- let mediaQuery = key;
118
- if (key.startsWith('@media ')) {
119
- // Use the media query as is, just remove @media prefix
120
- mediaQuery = key.replace(/^@media\s+/, '');
121
- }
122
- else if (mediaQueries[name]) {
123
- // Use the named media query from configuration
124
- mediaQuery = mediaQueries[name];
125
- }
126
- else {
127
- // Unknown media query type
128
- console.warn(`Warning: Media query type ${key} is unknown`);
129
- break;
130
- }
131
- // Store the media query with the selector and node
132
- // This way we collect all the rules for each media query
133
- const mediaQueryKey = '@media ' + mediaQuery;
134
- if (!mediaObject[mediaQueryKey]) {
135
- mediaObject[mediaQueryKey] = {};
136
- }
137
- // Add the selector and its rules to this media query
138
- mediaObject[mediaQueryKey] = mergeDeep(mediaObject[mediaQueryKey], { [selector]: node });
139
- }
140
- break;
141
- }
142
- }
143
- return node;
144
- });
145
- // Convert the main CSS style object to string
146
- let cssString = obj2css(cssStyle);
147
- // Add layer statements if any
148
- if (layerStatements.length > 0) {
149
- cssString = layerStatements.join('\n') + '\n\n' + cssString;
150
- }
151
- // Process and add layer blocks if any
152
- if (Object.keys(layerObject).length > 0) {
153
- const layers = Object.keys(layerObject);
154
- const layerCssString = layers
155
- .map((layer) => {
156
- // Type guard for object values
157
- const layerStyles = layerObject[layer];
158
- if (!isObject(layerStyles))
159
- return '';
160
- const layerContent = getCss(layerStyles, mediaQueries, mediaPrefixes, auto);
161
- return layerContent ? `${layer} {\n${indent(layerContent)}\n}` : '';
162
- })
163
- .filter(Boolean)
164
- .join('\n\n');
165
- if (layerCssString) {
166
- cssString += '\n\n' + layerCssString;
167
- }
168
- }
169
- // Process and add container queries if any
170
- if (Object.keys(containerObject).length > 0) {
171
- const containerQueries = Object.keys(containerObject);
172
- const containerCssString = containerQueries
173
- .map((containerQuery) => {
174
- // Type guard for object values
175
- const containerStyles = containerObject[containerQuery];
176
- if (!isObject(containerStyles))
177
- return '';
178
- const containerContent = getCss(containerStyles, mediaQueries, mediaPrefixes, auto);
179
- return containerContent
180
- ? `${containerQuery} {\n${indent(containerContent)}\n}`
181
- : '';
182
- })
183
- .filter(Boolean)
184
- .join('\n\n');
185
- if (containerCssString) {
186
- cssString += '\n\n' + containerCssString;
187
- }
188
- }
189
- // Process and add media queries if any
190
- if (Object.keys(mediaObject).length > 0) {
191
- const mediaCssString = processMediaQueries(mediaObject, mediaQueries);
192
- if (mediaCssString) {
193
- cssString += '\n\n' + mediaCssString;
194
- }
195
- }
196
- // Process and add media prefixes if any
197
- if (Object.keys(prefixObject).length > 0) {
198
- // First, process the prefix object as normal CSS
199
- const mediaPrefixedCssString = getCss(prefixObject, mediaQueries, mediaPrefixes);
200
- cssString += '\n\n' + mediaPrefixedCssString;
201
- // Handle auto mode if configured
202
- if (auto) {
203
- // Create a modified prefix object for auto mode
204
- const autoPrefixObject = {};
205
- for (const key of Object.keys(auto)) {
206
- const selector = mediaPrefixes[key];
207
- if (!selector || !prefixObject[selector])
208
- continue;
209
- const [autoSelector, mediaQuery] = auto[key];
210
- // Create media query for auto mode
211
- autoPrefixObject[`@media ${mediaQuery}`] = {
212
- [autoSelector]: prefixObject[selector],
213
- };
214
- }
215
- // Process the auto prefix object if not empty
216
- if (Object.keys(autoPrefixObject).length > 0) {
217
- const autoCssString = processMediaQueries(autoPrefixObject, mediaQueries);
218
- if (autoCssString) {
219
- cssString += '\n\n' + autoCssString;
220
- }
221
- }
222
- }
223
- }
224
- // Prettify the final CSS string
225
- return prettifyCss(cssString.replace(/__bs__/g, '\\'));
226
- }
227
- /**
228
- * Deep merge two objects
229
- * @param target - Target object to merge into
230
- * @param source - Source object to merge from
231
- * @returns Merged object
232
- */
233
- function mergeDeep(target, source) {
234
- const output = { ...target };
235
- if (isObject(target) && isObject(source)) {
236
- Object.keys(source).forEach((key) => {
237
- if (isObject(source[key])) {
238
- if (!(key in target)) {
239
- output[key] = source[key];
240
- }
241
- else {
242
- output[key] = mergeDeep(target[key], source[key]);
243
- }
244
- }
245
- else {
246
- output[key] = source[key];
247
- }
248
- });
249
- }
250
- return output;
251
- }
252
- /**
253
- * Checks if value is a non-null object
254
- * @param item - Value to check
255
- * @returns True if the value is a non-null object
256
- */
257
- function isObject(item) {
258
- return item && typeof item === 'object' && !Array.isArray(item);
259
- }
260
- export default getCss;
@@ -1,28 +0,0 @@
1
- /**
2
- * Utility functions for CSS processing
3
- */
4
- /**
5
- * Determines the object type in a more precise way than typeof
6
- * @param obj - Any value to check type
7
- * @returns The lowercase string representing the object type
8
- */
9
- export declare function getObjectType(obj: any): string;
10
- /**
11
- * Checks if a value is a primitive end value (string, number, boolean, null)
12
- * @param value - Value to check
13
- * @returns True if the value is a primitive end value
14
- */
15
- export declare function isEndValue(value: any): boolean;
16
- /**
17
- * Indents a string with spaces
18
- * @param str - String to indent
19
- * @param spaces - Number of spaces to indent with
20
- * @returns Indented string
21
- */
22
- export declare function indent(str: string, spaces?: number): string;
23
- /**
24
- * Converts a JavaScript property name in camelCase to CSS kebab-case
25
- * @param key - Property name in camelCase
26
- * @returns Property name in kebab-case
27
- */
28
- export declare function jsKeyToCssKey(key: string): string;
@@ -1,47 +0,0 @@
1
- /**
2
- * Utility functions for CSS processing
3
- */
4
- /**
5
- * Determines the object type in a more precise way than typeof
6
- * @param obj - Any value to check type
7
- * @returns The lowercase string representing the object type
8
- */
9
- export function getObjectType(obj) {
10
- return (Object.prototype.toString
11
- .call(obj)
12
- .match(/^\[object (\w+)\]$/)?.[1]
13
- .toLowerCase() || 'unknown');
14
- }
15
- /**
16
- * Checks if a value is a primitive end value (string, number, boolean, null)
17
- * @param value - Value to check
18
- * @returns True if the value is a primitive end value
19
- */
20
- export function isEndValue(value) {
21
- return ['string', 'number', 'boolean', 'null'].includes(getObjectType(value));
22
- }
23
- /**
24
- * Indents a string with spaces
25
- * @param str - String to indent
26
- * @param spaces - Number of spaces to indent with
27
- * @returns Indented string
28
- */
29
- export function indent(str, spaces = 2) {
30
- return str
31
- .split('\n')
32
- .map((s) => ' '.repeat(spaces) + s)
33
- .join('\n');
34
- }
35
- /**
36
- * Converts a JavaScript property name in camelCase to CSS kebab-case
37
- * @param key - Property name in camelCase
38
- * @returns Property name in kebab-case
39
- */
40
- export function jsKeyToCssKey(key) {
41
- // Keep vendor prefixes intact
42
- const prefix = key.match(/^[-]+/)?.[0] || '';
43
- const baseKey = key.replace(/^[-]+/, '');
44
- // Convert camelCase to kebab-case
45
- const kebabKey = baseKey.replace(/([A-Z])/g, '-$1').toLowerCase();
46
- return prefix + kebabKey;
47
- }
@@ -1,2 +0,0 @@
1
- import type { IsEndValue } from '../types/index.js';
2
- export declare const isEndValue: IsEndValue;
@@ -1,10 +0,0 @@
1
- export const isEndValue = (value) => {
2
- if (value == null)
3
- return false;
4
- if (typeof value === 'string' || typeof value === 'number')
5
- return true;
6
- if (Array.isArray(value)) {
7
- return value.every((v) => typeof v === 'string' || typeof v === 'number');
8
- }
9
- return false;
10
- };
@@ -1,24 +0,0 @@
1
- /**
2
- * Utilities for handling media queries
3
- */
4
- import { CssStyles, MediaQueries } from '../types/index.js';
5
- /**
6
- * Processes media query objects and converts them to CSS
7
- * @param mediaObject - Object containing media queries and their styles
8
- * @param mediaQueries - Named media query definitions
9
- * @returns CSS string with processed media queries
10
- */
11
- export declare function processMediaQueries(mediaObject: CssStyles, mediaQueries?: MediaQueries): string;
12
- /**
13
- * Checks if a key represents a media query
14
- * @param key - Key to check
15
- * @returns True if the key is a media query
16
- */
17
- export declare function isMediaQuery(key: string): boolean;
18
- /**
19
- * Checks if a key is a named media query that needs to be resolved
20
- * @param key - Key to check
21
- * @param mediaQueries - Named media query definitions
22
- * @returns True if the key is a named media query
23
- */
24
- export declare function isNamedMediaQuery(key: string, mediaQueries: MediaQueries): boolean;
@@ -1,93 +0,0 @@
1
- /**
2
- * Utilities for handling media queries
3
- */
4
- import { indent, jsKeyToCssKey } from './common.js';
5
- import { obj2css } from './obj2css.js';
6
- import { isEndValue } from './common.js';
7
- /**
8
- * Processes media query objects and converts them to CSS
9
- * @param mediaObject - Object containing media queries and their styles
10
- * @param mediaQueries - Named media query definitions
11
- * @returns CSS string with processed media queries
12
- */
13
- export function processMediaQueries(mediaObject, mediaQueries = {}) {
14
- if (!mediaObject || Object.keys(mediaObject).length === 0) {
15
- return '';
16
- }
17
- const mediaQueriesToProcess = Object.keys(mediaObject);
18
- // Process each media query and convert to CSS
19
- const mediaCssStrings = mediaQueriesToProcess.map((queryKey) => {
20
- // Handle named media queries (using @name syntax)
21
- const mediaQueryMatch = queryKey.match(/^@(\w+)$/);
22
- let actualQuery = queryKey;
23
- if (mediaQueryMatch &&
24
- mediaQueryMatch[1] &&
25
- mediaQueries[mediaQueryMatch[1]]) {
26
- // Replace named query with actual query definition
27
- actualQuery = mediaQueries[mediaQueryMatch[1]];
28
- }
29
- else if (queryKey.startsWith('@media ')) {
30
- // Strip @media prefix if present
31
- actualQuery = queryKey.replace(/^@media\s+/, '');
32
- }
33
- // Convert the styles for this media query to CSS
34
- const styles = mediaObject[queryKey];
35
- // Skip if the styles aren't an object
36
- if (isEndValue(styles)) {
37
- return '';
38
- }
39
- // Process the styles to convert camelCase properties to kebab-case
40
- const processedStyles = processStylesForMedia(styles);
41
- const stylesCss = obj2css(processedStyles);
42
- if (!stylesCss.trim()) {
43
- return '';
44
- }
45
- // Wrap the styles in a media query block
46
- return `@media ${actualQuery} {\n${indent(stylesCss)}\n}`;
47
- });
48
- // Join all media query blocks with newlines
49
- return mediaCssStrings.filter((css) => css).join('\n\n');
50
- }
51
- /**
52
- * Processes styles for media queries to ensure camelCase is converted to kebab-case
53
- * @param styles - Style object to process
54
- * @returns Processed style object with converted property names
55
- */
56
- function processStylesForMedia(styles) {
57
- const result = {};
58
- // Process each selector in the styles
59
- Object.keys(styles).forEach((selector) => {
60
- const selectorStyles = styles[selector];
61
- // Skip if not an object
62
- if (isEndValue(selectorStyles)) {
63
- result[selector] = selectorStyles;
64
- return;
65
- }
66
- const processedProps = {};
67
- // Convert each property name to kebab-case
68
- Object.keys(selectorStyles).forEach((prop) => {
69
- const cssKey = jsKeyToCssKey(prop);
70
- processedProps[cssKey] = selectorStyles[prop];
71
- });
72
- result[selector] = processedProps;
73
- });
74
- return result;
75
- }
76
- /**
77
- * Checks if a key represents a media query
78
- * @param key - Key to check
79
- * @returns True if the key is a media query
80
- */
81
- export function isMediaQuery(key) {
82
- return key.startsWith('@media') || key.startsWith('@');
83
- }
84
- /**
85
- * Checks if a key is a named media query that needs to be resolved
86
- * @param key - Key to check
87
- * @param mediaQueries - Named media query definitions
88
- * @returns True if the key is a named media query
89
- */
90
- export function isNamedMediaQuery(key, mediaQueries) {
91
- const match = key.match(/^@(\w+)$/);
92
- return Boolean(match && match[1] && mediaQueries[match[1]]);
93
- }
@@ -1,15 +0,0 @@
1
- /**
2
- * Utilities for converting JavaScript objects to CSS strings
3
- */
4
- /**
5
- * Converts a CSS object to a string representation
6
- * @param cssObject - Object with CSS selectors and properties
7
- * @returns CSS string
8
- */
9
- export declare function obj2css(cssObject: Record<string, any>): string;
10
- /**
11
- * Prettifies a CSS string by ensuring consistent spacing and formatting
12
- * @param cssString - CSS string to prettify
13
- * @returns Prettified CSS string
14
- */
15
- export declare function prettifyCss(cssString: string): string;