@stylexjs/shared 0.1.0-beta.7 → 0.2.0-beta.10
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +81 -0
- package/lib/convert-to-className.js +13 -6
- package/lib/expand-shorthands.d.ts +5 -0
- package/lib/expand-shorthands.js +241 -101
- package/lib/generate-css-rule.js +10 -38
- package/lib/index.d.ts +10 -0
- package/lib/index.js.flow +5 -0
- package/lib/messages.js +11 -3
- package/lib/namespace-transforms/__tests__/preflatten.test.js +120 -0
- package/lib/namespace-transforms/preflatten.js +89 -0
- package/lib/physical-rtl/generate-ltr.js +32 -32
- package/lib/physical-rtl/generate-rtl.js +30 -30
- package/lib/preprocess-rules/PreRule.js +101 -0
- package/lib/preprocess-rules/application-order.js +259 -0
- package/lib/preprocess-rules/basic-validation.js +92 -0
- package/lib/preprocess-rules/expand-shorthands.js +156 -0
- package/lib/preprocess-rules/flatten-raw-style-obj.js +148 -0
- package/lib/preprocess-rules/index.js +39 -0
- package/lib/preprocess-rules/legacy-expand-shorthands.js +219 -0
- package/lib/preprocess-rules/null-out-longhand.js +310 -0
- package/lib/preprocess-rules/property-specificity.js +135 -0
- package/lib/preprocess-rules/react-native-web.js +142 -0
- package/lib/stylex-create.js +30 -101
- package/lib/stylex-defaultValue.js +230 -98
- package/lib/stylex-keyframes.js +23 -10
- package/lib/utils/Rule.js +71 -0
- package/lib/utils/default-options.js +34 -0
- package/lib/utils/genCSSRule.js +9 -8
- package/lib/utils/normalize-value.js +3 -0
- package/lib/utils/object-utils.js +23 -2
- package/lib/utils/property-priorities.js +116 -0
- package/lib/utils/split-css-value.js +47 -0
- package/lib/validate.js +1 -1
- package/package.json +1 -1
package/README.md
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# @stylexjs/shared
|
2
|
+
|
3
|
+
This package contains most of the core JavaScript logic for stylex.
|
4
|
+
|
5
|
+
It exports two primary functions `create` and `keyframes`.
|
6
|
+
|
7
|
+
1. `create` - takes a map of style rules. The return value include: a) the map with each style value replaced by a unique, reproducible, hashed className string, and b) a list of the CSS styles to be inserted into the document.
|
8
|
+
2. `keyframes` - takes a `@keyframes` animation as JS object. Returns a hashed string and the style ot be injected.
|
9
|
+
|
10
|
+
#### ⭐️ `create`
|
11
|
+
|
12
|
+
The `stylex.create` function is implemented here and can be found within `stylex-create.js` and is the default export of a function named `styleXCreateSet(...)`.
|
13
|
+
|
14
|
+
##### `styleXCreateSet(...)`
|
15
|
+
|
16
|
+
> The function is called `styleXCreateSet` because `stylex.create` transforms a "set" or collection of multiple style [namespaces](#namespace)
|
17
|
+
|
18
|
+
This function itself mostly just traverses over the objects to run each [namespaces](#namespace) through the `styleXCreateNamespace(...)` function. Other than that, it takes the styles to be injected from each namespace in a [Namespace Set](#namespace-set) and deduplicates them so the style isn't injected multiple times if it's used within multiple Namespaces in the same set.
|
19
|
+
|
20
|
+
##### `styleXCreateNamespace(...)`
|
21
|
+
|
22
|
+
> This function has been kept separate in case we want to add a new function to the StyleX API in the future called `stylex.createOne` which transforms a single [namespace](#namespace) instead of a [Namespace Set](#namespace-set)
|
23
|
+
|
24
|
+
This function is responsible to transforming a [namespace](#namespace) to a [Compiled Namespace](#compiled-namespace) by hashing each key value pair and returning an object where the values have been replaced by classNames.
|
25
|
+
|
26
|
+
**Step 1**
|
27
|
+
|
28
|
+
The first step here is expanding all [shorthands](#shorthands) into their individual properties. To do this we `.flatMap` over the object entries of the Namespace and use the `expandShorthands(...)` function defined within `expand-shorthands.js`
|
29
|
+
|
30
|
+
**Step 2**
|
31
|
+
|
32
|
+
We hash each style `[key, value]` pair and generate a className and an associated CSS rule. Thie is done in the `convertToClassName(...)` function defined within [`convert-to-className.js`](#convert-to-classname-shared-package). (Explained below)
|
33
|
+
|
34
|
+
**Step 3**
|
35
|
+
|
36
|
+
Using the classNames generated in _step 2_ above, we collect all the individual style keys along with their associated classNames in the `resolvedNamespace` object.
|
37
|
+
|
38
|
+
All the generated CSS rules from _step 2_ are collected in the `injectedStyles` object.
|
39
|
+
|
40
|
+
The `[resolvedNamespace, injectedStyles]` is returned.
|
41
|
+
|
42
|
+
##### Back to `styleXCreateSet(...)`
|
43
|
+
|
44
|
+
`styleXCreateSet(...)` takes all the `[resolvedNamespace, finalInjectedStyles]` tuples and returns a tuple of `[compiledNamespaceSet, allInjectedStyles]`
|
45
|
+
|
46
|
+
### Back to `create` with the `@stylexjs/babel-plugin` package
|
47
|
+
|
48
|
+
The `create` function within the babel plugin package takes the `stylex.create(...)` function call and replaces it with the `compiledNamespaceSet`.
|
49
|
+
|
50
|
+
It also takes each of the `injectedStyles` and:
|
51
|
+
|
52
|
+
1. Either injects it as a `stylex.inject` call (if in `dev` mode)
|
53
|
+
2. Or, adds it to the array of injected styles on [`babel.state.metadata`](#babel-metadata)
|
54
|
+
|
55
|
+
#### ⭐️ `keyframes`
|
56
|
+
|
57
|
+
This is the function backing `stylex.keyframes`. It works similarly to `create` but it's more simplified since it only defines a single CSS `@keyframes` rule and returns a single string.
|
58
|
+
|
59
|
+
Here again, the source AST is converted to a JS object and passed to `stylex-keyframes.js` within the `shared` package.
|
60
|
+
|
61
|
+
There, first the shorthands are expanded and then the whole objects is hashed. The resulting hash is used as the generated `animation name` for a `@keyframes` rule.
|
62
|
+
|
63
|
+
The "name" and the CSS `@keyframes` rules are returned as a tuple.
|
64
|
+
|
65
|
+
The `stylex.keyframes` call is replaced with the final string.
|
66
|
+
|
67
|
+
The CSS `@keyframes` rule is either injected using `stylex.inject` in dev mode or set onto the `stylex` array on [`babel.state.metadata`](#babel-metadata).
|
68
|
+
|
69
|
+
#### `convert-to-className` (`shared` package)
|
70
|
+
|
71
|
+
This function is responsible for converting a single style key-value pair into a tuple of `[key, className, CSSRules]`
|
72
|
+
|
73
|
+
It does so in the following steps:
|
74
|
+
|
75
|
+
1. Convert the camelCased keys that are used by end-users to define [Namespaces](#namespace) and convert them to the dash-separated keys used within CSS.
|
76
|
+
2. Hash `key` + (any `pseudo` or `at-rule`) + `value` to generate a className
|
77
|
+
3. Generate the CSS rule using the `generateCSSRule` function defined in [`generate-css-rule.js`](#generate-css-rulejs) in the `shared` package.
|
78
|
+
|
79
|
+
#### `generate-css-rule.js`
|
80
|
+
|
81
|
+
This function takes a CSS key value pair, checks if has an RTL counterpart and returns them along side a pre-configured priority based on the type of CSS rule it is.
|
@@ -3,11 +3,13 @@
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
4
4
|
value: true
|
5
5
|
});
|
6
|
-
exports.
|
6
|
+
exports.convertStyleToClassName = convertStyleToClassName;
|
7
7
|
var _hash = _interopRequireDefault(require("./hash"));
|
8
8
|
var _dashify = _interopRequireDefault(require("./utils/dashify"));
|
9
9
|
var _transformValue = _interopRequireDefault(require("./transform-value"));
|
10
|
-
var _generateCssRule =
|
10
|
+
var _generateCssRule = require("./generate-css-rule");
|
11
|
+
var _defaultOptions = require("./utils/default-options");
|
12
|
+
var _objectUtils = require("./utils/object-utils");
|
11
13
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
12
14
|
/**
|
13
15
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
@@ -25,16 +27,21 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
25
27
|
// Handles RTL-flipping
|
26
28
|
// Hashes to get a className
|
27
29
|
// Returns the final key, className a CSS Rule
|
28
|
-
function
|
30
|
+
function convertStyleToClassName(objEntry, pseudos, atRules) {
|
29
31
|
let {
|
30
32
|
stylexSheetName = '<>',
|
31
33
|
classNamePrefix = 'x'
|
32
|
-
} = arguments.length >
|
34
|
+
} = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : _defaultOptions.defaultOptions;
|
33
35
|
const [key, rawValue] = objEntry;
|
34
36
|
const dashedKey = (0, _dashify.default)(key);
|
35
37
|
const value = Array.isArray(rawValue) ? rawValue.map(eachValue => (0, _transformValue.default)(key, eachValue)) : (0, _transformValue.default)(key, rawValue);
|
36
|
-
const
|
38
|
+
const sortedPseudos = (0, _objectUtils.arraySort)(pseudos ?? []);
|
39
|
+
const sortedAtRules = (0, _objectUtils.arraySort)(atRules ?? []);
|
40
|
+
const atRuleHashString = sortedPseudos.join('');
|
41
|
+
const pseudoHashString = sortedAtRules.join('');
|
42
|
+
const modifierHashString = atRuleHashString + pseudoHashString || 'null';
|
43
|
+
const stringToHash = Array.isArray(value) ? dashedKey + value.join(', ') + modifierHashString : dashedKey + value + modifierHashString;
|
37
44
|
const className = classNamePrefix + (0, _hash.default)(stylexSheetName + stringToHash);
|
38
|
-
const cssRules = (0, _generateCssRule.
|
45
|
+
const cssRules = (0, _generateCssRule.generateRule)(className, dashedKey, value, pseudos, atRules);
|
39
46
|
return [key, className, cssRules];
|
40
47
|
}
|
package/lib/expand-shorthands.js
CHANGED
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
5
5
|
});
|
6
6
|
exports.default = flatMapExpandedShorthands;
|
7
|
+
exports.expandedKeys = void 0;
|
7
8
|
var _postcssValueParser = _interopRequireDefault(require("postcss-value-parser"));
|
8
9
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
9
10
|
/**
|
@@ -40,143 +41,282 @@ function splitValue(str) {
|
|
40
41
|
return nodes;
|
41
42
|
}
|
42
43
|
|
43
|
-
// TODO: to be added later.
|
44
|
-
// const aliases = {
|
45
|
-
// marginInlineStart: (rawValue) => [['marginStart', rawValue]],
|
46
|
-
// marginInlineEnd: (rawValue) => [['marginEnd', rawValue]],
|
47
|
-
// marginInline: (rawValue) => [
|
48
|
-
// ['marginStart', rawValue],
|
49
|
-
// ['marginEnd', rawValue],
|
50
|
-
// ],
|
51
|
-
// paddingInlineStart: (rawValue) => [['paddingStart', rawValue]],
|
52
|
-
// paddingInlineEnd: (rawValue) => [['paddingEnd', rawValue]],
|
53
|
-
// paddingInline: (rawValue) => [
|
54
|
-
// ['paddingStart', rawValue],
|
55
|
-
// ['paddingEnd', rawValue],
|
56
|
-
// ],
|
57
|
-
// // 'borderInlineStart': (rawValue) => [['borderStart', rawValue]],
|
58
|
-
// // 'borderInlineEnd': (rawValue) => [['borderEnd', rawValue]],
|
59
|
-
// // // This will need to change.
|
60
|
-
// // 'borderInline': (rawValue) => [
|
61
|
-
// // ['borderStart', rawValue],
|
62
|
-
// // ['borderEnd', rawValue],
|
63
|
-
// // ],
|
64
|
-
// };
|
65
|
-
|
66
44
|
/**
|
67
45
|
* Shorthand properties:
|
68
46
|
* - [x] all - Should be banned
|
69
|
-
* - [
|
70
|
-
* - [
|
71
|
-
* - [
|
47
|
+
* - [x] animation
|
48
|
+
* - [x] background
|
49
|
+
* - [x] border
|
72
50
|
* - [x] border-block-end
|
73
51
|
* - [x] border-block-start
|
74
|
-
* - [
|
52
|
+
* - [x] border-bottom
|
75
53
|
* - [x] border-color
|
76
54
|
* - [x] border-image
|
77
55
|
* - [x] border-inline-end
|
78
56
|
* - [x] border-inline-start
|
79
|
-
* - [
|
57
|
+
* - [x] border-left
|
80
58
|
* - [x] border-radius
|
81
|
-
* - [
|
59
|
+
* - [x] border-right
|
82
60
|
* - [x] border-style
|
83
|
-
* - [
|
61
|
+
* - [x] border-top
|
84
62
|
* - [x] border-width
|
85
|
-
* - [
|
86
|
-
* - [
|
87
|
-
* - [
|
88
|
-
* - [
|
89
|
-
* - [
|
90
|
-
* - [
|
91
|
-
* - [
|
92
|
-
* - [
|
93
|
-
* - [
|
94
|
-
* - [
|
95
|
-
* - [
|
96
|
-
* - [
|
63
|
+
* - [x] column-rule
|
64
|
+
* - [x] columns
|
65
|
+
* - [x] container
|
66
|
+
* - [x] flex
|
67
|
+
* - [x] flex-flow
|
68
|
+
* - [x] font
|
69
|
+
* - [x] gap
|
70
|
+
* - [x] grid
|
71
|
+
* - [x] grid-area
|
72
|
+
* - [x] grid-column
|
73
|
+
* - [x] grid-row
|
74
|
+
* - [x] grid-template
|
75
|
+
* - [x] inset
|
76
|
+
* - [x] inset-block
|
77
|
+
* - [x] inset-inline
|
78
|
+
* - [x] list-style
|
97
79
|
* - [x] margin
|
98
|
-
* - [
|
99
|
-
* - [
|
100
|
-
* - [
|
80
|
+
* - [x] mask
|
81
|
+
* - [x] offset
|
82
|
+
* - [x] outline
|
101
83
|
* - [x] overflow
|
102
84
|
* - [x] padding
|
103
|
-
* - [
|
104
|
-
* - [
|
105
|
-
* - [
|
106
|
-
* - [
|
107
|
-
* - [
|
108
|
-
* - [
|
109
|
-
* - [
|
110
|
-
* - [
|
85
|
+
* - [x] place-content
|
86
|
+
* - [x] place-items
|
87
|
+
* - [x] place-self
|
88
|
+
* - [x] scroll-margin
|
89
|
+
* - [x] scroll-padding
|
90
|
+
* - [x] text-decoration
|
91
|
+
* - [x] text-emphasis
|
92
|
+
* - [x] transition
|
111
93
|
*/
|
112
94
|
|
113
|
-
const
|
114
|
-
|
95
|
+
const shorthands = {
|
96
|
+
all: _ => {
|
97
|
+
throw new Error('all is not supported');
|
98
|
+
},
|
99
|
+
animation: value => [['animation', value], ['animationName', null], ['animationDuration', null], ['animationTimingFunction', null], ['animationDelay', null], ['animationIterationCount', null], ['animationDirection', null], ['animationFillMode', null], ['animationPlayState', null]],
|
100
|
+
background: value => [['background', value], ['backgroundAttachment', null], ['backgroundClip', null], ['backgroundColor', null], ['backgroundImage', null], ['backgroundOrigin', null], ['backgroundPosition', null], ['backgroundRepeat', null], ['backgroundSize', null]],
|
101
|
+
// These will be removed later, matching the properties with React Native.
|
102
|
+
// For now, we're compiling them to the React Native properties.
|
103
|
+
// @Deprecated
|
115
104
|
border: rawValue => {
|
116
|
-
|
105
|
+
if (typeof rawValue === 'number') {
|
106
|
+
return shorthands.borderWidth(rawValue);
|
107
|
+
}
|
108
|
+
const [width, style, color] = splitValue(rawValue);
|
109
|
+
return [...shorthands.borderWidth(width), ...shorthands.borderStyle(style), ...shorthands.borderColor(color)];
|
117
110
|
},
|
118
|
-
|
119
|
-
|
120
|
-
border: (rawValue: string) => {
|
111
|
+
// @Deprecated
|
112
|
+
borderInline: rawValue => {
|
121
113
|
if (typeof rawValue === 'number') {
|
122
|
-
return
|
114
|
+
return [['borderInlineWidth', rawValue], ['borderInlineStartWidth', null], ['borderInlineEndWidth', null]];
|
123
115
|
}
|
124
116
|
const [width, style, color] = splitValue(rawValue);
|
125
|
-
return [
|
126
|
-
...expansions.borderWidth(width),
|
127
|
-
...expansions.borderStyle(style),
|
128
|
-
...expansions.borderColor(color),
|
129
|
-
];
|
130
|
-
}
|
131
|
-
*/
|
132
|
-
borderColor: rawValue => {
|
133
|
-
const [top, right = top, bottom = top, left = right] = splitValue(rawValue);
|
134
|
-
return [['borderTopColor', top], ['borderEndColor', right], ['borderBottomColor', bottom], ['borderStartColor', left]];
|
117
|
+
return [...shorthands.borderInlineWidth(width), ...shorthands.borderInlineStyle(style), ...shorthands.borderInlineColor(color)];
|
135
118
|
},
|
136
|
-
|
137
|
-
|
119
|
+
// @Deprecated
|
120
|
+
borderBlock: rawValue => {
|
121
|
+
if (typeof rawValue === 'number') {
|
122
|
+
return [['borderBlockWidth', rawValue], ['borderTopWidth', null], ['borderBottomWidth', null]];
|
123
|
+
}
|
124
|
+
const [width, style, color] = splitValue(rawValue);
|
125
|
+
return [...shorthands.borderBlockWidth(width), ...shorthands.borderBlockStyle(style), ...shorthands.borderBlockColor(color)];
|
138
126
|
},
|
139
|
-
|
140
|
-
|
141
|
-
|
127
|
+
// @Deprecated
|
128
|
+
borderTop: rawValue => {
|
129
|
+
if (typeof rawValue === 'number') {
|
130
|
+
return [['borderTopWidth', rawValue]];
|
131
|
+
}
|
132
|
+
const [width, style, color] = splitValue(rawValue);
|
133
|
+
return [['borderTopWidth', width], ['borderTopStyle', style], ['borderTopColor', color]];
|
142
134
|
},
|
143
|
-
|
144
|
-
|
135
|
+
// @Deprecated
|
136
|
+
borderInlineEnd: rawValue => {
|
137
|
+
if (typeof rawValue === 'number') {
|
138
|
+
return [['borderInlineEndWidth', rawValue]];
|
139
|
+
}
|
140
|
+
const [width, style, color] = splitValue(rawValue);
|
141
|
+
return [['borderInlineEndWidth', width], ['borderInlineEndStyle', style], ['borderInlineEndColor', color]];
|
145
142
|
},
|
146
|
-
|
147
|
-
|
148
|
-
|
143
|
+
// @Deprecated
|
144
|
+
borderRight: rawValue => {
|
145
|
+
throw new Error(['`borderRight` is not supported.', 'You could use `borderRightWidth`, `borderRightStyle` and `borderRightColor`,', 'but it is preferable to use `borderInlineEndWidth`, `borderInlineEndStyle` and `borderInlineEndColor`.'].join(' '));
|
149
146
|
},
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
147
|
+
// @Deprecated
|
148
|
+
borderBottom: rawValue => {
|
149
|
+
if (typeof rawValue === 'number') {
|
150
|
+
return [['borderBottomWidth', rawValue]];
|
151
|
+
}
|
152
|
+
const [width, style, color] = splitValue(rawValue);
|
153
|
+
return [['borderBottomWidth', width], ['borderBottomStyle', style], ['borderBottomColor', color]];
|
154
154
|
},
|
155
|
-
|
156
|
-
|
157
|
-
|
155
|
+
// @Deprecated
|
156
|
+
borderInlineStart: rawValue => {
|
157
|
+
if (typeof rawValue === 'number') {
|
158
|
+
return [['borderInlineStartWidth', rawValue]];
|
159
|
+
}
|
160
|
+
const [width, style, color] = splitValue(rawValue);
|
161
|
+
return [['borderInlineStartWidth', width], ['borderInlineStartStyle', style], ['borderInlineStartColor', color]];
|
158
162
|
},
|
159
|
-
|
160
|
-
|
163
|
+
// @Deprecated
|
164
|
+
borderLeft: rawValue => {
|
165
|
+
throw new Error(['`borderLeft` is not supported.', 'You could use `borderLeftWidth`, `borderLeftStyle` and `borderLeftColor`,', 'but it is preferable to use `borderInlineStartWidth`, `borderInlineStartStyle` and `borderInlineStartColor`.'].join(' '));
|
161
166
|
},
|
162
|
-
|
163
|
-
|
167
|
+
borderInlineWidth: rawValue => [['borderInlineWidth', rawValue], ['borderInlineStartWidth', null], ['borderLeftWidth', null], ['borderInlineEndWidth', null], ['borderRightWidth', null]],
|
168
|
+
borderInlineStyle: rawValue => [['borderInlineStyle', rawValue], ['borderInlineStartStyle', null], ['borderLeftStyle', null], ['borderInlineEndStyle', null], ['borderRightStyle', null]],
|
169
|
+
borderInlineColor: rawValue => [['borderInlineColor', rawValue], ['borderInlineStartColor', null], ['borderLeftColor', null], ['borderInlineEndColor', null], ['borderRightColor', null]],
|
170
|
+
borderBlockWidth: rawValue => [['borderBlockWidth', rawValue], ['borderTopWidth', null], ['borderBottomWidth', null]],
|
171
|
+
borderBlockStyle: rawValue => [['borderBlockStyle', rawValue], ['borderTopStyle', null], ['borderBottomStyle', null]],
|
172
|
+
borderBlockColor: rawValue => [['borderBlockColor', rawValue], ['borderTopColor', null], ['borderBottomColor', null]],
|
173
|
+
borderColor: value => [['borderColor', value], ['borderTopColor', null], ['borderInlineEndColor', null], ['borderRightColor', null], ['borderBottomColor', null], ['borderInlineStartColor', null], ['borderLeftColor', null]],
|
174
|
+
borderStyle: value => [['borderStyle', value], ['borderTopStyle', null], ['borderInlineEndStyle', null], ['borderRightStyle', null], ['borderBottomStyle', null], ['borderInlineStartStyle', null], ['borderLeftStyle', null]],
|
175
|
+
borderWidth: value => [['borderWidth', value], ['borderTopWidth', null], ['borderInlineEndWidth', null], ['borderRightWidth', null], ['borderBottomWidth', null], ['borderInlineStartWidth', null], ['borderLeftWidth', null]],
|
176
|
+
borderRadius: value => {
|
177
|
+
const values = typeof value === 'number' ? [value] : splitValue(value);
|
178
|
+
if (values.length === 1) {
|
179
|
+
return [['borderRadius', value],
|
180
|
+
// // logical constituents
|
181
|
+
['borderStartStartRadius', null], ['borderStartEndRadius', null], ['borderEndStartRadius', null], ['borderEndEndRadius', null],
|
182
|
+
// physical constituents
|
183
|
+
['borderTopLeftRadius', null], ['borderTopRightRadius', null], ['borderBottomLeftRadius', null], ['borderBottomRightRadius', null]];
|
184
|
+
}
|
185
|
+
|
186
|
+
// @Deprecated
|
187
|
+
const [startStart, startEnd = startStart, endEnd = startStart, endStart = startEnd] = values;
|
188
|
+
return [
|
189
|
+
// split into logical consituents
|
190
|
+
['borderStartStartRadius', startStart], ['borderStartEndRadius', startEnd], ['borderEndEndRadius', endEnd], ['borderEndStartRadius', endStart],
|
191
|
+
// unset physical consituents
|
192
|
+
['borderTopLeftRadius', null], ['borderTopRightRadius', null], ['borderBottomLeftRadius', null], ['borderBottomRightRadius', null]];
|
164
193
|
},
|
165
|
-
|
166
|
-
|
167
|
-
|
194
|
+
columnRule: value => [['columnRule', value], ['columnRuleWidth', null], ['columnRuleStyle', null], ['columnRuleColor', null]],
|
195
|
+
columns: value => [['columns', value], ['columnCount', null], ['columnWidth', null]],
|
196
|
+
container: value => [['container', value], ['containerName', null], ['containerType', null]],
|
197
|
+
flex: value => [['flex', value], ['flexGrow', null], ['flexShrink', null], ['flexBasis', null]],
|
198
|
+
flexFlow: value => [['flexFlow', value], ['flexDirection', null], ['flexWrap', null]],
|
199
|
+
// @Deprecated ?
|
200
|
+
font: value => [['font', value], ['fontFamily', null], ['fontSize', null], ['fontStretch', null], ['fontStyle', null], ['fontVariant', null], ['fontWeight', null], ['lineHeight', null]],
|
201
|
+
gap: value => [['gap', value], ['rowGap', null], ['columnGap', null]],
|
202
|
+
grid: value => [['grid', value], ['gridTemplate', null], ['gridTemplateAreas', null], ['gridTemplateColumns', null], ['gridTemplateRows', null], ['gridAutoRows', null], ['gridAutoColumns', null], ['gridAutoFlow', null]
|
203
|
+
|
204
|
+
// This is for grid items only
|
205
|
+
// Not a constituent of `grid`
|
206
|
+
// ['gridRow', null],
|
207
|
+
// ['gridRowStart', null],
|
208
|
+
// ['gridRowEnd', null],
|
209
|
+
// ['gridColumn', null],
|
210
|
+
// ['gridColumnStart', null],
|
211
|
+
// ['gridColumnEnd', null],
|
212
|
+
// ['gridArea', null],
|
213
|
+
],
|
214
|
+
|
215
|
+
gridArea: value => [['gridArea', value], ['gridRow', null], ['gridRowStart', null], ['gridRowEnd', null], ['gridColumn', null], ['gridColumnStart', null], ['gridColumnEnd', null]],
|
216
|
+
gridRow: value => [['gridRow', value], ['gridRowStart', null], ['gridRowEnd', null]],
|
217
|
+
gridColumn: value => [['gridColumn', value], ['gridColumnStart', null], ['gridColumnEnd', null]],
|
218
|
+
gridTemplate: value => [['gridTemplate', value], ['gridTemplateAreas', null], ['gridTemplateColumns', null], ['gridTemplateRows', null]],
|
219
|
+
inset: value => [['inset', value], ['insetInline', null], ['insetBlock', null], ['insetInlineStart', null], ['insetInlineEnd', null], ['top', null], ['right', null], ['bottom', null], ['left', null]],
|
220
|
+
insetInline: value => [['insetInline', value], ['insetInlineStart', null], ['insetInlineEnd', null], ['left', null], ['right', null]],
|
221
|
+
insetBlock: value => [['insetBlock', value], ['top', null], ['bottom', null]],
|
222
|
+
listStyle: value => [['listStyle', value], ['listStyleImage', null], ['listStylePosition', null], ['listStyleType', null]],
|
223
|
+
margin: value => {
|
224
|
+
const values = typeof value === 'number' ? [value] : splitValue(value);
|
225
|
+
if (values.length === 1) {
|
226
|
+
return [['margin', values[0]], ['marginInlineStart', null], ['marginLeft', null], ['marginInlineEnd', null], ['marginRight', null], ['marginTop', null], ['marginBottom', null]];
|
227
|
+
}
|
228
|
+
// @Deprecated
|
229
|
+
const [top, right = top, bottom = top, left = right] = values;
|
230
|
+
return [['marginTop', top], ['marginInlineEnd', right], ['marginBottom', bottom], ['marginInlineStart', left], ['marginLeft', null], ['marginRight', null]];
|
168
231
|
},
|
232
|
+
marginInline: value => [['marginInline', value], ['marginInlineStart', null], ['marginLeft', null], ['marginInlineEnd', null], ['marginRight', null]],
|
233
|
+
marginBlock: value => [['marginBlock', value], ['marginTop', null], ['marginBottom', null]],
|
234
|
+
mask: value => [['mask', value], ['maskClip', null], ['maskComposite', null], ['maskImage', null], ['maskMode', null], ['maskOrigin', null], ['maskPosition', null], ['maskRepeat', null], ['maskSize', null]],
|
235
|
+
offset: value => [['offset', value], ['offsetAnchor', null], ['offsetDistance', null], ['offsetPath', null], ['offsetPosition', null], ['offsetRotate', null]],
|
236
|
+
outline: value => [['outline', value], ['outlineColor', null], ['outlineStyle', null], ['outlineWidth', null]],
|
237
|
+
overflow: value => [['overflow', value], ['overflowX', null], ['overflowY', null]],
|
169
238
|
padding: rawValue => {
|
170
|
-
const
|
239
|
+
const values = typeof rawValue === 'number' ? [rawValue] : splitValue(rawValue);
|
240
|
+
if (values.length === 1) {
|
241
|
+
return [['padding', values[0]], ['paddingStart', null], ['paddingLeft', null], ['paddingEnd', null], ['paddingRight', null], ['paddingTop', null], ['paddingBottom', null]];
|
242
|
+
}
|
243
|
+
// @Deprecated
|
244
|
+
const [top, right = top, bottom = top, left = right] = values;
|
171
245
|
return [['paddingTop', top], ['paddingEnd', right], ['paddingBottom', bottom], ['paddingStart', left]];
|
172
246
|
},
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
247
|
+
paddingInline: rawValue => [['paddingInline', rawValue], ['paddingStart', null], ['paddingLeft', null], ['paddingEnd', null], ['paddingRight', null]],
|
248
|
+
paddingBlock: rawValue => [['paddingBlock', rawValue], ['paddingTop', null], ['paddingBottom', null]],
|
249
|
+
placeContent: value => [['placeContent', value], ['alignContent', null], ['justifyContent', null]],
|
250
|
+
placeItems: value => [['placeItems', value], ['alignItems', null], ['justifyItems', null]],
|
251
|
+
placeSelf: value => [['placeSelf', value], ['alignSelf', null], ['justifySelf', null]],
|
252
|
+
scrollMargin: value => [['scrollMargin', value], ['scrollMarginBottom', null], ['scrollMarginLeft', null], ['scrollMarginStart', null], ['scrollMarginRight', null], ['scrollMarginEnd', null], ['scrollMarginTop', null]],
|
253
|
+
scrollPadding: value => [['scrollPadding', value], ['scrollPaddingBottom', null], ['scrollPaddingLeft', null], ['scrollPaddingStart', null], ['scrollPaddingRight', null], ['scrollPaddingEnd', null], ['scrollPaddingTop', null]],
|
254
|
+
scrollTimeline: value => [['scrollTimeline', value], ['scrollTimelineName', null], ['scrollTimelineAxis', null]],
|
255
|
+
textDecoration: value => [['textDecoration', value], ['textDecorationColor', null], ['textDecorationLine', null], ['textDecorationStyle', null], ['textDecorationThickness', null]],
|
256
|
+
textEmphasis: value => [['textEmphasis', value], ['textEmphasisColor', null], ['textEmphasisStyle', null]],
|
257
|
+
transition: value => [['transition', value], ['transitionDelay', null], ['transitionDuration', null], ['transitionProperty', null], ['transitionTimingFunction', null]]
|
179
258
|
};
|
259
|
+
const aliases = {
|
260
|
+
// @Deprecated
|
261
|
+
borderHorizontal: shorthands.borderInline,
|
262
|
+
// @Deprecated
|
263
|
+
borderVertical: shorthands.borderBlock,
|
264
|
+
// @Deprecated
|
265
|
+
borderBlockStart: shorthands.borderTop,
|
266
|
+
// @Deprecated
|
267
|
+
borderEnd: shorthands.borderInlineEnd,
|
268
|
+
// @Deprecated
|
269
|
+
borderBlockEnd: shorthands.borderBottom,
|
270
|
+
// @Deprecated
|
271
|
+
borderStart: shorthands.borderInlineStart,
|
272
|
+
borderHorizontalWidth: shorthands.borderInlineWidth,
|
273
|
+
borderHorizontalStyle: shorthands.borderInlineStyle,
|
274
|
+
borderHorizontalColor: shorthands.borderInlineColor,
|
275
|
+
borderVerticalWidth: shorthands.borderBlockWidth,
|
276
|
+
borderVerticalStyle: shorthands.borderBlockStyle,
|
277
|
+
borderVerticalColor: shorthands.borderBlockColor,
|
278
|
+
borderBlockStartColor: value => [['borderTopColor', value]],
|
279
|
+
borderBlockEndColor: value => [['borderBottomColor', value]],
|
280
|
+
borderStartColor: value => [['borderInlineStartColor', value]],
|
281
|
+
borderEndColor: value => [['borderInlineEndColor', value]],
|
282
|
+
borderBlockStartStyle: value => [['borderTopStyle', value]],
|
283
|
+
borderBlockEndStyle: value => [['borderBottomStyle', value]],
|
284
|
+
borderStartStyle: value => [['borderInlineStartStyle', value]],
|
285
|
+
borderEndStyle: value => [['borderInlineEndStyle', value]],
|
286
|
+
borderBlockStartWidth: value => [['borderTopWidth', value]],
|
287
|
+
borderBlockEndWidth: value => [['borderBottomWidth', value]],
|
288
|
+
borderStartWidth: value => [['borderInlineStartWidth', value]],
|
289
|
+
borderEndWidth: value => [['borderInlineEndWidth', value]],
|
290
|
+
borderTopStartRadius: value => [['borderStartStartRadius', value]],
|
291
|
+
borderTopEndRadius: value => [['borderStartEndRadius', value]],
|
292
|
+
borderBottomStartRadius: value => [['borderEndStartRadius', value]],
|
293
|
+
borderBottomEndRadius: value => [['borderEndEndRadius', value]],
|
294
|
+
marginBlockStart: value => [['marginTop', value]],
|
295
|
+
marginBlockEnd: value => [['marginBottom', value]],
|
296
|
+
marginStart: value => [['marginInlineStart', value]],
|
297
|
+
marginEnd: value => [['marginInlineEnd', value]],
|
298
|
+
marginHorizontal: shorthands.marginInline,
|
299
|
+
marginVertical: shorthands.marginBlock,
|
300
|
+
paddingBlockStart: rawValue => [['paddingTop', rawValue]],
|
301
|
+
paddingBlockEnd: rawValue => [['paddingBottom', rawValue]],
|
302
|
+
paddingStart: rawValue => [['paddingInlinStart', rawValue]],
|
303
|
+
paddingEnd: rawValue => [['paddingInlineEnd', rawValue]],
|
304
|
+
paddingHorizontal: shorthands.paddingInline,
|
305
|
+
paddingVertical: shorthands.paddingBlock,
|
306
|
+
insetBlockStart: value => [['top', value]],
|
307
|
+
insetBlockEnd: value => [['bottom', value]],
|
308
|
+
start: value => [['insetInlineStart', value]],
|
309
|
+
end: value => [['insetInlineEnd', value]]
|
310
|
+
};
|
311
|
+
const expansions = {
|
312
|
+
...shorthands,
|
313
|
+
...aliases
|
314
|
+
};
|
315
|
+
|
316
|
+
// TODO: It should be possible to remove this as we should no longer have
|
317
|
+
// to disallow shorthand properties with object values.
|
318
|
+
const expandedKeys = Object.keys(expansions);
|
319
|
+
exports.expandedKeys = expandedKeys;
|
180
320
|
function flatMapExpandedShorthands(objEntry) {
|
181
321
|
const [key, value] = objEntry;
|
182
322
|
const expansion = expansions[key];
|
package/lib/generate-css-rule.js
CHANGED
@@ -3,10 +3,11 @@
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
4
4
|
value: true
|
5
5
|
});
|
6
|
-
exports.
|
6
|
+
exports.generateRule = generateRule;
|
7
7
|
var _generateLtr = _interopRequireDefault(require("./physical-rtl/generate-ltr"));
|
8
8
|
var _generateRtl = _interopRequireDefault(require("./physical-rtl/generate-rtl"));
|
9
|
-
var _genCSSRule =
|
9
|
+
var _genCSSRule = require("./utils/genCSSRule");
|
10
|
+
var _propertyPriorities = _interopRequireDefault(require("./utils/property-priorities"));
|
10
11
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
11
12
|
/**
|
12
13
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
@@ -17,48 +18,19 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
17
18
|
*
|
18
19
|
*/
|
19
20
|
|
20
|
-
function
|
21
|
+
function generateRule(className, key,
|
22
|
+
// pre-dashed
|
23
|
+
value, pseudos, atRules) {
|
21
24
|
const pairs = Array.isArray(value) ? value.map(eachValue => [key, eachValue]) : [[key, value]];
|
22
25
|
const ltrPairs = pairs.map(_generateLtr.default);
|
23
26
|
const ltrDecls = ltrPairs.map(pair => pair.join(':')).join(';');
|
24
27
|
const rtlDecls = pairs.map(_generateRtl.default).filter(Boolean).map(pair => pair.join(':')).join(';');
|
25
|
-
const ltrRule = (0, _genCSSRule.
|
26
|
-
const rtlRule = !rtlDecls ? null : (0, _genCSSRule.
|
27
|
-
|
28
|
-
if (pseudo != null) {
|
29
|
-
if (pseudo[0] === '@') {
|
30
|
-
priority = 2;
|
31
|
-
} else if (pseudo[0] === ':') {
|
32
|
-
priority = pseudoPriorities[pseudo] ?? 2;
|
33
|
-
if (pseudo.startsWith(':nth-child')) {
|
34
|
-
priority = 6;
|
35
|
-
}
|
36
|
-
if (pseudo.startsWith(':nth-of-type')) {
|
37
|
-
priority = 7;
|
38
|
-
}
|
39
|
-
}
|
40
|
-
}
|
41
|
-
if (key.toLowerCase().includes('left') || key.toLowerCase().includes('right')) {
|
42
|
-
// Bump priority for physical left/right values.
|
43
|
-
priority += 0.1;
|
44
|
-
}
|
28
|
+
const ltrRule = (0, _genCSSRule.genCSSRule)(className, ltrDecls, pseudos, atRules);
|
29
|
+
const rtlRule = !rtlDecls ? null : (0, _genCSSRule.genCSSRule)(className, rtlDecls, pseudos, atRules);
|
30
|
+
const priority = (0, _propertyPriorities.default)(key) + Math.max(...pseudos.map(_propertyPriorities.default), ...atRules.map(_propertyPriorities.default), 0);
|
45
31
|
return {
|
46
32
|
priority,
|
47
33
|
ltr: ltrRule,
|
48
34
|
rtl: rtlRule
|
49
35
|
};
|
50
|
-
}
|
51
|
-
const pseudoPriorities = {
|
52
|
-
// Might become unsupported:
|
53
|
-
':first-child': 3,
|
54
|
-
':last-child': 4,
|
55
|
-
':only-child': 5,
|
56
|
-
':nth-child': 6,
|
57
|
-
':nth-of-type': 7,
|
58
|
-
':hover': 8,
|
59
|
-
':focus': 9,
|
60
|
-
':active': 10,
|
61
|
-
':disabled': 11,
|
62
|
-
'::placeholder': 12,
|
63
|
-
'::thumb': 13
|
64
|
-
};
|
36
|
+
}
|
package/lib/index.d.ts
CHANGED
@@ -64,6 +64,13 @@ export type StyleXOptions = {
|
|
64
64
|
stylexSheetName?: string | undefined;
|
65
65
|
classNamePrefix: string;
|
66
66
|
definedStylexCSSVariables?: { [key: string]: any };
|
67
|
+
styleResolution:
|
68
|
+
| 'application-order' // The last style applied wins.
|
69
|
+
// More specific styles will win over less specific styles. (margin-top wins over margin)
|
70
|
+
| 'property-specificity'
|
71
|
+
// Legacy behavior, that expands shorthand properties into their longhand counterparts at compile-time.
|
72
|
+
// This is not recommended, and will be removed in a future version.
|
73
|
+
| 'legacy-expand-shorthands';
|
67
74
|
[key: string]: any;
|
68
75
|
};
|
69
76
|
|
@@ -89,4 +96,7 @@ export const messages: {
|
|
89
96
|
LOCAL_ONLY: string;
|
90
97
|
UNEXPECTED_ARGUMENT: string;
|
91
98
|
EXPECTED_FUNCTION_CALL: string;
|
99
|
+
INVALID_PSEUDO_OR_AT_RULE: string;
|
100
|
+
ONLY_TOP_LEVEL_INLCUDES: string;
|
101
|
+
DUPLICATE_CONDITIONAL: string;
|
92
102
|
};
|