@startupjs/css-to-react-native-transform 2.1.0-0 → 2.1.0-2

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/dist/index.js CHANGED
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports["default"] = void 0;
7
7
  var _cssMediaquery = _interopRequireDefault(require("css-mediaquery"));
8
- var _cssToReactNative = _interopRequireDefault(require("css-to-react-native"));
8
+ var _cssToReactNative = _interopRequireDefault(require("@cssxjs/css-to-react-native"));
9
9
  var _parse = _interopRequireDefault(require("css/lib/parse"));
10
10
  var _features = require("./transforms/media-queries/features");
11
11
  var _types = require("./transforms/media-queries/types");
@@ -22,7 +22,53 @@ var unsupportedUnitRe = /^([+-]?(?:\d*\.)?\d+(?:[Ee][+-]?\d+)?(ch|em|ex|cm|mm|in
22
22
  var cssPartRe = /::?part\(([^)]+)\)/;
23
23
  var rootRe = /:root/;
24
24
  var shorthandBorderProps = ["border-radius", "border-width", "border-color", "border-style"];
25
- var transformDecls = function transformDecls(styles, declarations, result) {
25
+
26
+ /**
27
+ * Extracts @keyframes from CSS and returns the cleaned CSS and keyframes object
28
+ * @param {string} css - The input CSS string
29
+ * @returns {{css: string, keyframes: Object}} - Cleaned CSS and keyframes object
30
+ */
31
+ var extractKeyframes = function extractKeyframes(css) {
32
+ var keyframes = {};
33
+ var cleanedCss = css;
34
+
35
+ // Find @keyframes by manually parsing to handle nested braces
36
+ var index = 0;
37
+ while (index < css.length) {
38
+ var keyframesMatch = css.slice(index).match(/@keyframes\s+([^\s{]+)\s*{/);
39
+ if (!keyframesMatch) break;
40
+ var startIndex = index + keyframesMatch.index;
41
+ var nameEndIndex = startIndex + keyframesMatch[0].length;
42
+ var name = keyframesMatch[1];
43
+
44
+ // Find the matching closing brace
45
+ var braceCount = 1;
46
+ var currentIndex = nameEndIndex;
47
+ while (currentIndex < css.length && braceCount > 0) {
48
+ if (css[currentIndex] === '{') {
49
+ braceCount++;
50
+ } else if (css[currentIndex] === '}') {
51
+ braceCount--;
52
+ }
53
+ currentIndex++;
54
+ }
55
+ if (braceCount === 0) {
56
+ // Extract the body (without the outer braces)
57
+ var body = css.slice(nameEndIndex, currentIndex - 1).trim();
58
+ keyframes[name] = body;
59
+
60
+ // Mark for removal by replacing with spaces to maintain positions
61
+ var fullKeyframe = css.slice(startIndex, currentIndex);
62
+ cleanedCss = cleanedCss.replace(fullKeyframe, '');
63
+ }
64
+ index = currentIndex;
65
+ }
66
+ return {
67
+ css: cleanedCss,
68
+ keyframes: keyframes
69
+ };
70
+ };
71
+ var transformDecls = function transformDecls(styles, declarations, result, keyframes) {
26
72
  for (var d in declarations) {
27
73
  var declaration = declarations[d];
28
74
  if (declaration.type !== "declaration") continue;
@@ -50,12 +96,27 @@ var transformDecls = function transformDecls(styles, declarations, result) {
50
96
  } else {
51
97
  Object.assign(styles, transformed);
52
98
  }
99
+ } else if (['animation', 'animation-name'].includes(property) && keyframes && Object.keys(keyframes).length > 0) {
100
+ // Pass all keyframes to transformCSS - it will figure out which ones to use
101
+ var keyframeDeclarations = [];
102
+ for (var name in keyframes) {
103
+ keyframeDeclarations.push(['@keyframes ' + name, keyframes[name]]);
104
+ }
105
+ var _transformed = (0, _cssToReactNative["default"])([].concat(keyframeDeclarations, [[property, value]]));
106
+ Object.assign(styles, _transformed);
53
107
  } else {
54
108
  Object.assign(styles, (0, _cssToReactNative["default"])([[property, value]]));
55
109
  }
56
110
  }
57
111
  };
58
112
  var transform = function transform(css, options) {
113
+ // Extract keyframes and store them separately, before parsing (remove them from css)
114
+ var keyframes;
115
+ if (options !== null && options !== void 0 && options.parseKeyframes) {
116
+ var _extractKeyframes = extractKeyframes(css);
117
+ css = _extractKeyframes.css;
118
+ keyframes = _extractKeyframes.keyframes;
119
+ }
59
120
  var _parseCSS = (0, _parse["default"])(css),
60
121
  stylesheet = _parseCSS.stylesheet;
61
122
  var rules = (0, _sortRules.sortRules)(stylesheet.rules);
@@ -86,7 +147,7 @@ var transform = function transform(css, options) {
86
147
  }
87
148
  var selector = rule.selectors[s].replace(/^\./, "");
88
149
  var styles = result[selector] = result[selector] || {};
89
- transformDecls(styles, rule.declarations, result);
150
+ transformDecls(styles, rule.declarations, result, keyframes);
90
151
  }
91
152
  if (rule.type == "media" && options != null && options.parseMediaQueries === true) {
92
153
  var parsed = _cssMediaquery["default"].parse(rule.media);
@@ -117,13 +178,17 @@ var transform = function transform(css, options) {
117
178
  result[media] = result[media] || {};
118
179
  var _selector = ruleRule.selectors[_s].replace(/^\./, "");
119
180
  var mediaStyles = result[media][_selector] = result[media][_selector] || {};
120
- transformDecls(mediaStyles, ruleRule.declarations, result);
181
+ transformDecls(mediaStyles, ruleRule.declarations, result, keyframes);
121
182
  }
122
183
  }
123
184
  }
124
185
  }
125
186
  if (result.__exportProps) {
126
- Object.assign(result, result.__exportProps);
187
+ if (Object.keys(result.__exportProps).length === 0) {
188
+ delete result.__exportProps;
189
+ } else {
190
+ Object.assign(result, result.__exportProps);
191
+ }
127
192
  }
128
193
  return result;
129
194
  };
