react-native-unistyles 2.0.0-alpha.5 → 2.0.0-alpha.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. package/cxx/UnistylesRuntime.cpp +262 -0
  2. package/cxx/UnistylesRuntime.h +61 -0
  3. package/lib/commonjs/Unistyles.js +1 -1
  4. package/lib/commonjs/Unistyles.js.map +1 -1
  5. package/lib/commonjs/UnistylesEngine.js +9 -5
  6. package/lib/commonjs/UnistylesEngine.js.map +1 -1
  7. package/lib/commonjs/createStyleSheet.js.map +1 -1
  8. package/lib/commonjs/types/cxx.js.map +1 -1
  9. package/lib/commonjs/useStyles.js +0 -2
  10. package/lib/commonjs/useStyles.js.map +1 -1
  11. package/lib/commonjs/utils/breakpoints.js +11 -68
  12. package/lib/commonjs/utils/breakpoints.js.map +1 -1
  13. package/lib/commonjs/utils/common.js +3 -1
  14. package/lib/commonjs/utils/common.js.map +1 -1
  15. package/lib/commonjs/utils/mediaQueries.js +57 -155
  16. package/lib/commonjs/utils/mediaQueries.js.map +1 -1
  17. package/lib/commonjs/utils/styles.js +11 -51
  18. package/lib/commonjs/utils/styles.js.map +1 -1
  19. package/lib/module/Unistyles.js +2 -2
  20. package/lib/module/Unistyles.js.map +1 -1
  21. package/lib/module/UnistylesEngine.js +7 -3
  22. package/lib/module/UnistylesEngine.js.map +1 -1
  23. package/lib/module/createStyleSheet.js.map +1 -1
  24. package/lib/module/types/cxx.js.map +1 -1
  25. package/lib/module/useStyles.js +0 -3
  26. package/lib/module/useStyles.js.map +1 -1
  27. package/lib/module/utils/breakpoints.js +11 -68
  28. package/lib/module/utils/breakpoints.js.map +1 -1
  29. package/lib/module/utils/common.js +2 -0
  30. package/lib/module/utils/common.js.map +1 -1
  31. package/lib/module/utils/mediaQueries.js +57 -155
  32. package/lib/module/utils/mediaQueries.js.map +1 -1
  33. package/lib/module/utils/styles.js +10 -51
  34. package/lib/module/utils/styles.js.map +1 -1
  35. package/lib/typescript/src/Unistyles.d.ts +2 -2
  36. package/lib/typescript/src/Unistyles.d.ts.map +1 -1
  37. package/lib/typescript/src/UnistylesEngine.d.ts +4 -1
  38. package/lib/typescript/src/UnistylesEngine.d.ts.map +1 -1
  39. package/lib/typescript/src/createStyleSheet.d.ts +2 -5
  40. package/lib/typescript/src/createStyleSheet.d.ts.map +1 -1
  41. package/lib/typescript/src/types/breakpoints.d.ts +2 -1
  42. package/lib/typescript/src/types/breakpoints.d.ts.map +1 -1
  43. package/lib/typescript/src/types/core.d.ts +18 -16
  44. package/lib/typescript/src/types/core.d.ts.map +1 -1
  45. package/lib/typescript/src/types/cxx.d.ts +7 -1
  46. package/lib/typescript/src/types/cxx.d.ts.map +1 -1
  47. package/lib/typescript/src/types/index.d.ts +1 -1
  48. package/lib/typescript/src/types/index.d.ts.map +1 -1
  49. package/lib/typescript/src/types/mediaQueries.d.ts +5 -3
  50. package/lib/typescript/src/types/mediaQueries.d.ts.map +1 -1
  51. package/lib/typescript/src/useStyles.d.ts +1 -3
  52. package/lib/typescript/src/useStyles.d.ts.map +1 -1
  53. package/lib/typescript/src/utils/breakpoints.d.ts +2 -60
  54. package/lib/typescript/src/utils/breakpoints.d.ts.map +1 -1
  55. package/lib/typescript/src/utils/common.d.ts +2 -0
  56. package/lib/typescript/src/utils/common.d.ts.map +1 -1
  57. package/lib/typescript/src/utils/mediaQueries.d.ts +8 -127
  58. package/lib/typescript/src/utils/mediaQueries.d.ts.map +1 -1
  59. package/lib/typescript/src/utils/styles.d.ts +1 -46
  60. package/lib/typescript/src/utils/styles.d.ts.map +1 -1
  61. package/package.json +10 -1
  62. package/src/Unistyles.ts +3 -3
  63. package/src/UnistylesEngine.ts +12 -3
  64. package/src/createStyleSheet.ts +2 -5
  65. package/src/types/breakpoints.ts +6 -3
  66. package/src/types/core.ts +25 -22
  67. package/src/types/cxx.ts +8 -1
  68. package/src/types/index.ts +1 -1
  69. package/src/types/mediaQueries.ts +9 -4
  70. package/src/useStyles.ts +3 -6
  71. package/src/utils/breakpoints.ts +14 -71
  72. package/src/utils/common.ts +2 -0
  73. package/src/utils/mediaQueries.ts +102 -163
  74. package/src/utils/styles.ts +13 -55
