rn-css 1.8.13 → 1.9.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 (40) hide show
  1. package/README.md +16 -0
  2. package/dist/app.json +4 -0
  3. package/dist/cssToRN/convert.js +26 -6
  4. package/dist/index.d.ts +3 -1439
  5. package/dist/index.js +166 -56
  6. package/dist/src/convertStyle.d.ts +5 -0
  7. package/dist/src/convertStyle.js +56 -0
  8. package/dist/src/convertUnits.d.ts +5 -0
  9. package/dist/src/convertUnits.js +71 -0
  10. package/dist/src/cssToRN/convert.d.ts +55 -0
  11. package/dist/src/cssToRN/convert.js +418 -0
  12. package/dist/src/cssToRN/index.d.ts +8 -0
  13. package/dist/src/cssToRN/index.js +134 -0
  14. package/dist/src/cssToRN/maths.d.ts +4 -0
  15. package/dist/src/cssToRN/maths.js +86 -0
  16. package/dist/src/cssToRN/mediaQueries.d.ts +7 -0
  17. package/dist/src/cssToRN/mediaQueries.js +161 -0
  18. package/dist/src/features.d.ts +34 -0
  19. package/dist/src/features.js +102 -0
  20. package/dist/src/generateHash.d.ts +2 -0
  21. package/dist/src/generateHash.js +8 -0
  22. package/dist/src/index.d.ts +1805 -0
  23. package/dist/src/index.js +60 -0
  24. package/dist/src/polyfill.d.ts +3 -0
  25. package/dist/src/polyfill.js +23 -0
  26. package/dist/src/rnToCss.d.ts +3 -0
  27. package/dist/src/rnToCss.js +8 -0
  28. package/dist/src/styleComponent.d.ts +45 -0
  29. package/dist/src/styleComponent.js +163 -0
  30. package/dist/src/types.d.ts +85 -0
  31. package/dist/src/types.js +2 -0
  32. package/dist/src/useTheme.d.ts +18 -0
  33. package/dist/src/useTheme.js +33 -0
  34. package/package.json +1 -1
  35. package/src/cssToRN/convert.ts +25 -6
  36. package/src/cssToRN/index.ts +7 -1
  37. package/src/features.tsx +15 -1
  38. package/src/styleComponent.tsx +15 -8
  39. package/src/types.ts +1 -0
  40. package/CHANGELOG.md +0 -25
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createMedia = exports.createContext = void 0;
4
+ const convertUnits_1 = require("../convertUnits");
5
+ const react_native_1 = require("react-native");
6
+ function createContext(units) {
7
+ const vw = (units.vw || 1) * 100;
8
+ const vh = (units.vh || 1) * 100;
9
+ return {
10
+ anyHover: 'hover',
11
+ anyPointer: react_native_1.Platform.OS === 'web' ? 'fine' : 'coarse',
12
+ aspectRatio: vw / vh,
13
+ color: 16,
14
+ colorGamut: 'srgb',
15
+ colorIndex: 0,
16
+ deviceAspectRatio: vw / vh,
17
+ deviceHeight: vh,
18
+ deviceWidth: vw,
19
+ dynamicRange: 'standard',
20
+ environmentBlending: 'opaque',
21
+ forcedColor: 'none',
22
+ grid: 0,
23
+ height: vh,
24
+ hover: 'hover',
25
+ invertedColors: 'none',
26
+ monochrome: 0,
27
+ orientation: vw > vh ? 'landscape' : 'portrait',
28
+ overflowBlock: 'scroll',
29
+ overflowInline: 'scroll',
30
+ pointer: 'coarse',
31
+ prefersColorScheme: 'dark',
32
+ prefersContrast: 'no-preference',
33
+ prefersReducedData: 'no-preference',
34
+ prefersReducedMotion: 'no-preference',
35
+ prefersReducedTransparency: 'no-preference',
36
+ resolution: react_native_1.PixelRatio.getPixelSizeForLayoutSize(vw),
37
+ scan: 'progressive',
38
+ scripting: 'enabled',
39
+ type: 'screen',
40
+ units,
41
+ update: 'fast',
42
+ width: vw
43
+ };
44
+ }
45
+ exports.createContext = createContext;
46
+ function convertAnyValue(key, value, units) {
47
+ if (key === 'resolution') {
48
+ // Convert density
49
+ if (value === 'infinite')
50
+ return Infinity;
51
+ const densityUnitsEquivalence = {
52
+ dpi: 'in',
53
+ dpcm: 'cm',
54
+ dppx: 'px',
55
+ x: 'px'
56
+ };
57
+ const [num, unit] = (0, convertUnits_1.parseValue)(value);
58
+ return num + densityUnitsEquivalence[unit];
59
+ }
60
+ else if (key === 'deviceAspectRatio' || key === 'aspectRatio') {
61
+ // Convert ratio
62
+ const [w, h] = value.split('/').map(v => parseInt(v, 10));
63
+ return w / h;
64
+ }
65
+ return (0, convertUnits_1.convertValue)(key, value, units);
66
+ }
67
+ /** Check if a constraint is respected by the provided context */
68
+ function evaluateConstraint(constraint, context) {
69
+ return Object.keys(constraint).every(key => {
70
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
71
+ const [, baseKey, minMax] = key.match(/(.*?)(Min|Max|$)/);
72
+ const value = convertAnyValue(baseKey, constraint[key] + '', context.units);
73
+ if (minMax === 'Min') {
74
+ return context[baseKey] >= value;
75
+ }
76
+ else if (key.endsWith('Max')) {
77
+ return context[baseKey] <= value;
78
+ }
79
+ else if (['all', 'sprint', 'speech', 'screen'].includes(key)) {
80
+ return context.type === key || key === 'all';
81
+ }
82
+ else {
83
+ // Boolean check: we want the value to be defined and not equal to 'none'
84
+ if (value === undefined)
85
+ return !!context[baseKey] && context[baseKey] !== 'none';
86
+ // float comparison
87
+ if (baseKey.endsWith('aspectRatio'))
88
+ return Math.abs(context[baseKey] - value) < (value + context[baseKey]) / 100;
89
+ return context[baseKey] === value;
90
+ }
91
+ });
92
+ }
93
+ /** Parse media query constraint such as min-width: 600px, or screen */
94
+ function parseConstraintValue(constraintString) {
95
+ let [key, value] = constraintString.split(':').map(v => v.trim());
96
+ if (key.startsWith('min-'))
97
+ key = key.substring(4) + 'Min';
98
+ else if (key.startsWith('max-'))
99
+ key = key.substring(4) + 'Max';
100
+ const constraint = { [key]: value };
101
+ return (context) => evaluateConstraint(constraint, context);
102
+ }
103
+ function parse(constraint, previous) {
104
+ const result = constraint.match(/\sand\s|,|\sonly\s|\(|\snot\s/im);
105
+ if (!result) {
106
+ // If we reached the end of the string, we just return the last constraint
107
+ if (constraint.match(/\w/))
108
+ return parseConstraintValue(constraint);
109
+ // If there is just an empty string, we just ignore it by returning a truthy evaluation
110
+ else
111
+ return previous || (() => true);
112
+ }
113
+ const token = result[0]; // The next command we found
114
+ const tail = constraint.substring(result.index + token.length); // The rest of the constraint
115
+ const current = constraint.substring(0, result.index); // The current constraint
116
+ if (token === '(') {
117
+ try {
118
+ const { index } = tail.match(/\)/);
119
+ const parenthesis = tail.substring(0, index);
120
+ const postParenthesis = tail.substring(index + 1);
121
+ return parse(postParenthesis, parse(parenthesis, previous));
122
+ }
123
+ catch (err) {
124
+ console.error('No matching parenthesis in the media query', constraint);
125
+ throw err;
126
+ }
127
+ }
128
+ else if (token.includes('and')) {
129
+ const left = previous || parseConstraintValue(current);
130
+ const right = parse(tail);
131
+ return (context) => left(context) && right(context);
132
+ }
133
+ else if (token.includes('not')) {
134
+ const evaluate = parse(tail);
135
+ return (context) => !evaluate(context);
136
+ }
137
+ else if (token.includes('only')) {
138
+ return parse(tail, previous || parseConstraintValue(current));
139
+ }
140
+ else if (token === ',') {
141
+ const left = previous || parseConstraintValue(current);
142
+ const right = parse(tail);
143
+ return (context) => left(context) || right(context);
144
+ }
145
+ else {
146
+ throw new Error(`Error while parsing media query '${constraint}'. No token found`);
147
+ }
148
+ }
149
+ const createMedia = (query) => {
150
+ // We use [\s\S] instead of dotall flag (s) because it is not supported by react-native-windows
151
+ const parsed = query.match(/@media([\s\S]*?){([^{}]*)}/mi);
152
+ if (!parsed)
153
+ throw new Error(`Parsing error: check the syntax of media query ${query}.`);
154
+ const [, constraints, css] = parsed;
155
+ const isValid = parse(constraints);
156
+ return {
157
+ css,
158
+ isValid
159
+ };
160
+ };
161
+ exports.createMedia = createMedia;
@@ -0,0 +1,34 @@
1
+ import { MouseEvent } from 'react';
2
+ import type { Style, Units, MediaQuery } from './types';
3
+ import { LayoutChangeEvent, NativeSyntheticEvent, TargetedEvent } from 'react-native';
4
+ /** Hook that will apply the screen size to the styles defined with vmin, vmax, vw, vh units, and handle media queries constraints */
5
+ export declare const useScreenSize: () => {
6
+ vw: number;
7
+ vh: number;
8
+ vmin: number;
9
+ vmax: number;
10
+ };
11
+ /** Hook that will apply the style reserved for hover state if needed */
12
+ export declare const useHover: (onMouseEnter: ((event: MouseEvent) => void) | undefined, onMouseLeave: ((event: MouseEvent) => void | undefined) | undefined, needsHover: boolean) => {
13
+ hover: boolean;
14
+ onMouseEnter: ((event: MouseEvent) => void) | undefined;
15
+ onMouseLeave: ((event: MouseEvent) => void | undefined) | undefined;
16
+ };
17
+ /** Hook that will apply the style reserved for active state if needed */
18
+ export declare const useActive: (onFocus: ((event: NativeSyntheticEvent<TargetedEvent>) => void) | undefined, onBlur: ((event: NativeSyntheticEvent<TargetedEvent>) => void | undefined) | undefined, needsFocus: boolean) => {
19
+ active: boolean;
20
+ onFocus: ((event: NativeSyntheticEvent<TargetedEvent>) => void) | undefined;
21
+ onBlur: ((event: NativeSyntheticEvent<TargetedEvent>) => void | undefined) | undefined;
22
+ };
23
+ /** Hook that will apply the style provided in the media queries */
24
+ export declare const useMediaQuery: (media: undefined | MediaQuery[], units: Units) => Style | undefined;
25
+ /** Hook that will measure the layout to handle styles that use % units */
26
+ export declare const useLayout: (onLayout: ((event: LayoutChangeEvent) => void) | undefined, needsLayout: boolean) => {
27
+ width: number;
28
+ height: number;
29
+ onLayout: ((event: LayoutChangeEvent) => void) | undefined;
30
+ };
31
+ /** Apply the new fontSize to the component before we can calculate em units */
32
+ export declare const useFontSize: (fontSizeTarget: string | undefined, rem: number, em: number) => {
33
+ em: number;
34
+ };
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.useFontSize = exports.useLayout = exports.useMediaQuery = exports.useActive = exports.useHover = exports.useScreenSize = void 0;
7
+ /* eslint-disable react/display-name */
8
+ const react_1 = __importDefault(require("react"));
9
+ const react_native_1 = require("react-native");
10
+ const convertUnits_1 = require("./convertUnits");
11
+ const mediaQueries_1 = require("./cssToRN/mediaQueries");
12
+ /** Hook that will apply the screen size to the styles defined with vmin, vmax, vw, vh units, and handle media queries constraints */
13
+ const useScreenSize = () => {
14
+ const { width, height } = (0, react_native_1.useWindowDimensions)();
15
+ return react_1.default.useMemo(() => ({
16
+ vw: width / 100, vh: height / 100, vmin: Math.min(width, height) / 100, vmax: Math.max(width, height) / 100
17
+ }), [height, width]);
18
+ };
19
+ exports.useScreenSize = useScreenSize;
20
+ /** Hook that will apply the style reserved for hover state if needed */
21
+ const useHover = (onMouseEnter, onMouseLeave, needsHover) => {
22
+ const [hover, setHover] = react_1.default.useState(false);
23
+ const hoverStart = react_1.default.useMemo(() => needsHover ? (event) => {
24
+ if (onMouseEnter)
25
+ onMouseEnter(event);
26
+ setHover(true);
27
+ } : undefined, [needsHover, onMouseEnter]);
28
+ const hoverStop = react_1.default.useMemo(() => needsHover ? (event) => {
29
+ if (onMouseLeave)
30
+ onMouseLeave(event);
31
+ setHover(false);
32
+ } : undefined, [needsHover, onMouseLeave]);
33
+ return { hover, onMouseEnter: hoverStart || onMouseEnter, onMouseLeave: hoverStop || onMouseLeave };
34
+ };
35
+ exports.useHover = useHover;
36
+ /** Hook that will apply the style reserved for active state if needed */
37
+ const useActive = (onFocus, onBlur, needsFocus) => {
38
+ const [active, setActive] = react_1.default.useState(false);
39
+ const focusStart = react_1.default.useMemo(() => needsFocus ? (event) => {
40
+ if (onFocus)
41
+ onFocus(event);
42
+ setActive(true);
43
+ } : undefined, [needsFocus, onFocus]);
44
+ const focusStop = react_1.default.useMemo(() => needsFocus ? (event) => {
45
+ if (onBlur)
46
+ onBlur(event);
47
+ setActive(false);
48
+ } : undefined, [needsFocus, onBlur]);
49
+ return { active, onFocus: focusStart || onFocus, onBlur: focusStop || onBlur };
50
+ };
51
+ exports.useActive = useActive;
52
+ /** Hook that will apply the style provided in the media queries */
53
+ const useMediaQuery = (media, units) => {
54
+ const mediaStyle = react_1.default.useMemo(() => {
55
+ if (media) {
56
+ const context = (0, mediaQueries_1.createContext)(units);
57
+ const mediaStyles = media.map(m => m(context)).filter(m => !!m);
58
+ if (!mediaStyles.length)
59
+ return;
60
+ const mq = {};
61
+ Object.assign(mq, ...mediaStyles);
62
+ return mq;
63
+ }
64
+ }, [media, units]);
65
+ return mediaStyle;
66
+ };
67
+ exports.useMediaQuery = useMediaQuery;
68
+ /** Hook that will measure the layout to handle styles that use % units */
69
+ const useLayout = (onLayout, needsLayout) => {
70
+ const [layout, setLayout] = react_1.default.useState({ width: 0, height: 0 });
71
+ // Prevent calling setState if the component is unmounted
72
+ const unmounted = react_1.default.useRef(false);
73
+ react_1.default.useEffect(() => () => { unmounted.current = true; }, []);
74
+ const updateLayout = react_1.default.useMemo(() => needsLayout ? (event) => {
75
+ if (unmounted.current)
76
+ return;
77
+ if (onLayout)
78
+ onLayout(event);
79
+ const { width, height } = event.nativeEvent.layout;
80
+ setLayout(layout => layout.width === width && layout.height === height ? layout : { width, height });
81
+ } : undefined, [needsLayout, onLayout]);
82
+ return { onLayout: updateLayout || onLayout, ...layout };
83
+ };
84
+ exports.useLayout = useLayout;
85
+ /** Apply the new fontSize to the component before we can calculate em units */
86
+ const useFontSize = (fontSizeTarget, rem, em) => {
87
+ const [fontSize, fontUnit] = react_1.default.useMemo(() => fontSizeTarget === undefined ? [] : (0, convertUnits_1.parseValue)(fontSizeTarget), [fontSizeTarget]);
88
+ const isRelative = fontUnit && ['rem', 'em', '%'].includes(fontUnit);
89
+ const newSize = react_1.default.useMemo(() => {
90
+ if (fontSize && isRelative) {
91
+ const newSize = fontUnit === 'em' ? em * fontSize
92
+ : fontUnit === 'rem' ? fontSize * rem
93
+ : fontUnit === '%' ? em * (1 + fontSize / 100)
94
+ : fontSize;
95
+ return newSize;
96
+ }
97
+ else
98
+ return fontSize || em;
99
+ }, [em, fontSize, fontUnit, isRelative, rem]);
100
+ return { em: newSize };
101
+ };
102
+ exports.useFontSize = useFontSize;
@@ -0,0 +1,2 @@
1
+ declare const _default: (value: string) => string;
2
+ export default _default;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = (value) => {
4
+ let h = 0;
5
+ for (let i = 0; i < value.length; i++)
6
+ h = Math.imul(31, h) + value.charCodeAt(i) | 0;
7
+ return h.toString(36);
8
+ };