@rafaelaugusto/jolt 0.1.0-beta.1 → 0.1.0-beta.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.
Files changed (302) hide show
  1. package/README.md +367 -18
  2. package/dist/animate.d.ts +19 -3
  3. package/dist/animate.d.ts.map +1 -1
  4. package/dist/animate.js +186 -14
  5. package/dist/animate.js.map +1 -1
  6. package/dist/color.d.ts +11 -0
  7. package/dist/color.d.ts.map +1 -0
  8. package/dist/color.js +73 -0
  9. package/dist/color.js.map +1 -0
  10. package/dist/config.d.ts +31 -0
  11. package/dist/config.d.ts.map +1 -0
  12. package/dist/config.js +73 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/decay.d.ts +11 -0
  15. package/dist/decay.d.ts.map +1 -0
  16. package/dist/decay.js +22 -0
  17. package/dist/decay.js.map +1 -0
  18. package/dist/decoration.d.ts +18 -0
  19. package/dist/decoration.d.ts.map +1 -0
  20. package/dist/decoration.js +155 -0
  21. package/dist/decoration.js.map +1 -0
  22. package/dist/drag-input.d.ts +15 -0
  23. package/dist/drag-input.d.ts.map +1 -0
  24. package/dist/drag-input.js +66 -0
  25. package/dist/drag-input.js.map +1 -0
  26. package/dist/drag-physics.d.ts +20 -0
  27. package/dist/drag-physics.d.ts.map +1 -0
  28. package/dist/drag-physics.js +75 -0
  29. package/dist/drag-physics.js.map +1 -0
  30. package/dist/drag.d.ts +58 -0
  31. package/dist/drag.d.ts.map +1 -0
  32. package/dist/drag.js +324 -0
  33. package/dist/drag.js.map +1 -0
  34. package/dist/driver/android-color.d.ts +20 -0
  35. package/dist/driver/android-color.d.ts.map +1 -0
  36. package/dist/driver/android-color.js +136 -0
  37. package/dist/driver/android-color.js.map +1 -0
  38. package/dist/driver/android-decoration.d.ts +22 -0
  39. package/dist/driver/android-decoration.d.ts.map +1 -0
  40. package/dist/driver/android-decoration.js +139 -0
  41. package/dist/driver/android-decoration.js.map +1 -0
  42. package/dist/driver/android-playback.d.ts +13 -0
  43. package/dist/driver/android-playback.d.ts.map +1 -0
  44. package/dist/driver/android-playback.js +141 -0
  45. package/dist/driver/android-playback.js.map +1 -0
  46. package/dist/driver/android.d.ts +1 -1
  47. package/dist/driver/android.d.ts.map +1 -1
  48. package/dist/driver/android.js +165 -13
  49. package/dist/driver/android.js.map +1 -1
  50. package/dist/driver/index.d.ts +25 -2
  51. package/dist/driver/index.d.ts.map +1 -1
  52. package/dist/driver/index.js.map +1 -1
  53. package/dist/driver/ios-color.d.ts +16 -0
  54. package/dist/driver/ios-color.d.ts.map +1 -0
  55. package/dist/driver/ios-color.js +392 -0
  56. package/dist/driver/ios-color.js.map +1 -0
  57. package/dist/driver/ios-decoration.d.ts +17 -0
  58. package/dist/driver/ios-decoration.d.ts.map +1 -0
  59. package/dist/driver/ios-decoration.js +271 -0
  60. package/dist/driver/ios-decoration.js.map +1 -0
  61. package/dist/driver/ios-layout.d.ts +9 -0
  62. package/dist/driver/ios-layout.d.ts.map +1 -0
  63. package/dist/driver/ios-layout.js +52 -0
  64. package/dist/driver/ios-layout.js.map +1 -0
  65. package/dist/driver/ios-playback.d.ts +10 -0
  66. package/dist/driver/ios-playback.d.ts.map +1 -0
  67. package/dist/driver/ios-playback.js +47 -0
  68. package/dist/driver/ios-playback.js.map +1 -0
  69. package/dist/driver/ios-shadow.d.ts +6 -0
  70. package/dist/driver/ios-shadow.d.ts.map +1 -0
  71. package/dist/driver/ios-shadow.js +52 -0
  72. package/dist/driver/ios-shadow.js.map +1 -0
  73. package/dist/driver/ios.d.ts.map +1 -1
  74. package/dist/driver/ios.js +163 -28
  75. package/dist/driver/ios.js.map +1 -1
  76. package/dist/engine.d.ts +75 -5
  77. package/dist/engine.d.ts.map +1 -1
  78. package/dist/engine.js +293 -23
  79. package/dist/engine.js.map +1 -1
  80. package/dist/haptics.d.ts +21 -0
  81. package/dist/haptics.d.ts.map +1 -0
  82. package/dist/haptics.js +120 -0
  83. package/dist/haptics.js.map +1 -0
  84. package/dist/image-effect-native.d.ts +26 -0
  85. package/dist/image-effect-native.d.ts.map +1 -0
  86. package/dist/image-effect-native.js +73 -0
  87. package/dist/image-effect-native.js.map +1 -0
  88. package/dist/image-effect.d.ts +50 -0
  89. package/dist/image-effect.d.ts.map +1 -0
  90. package/dist/image-effect.js +290 -0
  91. package/dist/image-effect.js.map +1 -0
  92. package/dist/image-owner.d.ts +3 -0
  93. package/dist/image-owner.d.ts.map +1 -0
  94. package/dist/image-owner.js +11 -0
  95. package/dist/image-owner.js.map +1 -0
  96. package/dist/index.d.ts +43 -2
  97. package/dist/index.d.ts.map +1 -1
  98. package/dist/index.js +20 -1
  99. package/dist/index.js.map +1 -1
  100. package/dist/interaction-surface.d.ts +12 -0
  101. package/dist/interaction-surface.d.ts.map +1 -0
  102. package/dist/interaction-surface.js +36 -0
  103. package/dist/interaction-surface.js.map +1 -0
  104. package/dist/items.d.ts +20 -0
  105. package/dist/items.d.ts.map +1 -0
  106. package/dist/items.js +109 -0
  107. package/dist/items.js.map +1 -0
  108. package/dist/keyboard.d.ts +41 -0
  109. package/dist/keyboard.d.ts.map +1 -0
  110. package/dist/keyboard.js +256 -0
  111. package/dist/keyboard.js.map +1 -0
  112. package/dist/label.d.ts +7 -0
  113. package/dist/label.d.ts.map +1 -0
  114. package/dist/label.js +60 -0
  115. package/dist/label.js.map +1 -0
  116. package/dist/layout.d.ts +13 -0
  117. package/dist/layout.d.ts.map +1 -0
  118. package/dist/layout.js +348 -0
  119. package/dist/layout.js.map +1 -0
  120. package/dist/liquid-grid.d.ts +3 -0
  121. package/dist/liquid-grid.d.ts.map +1 -0
  122. package/dist/liquid-grid.js +24 -0
  123. package/dist/liquid-grid.js.map +1 -0
  124. package/dist/liquid.d.ts +18 -0
  125. package/dist/liquid.d.ts.map +1 -0
  126. package/dist/liquid.js +234 -0
  127. package/dist/liquid.js.map +1 -0
  128. package/dist/loader.d.ts +19 -0
  129. package/dist/loader.d.ts.map +1 -0
  130. package/dist/loader.js +173 -0
  131. package/dist/loader.js.map +1 -0
  132. package/dist/motion-scope.d.ts +39 -0
  133. package/dist/motion-scope.d.ts.map +1 -0
  134. package/dist/motion-scope.js +238 -0
  135. package/dist/motion-scope.js.map +1 -0
  136. package/dist/motion-states.d.ts +36 -0
  137. package/dist/motion-states.d.ts.map +1 -0
  138. package/dist/motion-states.js +165 -0
  139. package/dist/motion-states.js.map +1 -0
  140. package/dist/particles.d.ts +39 -0
  141. package/dist/particles.d.ts.map +1 -0
  142. package/dist/particles.js +265 -0
  143. package/dist/particles.js.map +1 -0
  144. package/dist/path.d.ts +12 -0
  145. package/dist/path.d.ts.map +1 -0
  146. package/dist/path.js +90 -0
  147. package/dist/path.js.map +1 -0
  148. package/dist/playback-group.d.ts +6 -0
  149. package/dist/playback-group.d.ts.map +1 -0
  150. package/dist/playback-group.js +141 -0
  151. package/dist/playback-group.js.map +1 -0
  152. package/dist/playback.d.ts +25 -0
  153. package/dist/playback.d.ts.map +1 -0
  154. package/dist/playback.js +35 -0
  155. package/dist/playback.js.map +1 -0
  156. package/dist/press.d.ts.map +1 -1
  157. package/dist/press.js +23 -7
  158. package/dist/press.js.map +1 -1
  159. package/dist/properties.d.ts +6 -3
  160. package/dist/properties.d.ts.map +1 -1
  161. package/dist/properties.js +26 -2
  162. package/dist/properties.js.map +1 -1
  163. package/dist/reveal.d.ts +25 -0
  164. package/dist/reveal.d.ts.map +1 -0
  165. package/dist/reveal.js +294 -0
  166. package/dist/reveal.js.map +1 -0
  167. package/dist/roll-diff.d.ts +22 -0
  168. package/dist/roll-diff.d.ts.map +1 -0
  169. package/dist/roll-diff.js +36 -0
  170. package/dist/roll-diff.js.map +1 -0
  171. package/dist/roll.d.ts +29 -0
  172. package/dist/roll.d.ts.map +1 -0
  173. package/dist/roll.js +442 -0
  174. package/dist/roll.js.map +1 -0
  175. package/dist/scroll-linked.d.ts +10 -0
  176. package/dist/scroll-linked.d.ts.map +1 -0
  177. package/dist/scroll-linked.js +58 -0
  178. package/dist/scroll-linked.js.map +1 -0
  179. package/dist/sequence.d.ts +10 -5
  180. package/dist/sequence.d.ts.map +1 -1
  181. package/dist/sequence.js +208 -14
  182. package/dist/sequence.js.map +1 -1
  183. package/dist/shimmer.d.ts +12 -0
  184. package/dist/shimmer.d.ts.map +1 -0
  185. package/dist/shimmer.js +161 -0
  186. package/dist/shimmer.js.map +1 -0
  187. package/dist/svg-path.d.ts +14 -0
  188. package/dist/svg-path.d.ts.map +1 -0
  189. package/dist/svg-path.js +281 -0
  190. package/dist/svg-path.js.map +1 -0
  191. package/dist/symbol-effect.d.ts +23 -0
  192. package/dist/symbol-effect.d.ts.map +1 -0
  193. package/dist/symbol-effect.js +187 -0
  194. package/dist/symbol-effect.js.map +1 -0
  195. package/dist/text-layout.d.ts +30 -0
  196. package/dist/text-layout.d.ts.map +1 -0
  197. package/dist/text-layout.js +185 -0
  198. package/dist/text-layout.js.map +1 -0
  199. package/dist/text.d.ts +17 -0
  200. package/dist/text.d.ts.map +1 -0
  201. package/dist/text.js +263 -0
  202. package/dist/text.js.map +1 -0
  203. package/dist/track.d.ts +3 -1
  204. package/dist/track.d.ts.map +1 -1
  205. package/dist/track.js +266 -13
  206. package/dist/track.js.map +1 -1
  207. package/dist/transition.d.ts +17 -1
  208. package/dist/transition.d.ts.map +1 -1
  209. package/dist/transition.js +41 -6
  210. package/dist/transition.js.map +1 -1
  211. package/dist/types.d.ts +48 -1
  212. package/dist/types.d.ts.map +1 -1
  213. package/dist/vue/index.d.ts +95 -0
  214. package/dist/vue/index.d.ts.map +1 -0
  215. package/dist/vue/index.js +163 -0
  216. package/dist/vue/index.js.map +1 -0
  217. package/dist/zoom-native.d.ts +30 -0
  218. package/dist/zoom-native.d.ts.map +1 -0
  219. package/dist/zoom-native.js +56 -0
  220. package/dist/zoom-native.js.map +1 -0
  221. package/dist/zoomable.d.ts +48 -0
  222. package/dist/zoomable.d.ts.map +1 -0
  223. package/dist/zoomable.js +249 -0
  224. package/dist/zoomable.js.map +1 -0
  225. package/package.json +29 -5
  226. package/platforms/android/include.gradle +7 -0
  227. package/platforms/android/java/org/rafaelaugusto/jolt/ColorTarget.java +102 -0
  228. package/platforms/android/java/org/rafaelaugusto/jolt/DecorationTarget.java +154 -0
  229. package/platforms/android/java/org/rafaelaugusto/jolt/ImageEffect.java +288 -0
  230. package/platforms/android/java/org/rafaelaugusto/jolt/KeyboardFollower.java +91 -0
  231. package/platforms/android/java/org/rafaelaugusto/jolt/KeyboardObserver.java +97 -0
  232. package/platforms/android/java/org/rafaelaugusto/jolt/NumberRoll.java +190 -0
  233. package/platforms/android/java/org/rafaelaugusto/jolt/PhotoZoom.java +250 -0
  234. package/platforms/android/java/org/rafaelaugusto/jolt/TextReveal.java +180 -0
  235. package/platforms/android/proguard-rules.pro +19 -0
  236. package/platforms/ios/build.xcconfig +1 -0
  237. package/platforms/ios/src/JoltImageEffect.h +25 -0
  238. package/platforms/ios/src/JoltImageEffect.mm +242 -0
  239. package/platforms/ios/src/JoltInteractiveAnimation.h +18 -0
  240. package/platforms/ios/src/JoltInteractiveAnimation.m +123 -0
  241. package/platforms/ios/src/JoltPhotoZoom.h +23 -0
  242. package/platforms/ios/src/JoltPhotoZoom.m +229 -0
  243. package/platforms/ios/src/module.modulemap +6 -0
  244. package/src/android-plugin.d.ts +155 -0
  245. package/src/animate.ts +249 -36
  246. package/src/color.ts +101 -0
  247. package/src/config.ts +84 -0
  248. package/src/decay.ts +45 -0
  249. package/src/decoration.ts +180 -0
  250. package/src/drag-input.ts +74 -0
  251. package/src/drag-physics.ts +110 -0
  252. package/src/drag.ts +395 -0
  253. package/src/driver/android-color.ts +170 -0
  254. package/src/driver/android-decoration.ts +182 -0
  255. package/src/driver/android-playback.ts +157 -0
  256. package/src/driver/android.ts +208 -20
  257. package/src/driver/index.ts +37 -2
  258. package/src/driver/ios-color.ts +441 -0
  259. package/src/driver/ios-decoration.ts +332 -0
  260. package/src/driver/ios-layout.ts +63 -0
  261. package/src/driver/ios-playback.ts +51 -0
  262. package/src/driver/ios-shadow.ts +50 -0
  263. package/src/driver/ios.ts +193 -33
  264. package/src/engine.ts +321 -27
  265. package/src/haptics.ts +148 -0
  266. package/src/image-effect-native.ts +129 -0
  267. package/src/image-effect.ts +336 -0
  268. package/src/image-owner.ts +12 -0
  269. package/src/index.ts +59 -2
  270. package/src/interaction-surface.ts +41 -0
  271. package/src/ios-plugin.d.ts +81 -0
  272. package/src/items.ts +140 -0
  273. package/src/keyboard.ts +291 -0
  274. package/src/label.ts +76 -0
  275. package/src/layout.ts +408 -0
  276. package/src/liquid-grid.ts +28 -0
  277. package/src/liquid.ts +287 -0
  278. package/src/loader.ts +202 -0
  279. package/src/motion-scope.ts +279 -0
  280. package/src/motion-states.ts +215 -0
  281. package/src/particles.ts +323 -0
  282. package/src/path.ts +124 -0
  283. package/src/playback-group.ts +143 -0
  284. package/src/playback.ts +62 -0
  285. package/src/press.ts +26 -10
  286. package/src/properties.ts +32 -6
  287. package/src/reveal.ts +374 -0
  288. package/src/roll-diff.ts +57 -0
  289. package/src/roll.ts +515 -0
  290. package/src/scroll-linked.ts +73 -0
  291. package/src/sequence.ts +204 -14
  292. package/src/shimmer.ts +180 -0
  293. package/src/svg-path.ts +355 -0
  294. package/src/symbol-effect.ts +226 -0
  295. package/src/text-layout.ts +228 -0
  296. package/src/text.ts +279 -0
  297. package/src/track.ts +347 -12
  298. package/src/transition.ts +63 -6
  299. package/src/types.ts +49 -1
  300. package/src/vue/index.ts +231 -0
  301. package/src/zoom-native.ts +124 -0
  302. package/src/zoomable.ts +330 -0
