Skip to content

Commit

Permalink
feat(styled-system): enhance folder structure for better readability
Browse files Browse the repository at this point in the history
  • Loading branch information
cheton committed Dec 18, 2024
1 parent 8f6de44 commit 9855f90
Show file tree
Hide file tree
Showing 18 changed files with 273 additions and 214 deletions.
3 changes: 3 additions & 0 deletions packages/styled-system/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
"prepublish": "yarn run build",
"test": "jest --maxWorkers=2"
},
"dependencies": {
"ensure-type": "^1.5.1"
},
"devDependencies": {
"@babel/cli": "^7.0.0",
"@babel/core": "^7.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/styled-system/src/config/background.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import system from '../core/system';
import { positiveOrNegative as positiveOrNegativeTransform } from '../utils/transforms';
import positiveOrNegativeTransform from '../transforms/positiveOrNegative';

const group = 'background';
const config = {
Expand Down
2 changes: 1 addition & 1 deletion packages/styled-system/src/config/border.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import system from '../core/system';
import { positiveOrNegative as positiveOrNegativeTransform } from '../utils/transforms';
import positiveOrNegativeTransform from '../transforms/positiveOrNegative';

const _border = {
/**
Expand Down
2 changes: 1 addition & 1 deletion packages/styled-system/src/config/margin.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import system from '../core/system';
import { positiveOrNegative as positiveOrNegativeTransform } from '../utils/transforms';
import positiveOrNegativeTransform from '../transforms/positiveOrNegative';

const group = 'margin';
const config = {
Expand Down
4 changes: 1 addition & 3 deletions packages/styled-system/src/config/outline.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import system from '../core/system';
import {
positiveOrNegative as positiveOrNegativeTransform,
} from '../utils/transforms';
import positiveOrNegativeTransform from '../transforms/positiveOrNegative';

const group = 'outline';
const config = {
Expand Down
2 changes: 1 addition & 1 deletion packages/styled-system/src/config/position.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import system from '../core/system';
import { positiveOrNegative as positiveOrNegativeTransform } from '../utils/transforms';
import positiveOrNegativeTransform from '../transforms/positiveOrNegative';

const group = 'position';
const config = {
Expand Down
2 changes: 1 addition & 1 deletion packages/styled-system/src/config/scroll.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import system from '../core/system';
import { positiveOrNegative as positiveOrNegativeTransform } from '../utils/transforms';
import positiveOrNegativeTransform from '../transforms/positiveOrNegative';

const group = 'scroll';
const config = {
Expand Down
2 changes: 1 addition & 1 deletion packages/styled-system/src/config/shape.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import system from '../core/system';
import { positiveOrNegative as positiveOrNegativeTransform } from '../utils/transforms';
import positiveOrNegativeTransform from '../transforms/positiveOrNegative';

/**
* https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Shapes
Expand Down
2 changes: 1 addition & 1 deletion packages/styled-system/src/config/text.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import system from '../core/system';
import { positiveOrNegative as positiveOrNegativeTransform } from '../utils/transforms';
import positiveOrNegativeTransform from '../transforms/positiveOrNegative';

const group = 'text';
const config = {
Expand Down
4 changes: 2 additions & 2 deletions packages/styled-system/src/core/system.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import ensureArray from '../utils/ensure-array';
import { getter as getterTransform } from '../utils/transforms';
import { ensureArray } from 'ensure-type';
import getterTransform from '../transforms/getter';
import parser from './parser';

const system = (config, options) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/styled-system/src/sx.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ensureArray } from 'ensure-type';
import system from './system';
import ensureArray from './utils/ensure-array';
import get from './utils/get';
import { pseudoClassSelector, pseudoElementSelector } from './pseudo';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getter } from '../transforms';
import getter from '../getter';

describe('getter', () => {
const theme = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import positiveOrNegative from '../positiveOrNegative';

describe('positiveOrNegative', () => {
const theme = {
sizes: {
'1x': '.25rem',
'2x': '.5rem',
'3x': '.75rem',
'4x': '1rem',
},
};

it('should handle positive values', () => {
expect(positiveOrNegative(theme.sizes, '1x')).toBe('.25rem');
expect(positiveOrNegative(theme.sizes, '2x')).toBe('.5rem');
expect(positiveOrNegative(theme.sizes, '3x')).toBe('.75rem');
expect(positiveOrNegative(theme.sizes, '4x')).toBe('1rem');
});

it('should handle negative values', () => {
expect(positiveOrNegative(theme.sizes, '-1x')).toBe('-.25rem');
expect(positiveOrNegative(theme.sizes, '-2x')).toBe('-.5rem');
expect(positiveOrNegative(theme.sizes, '-3x')).toBe('-.75rem');
expect(positiveOrNegative(theme.sizes, '-4x')).toBe('-1rem');
});

it('should return original value when theme.sizes value is not found', () => {
expect(positiveOrNegative(theme.sizes, '5x')).toBe('5x');
expect(positiveOrNegative(theme.sizes, '-5x')).toBe('-5x');
});

it('should handle undefined theme.sizes', () => {
expect(positiveOrNegative(undefined, '2x')).toBe('2x');
expect(positiveOrNegative(undefined, '-2x')).toBe('-2x');
});

it('should handle non-numeric strings', () => {
expect(positiveOrNegative(theme.sizes, 'auto')).toBe('auto');
expect(positiveOrNegative(theme.sizes, '4px')).toBe('4px');
expect(positiveOrNegative(theme.sizes, '-4px')).toBe('-4px');
});
});
93 changes: 93 additions & 0 deletions packages/styled-system/src/transforms/getter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import get from '../utils/get';

/**
* Returns a CSS variable name formatted from the given name and options.
*
* @param {string} name - The name of the variable.
* @param {object} [options] - The options object.
* @param {string} [options.prefix=''] - The prefix to use for the variable name.
* @param {string} [options.delimiter='-'] - The delimiter to use between the prefix and name.
*
* @return {string} The CSS variable name.
*/
const toCSSVariable = (name, options) => {
const {
prefix = '',
delimiter = '-',
} = { ...options };
const variableName = ([prefix, name].filter(Boolean).join(delimiter))
.replace(/\s+/g, delimiter) // replace whitespace characters
.replace(/[^a-zA-Z0-9-_]/g, delimiter) // replace non-alphanumeric, non-hyphen, non-underscore characters
.replace(/^-+|-+$/g, ''); // trim hyphens from beginning and end of string
return `--${variableName}`;
};

const getter = (scale, value, options) => {
let result = get(scale, value);

// Extract the `value` property if the result is an object.
//
// Example usage:
// ```
// <Box color="white.primary" />
// <Box color="black.primary" />
// ```
//
// The `colors` scale in the theme:
// ```js
// {
// colors: {
// white: {
// primary: {
// value: 'rgba(255, 255, 255, .92)',
// },
// secondary: {
// value: 'rgba(255, 255, 255, .60)',
// },
// },
// black: {
// primary: {
// value: 'rgba(0, 0, 0, .92)',
// },
// secondary: {
// value: 'rgba(0, 0, 0, .65)',
// },
// },
// },
// }
// ```
if (typeof result === 'object') {
result = result?.value;
}

if (result === undefined) {
return value; // fallback to value if result is undefined
}

const theme = options?.props?.theme;
// FIXME: `theme.config.prefix` and `theme.__cssVariableMap` are deprecated and will be removed in the next major release
const hasCSSVariables = !!(theme?.cssVariables ?? theme?.__cssVariableMap);
if (hasCSSVariables) {
const cssVariablePrefix = (theme?.cssVariablePrefix) ?? (theme?.config?.prefix);
const cssVariables = (theme?.cssVariables) ?? (theme?.__cssVariableMap);
const contextScale = options?.context?.scale;
const cssVariable = toCSSVariable(
// | contextScale | value |
// | ------------ | --------- |
// | colors | 'blue:50' |
// | space | 0 |
[contextScale, String(value ?? '')].filter(Boolean).join('.'), // => 'colors.blue:50'
{ prefix: cssVariablePrefix, delimiter: '-' },
); // => '--tonic-colors-blue-50'
const cssVariableValue = cssVariables?.[cssVariable]; // => '#578aef'
if (cssVariableValue !== undefined) {
// => Replace '#578aef' with 'var(--tonic-colors-blue-50)'
return String(result ?? '').replaceAll(cssVariableValue, `var(${cssVariable})`);
}
// fallback to the original result
}

return result;
};

export default getter;
123 changes: 123 additions & 0 deletions packages/styled-system/src/transforms/positiveOrNegative.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import getter from './getter';

const hasOwnSafe = (obj, key) => {
if (obj === undefined || obj === null) {
return false;
}

return Object.hasOwn
? Object.hasOwn(obj, key)
: Object.prototype.hasOwnProperty.call(obj, key);
};

// Check if a value is a simple CSS variable
// e.g. var(--tonic-spacing-1)
const isSimpleCSSVariable = (value) => {
const re = /^var\(\s*([a-zA-Z0-9\-_]+)\s*\)$/;
return re.test(String(value ?? '').trim());
};

// Negate the value, handling CSS variables and numeric values
const toNegativeValue = (scale, absoluteValue, options) => {
const theme = options?.props?.theme;
const n = getter(scale, absoluteValue, options);

// Handle CSS variables for negative values
if (!!theme?.cssVariables && isSimpleCSSVariable(n)) {
// https://stackoverflow.com/questions/49469344/using-negative-css-custom-properties
return `calc(0px - ${n})`;
}

// Handle numeric value
if (typeof n === 'number' && Number.isFinite(n)) {
return n * -1;
}

return `-${n}`;
};

const positiveOrNegative = (scale, value, options) => {
/**
* Scale object
*
* ```js
* {
* '1x': '0.25rem',
* '2x': 8,
* }
* ```
*
* Example
*
* ```jsx
* <Box margin="1x" />
* // => margin: 0.25rem
* <Box margin="2x" />
* // => margin: 8px
* <Box margin="-1x" />
* // => margin: -0.25rem
* <Box margin="-2x" />
* // => margin: -8px
* ```
*/
if (typeof value === 'string') {
const absoluteValue = (value.startsWith('+') || value.startsWith('-')) ? value.slice(1) : value;
const isNonNegative = !value.startsWith('-');

// Return the result if the scale object does not contain the absolute value
if (!hasOwnSafe(scale, absoluteValue)) {
return getter(scale, value, options);
}

// Return the result if the value is non-negative
if (isNonNegative) {
return getter(scale, value, options);
}

return toNegativeValue(scale, absoluteValue, options);
}

/**
* Scale object
*
* ```js
* {
* 4: '0.25rem',
* 8: 8,
* }
* ```
*
* Example
*
* ```jsx
* <Box margin={4} />
* // => margin: 0.25rem
* <Box margin={8} />
* // => margin: 8px
* <Box margin={-4} />
* // => margin: -0.25rem
* <Box margin={-8} />
* // => margin: -8px
* ```
*/
if (typeof value === 'number' && Number.isFinite(value)) {
const absoluteValue = Math.abs(value);
const isNonNegative = !(value < 0);

// Return the result if the scale object does not contain the absolute value
if (!hasOwnSafe(scale, absoluteValue)) {
return getter(scale, value, options);
}

// Return the result if the value is non-negative
if (isNonNegative) {
return getter(scale, value, options);
}

return toNegativeValue(scale, absoluteValue, options);
}

return getter(scale, value, options);
};

export default positiveOrNegative;
21 changes: 0 additions & 21 deletions packages/styled-system/src/utils/css-vars.js

This file was deleted.

9 changes: 0 additions & 9 deletions packages/styled-system/src/utils/ensure-array.js

This file was deleted.

Loading

0 comments on commit 9855f90

Please sign in to comment.