rn-css 1.6.6 → 1.6.9
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 -13
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
- package/src/features.tsx +1 -1
- package/src/styleComponent.tsx +34 -14
- 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) => {
|
|
@@ -30,15 +48,10 @@ const styled = (Component) => {
|
|
|
30
48
|
// Build the css string with the context
|
|
31
49
|
const css = react_1.default.useMemo(() => buildCSSString(chunks, functs, props, shared), [props, shared]);
|
|
32
50
|
// Store the style in RN format
|
|
33
|
-
const
|
|
34
|
-
react_1.default.useEffect(() => {
|
|
35
|
-
// Try to load an existing style from the style map or save it for next time
|
|
36
|
-
const style = (0, cssToRN_1.default)(css);
|
|
37
|
-
setRNStyle(style);
|
|
38
|
-
}, [css]);
|
|
51
|
+
const rnStyle = react_1.default.useMemo(() => (0, cssToRN_1.default)(css), [css]);
|
|
39
52
|
const { needsLayout, needsHover } = react_1.default.useMemo(() => ({
|
|
40
53
|
// needsFontSize: !!css.match(/\b(\d+)(\.\d+)?em\b/)
|
|
41
|
-
// needsScreenSize: !!
|
|
54
|
+
// needsScreenSize: !!css.match(/\b(\d+)(\.\d*)?v([hw]|min|max)\b/) || !!rnStyle.media,
|
|
42
55
|
needsLayout: !!css.match(/\d%/),
|
|
43
56
|
needsHover: !!rnStyle.hover
|
|
44
57
|
}), [css, rnStyle.hover]);
|
|
@@ -82,18 +95,24 @@ const styled = (Component) => {
|
|
|
82
95
|
return style;
|
|
83
96
|
}, [em, mediaQuery, tempStyle]);
|
|
84
97
|
const units = react_1.default.useMemo(() => ({ ...baseUnits, em }), [baseUnits, em]);
|
|
85
|
-
const styleConvertedFromCSS = react_1.default.useMemo(() =>
|
|
86
|
-
|
|
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]);
|
|
87
104
|
const newProps = react_1.default.useMemo(() => {
|
|
88
|
-
const newProps = { style, onMouseEnter, onMouseLeave, onLayout };
|
|
89
|
-
if (
|
|
105
|
+
const newProps = { style: [styleConvertedFromCSS, props.style], onMouseEnter, onMouseLeave, onLayout };
|
|
106
|
+
if (finalStyle.textOverflow === 'ellipsis') {
|
|
90
107
|
Object.assign(newProps, { numberOfLines: 1 });
|
|
108
|
+
}
|
|
91
109
|
return newProps;
|
|
92
|
-
}, [onLayout, onMouseEnter, onMouseLeave, style]);
|
|
110
|
+
}, [finalStyle.textOverflow, onLayout, onMouseEnter, onMouseLeave, props.style, styleConvertedFromCSS]);
|
|
111
|
+
react_1.default.useEffect(() => () => removeStyle(hash), [hash]);
|
|
93
112
|
// The lines below can improve perfs, but it causes the component to remount when the font size changes
|
|
94
113
|
// const currentFontSize = React.useContext(FontSizeContext)
|
|
95
114
|
// if (em !== currentFontSize) {
|
|
96
|
-
if (
|
|
115
|
+
if (styleConvertedFromCSS.fontSize) {
|
|
97
116
|
return react_1.default.createElement(exports.FontSizeContext.Provider, { value: em },
|
|
98
117
|
react_1.default.createElement(Component, { ref: ref, ...props, ...newProps }));
|
|
99
118
|
}
|
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) => {
|
|
@@ -37,16 +54,11 @@ const styled = <Props, >(Component: React.ComponentType<Props>) => {
|
|
|
37
54
|
// Build the css string with the context
|
|
38
55
|
const css = React.useMemo(() => buildCSSString(chunks, functs, props, shared), [props, shared])
|
|
39
56
|
// Store the style in RN format
|
|
40
|
-
const
|
|
41
|
-
React.useEffect(() => {
|
|
42
|
-
// Try to load an existing style from the style map or save it for next time
|
|
43
|
-
const style = cssToStyle(css)
|
|
44
|
-
setRNStyle(style)
|
|
45
|
-
}, [css])
|
|
57
|
+
const rnStyle = React.useMemo(() => cssToStyle(css), [css])
|
|
46
58
|
|
|
47
59
|
const { needsLayout, needsHover } = React.useMemo(() => ({
|
|
48
60
|
// needsFontSize: !!css.match(/\b(\d+)(\.\d+)?em\b/)
|
|
49
|
-
// needsScreenSize: !!
|
|
61
|
+
// needsScreenSize: !!css.match(/\b(\d+)(\.\d*)?v([hw]|min|max)\b/) || !!rnStyle.media,
|
|
50
62
|
needsLayout: !!css.match(/\d%/),
|
|
51
63
|
needsHover: !!rnStyle.hover
|
|
52
64
|
}), [css, rnStyle.hover])
|
|
@@ -94,18 +106,26 @@ const styled = <Props, >(Component: React.ComponentType<Props>) => {
|
|
|
94
106
|
|
|
95
107
|
const units = React.useMemo<Units>(() => ({ ...baseUnits, em }), [baseUnits, em])
|
|
96
108
|
|
|
97
|
-
const styleConvertedFromCSS = React.useMemo(() =>
|
|
98
|
-
|
|
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])
|
|
99
115
|
const newProps = React.useMemo(() => {
|
|
100
|
-
const newProps: OptionalProps = { style, onMouseEnter, onMouseLeave, onLayout }
|
|
101
|
-
if (
|
|
116
|
+
const newProps: OptionalProps = { style: [styleConvertedFromCSS, props.style], onMouseEnter, onMouseLeave, onLayout }
|
|
117
|
+
if (finalStyle.textOverflow === 'ellipsis') {
|
|
118
|
+
Object.assign(newProps, { numberOfLines: 1 })
|
|
119
|
+
}
|
|
102
120
|
return newProps
|
|
103
|
-
}, [onLayout, onMouseEnter, onMouseLeave, style])
|
|
121
|
+
}, [finalStyle.textOverflow, onLayout, onMouseEnter, onMouseLeave, props.style, styleConvertedFromCSS])
|
|
122
|
+
|
|
123
|
+
React.useEffect(() => () => removeStyle(hash), [hash])
|
|
104
124
|
|
|
105
125
|
// The lines below can improve perfs, but it causes the component to remount when the font size changes
|
|
106
126
|
// const currentFontSize = React.useContext(FontSizeContext)
|
|
107
127
|
// if (em !== currentFontSize) {
|
|
108
|
-
if (
|
|
128
|
+
if (styleConvertedFromCSS.fontSize) {
|
|
109
129
|
return <FontSizeContext.Provider value={em}>
|
|
110
130
|
<Component ref={ref} {...props} {...newProps} />
|
|
111
131
|
</FontSizeContext.Provider>
|