-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(styled-system): enhance folder structure for better readability
- Loading branch information
Showing
18 changed files
with
273 additions
and
214 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...em/src/utils/__tests__/transforms.test.js → ...m/src/transforms/__tests__/getter.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
packages/styled-system/src/transforms/__tests__/positiveOrNegative.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
123
packages/styled-system/src/transforms/positiveOrNegative.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.