@stylexjs/stylex 0.1.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc.js +40 -0
- package/__tests__/StyleXSheet-test.js +101 -0
- package/__tests__/stylex-test.js +202 -0
- package/benchmark.js +144 -0
- package/lib/StyleXCSSTypes.js +10 -0
- package/lib/StyleXSheet.js +284 -0
- package/lib/StyleXTypes.js +10 -0
- package/lib/stylex-inject.js +20 -0
- package/lib/stylex.d.ts +84 -0
- package/lib/stylex.js +124 -0
- package/package.json +23 -0
package/.babelrc.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
function makeHaste() {
|
|
2
|
+
return {
|
|
3
|
+
visitor: {
|
|
4
|
+
ImportDeclaration(path) {
|
|
5
|
+
if (path.get('source').isStringLiteral()) {
|
|
6
|
+
const oldValue = path.get('source').node.value;
|
|
7
|
+
path.get('source').node.value = oldValue.slice(
|
|
8
|
+
oldValue.lastIndexOf('/') + 1
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const presets = process.env['HASTE']
|
|
17
|
+
? []
|
|
18
|
+
: [
|
|
19
|
+
[
|
|
20
|
+
'@babel/preset-env',
|
|
21
|
+
{
|
|
22
|
+
exclude: ['@babel/plugin-transform-typeof-symbol'],
|
|
23
|
+
targets: 'defaults',
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
'@babel/preset-flow',
|
|
27
|
+
'@babel/preset-react',
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
const plugins = process.env['HASTE']
|
|
31
|
+
? [makeHaste, '@babel/plugin-syntax-flow', '@babel/plugin-syntax-jsx']
|
|
32
|
+
: [];
|
|
33
|
+
|
|
34
|
+
module.exports = {
|
|
35
|
+
assumptions: {
|
|
36
|
+
iterableIsArray: true,
|
|
37
|
+
},
|
|
38
|
+
presets,
|
|
39
|
+
plugins,
|
|
40
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @flow strict
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
import { StyleXSheet } from '../src/StyleXSheet';
|
|
13
|
+
|
|
14
|
+
const testOpts = {
|
|
15
|
+
rootTheme: undefined,
|
|
16
|
+
supportsVariables: true,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
test('StyleXSheet.prototype.insert', () => {
|
|
20
|
+
const sheet = new StyleXSheet(testOpts);
|
|
21
|
+
|
|
22
|
+
expect(sheet.getRuleCount()).toBe(0);
|
|
23
|
+
sheet.inject();
|
|
24
|
+
expect(sheet.getRuleCount()).toBe(0);
|
|
25
|
+
|
|
26
|
+
sheet.insert('.a {}', 0);
|
|
27
|
+
expect(sheet.getRuleCount()).toBe(1);
|
|
28
|
+
|
|
29
|
+
sheet.insert('.b {}', 0);
|
|
30
|
+
expect(sheet.getRuleCount()).toBe(2);
|
|
31
|
+
|
|
32
|
+
sheet.insert('.b {}', 0);
|
|
33
|
+
expect(sheet.getRuleCount()).toBe(2);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('StyleXSheet.prototype.insert respects priorities', () => {
|
|
37
|
+
const sheet = new StyleXSheet(testOpts);
|
|
38
|
+
|
|
39
|
+
sheet.insert('.last {}', 6);
|
|
40
|
+
sheet.insert('.third {}', 3);
|
|
41
|
+
sheet.insert('.first {}', 0);
|
|
42
|
+
sheet.insert('.second {}', 1);
|
|
43
|
+
|
|
44
|
+
expect(sheet.getCSS()).toMatchInlineSnapshot(`
|
|
45
|
+
".first {}
|
|
46
|
+
.second {}
|
|
47
|
+
.third {}
|
|
48
|
+
.last {}"
|
|
49
|
+
`);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('StyleXSheet.prototype.insert respects priority floats', () => {
|
|
53
|
+
const sheet = new StyleXSheet(testOpts);
|
|
54
|
+
|
|
55
|
+
sheet.insert('.fourth {}', 6.8);
|
|
56
|
+
sheet.insert('.third {}', 6.5);
|
|
57
|
+
sheet.insert('.second {}', 6);
|
|
58
|
+
sheet.insert('.first {}', 2);
|
|
59
|
+
|
|
60
|
+
expect(sheet.getCSS()).toMatchInlineSnapshot(`
|
|
61
|
+
".first {}
|
|
62
|
+
.second {}
|
|
63
|
+
.third {}
|
|
64
|
+
.fourth {}"
|
|
65
|
+
`);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('StyleXSheet.prototype.insert handles RTL rules with media queries', () => {
|
|
69
|
+
const sheet = new StyleXSheet(testOpts);
|
|
70
|
+
|
|
71
|
+
sheet.insert(
|
|
72
|
+
'@media (min-width: 1000px) { .foo {} }',
|
|
73
|
+
0,
|
|
74
|
+
'@media (min-width: 1000px) { .foo {} }'
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
expect(sheet.getCSS()).toMatchInlineSnapshot(`
|
|
78
|
+
"@media (min-width: 1000px) {html:not([dir='rtl']) .foo {} }
|
|
79
|
+
@media (min-width: 1000px) {html[dir='rtl'] .foo {} }"
|
|
80
|
+
`);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('inlines variables for older browsers', () => {
|
|
84
|
+
const sheet = new StyleXSheet({
|
|
85
|
+
rootDarkTheme: { foo: 'reallydark' },
|
|
86
|
+
rootTheme: { foo: 'bar' },
|
|
87
|
+
supportsVariables: false,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
sheet.insert('.foo {color: var(--foo)}', 1);
|
|
91
|
+
|
|
92
|
+
expect(sheet.getCSS()).toMatchInlineSnapshot(`
|
|
93
|
+
":root, .__fb-light-mode {
|
|
94
|
+
--foo: bar;
|
|
95
|
+
}
|
|
96
|
+
.__fb-dark-mode:root, .__fb-dark-mode {
|
|
97
|
+
--foo: reallydark;
|
|
98
|
+
}
|
|
99
|
+
.foo {color: bar}"
|
|
100
|
+
`);
|
|
101
|
+
});
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @noflow
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
import { styleSheet } from '../src/StyleXSheet';
|
|
13
|
+
import stylex from '../src/stylex';
|
|
14
|
+
|
|
15
|
+
// TODO: priorities need testing
|
|
16
|
+
test('stylex.inject', () => {
|
|
17
|
+
const prevCount = styleSheet.getRuleCount();
|
|
18
|
+
stylex.inject('hey {}', 0);
|
|
19
|
+
expect(styleSheet.getRuleCount()).toBeGreaterThan(prevCount);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe('stylex', () => {
|
|
23
|
+
test('basic resolve', () => {
|
|
24
|
+
expect(stylex({ a: 'aaa', b: 'bbb' })).toBe('aaa bbb');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('merge order', () => {
|
|
28
|
+
expect(
|
|
29
|
+
stylex([
|
|
30
|
+
{ a: 'a', ':hover': { aa: 'aa' } },
|
|
31
|
+
{ b: 'b' },
|
|
32
|
+
{ c: 'c', ':hover': { cc: 'cc' } },
|
|
33
|
+
])
|
|
34
|
+
).toBe('a aa b c cc');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('with a top-level array of simple overridden classes', () => {
|
|
38
|
+
expect(
|
|
39
|
+
stylex([
|
|
40
|
+
{
|
|
41
|
+
backgroundColor: 'nu7423ey',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
backgroundColor: 'gh25dzvf',
|
|
45
|
+
},
|
|
46
|
+
])
|
|
47
|
+
).toEqual('gh25dzvf');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('with nested arrays and pseudoClasses overriding things', () => {
|
|
51
|
+
expect(
|
|
52
|
+
stylex([
|
|
53
|
+
{
|
|
54
|
+
backgroundColor: 'nu7423ey',
|
|
55
|
+
},
|
|
56
|
+
[
|
|
57
|
+
{
|
|
58
|
+
backgroundColor: 'abcdefg',
|
|
59
|
+
':hover': {
|
|
60
|
+
backgroundColor: 'ksdfmwjs',
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
{
|
|
65
|
+
color: 'gofk2cf1',
|
|
66
|
+
':hover': {
|
|
67
|
+
backgroundColor: 'rse6dlih',
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
])
|
|
71
|
+
).toEqual('abcdefg gofk2cf1 rse6dlih');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('with just pseudoclasses', () => {
|
|
75
|
+
expect(
|
|
76
|
+
stylex(
|
|
77
|
+
{
|
|
78
|
+
':hover': {
|
|
79
|
+
backgroundColor: 'rse6dlih',
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
':hover': {
|
|
84
|
+
color: 'gofk2cf1',
|
|
85
|
+
},
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
).toEqual('rse6dlih gofk2cf1');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('with complicated set of arguments', () => {
|
|
92
|
+
const styles = [
|
|
93
|
+
{
|
|
94
|
+
backgroundColor: 'nu7423ey',
|
|
95
|
+
borderColor: 'tpe1esc0',
|
|
96
|
+
borderStyle: 'gewhe1h2',
|
|
97
|
+
borderWidth: 'gcovof34',
|
|
98
|
+
boxSizing: 'bdao358l',
|
|
99
|
+
display: 'rse6dlih',
|
|
100
|
+
listStyle: 's5oniofx',
|
|
101
|
+
marginTop: 'm8h3af8h',
|
|
102
|
+
marginEnd: 'l7ghb35v',
|
|
103
|
+
marginBottom: 'kjdc1dyq',
|
|
104
|
+
marginStart: 'kmwttqpk',
|
|
105
|
+
paddingTop: 'srn514ro',
|
|
106
|
+
paddingEnd: 'oxkhqvkx',
|
|
107
|
+
paddingBottom: 'rl78xhln',
|
|
108
|
+
paddingStart: 'nch0832m',
|
|
109
|
+
WebkitTapHighlightColor: 'qi72231t',
|
|
110
|
+
textAlign: 'cr00lzj9',
|
|
111
|
+
textDecoration: 'rn8ck1ys',
|
|
112
|
+
whiteSpace: 'n3t5jt4f',
|
|
113
|
+
wordWrap: 'gh25dzvf',
|
|
114
|
+
zIndex: 'g4tp4svg',
|
|
115
|
+
},
|
|
116
|
+
false,
|
|
117
|
+
false,
|
|
118
|
+
false,
|
|
119
|
+
false,
|
|
120
|
+
[
|
|
121
|
+
{
|
|
122
|
+
cursor: 'fsf7x5fv',
|
|
123
|
+
touchAction: 's3jn8y49',
|
|
124
|
+
},
|
|
125
|
+
false,
|
|
126
|
+
{
|
|
127
|
+
outline: 'icdlwmnq',
|
|
128
|
+
},
|
|
129
|
+
[
|
|
130
|
+
{
|
|
131
|
+
WebkitTapHighlightColor: 'oajrlxb2',
|
|
132
|
+
cursor: 'nhd2j8a9',
|
|
133
|
+
touchAction: 'f1sip0of',
|
|
134
|
+
},
|
|
135
|
+
false,
|
|
136
|
+
false,
|
|
137
|
+
{
|
|
138
|
+
textDecoration: 'esuyzwwr',
|
|
139
|
+
':hover': {
|
|
140
|
+
textDecoration: 'p8dawk7l',
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
false,
|
|
144
|
+
[
|
|
145
|
+
{
|
|
146
|
+
backgroundColor: 'g5ia77u1',
|
|
147
|
+
border: 'e4t7hp5w',
|
|
148
|
+
color: 'gmql0nx0',
|
|
149
|
+
cursor: 'nhd2j8a9',
|
|
150
|
+
display: 'q9uorilb',
|
|
151
|
+
fontFamily: 'ihxqhq3m',
|
|
152
|
+
fontSize: 'l94mrbxd',
|
|
153
|
+
lineHeight: 'aenfhxwr',
|
|
154
|
+
marginTop: 'kvgmc6g5',
|
|
155
|
+
marginEnd: 'cxmmr5t8',
|
|
156
|
+
marginBottom: 'oygrvhab',
|
|
157
|
+
marginStart: 'hcukyx3x',
|
|
158
|
+
paddingTop: 'jb3vyjys',
|
|
159
|
+
paddingEnd: 'rz4wbd8a',
|
|
160
|
+
paddingBottom: 'qt6c0cv9',
|
|
161
|
+
paddingStart: 'a8nywdso',
|
|
162
|
+
textAlign: 'i1ao9s8h',
|
|
163
|
+
textDecoration: 'myohyog2',
|
|
164
|
+
':hover': {
|
|
165
|
+
color: 'ksdfmwjs',
|
|
166
|
+
textDecoration: 'gofk2cf1',
|
|
167
|
+
},
|
|
168
|
+
':active': {
|
|
169
|
+
transform: 'lsqurvkf',
|
|
170
|
+
transition: 'bj9fd4vl',
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
display: 'a8c37x1j',
|
|
175
|
+
width: 'k4urcfbm',
|
|
176
|
+
},
|
|
177
|
+
[
|
|
178
|
+
{
|
|
179
|
+
':active': {
|
|
180
|
+
transform: 'tm8avpzi',
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
],
|
|
184
|
+
],
|
|
185
|
+
],
|
|
186
|
+
],
|
|
187
|
+
];
|
|
188
|
+
|
|
189
|
+
const value = stylex(styles);
|
|
190
|
+
const repeat = stylex(styles);
|
|
191
|
+
|
|
192
|
+
// Check the cached-derived result is correct
|
|
193
|
+
expect(value).toEqual(repeat);
|
|
194
|
+
|
|
195
|
+
expect(value.split(' ').sort().join(' ')).toEqual(
|
|
196
|
+
'g5ia77u1 tpe1esc0 gewhe1h2 gcovof34 bdao358l a8c37x1j s5oniofx kvgmc6g5 cxmmr5t8 oygrvhab hcukyx3x jb3vyjys rz4wbd8a qt6c0cv9 a8nywdso oajrlxb2 i1ao9s8h myohyog2 n3t5jt4f gh25dzvf g4tp4svg nhd2j8a9 f1sip0of icdlwmnq e4t7hp5w gmql0nx0 ihxqhq3m l94mrbxd aenfhxwr k4urcfbm gofk2cf1 ksdfmwjs tm8avpzi bj9fd4vl'
|
|
197
|
+
.split(' ')
|
|
198
|
+
.sort()
|
|
199
|
+
.join(' ')
|
|
200
|
+
);
|
|
201
|
+
});
|
|
202
|
+
});
|
package/benchmark.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const stylex = require('./lib/stylex').default;
|
|
9
|
+
const Benchmark = require('benchmark');
|
|
10
|
+
const suite = new Benchmark.Suite();
|
|
11
|
+
const test = (...args) => suite.add(...args);
|
|
12
|
+
|
|
13
|
+
const basicStyleFixture1 = {
|
|
14
|
+
backgroundColor: 'nu7423ey',
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const basicStyleFixture2 = {
|
|
18
|
+
backgroundColor: 'gh25dzvf',
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const bigStyleFixture = {
|
|
22
|
+
backgroundColor: 'nu7423ey',
|
|
23
|
+
borderColor: 'tpe1esc0',
|
|
24
|
+
borderStyle: 'gewhe1h2',
|
|
25
|
+
borderWidth: 'gcovof34',
|
|
26
|
+
boxSizing: 'bdao358l',
|
|
27
|
+
display: 'rse6dlih',
|
|
28
|
+
listStyle: 's5oniofx',
|
|
29
|
+
marginTop: 'm8h3af8h',
|
|
30
|
+
marginEnd: 'l7ghb35v',
|
|
31
|
+
marginBottom: 'kjdc1dyq',
|
|
32
|
+
marginStart: 'kmwttqpk',
|
|
33
|
+
paddingTop: 'srn514ro',
|
|
34
|
+
paddingEnd: 'oxkhqvkx',
|
|
35
|
+
paddingBottom: 'rl78xhln',
|
|
36
|
+
paddingStart: 'nch0832m',
|
|
37
|
+
textAlign: 'cr00lzj9',
|
|
38
|
+
textDecoration: 'rn8ck1ys',
|
|
39
|
+
whiteSpace: 'n3t5jt4f',
|
|
40
|
+
wordWrap: 'gh25dzvf',
|
|
41
|
+
zIndex: 'g4tp4svg',
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const bigStyleWithPseudosFixture = {
|
|
45
|
+
backgroundColor: 'g5ia77u1',
|
|
46
|
+
border: 'e4t7hp5w',
|
|
47
|
+
color: 'gmql0nx0',
|
|
48
|
+
cursor: 'nhd2j8a9',
|
|
49
|
+
display: 'q9uorilb',
|
|
50
|
+
fontFamily: 'ihxqhq3m',
|
|
51
|
+
fontSize: 'l94mrbxd',
|
|
52
|
+
lineHeight: 'aenfhxwr',
|
|
53
|
+
marginTop: 'kvgmc6g5',
|
|
54
|
+
marginEnd: 'cxmmr5t8',
|
|
55
|
+
marginBottom: 'oygrvhab',
|
|
56
|
+
marginStart: 'hcukyx3x',
|
|
57
|
+
paddingTop: 'jb3vyjys',
|
|
58
|
+
paddingEnd: 'rz4wbd8a',
|
|
59
|
+
paddingBottom: 'qt6c0cv9',
|
|
60
|
+
paddingStart: 'a8nywdso',
|
|
61
|
+
textAlign: 'i1ao9s8h',
|
|
62
|
+
textDecoration: 'myohyog2',
|
|
63
|
+
':hover': {
|
|
64
|
+
color: 'ksdfmwjs',
|
|
65
|
+
textDecoration: 'gofk2cf1',
|
|
66
|
+
},
|
|
67
|
+
':active': {
|
|
68
|
+
transform: 'lsqurvkf',
|
|
69
|
+
transition: 'bj9fd4vl',
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
test('stylex(): basic', () => {
|
|
74
|
+
stylex(basicStyleFixture1);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test('stylex(): complex', () => {
|
|
78
|
+
stylex(bigStyleFixture);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test('stylex(): basic merge (args)', () => {
|
|
82
|
+
stylex(basicStyleFixture1, basicStyleFixture2);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('stylex(): basic merge (array)', () => {
|
|
86
|
+
stylex([basicStyleFixture1, basicStyleFixture2]);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const complexNestedStyleFixture = [
|
|
90
|
+
bigStyleFixture,
|
|
91
|
+
false,
|
|
92
|
+
false,
|
|
93
|
+
false,
|
|
94
|
+
false,
|
|
95
|
+
[
|
|
96
|
+
{
|
|
97
|
+
cursor: 'fsf7x5fv',
|
|
98
|
+
touchAction: 's3jn8y49',
|
|
99
|
+
},
|
|
100
|
+
false,
|
|
101
|
+
{
|
|
102
|
+
outline: 'icdlwmnq',
|
|
103
|
+
},
|
|
104
|
+
[
|
|
105
|
+
{
|
|
106
|
+
cursor: 'nhd2j8a9',
|
|
107
|
+
touchAction: 'f1sip0of',
|
|
108
|
+
},
|
|
109
|
+
false,
|
|
110
|
+
false,
|
|
111
|
+
{
|
|
112
|
+
textDecoration: 'esuyzwwr',
|
|
113
|
+
':hover': {
|
|
114
|
+
textDecoration: 'p8dawk7l',
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
false,
|
|
118
|
+
[
|
|
119
|
+
bigStyleWithPseudosFixture,
|
|
120
|
+
{
|
|
121
|
+
display: 'a8c37x1j',
|
|
122
|
+
width: 'k4urcfbm',
|
|
123
|
+
},
|
|
124
|
+
[
|
|
125
|
+
{
|
|
126
|
+
':active': {
|
|
127
|
+
transform: 'tm8avpzi',
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
],
|
|
132
|
+
],
|
|
133
|
+
],
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
test('stylex(): complex merge (array)', () => {
|
|
137
|
+
stylex([complexNestedStyleFixture]);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
suite.on('cycle', (event) => {
|
|
141
|
+
console.log(String(event.target));
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
suite.run();
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
Object.defineProperty(exports, "__esModule", {
|
|
13
|
+
value: true
|
|
14
|
+
});
|
|
15
|
+
exports.styleSheet = exports.StyleXSheet = void 0;
|
|
16
|
+
var _invariant = _interopRequireDefault(require("invariant"));
|
|
17
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
18
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
19
|
+
const LIGHT_MODE_CLASS_NAME = '__fb-light-mode';
|
|
20
|
+
const DARK_MODE_CLASS_NAME = '__fb-dark-mode';
|
|
21
|
+
/**
|
|
22
|
+
* Take a theme and generate it's accompanying CSS variables
|
|
23
|
+
*/
|
|
24
|
+
function buildTheme(selector, theme) {
|
|
25
|
+
const lines = [];
|
|
26
|
+
lines.push(`${selector} {`);
|
|
27
|
+
for (const key in theme) {
|
|
28
|
+
const value = theme[key];
|
|
29
|
+
lines.push(` --${key}: ${value};`);
|
|
30
|
+
}
|
|
31
|
+
lines.push('}');
|
|
32
|
+
return lines.join('\n');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Create a <style> tag and add it to the head.
|
|
37
|
+
*/
|
|
38
|
+
function makeStyleTag() {
|
|
39
|
+
const tag = document.createElement('style');
|
|
40
|
+
tag.setAttribute('type', 'text/css');
|
|
41
|
+
tag.setAttribute('data-stylex', 'true');
|
|
42
|
+
const head = document.head || document.getElementsByTagName('head')[0];
|
|
43
|
+
(0, _invariant.default)(head, 'expected head');
|
|
44
|
+
head.appendChild(tag);
|
|
45
|
+
return tag;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Check if the browser supports CSS variables
|
|
50
|
+
*/
|
|
51
|
+
function doesSupportCSSVariables() {
|
|
52
|
+
return globalThis.CSS != null && globalThis.CSS.supports != null && globalThis.CSS.supports('--fake-var:0');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Regex to replace var(--foo) with an inlined version
|
|
56
|
+
const VARIABLE_MATCH = /var\(--(.*?)\)/g;
|
|
57
|
+
|
|
58
|
+
// Stylesheet options
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* This class manages the CSS stylesheet for the page and the injection of new
|
|
62
|
+
* CSS rules.
|
|
63
|
+
*/
|
|
64
|
+
class StyleXSheet {
|
|
65
|
+
constructor(opts) {
|
|
66
|
+
this.tag = null;
|
|
67
|
+
this.injected = false;
|
|
68
|
+
this.ruleForPriority = new Map();
|
|
69
|
+
this.rules = [];
|
|
70
|
+
this.rootTheme = opts.rootTheme;
|
|
71
|
+
this.rootDarkTheme = opts.rootDarkTheme;
|
|
72
|
+
this.supportsVariables = opts.supportsVariables ?? doesSupportCSSVariables();
|
|
73
|
+
}
|
|
74
|
+
getVariableMatch() {
|
|
75
|
+
return VARIABLE_MATCH;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Check if we have don't have access to the dom
|
|
80
|
+
*/
|
|
81
|
+
isHeadless() {
|
|
82
|
+
var _globalThis$document;
|
|
83
|
+
return this.tag == null || (globalThis === null || globalThis === void 0 ? void 0 : (_globalThis$document = globalThis.document) === null || _globalThis$document === void 0 ? void 0 : _globalThis$document.body) == null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Get the stylesheet tag. Throw if none exists.
|
|
88
|
+
*/
|
|
89
|
+
getTag() {
|
|
90
|
+
const {
|
|
91
|
+
tag
|
|
92
|
+
} = this;
|
|
93
|
+
(0, _invariant.default)(tag != null, 'expected tag');
|
|
94
|
+
return tag;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Get the current stylesheet CSS.
|
|
99
|
+
*/
|
|
100
|
+
getCSS() {
|
|
101
|
+
return this.rules.join('\n');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get the position of the rule in the stylesheet.
|
|
106
|
+
*/
|
|
107
|
+
getRulePosition(rule) {
|
|
108
|
+
return this.rules.indexOf(rule);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Count of the current rules in the stylesheet. Used in tests.
|
|
113
|
+
*/
|
|
114
|
+
getRuleCount() {
|
|
115
|
+
return this.rules.length;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Inject a style tag into the document head
|
|
120
|
+
*/
|
|
121
|
+
inject() {
|
|
122
|
+
var _globalThis$document2;
|
|
123
|
+
if (this.injected) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
this.injected = true;
|
|
127
|
+
|
|
128
|
+
// Running in a server environment
|
|
129
|
+
if (((_globalThis$document2 = globalThis.document) === null || _globalThis$document2 === void 0 ? void 0 : _globalThis$document2.body) == null) {
|
|
130
|
+
this.injectTheme();
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Create style tag if in browser
|
|
135
|
+
this.tag = makeStyleTag();
|
|
136
|
+
this.injectTheme();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Inject the theme styles
|
|
141
|
+
*/
|
|
142
|
+
injectTheme() {
|
|
143
|
+
if (this.rootTheme != null) {
|
|
144
|
+
this.insert(buildTheme(`:root, .${LIGHT_MODE_CLASS_NAME}`, this.rootTheme), 0);
|
|
145
|
+
}
|
|
146
|
+
if (this.rootDarkTheme != null) {
|
|
147
|
+
this.insert(buildTheme(`.${DARK_MODE_CLASS_NAME}:root, .${DARK_MODE_CLASS_NAME}`, this.rootDarkTheme), 0);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Inject custom theme styles (only for internal testing)
|
|
153
|
+
*/
|
|
154
|
+
__injectCustomThemeForTesting(selector, theme) {
|
|
155
|
+
if (theme != null) {
|
|
156
|
+
this.insert(buildTheme(selector, theme), 0);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Delete the requested rule from the stylesheet
|
|
162
|
+
*/
|
|
163
|
+
delete(rule) {
|
|
164
|
+
// Get the index of this rule
|
|
165
|
+
const index = this.rules.indexOf(rule);
|
|
166
|
+
(0, _invariant.default)(index >= 0, "Couldn't find the index for rule %s", rule);
|
|
167
|
+
|
|
168
|
+
// Remove the rule from our index
|
|
169
|
+
this.rules.splice(index, 1);
|
|
170
|
+
if (this.isHeadless()) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const tag = this.getTag();
|
|
174
|
+
const sheet = tag.sheet;
|
|
175
|
+
(0, _invariant.default)(sheet, 'expected sheet');
|
|
176
|
+
sheet.deleteRule(index);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
*
|
|
181
|
+
*/
|
|
182
|
+
normalizeRule(rule) {
|
|
183
|
+
const {
|
|
184
|
+
rootTheme
|
|
185
|
+
} = this;
|
|
186
|
+
if (this.supportsVariables || rootTheme == null) {
|
|
187
|
+
return rule;
|
|
188
|
+
}
|
|
189
|
+
return rule.replace(VARIABLE_MATCH, (_match, name) => {
|
|
190
|
+
return rootTheme[name];
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Get the rule position a rule should be inserted at according to the
|
|
196
|
+
* specified priority.
|
|
197
|
+
*/
|
|
198
|
+
getInsertPositionForPriority(priority) {
|
|
199
|
+
// If there's an end rule associated with this priority, then get the next
|
|
200
|
+
// rule which will belong to the next priority
|
|
201
|
+
// The rule will be inserted before it and assigned to the current priority
|
|
202
|
+
const priorityRule = this.ruleForPriority.get(priority);
|
|
203
|
+
if (priorityRule != null) {
|
|
204
|
+
return this.rules.indexOf(priorityRule) + 1;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// If we've never created this priority before, then let's find the highest
|
|
208
|
+
// priority to target
|
|
209
|
+
const priorities = Array.from(this.ruleForPriority.keys()).sort((a, b) => b - a).filter(num => num > priority ? 1 : 0);
|
|
210
|
+
|
|
211
|
+
// If there's no priorities then place us at the start
|
|
212
|
+
if (priorities.length === 0) {
|
|
213
|
+
return this.getRuleCount();
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Place us next to the next highest priority
|
|
217
|
+
const lastPriority = priorities.pop();
|
|
218
|
+
return this.rules.indexOf(this.ruleForPriority.get(lastPriority));
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Insert a rule into the stylesheet.
|
|
223
|
+
*/
|
|
224
|
+
insert(rawLTRRule, priority, rawRTLRule) {
|
|
225
|
+
// Inject the stylesheet if it hasn't already been
|
|
226
|
+
if (this.injected === false) {
|
|
227
|
+
this.inject();
|
|
228
|
+
}
|
|
229
|
+
if (rawRTLRule != null) {
|
|
230
|
+
this.insert(addAncestorSelector(rawLTRRule, "html:not([dir='rtl'])"), priority);
|
|
231
|
+
this.insert(addAncestorSelector(rawRTLRule, "html[dir='rtl']"), priority);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const rawRule = rawLTRRule;
|
|
235
|
+
|
|
236
|
+
// Don't insert this rule if it already exists
|
|
237
|
+
if (this.rules.includes(rawRule)) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
const rule = this.normalizeRule(rawRule);
|
|
241
|
+
|
|
242
|
+
// Get the position where we should insert the rule
|
|
243
|
+
const insertPos = this.getInsertPositionForPriority(priority);
|
|
244
|
+
this.rules.splice(insertPos, 0, rule);
|
|
245
|
+
|
|
246
|
+
// Set this rule as the end of the priority group
|
|
247
|
+
this.ruleForPriority.set(priority, rule);
|
|
248
|
+
if (this.isHeadless()) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
const tag = this.getTag();
|
|
252
|
+
const sheet = tag.sheet;
|
|
253
|
+
if (sheet != null) {
|
|
254
|
+
try {
|
|
255
|
+
sheet.insertRule(rule, insertPos);
|
|
256
|
+
} catch {
|
|
257
|
+
// Ignore: error likely due to inserting prefixed rules (e.g. `::-moz-range-thumb`).
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
// Ignore the case where sheet == null. It's an edge-case Edge 17 bug.
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Adds an ancestor selector in a media-query-aware way.
|
|
266
|
+
*/
|
|
267
|
+
exports.StyleXSheet = StyleXSheet;
|
|
268
|
+
_defineProperty(StyleXSheet, "LIGHT_MODE_CLASS_NAME", LIGHT_MODE_CLASS_NAME);
|
|
269
|
+
_defineProperty(StyleXSheet, "DARK_MODE_CLASS_NAME", DARK_MODE_CLASS_NAME);
|
|
270
|
+
function addAncestorSelector(selector, ancestorSelector) {
|
|
271
|
+
if (!selector.startsWith('@')) {
|
|
272
|
+
return `${ancestorSelector} ${selector}`;
|
|
273
|
+
}
|
|
274
|
+
const firstBracketIndex = selector.indexOf('{');
|
|
275
|
+
const mediaQueryPart = selector.slice(0, firstBracketIndex + 1);
|
|
276
|
+
const rest = selector.slice(firstBracketIndex + 1);
|
|
277
|
+
return `${mediaQueryPart}${ancestorSelector} ${rest}`;
|
|
278
|
+
}
|
|
279
|
+
const styleSheet = new StyleXSheet({
|
|
280
|
+
supportsVariables: true,
|
|
281
|
+
rootTheme: {},
|
|
282
|
+
rootDarkTheme: {}
|
|
283
|
+
});
|
|
284
|
+
exports.styleSheet = styleSheet;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = inject;
|
|
7
|
+
var _StyleXSheet = require("./StyleXSheet");
|
|
8
|
+
/**
|
|
9
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
10
|
+
*
|
|
11
|
+
* This source code is licensed under the MIT license found in the
|
|
12
|
+
* LICENSE file in the root directory of this source tree.
|
|
13
|
+
*
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
function inject(ltrRule, priority) {
|
|
18
|
+
let rtlRule = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
|
19
|
+
_StyleXSheet.styleSheet.insert(ltrRule, priority, rtlRule);
|
|
20
|
+
}
|
package/lib/stylex.d.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { $ReadOnly } from 'utility-types';
|
|
9
|
+
|
|
10
|
+
// Simulating an opaque type
|
|
11
|
+
declare const classNameSymbol: unique symbol;
|
|
12
|
+
|
|
13
|
+
export type ClassNameFor<K, V> = string & {
|
|
14
|
+
_tag: typeof classNameSymbol;
|
|
15
|
+
_key: K;
|
|
16
|
+
_value: V;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type ClassNameForKey<K> = ClassNameFor<K, string | number>;
|
|
20
|
+
export type ClassNameForValue<V> = ClassNameFor<string, V>;
|
|
21
|
+
export type ClassName = ClassNameFor<string, string | number>;
|
|
22
|
+
|
|
23
|
+
export type Namespace = {
|
|
24
|
+
readonly [K in string]: string | number | { [K in string]: string | number };
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type CompiledNamespace = {
|
|
28
|
+
readonly [K in string]:
|
|
29
|
+
| ClassNameFor<K, string | number>
|
|
30
|
+
| { [J in string]: ClassNameFor<`${K}+${J}`, string | number> };
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type NamespaceSet = {
|
|
34
|
+
readonly [K in string]: Namespace;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type CompiledNamespaceSet = {
|
|
38
|
+
readonly [K in string]: CompiledNamespace;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
type Stylex$Create = <S extends StyleXNamespaceSet>(
|
|
42
|
+
styles: S
|
|
43
|
+
) => $ReadOnly<{
|
|
44
|
+
readonly [K in keyof S]: {
|
|
45
|
+
readonly [P in keyof S[K]]: S[K][P] extends string | number
|
|
46
|
+
? StyleXClassNameFor<P, S[K][P]>
|
|
47
|
+
: {
|
|
48
|
+
readonly [F in keyof S[K][P]]: StyleXClassNameFor<
|
|
49
|
+
`${P}+${F}`,
|
|
50
|
+
S[K][P][F]
|
|
51
|
+
>;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
}>;
|
|
55
|
+
|
|
56
|
+
type StylexInclude = <S extends CompiledNamespace>(
|
|
57
|
+
compiledNamespace: S
|
|
58
|
+
) => {
|
|
59
|
+
readonly [K in keyof S]: S[K] extends ClassNameFor<K, infer V>
|
|
60
|
+
? V
|
|
61
|
+
: Uncompiled<S[K]>;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
type Stylex$Keyframes = <S extends StyleXNamespaceSet>(
|
|
65
|
+
animationConfig: S
|
|
66
|
+
) => string;
|
|
67
|
+
|
|
68
|
+
type stylex = {
|
|
69
|
+
(
|
|
70
|
+
...styles: ReadonlyArray<
|
|
71
|
+
StyleXArray<(CompiledNamespace | null | undefined) | boolean>
|
|
72
|
+
>
|
|
73
|
+
): string;
|
|
74
|
+
create: Stylex$Create;
|
|
75
|
+
include: StylexInclude;
|
|
76
|
+
inject: (
|
|
77
|
+
ltrRule: string,
|
|
78
|
+
priority: number,
|
|
79
|
+
rtlRule: string | null | undefined
|
|
80
|
+
) => void;
|
|
81
|
+
keyframes: Stylex$Keyframes;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export default stylex;
|
package/lib/stylex.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
Object.defineProperty(exports, "__esModule", {
|
|
13
|
+
value: true
|
|
14
|
+
});
|
|
15
|
+
exports.default = void 0;
|
|
16
|
+
var _stylexInject = _interopRequireDefault(require("./stylex-inject"));
|
|
17
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
18
|
+
const enableCache = true;
|
|
19
|
+
const cache = enableCache ? new WeakMap() : null;
|
|
20
|
+
function stylex() {
|
|
21
|
+
// Keep a set of property commits to the className
|
|
22
|
+
const definedProperties = [];
|
|
23
|
+
let className = '';
|
|
24
|
+
let nextCache = cache;
|
|
25
|
+
for (var _len = arguments.length, styles = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
26
|
+
styles[_key] = arguments[_key];
|
|
27
|
+
}
|
|
28
|
+
while (styles.length) {
|
|
29
|
+
// Push nested styles back onto the stack to be processed
|
|
30
|
+
const possibleStyle = styles.pop();
|
|
31
|
+
if (Array.isArray(possibleStyle)) {
|
|
32
|
+
for (let i = 0; i < possibleStyle.length; i++) {
|
|
33
|
+
styles.push(possibleStyle[i]);
|
|
34
|
+
}
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Process an individual style object
|
|
39
|
+
const styleObj = possibleStyle;
|
|
40
|
+
if (styleObj != null && typeof styleObj === 'object') {
|
|
41
|
+
// Build up the class names defined by this object
|
|
42
|
+
let classNameChunk = '';
|
|
43
|
+
if (nextCache != null && nextCache.has(styleObj)) {
|
|
44
|
+
// Cache: read
|
|
45
|
+
const cacheEntry = nextCache.get(styleObj);
|
|
46
|
+
if (cacheEntry != null) {
|
|
47
|
+
classNameChunk = cacheEntry.classNameChunk;
|
|
48
|
+
definedProperties.push(...cacheEntry.definedPropertiesChunk);
|
|
49
|
+
nextCache = cacheEntry.next;
|
|
50
|
+
}
|
|
51
|
+
} else {
|
|
52
|
+
// Record the properties this object defines (and that haven't already
|
|
53
|
+
// been defined by later objects.)
|
|
54
|
+
const definedPropertiesChunk = [];
|
|
55
|
+
for (const prop in styleObj) {
|
|
56
|
+
const value = styleObj[prop];
|
|
57
|
+
// Style declarations, e.g., opacity: 's3fkgpd'
|
|
58
|
+
if (typeof value === 'string') {
|
|
59
|
+
// Skip adding to the chunks if property has already been seen
|
|
60
|
+
if (!definedProperties.includes(prop)) {
|
|
61
|
+
definedProperties.push(prop);
|
|
62
|
+
definedPropertiesChunk.push(prop);
|
|
63
|
+
classNameChunk += classNameChunk ? ' ' + value : value;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Style conditions, e.g., ':hover', '@media', etc.
|
|
67
|
+
// TODO: remove if #98 is fixed
|
|
68
|
+
else if (typeof value === 'object') {
|
|
69
|
+
const condition = prop;
|
|
70
|
+
const nestedStyleObject = value;
|
|
71
|
+
for (const conditionalProp in nestedStyleObject) {
|
|
72
|
+
const conditionalValue = nestedStyleObject[conditionalProp];
|
|
73
|
+
const conditionalProperty = condition + conditionalProp;
|
|
74
|
+
// Skip if conditional property has already been seen
|
|
75
|
+
if (!definedProperties.includes(conditionalProperty)) {
|
|
76
|
+
definedProperties.push(conditionalProperty);
|
|
77
|
+
definedPropertiesChunk.push(conditionalProperty);
|
|
78
|
+
classNameChunk += classNameChunk ? ' ' + conditionalValue : conditionalValue;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Cache: write
|
|
84
|
+
if (nextCache != null) {
|
|
85
|
+
const emptyCache = new WeakMap();
|
|
86
|
+
nextCache.set(styleObj, {
|
|
87
|
+
classNameChunk,
|
|
88
|
+
definedPropertiesChunk,
|
|
89
|
+
next: emptyCache
|
|
90
|
+
});
|
|
91
|
+
nextCache = emptyCache;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Order of classes in chunks matches property-iteration order of style
|
|
96
|
+
// object. Order of chunks matches passed order of styles from first to
|
|
97
|
+
// last (which we iterate over in reverse).
|
|
98
|
+
if (classNameChunk) {
|
|
99
|
+
className = className ? classNameChunk + ' ' + className : classNameChunk;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return className;
|
|
104
|
+
}
|
|
105
|
+
function stylexCreate(_styles) {
|
|
106
|
+
throw new Error('stylex.create should never be called. It should be compiled away.');
|
|
107
|
+
}
|
|
108
|
+
function stylexIncludes(_styles) {
|
|
109
|
+
throw new Error('stylex.extends should never be called. It should be compiled away.');
|
|
110
|
+
}
|
|
111
|
+
stylex.create = stylexCreate;
|
|
112
|
+
stylex.include = stylexIncludes;
|
|
113
|
+
stylex.keyframes = _keyframes => {
|
|
114
|
+
throw new Error('stylex.keyframes should never be called');
|
|
115
|
+
};
|
|
116
|
+
stylex.firstThatWorks = function () {
|
|
117
|
+
throw new Error('stylex.firstThatWorks should never be called.');
|
|
118
|
+
};
|
|
119
|
+
stylex.inject = _stylexInject.default;
|
|
120
|
+
stylex.UNSUPPORTED_PROPERTY = props => {
|
|
121
|
+
throw new Error('stylex.UNSUPPORTED_PROPERTY should never be called. It should be compiled away.');
|
|
122
|
+
};
|
|
123
|
+
var _default = stylex;
|
|
124
|
+
exports.default = _default;
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stylexjs/stylex",
|
|
3
|
+
"version": "0.1.0-beta.1",
|
|
4
|
+
"description": "A minimal runtime styling library for web.",
|
|
5
|
+
"main": "lib/stylex.js",
|
|
6
|
+
"types": "lib/stylex.d.ts",
|
|
7
|
+
"repository": "https://www.github.com/facebookexternal/stylex",
|
|
8
|
+
"author": "Naman Goel <nmn@fb.com>",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "babel src/ --out-dir lib/ --copy-files",
|
|
12
|
+
"build-haste": "HASTE=true babel src/ --out-dir lib/ --copy-files",
|
|
13
|
+
"test": "jest"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"invariant": "^2.2.4",
|
|
17
|
+
"utility-types": "^3.10.0"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"benchmark": "^2.1.4"
|
|
21
|
+
},
|
|
22
|
+
"jest": {}
|
|
23
|
+
}
|