@acusti/styling 1.0.1 → 1.1.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/dist/Style.js +3 -5
- package/dist/Style.js.flow +5 -5
- package/dist/Style.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +2 -3
- package/dist/index.js.flow +2 -2
- package/dist/minifyStyles.js +15 -32
- package/dist/minifyStyles.js.flow +1 -1
- package/dist/minifyStyles.test.js +9 -17
- package/dist/minifyStyles.test.js.flow +1 -1
- package/dist/style-registry.js.flow +8 -8
- package/dist/style-registry.test.js.flow +1 -1
- package/dist/useStyles.d.ts +6 -12
- package/dist/useStyles.js +9 -14
- package/dist/useStyles.js.flow +12 -12
- package/dist/useStyles.test.js +31 -106
- package/dist/useStyles.test.js.flow +1 -1
- package/package.json +9 -9
- package/src/Style.tsx +2 -3
package/dist/Style.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { useStyles } from './useStyles.js';
|
|
3
3
|
const Style = ({ children, href: _href, precedence = 'medium' }) => {
|
|
4
|
-
// Minify CSS styles
|
|
4
|
+
// Minify CSS styles to prevent unnecessary cache misses
|
|
5
5
|
const { href, styles } = useStyles(children, _href);
|
|
6
|
-
|
|
7
|
-
// https://react.dev/reference/react-dom/components/style#props
|
|
8
|
-
return React.createElement('style', { href: href, precedence: precedence }, styles);
|
|
6
|
+
return (React.createElement("style", { href: href, precedence: precedence }, styles));
|
|
9
7
|
};
|
|
10
8
|
export default Style;
|
|
11
|
-
//# sourceMappingURL=Style.js.map
|
|
9
|
+
//# sourceMappingURL=Style.js.map
|
package/dist/Style.js.flow
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Flowtype definitions for Style
|
|
3
3
|
* Generated by Flowgen from a Typescript Definition
|
|
4
|
-
* Flowgen v1.
|
|
4
|
+
* Flowgen v1.21.0
|
|
5
5
|
* @flow
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import React from
|
|
8
|
+
import React from "react";
|
|
9
9
|
declare type Props = {|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
children: string,
|
|
11
|
+
href?: string,
|
|
12
|
+
precedence?: string,
|
|
13
13
|
|};
|
|
14
14
|
declare var Style: (x: Props) => React.Node;
|
|
15
15
|
declare export default typeof Style;
|
package/dist/Style.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Style.js","sourceRoot":"","sources":["../src/Style.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAQ3C,MAAM,KAAK,GAAG,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,GAAG,QAAQ,EAAS,EAAE,EAAE;IACtE,
|
|
1
|
+
{"version":3,"file":"Style.js","sourceRoot":"","sources":["../src/Style.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAQ3C,MAAM,KAAK,GAAG,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,GAAG,QAAQ,EAAS,EAAE,EAAE;IACtE,wDAAwD;IACxD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAEpD,OAAO,CACH,+BAAO,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,IACpC,MAAM,CACH,CACX,CAAC;AACN,CAAC,CAAC;AAEF,eAAe,KAAK,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
export { default as Style } from './Style.js';
|
|
2
|
-
export declare const SYSTEM_UI_FONT =
|
|
3
|
-
'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif';
|
|
2
|
+
export declare const SYSTEM_UI_FONT = "-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen-Sans, Ubuntu, Cantarell, \"Helvetica Neue\", sans-serif";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
export { default as Style } from './Style.js';
|
|
2
|
-
export const SYSTEM_UI_FONT =
|
|
3
|
-
|
|
4
|
-
//# sourceMappingURL=index.js.map
|
|
2
|
+
export const SYSTEM_UI_FONT = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif';
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
package/dist/index.js.flow
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Flowtype definitions for index
|
|
3
3
|
* Generated by Flowgen from a Typescript Definition
|
|
4
|
-
* Flowgen v1.
|
|
4
|
+
* Flowgen v1.21.0
|
|
5
5
|
* @flow
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
declare export { default as Style } from
|
|
8
|
+
declare export { default as Style } from "./Style.js";
|
|
9
9
|
declare export var SYSTEM_UI_FONT: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif';
|
package/dist/minifyStyles.js
CHANGED
|
@@ -26,10 +26,7 @@ export function minifyStyles(css) {
|
|
|
26
26
|
const preservedTokens = [];
|
|
27
27
|
const comments = [];
|
|
28
28
|
const totalLength = css.length;
|
|
29
|
-
let endIndex = 0,
|
|
30
|
-
placeholder = '',
|
|
31
|
-
startIndex = 0,
|
|
32
|
-
token = '';
|
|
29
|
+
let endIndex = 0, placeholder = '', startIndex = 0, token = '';
|
|
33
30
|
// collect all comment blocks...
|
|
34
31
|
while ((startIndex = css.indexOf('/*', startIndex)) >= 0) {
|
|
35
32
|
endIndex = css.indexOf('*/', startIndex + 2);
|
|
@@ -40,10 +37,10 @@ export function minifyStyles(css) {
|
|
|
40
37
|
comments.push(token);
|
|
41
38
|
css =
|
|
42
39
|
css.slice(0, startIndex + 2) +
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
'___PRESERVE_CANDIDATE_COMMENT_' +
|
|
41
|
+
(comments.length - 1) +
|
|
42
|
+
'___' +
|
|
43
|
+
css.slice(endIndex);
|
|
47
44
|
startIndex += 2;
|
|
48
45
|
}
|
|
49
46
|
// preserve strings so their content doesn't get accidentally minified
|
|
@@ -54,16 +51,11 @@ export function minifyStyles(css) {
|
|
|
54
51
|
// one, maybe more? put'em back then
|
|
55
52
|
if (match.indexOf('___PRESERVE_CANDIDATE_COMMENT_') >= 0) {
|
|
56
53
|
for (let i = 0, max = comments.length; i < max; i++) {
|
|
57
|
-
match = match.replace(
|
|
58
|
-
'___PRESERVE_CANDIDATE_COMMENT_' + i + '___',
|
|
59
|
-
comments[i],
|
|
60
|
-
);
|
|
54
|
+
match = match.replace('___PRESERVE_CANDIDATE_COMMENT_' + i + '___', comments[i]);
|
|
61
55
|
}
|
|
62
56
|
}
|
|
63
57
|
preservedTokens.push(match);
|
|
64
|
-
return (
|
|
65
|
-
quote + '___PRESERVED_TOKEN_' + (preservedTokens.length - 1) + '___' + quote
|
|
66
|
-
);
|
|
58
|
+
return (quote + '___PRESERVED_TOKEN_' + (preservedTokens.length - 1) + '___' + quote);
|
|
67
59
|
});
|
|
68
60
|
// strings are safe, now wrestle the comments
|
|
69
61
|
for (let i = 0, max = comments.length; i < max; i = i + 1) {
|
|
@@ -73,10 +65,7 @@ export function minifyStyles(css) {
|
|
|
73
65
|
// so push to the preserved tokens keeping the !
|
|
74
66
|
if (token.charAt(0) === '!') {
|
|
75
67
|
preservedTokens.push(token);
|
|
76
|
-
css = css.replace(
|
|
77
|
-
placeholder,
|
|
78
|
-
'___PRESERVED_TOKEN_' + (preservedTokens.length - 1) + '___',
|
|
79
|
-
);
|
|
68
|
+
css = css.replace(placeholder, '___PRESERVED_TOKEN_' + (preservedTokens.length - 1) + '___');
|
|
80
69
|
continue;
|
|
81
70
|
}
|
|
82
71
|
// otherwise, kill the comment
|
|
@@ -118,21 +107,15 @@ export function minifyStyles(css) {
|
|
|
118
107
|
css = css.replace(/:0 0(;|\})/g, ':0$1');
|
|
119
108
|
// Replace background-position:0; with background-position:0 0;
|
|
120
109
|
// same for transform-origin
|
|
121
|
-
css = css.replace(
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
return prop.toLowerCase() + ':0 0' + tail;
|
|
125
|
-
},
|
|
126
|
-
);
|
|
110
|
+
css = css.replace(/(background-position|transform-origin):0(;|\})/gi, function (_all, prop, tail) {
|
|
111
|
+
return prop.toLowerCase() + ':0 0' + tail;
|
|
112
|
+
});
|
|
127
113
|
// Replace 0.6 to .6, but only when preceded by : or a white-space
|
|
128
114
|
css = css.replace(/(:|\s)0+\.(\d+)/g, '$1.$2');
|
|
129
115
|
// border: none -> border:0
|
|
130
|
-
css = css.replace(
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
return prop.toLowerCase() + ':0' + tail;
|
|
134
|
-
},
|
|
135
|
-
);
|
|
116
|
+
css = css.replace(/(border|border-top|border-right|border-bottom|border-right|outline|background):none(;|\})/gi, function (_all, prop, tail) {
|
|
117
|
+
return prop.toLowerCase() + ':0' + tail;
|
|
118
|
+
});
|
|
136
119
|
// Remove empty rules.
|
|
137
120
|
css = css.replace(/[^};{/]+\{\}/g, '');
|
|
138
121
|
// Replace multiple semi-colons in a row by a single one
|
|
@@ -145,4 +128,4 @@ export function minifyStyles(css) {
|
|
|
145
128
|
return css.trim();
|
|
146
129
|
}
|
|
147
130
|
export default minifyStyles;
|
|
148
|
-
//# sourceMappingURL=minifyStyles.js.map
|
|
131
|
+
//# sourceMappingURL=minifyStyles.js.map
|
|
@@ -3,38 +3,30 @@ import { minifyStyles } from './minifyStyles.js';
|
|
|
3
3
|
describe('@acusti/styling', () => {
|
|
4
4
|
describe('minifyStyles.ts', () => {
|
|
5
5
|
it('minifies basic CSS declarations', () => {
|
|
6
|
-
expect(
|
|
7
|
-
minifyStyles(`
|
|
6
|
+
expect(minifyStyles(`
|
|
8
7
|
.foo {
|
|
9
8
|
padding: 10px;
|
|
10
9
|
color: red;
|
|
11
|
-
}`)
|
|
12
|
-
).toBe('.foo{padding:10px;color:red}');
|
|
10
|
+
}`)).toBe('.foo{padding:10px;color:red}');
|
|
13
11
|
});
|
|
14
12
|
it('preserves whitespace where needed in selectors', () => {
|
|
15
|
-
expect(
|
|
16
|
-
minifyStyles(`
|
|
13
|
+
expect(minifyStyles(`
|
|
17
14
|
.foo > .bar :hover {
|
|
18
15
|
background-color: cyan;
|
|
19
|
-
}`)
|
|
20
|
-
).toBe('.foo>.bar :hover{background-color:cyan}');
|
|
16
|
+
}`)).toBe('.foo>.bar :hover{background-color:cyan}');
|
|
21
17
|
});
|
|
22
18
|
it('minifies 0.6 to .6, but only when preceded by : or a whitespace', () => {
|
|
23
|
-
expect(
|
|
24
|
-
minifyStyles(`
|
|
19
|
+
expect(minifyStyles(`
|
|
25
20
|
.foo {
|
|
26
21
|
opacity: 0.6;
|
|
27
|
-
}`)
|
|
28
|
-
).toBe('.foo{opacity:.6}');
|
|
22
|
+
}`)).toBe('.foo{opacity:.6}');
|
|
29
23
|
});
|
|
30
24
|
it('strips out comments', () => {
|
|
31
|
-
expect(
|
|
32
|
-
minifyStyles(`
|
|
25
|
+
expect(minifyStyles(`
|
|
33
26
|
.bar {
|
|
34
27
|
font-weight: 900;/*.bar is so *strong**/
|
|
35
|
-
}`)
|
|
36
|
-
).toBe('.bar{font-weight:900}');
|
|
28
|
+
}`)).toBe('.bar{font-weight:900}');
|
|
37
29
|
});
|
|
38
30
|
});
|
|
39
31
|
});
|
|
40
|
-
//# sourceMappingURL=minifyStyles.test.js.map
|
|
32
|
+
//# sourceMappingURL=minifyStyles.test.js.map
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Flowtype definitions for style-registry
|
|
3
3
|
* Generated by Flowgen from a Typescript Definition
|
|
4
|
-
* Flowgen v1.
|
|
4
|
+
* Flowgen v1.21.0
|
|
5
5
|
* @flow
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
declare type Payload = {|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
ownerDocument: Document | "global",
|
|
10
|
+
styles: string,
|
|
11
11
|
|};
|
|
12
12
|
declare export var getRegisteredStyles: (x: Payload) => {|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
element: HTMLStyleElement | null,
|
|
14
|
+
referenceCount: number,
|
|
15
15
|
|} | null;
|
|
16
16
|
declare export var registerStyles: (x: Payload) => void;
|
|
17
17
|
declare export var unregisterStyles: (x: Payload) => void;
|
|
18
18
|
declare type UpdatePayload = {|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
ownerDocument: Document,
|
|
20
|
+
previousStyles: string,
|
|
21
|
+
styles: string,
|
|
22
22
|
|};
|
|
23
23
|
declare export var updateStyles: (x: UpdatePayload) => void;
|
|
24
24
|
declare export var getStyleRegistryKeys: () => IterableIterator<string>;
|
package/dist/useStyles.d.ts
CHANGED
|
@@ -1,15 +1,9 @@
|
|
|
1
|
-
type StyleCache = Map<
|
|
2
|
-
string
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
>;
|
|
9
|
-
export declare function useStyles(
|
|
10
|
-
styles: string,
|
|
11
|
-
initialHref?: string,
|
|
12
|
-
): {
|
|
1
|
+
type StyleCache = Map<string, {
|
|
2
|
+
href: string;
|
|
3
|
+
referenceCount: number;
|
|
4
|
+
styles: string;
|
|
5
|
+
}>;
|
|
6
|
+
export declare function useStyles(styles: string, initialHref?: string): {
|
|
13
7
|
href: string;
|
|
14
8
|
referenceCount: number;
|
|
15
9
|
styles: string;
|
package/dist/useStyles.js
CHANGED
|
@@ -4,19 +4,17 @@ const styleCache = new Map();
|
|
|
4
4
|
const EMPTY_STYLES_ITEM = { href: '', referenceCount: 0, styles: '' };
|
|
5
5
|
export function useStyles(styles, initialHref) {
|
|
6
6
|
const [stylesItem, setStylesItem] = useState(() => {
|
|
7
|
-
if (!styles)
|
|
7
|
+
if (!styles)
|
|
8
|
+
return EMPTY_STYLES_ITEM;
|
|
8
9
|
const key = initialHref !== null && initialHref !== void 0 ? initialHref : styles;
|
|
9
10
|
let item = styleCache.get(key);
|
|
10
11
|
if (item) {
|
|
11
12
|
item.referenceCount++;
|
|
12
|
-
}
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
13
15
|
const minified = minifyStyles(styles);
|
|
14
16
|
item = {
|
|
15
|
-
href: sanitizeHref(
|
|
16
|
-
initialHref !== null && initialHref !== void 0
|
|
17
|
-
? initialHref
|
|
18
|
-
: minified,
|
|
19
|
-
),
|
|
17
|
+
href: sanitizeHref(initialHref !== null && initialHref !== void 0 ? initialHref : minified),
|
|
20
18
|
referenceCount: 1,
|
|
21
19
|
styles: minified,
|
|
22
20
|
};
|
|
@@ -25,16 +23,13 @@ export function useStyles(styles, initialHref) {
|
|
|
25
23
|
return item;
|
|
26
24
|
});
|
|
27
25
|
useEffect(() => {
|
|
28
|
-
if (!styles)
|
|
26
|
+
if (!styles)
|
|
27
|
+
return;
|
|
29
28
|
const key = initialHref !== null && initialHref !== void 0 ? initialHref : styles;
|
|
30
29
|
if (!styleCache.get(key)) {
|
|
31
30
|
const minified = minifyStyles(styles);
|
|
32
31
|
const item = {
|
|
33
|
-
href: sanitizeHref(
|
|
34
|
-
initialHref !== null && initialHref !== void 0
|
|
35
|
-
? initialHref
|
|
36
|
-
: minified,
|
|
37
|
-
),
|
|
32
|
+
href: sanitizeHref(initialHref !== null && initialHref !== void 0 ? initialHref : minified),
|
|
38
33
|
referenceCount: 1,
|
|
39
34
|
styles: minified,
|
|
40
35
|
};
|
|
@@ -65,4 +60,4 @@ function sanitizeHref(text) {
|
|
|
65
60
|
}
|
|
66
61
|
// The following export is for test usage only
|
|
67
62
|
export const getStyleCache = () => styleCache;
|
|
68
|
-
//# sourceMappingURL=useStyles.js.map
|
|
63
|
+
//# sourceMappingURL=useStyles.js.map
|
package/dist/useStyles.js.flow
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Flowtype definitions for useStyles
|
|
3
3
|
* Generated by Flowgen from a Typescript Definition
|
|
4
|
-
* Flowgen v1.
|
|
4
|
+
* Flowgen v1.21.0
|
|
5
5
|
* @flow
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
declare type StyleCache = Map<
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
href: string,
|
|
12
|
-
referenceCount: number,
|
|
13
|
-
styles: string,
|
|
14
|
-
|},
|
|
15
|
-
>;
|
|
16
|
-
declare export function useStyles(
|
|
17
|
-
styles: string,
|
|
18
|
-
initialHref?: string,
|
|
19
|
-
): {|
|
|
9
|
+
string,
|
|
10
|
+
{|
|
|
20
11
|
href: string,
|
|
21
12
|
referenceCount: number,
|
|
22
13
|
styles: string,
|
|
14
|
+
|}
|
|
15
|
+
>;
|
|
16
|
+
declare export function useStyles(
|
|
17
|
+
styles: string,
|
|
18
|
+
initialHref?: string
|
|
19
|
+
): {|
|
|
20
|
+
href: string,
|
|
21
|
+
referenceCount: number,
|
|
22
|
+
styles: string,
|
|
23
23
|
|};
|
|
24
24
|
declare export default typeof useStyles;
|
|
25
25
|
declare export var getStyleCache: () => StyleCache;
|
package/dist/useStyles.test.js
CHANGED
|
@@ -14,141 +14,66 @@ describe('@acusti/styling', () => {
|
|
|
14
14
|
});
|
|
15
15
|
it('should cache minified styles in the registry keyed by the style string', () => {
|
|
16
16
|
const styleCache = getStyleCache();
|
|
17
|
-
const { rerender } = render(
|
|
18
|
-
React.createElement(
|
|
19
|
-
|
|
20
|
-
null,
|
|
21
|
-
React.createElement(Style, null, mockStylesA),
|
|
22
|
-
React.createElement(Style, null, mockStylesA),
|
|
23
|
-
),
|
|
24
|
-
);
|
|
17
|
+
const { rerender } = render(React.createElement(React.Fragment, null,
|
|
18
|
+
React.createElement(Style, null, mockStylesA),
|
|
19
|
+
React.createElement(Style, null, mockStylesA)));
|
|
25
20
|
let stylesItemA = styleCache.get(mockStylesA);
|
|
26
|
-
expect(
|
|
27
|
-
|
|
28
|
-
? void 0
|
|
29
|
-
: stylesItemA.referenceCount,
|
|
30
|
-
).toBe(2);
|
|
31
|
-
expect(
|
|
32
|
-
stylesItemA === null || stylesItemA === void 0
|
|
33
|
-
? void 0
|
|
34
|
-
: stylesItemA.styles,
|
|
35
|
-
).toBe('.test-a{color:cyan}');
|
|
21
|
+
expect(stylesItemA === null || stylesItemA === void 0 ? void 0 : stylesItemA.referenceCount).toBe(2);
|
|
22
|
+
expect(stylesItemA === null || stylesItemA === void 0 ? void 0 : stylesItemA.styles).toBe('.test-a{color:cyan}');
|
|
36
23
|
expect(styleCache.size).toBe(1);
|
|
37
24
|
rerender(React.createElement(Style, null, mockStylesA));
|
|
38
|
-
expect(
|
|
39
|
-
stylesItemA === null || stylesItemA === void 0
|
|
40
|
-
? void 0
|
|
41
|
-
: stylesItemA.referenceCount,
|
|
42
|
-
).toBe(1);
|
|
25
|
+
expect(stylesItemA === null || stylesItemA === void 0 ? void 0 : stylesItemA.referenceCount).toBe(1);
|
|
43
26
|
expect(stylesItemA).toBe(styleCache.get(mockStylesA));
|
|
44
27
|
expect(styleCache.size).toBe(1);
|
|
45
28
|
rerender(React.createElement(Style, null, mockStylesB));
|
|
46
29
|
stylesItemA = styleCache.get(mockStylesA);
|
|
47
30
|
expect(stylesItemA).toBe(undefined);
|
|
48
31
|
let stylesItemB = styleCache.get(mockStylesB);
|
|
49
|
-
expect(
|
|
50
|
-
stylesItemB === null || stylesItemB === void 0
|
|
51
|
-
? void 0
|
|
52
|
-
: stylesItemB.referenceCount,
|
|
53
|
-
).toBe(1);
|
|
32
|
+
expect(stylesItemB === null || stylesItemB === void 0 ? void 0 : stylesItemB.referenceCount).toBe(1);
|
|
54
33
|
expect(styleCache.size).toBe(1);
|
|
55
|
-
rerender(
|
|
56
|
-
React.createElement(
|
|
57
|
-
|
|
58
|
-
null,
|
|
59
|
-
React.createElement(Style, null, mockStylesA),
|
|
60
|
-
React.createElement(Style, null, mockStylesB),
|
|
61
|
-
),
|
|
62
|
-
);
|
|
34
|
+
rerender(React.createElement(React.Fragment, null,
|
|
35
|
+
React.createElement(Style, null, mockStylesA),
|
|
36
|
+
React.createElement(Style, null, mockStylesB)));
|
|
63
37
|
stylesItemA = styleCache.get(mockStylesA);
|
|
64
|
-
expect(
|
|
65
|
-
stylesItemA === null || stylesItemA === void 0
|
|
66
|
-
? void 0
|
|
67
|
-
: stylesItemA.referenceCount,
|
|
68
|
-
).toBe(1);
|
|
38
|
+
expect(stylesItemA === null || stylesItemA === void 0 ? void 0 : stylesItemA.referenceCount).toBe(1);
|
|
69
39
|
expect(stylesItemA).toBe(styleCache.get(mockStylesA));
|
|
70
40
|
stylesItemB = styleCache.get(mockStylesB);
|
|
71
|
-
expect(
|
|
72
|
-
stylesItemB === null || stylesItemB === void 0
|
|
73
|
-
? void 0
|
|
74
|
-
: stylesItemB.referenceCount,
|
|
75
|
-
).toBe(1);
|
|
41
|
+
expect(stylesItemB === null || stylesItemB === void 0 ? void 0 : stylesItemB.referenceCount).toBe(1);
|
|
76
42
|
expect(styleCache.size).toBe(2);
|
|
77
|
-
rerender(React.createElement(
|
|
43
|
+
rerender(React.createElement("div", null));
|
|
78
44
|
expect(styleCache.size).toBe(0);
|
|
79
45
|
});
|
|
80
46
|
it('should preserve style cache across component position changes and re-keying', () => {
|
|
81
47
|
const styleCache = getStyleCache();
|
|
82
|
-
const { rerender } = render(
|
|
83
|
-
React.createElement(
|
|
84
|
-
React.Fragment,
|
|
85
|
-
null,
|
|
86
|
-
React.createElement(Style, null, mockStylesA),
|
|
87
|
-
),
|
|
88
|
-
);
|
|
48
|
+
const { rerender } = render(React.createElement(React.Fragment, null,
|
|
49
|
+
React.createElement(Style, null, mockStylesA)));
|
|
89
50
|
const stylesItemA = styleCache.get(mockStylesA);
|
|
90
|
-
expect(
|
|
91
|
-
|
|
92
|
-
? void 0
|
|
93
|
-
: stylesItemA.referenceCount,
|
|
94
|
-
).toBe(1);
|
|
95
|
-
expect(
|
|
96
|
-
stylesItemA === null || stylesItemA === void 0
|
|
97
|
-
? void 0
|
|
98
|
-
: stylesItemA.styles,
|
|
99
|
-
).toBe('.test-a{color:cyan}');
|
|
51
|
+
expect(stylesItemA === null || stylesItemA === void 0 ? void 0 : stylesItemA.referenceCount).toBe(1);
|
|
52
|
+
expect(stylesItemA === null || stylesItemA === void 0 ? void 0 : stylesItemA.styles).toBe('.test-a{color:cyan}');
|
|
100
53
|
expect(styleCache.size).toBe(1);
|
|
101
|
-
rerender(
|
|
102
|
-
React.createElement(
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
React.createElement(Style, null, mockStylesB),
|
|
106
|
-
React.createElement(Style, null, mockStylesA),
|
|
107
|
-
),
|
|
108
|
-
);
|
|
109
|
-
expect(
|
|
110
|
-
stylesItemA === null || stylesItemA === void 0
|
|
111
|
-
? void 0
|
|
112
|
-
: stylesItemA.referenceCount,
|
|
113
|
-
).toBe(1);
|
|
54
|
+
rerender(React.createElement(React.Fragment, null,
|
|
55
|
+
React.createElement(Style, null, mockStylesB),
|
|
56
|
+
React.createElement(Style, null, mockStylesA)));
|
|
57
|
+
expect(stylesItemA === null || stylesItemA === void 0 ? void 0 : stylesItemA.referenceCount).toBe(1);
|
|
114
58
|
expect(stylesItemA).toBe(styleCache.get(mockStylesA));
|
|
115
|
-
rerender(React.createElement(Style, { key:
|
|
116
|
-
expect(
|
|
117
|
-
stylesItemA === null || stylesItemA === void 0
|
|
118
|
-
? void 0
|
|
119
|
-
: stylesItemA.referenceCount,
|
|
120
|
-
).toBe(1);
|
|
59
|
+
rerender(React.createElement(Style, { key: "new-a" }, mockStylesA));
|
|
60
|
+
expect(stylesItemA === null || stylesItemA === void 0 ? void 0 : stylesItemA.referenceCount).toBe(1);
|
|
121
61
|
expect(stylesItemA).toBe(styleCache.get(mockStylesA));
|
|
122
|
-
rerender(
|
|
123
|
-
React.createElement(
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
React.createElement(Style, null, mockStylesA),
|
|
127
|
-
React.createElement(Style, { key: 'new-a' }, mockStylesA),
|
|
128
|
-
),
|
|
129
|
-
);
|
|
130
|
-
expect(
|
|
131
|
-
stylesItemA === null || stylesItemA === void 0
|
|
132
|
-
? void 0
|
|
133
|
-
: stylesItemA.referenceCount,
|
|
134
|
-
).toBe(2);
|
|
62
|
+
rerender(React.createElement(React.Fragment, null,
|
|
63
|
+
React.createElement(Style, null, mockStylesA),
|
|
64
|
+
React.createElement(Style, { key: "new-a" }, mockStylesA)));
|
|
65
|
+
expect(stylesItemA === null || stylesItemA === void 0 ? void 0 : stylesItemA.referenceCount).toBe(2);
|
|
135
66
|
expect(stylesItemA).toBe(styleCache.get(mockStylesA));
|
|
136
|
-
rerender(React.createElement(
|
|
137
|
-
expect(
|
|
138
|
-
stylesItemA === null || stylesItemA === void 0
|
|
139
|
-
? void 0
|
|
140
|
-
: stylesItemA.referenceCount,
|
|
141
|
-
).toBe(0);
|
|
67
|
+
rerender(React.createElement("div", null));
|
|
68
|
+
expect(stylesItemA === null || stylesItemA === void 0 ? void 0 : stylesItemA.referenceCount).toBe(0);
|
|
142
69
|
expect(styleCache.size).toBe(0);
|
|
143
70
|
});
|
|
144
71
|
it('should sanitize styles used as href prop if no href prop provided', () => {
|
|
145
|
-
render(
|
|
146
|
-
React.createElement(Style, null, `div[data-foo-bar] { color: cyan; }`),
|
|
147
|
-
);
|
|
72
|
+
render(React.createElement(Style, null, `div[data-foo-bar] { color: cyan; }`));
|
|
148
73
|
// the two-dash attribute selector results in “Range out of order in character class”
|
|
149
74
|
// and render() fails with SyntaxError: Invalid regular expression if not sanitized
|
|
150
75
|
expect(true).toBeTruthy();
|
|
151
76
|
});
|
|
152
77
|
});
|
|
153
78
|
});
|
|
154
|
-
//# sourceMappingURL=useStyles.test.js.map
|
|
79
|
+
//# sourceMappingURL=useStyles.test.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@acusti/styling",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"exports": "./dist/index.js",
|
|
@@ -38,17 +38,17 @@
|
|
|
38
38
|
"homepage": "https://github.com/acusti/uikit/tree/main/packages/styling#readme",
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@testing-library/dom": "^10.4.0",
|
|
41
|
-
"@testing-library/react": "^16.
|
|
42
|
-
"@testing-library/user-event": "^14.
|
|
43
|
-
"@types/react": "^19.
|
|
44
|
-
"happy-dom": "^
|
|
41
|
+
"@testing-library/react": "^16.3.0",
|
|
42
|
+
"@testing-library/user-event": "^14.6.1",
|
|
43
|
+
"@types/react": "^19.1.6",
|
|
44
|
+
"happy-dom": "^17.4.7",
|
|
45
45
|
"react": "^19",
|
|
46
46
|
"react-dom": "^19",
|
|
47
|
-
"typescript": "5.
|
|
48
|
-
"vitest": "^
|
|
47
|
+
"typescript": "5.8.3",
|
|
48
|
+
"vitest": "^3.1.4"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
|
-
"react": "^19",
|
|
52
|
-
"react-dom": "^19"
|
|
51
|
+
"react": "^19 || ~0.0.0-experimental < 0.0.0-f",
|
|
52
|
+
"react-dom": "^19 || ~0.0.0-experimental < 0.0.0-f"
|
|
53
53
|
}
|
|
54
54
|
}
|
package/src/Style.tsx
CHANGED
|
@@ -9,10 +9,9 @@ type Props = {
|
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
const Style = ({ children, href: _href, precedence = 'medium' }: Props) => {
|
|
12
|
-
// Minify CSS styles
|
|
12
|
+
// Minify CSS styles to prevent unnecessary cache misses
|
|
13
13
|
const { href, styles } = useStyles(children, _href);
|
|
14
|
-
|
|
15
|
-
// https://react.dev/reference/react-dom/components/style#props
|
|
14
|
+
|
|
16
15
|
return (
|
|
17
16
|
<style href={href} precedence={precedence}>
|
|
18
17
|
{styles}
|