@compiled/react 0.12.0 → 0.13.0

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.
Files changed (130) hide show
  1. package/dist/browser/css/index.js +1 -5
  2. package/dist/browser/css/index.js.map +1 -1
  3. package/dist/browser/index.js +1 -1
  4. package/dist/browser/index.js.map +1 -1
  5. package/dist/browser/keyframes/__fixtures__/index.js +2 -2
  6. package/dist/browser/keyframes/__fixtures__/index.js.map +1 -1
  7. package/dist/browser/keyframes/index.js +1 -5
  8. package/dist/browser/keyframes/index.js.map +1 -1
  9. package/dist/browser/runtime/ac.d.ts +47 -0
  10. package/dist/browser/runtime/ac.js +118 -0
  11. package/dist/browser/runtime/ac.js.flow +56 -0
  12. package/dist/browser/runtime/ac.js.map +1 -0
  13. package/dist/browser/runtime/ax.js +17 -18
  14. package/dist/browser/runtime/ax.js.map +1 -1
  15. package/dist/browser/runtime/cache.js +1 -1
  16. package/dist/browser/runtime/cache.js.map +1 -1
  17. package/dist/browser/runtime/dev-warnings.js +19 -21
  18. package/dist/browser/runtime/dev-warnings.js.map +1 -1
  19. package/dist/browser/runtime/index.d.ts +1 -0
  20. package/dist/browser/runtime/index.js +9 -0
  21. package/dist/browser/runtime/index.js.flow +1 -0
  22. package/dist/browser/runtime/index.js.map +1 -1
  23. package/dist/browser/runtime/is-server-environment.js +4 -6
  24. package/dist/browser/runtime/is-server-environment.js.map +1 -1
  25. package/dist/browser/runtime/sheet.js +11 -11
  26. package/dist/browser/runtime/sheet.js.map +1 -1
  27. package/dist/browser/runtime/style-cache.js +6 -6
  28. package/dist/browser/runtime/style-cache.js.map +1 -1
  29. package/dist/browser/runtime/style.js +10 -10
  30. package/dist/browser/runtime/style.js.map +1 -1
  31. package/dist/browser/runtime.d.ts +1 -1
  32. package/dist/browser/runtime.js +1 -1
  33. package/dist/browser/runtime.js.flow +1 -1
  34. package/dist/browser/runtime.js.map +1 -1
  35. package/dist/browser/styled/index.js +3 -3
  36. package/dist/browser/styled/index.js.map +1 -1
  37. package/dist/browser/utils/error.js +18 -2
  38. package/dist/browser/utils/error.js.map +1 -1
  39. package/dist/cjs/class-names/index.js +1 -1
  40. package/dist/cjs/class-names/index.js.map +1 -1
  41. package/dist/cjs/css/index.js +2 -6
  42. package/dist/cjs/css/index.js.map +1 -1
  43. package/dist/cjs/index.js +1 -1
  44. package/dist/cjs/index.js.map +1 -1
  45. package/dist/cjs/keyframes/__fixtures__/index.js +1 -1
  46. package/dist/cjs/keyframes/__fixtures__/index.js.map +1 -1
  47. package/dist/cjs/keyframes/index.js +2 -6
  48. package/dist/cjs/keyframes/index.js.map +1 -1
  49. package/dist/cjs/runtime/ac.d.ts +47 -0
  50. package/dist/cjs/runtime/ac.js +125 -0
  51. package/dist/cjs/runtime/ac.js.flow +56 -0
  52. package/dist/cjs/runtime/ac.js.map +1 -0
  53. package/dist/cjs/runtime/ax.js +17 -18
  54. package/dist/cjs/runtime/ax.js.map +1 -1
  55. package/dist/cjs/runtime/cache.js +1 -1
  56. package/dist/cjs/runtime/cache.js.map +1 -1
  57. package/dist/cjs/runtime/dev-warnings.js +19 -21
  58. package/dist/cjs/runtime/dev-warnings.js.map +1 -1
  59. package/dist/cjs/runtime/index.d.ts +1 -0
  60. package/dist/cjs/runtime/index.js +12 -1
  61. package/dist/cjs/runtime/index.js.flow +1 -0
  62. package/dist/cjs/runtime/index.js.map +1 -1
  63. package/dist/cjs/runtime/is-server-environment.js +4 -6
  64. package/dist/cjs/runtime/is-server-environment.js.map +1 -1
  65. package/dist/cjs/runtime/sheet.js +11 -11
  66. package/dist/cjs/runtime/sheet.js.map +1 -1
  67. package/dist/cjs/runtime/style-cache.js +10 -10
  68. package/dist/cjs/runtime/style-cache.js.map +1 -1
  69. package/dist/cjs/runtime/style.js +15 -15
  70. package/dist/cjs/runtime/style.js.map +1 -1
  71. package/dist/cjs/runtime.d.ts +1 -1
  72. package/dist/cjs/runtime.js +3 -1
  73. package/dist/cjs/runtime.js.flow +1 -1
  74. package/dist/cjs/runtime.js.map +1 -1
  75. package/dist/cjs/styled/index.js +3 -3
  76. package/dist/cjs/styled/index.js.map +1 -1
  77. package/dist/cjs/utils/error.js +18 -2
  78. package/dist/cjs/utils/error.js.map +1 -1
  79. package/dist/esm/css/index.js +1 -5
  80. package/dist/esm/css/index.js.map +1 -1
  81. package/dist/esm/index.js +1 -1
  82. package/dist/esm/index.js.map +1 -1
  83. package/dist/esm/keyframes/__fixtures__/index.js +2 -2
  84. package/dist/esm/keyframes/__fixtures__/index.js.map +1 -1
  85. package/dist/esm/keyframes/index.js +1 -5
  86. package/dist/esm/keyframes/index.js.map +1 -1
  87. package/dist/esm/runtime/ac.d.ts +47 -0
  88. package/dist/esm/runtime/ac.js +118 -0
  89. package/dist/esm/runtime/ac.js.flow +56 -0
  90. package/dist/esm/runtime/ac.js.map +1 -0
  91. package/dist/esm/runtime/ax.js +17 -18
  92. package/dist/esm/runtime/ax.js.map +1 -1
  93. package/dist/esm/runtime/cache.js +1 -1
  94. package/dist/esm/runtime/cache.js.map +1 -1
  95. package/dist/esm/runtime/dev-warnings.js +19 -21
  96. package/dist/esm/runtime/dev-warnings.js.map +1 -1
  97. package/dist/esm/runtime/index.d.ts +1 -0
  98. package/dist/esm/runtime/index.js +9 -0
  99. package/dist/esm/runtime/index.js.flow +1 -0
  100. package/dist/esm/runtime/index.js.map +1 -1
  101. package/dist/esm/runtime/is-server-environment.js +4 -6
  102. package/dist/esm/runtime/is-server-environment.js.map +1 -1
  103. package/dist/esm/runtime/sheet.js +11 -11
  104. package/dist/esm/runtime/sheet.js.map +1 -1
  105. package/dist/esm/runtime/style-cache.js +6 -6
  106. package/dist/esm/runtime/style-cache.js.map +1 -1
  107. package/dist/esm/runtime/style.js +10 -10
  108. package/dist/esm/runtime/style.js.map +1 -1
  109. package/dist/esm/runtime.d.ts +1 -1
  110. package/dist/esm/runtime.js +1 -1
  111. package/dist/esm/runtime.js.flow +1 -1
  112. package/dist/esm/runtime.js.map +1 -1
  113. package/dist/esm/styled/index.js +3 -3
  114. package/dist/esm/styled/index.js.map +1 -1
  115. package/dist/esm/utils/error.js +18 -2
  116. package/dist/esm/utils/error.js.map +1 -1
  117. package/package.json +7 -3
  118. package/src/__tests__/server-side-hydrate.test.tsx +1 -1
  119. package/src/global.d.ts +7 -0
  120. package/src/runtime/__perf__/ac.test.ts +97 -0
  121. package/src/runtime/__perf__/ax.test.ts +0 -20
  122. package/src/runtime/__tests__/ac.test.ts +112 -0
  123. package/src/runtime/__tests__/ax.test.ts +2 -27
  124. package/src/runtime/ac.js.flow +56 -0
  125. package/src/runtime/ac.ts +143 -0
  126. package/src/runtime/ax.ts +9 -7
  127. package/src/runtime/index.js.flow +1 -0
  128. package/src/runtime/index.ts +12 -0
  129. package/src/runtime.js.flow +1 -1
  130. package/src/runtime.ts +1 -1