package/src/driver/ios.ts CHANGED
@@ -1,14 +1,26 @@
1
- import type { View } from '@nativescript/core'
2
- import type { Property } from '../properties.js'
1
+ import { iosPlayback } from './ios-playback.js'
2
+ import { isDecorationProperty } from '../decoration.js'
3
+ import {
4
+ playIOSDecoration,
5
+ presentedIOSDecoration,
6
+ syncIOSDecoration,
7
+ } from './ios-decoration.js'
8
+ import { Application, type View } from '@nativescript/core'
9
+ import { stopView } from '../engine.js'
10
+ import type { NumericProperty } from '../properties.js'
11
+ import { isColorProperty } from '../color.js'
12
+ import { playIOSColor, presentedIOSColor } from './ios-color.js'
3
13
  import { after, type Driver } from './index.js'
14
+ import { hasInteractionSurface } from '../interaction-surface.js'
15
+ import { retainInteractiveLayout } from './ios-layout.js'
4
16
 
5
17
  interface Handle {
6
- layers: CALayer[]
7
- key: string
8
- onStop?: () => void
18
+ stop(): void
19
+ elapsed(): number
20
+ control(elapsed: number, paused: boolean): void
9
21
  }
10
22
 
11
- const keyPaths: Record<Property, string> = {
23
+ const keyPaths: Record<NumericProperty, string> = {
12
24
  opacity: 'opacity',
13
25
  x: 'transform.translation.x',
14
26
  y: 'transform.translation.y',
@@ -49,49 +61,197 @@ export function createIOSDriver(): Driver {
49
61
  now: () => CACurrentMediaTime() * 1000,
50
62
 
51
63
  play(view, track, startedAt, onEnd): Handle {
64
+ if (isDecorationProperty(track.property))
65
+ return playIOSDecoration(view, track, startedAt, onEnd)
66
+ if (isColorProperty(track.property))
67
+ return playIOSColor(view, track, startedAt, onEnd)
52
68
  const layers = layersOf(view)
53
69
  const key = `jolt:${track.property}`
54
70
  const rotation = track.property.startsWith('rotate')
71
+ if (hasInteractionSurface(view)) {
72
+ if (typeof JoltInteractiveAnimation === 'undefined')
73
+ throw new Error('Rebuild the iOS app to enable Jolt interaction surfaces.')
74
+ if (track.property === 'rotateX' || track.property === 'rotateY')
75
+ ensurePerspective(view, layers)
76
+ const releaseLayout = retainInteractiveLayout(view)
77
+ const suspend = () => stopView(view, [track.property])
78
+ const completed = (finished: boolean) => {
79
+ Application.off(Application.suspendEvent, suspend)
80
+ releaseLayout()
81
+ onEnd(finished)
82
+ }
83
+ let native: JoltInteractiveAnimation
84
+ try {
85
+ native =
86
+ JoltInteractiveAnimation.startViewLayersKeyPathValuesTimesDurationDelayRepeatReverseFinalValueStartedAtCompletion(
87
+ view.nativeViewProtected,
88
+ NSArray.arrayWithArray(layers),
89
+ keyPaths[track.property as NumericProperty],
90
+ NSArray.arrayWithArray(
91
+ track.values.map((value) => (rotation ? radians(value) : value)),
92
+ ),
93
+ NSArray.arrayWithArray(track.times as number[]),
94
+ track.duration,
95
+ track.delay,
96
+ track.repeat,
97
+ track.reverse,
98
+ rotation ? radians(track.to) : track.to,
99
+ startedAt,
100
+ completed,
101
+ )
102
+ } catch (error) {
103
+ releaseLayout()
104
+ throw error
105
+ }
106
+ Application.on(Application.suspendEvent, suspend)
107
+ return {
108
+ elapsed: () => native.elapsed,
109
+ control: (time, paused) => native.controlPaused(time, paused),
110
+ stop: () => native.cancel(),
111
+ }
112
+ }
55
113
  const infinite = track.repeat === Infinity
56
114
  if (track.property === 'rotateX' || track.property === 'rotateY') {
57
115
  ensurePerspective(view, layers)
58
116
  }
59
117
 
60
- const animation = CAKeyframeAnimation.animationWithKeyPath(keyPaths[track.property])
61
- animation.values = NSArray.arrayWithArray(
62
- track.values.map((value) => (rotation ? radians(value) : value)),
63
- )
64
- animation.keyTimes = NSArray.arrayWithArray(track.times as number[])
65
- animation.duration = Math.max(track.duration, 1) / 1000
66
- animation.beginTime = (startedAt + track.delay) / 1000
67
- animation.fillMode = kCAFillModeBackwards
68
- // Keep infinite loops when iOS removes animations on backgrounding.
69
- // They are removed explicitly when stopped or replaced.
70
- animation.removedOnCompletion = !infinite
71
- if (track.repeat > 0) {
72
- animation.autoreverses = track.reverse
73
- animation.repeatCount = track.reverse ? (track.repeat + 1) / 2 : track.repeat + 1
118
+ const timing = iosPlayback(track, startedAt)
119
+ let stopped = false,
120
+ generation = 0
121
+ const attach = () => {
122
+ const instance = ++generation
123
+ const animation = CAKeyframeAnimation.animationWithKeyPath(
124
+ keyPaths[track.property as NumericProperty],
125
+ )
126
+ // iOS 15+. The app must opt in through CADisableMinimumFrameDurationOnPhone.
127
+ if (animation.respondsToSelector('setPreferredFrameRateRange:')) {
128
+ const nativeView = view.nativeViewProtected as UIView
129
+ const screen = nativeView.window?.screen ?? UIScreen.mainScreen
130
+ const maximum = Math.min(120, screen.maximumFramesPerSecond)
131
+ animation.preferredFrameRateRange = CAFrameRateRangeMake(
132
+ Math.min(80, maximum),
133
+ maximum,
134
+ maximum,
135
+ )
136
+ }
137
+ animation.values = NSArray.arrayWithArray(
138
+ track.values.map((value) => (rotation ? radians(value) : value)),
139
+ )
140
+ animation.keyTimes = NSArray.arrayWithArray(track.times as number[])
141
+ animation.duration = Math.max(track.duration, 1) / 1000
142
+ // Keep infinite loops when iOS removes animations on backgrounding.
143
+ // They are removed explicitly when stopped or replaced.
144
+ if (track.repeat > 0) {
145
+ animation.autoreverses = track.reverse
146
+ animation.repeatCount = track.reverse
147
+ ? (track.repeat + 1) / 2
148
+ : track.repeat + 1
149
+ }
150
+
151
+ CATransaction.begin()
152
+ if (!timing.paused && !infinite)
153
+ CATransaction.setCompletionBlock(() => {
154
+ if (stopped || instance !== generation) return
155
+ stopped = true
156
+ onEnd()
157
+ })
158
+ for (const layer of layers) {
159
+ timing.configure(animation, layer)
160
+ layer.addAnimationForKey(animation, key)
161
+ }
162
+ CATransaction.commit()
74
163
  }
164
+ attach()
165
+ return {
166
+ elapsed: timing.elapsed,
167
+ control(time, paused) {
168
+ if (!stopped) {
169
+ timing.control(time, paused)
170
+ attach()
171
+ }
172
+ },
173
+ stop() {
174
+ if (stopped) return
175
+ stopped = true
176
+ generation++
177
+ for (const layer of layers) layer.removeAnimationForKey(key)
178
+ onEnd(false)
179
+ },
180
+ }
181
+ },
75
182
 
76
- CATransaction.begin()
77
- // iOS completes the transaction on backgrounding even if the loop is retained.
78
- if (!infinite) CATransaction.setCompletionBlock(onEnd)
79
- for (const layer of layers) layer.addAnimationForKey(animation, key)
80
- CATransaction.commit()
183
+ stop(_view, handle) {
184
+ ;(handle as Handle).stop()
185
+ },
186
+ control(_view, handle, elapsed, paused) {
187
+ ;(handle as Handle).control(elapsed, paused)
188
+ },
189
+ elapsed: (handle) => (handle as Handle).elapsed(),
81
190
 
82
- return { layers, key, onStop: infinite ? onEnd : undefined }
191
+ sync(view, excluding) {
192
+ syncIOSDecoration(view, excluding)
193
+ if (view.nativeViewProtected && typeof JoltInteractiveAnimation !== 'undefined')
194
+ JoltInteractiveAnimation.syncViewExcluding(
195
+ view.nativeViewProtected,
196
+ excluding ? (keyPaths[excluding as NumericProperty] ?? null) : null,
197
+ )
83
198
  },
84
199
 
85
- stop(_view, handle) {
86
- const playing = handle as Handle
87
- const { layers, key, onStop } = playing
88
- playing.onStop = undefined
89
- for (const layer of layers) layer.removeAnimationForKey(key)
90
- onStop?.()
200
+ presented(view, property) {
201
+ if (isDecorationProperty(property)) return presentedIOSDecoration(view, property)
202
+ if (isColorProperty(property)) return presentedIOSColor(view, property)
203
+ if (!view.nativeViewProtected || typeof JoltInteractiveAnimation === 'undefined')
204
+ return undefined
205
+ const value = JoltInteractiveAnimation.valueForViewKeyPath(
206
+ view.nativeViewProtected,
207
+ keyPaths[property],
208
+ )
209
+ if (value === null || value === undefined) return undefined
210
+ return property.startsWith('rotate') ? (value * 180) / Math.PI : Number(value)
91
211
  },
92
212
 
93
- presented: () => undefined,
213
+ layoutFrame(view) {
214
+ const native = view.nativeViewProtected as UIView | undefined
215
+ if (!native) return undefined
216
+ const { width, height } = native.bounds.size
217
+ const { position, anchorPoint } = native.layer
218
+ return {
219
+ x: position.x - width * anchorPoint.x,
220
+ y: position.y - height * anchorPoint.y,
221
+ width,
222
+ height,
223
+ }
224
+ },
225
+
226
+ afterLayout(view, callback) {
227
+ const original = view.layout
228
+ const descriptor = Object.getOwnPropertyDescriptor(view, 'layout')
229
+ let active = true
230
+ const detach = () => {
231
+ active = false
232
+ if (view.layout !== wrapper) return
233
+ if (descriptor) Object.defineProperty(view, 'layout', descriptor)
234
+ else delete (view as Partial<View>).layout
235
+ }
236
+ const wrapper: View['layout'] = function (this: View, ...args) {
237
+ original.apply(this, args)
238
+ if (active) {
239
+ detach()
240
+ callback()
241
+ }
242
+ }
243
+ view.layout = wrapper
244
+ return detach
245
+ },
94
246
 
95
247
  after,
248
+
249
+ reducedMotion: () => UIAccessibilityIsReduceMotionEnabled(),
250
+
251
+ watchReducedMotion(callback) {
252
+ const name = UIAccessibilityReduceMotionStatusDidChangeNotification
253
+ const observer = Application.ios.addNotificationObserver(name, callback)
254
+ return () => Application.ios.removeNotificationObserver(observer, name)
255
+ },
96
256
  }
97
257
  }