@stylexjs/shared 0.1.0-beta.6 → 0.2.0-beta.10
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.
- 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 +14 -2
- 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 +32 -91
- package/lib/stylex-defaultValue.js +397 -0
- 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 +24 -3
- 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
@@ -25,10 +25,12 @@ export type InjectableStyle = {
|
|
25
25
|
export type StyleRule = readonly [string, string, InjectableStyle];
|
26
26
|
|
27
27
|
export type CompiledStyles = {
|
28
|
-
readonly [key: string]: string |
|
28
|
+
readonly [key: string]: string | null;
|
29
|
+
readonly $$css: true;
|
29
30
|
};
|
30
31
|
export type MutableCompiledStyles = {
|
31
|
-
[key: string]: string |
|
32
|
+
[key: string]: string | null;
|
33
|
+
$$css: true;
|
32
34
|
};
|
33
35
|
|
34
36
|
export type CompiledNamespaces = { readonly [key: string]: CompiledStyles };
|
@@ -62,6 +64,13 @@ export type StyleXOptions = {
|
|
62
64
|
stylexSheetName?: string | undefined;
|
63
65
|
classNamePrefix: string;
|
64
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';
|
65
74
|
[key: string]: any;
|
66
75
|
};
|
67
76
|
|
@@ -87,4 +96,7 @@ export const messages: {
|
|
87
96
|
LOCAL_ONLY: string;
|
88
97
|
UNEXPECTED_ARGUMENT: string;
|
89
98
|
EXPECTED_FUNCTION_CALL: string;
|
99
|
+
INVALID_PSEUDO_OR_AT_RULE: string;
|
100
|
+
ONLY_TOP_LEVEL_INLCUDES: string;
|
101
|
+
DUPLICATE_CONDITIONAL: string;
|
90
102
|
};
|