react-native-unistyles 3.0.0-alpha.21 → 3.0.0-alpha.23

Sign up to get free protection for your applications and to get access to all the features.
Files changed (165) hide show
  1. package/cxx/core/UnistylesRegistry.cpp +26 -0
  2. package/cxx/core/UnistylesRegistry.h +1 -0
  3. package/cxx/hybridObjects/HybridStyleSheet.cpp +11 -5
  4. package/cxx/hybridObjects/HybridStyleSheet.h +1 -1
  5. package/cxx/parser/Parser.cpp +27 -1
  6. package/cxx/parser/Parser.h +1 -1
  7. package/lib/commonjs/web/convert/boxShadow.js +13 -13
  8. package/lib/commonjs/web/convert/boxShadow.js.map +1 -1
  9. package/lib/commonjs/web/convert/index.js +9 -11
  10. package/lib/commonjs/web/convert/index.js.map +1 -1
  11. package/lib/commonjs/web/convert/pseudo.js.map +1 -0
  12. package/lib/commonjs/web/convert/style.js +11 -7
  13. package/lib/commonjs/web/convert/style.js.map +1 -1
  14. package/lib/commonjs/web/convert/textShadow.js +12 -12
  15. package/lib/commonjs/web/convert/textShadow.js.map +1 -1
  16. package/lib/commonjs/web/convert/transform.js +5 -5
  17. package/lib/commonjs/web/convert/transform.js.map +1 -1
  18. package/lib/commonjs/web/{listener/listener.js → listener.js} +2 -2
  19. package/lib/commonjs/web/listener.js.map +1 -0
  20. package/lib/commonjs/web/mq.js.map +1 -1
  21. package/lib/commonjs/web/registry.js +159 -21
  22. package/lib/commonjs/web/registry.js.map +1 -1
  23. package/lib/commonjs/web/shadowRegistry.js +50 -48
  24. package/lib/commonjs/web/shadowRegistry.js.map +1 -1
  25. package/lib/commonjs/web/state.js +8 -16
  26. package/lib/commonjs/web/state.js.map +1 -1
  27. package/lib/commonjs/web/{utils.js → utils/common.js} +9 -47
  28. package/lib/commonjs/web/utils/common.js.map +1 -0
  29. package/lib/commonjs/web/utils/index.js +28 -0
  30. package/lib/commonjs/web/utils/index.js.map +1 -0
  31. package/lib/commonjs/web/utils/unistyle.js +82 -0
  32. package/lib/commonjs/web/utils/unistyle.js.map +1 -0
  33. package/lib/module/web/convert/boxShadow.js +13 -13
  34. package/lib/module/web/convert/boxShadow.js.map +1 -1
  35. package/lib/module/web/convert/index.js +7 -9
  36. package/lib/module/web/convert/index.js.map +1 -1
  37. package/lib/module/web/convert/pseudo.js.map +1 -0
  38. package/lib/module/web/convert/style.js +11 -7
  39. package/lib/module/web/convert/style.js.map +1 -1
  40. package/lib/module/web/convert/textShadow.js +12 -12
  41. package/lib/module/web/convert/textShadow.js.map +1 -1
  42. package/lib/module/web/convert/transform.js +5 -5
  43. package/lib/module/web/convert/transform.js.map +1 -1
  44. package/lib/module/web/{listener/listener.js → listener.js} +2 -2
  45. package/lib/module/web/listener.js.map +1 -0
  46. package/lib/module/web/mq.js.map +1 -1
  47. package/lib/module/web/registry.js +160 -22
  48. package/lib/module/web/registry.js.map +1 -1
  49. package/lib/module/web/shadowRegistry.js +51 -49
  50. package/lib/module/web/shadowRegistry.js.map +1 -1
  51. package/lib/module/web/state.js +8 -16
  52. package/lib/module/web/state.js.map +1 -1
  53. package/lib/module/web/{utils.js → utils/common.js} +7 -39
  54. package/lib/module/web/utils/common.js.map +1 -0
  55. package/lib/module/web/utils/index.js +5 -0
  56. package/lib/module/web/utils/index.js.map +1 -0
  57. package/lib/module/web/utils/unistyle.js +69 -0
  58. package/lib/module/web/utils/unistyle.js.map +1 -0
  59. package/lib/typescript/src/specs/StyleSheet/UnistylesStyleSheet.nitro.d.ts +1 -1
  60. package/lib/typescript/src/specs/StyleSheet/UnistylesStyleSheet.nitro.d.ts.map +1 -1
  61. package/lib/typescript/src/types/stylesheet.d.ts +1 -1
  62. package/lib/typescript/src/types/stylesheet.d.ts.map +1 -1
  63. package/lib/typescript/src/web/convert/boxShadow.d.ts +7 -2
  64. package/lib/typescript/src/web/convert/boxShadow.d.ts.map +1 -1
  65. package/lib/typescript/src/web/convert/index.d.ts +1 -2
  66. package/lib/typescript/src/web/convert/index.d.ts.map +1 -1
  67. package/lib/typescript/src/web/convert/pseudo.d.ts.map +1 -0
  68. package/lib/typescript/src/web/convert/style.d.ts +1 -2
  69. package/lib/typescript/src/web/convert/style.d.ts.map +1 -1
  70. package/lib/typescript/src/web/convert/textShadow.d.ts +7 -2
  71. package/lib/typescript/src/web/convert/textShadow.d.ts.map +1 -1
  72. package/lib/typescript/src/web/convert/transform.d.ts +1 -2
  73. package/lib/typescript/src/web/convert/transform.d.ts.map +1 -1
  74. package/lib/typescript/src/web/{listener/listener.d.ts → listener.d.ts} +1 -1
  75. package/lib/typescript/src/web/listener.d.ts.map +1 -0
  76. package/lib/typescript/src/web/mq.d.ts +6 -2
  77. package/lib/typescript/src/web/mq.d.ts.map +1 -1
  78. package/lib/typescript/src/web/registry.d.ts +21 -8
  79. package/lib/typescript/src/web/registry.d.ts.map +1 -1
  80. package/lib/typescript/src/web/shadowRegistry.d.ts +3 -4
  81. package/lib/typescript/src/web/shadowRegistry.d.ts.map +1 -1
  82. package/lib/typescript/src/web/state.d.ts +2 -2
  83. package/lib/typescript/src/web/state.d.ts.map +1 -1
  84. package/lib/typescript/src/web/{utils.d.ts → utils/common.d.ts} +2 -20
  85. package/lib/typescript/src/web/utils/common.d.ts.map +1 -0
  86. package/lib/typescript/src/web/utils/index.d.ts +3 -0
  87. package/lib/typescript/src/web/utils/index.d.ts.map +1 -0
  88. package/lib/typescript/src/web/utils/unistyle.d.ts +20 -0
  89. package/lib/typescript/src/web/utils/unistyle.d.ts.map +1 -0
  90. package/nitrogen/generated/android/c++/JColorScheme.hpp +1 -1
  91. package/nitrogen/generated/android/c++/JFunc_void_std__vector_UnistyleDependency_.hpp +8 -8
  92. package/nitrogen/generated/android/c++/JHybridNativePlatformSpec.cpp +22 -22
  93. package/nitrogen/generated/android/c++/JOrientation.hpp +1 -1
  94. package/nitrogen/generated/android/c++/JUnistyleDependency.hpp +1 -1
  95. package/nitrogen/generated/android/kotlin/com/margelo/nitro/unistyles/HybridNativePlatformSpec.kt +2 -2
  96. package/nitrogen/generated/android/{UnistylesOnLoad.cpp → unistylesOnLoad.cpp} +2 -2
  97. package/nitrogen/generated/android/{UnistylesOnLoad.hpp → unistylesOnLoad.hpp} +1 -1
  98. package/nitrogen/generated/ios/Unistyles+autolinking.rb +5 -3
  99. package/nitrogen/generated/ios/Unistyles-Swift-Cxx-Bridge.cpp +25 -0
  100. package/nitrogen/generated/ios/Unistyles-Swift-Cxx-Bridge.hpp +32 -32
  101. package/nitrogen/generated/ios/Unistyles-Swift-Cxx-Umbrella.hpp +0 -29
  102. package/nitrogen/generated/ios/swift/HybridNativePlatformSpec.swift +0 -12
  103. package/nitrogen/generated/ios/swift/HybridNativePlatformSpecCxx.swift +134 -110
  104. package/nitrogen/generated/shared/c++/ColorScheme.hpp +2 -2
  105. package/nitrogen/generated/shared/c++/HybridUnistylesStyleSheetSpec.cpp +1 -1
  106. package/nitrogen/generated/shared/c++/HybridUnistylesStyleSheetSpec.hpp +1 -1
  107. package/nitrogen/generated/shared/c++/Orientation.hpp +2 -2
  108. package/package.json +4 -15
  109. package/src/specs/StyleSheet/UnistylesStyleSheet.nitro.ts +1 -1
  110. package/src/types/stylesheet.ts +1 -1
  111. package/src/web/convert/boxShadow.ts +14 -15
  112. package/src/web/convert/index.ts +6 -13
  113. package/src/web/convert/style.ts +61 -10
  114. package/src/web/convert/textShadow.ts +13 -14
  115. package/src/web/convert/transform.ts +7 -8
  116. package/src/web/{listener/listener.ts → listener.ts} +2 -2
  117. package/src/web/mq.ts +1 -3
  118. package/src/web/registry.ts +202 -23
  119. package/src/web/shadowRegistry.ts +49 -49
  120. package/src/web/state.ts +13 -23
  121. package/src/web/{utils.ts → utils/common.ts} +6 -68
  122. package/src/web/utils/index.ts +2 -0
  123. package/src/web/utils/unistyle.ts +104 -0
  124. package/lib/commonjs/web/convert/breakpoint.js +0 -25
  125. package/lib/commonjs/web/convert/breakpoint.js.map +0 -1
  126. package/lib/commonjs/web/createUnistylesComponent.js +0 -61
  127. package/lib/commonjs/web/createUnistylesComponent.js.map +0 -1
  128. package/lib/commonjs/web/listener/index.js +0 -20
  129. package/lib/commonjs/web/listener/index.js.map +0 -1
  130. package/lib/commonjs/web/listener/listenToDependencies.js +0 -38
  131. package/lib/commonjs/web/listener/listenToDependencies.js.map +0 -1
  132. package/lib/commonjs/web/listener/listener.js.map +0 -1
  133. package/lib/commonjs/web/pseudo.js.map +0 -1
  134. package/lib/commonjs/web/utils.js.map +0 -1
  135. package/lib/module/web/convert/breakpoint.js +0 -20
  136. package/lib/module/web/convert/breakpoint.js.map +0 -1
  137. package/lib/module/web/createUnistylesComponent.js +0 -54
  138. package/lib/module/web/createUnistylesComponent.js.map +0 -1
  139. package/lib/module/web/listener/index.js +0 -5
  140. package/lib/module/web/listener/index.js.map +0 -1
  141. package/lib/module/web/listener/listenToDependencies.js +0 -33
  142. package/lib/module/web/listener/listenToDependencies.js.map +0 -1
  143. package/lib/module/web/listener/listener.js.map +0 -1
  144. package/lib/module/web/pseudo.js.map +0 -1
  145. package/lib/module/web/utils.js.map +0 -1
  146. package/lib/typescript/src/web/convert/breakpoint.d.ts +0 -3
  147. package/lib/typescript/src/web/convert/breakpoint.d.ts.map +0 -1
  148. package/lib/typescript/src/web/createUnistylesComponent.d.ts +0 -3
  149. package/lib/typescript/src/web/createUnistylesComponent.d.ts.map +0 -1
  150. package/lib/typescript/src/web/listener/index.d.ts +0 -3
  151. package/lib/typescript/src/web/listener/index.d.ts.map +0 -1
  152. package/lib/typescript/src/web/listener/listenToDependencies.d.ts +0 -12
  153. package/lib/typescript/src/web/listener/listenToDependencies.d.ts.map +0 -1
  154. package/lib/typescript/src/web/listener/listener.d.ts.map +0 -1
  155. package/lib/typescript/src/web/pseudo.d.ts.map +0 -1
  156. package/lib/typescript/src/web/utils.d.ts.map +0 -1
  157. package/src/web/convert/breakpoint.ts +0 -21
  158. package/src/web/createUnistylesComponent.tsx +0 -54
  159. package/src/web/listener/index.ts +0 -2
  160. package/src/web/listener/listenToDependencies.ts +0 -45
  161. /package/lib/commonjs/web/{pseudo.js → convert/pseudo.js} +0 -0
  162. /package/lib/module/web/{pseudo.js → convert/pseudo.js} +0 -0
  163. /package/lib/typescript/src/web/{pseudo.d.ts → convert/pseudo.d.ts} +0 -0
  164. /package/nitrogen/generated/android/{UnistylesOnLoad.kt → unistylesOnLoad.kt} +0 -0
  165. /package/src/web/{pseudo.ts → convert/pseudo.ts} +0 -0