@@ -1,29 +1,9 @@
1
1
  import { unistyles } from '../Unistyles'
2
2
  import { isMobile, Orientation, throwError } from './common'
3
- import type { ScreenSize, MediaQueries } from '../types'
3
+ import type { MediaQueries } from '../types'
4
4
  import { ScreenOrientation } from '../types'
5
- import { getKeyForCustomMediaQuery, isMediaQuery } from './mediaQueries'
6
5
  import type { UnistylesBreakpoints } from '../global'
7
6
 
8
- /**
9
- * Sorts the breakpoints object based on its numeric values in ascending order and validates them.
10
- *
11
- * This function takes an object where keys represent breakpoint names and values are numeric.
12
- * It returns a new object with the same keys but sorted based on their corresponding numeric values.
13
- * Additionally, it validates that:
14
- * 1. The first breakpoint starts with a value of 0.
15
- * 2. No duplicate breakpoint values exist.
16
- *
17
- * If the validation fails, appropriate error messages are logged to the console.
18
- *
19
- * @template B - An object type where keys are strings and values are numbers.
20
- * @param {B} breakpoints - The breakpoints object to be sorted and validated.
21
- * @returns {B} A new object with sorted and validated breakpoints.
22
- *
23
- * @example
24
- * const input = { md: 768, lg: 1024, sm: 0 }
25
- * sortAndValidateBreakpoints(input) // returns { sm: 0, md: 768, lg: 1024 }
26
- */
27
7
  export const sortAndValidateBreakpoints = (breakpoints: UnistylesBreakpoints): UnistylesBreakpoints => {
28
8
  const sortedPairs = Object
29
9
  .entries(breakpoints)
@@ -49,21 +29,6 @@ export const sortAndValidateBreakpoints = (breakpoints: UnistylesBreakpoints): U
49
29
  return sortedBreakpoints
50
30
  }
51
31
 
