rn-css 1.6.7 → 1.6.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/features.js +1 -1
- package/dist/styleComponent.js +32 -10
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
- package/src/features.tsx +1 -1
- package/src/styleComponent.tsx +34 -11
- package/src/types.ts +1 -0
package/README.md
CHANGED
|
@@ -180,6 +180,14 @@ if(width < 70 * em) { /* Do something when width is lesser than 70em */ }
|
|
|
180
180
|
return <View onLayout={event => setWidth(event.nativeEvent.layout.width)}>...</View>
|
|
181
181
|
```
|
|
182
182
|
|
|
183
|
+
Default value for `rem` units is 16. If you want to declare another value, you can use `RemContext`:
|
|
184
|
+
|
|
185
|
+
```javascript
|
|
186
|
+
import { RemContext } from 'rn-css'
|
|
187
|
+
...
|
|
188
|
+
return <RemContext.Provider value={10}>{children}</RemContext.Provider>
|
|
189
|
+
```
|
|
190
|
+
|
|
183
191
|
---
|
|
184
192
|
|
|
185
193
|
## Convert a CSS string to React-Native Style
|
package/dist/features.js
CHANGED
|
@@ -68,7 +68,7 @@ const useLayout = (onLayout, needsLayout) => {
|
|
|
68
68
|
exports.useLayout = useLayout;
|
|
69
69
|
/** Apply the new fontSize to the component before we can calculate em units */
|
|
70
70
|
const useFontSize = (fontSizeTarget, rem, em) => {
|
|
71
|
-
const [fontSize, fontUnit] = react_1.default.useMemo(() => fontSizeTarget === undefined ? [
|
|
71
|
+
const [fontSize, fontUnit] = react_1.default.useMemo(() => fontSizeTarget === undefined ? [] : (0, convertUnits_1.parseValue)(fontSizeTarget), [fontSizeTarget]);
|
|
72
72
|
const isRelative = fontUnit && ['rem', 'em', '%'].includes(fontUnit);
|
|
73
73
|
const newSize = react_1.default.useMemo(() => {
|
|
74
74
|
if (fontSize && isRelative) {
|
package/dist/styleComponent.js
CHANGED
|
@@ -11,6 +11,7 @@ const react_native_1 = require("react-native");
|
|
|
11
11
|
const convertStyle_1 = __importDefault(require("./convertStyle"));
|
|
12
12
|
const cssToRN_1 = __importDefault(require("./cssToRN"));
|
|
13
13
|
const features_1 = require("./features");
|
|
14
|
+
const generateHash_1 = __importDefault(require("./generateHash"));
|
|
14
15
|
exports.defaultUnits = { em: 16, vw: 1, vh: 1, vmin: 1, vmax: 1, rem: 16, px: 1, pt: 72 / 96, in: 96, pc: 9, cm: 96 / 2.54, mm: 96 / 25.4 };
|
|
15
16
|
exports.RemContext = react_1.default.createContext(exports.defaultUnits.rem);
|
|
16
17
|
exports.FontSizeContext = react_1.default.createContext(exports.defaultUnits.em);
|
|
@@ -22,6 +23,23 @@ function buildCSSString(chunks, functs, props, shared) {
|
|
|
22
23
|
computedString += props.rnCSS.replace(/=/gm, ':') + ';';
|
|
23
24
|
return computedString;
|
|
24
25
|
}
|
|
26
|
+
const styleMap = {};
|
|
27
|
+
function getStyle(hash, style) {
|
|
28
|
+
const styleInfo = styleMap[hash];
|
|
29
|
+
if (styleInfo) {
|
|
30
|
+
styleInfo.usage++;
|
|
31
|
+
return styleInfo.style;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
const sheet = react_native_1.StyleSheet.create({ [hash]: style });
|
|
35
|
+
return (styleMap[hash] = { style: sheet[hash], usage: 1 }).style;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function removeStyle(hash) {
|
|
39
|
+
styleMap[hash].usage--;
|
|
40
|
+
if (styleMap[hash].usage <= 0)
|
|
41
|
+
delete styleMap[hash];
|
|
42
|
+
}
|
|
25
43
|
const styled = (Component) => {
|
|
26
44
|
const styledComponent = (chunks, ...functs) => {
|
|
27
45
|
const ForwardRefComponent = react_1.default.forwardRef((props, ref) => {
|
|
@@ -33,7 +51,7 @@ const styled = (Component) => {
|
|
|
33
51
|
const rnStyle = react_1.default.useMemo(() => (0, cssToRN_1.default)(css), [css]);
|
|
34
52
|
const { needsLayout, needsHover } = react_1.default.useMemo(() => ({
|
|
35
53
|
// needsFontSize: !!css.match(/\b(\d+)(\.\d+)?em\b/)
|
|
36
|
-
// needsScreenSize: !!
|
|
54
|
+
// needsScreenSize: !!css.match(/\b(\d+)(\.\d*)?v([hw]|min|max)\b/) || !!rnStyle.media,
|
|
37
55
|
needsLayout: !!css.match(/\d%/),
|
|
38
56
|
needsHover: !!rnStyle.hover
|
|
39
57
|
}), [css, rnStyle.hover]);
|
|
@@ -77,18 +95,22 @@ const styled = (Component) => {
|
|
|
77
95
|
return style;
|
|
78
96
|
}, [em, mediaQuery, tempStyle]);
|
|
79
97
|
const units = react_1.default.useMemo(() => ({ ...baseUnits, em }), [baseUnits, em]);
|
|
80
|
-
const styleConvertedFromCSS = react_1.default.useMemo(() =>
|
|
81
|
-
|
|
98
|
+
const { style: styleConvertedFromCSS, hash } = react_1.default.useMemo(() => {
|
|
99
|
+
const style = (0, convertStyle_1.default)(finalStyle, units);
|
|
100
|
+
delete style.textOverflow;
|
|
101
|
+
const hash = (0, generateHash_1.default)(JSON.stringify(style));
|
|
102
|
+
return { style: getStyle(hash, style), hash };
|
|
103
|
+
}, [finalStyle, units]);
|
|
82
104
|
const newProps = react_1.default.useMemo(() => {
|
|
83
|
-
const newProps = { style, onMouseEnter, onMouseLeave, onLayout };
|
|
84
|
-
if (
|
|
105
|
+
const newProps = { style: [styleConvertedFromCSS, props.style], onMouseEnter, onMouseLeave, onLayout };
|
|
106
|
+
if (finalStyle.textOverflow === 'ellipsis') {
|
|
85
107
|
Object.assign(newProps, { numberOfLines: 1 });
|
|
108
|
+
}
|
|
86
109
|
return newProps;
|
|
87
|
-
}, [onLayout, onMouseEnter, onMouseLeave, style]);
|
|
88
|
-
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
if (style.fontSize) {
|
|
110
|
+
}, [finalStyle.textOverflow, onLayout, onMouseEnter, onMouseLeave, props.style, styleConvertedFromCSS]);
|
|
111
|
+
react_1.default.useEffect(() => () => removeStyle(hash), [hash]);
|
|
112
|
+
// em !== parentEm alone is a bit dangerous as the component would rerender when the font size change
|
|
113
|
+
if (em !== parentEm || finalStyle.fontSize !== undefined) {
|
|
92
114
|
return react_1.default.createElement(exports.FontSizeContext.Provider, { value: em },
|
|
93
115
|
react_1.default.createElement(Component, { ref: ref, ...props, ...newProps }));
|
|
94
116
|
}
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
package/src/features.tsx
CHANGED
|
@@ -59,7 +59,7 @@ export const useLayout = (onLayout: undefined | ((event: LayoutChangeEvent) => v
|
|
|
59
59
|
|
|
60
60
|
/** Apply the new fontSize to the component before we can calculate em units */
|
|
61
61
|
export const useFontSize = (fontSizeTarget: string | undefined, rem: number, em: number): { em: number } => {
|
|
62
|
-
const [fontSize, fontUnit] = React.useMemo(() => fontSizeTarget === undefined ? [
|
|
62
|
+
const [fontSize, fontUnit] = React.useMemo(() => fontSizeTarget === undefined ? [] : parseValue(fontSizeTarget), [fontSizeTarget])
|
|
63
63
|
const isRelative = fontUnit && ['rem', 'em', '%'].includes(fontUnit)
|
|
64
64
|
const newSize = React.useMemo(() => {
|
|
65
65
|
if (fontSize && isRelative) {
|
package/src/styleComponent.tsx
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/* eslint-disable react/prop-types */
|
|
2
2
|
/* eslint-disable react/display-name */
|
|
3
3
|
import React, { MouseEvent } from 'react'
|
|
4
|
-
import { FlatList, FlatListProps, LayoutChangeEvent, Platform, SectionList, SectionListProps, StyleProp, StyleSheet, VirtualizedList, VirtualizedListProps } from 'react-native'
|
|
4
|
+
import { FlatList, FlatListProps, LayoutChangeEvent, Platform, SectionList, SectionListProps, StyleProp, StyleSheet, TextStyle, ViewStyle, VirtualizedList, VirtualizedListProps } from 'react-native'
|
|
5
5
|
import convertStyle from './convertStyle'
|
|
6
6
|
import cssToStyle from './cssToRN'
|
|
7
7
|
import { useFontSize, useHover, useLayout, useScreenSize, useMediaQuery } from './features'
|
|
8
8
|
import type { Style, Units } from './types'
|
|
9
|
+
import generateHash from './generateHash'
|
|
9
10
|
|
|
10
11
|
export const defaultUnits: Units = { em: 16, vw: 1, vh: 1, vmin: 1, vmax: 1, rem: 16, px: 1, pt: 72 / 96, in: 96, pc: 9, cm: 96 / 2.54, mm: 96 / 25.4 }
|
|
11
12
|
export const RemContext = React.createContext<number>(defaultUnits.rem)
|
|
@@ -29,6 +30,22 @@ function buildCSSString<T extends { rnCSS?: string }> (chunks: TemplateStringsAr
|
|
|
29
30
|
if (props.rnCSS) computedString += props.rnCSS.replace(/=/gm, ':') + ';'
|
|
30
31
|
return computedString
|
|
31
32
|
}
|
|
33
|
+
const styleMap: Record<string, { style: ViewStyle & TextStyle, usage: number }> = {}
|
|
34
|
+
function getStyle (hash: string, style: ViewStyle & TextStyle) {
|
|
35
|
+
const styleInfo = styleMap[hash]
|
|
36
|
+
if (styleInfo) {
|
|
37
|
+
styleInfo.usage++
|
|
38
|
+
return styleInfo.style
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
const sheet = StyleSheet.create({ [hash]: style })
|
|
42
|
+
return (styleMap[hash] = { style: sheet[hash], usage: 1 }).style
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function removeStyle (hash: string) {
|
|
46
|
+
styleMap[hash].usage--
|
|
47
|
+
if (styleMap[hash].usage <= 0) delete styleMap[hash]
|
|
48
|
+
}
|
|
32
49
|
const styled = <Props, >(Component: React.ComponentType<Props>) => {
|
|
33
50
|
const styledComponent = <S, >(chunks: TemplateStringsArray, ...functs: (Primitive | Functs<S & Props>)[]) => {
|
|
34
51
|
const ForwardRefComponent = React.forwardRef<React.ComponentType<S & Props & OptionalProps>, S & Props & OptionalProps>((props: S & Props & OptionalProps, ref) => {
|
|
@@ -41,7 +58,7 @@ const styled = <Props, >(Component: React.ComponentType<Props>) => {
|
|
|
41
58
|
|
|
42
59
|
const { needsLayout, needsHover } = React.useMemo(() => ({
|
|
43
60
|
// needsFontSize: !!css.match(/\b(\d+)(\.\d+)?em\b/)
|
|
44
|
-
// needsScreenSize: !!
|
|
61
|
+
// needsScreenSize: !!css.match(/\b(\d+)(\.\d*)?v([hw]|min|max)\b/) || !!rnStyle.media,
|
|
45
62
|
needsLayout: !!css.match(/\d%/),
|
|
46
63
|
needsHover: !!rnStyle.hover
|
|
47
64
|
}), [css, rnStyle.hover])
|
|
@@ -89,18 +106,24 @@ const styled = <Props, >(Component: React.ComponentType<Props>) => {
|
|
|
89
106
|
|
|
90
107
|
const units = React.useMemo<Units>(() => ({ ...baseUnits, em }), [baseUnits, em])
|
|
91
108
|
|
|
92
|
-
const styleConvertedFromCSS = React.useMemo(() =>
|
|
93
|
-
|
|
109
|
+
const { style: styleConvertedFromCSS, hash } = React.useMemo(() => {
|
|
110
|
+
const style = convertStyle(finalStyle, units)
|
|
111
|
+
delete (style as Style).textOverflow
|
|
112
|
+
const hash = generateHash(JSON.stringify(style))
|
|
113
|
+
return { style: getStyle(hash, style), hash }
|
|
114
|
+
}, [finalStyle, units])
|
|
94
115
|
const newProps = React.useMemo(() => {
|
|
95
|
-
const newProps: OptionalProps = { style, onMouseEnter, onMouseLeave, onLayout }
|
|
96
|
-
if (
|
|
116
|
+
const newProps: OptionalProps = { style: [styleConvertedFromCSS, props.style], onMouseEnter, onMouseLeave, onLayout }
|
|
117
|
+
if (finalStyle.textOverflow === 'ellipsis') {
|
|
118
|
+
Object.assign(newProps, { numberOfLines: 1 })
|
|
119
|
+
}
|
|
97
120
|
return newProps
|
|
98
|
-
}, [onLayout, onMouseEnter, onMouseLeave, style])
|
|
121
|
+
}, [finalStyle.textOverflow, onLayout, onMouseEnter, onMouseLeave, props.style, styleConvertedFromCSS])
|
|
122
|
+
|
|
123
|
+
React.useEffect(() => () => removeStyle(hash), [hash])
|
|
99
124
|
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
// if (em !== currentFontSize) {
|
|
103
|
-
if (style.fontSize) {
|
|
125
|
+
// em !== parentEm alone is a bit dangerous as the component would rerender when the font size change
|
|
126
|
+
if (em !== parentEm || finalStyle.fontSize !== undefined) {
|
|
104
127
|
return <FontSizeContext.Provider value={em}>
|
|
105
128
|
<Component ref={ref} {...props} {...newProps} />
|
|
106
129
|
</FontSizeContext.Provider>
|