@@ -1,7 +1,6 @@
1
1
  import { keyInObject } from '../utils'
2
- import type { NestedCSSProperties } from 'typestyle/lib/types'
3
2
 
4
- const stylesToSkip = [
3
+ const SKIP_STYLES = [
5
4
  'borderCurve',
6
5
  'elevation',
7
6
  'textAlignVertical',
@@ -10,6 +9,53 @@ const stylesToSkip = [
10
9
  'tintColor'
11
10
  ]
12
11
 
12
+ const CSS_NUMBER_KEYS = [
13
+ 'animationIterationCount',
14
+ 'borderImageOutset',
15
+ 'borderImageSlice',
16
+ 'borderImageWidth',
17
+ 'boxFlex',
18
+ 'boxFlexGroup',
19
+ 'boxOrdinalGroup',
20
+ 'columnCount',
21
+ 'columns',
22
+ 'counterIncrement',
23
+ 'counterReset',
24
+ 'flex',
25
+ 'flexGrow',
26
+ 'flexPositive',
27
+ 'flexShrink',
28
+ 'flexNegative',
29
+ 'flexOrder',
30
+ 'fontWeight',
31
+ 'gridArea',
32
+ 'gridColumn',
33
+ 'gridColumnEnd',
34
+ 'gridColumnSpan',
35
+ 'gridColumnStart',
36
+ 'gridRow',
37
+ 'gridRowEnd',
38
+ 'gridRowSpan',
39
+ 'gridRowStart',
40
+ 'line-clamp',
41
+ 'line-height',
42
+ 'opacity',
43
+ 'order',
44
+ 'orphans',
45
+ 'tabSize',
46
+ 'widows',
47
+ 'zIndex',
48
+ 'zoom',
49
+ 'fillOpacity',
50
+ 'floodOpacity',
51
+ 'stopOpacity',
52
+ 'strokeDasharray',
53
+ 'strokeDashoffset',
54
+ 'strokeMiterlimit',
55
+ 'strokeOpacity',
56
+ 'strokeWidth'
57
+ ]
58
+
13
59
  const convertMap = {
14
60
  marginHorizontal: (value: number) => ({
15
61
  marginInline: value
@@ -73,22 +119,27 @@ const convertMap = {
73
119
  }),
74
120
  resizeMode: (value: string) => ({
75
121
  backgroundSize: value
76
- }),
77
- lineHeight: (value: number) => ({
78
- lineHeight: `${value}px`
79
- }),
80
- } as Record<PropertyKey, (value: any) => NestedCSSProperties>
122
+ })
123
+ } as Record<PropertyKey, (value: any) => Record<string, any>>
124
+
125
+ const convertNumber = (key: string, value: any) => {
126
+ if (typeof value === 'number') {
127
+ return CSS_NUMBER_KEYS.includes(key, value) ? value : `${value}px`
128
+ }
129
+
130
+ return value
131
+ }
81
132
 