52
- /**
53
- * Determines the appropriate breakpoint key for a given screen width based on provided breakpoints.
54
- *
55
- * This function takes a screen width and an object of breakpoints. It returns the key of the breakpoint
56
- * that the screen width falls into. The breakpoints are assumed to be sorted in ascending order.
57
- *
58
- * @template B - An object type where keys are strings and values are numbers representing screen widths.
59
- * @param {number} width - The screen width to determine the breakpoint for.
60
- * @param breakpointEntries - sorted pairs of breakpoints
61
- * @returns {keyof B & string} The key of the breakpoint that the screen width falls into.
62
- *
63
- * @example
64
- * const breakpoints = { sm: 0, md: 768, lg: 1024 }
65
- * getBreakpointFromScreenWidth(800, breakpoints) // returns 'md'
66
- */
67
32
  export const getBreakpointFromScreenWidth = (width: number, breakpointEntries: Array<[keyof UnistylesBreakpoints, UnistylesBreakpoints[keyof UnistylesBreakpoints]]>): keyof UnistylesBreakpoints & string => {
68
33
  const [key] = breakpointEntries
69
34
  .find(([, value], index, otherBreakpoints) => {
@@ -80,40 +45,13 @@ export const getBreakpointFromScreenWidth = (width: number, breakpointEntries: A
80
45
  return key
81
46
  }
82
47
 
83
- /**
84
- * Retrieves the value associated with a given breakpoint or custom media query based on the provided screen size.
85
- *
86
- * The function first checks for custom media queries. If a matching custom media query is found, its associated value is returned.
87
- * If no custom media query matches, the function then checks for a direct breakpoint match.
88
- * If there's no direct breakpoint match, the function simulates CSS cascading to find the closest matching breakpoint.
89
- *
90
- * @template B - An object type where keys represent breakpoint names and values represent breakpoint values.
91
- *
92
- * @param {Record<keyof B & string, string | number>} value - An object containing values associated with breakpoints or custom media queries.
93
- * @param {keyof B & string} breakpoint - The breakpoint name to check against.
94
- * @param {ScreenSize} screenSize - An object representing the screen size to be checked against the media queries.
95
- * @param breakpointPairs - sorted pairs of breakpoints
96
- *
97
- * @returns {string | number | undefined} Returns the value associated with the matching breakpoint or custom media query, or `undefined` if no match is found.
98
- *
99
- * @example
100
- *
101
- * const values = { ':w[200]': 'value1', sm: 'value2', md: 'value3' }
102
- * const screenSize = { width: 250, height: 400 }
103
- * const breakpoints = { sm: 300, md: 600, lg: 900 }
104
- *
105
- * getValueForBreakpoint(values, 'sm', screenSize, breakpoints); // 'value1'
106
- */
107
- export const getValueForBreakpoint = (
108
- value: Record<keyof UnistylesBreakpoints | MediaQueries, string | number | undefined>,
109
- breakpoint: keyof UnistylesBreakpoints,
110
- screenSize: ScreenSize
111
- ): string | number | undefined => {
48
+ export const getValueForBreakpoint = (value: Record<keyof UnistylesBreakpoints | MediaQueries, string | number | undefined>): string | number | undefined => {
112
49
  // the highest priority is for custom media queries
113
50
  const customMediaQueries = Object
114
51
  .entries(value)
115
- .filter(([key]) => isMediaQuery(key))
116
- const customMediaQueryKey = getKeyForCustomMediaQuery(customMediaQueries, screenSize) as keyof typeof value
52
+ .filter(([key]) => unistyles.engine.isMediaQuery(key)) as Array<[keyof UnistylesBreakpoints | MediaQueries, string | number | undefined]>
53
+ // const customMediaQueryKey = getKeyForCustomMediaQuery(customMediaQueries, screenSize) as keyof typeof value
54
+ const customMediaQueryKey = unistyles.engine.didMatchMediaQuery(customMediaQueries) as keyof typeof value
117
55
 
118
56
  if (customMediaQueryKey && customMediaQueryKey in value) {
119
57
  return value[customMediaQueryKey]
@@ -132,19 +70,24 @@ export const getValueForBreakpoint = (
132
70
  ]
133
71
  }
134
72
 
73
+ const breakpoint = unistyles.runtime.breakpoint
74
+
75
+ if (!breakpoint) {
76
+ return undefined
77
+ }
78
+
135
79
  // if user defined breakpoints, then we look for the valid one
136
- const unifiedKey = breakpoint?.toLowerCase() as keyof typeof value
137
- const directBreakpoint = value[unifiedKey]
80
+ const directBreakpoint = value[breakpoint]
138
81
 
139
82
  // if there is a direct key like 'sm' or 'md', or value for this key exists but its undefined
140
- if (directBreakpoint || (unifiedKey in value)) {
83
+ if (directBreakpoint || (breakpoint in value)) {
141
84
  return directBreakpoint
142
85
  }
143
86
 
144
87
  // there is no direct hit for breakpoint nor media-query, let's simulate CSS cascading
145
88
  const breakpointPairs = unistyles.runtime.sortedBreakpoints
146
89
  const currentBreakpoint = breakpointPairs
147
- .findIndex(([key]) => key === unifiedKey)
90
+ .findIndex(([key]) => key === breakpoint)
148
91
 
149
92
  const availableBreakpoints = breakpointPairs
150
93
  .filter(([key], index) => index < currentBreakpoint && key && key in value)
@@ -10,6 +10,8 @@ export const warn = (message: string) => {
10
10
 
11
11
  export const isMobile = Platform.OS === 'android' || Platform.OS === 'ios'
12
12
  export const isWeb = Platform.OS === 'web'
13
+ export const isIOS = Platform.OS === 'ios'
14
+ export const isAndroid = Platform.OS === 'android'
13
15
  export const isServer = typeof window === 'undefined'
14
16
 
15
17
  export const Orientation = {
@@ -1,92 +1,110 @@
1
+ import type { UnistylesBreakpoints } from 'react-native-unistyles'
1
2
  import type { ScreenSize } from '../types'
3
+ import type { MediaQueries } from '../types'
4
+
5
+ const parseLhs = (lhs: string, breakpoints: UnistylesBreakpoints, hasRhs: boolean) => {
6
+ const matches = lhs.match(/([([])|([^[\]()]+)|([\])])/g)
7
+
8
+ if (!hasRhs) {
9
+ const [openBracket, value, closeBracket] = matches as [string, string, string]
10
+ const spacelessValue = value?.trim()
11
+ const parsedNumber = Number(spacelessValue)
12
+
13
+ const parsedValue = isNaN(parsedNumber)
14
+ ? breakpoints[spacelessValue as keyof UnistylesBreakpoints] as number
15
+ : parsedNumber
16
+
17
+ return [
18
+ Number(openBracket === '('),
19
+ closeBracket === ')'
20
+ ? parsedValue - 1
21
+ : parsedValue
22
+ ]
23
+ }
24
+
25
+ const [openBracket, value] = matches as [string, string]
2
26
 
3
- /**
4
- * Extracts numeric values from a coded string.
5
- *
6
- * The function is designed to process strings that have a format like "w[100,200]" or "h[300]".
7
- * It removes characters 'w', 'h', '[', and ']' from the input string and then extracts the numbers.
8
- *
9
- * @param {string} codedValue - The input string to extract values from.
10
- * @returns {Array<number>} An array of extracted numbers. Can contain one or two numbers based on the input format.
11
- *
12
- * @example
13
- * extractValues("w[100,200]") // returns [100, 200]
14
- * extractValues("h[300]") // returns [300]
15
- * extractValues("h[,300]") // returns [0,300]
16
- * extractValues("h[100,]") // returns [100]
17
- */
18
- export const extractValues = (codedValue: string): Array<number> => {
19
- const cleanedValue = codedValue.replace(/[wh ]/g, '')
20
- const [left, right] = cleanedValue.split(',') as [string, string | undefined]
21
-
22
- if (!right) {
23
- const lh = left.startsWith('[')
24
- ? Number(left.replace(/[[\]()]/g, ''))
25
- : Number(left.replace(/[[\]()]/g, '')) + 1
26
-
27
- return [lh]
27
+ if (!value) {
28
+ return [Number(openBracket === '(')]
28
29
  }
29
30
 
30
- const lh = left.startsWith('[')
31
- ? Number(left.replace('[', ''))
32
- : Number(left.replace('(', '')) + 1
33
- const rh = right.endsWith(']')
34
- ? Number(right.replace(']', ''))
35
- : Number(right.replace(')', '')) - 1
31
+ const spacelessValue = value?.trim()
32
+ const parsedNumber = Number(spacelessValue)
33
+
34
+ const parsedValue = isNaN(parsedNumber)
35
+ ? breakpoints[spacelessValue as keyof UnistylesBreakpoints] as number
36
+ : parsedNumber
37
+
38
+ return openBracket === '('
39
+ ? [parsedValue - 1]
40
+ : [parsedValue]
41
+ }
36
42
 
37
- return [lh, rh]
43
+ const parseRhs = (rhs: string, breakpoints: UnistylesBreakpoints) => {
44
+ const matches = rhs.match(/([([])|([^[\]()]+)|([\])])/g)
45
+ const [value, closeBrackets] = matches as [string, string]
46
+ const spacelessValue = value.trim()
47
+ const parsedNumber = Number(spacelessValue)
48
+
49
+ const parsedValue = isNaN(parsedNumber)
50
+ ? breakpoints[spacelessValue as keyof UnistylesBreakpoints] as number
51
+ : parsedNumber
52
+
53
+ return [
54
+ closeBrackets === ')'
55
+ ? parsedValue - 1
56
+ : parsedValue
57
+ ]
38
58
  }
39
59
 
40
- /**
41
- * Determines if the given screen size matches the specified breakpoint query.
42
- *
43
- * The function checks if the screen size (width and/or height) falls within the range
44
- * specified by the breakpoint query. The query can specify width (using 'w'), height (using 'h'),
45
- * or both.
46
- *
47
- * @param {string} query - The breakpoint query string. Examples: 'w[100,200]', 'h[300]', 'w[100,200]h[300,400]'.
48
- * @param {ScreenSize} screenSize - The screen size to check against the breakpoint query.
49
- * @returns {boolean} True if the screen size matches the breakpoint query, false otherwise.
50
- *
51
- * @example
52
- * const screenSize = { width: 150, height: 350 }
53
- * isWithinBreakpoint('w[100,200]', screenSize) // returns true
54
- * isWithinBreakpoint('h[400]', screenSize) // returns false
55
- */
56
- export const isWithinBreakpoint = (query: string, screenSize: ScreenSize): boolean => {
57
- if (query.includes('w') && query.includes('h')) {
58
- return isWithinTheWidthAndHeight(query, screenSize)
60
+ export const extractValues = (pattern: string, breakpoints: UnistylesBreakpoints): Array<number> => {
61
+ const [lhs, rhs] = pattern
62
+ .replace(/(:w|:h)/g, '')
63
+ .split(',') as [string, string | undefined]
64
+
65
+ if (!rhs) {
66
+ return parseLhs(lhs, breakpoints, false)
67
+ }
68
+
69
+ const [parsedLhs] = parseLhs(lhs, breakpoints, true)
70
+
71
+ if (parsedLhs === undefined || isNaN(parsedLhs)) {
72
+ return []
73
+ }
74
+
75
+ const [parsedRhs] = parseRhs(rhs, breakpoints)
76
+
77
+ if (parsedRhs === undefined || isNaN(parsedRhs)) {
78
+ return []
79
+ }
80
+
81
+ return [
82
+ parsedLhs,
83
+ parsedRhs
84
+ ]
85
+ }
86
+
87
+ export const isWithinBreakpoint = (query: string, screenSize: ScreenSize, breakpoints: UnistylesBreakpoints): boolean => {
88
+ const hasWidthBreakpoint = query.includes(':w')
89
+ const hasHeightBreakpoint = query.includes(':h')
90
+
91
+ if (hasWidthBreakpoint && hasHeightBreakpoint) {
92
+ return isWithinTheWidthAndHeight(query, screenSize, breakpoints)
59
93
  }
60
94
 
61
- if (query.charAt(0) === 'w') {
62
- return isWithinTheWidth(query, screenSize.width)
95
+ if (hasWidthBreakpoint) {
96
+ return isWithinTheWidth(query, screenSize.width, breakpoints)
63
97
  }
64
98
 
65
- if (query.charAt(0) === 'h') {
66
- return isWithinTheHeight(query, screenSize.height)
99
+ if (hasHeightBreakpoint) {
100
+ return isWithinTheHeight(query, screenSize.height, breakpoints)
67
101
  }
68
102
 
69
103
  return false
70
104
  }
71
105
 
72
- /**
73
- * Determines if the given width matches the specified width range in the query.
74
- *
75
- * The function checks if the provided width falls within the range specified by the query.
76
- * The query specifies a width range using a format like 'w[100,200]'. If only one value is provided,
77
- * it's treated as a minimum width.
78
- *
79
- * @param {string} query - The width query string. Examples: 'w[100,200]' or 'w[100]'.
80
- * @param {number} width - The width to check against the query.
81
- * @returns {boolean} True if the width matches the query range, false otherwise.
82
- *
83
- * @example
84
- * isWithinTheWidth('w[100,200]', 150) // returns true
85
- * isWithinTheWidth('w[100]', 50) // returns false
86
- * isWithinTheWidth('w[100]', 150) // returns true
87
- */
88
- export const isWithinTheWidth = (query: string, width: number): boolean => {
89
- const [minWidth, maxWidth] = extractValues(query) as [number, number | undefined]
106
+ export const isWithinTheWidth = (query: string, width: number, breakpoints: UnistylesBreakpoints): boolean => {
107
+ const [minWidth, maxWidth] = extractValues(query, breakpoints) as [number, number | undefined]
90
108
 
91
109
  if (maxWidth && width >= minWidth && width <= maxWidth) {
92
110
  return true
@@ -95,24 +113,8 @@ export const isWithinTheWidth = (query: string, width: number): boolean => {
95
113
  return !maxWidth && width >= minWidth
96
114
  }
97
115
 
98
- /**
99
- * Determines if the given height matches the specified height range in the query.
100
- *
101
- * The function checks if the provided height falls within the range specified by the query.
102
- * The query specifies a height range using a format like 'h[100,200]'. If only one value is provided,
103
- * it's treated as a minimum height.
104
- *
105
- * @param {string} query - The height query string. Examples: 'h[100,200]' or 'h[100]'.
106
- * @param {number} height - The height to check against the query.
107
- * @returns {boolean} True if the height matches the query range, false otherwise.
108
- *
109
- * @example
110
- * isWithinTheHeight('h[100,200]', 150) // returns true
111
- * isWithinTheHeight('h[100]', 50) // returns false
112
- * isWithinTheHeight('h[100]', 150) // returns true
113
- */
114
- export const isWithinTheHeight = (query: string, height: number): boolean => {
115
- const [minHeight, maxHeight] = extractValues(query) as [number, number | undefined]
116
+ export const isWithinTheHeight = (query: string, height: number, breakpoints: UnistylesBreakpoints): boolean => {
117
+ const [minHeight, maxHeight] = extractValues(query, breakpoints) as [number, number | undefined]
116
118
 
117
119
  if (maxHeight && height >= minHeight && height <= maxHeight) {
118
120
  return true
@@ -121,92 +123,29 @@ export const isWithinTheHeight = (query: string, height: number): boolean => {
121
123
  return !maxHeight && height >= minHeight
122
124
  }
123
125
 
124
- /**
125
- * Determines if the given screen size matches both the specified width and height ranges in the query.
126
- *
127
- * The function checks if the provided screen size (both width and height) falls within the ranges
128
- * specified by the query. The query can specify both width and height using a format like 'w[100,200]:h[300,400]'.
129
- *
130
- * @param {string} query - The combined width and height query string. Example: 'w[100,200]:h[300,400]'.
131
- * @param {ScreenSize} screenSize - The screen size to check against the query.
132
- * @returns {boolean} True if the screen size matches both the width and height ranges in the query, false otherwise.
133
- *
134
- * @example
135
- * const screenSize = { width: 150, height: 350 }
136
- * isWithinTheWidthAndHeight('w[100,200]:h[300,400]', screenSize) // returns true
137
- * isWithinTheWidthAndHeight('w[100,200]:h[400,500]', screenSize) // returns false
138
- */
139
- export const isWithinTheWidthAndHeight = (query: string, screenSize: ScreenSize): boolean => {
126
+ export const isWithinTheWidthAndHeight = (query: string, screenSize: ScreenSize, breakpoints: UnistylesBreakpoints): boolean => {
140
127
  const result = query
141
128
  .split(':')
142
129
  .filter(Boolean)
143
- .map(q => isWithinBreakpoint(q, screenSize))
130
+ .map(q => isWithinBreakpoint(`:${q}`, screenSize, breakpoints))
144
131
  .filter(Boolean)
145
132
 
146
133
  return result.length === 2
147
134
  }
148
135
 
149
- /**
150
- * Checks if the given query string is a valid custom media query.
151
- *
152
- * The valid custom media query formats include:
153
- * - :w[200]
154
- * - :w[0, 200]
155
- * - :w[, 300]
156
- * - :h[200]
157
- * - :h[0, 500]
158
- * - :h[,200]
159
- * - :w[100, 300]:h[200,500]
160
- * - :h[200,500]:w[100, 300]
161
- *
162
- * @param {string} query - The query string to be checked.
163
- * @returns {boolean} Returns `true` if the query is a valid custom media query, otherwise `false`.
164
- * @example
165
- *
166
- * isMediaQuery(':w[200]') // true
167
- * isMediaQuery(':w100]') // false
168
- */
169
136
  export const isMediaQuery = (query: string): boolean => {
170
- const regex = /^(?:(:w\[\d*(?:,\s?\d+)?])?(:h\[\d*(?:,\s?\d+)?])?|(:h\[\d*(?:,\s?\d+)?])?(:w\[\d*(?:,\s?\d+)?])?)$/
137
+ const regex = /(:w|:h)/
171
138
 
172
139
  return query.length > 0 && regex.test(query)
173
140
  }
174
141
 
175
- /**
176
- * Retrieves the first matching custom media query key based on the provided screen size.
177
- *
178
- * The function processes an array of media queries and returns the first query that matches
179
- * the given screen size. The media queries can be in formats like:
180
- * - w[200]
181
- * - w[0, 200]
182
- * - w[, 300]
183
- * - h[200]
184
- * - h[0, 500]
185
- * - h[,200]
186
- * - w[100, 300]:h[200,500]
187
- * - h[200,500]:w[100, 300]
188
- *
189
- * @param {Array<[string, string | number]>} mediaQueries - An array of tuples containing media query keys and associated values.
190
- * @param {ScreenSize} screenSize - An object representing the screen size to be checked against the media queries.
191
- * @returns {string | undefined} Returns the first matching media query key or `undefined` if no match is found.
192
- * @example
193
- *
194
- * const queries = [[':w[200]', 'value1'], [':h[300,500]', 'value2']]
195
- * const size = { width: 250, height: 400 }
196
- * getKeyForCustomMediaQuery(queries, size) // ':w[200]
197
- */
198
- export const getKeyForCustomMediaQuery = (mediaQueries: Array<[string, string | number | undefined]>, screenSize: ScreenSize): string | undefined => {
142
+ export const getKeyForCustomMediaQuery = (
143
+ mediaQueries: Array<[keyof UnistylesBreakpoints | MediaQueries, string | number | undefined]>,
144
+ screenSize: ScreenSize,
145
+ breakpoints: UnistylesBreakpoints
146
+ ): string | undefined => {
199
147
  const [matchedQuery] = mediaQueries
200
- .flatMap(([key]) => {
201
- if (key.includes('w') && key.includes('h')) {
202
- return isWithinBreakpoint(key, screenSize) ? key : undefined
203
- }
204
-
205
- return key
206
- .split(':')
207
- .filter(Boolean)
208
- .map(query => isWithinBreakpoint(query, screenSize) ? key : undefined)
209
- })
148
+ .flatMap(([key]) => isWithinBreakpoint(key, screenSize, breakpoints) ? key : undefined)
210
149
  .filter(Boolean)
211
150
 
212
151
  return matchedQuery
@@ -1,30 +1,9 @@
1
- import type { CustomNamedStyles, ScreenSize } from '../types'
1
+ import type { CustomNamedStyles, MediaQueries, ScreenSize } from '../types'
2
2
  import { getValueForBreakpoint } from './breakpoints'
3
3
  import { normalizeStyles } from './normalizeStyles'
4
- import { isWeb } from './common'
5
4
  import type { UnistylesBreakpoints } from '../global'
5
+ import { isAndroid, isIOS, isWeb } from './common'
6
6
 
7
- /**
8
- * Proxies a function to parse its return value for custom media queries or breakpoints.
9
- *
10
- * @template B - An object type where keys represent breakpoint names and values represent breakpoint values.
11
- *
12
- * @param {Function} fn - The function to be proxified.
13
- * @param {keyof B & string} breakpoint - The breakpoint name to check against.
14
- * @param {ScreenSize} screenSize - An object representing the screen size to be checked against the media queries.
15
- * @param breakpointPairs - sorted pairs of breakpoints
16
- *
17
- * @returns {Function} Returns the proxified function
18
- *
19
- * @example
20
- *
21
- * const myFunction = () => ({ ':w[200]': 'value1', sm: 'value2' })
22
- * const screenSize = { width: 250, height: 400 }
23
- * const breakpoints = { sm: 300, md: 600 }
24
- *
25
- * const proxifiedFunction = proxifyFunction(myFunction, 'sm', screenSize, breakpoints)
26
- * proxifiedFunction() // parsed style based on screenSize and breakpoints
27
- */
28
7
  export const proxifyFunction = (
29
8
  fn: Function, breakpoint: keyof UnistylesBreakpoints & string,
30
9
  screenSize: ScreenSize
@@ -33,37 +12,20 @@ export const proxifyFunction = (
33
12
  parseStyle(target.apply(thisArg, argumentsList), breakpoint, screenSize)
34
13
  })
35
14
 
36
- /**
37
- * Parses a style object to resolve custom media queries or breakpoints based on the provided screen size and breakpoints.
38
- *
39
- * The function processes each key-value pair in the style object. If the value is a function or a valid style (not an object or a 'transform' key),
40
- * it is returned as-is. Otherwise, the function attempts to resolve the value based on the provided breakpoint, screen size, and defined breakpoints.
41
- *
42
- * @template T - The type of the style object.
43
- * @template B - An object type where keys represent breakpoint names and values represent breakpoint values.
44
- *
45
- * @param {CustomNamedStyles<T, B>} style - The style object to be parsed.
46
- * @param {keyof B & string} breakpoint - The breakpoint name to check against.
47
- * @param {ScreenSize} screenSize - An object representing the screen size to be checked against the media queries.
48
- * @param breakpointPairs - sorted pairs of breakpoints
49
- *
50
- * @returns {Record<string, string | number | Function>} Returns the parsed style object with resolved custom media queries or breakpoints.
51
- *
52
- * @example
53
- *
54
- * const style = { fontSize: { sm: '12px', md: '16px' } }
55
- * const screenSize = { width: 300, height: 400 }
56
- * const breakpoints = { xs: 0, sm: 300, md: 600 }
57
- *
58
- * const parsedStyle = parseStyle(style, 'sm', screenSize, breakpoints)
59
- * // { fontSize: '12px' }
60
- */
15
+ export const isPlatformColor = <T extends {}>(value: T): boolean => {
16
+ if (isIOS) {
17
+ return 'semantic' in value && typeof value.semantic === 'object'
18
+ }
19
+
20
+ return isAndroid && 'resource_paths' in value && typeof value.resource_paths === 'object'
21
+ }
22
+
61
23
  export const parseStyle = <T>(
62
24
  style: CustomNamedStyles<T>,
63
25
  breakpoint: keyof UnistylesBreakpoints & string,
64
26
  screenSize: ScreenSize
65
27
  ): T => {
66
- const entries = Object.entries(style) as [[
28
+ const entries = Object.entries(style || {}) as [[
67
29
  keyof T,
68
30
  CustomNamedStyles<T> | Record<keyof UnistylesBreakpoints & string, string | number | undefined>]
69
31
  ]
@@ -90,7 +52,7 @@ export const parseStyle = <T>(
90
52
  }
91
53
 
92
54
  const isDynamicFunction = typeof value === 'function'
93
- const isValidStyle = typeof value !== 'object'
55
+ const isValidStyle = typeof value !== 'object' || isPlatformColor(value)
94
56
 
95
57
  if (isDynamicFunction || isValidStyle) {
96
58
  return [key, value]
@@ -98,11 +60,7 @@ export const parseStyle = <T>(
98
60
 
99
61
  return [
100
62
  key,
101
- getValueForBreakpoint(
102
- value as Record<keyof UnistylesBreakpoints & string, string | number | undefined>,
103
- breakpoint,
104
- screenSize
105
- )
63
+ getValueForBreakpoint(value as Record<keyof UnistylesBreakpoints | MediaQueries, string | number | undefined>)
106
64
  ]
107
65
  })
108
66
  )