@@ -152,13 +152,7 @@ describe("misc", function () {
152
152
  fontSize: 18,
153
153
  textAlign: "center",
154
154
  color: "#656656",
155
- shadowColor: "#fff",
156
- shadowOffset: {
157
- height: 20,
158
- width: 10
159
- },
160
- shadowRadius: 30,
161
- shadowOpacity: 1
155
+ boxShadow: "10px 20px 30px #fff"
162
156
  },
163
157
  container: {
164
158
  paddingBottom: 30,
@@ -1307,195 +1301,91 @@ describe("font", function () {
1307
1301
  });
1308
1302
  });
1309
1303
  describe("box-shadow", function () {
1310
- it("transforms box-shadow into shadow- properties", function () {
1304
+ it("transforms box-shadow", function () {
1311
1305
  expect((0, _index["default"])("\n .test {\n box-shadow: 10px 20px 30px red;\n }\n ")).toEqual({
1312
1306
  test: {
1313
- shadowOffset: {
1314
- width: 10,
1315
- height: 20
1316
- },
1317
- shadowRadius: 30,
1318
- shadowColor: "red",
1319
- shadowOpacity: 1
1307
+ boxShadow: "10px 20px 30px red"
1320
1308
  }
1321
1309
  });
1322
1310
  expect((0, _index["default"])("\n .test {\n box-shadow: 10px 20px 30px #f00;\n }\n ")).toEqual({
1323
1311
  test: {
1324
- shadowOffset: {
1325
- width: 10,
1326
- height: 20
1327
- },
1328
- shadowRadius: 30,
1329
- shadowColor: "#f00",
1330
- shadowOpacity: 1
1312
+ boxShadow: "10px 20px 30px #f00"
1331
1313
  }
1332
1314
  });
1333
1315
  });
1334
1316
  it("supports rgb values", function () {
1335
1317
  expect((0, _index["default"])("\n .test {\n box-shadow: 10px 20px 30px rgb(100, 100, 100);\n }\n ")).toEqual({
1336
1318
  test: {
1337
- shadowOffset: {
1338
- width: 10,
1339
- height: 20
1340
- },
1341
- shadowRadius: 30,
1342
- shadowColor: "rgb(100, 100, 100)",
1343
- shadowOpacity: 1
1319
+ boxShadow: "10px 20px 30px rgb(100, 100, 100)"
1344
1320
  }
1345
1321
  });
1346
1322
  });
1347
1323
  it("supports rgba values", function () {
1348
1324
  expect((0, _index["default"])("\n .test {\n box-shadow: 10px 20px 30px rgba(100, 100, 100, 0.5);\n }\n ")).toEqual({
1349
1325
  test: {
1350
- shadowOffset: {
1351
- width: 10,
1352
- height: 20
1353
- },
1354
- shadowRadius: 30,
1355
- shadowColor: "rgba(100, 100, 100, 0.5)",
1356
- shadowOpacity: 1
1326
+ boxShadow: "10px 20px 30px rgba(100, 100, 100, 0.5)"
1357
1327
  }
1358
1328
  });
1359
1329
  });
1360
1330
  it("supports box-shadow with hsl color", function () {
1361
1331
  expect((0, _index["default"])("\n .test {\n box-shadow: 10px 20px 30px hsl(120, 100%, 50%);\n }\n ")).toEqual({
1362
1332
  test: {
1363
- shadowOffset: {
1364
- width: 10,
1365
- height: 20
1366
- },
1367
- shadowRadius: 30,
1368
- shadowColor: "hsl(120, 100%, 50%)",
1369
- shadowOpacity: 1
1333
+ boxShadow: "10px 20px 30px hsl(120, 100%, 50%)"
1370
1334
  }
1371
1335
  });
1372
1336
  });
1373
1337
  it("supports box-shadow with hsla color", function () {
1374
1338
  expect((0, _index["default"])("\n .test {\n box-shadow: 10px 20px 30px hsla(120, 100%, 50%, 0.7);\n }\n ")).toEqual({
1375
1339
  test: {
1376
- shadowOffset: {
1377
- width: 10,
1378
- height: 20
1379
- },
1380
- shadowRadius: 30,
1381
- shadowColor: "hsla(120, 100%, 50%, 0.7)",
1382
- shadowOpacity: 1
1340
+ boxShadow: "10px 20px 30px hsla(120, 100%, 50%, 0.7)"
1383
1341
  }
1384
1342
  });
1385
1343
  });
1386
- it("trims values", function () {
1344
+ it("preserves spacing in values", function () {
1387
1345
  expect((0, _index["default"])("\n .test {\n box-shadow: 10px 20px 30px #f00 ;\n }\n ")).toEqual({
1388
1346
  test: {
1389
- shadowOffset: {
1390
- width: 10,
1391
- height: 20
1392
- },
1393
- shadowRadius: 30,
1394
- shadowColor: "#f00",
1395
- shadowOpacity: 1
1347
+ boxShadow: "10px 20px 30px #f00"
1396
1348
  }
1397
1349
  });
1398
1350
  });
1399
1351
  it("transforms box-shadow with 0 values", function () {
1400
1352
  expect((0, _index["default"])("\n .test {\n box-shadow: 0 0 1px red;\n }\n ")).toEqual({
1401
1353
  test: {
1402
- shadowOffset: {
1403
- width: 0,
1404
- height: 0
1405
- },
1406
- shadowRadius: 1,
1407
- shadowColor: "red",
1408
- shadowOpacity: 1
1354
+ boxShadow: "0 0 1px red"
1409
1355
  }
1410
1356
  });
1411
1357
  expect((0, _index["default"])("\n .test {\n box-shadow: 0 0 0 red;\n }\n ")).toEqual({
1412
1358
  test: {
1413
- shadowOffset: {
1414
- width: 0,
1415
- height: 0
1416
- },
1417
- shadowRadius: 0,
1418
- shadowColor: "red",
1419
- shadowOpacity: 1
1359
+ boxShadow: "0 0 0 red"
1420
1360
  }
1421
1361
  });
1422
1362
  expect((0, _index["default"])("\n .test {\n box-shadow: 1px 1px 0 #00f;\n }\n ")).toEqual({
1423
1363
  test: {
1424
- shadowOffset: {
1425
- width: 1,
1426
- height: 1
1427
- },
1428
- shadowRadius: 0,
1429
- shadowColor: "#00f",
1430
- shadowOpacity: 1
1364
+ boxShadow: "1px 1px 0 #00f"
1431
1365
  }
1432
1366
  });
1433
1367
  });
1434
1368
  it("transforms box-shadow without blur-radius", function () {
1435
1369
  expect((0, _index["default"])("\n .test {\n box-shadow: 10px 20px red;\n }\n ")).toEqual({
1436
1370
  test: {
1437
- shadowOffset: {
1438
- width: 10,
1439
- height: 20
1440
- },
1441
- shadowRadius: 0,
1442
- shadowColor: "red",
1443
- shadowOpacity: 1
1371
+ boxShadow: "10px 20px red"
1444
1372
  }
1445
1373
  });
1446
1374
  });
1447
1375
  it("transforms box-shadow without color", function () {
1448
1376
  expect((0, _index["default"])("\n .test {\n box-shadow: 10px 20px 30px;\n }\n ")).toEqual({
1449
1377
  test: {
1450
- shadowOffset: {
1451
- width: 10,
1452
- height: 20
1453
- },
1454
- shadowRadius: 30,
1455
- shadowColor: "black",
1456
- shadowOpacity: 1
1378
+ boxShadow: "10px 20px 30px"
1457
1379
  }
1458
1380
  });
1459
1381
  });
1460
1382
  it("transforms box-shadow without blur-radius, color", function () {
1461
1383
  expect((0, _index["default"])("\n .test {\n box-shadow: 10px 20px;\n }\n ")).toEqual({
1462
1384
  test: {
1463
- shadowOffset: {
1464
- width: 10,
1465
- height: 20
1466
- },
1467
- shadowRadius: 0,
1468
- shadowColor: "black",
1469
- shadowOpacity: 1
1385
+ boxShadow: "10px 20px"
1470
1386
  }
1471
1387
  });
1472
1388
  });
1473
- it("transforms box-shadow enforces offset to be present", function () {
1474
- expect(function () {
1475
- (0, _index["default"])("\n .test {\n box-shadow: red;\n }\n ");
1476
- }).toThrowError('Failed to parse declaration "boxShadow: red"');
1477
- });
1478
- it("transforms box-shadow and throws if multiple colors are used", function () {
1479
- expect(function () {
1480
- (0, _index["default"])("\n .test {\n box-shadow: 0 0 0 red yellow green blue;\n }\n ");
1481
- }).toThrowError('Failed to parse declaration "boxShadow: 0 0 0 red yellow green blue"');
1482
- });
1483
- it("transforms box-shadow and enforces offset-y if offset-x present", function () {
1484
- expect(function () {
1485
- (0, _index["default"])("\n .test {\n box-shadow: 10px;\n }\n ");
1486
- }).toThrowError('Failed to parse declaration "boxShadow: 10px"');
1487
- });
1488
- it("transforms box-shadow and enforces units for non 0 values", function () {
1489
- expect(function () {
1490
- (0, _index["default"])("\n .test {\n box-shadow: 10 20px 30px #f00;\n }\n ");
1491
- }).toThrowError('Failed to parse declaration "boxShadow: 10 20px 30px #f00"');
1492
- expect(function () {
1493
- (0, _index["default"])("\n .test {\n box-shadow: 10px 20;\n }\n ");
1494
- }).toThrowError('Failed to parse declaration "boxShadow: 10px 20"');
1495
- expect(function () {
1496
- (0, _index["default"])("\n .test {\n box-shadow: 20;\n }\n ");
1497
- }).toThrowError('Failed to parse declaration "boxShadow: 20"');
1498
- });
1499
1389
  });
1500
1390
  describe("text-shadow", function () {
1501
1391
  it("textShadow with all values", function () {
@@ -1588,13 +1478,7 @@ describe("rem unit", function () {
1588
1478
  }]
1589
1479
  },
1590
1480
  test2: {
1591
- shadowColor: "#fff",
1592
- shadowOffset: {
1593
- height: 32,
1594
- width: 16
1595
- },
1596
- shadowRadius: 48,
1597
- shadowOpacity: 1
1481
+ boxShadow: "16px 32px 48px #fff"
1598
1482
  }
1599
1483
  });
1600
1484
  });
@@ -2079,6 +1963,10 @@ describe("ICSS :export pseudo-selector", function () {
2079
1963
 
2080
1964
  it("should parse ICSS :export pseudo-selectors", function () {
2081
1965
  expect((0, _index["default"])("\n :export {\n whitecolor: #fcf5ed;\n test: 1px;\n }\n ")).toEqual({
1966
+ __exportProps: {
1967
+ whitecolor: "#fcf5ed",
1968
+ test: "1px"
1969
+ },
2082
1970
  whitecolor: "#fcf5ed",
2083
1971
  test: "1px"
2084
1972
  });
@@ -2088,6 +1976,11 @@ describe("ICSS :export pseudo-selector", function () {
2088
1976
  bar: {
2089
1977
  color: "blue"
2090
1978
  },
1979
+ __exportProps: {
1980
+ blackColor: "#000",
1981
+ whitecolor: "#fcf5ed",
1982
+ test: "1px"
1983
+ },
2091
1984
  blackColor: "#000",
2092
1985
  whitecolor: "#fcf5ed",
2093
1986
  test: "1px"
@@ -2098,6 +1991,9 @@ describe("ICSS :export pseudo-selector", function () {
2098
1991
  bar: {
2099
1992
  color: "blue"
2100
1993
  },
1994
+ __exportProps: {
1995
+ blackColor: "something is something"
1996
+ },
2101
1997
  blackColor: "something is something"
2102
1998
  });
2103
1999
  });
@@ -2106,12 +2002,20 @@ describe("ICSS :export pseudo-selector", function () {
2106
2002
  bar: {
2107
2003
  color: "blue"
2108
2004
  },
2005
+ __exportProps: {
2006
+ foo: "something",
2007
+ boo: "0"
2008
+ },
2109
2009
  foo: "something",
2110
2010
  boo: "0"
2111
2011
  });
2112
2012
  });
2113
2013
  it("should parse :export and support the same exportedKey with different case", function () {
2114
2014
  expect((0, _index["default"])("\n :export {\n whitecolor: #fcf5ed;\n WhiteColor: #fff;\n }\n ")).toEqual({
2015
+ __exportProps: {
2016
+ whitecolor: "#fcf5ed",
2017
+ WhiteColor: "#fff"
2018
+ },
2115
2019
  whitecolor: "#fcf5ed",
2116
2020
  WhiteColor: "#fff"
2117
2021
  });
@@ -2121,6 +2025,11 @@ describe("ICSS :export pseudo-selector", function () {
2121
2025
  foo: {
2122
2026
  color: "blue"
2123
2027
  },
2028
+ __exportProps: {
2029
+ whitecolor: "#fcf5ed",
2030
+ b: "0",
2031
+ test: "1px"
2032
+ },
2124
2033
  whitecolor: "#fcf5ed",
2125
2034
  b: "0",
2126
2035
  test: "1px"
@@ -2138,18 +2047,28 @@ describe("ICSS :export pseudo-selector", function () {
2138
2047
  foo: {
2139
2048
  color: "blue"
2140
2049
  },
2050
+ __exportProps: {
2051
+ bar: "2"
2052
+ },
2141
2053
  bar: "2"
2142
2054
  });
2143
2055
  expect((0, _index["default"])("\n :export {\n bar: 3;\n }\n\n .foo {\n color: blue;\n }\n\n :export {\n bar: 1;\n bar: 2;\n }\n ")).toEqual({
2144
2056
  foo: {
2145
2057
  color: "blue"
2146
2058
  },
2059
+ __exportProps: {
2060
+ bar: "2"
2061
+ },
2147
2062
  bar: "2"
2148
2063
  });
2149
2064
  expect((0, _index["default"])("\n :export {\n baz: 1;\n bar: 3;\n }\n\n .foo {\n color: blue;\n }\n\n :export {\n bar: 1;\n bar: 2;\n }\n ")).toEqual({
2150
2065
  foo: {
2151
2066
  color: "blue"
2152
2067
  },
2068
+ __exportProps: {
2069
+ baz: "1",
2070
+ bar: "2"
2071
+ },
2153
2072
  baz: "1",
2154
2073
  bar: "2"
2155
2074
  });
@@ -2206,4 +2125,128 @@ describe("::part() selectors", function () {
2206
2125
  }
2207
2126
  });
2208
2127
  });
2128
+ });
2129
+ describe("@keyframes rules", function () {
2130
+ it("transforms @keyframes rules with animation property", function () {
2131
+ expect((0, _index["default"])("\n .container {\n animation: slidein 3s ease-in-out infinite;\n background-color: #f00;\n }\n\n @keyframes slidein {\n from {\n transform: translateX(0%);\n }\n to {\n transform: translateX(100%);\n }\n }\n ", {
2132
+ parseKeyframes: true
2133
+ })).toEqual({
2134
+ container: {
2135
+ animationName: {
2136
+ from: {
2137
+ transform: [{
2138
+ translateX: "0%"
2139
+ }]
2140
+ },
2141
+ to: {
2142
+ transform: [{
2143
+ translateX: "100%"
2144
+ }]
2145
+ }
2146
+ },
2147
+ animationDuration: '3s',
2148
+ animationDelay: '0s',
2149
+ animationDirection: 'normal',
2150
+ animationFillMode: 'none',
2151
+ animationPlayState: 'running',
2152
+ animationTimingFunction: 'ease-in-out',
2153
+ animationIterationCount: 'infinite',
2154
+ backgroundColor: "#f00"
2155
+ }
2156
+ });
2157
+ });
2158
+ it("transforms animation-name property with @keyframes", function () {
2159
+ expect((0, _index["default"])("\n .container {\n animation-name: fadeIn;\n animation-duration: 2s;\n }\n\n @keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n ", {
2160
+ parseKeyframes: true
2161
+ })).toEqual({
2162
+ container: {
2163
+ animationName: {
2164
+ from: {
2165
+ opacity: 0
2166
+ },
2167
+ to: {
2168
+ opacity: 1
2169
+ }
2170
+ },
2171
+ animationDuration: '2s'
2172
+ }
2173
+ });
2174
+ });
2175
+ it("transforms animation property without @keyframes", function () {
2176
+ expect((0, _index["default"])("\n .container {\n animation: slidein 3s ease-in-out infinite;\n background-color: #f00;\n }\n ", {
2177
+ parseKeyframes: true
2178
+ })).toEqual({
2179
+ container: {
2180
+ animationName: 'slidein',
2181
+ animationDuration: '3s',
2182
+ animationDelay: '0s',
2183
+ animationDirection: 'normal',
2184
+ animationFillMode: 'none',
2185
+ animationPlayState: 'running',
2186
+ animationTimingFunction: 'ease-in-out',
2187
+ animationIterationCount: 'infinite',
2188
+ backgroundColor: "#f00"
2189
+ }
2190
+ });
2191
+ });
2192
+ it("transforms animation-name property without @keyframes", function () {
2193
+ expect((0, _index["default"])("\n .container {\n animation-name: fadeIn;\n animation-duration: 2s;\n }\n ", {
2194
+ parseKeyframes: true
2195
+ })).toEqual({
2196
+ container: {
2197
+ animationName: 'fadeIn',
2198
+ animationDuration: '2s'
2199
+ }
2200
+ });
2201
+ });
2202
+ it("transforms animation: none", function () {
2203
+ expect((0, _index["default"])("\n .container {\n animation: none;\n }\n ", {
2204
+ parseKeyframes: true
2205
+ })).toEqual({
2206
+ container: {
2207
+ animationName: 'none',
2208
+ animationDuration: '0s',
2209
+ animationDelay: '0s',
2210
+ animationDirection: 'normal',
2211
+ animationFillMode: 'none',
2212
+ animationPlayState: 'running',
2213
+ animationTimingFunction: 'ease',
2214
+ animationIterationCount: 1
2215
+ }
2216
+ });
2217
+ });
2218
+ it("transforms multiple animations with unused keyframe", function () {
2219
+ expect((0, _index["default"])("\n .container {\n animation: slidein 2s, fadeIn 1s ease-in;\n }\n\n @keyframes slidein {\n from {\n transform: translateX(0%);\n }\n to {\n transform: translateX(100%);\n }\n }\n\n @keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n\n @keyframes unused {\n from {\n color: red;\n }\n to {\n color: blue;\n }\n }\n ", {
2220
+ parseKeyframes: true
2221
+ })).toEqual({
2222
+ container: {
2223
+ animationName: [{
2224
+ from: {
2225
+ transform: [{
2226
+ translateX: "0%"
2227
+ }]
2228
+ },
2229
+ to: {
2230
+ transform: [{
2231
+ translateX: "100%"
2232
+ }]
2233
+ }
2234
+ }, {
2235
+ from: {
2236
+ opacity: 0
2237
+ },
2238
+ to: {
2239
+ opacity: 1
2240
+ }
2241
+ }],
2242
+ animationDuration: ['2s', '1s'],
2243
+ animationDelay: ['0s', '0s'],
2244
+ animationDirection: ['normal', 'normal'],
2245
+ animationFillMode: ['none', 'none'],
2246
+ animationPlayState: ['running', 'running'],
2247
+ animationTimingFunction: ['ease', 'ease-in'],
2248
+ animationIterationCount: [1, 1]
2249
+ }
2250
+ });
2251
+ });
2209
2252
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@startupjs/css-to-react-native-transform",
3
3
  "description": "Convert CSS text to a React Native stylesheet object",
4
- "version": "2.1.0-0",
4
+ "version": "2.1.0-2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -62,7 +62,7 @@
62
62
  "dependencies": {
63
63
  "css": "^3.0.0",
64
64
  "css-mediaquery": "^0.1.2",
65
- "css-to-react-native": "^3.2.0"
65
+ "@cssxjs/css-to-react-native": "3.2.0-1"
66
66
  },
67
67
  "repository": {
68
68
  "type": "git",
package/src/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import mediaQuery from "css-mediaquery";
2
- import transformCSS from "css-to-react-native";
2
+ import transformCSS from "@cssxjs/css-to-react-native";
3
3
  import parseCSS from "css/lib/parse";
4
4
  import {
5
5
  dimensionFeatures,
@@ -25,7 +25,54 @@ const shorthandBorderProps = [
25
25
  "border-style",
26
26
  ];
27
27
 
28
- const transformDecls = (styles, declarations, result) => {
28
+ /**
29
+ * Extracts @keyframes from CSS and returns the cleaned CSS and keyframes object
30
+ * @param {string} css - The input CSS string
31
+ * @returns {{css: string, keyframes: Object}} - Cleaned CSS and keyframes object
32
+ */
33
+ const extractKeyframes = (css) => {
34
+ const keyframes = {};
35
+ let cleanedCss = css;
36
+
37
+ // Find @keyframes by manually parsing to handle nested braces
38
+ let index = 0;
39
+ while (index < css.length) {
40
+ const keyframesMatch = css.slice(index).match(/@keyframes\s+([^\s{]+)\s*{/);
41
+ if (!keyframesMatch) break;
42
+
43
+ const startIndex = index + keyframesMatch.index;
44
+ const nameEndIndex = startIndex + keyframesMatch[0].length;
45
+ const name = keyframesMatch[1];
46
+
47
+ // Find the matching closing brace
48
+ let braceCount = 1;
49
+ let currentIndex = nameEndIndex;
50
+ while (currentIndex < css.length && braceCount > 0) {
51
+ if (css[currentIndex] === '{') {
52
+ braceCount++;
53
+ } else if (css[currentIndex] === '}') {
54
+ braceCount--;
55
+ }
56
+ currentIndex++;
57
+ }
58
+
59
+ if (braceCount === 0) {
60
+ // Extract the body (without the outer braces)
61
+ const body = css.slice(nameEndIndex, currentIndex - 1).trim();
62
+ keyframes[name] = body;
63
+
64
+ // Mark for removal by replacing with spaces to maintain positions
65
+ const fullKeyframe = css.slice(startIndex, currentIndex);
66
+ cleanedCss = cleanedCss.replace(fullKeyframe, '');
67
+ }
68
+
69
+ index = currentIndex;
70
+ }
71
+
72
+ return { css: cleanedCss, keyframes };
73
+ };
74
+
75
+ const transformDecls = (styles, declarations, result, keyframes) => {
29
76
  for (const d in declarations) {
30
77
  const declaration = declarations[d];
31
78
  if (declaration.type !== "declaration") continue;
@@ -64,6 +111,17 @@ const transformDecls = (styles, declarations, result) => {
64
111
  } else {
65
112
  Object.assign(styles, transformed);
66
113
  }
114
+ } else if (['animation', 'animation-name'].includes(property) && keyframes && Object.keys(keyframes).length > 0) {
115
+ // Pass all keyframes to transformCSS - it will figure out which ones to use
116
+ const keyframeDeclarations = [];
117
+ for (const name in keyframes) {
118
+ keyframeDeclarations.push(['@keyframes ' + name, keyframes[name]]);
119
+ }
120
+ const transformed = transformCSS([
121
+ ...keyframeDeclarations,
122
+ [property, value]
123
+ ]);
124
+ Object.assign(styles, transformed);
67
125
  } else {
68
126
  Object.assign(styles, transformCSS([[property, value]]));
69
127
  }
@@ -71,6 +129,12 @@ const transformDecls = (styles, declarations, result) => {
71
129
  };
72
130
 
73
131
  const transform = (css, options) => {
132
+ // Extract keyframes and store them separately, before parsing (remove them from css)
133
+ let keyframes;
134
+ if (options?.parseKeyframes) {
135
+ ({ css, keyframes } = extractKeyframes(css));
136
+ }
137
+
74
138
  const { stylesheet } = parseCSS(css);
75
139
  const rules = sortRules(stylesheet.rules);
76
140
 
@@ -126,7 +190,7 @@ const transform = (css, options) => {
126
190
 
127
191
  const selector = rule.selectors[s].replace(/^\./, "");
128
192
  const styles = (result[selector] = result[selector] || {});
129
- transformDecls(styles, rule.declarations, result);
193
+ transformDecls(styles, rule.declarations, result, keyframes);
130
194
  }
131
195
 
132
196
  if (
@@ -179,14 +243,18 @@ const transform = (css, options) => {
179
243
  const selector = ruleRule.selectors[s].replace(/^\./, "");
180
244
  const mediaStyles = (result[media][selector] =
181
245
  result[media][selector] || {});
182
- transformDecls(mediaStyles, ruleRule.declarations, result);
246
+ transformDecls(mediaStyles, ruleRule.declarations, result, keyframes);
183
247
  }
184
248
  }
185
249
  }
186
250
  }
187
251
 
188
252
  if (result.__exportProps) {
189
- Object.assign(result, result.__exportProps);
253
+ if (Object.keys(result.__exportProps).length === 0) {
254
+ delete result.__exportProps;
255
+ } else {
256
+ Object.assign(result, result.__exportProps);
257
+ }
190
258
  }
191
259
 
192
260
  return result;
package/src/index.spec.js CHANGED
@@ -268,10 +268,7 @@ describe("misc", () => {
268
268
  fontSize: 18,
269
269
  textAlign: "center",
270
270
  color: "#656656",
271
- shadowColor: "#fff",
272
- shadowOffset: { height: 20, width: 10 },
273
- shadowRadius: 30,
274
- shadowOpacity: 1,
271
+ boxShadow: "10px 20px 30px #fff",
275
272
  },
276
273
  container: {
277
274
  paddingBottom: 30,
@@ -2210,7 +2207,7 @@ describe("font", () => {
2210
2207
  });
2211
2208
 
2212
2209
  describe("box-shadow", () => {
2213
- it("transforms box-shadow into shadow- properties", () => {
2210
+ it("transforms box-shadow", () => {
2214
2211
  expect(
2215
2212
  transform(`
2216
2213
  .test {
@@ -2219,10 +2216,7 @@ describe("box-shadow", () => {
2219
2216
  `),
2220
2217
  ).toEqual({
2221
2218
  test: {
2222
- shadowOffset: { width: 10, height: 20 },
2223
- shadowRadius: 30,
2224
- shadowColor: "red",
2225
- shadowOpacity: 1,
2219
+ boxShadow: "10px 20px 30px red",
2226
2220
  },
2227
2221
  });
2228
2222
  expect(
@@ -2233,10 +2227,7 @@ describe("box-shadow", () => {
2233
2227
  `),
2234
2228
  ).toEqual({
2235
2229
  test: {
2236
- shadowOffset: { width: 10, height: 20 },
2237
- shadowRadius: 30,
2238
- shadowColor: "#f00",
2239
- shadowOpacity: 1,
2230
+ boxShadow: "10px 20px 30px #f00",
2240
2231
  },
2241
2232
  });
2242
2233
  });
@@ -2250,10 +2241,7 @@ describe("box-shadow", () => {
2250
2241
  `),
2251
2242
  ).toEqual({
2252
2243
  test: {
2253
- shadowOffset: { width: 10, height: 20 },
2254
- shadowRadius: 30,
2255
- shadowColor: "rgb(100, 100, 100)",
2256
- shadowOpacity: 1,
2244
+ boxShadow: "10px 20px 30px rgb(100, 100, 100)",
2257
2245
  },
2258
2246
  });
2259
2247
  });
@@ -2267,10 +2255,7 @@ describe("box-shadow", () => {
2267
2255
  `),
2268
2256
  ).toEqual({
2269
2257
  test: {
2270
- shadowOffset: { width: 10, height: 20 },
2271
- shadowRadius: 30,
2272
- shadowColor: "rgba(100, 100, 100, 0.5)",
2273
- shadowOpacity: 1,
2258
+ boxShadow: "10px 20px 30px rgba(100, 100, 100, 0.5)",
2274
2259
  },
2275
2260
  });
2276
2261
  });
@@ -2284,10 +2269,7 @@ describe("box-shadow", () => {
2284
2269
  `),
2285
2270
  ).toEqual({
2286
2271
  test: {
2287
- shadowOffset: { width: 10, height: 20 },
2288
- shadowRadius: 30,
2289
- shadowColor: "hsl(120, 100%, 50%)",
2290
- shadowOpacity: 1,
2272
+ boxShadow: "10px 20px 30px hsl(120, 100%, 50%)",
2291
2273
  },
2292
2274
  });
2293
2275
  });
@@ -2301,15 +2283,12 @@ describe("box-shadow", () => {
2301
2283
  `),
2302
2284
  ).toEqual({
2303
2285
  test: {
2304
- shadowOffset: { width: 10, height: 20 },
2305
- shadowRadius: 30,
2306
- shadowColor: "hsla(120, 100%, 50%, 0.7)",
2307
- shadowOpacity: 1,
2286
+ boxShadow: "10px 20px 30px hsla(120, 100%, 50%, 0.7)",
2308
2287
  },
2309
2288
  });
2310
2289
  });
2311
2290
 
2312
- it("trims values", () => {
2291
+ it("preserves spacing in values", () => {
2313
2292
  expect(
2314
2293
  transform(`
2315
2294
  .test {
@@ -2318,10 +2297,7 @@ describe("box-shadow", () => {
2318
2297
  `),
2319
2298
  ).toEqual({
2320
2299
  test: {
2321
- shadowOffset: { width: 10, height: 20 },
2322
- shadowRadius: 30,
2323
- shadowColor: "#f00",
2324
- shadowOpacity: 1,
2300
+ boxShadow: "10px 20px 30px #f00",
2325
2301
  },
2326
2302
  });
2327
2303
  });
@@ -2335,10 +2311,7 @@ describe("box-shadow", () => {
2335
2311
  `),
2336
2312
  ).toEqual({
2337
2313
  test: {
2338
- shadowOffset: { width: 0, height: 0 },
2339
- shadowRadius: 1,
2340
- shadowColor: "red",
2341
- shadowOpacity: 1,
2314
+ boxShadow: "0 0 1px red",
2342
2315
  },
2343
2316
  });
2344
2317
  expect(
@@ -2349,10 +2322,7 @@ describe("box-shadow", () => {
2349
2322
  `),
2350
2323
  ).toEqual({
2351
2324
  test: {
2352
- shadowOffset: { width: 0, height: 0 },
2353
- shadowRadius: 0,
2354
- shadowColor: "red",
2355
- shadowOpacity: 1,
2325
+ boxShadow: "0 0 0 red",
2356
2326
  },
2357
2327
  });
2358
2328
  expect(
@@ -2363,10 +2333,7 @@ describe("box-shadow", () => {
2363
2333
  `),
2364
2334
  ).toEqual({
2365
2335
  test: {
2366
- shadowOffset: { width: 1, height: 1 },
2367
- shadowRadius: 0,
2368
- shadowColor: "#00f",
2369
- shadowOpacity: 1,
2336
+ boxShadow: "1px 1px 0 #00f",
2370
2337
  },
2371
2338
  });
2372
2339
  });
@@ -2380,10 +2347,7 @@ describe("box-shadow", () => {
2380
2347
  `),
2381
2348
  ).toEqual({
2382
2349
  test: {
2383
- shadowOffset: { width: 10, height: 20 },
2384
- shadowRadius: 0,
2385
- shadowColor: "red",
2386
- shadowOpacity: 1,
2350
+ boxShadow: "10px 20px red",
2387
2351
  },
2388
2352
  });
2389
2353
  });
@@ -2397,10 +2361,7 @@ describe("box-shadow", () => {
2397
2361
  `),
2398
2362
  ).toEqual({
2399
2363
  test: {
2400
- shadowOffset: { width: 10, height: 20 },
2401
- shadowRadius: 30,
2402
- shadowColor: "black",
2403
- shadowOpacity: 1,
2364
+ boxShadow: "10px 20px 30px",
2404
2365
  },
2405
2366
  });
2406
2367
  });
@@ -2414,71 +2375,11 @@ describe("box-shadow", () => {
2414
2375
  `),
2415
2376
  ).toEqual({
2416
2377
  test: {
2417
- shadowOffset: { width: 10, height: 20 },
2418
- shadowRadius: 0,
2419
- shadowColor: "black",
2420
- shadowOpacity: 1,
2378
+ boxShadow: "10px 20px",
2421
2379
  },
2422
2380
  });
2423
2381
  });
2424
2382
 
2425
- it("transforms box-shadow enforces offset to be present", () => {
2426
- expect(() => {
2427
- transform(`
2428
- .test {
2429
- box-shadow: red;
2430
- }
2431
- `);
2432
- }).toThrowError('Failed to parse declaration "boxShadow: red"');
2433
- });
2434
-
2435
- it("transforms box-shadow and throws if multiple colors are used", () => {
2436
- expect(() => {
2437
- transform(`
2438
- .test {
2439
- box-shadow: 0 0 0 red yellow green blue;
2440
- }
2441
- `);
2442
- }).toThrowError(
2443
- 'Failed to parse declaration "boxShadow: 0 0 0 red yellow green blue"',
2444
- );
2445
- });
2446
-
2447
- it("transforms box-shadow and enforces offset-y if offset-x present", () => {
2448
- expect(() => {
2449
- transform(`
2450
- .test {
2451
- box-shadow: 10px;
2452
- }
2453
- `);
2454
- }).toThrowError('Failed to parse declaration "boxShadow: 10px"');
2455
- });
2456
-
2457
- it("transforms box-shadow and enforces units for non 0 values", () => {
2458
- expect(() => {
2459
- transform(`
2460
- .test {
2461
- box-shadow: 10 20px 30px #f00;
2462
- }
2463
- `);
2464
- }).toThrowError(
2465
- 'Failed to parse declaration "boxShadow: 10 20px 30px #f00"',
2466
- );
2467
- expect(() => {
2468
- transform(`
2469
- .test {
2470
- box-shadow: 10px 20;
2471
- }
2472
- `);
2473
- }).toThrowError('Failed to parse declaration "boxShadow: 10px 20"');
2474
- expect(() => {
2475
- transform(`
2476
- .test {
2477
- box-shadow: 20;
2478
- }
2479
- `);
2480
- }).toThrowError('Failed to parse declaration "boxShadow: 20"');
2481
- });
2482
2383
  });
2483
2384
 
2484
2385
  describe("text-shadow", () => {
@@ -2627,10 +2528,7 @@ describe("rem unit", () => {
2627
2528
  transform: [{ translateY: 32 }, { translateX: 16 }],
2628
2529
  },
2629
2530
  test2: {
2630
- shadowColor: "#fff",
2631
- shadowOffset: { height: 32, width: 16 },
2632
- shadowRadius: 48,
2633
- shadowOpacity: 1,
2531
+ boxShadow: "16px 32px 48px #fff",
2634
2532
  },
2635
2533
  });
2636
2534
  });
@@ -3471,6 +3369,10 @@ describe("ICSS :export pseudo-selector", () => {
3471
3369
  }
3472
3370
  `),
3473
3371
  ).toEqual({
3372
+ __exportProps: {
3373
+ whitecolor: "#fcf5ed",
3374
+ test: "1px",
3375
+ },
3474
3376
  whitecolor: "#fcf5ed",
3475
3377
  test: "1px",
3476
3378
  });
@@ -3497,6 +3399,11 @@ describe("ICSS :export pseudo-selector", () => {
3497
3399
  bar: {
3498
3400
  color: "blue",
3499
3401
  },
3402
+ __exportProps: {
3403
+ blackColor: "#000",
3404
+ whitecolor: "#fcf5ed",
3405
+ test: "1px",
3406
+ },
3500
3407
  blackColor: "#000",
3501
3408
  whitecolor: "#fcf5ed",
3502
3409
  test: "1px",
@@ -3518,6 +3425,9 @@ describe("ICSS :export pseudo-selector", () => {
3518
3425
  bar: {
3519
3426
  color: "blue",
3520
3427
  },
3428
+ __exportProps: {
3429
+ blackColor: "something is something",
3430
+ },
3521
3431
  blackColor: "something is something",
3522
3432
  });
3523
3433
  });
@@ -3538,6 +3448,10 @@ describe("ICSS :export pseudo-selector", () => {
3538
3448
  bar: {
3539
3449
  color: "blue",
3540
3450
  },
3451
+ __exportProps: {
3452
+ foo: "something",
3453
+ boo: "0",
3454
+ },
3541
3455
  foo: "something",
3542
3456
  boo: "0",
3543
3457
  });
@@ -3552,6 +3466,10 @@ describe("ICSS :export pseudo-selector", () => {
3552
3466
  }
3553
3467
  `),
3554
3468
  ).toEqual({
3469
+ __exportProps: {
3470
+ whitecolor: "#fcf5ed",
3471
+ WhiteColor: "#fff",
3472
+ },
3555
3473
  whitecolor: "#fcf5ed",
3556
3474
  WhiteColor: "#fff",
3557
3475
  });
@@ -3574,6 +3492,11 @@ describe("ICSS :export pseudo-selector", () => {
3574
3492
  foo: {
3575
3493
  color: "blue",
3576
3494
  },
3495
+ __exportProps: {
3496
+ whitecolor: "#fcf5ed",
3497
+ b: "0",
3498
+ test: "1px",
3499
+ },
3577
3500
  whitecolor: "#fcf5ed",
3578
3501
  b: "0",
3579
3502
  test: "1px",
@@ -3613,6 +3536,9 @@ describe("ICSS :export pseudo-selector", () => {
3613
3536
  foo: {
3614
3537
  color: "blue",
3615
3538
  },
3539
+ __exportProps: {
3540
+ bar: "2",
3541
+ },
3616
3542
  bar: "2",
3617
3543
  });
3618
3544
  expect(
@@ -3634,6 +3560,9 @@ describe("ICSS :export pseudo-selector", () => {
3634
3560
  foo: {
3635
3561
  color: "blue",
3636
3562
  },
3563
+ __exportProps: {
3564
+ bar: "2",
3565
+ },
3637
3566
  bar: "2",
3638
3567
  });
3639
3568
  expect(
@@ -3656,6 +3585,10 @@ describe("ICSS :export pseudo-selector", () => {
3656
3585
  foo: {
3657
3586
  color: "blue",
3658
3587
  },
3588
+ __exportProps: {
3589
+ baz: "1",
3590
+ bar: "2",
3591
+ },
3659
3592
  baz: "1",
3660
3593
  bar: "2",
3661
3594
  });
@@ -3810,3 +3743,215 @@ describe("::part() selectors", () => {
3810
3743
  });
3811
3744
  });
3812
3745
  });
3746
+
3747
+ describe("@keyframes rules", () => {
3748
+ it("transforms @keyframes rules with animation property", () => {
3749
+ expect(
3750
+ transform(
3751
+ `
3752
+ .container {
3753
+ animation: slidein 3s ease-in-out infinite;
3754
+ background-color: #f00;
3755
+ }
3756
+
3757
+ @keyframes slidein {
3758
+ from {
3759
+ transform: translateX(0%);
3760
+ }
3761
+ to {
3762
+ transform: translateX(100%);
3763
+ }
3764
+ }
3765
+ `,
3766
+ {
3767
+ parseKeyframes: true,
3768
+ },
3769
+ ),
3770
+ ).toEqual({
3771
+ container: {
3772
+ animationName: {
3773
+ from: { transform: [{ translateX: "0%" }] },
3774
+ to: { transform: [{ translateX: "100%" }] },
3775
+ },
3776
+ animationDuration: '3s',
3777
+ animationDelay: '0s',
3778
+ animationDirection: 'normal',
3779
+ animationFillMode: 'none',
3780
+ animationPlayState: 'running',
3781
+ animationTimingFunction: 'ease-in-out',
3782
+ animationIterationCount: 'infinite',
3783
+ backgroundColor: "#f00",
3784
+ }
3785
+ });
3786
+ });
3787
+
3788
+ it("transforms animation-name property with @keyframes", () => {
3789
+ expect(
3790
+ transform(
3791
+ `
3792
+ .container {
3793
+ animation-name: fadeIn;
3794
+ animation-duration: 2s;
3795
+ }
3796
+
3797
+ @keyframes fadeIn {
3798
+ from {
3799
+ opacity: 0;
3800
+ }
3801
+ to {
3802
+ opacity: 1;
3803
+ }
3804
+ }
3805
+ `,
3806
+ {
3807
+ parseKeyframes: true,
3808
+ },
3809
+ ),
3810
+ ).toEqual({
3811
+ container: {
3812
+ animationName: {
3813
+ from: { opacity: 0 },
3814
+ to: { opacity: 1 },
3815
+ },
3816
+ animationDuration: '2s',
3817
+ }
3818
+ });
3819
+ });
3820
+
3821
+ it("transforms animation property without @keyframes", () => {
3822
+ expect(
3823
+ transform(
3824
+ `
3825
+ .container {
3826
+ animation: slidein 3s ease-in-out infinite;
3827
+ background-color: #f00;
3828
+ }
3829
+ `,
3830
+ {
3831
+ parseKeyframes: true,
3832
+ },
3833
+ ),
3834
+ ).toEqual({
3835
+ container: {
3836
+ animationName: 'slidein',
3837
+ animationDuration: '3s',
3838
+ animationDelay: '0s',
3839
+ animationDirection: 'normal',
3840
+ animationFillMode: 'none',
3841
+ animationPlayState: 'running',
3842
+ animationTimingFunction: 'ease-in-out',
3843
+ animationIterationCount: 'infinite',
3844
+ backgroundColor: "#f00",
3845
+ }
3846
+ });
3847
+ });
3848
+
3849
+ it("transforms animation-name property without @keyframes", () => {
3850
+ expect(
3851
+ transform(
3852
+ `
3853
+ .container {
3854
+ animation-name: fadeIn;
3855
+ animation-duration: 2s;
3856
+ }
3857
+ `,
3858
+ {
3859
+ parseKeyframes: true,
3860
+ },
3861
+ ),
3862
+ ).toEqual({
3863
+ container: {
3864
+ animationName: 'fadeIn',
3865
+ animationDuration: '2s',
3866
+ }
3867
+ });
3868
+ });
3869
+
3870
+ it("transforms animation: none", () => {
3871
+ expect(
3872
+ transform(
3873
+ `
3874
+ .container {
3875
+ animation: none;
3876
+ }
3877
+ `,
3878
+ {
3879
+ parseKeyframes: true,
3880
+ },
3881
+ ),
3882
+ ).toEqual({
3883
+ container: {
3884
+ animationName: 'none',
3885
+ animationDuration: '0s',
3886
+ animationDelay: '0s',
3887
+ animationDirection: 'normal',
3888
+ animationFillMode: 'none',
3889
+ animationPlayState: 'running',
3890
+ animationTimingFunction: 'ease',
3891
+ animationIterationCount: 1,
3892
+ }
3893
+ });
3894
+ });
3895
+
3896
+ it("transforms multiple animations with unused keyframe", () => {
3897
+ expect(
3898
+ transform(
3899
+ `
3900
+ .container {
3901
+ animation: slidein 2s, fadeIn 1s ease-in;
3902
+ }
3903
+
3904
+ @keyframes slidein {
3905
+ from {
3906
+ transform: translateX(0%);
3907
+ }
3908
+ to {
3909
+ transform: translateX(100%);
3910
+ }
3911
+ }
3912
+
3913
+ @keyframes fadeIn {
3914
+ from {
3915
+ opacity: 0;
3916
+ }
3917
+ to {
3918
+ opacity: 1;
3919
+ }
3920
+ }
3921
+
3922
+ @keyframes unused {
3923
+ from {
3924
+ color: red;
3925
+ }
3926
+ to {
3927
+ color: blue;
3928
+ }
3929
+ }
3930
+ `,
3931
+ {
3932
+ parseKeyframes: true,
3933
+ },
3934
+ ),
3935
+ ).toEqual({
3936
+ container: {
3937
+ animationName: [
3938
+ {
3939
+ from: { transform: [{ translateX: "0%" }] },
3940
+ to: { transform: [{ translateX: "100%" }] },
3941
+ },
3942
+ {
3943
+ from: { opacity: 0 },
3944
+ to: { opacity: 1 },
3945
+ }
3946
+ ],
3947
+ animationDuration: ['2s', '1s'],
3948
+ animationDelay: ['0s', '0s'],
3949
+ animationDirection: ['normal', 'normal'],
3950
+ animationFillMode: ['none', 'none'],
3951
+ animationPlayState: ['running', 'running'],
3952
+ animationTimingFunction: ['ease', 'ease-in'],
3953
+ animationIterationCount: [1, 1],
3954
+ }
3955
+ });
3956
+ });
3957
+ });