@@ -1,4 +1,20 @@
1
- export var createSetupError = function () {
2
- return new Error("\n \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557\n\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\n\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551\n\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\n\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\n \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u255D\n\n @compiled/react\n\n Code was executed when it shouldn't have. This could have happened because:\n\n 1. You haven't configured a transformer yet. Visit https://compiledcssinjs.com/docs/installation and follow the instructions.\n 2. You have duplicate versions of React and hooks are blowing up. You need to de-duplicate your dependencies.\n\n Good luck!\n");
1
+ export const createSetupError = () => {
2
+ return new Error(`
3
+ ██████╗ ██████╗ ███╗ ███╗██████╗ ██╗██╗ ███████╗██████╗
4
+ ██╔════╝██╔═══██╗████╗ ████║██╔══██╗██║██║ ██╔════╝██╔══██╗
5
+ ██║ ██║ ██║██╔████╔██║██████╔╝██║██║ █████╗ ██║ ██║
6
+ ██║ ██║ ██║██║╚██╔╝██║██╔═══╝ ██║██║ ██╔══╝ ██║ ██║
7
+ ╚██████╗╚██████╔╝██║ ╚═╝ ██║██║ ██║███████╗███████╗██████╔╝
8
+ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝╚═════╝
9
+
10
+ @compiled/react
11
+
12
+ Code was executed when it shouldn't have. This could have happened because:
13
+
14
+ 1. You haven't configured a transformer yet. Visit https://compiledcssinjs.com/docs/installation and follow the instructions.
15
+ 2. You have duplicate versions of React and hooks are blowing up. You need to de-duplicate your dependencies.
16
+
17
+ Good luck!
18
+ `);
3
19
  };
4
20
  //# sourceMappingURL=error.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"error.js","sourceRoot":"","sources":["../../../src/utils/error.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,IAAM,gBAAgB,GAAG;IAC9B,OAAO,IAAI,KAAK,CAAC,6tEAgBlB,CAAC,CAAC;AACH,CAAC,CAAC"}
1
+ {"version":3,"file":"error.js","sourceRoot":"","sources":["../../../src/utils/error.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAU,EAAE;IAC1C,OAAO,IAAI,KAAK,CAAC;;;;;;;;;;;;;;;;CAgBlB,CAAC,CAAC;AACH,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@compiled/react",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "A familiar and performant compile time CSS-in-JS library for React.",
5
5
  "keywords": [
6
6
  "compiled",
@@ -17,7 +17,11 @@
17
17
  },
18
18
  "license": "Apache-2.0",
19
19
  "author": "Michael Dougall",
20
- "sideEffects": false,
20
+ "sideEffects": [
21
+ "./dist/browser/runtime/index.js",
22
+ "./dist/cjs/runtime/index.js",
23
+ "./dist/esm/runtime/index.js"
24
+ ],
21
25
  "exports": {
22
26
  ".": {
23
27
  "import": [
@@ -78,7 +82,7 @@
78
82
  "@compiled/benchmark": "^1.1.0",
79
83
  "@testing-library/react": "^12.1.5",
80
84
  "@types/jsdom": "^16.2.15",
81
- "@types/react-dom": "^17.0.18",
85
+ "@types/react-dom": "^17.0.19",
82
86
  "jsdom": "^19.0.0",
83
87
  "react": "^17.0.2",
84
88
  "react-dom": "^17.0.2"
@@ -16,7 +16,7 @@ describe('server side hydrate', () => {
16
16
  jest.resetModules();
17
17
  // We need to force this module to re-instantiate because on the client
18
18
  // when it does it will move all found SSRd style elements to the head.
19
- require('../runtime');
19
+ require('../runtime/style-cache');
20
20
  };
21
21
 
22
22
  const appendHTML = (markup: string) => {
@@ -0,0 +1,7 @@
1
+ export {};
2
+
3
+ declare global {
4
+ interface Window {
5
+ __COMPILED_IMPORTED__: undefined | true;
6
+ }
7
+ }
@@ -0,0 +1,97 @@
1
+ import { runBenchmark } from '@compiled/benchmark';
2
+
3
+ import { ac } from '../ac';
4
+ import ax from '../ax';
5
+
6
+ describe('ac vs ax benchmark', () => {
7
+ const arr = [
8
+ '_19itglyw',
9
+ '_2rko1l7b',
10
+ '_ca0qftgi',
11
+ '_u5f319bv',
12
+ '_n3tdftgi',
13
+ '_19bv19bv',
14
+ '_bfhk1mzw',
15
+ '_syazu67f',
16
+ '_k48p1nn1',
17
+ '_ect41kw7',
18
+ '_1wybdlk8',
19
+ '_irr3mlcl',
20
+ '_1di6vctu',
21
+ // `undefined` is an acceptable parameter so we want to include it in the test case.
22
+ // Example: ax(['aaaabbbb', foo() && "aaaacccc"])
23
+ undefined,
24
+ ];
25
+
26
+ // Remove undefined and join the strings
27
+ const str = arr.slice(0, -1).join(' ');
28
+
29
+ const arrWithCompressedClassNames = arr.map((item) =>
30
+ item ? `${item.slice(0, 4)}_${item.slice(8)}` : item
31
+ );
32
+
33
+ const strWithCompressedClassNames = arr
34
+ .map((item) => (item ? `${item.slice(0, 4)}_${item.slice(8)}` : item))
35
+ .slice(0, -1)
36
+ .join(' ');
37
+
38
+ it('compares ax array with ac array', async () => {
39
+ // Remove undefined and join the strings
40
+ const benchmark = await runBenchmark('ax', [
41
+ {
42
+ name: 'ax() array',
43
+ fn: () => ax(arr),
44
+ },
45
+ {
46
+ name: 'ac() array with compressed class names',
47
+ fn: () => {
48
+ ac(arrWithCompressedClassNames)?.toString();
49
+ },
50
+ },
51
+ ]);
52
+
53
+ expect(benchmark).toMatchObject({
54
+ fastest: ['ax() array'],
55
+ });
56
+ }, 30000);
57
+
58
+ it('compares ax string with ac string', async () => {
59
+ // Remove undefined and join the strings
60
+ const benchmark = await runBenchmark('ax', [
61
+ {
62
+ name: 'ax() string',
63
+ fn: () => ax([str, undefined]),
64
+ },
65
+ {
66
+ name: 'ac() string with compressed class names',
67
+ fn: () => {
68
+ ac([strWithCompressedClassNames, undefined])?.toString();
69
+ },
70
+ },
71
+ ]);
72
+
73
+ expect(benchmark).toMatchObject({
74
+ fastest: ['ax() string'],
75
+ });
76
+ }, 30000);
77
+
78
+ it('compares chaining ax with chaining ac', async () => {
79
+ // Remove undefined and join the strings
80
+ const benchmark = await runBenchmark('ax', [
81
+ {
82
+ name: 'chain ax() string',
83
+ fn: () => ax([ax([str, undefined]), '_aaaabbbb']),
84
+ },
85
+ {
86
+ name: 'chain ac() string with compressed class names',
87
+ fn: () => {
88
+ ac([ac([strWithCompressedClassNames, undefined]), '_aaaa_a'])?.toString();
89
+ },
90
+ },
91
+ ]);
92
+
93
+ expect(benchmark).toMatchObject({
94
+ fastest: ['chain ac() string with compressed class names'],
95
+ });
96
+ }, 30000);
97
+ });
@@ -41,24 +41,4 @@ describe('ax benchmark', () => {
41
41
  fastest: ['ax() string'],
42
42
  });
43
43
  }, 30000);
44
-
45
- it('completes with ax() non-compressed class names as the fastest', async () => {
46
- const arrWithCompressedClassNames = arr.map((item) =>
47
- item ? `${item.slice(0, 4)}_${item.slice(8)}` : item
48
- );
49
- const benchmark = await runBenchmark('ax', [
50
- {
51
- name: 'ax() array',
52
- fn: () => ax(arr),
53
- },
54
- {
55
- name: 'ax() array with compressed class names',
56
- fn: () => ax(arrWithCompressedClassNames),
57
- },
58
- ]);
59
-
60
- expect(benchmark).toMatchObject({
61
- fastest: ['ax() array'],
62
- });
63
- }, 30000);
64
44
  });
@@ -0,0 +1,112 @@
1
+ import { ac, memoizedAc, getCache } from '../ac';
2
+
3
+ describe('ac', () => {
4
+ const isEnabled: boolean = (() => false)();
5
+
6
+ it.each([
7
+ ['should handle empty array', [], undefined],
8
+ ['should handle array with undefined', [undefined], undefined],
9
+ ['should join single classes together', ['foo', 'bar'], 'foo bar'],
10
+ ['should join multi classes together', ['foo baz', 'bar'], 'foo baz bar'],
11
+ ['should remove undefined', ['foo', 'bar', undefined], 'foo bar'],
12
+ [
13
+ 'should ensure the last atomic declaration of a single group wins',
14
+ ['_aaaabbbb', '_aaaacccc'],
15
+ '_aaaacccc',
16
+ ],
17
+ [
18
+ 'should ensure the last atomic declaration of a single group with short class name wins',
19
+ ['_aaaabbbb', '_aaaacccc', '_aaaa_a'],
20
+ 'a',
21
+ ],
22
+ [
23
+ 'should ensure the last atomic declaration of many single groups wins',
24
+ ['_aaaabbbb', '_aaaacccc', '_aaaadddd', '_aaaaeeee'],
25
+ '_aaaaeeee',
26
+ ],
27
+ [
28
+ 'should ensure the last atomic declaration of many single groups with short class name wins',
29
+ ['_aaaabbbb', '_aaaacccc', '_aaaa_a', '_aaaa_b'],
30
+ 'b',
31
+ ],
32
+ [
33
+ 'should ensure the last atomic declaration of a multi group wins',
34
+ ['_aaaabbbb _aaaacccc'],
35
+ '_aaaacccc',
36
+ ],
37
+ [
38
+ 'should ensure the last atomic declaration of a multi group with short class name wins',
39
+ ['_aaaa_e', '_aaaabbbb _aaaacccc'],
40
+ '_aaaacccc',
41
+ ],
42
+ [
43
+ 'should ensure the last atomic declaration of many multi groups wins',
44
+ ['_aaaabbbb _aaaacccc _aaaadddd _aaaaeeee'],
45
+ '_aaaaeeee',
46
+ ],
47
+ [
48
+ 'should ensure the last atomic declaration of many multi groups with short class name wins',
49
+ ['_aaaabbbb', '_aaaa_a', '_bbbb_b', '_ddddcccc'],
50
+ 'a b _ddddcccc',
51
+ ],
52
+ [
53
+ 'should not remove any atomic declarations if there are no duplicate groups',
54
+ ['_aaaabbbb', '_bbbbcccc'],
55
+ '_aaaabbbb _bbbbcccc',
56
+ ],
57
+ [
58
+ 'should not remove any atomic declarations if there are short class name and no duplicate groups',
59
+ ['_eeee_e', '_aaaabbbb', '_bbbbcccc'],
60
+ 'e _aaaabbbb _bbbbcccc',
61
+ ],
62
+ ['should not apply conditional class', [isEnabled && 'foo', 'bar'], 'bar'],
63
+ [
64
+ 'should ignore non atomic declarations',
65
+ ['hello_there', 'hello_world'],
66
+ 'hello_there hello_world',
67
+ ],
68
+ [
69
+ 'should ignore non atomic declarations when atomic declarations exist',
70
+ ['hello_there', 'hello_world', '_aaaabbbb'],
71
+ 'hello_there hello_world _aaaabbbb',
72
+ ],
73
+ [
74
+ 'should ignore non atomic declarations when atomic declarations with short class name exist',
75
+ ['hello_there', 'hello_world', '_aaaa_a'],
76
+ 'hello_there hello_world a',
77
+ ],
78
+ ])('%s', (_, params, result) => {
79
+ expect(result).toEqual(ac(params)?.toString());
80
+ });
81
+
82
+ it('should ensure the last atomic declaration wins if calling ax multiple times with short class names', () => {
83
+ expect(ac([ac(['_aaaa_b']), '_aaaa_c'])?.toString()).toEqual('c');
84
+ });
85
+ });
86
+
87
+ describe('memoizedAc', () => {
88
+ it('should cache correctly', () => {
89
+ memoizedAc([memoizedAc(['_aaaa_b', '_aaaabbbb', 'hello_world']), '_bbbb_d', '_aaaa_e']);
90
+
91
+ expect(getCache()).toMatchInlineSnapshot(`
92
+ Map {
93
+ "_aaaa_b _aaaabbbb hello_world" => AtomicGroups {
94
+ "values": Map {
95
+ "_aaaa" => "_aaaabbbb",
96
+ "hello_world" => "hello_world",
97
+ },
98
+ },
99
+ "_aaaabbbb hello_world _bbbb_d _aaaa_e" => AtomicGroups {
100
+ "values": Map {
101
+ "_aaaa" => "e",
102
+ "hello_world" => "hello_world",
103
+ "_bbbb" => "d",
104
+ },
105
+ },
106
+ }
107
+ `);
108
+ });
109
+ it('should not create a new ref', () => {
110
+ expect(memoizedAc(['a'])).toBe(memoizedAc(['a']));
111
+ });
112
+ });
@@ -14,31 +14,16 @@ describe('ax', () => {
14
14
  ['_aaaabbbb', '_aaaacccc'],
15
15
  '_aaaacccc',
16
16
  ],
17
- [
18
- 'should ensure the last atomic declaration of a single group with short class name wins',
19
- ['_aaaabbbb', '_aaaacccc', '_aaaa_a'],
20
- 'a',
21
- ],
22
17
  [
23
18
  'should ensure the last atomic declaration of many single groups wins',
24
19
  ['_aaaabbbb', '_aaaacccc', '_aaaadddd', '_aaaaeeee'],
25
20
  '_aaaaeeee',
26
21
  ],
27
- [
28
- 'should ensure the last atomic declaration of many single groups with short class name wins',
29
- ['_aaaabbbb', '_aaaacccc', '_aaaa_a', '_aaaa_b'],
30
- 'b',
31
- ],
32
22
  [
33
23
  'should ensure the last atomic declaration of a multi group wins',
34
24
  ['_aaaabbbb _aaaacccc'],
35
25
  '_aaaacccc',
36
26
  ],
37
- [
38
- 'should ensure the last atomic declaration of a multi group with short class name wins',
39
- ['_aaaa_e', '_aaaabbbb _aaaacccc'],
40
- '_aaaacccc',
41
- ],
42
27
  [
43
28
  'should ensure the last atomic declaration of many multi groups wins',
44
29
  ['_aaaabbbb _aaaacccc _aaaadddd _aaaaeeee'],
@@ -46,19 +31,14 @@ describe('ax', () => {
46
31
  ],
47
32
  [
48
33
  'should ensure the last atomic declaration of many multi groups with short class name wins',
49
- ['_aaaabbbb', '_aaaa_a', '_bbbb_b', '_ddddcccc'],
50
- 'a b _ddddcccc',
34
+ ['_aaaabbbb', '_aaaaaaa', '_ddddbbb', '_ddddcccc'],
35
+ '_aaaaaaa _ddddcccc',
51
36
  ],
52
37
  [
53
38
  'should not remove any atomic declarations if there are no duplicate groups',
54
39
  ['_aaaabbbb', '_bbbbcccc'],
55
40
  '_aaaabbbb _bbbbcccc',
56
41
  ],
57
- [
58
- 'should not remove any atomic declarations if there are short class name and no duplicate groups',
59
- ['_eeee_e', '_aaaabbbb', '_bbbbcccc'],
60
- 'e _aaaabbbb _bbbbcccc',
61
- ],
62
42
  ['should not apply conditional class', [isEnabled && 'foo', 'bar'], 'bar'],
63
43
  [
64
44
  'should ignore non atomic declarations',
@@ -70,11 +50,6 @@ describe('ax', () => {
70
50
  ['hello_there', 'hello_world', '_aaaabbbb'],
71
51
  'hello_there hello_world _aaaabbbb',
72
52
  ],
73
- [
74
- 'should ignore non atomic declarations when atomic declarations with short class name exist',
75
- ['hello_there', 'hello_world', '_aaaa_a'],
76
- 'hello_there hello_world a',
77
- ],
78
53
  ])('%s', (_, params, result) => {
79
54
  expect(result).toEqual(ax(params));
80
55
  });
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Flowtype definitions for ac
3
+ * Generated by Flowgen from a Typescript Definition
4
+ * Flowgen v1.20.1
5
+ * @flow
6
+ */
7
+ /**
8
+ * Memoize the result of ac so if it is called with the same args, it returns immediately.
9
+ * Also, to prevent useless React rerenders
10
+ */
11
+ declare var cache: Map<any, any>;
12
+ /**
13
+ * `ac` returns an instance of AtomicGroups. The instance holds the knowledge of Atomic Group so we can chain `ac`.
14
+ * e.g. <div className={ax([ax(['_aaaa_b']), '_aaaa_c'])} />
15
+ */
16
+ declare class AtomicGroups {
17
+ values: Map<string, string>;
18
+ constructor(values: Map<string, string>): this;
19
+ toString(): string;
20
+ }
21
+ /**
22
+ * Joins classes together and ensures atomic declarations of a single group exist.
23
+ * Atomic declarations take the form of `_{group}{value}` (always prefixed with an underscore),
24
+ * where both `group` and `value` are hashes **four characters long**.
25
+ * Class names can be of any length,
26
+ * this function can take both atomic declarations and class names.
27
+ *
28
+ * Input:
29
+ *
30
+ * ```
31
+ * ax(['_aaaabbbb', '_aaaacccc'])
32
+ * ```
33
+ *
34
+ * Output:
35
+ *
36
+ * ```
37
+ * '_aaaacccc'
38
+ * ```
39
+ * @param classes
40
+ */
41
+ declare export function ac(
42
+ classNames: (AtomicGroups | string | void | false)[]
43
+ ): AtomicGroups | void;
44
+ declare export function memoizedAc(
45
+ classNames: (AtomicGroups | string | void | false)[]
46
+ ): AtomicGroups | void;
47
+ declare var _default: typeof ac;
48
+ declare export default typeof _default;
49
+ /**
50
+ * Provide an opportunity to clear the cache to prevent memory leak.
51
+ */
52
+ declare export function clearCache(): void;
53
+ /**
54
+ * Expose cache
55
+ */
56
+ declare export function getCache(): typeof cache;
@@ -0,0 +1,143 @@
1
+ import { isServerEnvironment } from './is-server-environment';
2
+
3
+ const UNDERSCORE_UNICODE = 95;
4
+
5
+ /**
6
+ * This length includes the underscore,
7
+ * e.g. `"_1s4A"` would be a valid atomic group hash.
8
+ */
9
+ const ATOMIC_GROUP_LENGTH = 5;
10
+
11
+ /**
12
+ * Memoize the result of ac so if it is called with the same args, it returns immediately.
13
+ * Also, to prevent useless React rerenders
14
+ */
15
+ const cache = new Map();
16
+
17
+ /**
18
+ * `ac` returns an instance of AtomicGroups. The instance holds the knowledge of Atomic Group so we can chain `ac`.
19
+ * e.g. <div className={ax([ax(['_aaaa_b']), '_aaaa_c'])} />
20
+ */
21
+ class AtomicGroups {
22
+ values: Map<string, string>;
23
+ constructor(values: Map<string, string>) {
24
+ // An object stores the relation between Atomic group and actual class name
25
+ // e.g. { "aaaa": "a" } `aaaa` is the Atomic group and `a` is the actual class name
26
+ this.values = values;
27
+ }
28
+ toString() {
29
+ let str = '';
30
+
31
+ for (const [, value] of this.values) {
32
+ str += value + ' ';
33
+ }
34
+
35
+ return str.slice(0, -1);
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Joins classes together and ensures atomic declarations of a single group exist.
41
+ * Atomic declarations take the form of `_{group}{value}` (always prefixed with an underscore),
42
+ * where both `group` and `value` are hashes **four characters long**.
43
+ * Class names can be of any length,
44
+ * this function can take both atomic declarations and class names.
45
+ *
46
+ * Input:
47
+ *
48
+ * ```
49
+ * ax(['_aaaabbbb', '_aaaacccc'])
50
+ * ```
51
+ *
52
+ * Output:
53
+ *
54
+ * ```
55
+ * '_aaaacccc'
56
+ * ```
57
+ *
58
+ * @param classes
59
+ */
60
+ export function ac(
61
+ classNames: (AtomicGroups | string | undefined | false)[]
62
+ ): AtomicGroups | undefined {
63
+ // short circuit if there's no class names.
64
+ if (classNames.length <= 1 && !classNames[0]) return undefined;
65
+
66
+ const atomicGroups: Map<string, string> = new Map();
67
+
68
+ for (let i = 0; i < classNames.length; i++) {
69
+ const cls = classNames[i];
70
+ if (!cls) {
71
+ continue;
72
+ }
73
+
74
+ if (typeof cls === 'string') {
75
+ const groups = cls.split(' ');
76
+
77
+ for (let x = 0; x < groups.length; x++) {
78
+ const atomic = groups[x];
79
+ const isAtomic = atomic.charCodeAt(0) === UNDERSCORE_UNICODE;
80
+ const isCompressed = isAtomic && atomic.charCodeAt(5) === UNDERSCORE_UNICODE;
81
+
82
+ const atomicGroupName = isAtomic ? atomic.slice(0, ATOMIC_GROUP_LENGTH) : atomic;
83
+ atomicGroups.set(
84
+ atomicGroupName,
85
+ isCompressed ? atomic.slice(ATOMIC_GROUP_LENGTH + 1) : atomic
86
+ );
87
+ }
88
+ } else {
89
+ // if cls is an instance of AtomicGroups, transfer its values to `atomicGroups`
90
+ for (const [key, value] of cls.values) {
91
+ atomicGroups.set(key, value);
92
+ }
93
+ }
94
+ }
95
+
96
+ return new AtomicGroups(atomicGroups);
97
+ }
98
+
99
+ export function memoizedAc(
100
+ classNames: (AtomicGroups | string | undefined | false)[]
101
+ ): AtomicGroups | undefined {
102
+ // short circuit if there's no class names.
103
+ if (classNames.length <= 1 && !classNames[0]) return undefined;
104
+
105
+ // build the cacheKey based on the function argument
106
+ // e.g. if the argument is ["_aaaabbbb", "_aaaa_a", "some-class-name"],
107
+ // then the cacheKey is "_aaaabbbb _aaaa_a some-class-name"
108
+ let cacheKey = '';
109
+ for (let i = 0; i < classNames.length; i += 1) {
110
+ const current = classNames[i];
111
+ // continue if current is undefined, false, or ""
112
+ if (!current) continue;
113
+ cacheKey += current + ' ';
114
+ }
115
+
116
+ cacheKey = cacheKey.slice(0, -1);
117
+
118
+ if (cache.has(cacheKey)) return cache.get(cacheKey);
119
+
120
+ const result = ac(classNames);
121
+
122
+ cache.set(cacheKey, result);
123
+
124
+ return result;
125
+ }
126
+
127
+ // Memoization is primarily used to prevent React from unncessary re-rendering.
128
+ // Use unmemoizedAc on server-side because We don't need to worry about re-rendering on server-side.
129
+ export default isServerEnvironment() ? ac : memoizedAc;
130
+
131
+ /**
132
+ * Provide an opportunity to clear the cache to prevent memory leak.
133
+ */
134
+ export function clearCache(): void {
135
+ cache.clear();
136
+ }
137
+
138
+ /**
139
+ * Expose cache
140
+ */
141
+ export function getCache(): typeof cache {
142
+ return cache;
143
+ }
package/src/runtime/ax.ts CHANGED
@@ -28,8 +28,10 @@ const ATOMIC_GROUP_LENGTH = 5;
28
28
  * @param classes
29
29
  */
30
30
  export default function ax(classNames: (string | undefined | false)[]): string | undefined {
31
- // short circuit if there's no class names.
32
- if (classNames.length <= 1 && !classNames[0]) return undefined;
31
+ if (classNames.length <= 1 && (!classNames[0] || classNames[0].indexOf(' ') === -1)) {
32
+ // short circuit if there's no custom class names.
33
+ return classNames[0] || undefined;
34
+ }
33
35
 
34
36
  const atomicGroups: Record<string, string> = {};
35
37
 
@@ -43,11 +45,11 @@ export default function ax(classNames: (string | undefined | false)[]): string |
43
45
 
44
46
  for (let x = 0; x < groups.length; x++) {
45
47
  const atomic = groups[x];
46
- const isAtomic = atomic.charCodeAt(0) === UNDERSCORE_UNICODE;
47
- const isCompressed = isAtomic && atomic.charCodeAt(5) === UNDERSCORE_UNICODE;
48
-
49
- const atomicGroupName = isAtomic ? atomic.slice(0, ATOMIC_GROUP_LENGTH) : atomic;
50
- atomicGroups[atomicGroupName] = isCompressed ? atomic.slice(ATOMIC_GROUP_LENGTH + 1) : atomic;
48
+ const atomicGroupName = atomic.slice(
49
+ 0,
50
+ atomic.charCodeAt(0) === UNDERSCORE_UNICODE ? ATOMIC_GROUP_LENGTH : undefined
51
+ );
52
+ atomicGroups[atomicGroupName] = atomic;
51
53
  }
52
54
  }
53
55
 
@@ -7,4 +7,5 @@
7
7
  declare export { default as CS } from './style';
8
8
  declare export { default as CC } from './style-cache';
9
9
  declare export { default as ax } from './ax';
10
+ declare export { default as ac, clearCache as clearAcCache } from './ac';
10
11
  declare export { default as ix } from './css-custom-property';
@@ -1,4 +1,16 @@
1
1
  export { default as CS } from './style';
2
2
  export { default as CC } from './style-cache';
3
3
  export { default as ax } from './ax';
4
+ export { default as ac, clearCache as clearAcCache } from './ac';
4
5
  export { default as ix } from './css-custom-property';
6
+
7
+ // Ensure only one `@compiled/runtime` exist in the bundle.
8
+ // This is because `ac` and `style-cache` need to access a singlton.
9
+ if (typeof window !== 'undefined') {
10
+ if (typeof window.__COMPILED_IMPORTED__ !== 'undefined') {
11
+ throw new Error(
12
+ 'Multiple instances of Compiled Runtime have been found on the page. A likely cause is that muliple versions of `@compiled/react` exist in JS bundle.'
13
+ );
14
+ }
15
+ window.__COMPILED_IMPORTED__ = true;
16
+ }
@@ -4,4 +4,4 @@
4
4
  * Flowgen v1.20.1
5
5
  * @flow
6
6
  */
7
- declare export { CC, CS, ax, ix } from './runtime/index';
7
+ declare export { CC, CS, ax, ac, clearAcCache, ix } from './runtime/index';
package/src/runtime.ts CHANGED
@@ -1 +1 @@
1
- export { CC, CS, ax, ix } from './runtime/index';
1
+ export { CC, CS, ax, ac, clearAcCache, ix } from './runtime/index';