82
133
  export const getStyle = (key: string, value: any) => {
83
- if (stylesToSkip.includes(key)) {
134
+ if (SKIP_STYLES.includes(key)) {
84
135
  return {}
85
136
  }
86
137
 
87
138
  if (keyInObject(convertMap, key)) {
88
- return convertMap[key]?.(value) ?? {}
139
+ return convertMap[key]?.(convertNumber(key, value)) ?? {}
89
140
  }
90
141
 
91
142
  return {
92
- [key]: value
143
+ [key]: convertNumber(key, value)
93
144
  }
94
145
  }
@@ -1,8 +1,5 @@
1
- import { media } from 'typestyle'
2
- import type { NestedCSSProperties } from 'typestyle/lib/types'
3
1
  import { deepMergeObjects, warn } from '../utils'
4
2
  import { validateShadow } from './shadow'
5
- import { convertBreakpoint } from './breakpoint'
6
3
  import { TEXT_SHADOW_STYLES, type TextShadow } from './types'
7
4
  import { extractShadowValue, normalizeColor, normalizeNumericValue } from './utils'
8
5
 
@@ -16,7 +13,7 @@ const createTextShadowValue = (style: TextShadow) => {
16
13
  return `${offsetX} ${offsetY} ${radius} ${color}`
17
14
  }
18
15
 
19
- export const getTextShadowStyle = (styles: Record<string, any>): NestedCSSProperties => {
16
+ export const getTextShadowStyle = (styles: Record<string, any>) => {
20
17
  const missingStyles = TEXT_SHADOW_STYLES.filter(key => !(key in styles))
21
18
 
22
19
  if (missingStyles.length) {
@@ -52,16 +49,18 @@ export const getTextShadowStyle = (styles: Record<string, any>): NestedCSSProper
52
49
  const { width, height } = extractShadowValue('textShadowOffset', breakpoint, styles)
53
50
  const radius = extractShadowValue('textShadowRadius', breakpoint, styles)
54
51
 
55
- return media(convertBreakpoint(breakpoint), {
56
- textShadow: createTextShadowValue({
57
- textShadowColor: color,
58
- textShadowOffset: {
59
- width,
60
- height
61
- },
62
- textShadowRadius: radius
63
- })
64
- })
52
+ return {
53
+ [breakpoint]: {
54
+ textShadow: createTextShadowValue({
55
+ textShadowColor: color,
56
+ textShadowOffset: {
57
+ width,
58
+ height
59
+ },
60
+ textShadowRadius: radius
61
+ })
62
+ }
63
+ }
65
64
  })
66
65
 
67
66
  // Merge all breakpoints styles into one
@@ -1,8 +1,5 @@
1
- import { media } from 'typestyle'
2
- import type { NestedCSSProperties } from 'typestyle/lib/types'
3
1
  import { deepMergeObjects, keyInObject } from '../utils'
4
2
  import { normalizeNumericValue } from './utils'
5
- import { convertBreakpoint } from './breakpoint'
6
3
 
7
4
  type Transforms = Array<Record<string, any>>
8
5
 
@@ -39,7 +36,7 @@ const createTransformValue = (transforms: Transforms) => transforms
39
36
  .filter(Boolean)
40
37
  .join(' ')
41
38
 
42
- export const getTransformStyle = (transforms: Transforms): NestedCSSProperties => {
39
+ export const getTransformStyle = (transforms: Transforms) => {
43
40
  const breakpoints = new Set<string>()
44
41
  const normalTransforms: Transforms = []
45
42
 
@@ -78,12 +75,14 @@ export const getTransformStyle = (transforms: Transforms): NestedCSSProperties =
78
75
  return []
79
76
  })
80
77
 
81
- return media(convertBreakpoint(breakpoint), {
82
- transform: createTransformValue(transformsPerBreakpoint)
83
- })
78
+ return [{
79
+ [breakpoint]: {
80
+ transform: createTransformValue(transformsPerBreakpoint)
81
+ }
82
+ }]
84
83
  })
85
84
 
86
- return deepMergeObjects({
85
+ return deepMergeObjects<Record<string, any>>({
87
86
  transform: createTransformValue(normalTransforms)
88
87
  }, ...breakpointTransforms)
89
88
  }
@@ -1,5 +1,5 @@
1
- import { UnistyleDependency } from '../../specs/NativePlatform'
2
- import { UnistylesRuntime } from '../runtime'
1
+ import { UnistyleDependency } from '../specs/NativePlatform'
2
+ import { UnistylesRuntime } from './runtime'
3
3
 
4
4
  class UnistylesListenerBuilder {
5
5
  private isInitialized = false
package/src/web/mq.ts CHANGED
@@ -1,10 +1,8 @@
1
- import type { MediaQuery } from 'typestyle/lib/types'
2
-
3
1
  const IS_UNISTYLES_REGEX = /:([hw])\[(\d+)(?:,\s*(\d+|Infinity))?]/
4
2
  const UNISTYLES_WIDTH_REGEX = /:(w)\[(\d+)(?:,\s*(\d+|Infinity))?]/
5
3
  const UNISTYLES_HEIGHT_REGEX = /:(h)\[(\d+)(?:,\s*(\d+|Infinity))?]/
6
4
 
7
- export const parseMq = (mq: string): MediaQuery => {
5
+ export const parseMq = (mq: string) => {
8
6
  const [, width, fromW, toW] = UNISTYLES_WIDTH_REGEX.exec(mq) || []
9
7
  const [, height, fromH, toH] = UNISTYLES_HEIGHT_REGEX.exec(mq) || []
10
8
 
@@ -1,13 +1,52 @@
1
- import { createTypeStyle, TypeStyle } from 'typestyle'
2
- import type { UnistylesValues } from '../types'
3
- import { convertToTypeStyle } from './convert'
1
+ import type { UnistylesTheme, UnistylesValues } from '../types'
4
2
  import type { StyleSheet, StyleSheetWithSuperPowers } from '../types/stylesheet'
5
3
  import { UnistylesRuntime } from './runtime'
6
- import { keyInObject } from './utils'
4
+ import { extractMediaQueryValue, keyInObject, getMediaQuery, generateHash, extractUnistyleDependencies } from './utils'
7
5
  import { UnistylesListener } from './listener'
6
+ import { convertUnistyles } from './convert'
7
+ import type { UnistyleDependency } from '../specs/NativePlatform'
8
+ import type { UnistylesMiniRuntime } from '../specs'
9
+ import { getVariants } from './variants'
10
+
11
+ type AddProps = {
12
+ value: UnistylesValues,
13
+ stylesheet: StyleSheetWithSuperPowers<StyleSheet>,
14
+ key: string,
15
+ args: Array<any>,
16
+ variants: Record<string, any>
17
+ }
18
+
19
+ type ApplyRuleProps = {
20
+ hash: string,
21
+ key: string,
22
+ value: any,
23
+ sheet: CSSStyleSheet | CSSMediaRule
24
+ }
25
+
26
+ type RemoveReadonlyStyleKeys<T extends string> = T extends 'length' | 'parentRule' ? never : T
8
27
 
9
28
  class UnistylesRegistryBuilder {
10
- private stylesheets = new Map<StyleSheetWithSuperPowers<StyleSheet>, StyleSheet>()
29
+ private readonly stylesheets = new Map<StyleSheetWithSuperPowers<StyleSheet>, StyleSheet>()
30
+ private readonly stylesCounter = new Map<string, Set<UnistylesValues>>()
31
+ #styleTag: HTMLStyleElement | null = null
32
+ private readonly disposeListenersMap = new Map<object, VoidFunction>()
33
+ private readonly dependenciesMap = new Map<StyleSheetWithSuperPowers<StyleSheet>, Set<UnistyleDependency>>()
34
+
35
+ private get styleTag() {
36
+ const tag = this.#styleTag
37
+
38
+ if (!tag) {
39
+ const newTag = document.createElement('style')
40
+
41
+ newTag.id = 'unistyles-web'
42
+ this.#styleTag = newTag
43
+ document.head.appendChild(newTag)
44
+
45
+ return newTag
46
+ }
47
+
48
+ return tag
49
+ }
11
50
 
12
51
  getComputedStylesheet = (stylesheet: StyleSheetWithSuperPowers<StyleSheet>) => {
13
52
  if (typeof stylesheet !== 'function') {
@@ -21,39 +60,179 @@ class UnistylesRegistryBuilder {
21
60
  }
22
61
 
23
62
  const createdStylesheet = stylesheet(UnistylesRuntime.theme, UnistylesRuntime.miniRuntime)
24
- // @ts-expect-error uni__dependencies is hidden
25
- const dependencies = Object.values(createdStylesheet).flatMap(value => keyInObject(value, 'uni__dependencies') ? value.uni__dependencies : [])
63
+ const dependencies = Object.values(createdStylesheet).flatMap(value => extractUnistyleDependencies(value))
64
+
65
+ this.addDependenciesToStylesheet(stylesheet, dependencies)
66
+ this.stylesheets.set(stylesheet, createdStylesheet)
26
67
 
27
- UnistylesListener.addListeners(dependencies, () => {
68
+ return createdStylesheet
69
+ }
70
+
71
+ addDependenciesToStylesheet = (stylesheet: (theme: UnistylesTheme, miniRuntime: UnistylesMiniRuntime) => StyleSheet, dependencies: Array<UnistyleDependency>) => {
72
+ this.disposeListenersMap.get(stylesheet)?.()
73
+
74
+ const dependenciesMap = this.dependenciesMap.get(stylesheet) ?? new Set(dependencies)
75
+
76
+ dependencies.forEach(dependency => dependenciesMap.add(dependency))
77
+
78
+ const dispose = UnistylesListener.addListeners(Array.from(dependenciesMap), () => {
28
79
  const newComputedStylesheet = stylesheet(UnistylesRuntime.theme, UnistylesRuntime.miniRuntime)
29
80
 
30
81
  this.stylesheets.set(stylesheet, newComputedStylesheet)
31
82
  })
32
83
 
33
- this.stylesheets.set(stylesheet, createdStylesheet)
84
+ this.dependenciesMap.set(stylesheet, dependenciesMap)
85
+ this.disposeListenersMap.set(stylesheet, dispose)
86
+ }
34
87
 
35
- return createdStylesheet
88
+ add = ({ key, value, stylesheet, args, variants }: AddProps) => {
89
+ const hash = generateHash(value)
90
+ const existingCounter = this.stylesCounter.get(hash)
91
+
92
+ if (!existingCounter || existingCounter.size === 0) {
93
+ const counter = new Set<UnistylesValues>()
94
+ const dependencies = extractUnistyleDependencies(value)
95
+
96
+ counter.add(value)
97
+ this.stylesCounter.set(hash, counter)
98
+ this.applyStyles(hash, convertUnistyles(value))
99
+
100
+ UnistylesListener.addListeners(dependencies, async () => {
101
+ // Move this callback to the end of the event loop
102
+ await Promise.resolve()
103
+
104
+ const newComputedStyleSheet = this.getComputedStylesheet(stylesheet)
105
+ const newValue = newComputedStyleSheet[key]!
106
+ const result = typeof newValue === 'function'
107
+ ? newValue(...args)
108
+ : newValue
109
+ const { variantsResult } = Object.fromEntries(getVariants({ variantsResult: result }, variants))
110
+ const resultWithVariants = {
111
+ ...result,
112
+ ...variantsResult
113
+ }
114
+
115
+ this.applyStyles(hash, convertUnistyles(resultWithVariants))
116
+ })
117
+
118
+ return hash
119
+ }
120
+
121
+ existingCounter.add(value)
122
+
123
+ return hash
36
124
  }
37
125
 
38
- createStyles = (stylesheet: UnistylesValues, key: string) => {
39
- const unistyles = createTypeStyle()
40
- const typestyleStylesheet = convertToTypeStyle(stylesheet)
126
+ private applyStyles = (hash: string, styles: Record<string, any>) => {
127
+ Object.entries(styles).forEach(([key, value]) => {
128
+ if (!this.styleTag.sheet) {
129
+ return
130
+ }
131
+
132
+ if (typeof value === 'object' && !key.startsWith('_')) {
133
+ const mediaQuery = getMediaQuery(key)
134
+ const cssRules = Array.from(this.styleTag.sheet.cssRules)
135
+ let queryRule = cssRules.find(rule => {
136
+ if (!(rule instanceof CSSMediaRule)) {
137
+ return false
138
+ }
139
+
140
+ return rule.media.item(0)?.includes(mediaQuery)
141
+ }) ?? null
142
+
143
+ if (!queryRule) {
144
+ const mediaQueryValue = extractMediaQueryValue(mediaQuery)
145
+ const ruleIndex = mediaQueryValue
146
+ ? cssRules.reduce<number | undefined>((acc, rule, ruleIndex) => {
147
+ if (!(rule instanceof CSSMediaRule)) {
148
+ return acc
149
+ }
150
+
151
+ const ruleMediaQueryValue = extractMediaQueryValue(rule.conditionText)
152
+
153
+ if (ruleMediaQueryValue === undefined) {
154
+ return
155
+ }
156
+
157
+ return ruleMediaQueryValue > mediaQueryValue ? ruleIndex : acc
158
+ }, cssRules.length)
159
+ : undefined
160
+ queryRule = this.styleTag.sheet.cssRules.item(this.styleTag.sheet.insertRule(`@media ${mediaQuery} {.${hash} {}}`, ruleIndex))
161
+ }
162
+
163
+ if (queryRule instanceof CSSMediaRule) {
164
+ Object.entries(value).forEach(([mqKey, mqValue]) => {
165
+ this.applyRule({
166
+ hash,
167
+ key: mqKey,
168
+ value: mqValue,
169
+ sheet: queryRule
170
+ })
171
+ })
172
+ }
173
+
174
+ return
175
+ }
176
+
177
+ // Pseudo
178
+ if (typeof value === 'object') {
179
+ Object.entries(value).forEach(([pseudoKey, pseudoValue]) => {
180
+ this.applyRule({
181
+ hash: `${hash}${key.replace('_', ':')}`,
182
+ key: pseudoKey,
183
+ value: pseudoValue,
184
+ sheet: this.styleTag.sheet!
185
+ })
186
+ })
41
187
 
42
- const className = unistyles.style({
43
- $debugName: `${key}-${Math.random().toString(16).slice(10)}`,
44
- }, typestyleStylesheet)
188
+ return
189
+ }
45
190
 
46
- return {
47
- className,
48
- unistyles
191
+ this.applyRule({
192
+ hash,
193
+ key,
194
+ value,
195
+ sheet: this.styleTag.sheet
196
+ })
197
+ })
198
+ }
199
+
200
+ private applyRule = ({ hash, key, value, sheet }: ApplyRuleProps) => {
201
+ let rule = Array.from(sheet.cssRules).find(rule => {
202
+ if (!(rule instanceof CSSStyleRule)) {
203
+ return false
204
+ }
205
+
206
+ // In unistyles pseudos are prefixed with ':' but in css some of them are prefixed with '::'
207
+ return rule.selectorText.replace('::', ':').includes(hash)
208
+ }) ?? null
209
+
210
+ if (!rule) {
211
+ rule = sheet.cssRules.item(sheet.insertRule(`.${hash} {}`))
212
+ }
213
+
214
+ if (!(rule instanceof CSSStyleRule) || !keyInObject(rule.style, key)) {
215
+ return
49
216
  }
217
+
218
+ rule.style[key as RemoveReadonlyStyleKeys<typeof key>] = value
50
219
  }
51
220
 
52
- updateStyles = (unistyles: TypeStyle, stylesheet: UnistylesValues, className: string) => {
53
- const typestyleStylesheet = convertToTypeStyle(stylesheet)
221
+ remove = (value: UnistylesValues) => {
222
+ const hash = generateHash(value)
223
+ const existingStyles = this.stylesCounter.get(hash)
224
+
225
+ if (!existingStyles) {
226
+ return
227
+ }
228
+
229
+ existingStyles.delete(value)
230
+
231
+ if (existingStyles.size === 0) {
232
+ const ruleIndex = Array.from(this.styleTag.sheet?.cssRules ?? []).findIndex(rule => rule.cssText.includes(`.${hash}`))
54
233
 
55
- unistyles.reinit()
56
- unistyles.cssRule(`.${className}`, typestyleStylesheet)
234
+ this.styleTag.sheet?.deleteRule(ruleIndex)
235
+ }
57
236
  }
58
237
  }
59
238
 
@@ -1,11 +1,8 @@
1
1
  import type { UnistylesValues } from '../types'
2
- import { listenToDependencies } from './listener'
3
2
  import { UnistylesRegistry } from './registry'
4
- import { createDoubleMap, extractHiddenProperties, extractSecrets, isInDocument } from './utils'
3
+ import { createDoubleMap, equal, extractSecrets, extractUnistyleDependencies, isInDocument } from './utils'
5
4
  import { getVariants } from './variants'
6
5
 
7
- type WebUnistyle = ReturnType<typeof UnistylesRegistry.createStyles>
8
-
9
6
  type Style = UnistylesValues | ((...args: Array<any>) => UnistylesValues)
10
7
 
11
8
  class UnistylesShadowRegistryBuilder {
@@ -17,9 +14,8 @@ class UnistylesShadowRegistryBuilder {
17
14
  dispose = () => {}
18
15
  // END MOCKS
19
16
 
20
- private readonly webUnistylesMap = createDoubleMap<HTMLElement, string, WebUnistyle>()
21
- private readonly disposeMap = createDoubleMap<HTMLElement, string, VoidFunction | undefined>()
22
- private readonly stylesMap = createDoubleMap<HTMLElement, string, HTMLStyleElement>()
17
+ private resultsMap = createDoubleMap<HTMLElement, string, UnistylesValues>()
18
+ private classNamesMap = createDoubleMap<HTMLElement, string, Array<string>>()
23
19
 
24
20
  add = (ref: any, _style?: Style | Array<Style>, _variants?: Record<string, any>, _args?: Array<any>) => {
25
21
  // Style is not provided
@@ -43,13 +39,19 @@ class UnistylesShadowRegistryBuilder {
43
39
  if (ref === null) {
44
40
  const secrets = extractSecrets(_style)
45
41
 
46
- secrets.forEach(({ __uni__refs }) => {
42
+ secrets.forEach(({ __uni__refs, __uni__key }) => {
47
43
  __uni__refs.forEach(ref => {
48
44
  if (isInDocument(ref)) {
49
45
  return
50
46
  }
51
47
 
52
- this.remove(ref, _style)
48
+ const oldResult = this.resultsMap.get(ref, __uni__key)
49
+ this.resultsMap.delete(ref, __uni__key)
50
+ this.classNamesMap.delete(ref, __uni__key)
51
+
52
+ if (oldResult) {
53
+ UnistylesRegistry.remove(oldResult)
54
+ }
53
55
  })
54
56
  })
55
57
 
@@ -62,63 +64,61 @@ class UnistylesShadowRegistryBuilder {
62
64
  }
63
65
 
64
66
  extractSecrets(_style).forEach(secret => {
65
- const { __uni__key, __uni__stylesheet, __uni__refs, __uni__variants, __uni__args = [] } = secret
67
+ const { __uni__key, __uni__stylesheet, __uni__variants, __uni__args = [], __uni__refs } = secret
66
68
  const newComputedStylesheet = UnistylesRegistry.getComputedStylesheet(__uni__stylesheet)
67
- const style = newComputedStylesheet[__uni__key]
69
+ const style = newComputedStylesheet[__uni__key]!
68
70
  const args = _args ?? __uni__args
69
- const resultHidden = typeof style === 'function'
71
+ const variants = _variants && Object.keys(_variants).length > 0 ? _variants : __uni__variants
72
+ const result = typeof style === 'function'
70
73
  ? style(...args)
71
74
  : style
72
- const result = extractHiddenProperties(resultHidden)
73
- const { variants } = Object.fromEntries(getVariants({ variants: result }, _variants && Object.keys(_variants).length > 0 ? _variants : __uni__variants))
75
+ const { variantsResult } = Object.fromEntries(getVariants({ variantsResult: result }, variants))
74
76
  const resultWithVariants = {
75
77
  ...result,
76
- ...variants
78
+ ...variantsResult
77
79
  }
78
- const storedWebUnistyle = this.webUnistylesMap.get(ref, __uni__key)
79
- const webUnistyle = storedWebUnistyle ?? UnistylesRegistry.createStyles(resultWithVariants, __uni__key)
80
+ const oldResult = this.resultsMap.get(ref, __uni__key)
80
81
 
81
- this.webUnistylesMap.set(ref, __uni__key, webUnistyle)
82
- this.disposeMap.get(ref, __uni__key)?.()
83
- this.disposeMap.set(ref, __uni__key, listenToDependencies({
84
- key: __uni__key,
85
- stylesheet: __uni__stylesheet,
86
- args,
87
- className: webUnistyle.className,
88
- unistyles: webUnistyle.unistyles,
89
- }))
82
+ // If results are the same do nothing
83
+ if (equal(oldResult, resultWithVariants)) {
84
+ return
85
+ }
86
+
87
+ const oldClassNames = this.classNamesMap.get(ref, __uni__key)
90
88
 
91
- if (!storedWebUnistyle) {
92
- const styleTag = document.createElement('style')
89
+ // Remove old styles
90
+ if (oldResult) {
91
+ UnistylesRegistry.remove(oldResult)
92
+ }
93
93
 
94
- const additionalClasses = resultWithVariants?._web?._classNames
94
+ // Remove old classnames from the ref
95
+ oldClassNames?.forEach(className => ref.classList.remove(className))
96
+ this.resultsMap.set(ref, __uni__key, resultWithVariants)
95
97
 
96
- if (additionalClasses) {
97
- ref.classList.add(...Array.isArray(additionalClasses) ? additionalClasses : [additionalClasses])
98
- }
98
+ const className = UnistylesRegistry.add({
99
+ key: __uni__key,
100
+ args,
101
+ stylesheet: __uni__stylesheet,
102
+ value: resultWithVariants,
103
+ variants
104
+ })
105
+ const injectedClassNames: Array<string> = resultWithVariants?._web?._classNames ?? []
106
+ const newClassNames = injectedClassNames.concat(className)
107
+ const dependencies = extractUnistyleDependencies(resultWithVariants)
99
108
 
100
- ref.classList.add(webUnistyle.className)
101
- webUnistyle.unistyles.setStylesTarget(styleTag)
102
- document.head.appendChild(styleTag)
103
- __uni__refs.add(ref)
104
- this.stylesMap.set(ref, __uni__key, styleTag)
109
+ if (typeof __uni__stylesheet === 'function') {
110
+ // Add dependencies from dynamic styles to stylesheet
111
+ UnistylesRegistry.addDependenciesToStylesheet(__uni__stylesheet, dependencies)
105
112
  }
106
113
 
107
- if (storedWebUnistyle) {
108
- UnistylesRegistry.updateStyles(webUnistyle.unistyles, resultWithVariants, webUnistyle.className)
109
- }
114
+ __uni__refs.add(ref)
115
+ this.classNamesMap.set(ref, __uni__key, newClassNames)
116
+ // Add new classnames to the ref
117
+ ref.classList.add(...newClassNames)
110
118
  })
111
119
  }
112
120
 
113
- remove = (ref: HTMLElement, style: Style) => {
114
- extractSecrets(style).forEach(({ __uni__key }) => {
115
- this.webUnistylesMap.delete(ref, __uni__key)
116
- this.disposeMap.get(ref, __uni__key)?.()
117
- this.disposeMap.delete(ref, __uni__key)
118
- this.stylesMap.get(ref, __uni__key)?.remove()
119
- this.stylesMap.delete(ref, __uni__key)
120
- })
121
- }
121
+ remove = () => {}
122
122
  }
123
123
 
124
124
  export const UnistylesShadowRegistry = new UnistylesShadowRegistryBuilder()
package/src/web/state.ts CHANGED
@@ -8,12 +8,19 @@ import { UnistylesListener } from './listener'
8
8
  import { UnistyleDependency } from '../specs/NativePlatform'
9
9
 
10
10
  class UnistylesStateBuilder {
11
- private readonly isSSR = isServer()
12
-
13
11
  themes = new Map<string, UnistylesTheme>()
14
12
  themeName?: AppThemeName
15
13
 
16
- breakpoint?: AppBreakpoint
14
+ private matchingBreakpoints = new Map<string, boolean>()
15
+
16
+ get breakpoint() {
17
+ const [currentBreakpoint] = Array.from(this.matchingBreakpoints)
18
+ .reverse()
19
+ .find(([_key, value]) => value) ?? []
20
+
21
+ return currentBreakpoint as AppBreakpoint | undefined
22
+ }
23
+
17
24
  breakpoints?: UnistylesBreakpoints
18
25
 
19
26
  hasAdaptiveThemes = false
@@ -23,7 +30,7 @@ class UnistylesStateBuilder {
23
30
  this.initBreakpoints(config.breakpoints)
24
31
  this.initSettings(config.settings)
25
32
 
26
- if (this.isSSR) {
33
+ if (isServer()) {
27
34
  return
28
35
  }
29
36
 
@@ -64,8 +71,6 @@ class UnistylesStateBuilder {
64
71
  }
65
72
 
66
73
  private initBreakpoints = (breakpoints = {} as UnistylesBreakpoints) => {
67
- const breakpointsMap = new Map<string, MediaQueryList>()
68
-
69
74
  this.breakpoints = breakpoints
70
75
 
71
76
  Object.entries(breakpoints)
@@ -76,25 +81,10 @@ class UnistylesStateBuilder {
76
81
  }
77
82
 
78
83
  const mediaQuery = window.matchMedia(`(min-width: ${value}px)`)
79
- breakpointsMap.set(breakpoint, mediaQuery)
80
-
81
- if (mediaQuery.matches) {
82
- this.breakpoint = breakpoint as AppBreakpoint
83
- }
84
+ this.matchingBreakpoints.set(breakpoint, mediaQuery.matches)
84
85
 
85
86
  mediaQuery.addEventListener('change', event => {
86
- if (!event.matches) {
87
- const [currentBreakpoint] = Array.from(breakpointsMap).find(([,mq]) => mq.matches) ?? []
88
-
89
- if (currentBreakpoint) {
90
- this.breakpoint = currentBreakpoint as AppBreakpoint
91
- UnistylesListener.emitChange(UnistyleDependency.Breakpoints)
92
- }
93
-
94
- return
95
- }
96
-
97
- this.breakpoint = breakpoint as AppBreakpoint
87
+ this.matchingBreakpoints.set(breakpoint, event.matches)
98
88
  UnistylesListener.emitChange(UnistyleDependency.Breakpoints)
99
89
  })
100
90
  })