@use-voltra/ios-client 1.4.1 → 2.0.0-rc.1

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 (559) hide show
  1. package/README.md +113 -0
  2. package/Voltra.podspec +28 -0
  3. package/build/commonjs/VoltraModule.js +13 -0
  4. package/build/commonjs/VoltraModule.js.map +1 -0
  5. package/build/commonjs/components/VoltraLiveActivityPreview.js +30 -0
  6. package/build/commonjs/components/VoltraLiveActivityPreview.js.map +1 -0
  7. package/build/commonjs/components/VoltraView.js +50 -0
  8. package/build/commonjs/components/VoltraView.js.map +1 -0
  9. package/build/commonjs/components/VoltraWidgetPreview.js +58 -0
  10. package/build/commonjs/components/VoltraWidgetPreview.js.map +1 -0
  11. package/build/commonjs/events.js +32 -0
  12. package/build/commonjs/events.js.map +1 -0
  13. package/build/commonjs/helpers.js +26 -0
  14. package/build/commonjs/helpers.js.map +1 -0
  15. package/build/commonjs/index.js +226 -0
  16. package/build/commonjs/index.js.map +1 -0
  17. package/build/commonjs/live-activity/api.js +168 -0
  18. package/build/commonjs/live-activity/api.js.map +1 -0
  19. package/build/commonjs/logger.js +39 -0
  20. package/build/commonjs/logger.js.map +1 -0
  21. package/build/commonjs/native/NativeVoltra.js +15 -0
  22. package/build/commonjs/native/NativeVoltra.js.map +1 -0
  23. package/build/commonjs/native/VoltraRNNativeComponent.ts +9 -0
  24. package/build/commonjs/package.json +1 -0
  25. package/build/commonjs/preload.js +54 -0
  26. package/build/commonjs/preload.js.map +1 -0
  27. package/build/commonjs/types.js +2 -0
  28. package/build/commonjs/types.js.map +1 -0
  29. package/build/commonjs/utils/assertRunningOnApple.js +16 -0
  30. package/build/commonjs/utils/assertRunningOnApple.js.map +1 -0
  31. package/build/commonjs/utils/helpers.js +19 -0
  32. package/build/commonjs/utils/helpers.js.map +1 -0
  33. package/build/commonjs/utils/index.js +28 -0
  34. package/build/commonjs/utils/index.js.map +1 -0
  35. package/build/commonjs/utils/useUpdateOnHMR.js +25 -0
  36. package/build/commonjs/utils/useUpdateOnHMR.js.map +1 -0
  37. package/build/commonjs/widgets/server-credentials.js +18 -0
  38. package/build/commonjs/widgets/server-credentials.js.map +1 -0
  39. package/build/commonjs/widgets/widget-api.js +55 -0
  40. package/build/commonjs/widgets/widget-api.js.map +1 -0
  41. package/build/module/VoltraModule.js +4 -0
  42. package/build/module/VoltraModule.js.map +1 -0
  43. package/build/module/components/VoltraLiveActivityPreview.js +25 -0
  44. package/build/module/components/VoltraLiveActivityPreview.js.map +1 -0
  45. package/build/module/components/VoltraView.js +44 -0
  46. package/build/module/components/VoltraView.js.map +1 -0
  47. package/build/module/components/VoltraWidgetPreview.js +53 -0
  48. package/build/module/components/VoltraWidgetPreview.js.map +1 -0
  49. package/build/module/events.js +28 -0
  50. package/build/module/events.js.map +1 -0
  51. package/build/module/helpers.js +21 -0
  52. package/build/module/helpers.js.map +1 -0
  53. package/build/module/index.js +17 -0
  54. package/build/module/index.js.map +1 -0
  55. package/build/module/live-activity/api.js +158 -0
  56. package/build/module/live-activity/api.js.map +1 -0
  57. package/build/module/logger.js +35 -0
  58. package/build/module/logger.js.map +1 -0
  59. package/build/module/native/NativeVoltra.js +11 -0
  60. package/build/module/native/NativeVoltra.js.map +1 -0
  61. package/build/module/native/VoltraRNNativeComponent.ts +9 -0
  62. package/build/module/package.json +1 -0
  63. package/build/module/preload.js +48 -0
  64. package/build/module/preload.js.map +1 -0
  65. package/build/module/types.js +2 -0
  66. package/build/module/types.js.map +1 -0
  67. package/build/module/utils/assertRunningOnApple.js +11 -0
  68. package/build/module/utils/assertRunningOnApple.js.map +1 -0
  69. package/build/module/utils/helpers.js +4 -0
  70. package/build/module/utils/helpers.js.map +1 -0
  71. package/build/module/utils/index.js +5 -0
  72. package/build/module/utils/index.js.map +1 -0
  73. package/build/module/utils/useUpdateOnHMR.js +20 -0
  74. package/build/module/utils/useUpdateOnHMR.js.map +1 -0
  75. package/build/module/widgets/server-credentials.js +13 -0
  76. package/build/module/widgets/server-credentials.js.map +1 -0
  77. package/build/module/widgets/widget-api.js +45 -0
  78. package/build/module/widgets/widget-api.js.map +1 -0
  79. package/build/typescript/commonjs/VoltraModule.d.ts +3 -0
  80. package/build/typescript/commonjs/VoltraModule.d.ts.map +1 -0
  81. package/build/typescript/commonjs/components/VoltraLiveActivityPreview.d.ts.map +1 -0
  82. package/build/typescript/commonjs/components/VoltraView.d.ts.map +1 -0
  83. package/build/typescript/commonjs/components/VoltraWidgetPreview.d.ts.map +1 -0
  84. package/build/typescript/commonjs/events.d.ts.map +1 -0
  85. package/build/typescript/commonjs/helpers.d.ts.map +1 -0
  86. package/build/{types → typescript/commonjs}/index.d.ts +5 -0
  87. package/build/typescript/commonjs/index.d.ts.map +1 -0
  88. package/build/typescript/commonjs/live-activity/api.d.ts.map +1 -0
  89. package/build/typescript/commonjs/logger.d.ts.map +1 -0
  90. package/build/typescript/commonjs/native/NativeVoltra.d.ts +100 -0
  91. package/build/typescript/commonjs/native/NativeVoltra.d.ts.map +1 -0
  92. package/build/typescript/commonjs/native/VoltraRNNativeComponent.d.ts +8 -0
  93. package/build/typescript/commonjs/native/VoltraRNNativeComponent.d.ts.map +1 -0
  94. package/build/typescript/commonjs/package.json +1 -0
  95. package/build/typescript/commonjs/preload.d.ts.map +1 -0
  96. package/build/typescript/commonjs/types.d.ts.map +1 -0
  97. package/build/typescript/commonjs/utils/assertRunningOnApple.d.ts.map +1 -0
  98. package/build/typescript/commonjs/utils/helpers.d.ts.map +1 -0
  99. package/build/typescript/commonjs/utils/index.d.ts.map +1 -0
  100. package/build/typescript/commonjs/utils/useUpdateOnHMR.d.ts.map +1 -0
  101. package/build/typescript/commonjs/widgets/server-credentials.d.ts.map +1 -0
  102. package/build/typescript/commonjs/widgets/widget-api.d.ts.map +1 -0
  103. package/build/typescript/module/VoltraModule.d.ts +3 -0
  104. package/build/typescript/module/VoltraModule.d.ts.map +1 -0
  105. package/build/typescript/module/components/VoltraLiveActivityPreview.d.ts +7 -0
  106. package/build/typescript/module/components/VoltraLiveActivityPreview.d.ts.map +1 -0
  107. package/build/typescript/module/components/VoltraView.d.ts +12 -0
  108. package/build/typescript/module/components/VoltraView.d.ts.map +1 -0
  109. package/build/typescript/module/components/VoltraWidgetPreview.d.ts +9 -0
  110. package/build/typescript/module/components/VoltraWidgetPreview.d.ts.map +1 -0
  111. package/build/typescript/module/events.d.ts +33 -0
  112. package/build/typescript/module/events.d.ts.map +1 -0
  113. package/build/typescript/module/helpers.d.ts +3 -0
  114. package/build/typescript/module/helpers.d.ts.map +1 -0
  115. package/build/typescript/module/index.d.ts +18 -0
  116. package/build/typescript/module/index.d.ts.map +1 -0
  117. package/build/typescript/module/live-activity/api.d.ts +35 -0
  118. package/build/typescript/module/live-activity/api.d.ts.map +1 -0
  119. package/build/typescript/module/logger.d.ts +16 -0
  120. package/build/typescript/module/logger.d.ts.map +1 -0
  121. package/build/typescript/module/native/NativeVoltra.d.ts +100 -0
  122. package/build/typescript/module/native/NativeVoltra.d.ts.map +1 -0
  123. package/build/typescript/module/native/VoltraRNNativeComponent.d.ts +8 -0
  124. package/build/typescript/module/native/VoltraRNNativeComponent.d.ts.map +1 -0
  125. package/build/typescript/module/package.json +1 -0
  126. package/build/typescript/module/preload.d.ts +6 -0
  127. package/build/typescript/module/preload.d.ts.map +1 -0
  128. package/build/typescript/module/types.d.ts +2 -0
  129. package/build/typescript/module/types.d.ts.map +1 -0
  130. package/build/typescript/module/utils/assertRunningOnApple.d.ts +2 -0
  131. package/build/typescript/module/utils/assertRunningOnApple.d.ts.map +1 -0
  132. package/build/{esm/utils/helpers.js → typescript/module/utils/helpers.d.ts} +1 -1
  133. package/build/typescript/module/utils/helpers.d.ts.map +1 -0
  134. package/build/{esm/utils/index.js → typescript/module/utils/index.d.ts} +1 -1
  135. package/build/typescript/module/utils/index.d.ts.map +1 -0
  136. package/build/typescript/module/utils/useUpdateOnHMR.d.ts +5 -0
  137. package/build/typescript/module/utils/useUpdateOnHMR.d.ts.map +1 -0
  138. package/build/typescript/module/widgets/server-credentials.d.ts +5 -0
  139. package/build/typescript/module/widgets/server-credentials.d.ts.map +1 -0
  140. package/build/typescript/module/widgets/widget-api.d.ts +11 -0
  141. package/build/typescript/module/widgets/widget-api.d.ts.map +1 -0
  142. package/expo-plugin/app.plugin.js +3 -0
  143. package/expo-plugin/build/cjs/constants.js +23 -0
  144. package/expo-plugin/build/cjs/constants.js.map +1 -0
  145. package/expo-plugin/build/cjs/index.js +51 -0
  146. package/expo-plugin/build/cjs/index.js.map +1 -0
  147. package/expo-plugin/build/cjs/ios/eas.js +28 -0
  148. package/expo-plugin/build/cjs/ios/eas.js.map +1 -0
  149. package/expo-plugin/build/cjs/ios/entitlements.js +46 -0
  150. package/expo-plugin/build/cjs/ios/entitlements.js.map +1 -0
  151. package/expo-plugin/build/cjs/ios/index.js +39 -0
  152. package/expo-plugin/build/cjs/ios/index.js.map +1 -0
  153. package/expo-plugin/build/cjs/ios/infoPlist.js +51 -0
  154. package/expo-plugin/build/cjs/ios/infoPlist.js.map +1 -0
  155. package/expo-plugin/build/cjs/ios/pushNotifications.js +22 -0
  156. package/expo-plugin/build/cjs/ios/pushNotifications.js.map +1 -0
  157. package/expo-plugin/build/cjs/ios-widget/eas.js +66 -0
  158. package/expo-plugin/build/cjs/ios-widget/eas.js.map +1 -0
  159. package/expo-plugin/build/cjs/ios-widget/files/assets.js +199 -0
  160. package/expo-plugin/build/cjs/ios-widget/files/assets.js.map +1 -0
  161. package/expo-plugin/build/cjs/ios-widget/files/entitlements.js +77 -0
  162. package/expo-plugin/build/cjs/ios-widget/files/entitlements.js.map +1 -0
  163. package/expo-plugin/build/cjs/ios-widget/files/index.js +92 -0
  164. package/expo-plugin/build/cjs/ios-widget/files/index.js.map +1 -0
  165. package/expo-plugin/build/cjs/ios-widget/files/infoPlist.js +91 -0
  166. package/expo-plugin/build/cjs/ios-widget/files/infoPlist.js.map +1 -0
  167. package/expo-plugin/build/cjs/ios-widget/files/swift.js +443 -0
  168. package/expo-plugin/build/cjs/ios-widget/files/swift.js.map +1 -0
  169. package/expo-plugin/build/cjs/ios-widget/fonts.js +151 -0
  170. package/expo-plugin/build/cjs/ios-widget/fonts.js.map +1 -0
  171. package/expo-plugin/build/cjs/ios-widget/index.js +46 -0
  172. package/expo-plugin/build/cjs/ios-widget/index.js.map +1 -0
  173. package/expo-plugin/build/cjs/ios-widget/podfile.js +41 -0
  174. package/expo-plugin/build/cjs/ios-widget/podfile.js.map +1 -0
  175. package/expo-plugin/build/cjs/ios-widget/widgetPlist.js +99 -0
  176. package/expo-plugin/build/cjs/ios-widget/widgetPlist.js.map +1 -0
  177. package/expo-plugin/build/cjs/ios-widget/xcode/buildPhases.js +247 -0
  178. package/expo-plugin/build/cjs/ios-widget/xcode/buildPhases.js.map +1 -0
  179. package/expo-plugin/build/cjs/ios-widget/xcode/configurationList.js +91 -0
  180. package/expo-plugin/build/cjs/ios-widget/xcode/configurationList.js.map +1 -0
  181. package/expo-plugin/build/cjs/ios-widget/xcode/groups.js +79 -0
  182. package/expo-plugin/build/cjs/ios-widget/xcode/groups.js.map +1 -0
  183. package/expo-plugin/build/cjs/ios-widget/xcode/index.js +155 -0
  184. package/expo-plugin/build/cjs/ios-widget/xcode/index.js.map +1 -0
  185. package/expo-plugin/build/cjs/ios-widget/xcode/mainAppSettings.js +71 -0
  186. package/expo-plugin/build/cjs/ios-widget/xcode/mainAppSettings.js.map +1 -0
  187. package/expo-plugin/build/cjs/ios-widget/xcode/productFile.js +74 -0
  188. package/expo-plugin/build/cjs/ios-widget/xcode/productFile.js.map +1 -0
  189. package/expo-plugin/build/cjs/ios-widget/xcode/target.js +113 -0
  190. package/expo-plugin/build/cjs/ios-widget/xcode/target.js.map +1 -0
  191. package/expo-plugin/build/cjs/utils/fileDiscovery.js +120 -0
  192. package/expo-plugin/build/cjs/utils/fileDiscovery.js.map +1 -0
  193. package/expo-plugin/build/cjs/utils/urlScheme.js +40 -0
  194. package/expo-plugin/build/cjs/utils/urlScheme.js.map +1 -0
  195. package/expo-plugin/build/cjs/validation.js +55 -0
  196. package/expo-plugin/build/cjs/validation.js.map +1 -0
  197. package/expo-plugin/build/esm/constants.js +20 -0
  198. package/expo-plugin/build/esm/constants.js.map +1 -0
  199. package/expo-plugin/build/esm/index.js +49 -0
  200. package/expo-plugin/build/esm/index.js.map +1 -0
  201. package/expo-plugin/build/esm/ios/eas.js +24 -0
  202. package/expo-plugin/build/esm/ios/eas.js.map +1 -0
  203. package/expo-plugin/build/esm/ios/entitlements.js +42 -0
  204. package/expo-plugin/build/esm/ios/entitlements.js.map +1 -0
  205. package/expo-plugin/build/esm/ios/index.js +34 -0
  206. package/expo-plugin/build/esm/ios/index.js.map +1 -0
  207. package/expo-plugin/build/esm/ios/infoPlist.js +47 -0
  208. package/expo-plugin/build/esm/ios/infoPlist.js.map +1 -0
  209. package/expo-plugin/build/esm/ios/pushNotifications.js +18 -0
  210. package/expo-plugin/build/esm/ios/pushNotifications.js.map +1 -0
  211. package/expo-plugin/build/esm/ios-widget/eas.js +62 -0
  212. package/expo-plugin/build/esm/ios-widget/eas.js.map +1 -0
  213. package/expo-plugin/build/esm/ios-widget/files/assets.js +163 -0
  214. package/expo-plugin/build/esm/ios-widget/files/assets.js.map +1 -0
  215. package/expo-plugin/build/esm/ios-widget/files/entitlements.js +37 -0
  216. package/expo-plugin/build/esm/ios-widget/files/entitlements.js.map +1 -0
  217. package/expo-plugin/build/esm/ios-widget/files/index.js +55 -0
  218. package/expo-plugin/build/esm/ios-widget/files/index.js.map +1 -0
  219. package/expo-plugin/build/esm/ios-widget/files/infoPlist.js +55 -0
  220. package/expo-plugin/build/esm/ios-widget/files/infoPlist.js.map +1 -0
  221. package/expo-plugin/build/esm/ios-widget/files/swift.js +403 -0
  222. package/expo-plugin/build/esm/ios-widget/files/swift.js.map +1 -0
  223. package/expo-plugin/build/esm/ios-widget/fonts.js +111 -0
  224. package/expo-plugin/build/esm/ios-widget/fonts.js.map +1 -0
  225. package/expo-plugin/build/esm/ios-widget/index.js +42 -0
  226. package/expo-plugin/build/esm/ios-widget/index.js.map +1 -0
  227. package/expo-plugin/build/esm/ios-widget/podfile.js +37 -0
  228. package/expo-plugin/build/esm/ios-widget/podfile.js.map +1 -0
  229. package/expo-plugin/build/esm/ios-widget/widgetPlist.js +92 -0
  230. package/expo-plugin/build/esm/ios-widget/widgetPlist.js.map +1 -0
  231. package/expo-plugin/build/esm/ios-widget/xcode/buildPhases.js +210 -0
  232. package/expo-plugin/build/esm/ios-widget/xcode/buildPhases.js.map +1 -0
  233. package/expo-plugin/build/esm/ios-widget/xcode/configurationList.js +87 -0
  234. package/expo-plugin/build/esm/ios-widget/xcode/configurationList.js.map +1 -0
  235. package/expo-plugin/build/esm/ios-widget/xcode/groups.js +75 -0
  236. package/expo-plugin/build/esm/ios-widget/xcode/groups.js.map +1 -0
  237. package/expo-plugin/build/esm/ios-widget/xcode/index.js +118 -0
  238. package/expo-plugin/build/esm/ios-widget/xcode/index.js.map +1 -0
  239. package/expo-plugin/build/esm/ios-widget/xcode/mainAppSettings.js +68 -0
  240. package/expo-plugin/build/esm/ios-widget/xcode/mainAppSettings.js.map +1 -0
  241. package/expo-plugin/build/esm/ios-widget/xcode/productFile.js +70 -0
  242. package/expo-plugin/build/esm/ios-widget/xcode/productFile.js.map +1 -0
  243. package/expo-plugin/build/esm/ios-widget/xcode/target.js +108 -0
  244. package/expo-plugin/build/esm/ios-widget/xcode/target.js.map +1 -0
  245. package/expo-plugin/build/esm/utils/fileDiscovery.js +83 -0
  246. package/expo-plugin/build/esm/utils/fileDiscovery.js.map +1 -0
  247. package/expo-plugin/build/esm/utils/urlScheme.js +37 -0
  248. package/expo-plugin/build/esm/utils/urlScheme.js.map +1 -0
  249. package/expo-plugin/build/esm/validation.js +51 -0
  250. package/expo-plugin/build/esm/validation.js.map +1 -0
  251. package/expo-plugin/build/types/constants.d.ts +13 -0
  252. package/expo-plugin/build/types/constants.d.ts.map +1 -0
  253. package/expo-plugin/build/types/index.d.ts +10 -0
  254. package/expo-plugin/build/types/index.d.ts.map +1 -0
  255. package/expo-plugin/build/types/ios/eas.d.ts +12 -0
  256. package/expo-plugin/build/types/ios/eas.d.ts.map +1 -0
  257. package/expo-plugin/build/types/ios/entitlements.d.ts +14 -0
  258. package/expo-plugin/build/types/ios/entitlements.d.ts.map +1 -0
  259. package/expo-plugin/build/types/ios/index.d.ts +19 -0
  260. package/expo-plugin/build/types/ios/index.d.ts.map +1 -0
  261. package/expo-plugin/build/types/ios/infoPlist.d.ts +21 -0
  262. package/expo-plugin/build/types/ios/infoPlist.d.ts.map +1 -0
  263. package/expo-plugin/build/types/ios/pushNotifications.d.ts +10 -0
  264. package/expo-plugin/build/types/ios/pushNotifications.d.ts.map +1 -0
  265. package/expo-plugin/build/types/ios-widget/eas.d.ts +15 -0
  266. package/expo-plugin/build/types/ios-widget/eas.d.ts.map +1 -0
  267. package/expo-plugin/build/types/ios-widget/files/assets.d.ts +13 -0
  268. package/expo-plugin/build/types/ios-widget/files/assets.d.ts.map +1 -0
  269. package/expo-plugin/build/types/ios-widget/files/entitlements.d.ts +17 -0
  270. package/expo-plugin/build/types/ios-widget/files/entitlements.d.ts.map +1 -0
  271. package/expo-plugin/build/types/ios-widget/files/index.d.ts +24 -0
  272. package/expo-plugin/build/types/ios-widget/files/index.d.ts.map +1 -0
  273. package/expo-plugin/build/types/ios-widget/files/infoPlist.d.ts +10 -0
  274. package/expo-plugin/build/types/ios-widget/files/infoPlist.d.ts.map +1 -0
  275. package/expo-plugin/build/types/ios-widget/files/swift.d.ts +24 -0
  276. package/expo-plugin/build/types/ios-widget/files/swift.d.ts.map +1 -0
  277. package/expo-plugin/build/types/ios-widget/fonts.d.ts +22 -0
  278. package/expo-plugin/build/types/ios-widget/fonts.d.ts.map +1 -0
  279. package/expo-plugin/build/types/ios-widget/index.d.ts +31 -0
  280. package/expo-plugin/build/types/ios-widget/index.d.ts.map +1 -0
  281. package/expo-plugin/build/types/ios-widget/podfile.d.ts +9 -0
  282. package/expo-plugin/build/types/ios-widget/podfile.d.ts.map +1 -0
  283. package/expo-plugin/build/types/ios-widget/widgetPlist.d.ts +20 -0
  284. package/expo-plugin/build/types/ios-widget/widgetPlist.d.ts.map +1 -0
  285. package/expo-plugin/build/types/ios-widget/xcode/buildPhases.d.ts +25 -0
  286. package/expo-plugin/build/types/ios-widget/xcode/buildPhases.d.ts.map +1 -0
  287. package/expo-plugin/build/types/ios-widget/xcode/configurationList.d.ts +20 -0
  288. package/expo-plugin/build/types/ios-widget/xcode/configurationList.d.ts.map +1 -0
  289. package/expo-plugin/build/types/ios-widget/xcode/groups.d.ts +15 -0
  290. package/expo-plugin/build/types/ios-widget/xcode/groups.d.ts.map +1 -0
  291. package/expo-plugin/build/types/ios-widget/xcode/index.d.ts +20 -0
  292. package/expo-plugin/build/types/ios-widget/xcode/index.d.ts.map +1 -0
  293. package/expo-plugin/build/types/ios-widget/xcode/mainAppSettings.d.ts +15 -0
  294. package/expo-plugin/build/types/ios-widget/xcode/mainAppSettings.d.ts.map +1 -0
  295. package/expo-plugin/build/types/ios-widget/xcode/productFile.d.ts +14 -0
  296. package/expo-plugin/build/types/ios-widget/xcode/productFile.d.ts.map +1 -0
  297. package/expo-plugin/build/types/ios-widget/xcode/target.d.ts +42 -0
  298. package/expo-plugin/build/types/ios-widget/xcode/target.d.ts.map +1 -0
  299. package/expo-plugin/build/types/types.d.ts +74 -0
  300. package/expo-plugin/build/types/types.d.ts.map +1 -0
  301. package/expo-plugin/build/types/utils/fileDiscovery.d.ts +15 -0
  302. package/expo-plugin/build/types/utils/fileDiscovery.d.ts.map +1 -0
  303. package/expo-plugin/build/types/utils/urlScheme.d.ts +10 -0
  304. package/expo-plugin/build/types/utils/urlScheme.d.ts.map +1 -0
  305. package/expo-plugin/build/types/validation.d.ts +4 -0
  306. package/expo-plugin/build/types/validation.d.ts.map +1 -0
  307. package/expo-plugin/jest.config.js +18 -0
  308. package/expo-plugin/src/constants.ts +25 -0
  309. package/expo-plugin/src/index.ts +72 -0
  310. package/expo-plugin/src/ios/eas.ts +33 -0
  311. package/expo-plugin/src/ios/entitlements.ts +59 -0
  312. package/expo-plugin/src/ios/index.ts +47 -0
  313. package/expo-plugin/src/ios/infoPlist.ts +63 -0
  314. package/expo-plugin/src/ios/pushNotifications.ts +22 -0
  315. package/expo-plugin/src/ios-widget/eas.ts +79 -0
  316. package/expo-plugin/src/ios-widget/files/assets.ts +201 -0
  317. package/expo-plugin/src/ios-widget/files/entitlements.ts +48 -0
  318. package/expo-plugin/src/ios-widget/files/index.ts +74 -0
  319. package/expo-plugin/src/ios-widget/files/infoPlist.ts +57 -0
  320. package/expo-plugin/src/ios-widget/files/swift.node.test.ts +22 -0
  321. package/expo-plugin/src/ios-widget/files/swift.ts +476 -0
  322. package/expo-plugin/src/ios-widget/fonts.ts +132 -0
  323. package/expo-plugin/src/ios-widget/index.ts +73 -0
  324. package/expo-plugin/src/ios-widget/podfile.ts +44 -0
  325. package/expo-plugin/src/ios-widget/widgetPlist.ts +115 -0
  326. package/expo-plugin/src/ios-widget/xcode/buildPhases.ts +301 -0
  327. package/expo-plugin/src/ios-widget/xcode/configurationList.ts +127 -0
  328. package/expo-plugin/src/ios-widget/xcode/groups.ts +101 -0
  329. package/expo-plugin/src/ios-widget/xcode/index.ts +149 -0
  330. package/expo-plugin/src/ios-widget/xcode/mainAppSettings.ts +95 -0
  331. package/expo-plugin/src/ios-widget/xcode/productFile.ts +91 -0
  332. package/expo-plugin/src/ios-widget/xcode/target.ts +148 -0
  333. package/expo-plugin/src/types.ts +89 -0
  334. package/expo-plugin/src/utils/fileDiscovery.ts +96 -0
  335. package/expo-plugin/src/utils/urlScheme.ts +45 -0
  336. package/expo-plugin/src/validation.node.test.ts +19 -0
  337. package/expo-plugin/src/validation.ts +63 -0
  338. package/expo-plugin/tsconfig.base.json +17 -0
  339. package/expo-plugin/tsconfig.cjs.json +9 -0
  340. package/expo-plugin/tsconfig.esm.json +9 -0
  341. package/expo-plugin/tsconfig.jest.json +8 -0
  342. package/expo-plugin/tsconfig.typecheck.json +12 -0
  343. package/expo-plugin/tsconfig.types.json +10 -0
  344. package/ios/Package.swift +68 -0
  345. package/ios/Tests/JSGradientParserTests.swift +201 -0
  346. package/ios/Tests/VoltraSharedTests/SmokeTests.swift +8 -0
  347. package/ios/VoltraWidget.podspec +30 -0
  348. package/ios/app/NativeVoltra.h +5 -0
  349. package/ios/app/NativeVoltra.mm +211 -0
  350. package/ios/app/VoltraActivity.swift +5 -0
  351. package/ios/app/VoltraImagePreload.swift +154 -0
  352. package/ios/app/VoltraLiveActivityManager.swift +228 -0
  353. package/ios/app/VoltraLiveActivityService.swift +306 -0
  354. package/ios/app/VoltraModule.swift +215 -0
  355. package/ios/app/VoltraModuleImpl.swift +331 -0
  356. package/ios/app/VoltraOptions.swift +27 -0
  357. package/ios/app/VoltraViewComponentView.h +10 -0
  358. package/ios/app/VoltraViewComponentView.mm +67 -0
  359. package/ios/app/VoltraViewRoot.swift +63 -0
  360. package/ios/app/VoltraWidgetService.swift +154 -0
  361. package/ios/shared/BrotliCompression.swift +81 -0
  362. package/ios/shared/ComponentTypeID.swift +117 -0
  363. package/ios/shared/Data+hexString.swift +8 -0
  364. package/ios/shared/Date+toTimerInterval.swift +25 -0
  365. package/ios/shared/JSONValue.swift +128 -0
  366. package/ios/shared/ShortNames.swift +180 -0
  367. package/ios/shared/VoltraAttributes.swift +58 -0
  368. package/ios/shared/VoltraConfig.swift +18 -0
  369. package/ios/shared/VoltraConstants.swift +45 -0
  370. package/ios/shared/VoltraElement.swift +153 -0
  371. package/ios/shared/VoltraEvent.swift +72 -0
  372. package/ios/shared/VoltraEventBus.swift +80 -0
  373. package/ios/shared/VoltraImageStore.swift +119 -0
  374. package/ios/shared/VoltraInitialStateLocale.swift +54 -0
  375. package/ios/shared/VoltraInteractionIntent.swift +39 -0
  376. package/ios/shared/VoltraKeychainHelper.swift +178 -0
  377. package/ios/shared/VoltraLiveActivityPayload.swift +113 -0
  378. package/ios/shared/VoltraLogger.swift +30 -0
  379. package/ios/shared/VoltraNode.swift +194 -0
  380. package/ios/shared/VoltraPayloadMigrator.swift +63 -0
  381. package/ios/shared/VoltraPersistentEventQueue.swift +67 -0
  382. package/ios/shared/VoltraRefreshIntent.swift +29 -0
  383. package/ios/shared/VoltraRegion.swift +37 -0
  384. package/ios/shared/VoltraWidgetDefaults.swift +114 -0
  385. package/ios/shared/VoltraWidgetServerFetcher.swift +166 -0
  386. package/ios/target/VoltraHomeWidget.swift +508 -0
  387. package/ios/target/VoltraWidget.swift +158 -0
  388. package/ios/ui/Extensions/View.modifiers.swift +28 -0
  389. package/ios/ui/Extensions/VoltraNode+Parameters.swift +18 -0
  390. package/ios/ui/Generated/Parameters/.generated +8 -0
  391. package/ios/ui/Generated/Parameters/ButtonParameters.swift +15 -0
  392. package/ios/ui/Generated/Parameters/ChartParameters.swift +33 -0
  393. package/ios/ui/Generated/Parameters/CircularProgressViewParameters.swift +59 -0
  394. package/ios/ui/Generated/Parameters/ComponentParameters.swift +12 -0
  395. package/ios/ui/Generated/Parameters/DividerParameters.swift +12 -0
  396. package/ios/ui/Generated/Parameters/GaugeParameters.swift +54 -0
  397. package/ios/ui/Generated/Parameters/GlassContainerParameters.swift +15 -0
  398. package/ios/ui/Generated/Parameters/GroupBoxParameters.swift +12 -0
  399. package/ios/ui/Generated/Parameters/HStackParameters.swift +34 -0
  400. package/ios/ui/Generated/Parameters/ImageParameters.swift +29 -0
  401. package/ios/ui/Generated/Parameters/LabelParameters.swift +18 -0
  402. package/ios/ui/Generated/Parameters/LinearGradientParameters.swift +27 -0
  403. package/ios/ui/Generated/Parameters/LinearProgressViewParameters.swift +64 -0
  404. package/ios/ui/Generated/Parameters/LinkParameters.swift +15 -0
  405. package/ios/ui/Generated/Parameters/MaskParameters.swift +12 -0
  406. package/ios/ui/Generated/Parameters/SpacerParameters.swift +15 -0
  407. package/ios/ui/Generated/Parameters/SymbolParameters.swift +59 -0
  408. package/ios/ui/Generated/Parameters/TextParameters.swift +18 -0
  409. package/ios/ui/Generated/Parameters/TimerParameters.swift +54 -0
  410. package/ios/ui/Generated/Parameters/ToggleParameters.swift +24 -0
  411. package/ios/ui/Generated/Parameters/VStackParameters.swift +34 -0
  412. package/ios/ui/Generated/Parameters/ViewParameters.swift +12 -0
  413. package/ios/ui/Generated/Parameters/ZStackParameters.swift +15 -0
  414. package/ios/ui/Helpers/VoltraDeepLinkResolver.swift +43 -0
  415. package/ios/ui/Helpers/VoltraProgressDriver.swift +52 -0
  416. package/ios/ui/Layout/FlexContainerHelper.swift +114 -0
  417. package/ios/ui/Layout/VoltraFlexStackLayout.swift +417 -0
  418. package/ios/ui/Protocols/VoltraView.swift +29 -0
  419. package/ios/ui/Style/BackgroundValue.swift +27 -0
  420. package/ios/ui/Style/CompositeStyle.swift +81 -0
  421. package/ios/ui/Style/DecorationStyle.swift +207 -0
  422. package/ios/ui/Style/FlexEnvironment.swift +35 -0
  423. package/ios/ui/Style/FontVariant.swift +4 -0
  424. package/ios/ui/Style/GlassEffect.swift +6 -0
  425. package/ios/ui/Style/JSColorParser.swift +517 -0
  426. package/ios/ui/Style/JSGradientParser.swift +674 -0
  427. package/ios/ui/Style/JSStyleParser.swift +223 -0
  428. package/ios/ui/Style/LayoutStyle.swift +184 -0
  429. package/ios/ui/Style/Overflow.swift +4 -0
  430. package/ios/ui/Style/RenderingStyle.swift +33 -0
  431. package/ios/ui/Style/StyleConverter.swift +202 -0
  432. package/ios/ui/Style/TextDecoration.swift +6 -0
  433. package/ios/ui/Style/TextStyle.swift +50 -0
  434. package/ios/ui/Style/View+applyStyle.swift +38 -0
  435. package/ios/ui/Views/VoltraButton.swift +57 -0
  436. package/ios/ui/Views/VoltraChart.swift +840 -0
  437. package/ios/ui/Views/VoltraCircularProgressView.swift +103 -0
  438. package/ios/ui/Views/VoltraDivider.swift +16 -0
  439. package/ios/ui/Views/VoltraFlexView.swift +33 -0
  440. package/ios/ui/Views/VoltraGauge.swift +65 -0
  441. package/ios/ui/Views/VoltraGlassContainer.swift +29 -0
  442. package/ios/ui/Views/VoltraGroupBox.swift +26 -0
  443. package/ios/ui/Views/VoltraHStack.swift +70 -0
  444. package/ios/ui/Views/VoltraImage.swift +109 -0
  445. package/ios/ui/Views/VoltraLabel.swift +24 -0
  446. package/ios/ui/Views/VoltraLinearGradient.swift +115 -0
  447. package/ios/ui/Views/VoltraLinearProgressView.swift +118 -0
  448. package/ios/ui/Views/VoltraLink.swift +25 -0
  449. package/ios/ui/Views/VoltraMask.swift +23 -0
  450. package/ios/ui/Views/VoltraSpacer.swift +16 -0
  451. package/ios/ui/Views/VoltraSymbol.swift +160 -0
  452. package/ios/ui/Views/VoltraText.swift +87 -0
  453. package/ios/ui/Views/VoltraTimer.swift +131 -0
  454. package/ios/ui/Views/VoltraToggle.swift +39 -0
  455. package/ios/ui/Views/VoltraVStack.swift +68 -0
  456. package/ios/ui/Views/VoltraZStack.swift +33 -0
  457. package/ios/ui/Voltra.swift +86 -0
  458. package/package.json +91 -18
  459. package/build/cjs/VoltraModule.js +0 -6
  460. package/build/cjs/VoltraModule.js.map +0 -1
  461. package/build/cjs/components/VoltraLiveActivityPreview.js +0 -20
  462. package/build/cjs/components/VoltraLiveActivityPreview.js.map +0 -1
  463. package/build/cjs/components/VoltraView.js +0 -37
  464. package/build/cjs/components/VoltraView.js.map +0 -1
  465. package/build/cjs/components/VoltraWidgetPreview.js +0 -26
  466. package/build/cjs/components/VoltraWidgetPreview.js.map +0 -1
  467. package/build/cjs/events.js +0 -19
  468. package/build/cjs/events.js.map +0 -1
  469. package/build/cjs/helpers.js +0 -30
  470. package/build/cjs/helpers.js.map +0 -1
  471. package/build/cjs/index.js +0 -49
  472. package/build/cjs/index.js.map +0 -1
  473. package/build/cjs/live-activity/api.js +0 -158
  474. package/build/cjs/live-activity/api.js.map +0 -1
  475. package/build/cjs/logger.js +0 -36
  476. package/build/cjs/logger.js.map +0 -1
  477. package/build/cjs/preload.js +0 -54
  478. package/build/cjs/preload.js.map +0 -1
  479. package/build/cjs/utils/assertRunningOnApple.js +0 -13
  480. package/build/cjs/utils/assertRunningOnApple.js.map +0 -1
  481. package/build/cjs/utils/helpers.js +0 -7
  482. package/build/cjs/utils/helpers.js.map +0 -1
  483. package/build/cjs/utils/index.js +0 -19
  484. package/build/cjs/utils/index.js.map +0 -1
  485. package/build/cjs/utils/useUpdateOnHMR.js +0 -22
  486. package/build/cjs/utils/useUpdateOnHMR.js.map +0 -1
  487. package/build/cjs/widgets/server-credentials.js +0 -18
  488. package/build/cjs/widgets/server-credentials.js.map +0 -1
  489. package/build/cjs/widgets/widget-api.js +0 -59
  490. package/build/cjs/widgets/widget-api.js.map +0 -1
  491. package/build/esm/VoltraModule.js +0 -4
  492. package/build/esm/VoltraModule.js.map +0 -1
  493. package/build/esm/components/VoltraLiveActivityPreview.js +0 -17
  494. package/build/esm/components/VoltraLiveActivityPreview.js.map +0 -1
  495. package/build/esm/components/VoltraView.js +0 -34
  496. package/build/esm/components/VoltraView.js.map +0 -1
  497. package/build/esm/components/VoltraWidgetPreview.js +0 -23
  498. package/build/esm/components/VoltraWidgetPreview.js.map +0 -1
  499. package/build/esm/events.js +0 -13
  500. package/build/esm/events.js.map +0 -1
  501. package/build/esm/helpers.js +0 -23
  502. package/build/esm/helpers.js.map +0 -1
  503. package/build/esm/index.js +0 -10
  504. package/build/esm/index.js.map +0 -1
  505. package/build/esm/live-activity/api.js +0 -146
  506. package/build/esm/live-activity/api.js.map +0 -1
  507. package/build/esm/logger.js +0 -33
  508. package/build/esm/logger.js.map +0 -1
  509. package/build/esm/preload.js +0 -46
  510. package/build/esm/preload.js.map +0 -1
  511. package/build/esm/utils/assertRunningOnApple.js +0 -9
  512. package/build/esm/utils/assertRunningOnApple.js.map +0 -1
  513. package/build/esm/utils/helpers.js.map +0 -1
  514. package/build/esm/utils/index.js.map +0 -1
  515. package/build/esm/utils/useUpdateOnHMR.js +0 -18
  516. package/build/esm/utils/useUpdateOnHMR.js.map +0 -1
  517. package/build/esm/widgets/server-credentials.js +0 -11
  518. package/build/esm/widgets/server-credentials.js.map +0 -1
  519. package/build/esm/widgets/widget-api.js +0 -47
  520. package/build/esm/widgets/widget-api.js.map +0 -1
  521. package/build/types/VoltraModule.d.ts +0 -44
  522. package/build/types/VoltraModule.d.ts.map +0 -1
  523. package/build/types/components/VoltraLiveActivityPreview.d.ts.map +0 -1
  524. package/build/types/components/VoltraView.d.ts.map +0 -1
  525. package/build/types/components/VoltraWidgetPreview.d.ts.map +0 -1
  526. package/build/types/events.d.ts.map +0 -1
  527. package/build/types/helpers.d.ts.map +0 -1
  528. package/build/types/index.d.ts.map +0 -1
  529. package/build/types/live-activity/api.d.ts.map +0 -1
  530. package/build/types/logger.d.ts.map +0 -1
  531. package/build/types/preload.d.ts.map +0 -1
  532. package/build/types/types.d.ts.map +0 -1
  533. package/build/types/utils/assertRunningOnApple.d.ts.map +0 -1
  534. package/build/types/utils/helpers.d.ts.map +0 -1
  535. package/build/types/utils/index.d.ts.map +0 -1
  536. package/build/types/utils/useUpdateOnHMR.d.ts.map +0 -1
  537. package/build/types/widgets/server-credentials.d.ts.map +0 -1
  538. package/build/types/widgets/widget-api.d.ts.map +0 -1
  539. /package/build/{types → typescript/commonjs}/components/VoltraLiveActivityPreview.d.ts +0 -0
  540. /package/build/{types → typescript/commonjs}/components/VoltraView.d.ts +0 -0
  541. /package/build/{types → typescript/commonjs}/components/VoltraWidgetPreview.d.ts +0 -0
  542. /package/build/{types → typescript/commonjs}/events.d.ts +0 -0
  543. /package/build/{types → typescript/commonjs}/helpers.d.ts +0 -0
  544. /package/build/{types → typescript/commonjs}/live-activity/api.d.ts +0 -0
  545. /package/build/{types → typescript/commonjs}/logger.d.ts +0 -0
  546. /package/build/{types → typescript/commonjs}/preload.d.ts +0 -0
  547. /package/build/{types → typescript/commonjs}/types.d.ts +0 -0
  548. /package/build/{types → typescript/commonjs}/utils/assertRunningOnApple.d.ts +0 -0
  549. /package/build/{types → typescript/commonjs}/utils/helpers.d.ts +0 -0
  550. /package/build/{types → typescript/commonjs}/utils/index.d.ts +0 -0
  551. /package/build/{types → typescript/commonjs}/utils/useUpdateOnHMR.d.ts +0 -0
  552. /package/build/{types → typescript/commonjs}/widgets/server-credentials.d.ts +0 -0
  553. /package/build/{types → typescript/commonjs}/widgets/widget-api.d.ts +0 -0
  554. /package/{build → expo-plugin/build}/cjs/package.json +0 -0
  555. /package/{build → expo-plugin/build}/cjs/types.js +0 -0
  556. /package/{build → expo-plugin/build}/cjs/types.js.map +0 -0
  557. /package/{build → expo-plugin/build}/esm/package.json +0 -0
  558. /package/{build → expo-plugin/build}/esm/types.js +0 -0
  559. /package/{build → expo-plugin/build}/esm/types.js.map +0 -0
@@ -0,0 +1,674 @@
1
+ import Foundation
2
+ import SwiftUI
3
+
4
+ enum JSGradientParser {
5
+ private enum CacheEntry {
6
+ case success(BackgroundValue)
7
+ case failure
8
+ }
9
+
10
+ private enum GradientKind {
11
+ case linear
12
+ case radial
13
+ case conic
14
+ }
15
+
16
+ private struct ColorStopToken {
17
+ var color: Color
18
+ var firstPosition: Double?
19
+ var secondPosition: Double?
20
+ }
21
+
22
+ private struct LinearSpec {
23
+ var startPoint: UnitPoint
24
+ var endPoint: UnitPoint
25
+ var stops: [Gradient.Stop]
26
+ }
27
+
28
+ private struct RadialSpec {
29
+ var center: UnitPoint
30
+ var shape: RadialGradientShape
31
+ var extent: RadialGradientExtent
32
+ var stops: [Gradient.Stop]
33
+ }
34
+
35
+ private struct ConicSpec {
36
+ var center: UnitPoint
37
+ var angle: Angle
38
+ var stops: [Gradient.Stop]
39
+ }
40
+
41
+ private static let cacheLimit = 256
42
+ private static var cache: [String: CacheEntry] = [:]
43
+ private static var cacheOrder: [String] = []
44
+ private static let cacheLock = NSLock()
45
+
46
+ static func parse(_ input: String) -> BackgroundValue? {
47
+ let raw = input.trimmingCharacters(in: .whitespacesAndNewlines)
48
+ guard !raw.isEmpty else { return nil }
49
+ let key = raw.lowercased()
50
+
51
+ if let cached = cacheValue(for: key) {
52
+ switch cached {
53
+ case let .success(value):
54
+ return value
55
+ case .failure:
56
+ return nil
57
+ }
58
+ }
59
+
60
+ let result = parseUncached(raw)
61
+ setCacheValue(result.map(CacheEntry.success) ?? .failure, for: key)
62
+ return result
63
+ }
64
+
65
+ private static func parseUncached(_ raw: String) -> BackgroundValue? {
66
+ let lower = raw.lowercased()
67
+ if lower.hasPrefix("repeating-linear-gradient(") || lower.hasPrefix("repeating-radial-gradient(") || lower.hasPrefix("repeating-conic-gradient(") {
68
+ return nil
69
+ }
70
+ if lower.hasPrefix("linear-gradient(") {
71
+ return parseLinear(raw)
72
+ }
73
+ if lower.hasPrefix("radial-gradient(") {
74
+ return parseRadial(raw)
75
+ }
76
+ if lower.hasPrefix("conic-gradient(") {
77
+ return parseConic(raw)
78
+ }
79
+ return nil
80
+ }
81
+
82
+ // MARK: - Top level parsers
83
+
84
+ private static func parseLinear(_ value: String) -> BackgroundValue? {
85
+ guard let content = extractContent(value, prefix: "linear-gradient(") else { return nil }
86
+ let args = splitGradientArgs(content)
87
+ guard args.count >= 2 else { return nil }
88
+
89
+ var startPoint = UnitPoint(x: 0.5, y: 0)
90
+ var endPoint = UnitPoint(x: 0.5, y: 1)
91
+ var stopArgs = args
92
+
93
+ if let first = args.first {
94
+ let trimmed = first.trimmingCharacters(in: .whitespacesAndNewlines)
95
+ if trimmed.lowercased().hasPrefix("to ") {
96
+ guard let points = parseLinearDirection(trimmed) else { return nil }
97
+ startPoint = points.start
98
+ endPoint = points.end
99
+ stopArgs = Array(args.dropFirst())
100
+ } else if let angle = parseAngle(trimmed) {
101
+ let points = angleToPoints(angle)
102
+ startPoint = points.start
103
+ endPoint = points.end
104
+ stopArgs = Array(args.dropFirst())
105
+ }
106
+ }
107
+
108
+ guard let stops = parseStops(stopArgs, kind: .linear), stops.count >= 2 else { return nil }
109
+ let spec = LinearSpec(startPoint: startPoint, endPoint: endPoint, stops: stops)
110
+ return .linearGradient(gradient: Gradient(stops: spec.stops), startPoint: spec.startPoint, endPoint: spec.endPoint)
111
+ }
112
+
113
+ private static func parseRadial(_ value: String) -> BackgroundValue? {
114
+ guard let content = extractContent(value, prefix: "radial-gradient(") else { return nil }
115
+ let args = splitGradientArgs(content)
116
+ guard args.count >= 2 else { return nil }
117
+
118
+ var shape: RadialGradientShape = .ellipse
119
+ var extent: RadialGradientExtent = .farthestCorner
120
+ var center = UnitPoint.center
121
+ var stopArgs = args
122
+
123
+ if let first = args.first, parseColorStop(first, kind: .radial) == nil {
124
+ guard let radialPrelude = parseRadialPrelude(first) else { return nil }
125
+ shape = radialPrelude.shape
126
+ extent = radialPrelude.extent
127
+ center = radialPrelude.center
128
+ stopArgs = Array(args.dropFirst())
129
+ }
130
+
131
+ guard let stops = parseStops(stopArgs, kind: .radial), stops.count >= 2 else { return nil }
132
+ let spec = RadialSpec(center: center, shape: shape, extent: extent, stops: stops)
133
+ return .radialGradient(spec: RadialGradientSpec(
134
+ gradient: Gradient(stops: spec.stops),
135
+ center: spec.center,
136
+ shape: spec.shape,
137
+ extent: spec.extent
138
+ ))
139
+ }
140
+
141
+ private static func parseConic(_ value: String) -> BackgroundValue? {
142
+ guard let content = extractContent(value, prefix: "conic-gradient(") else { return nil }
143
+ let args = splitGradientArgs(content)
144
+ guard args.count >= 2 else { return nil }
145
+
146
+ var center = UnitPoint.center
147
+ var angle = Angle.zero
148
+ var stopArgs = args
149
+
150
+ if let first = args.first, parseColorStop(first, kind: .conic) == nil {
151
+ guard let prelude = parseConicPrelude(first) else { return nil }
152
+ center = prelude.center
153
+ angle = prelude.angle
154
+ stopArgs = Array(args.dropFirst())
155
+ }
156
+
157
+ guard let stops = parseStops(stopArgs, kind: .conic), stops.count >= 2 else { return nil }
158
+ let spec = ConicSpec(center: center, angle: angle, stops: stops)
159
+ return .angularGradient(gradient: Gradient(stops: spec.stops), center: spec.center, angle: spec.angle)
160
+ }
161
+
162
+ // MARK: - Cache
163
+
164
+ private static func cacheValue(for key: String) -> CacheEntry? {
165
+ cacheLock.lock()
166
+ defer { cacheLock.unlock() }
167
+ return cache[key]
168
+ }
169
+
170
+ private static func setCacheValue(_ value: CacheEntry, for key: String) {
171
+ cacheLock.lock()
172
+ defer { cacheLock.unlock() }
173
+
174
+ if cache[key] == nil {
175
+ cacheOrder.append(key)
176
+ if cacheOrder.count > cacheLimit {
177
+ let oldest = cacheOrder.removeFirst()
178
+ cache.removeValue(forKey: oldest)
179
+ }
180
+ }
181
+ cache[key] = value
182
+ }
183
+
184
+ // MARK: - Grammar helpers
185
+
186
+ static func extractContent(_ value: String, prefix: String) -> String? {
187
+ let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines)
188
+ let lower = trimmed.lowercased()
189
+ guard lower.hasPrefix(prefix), trimmed.hasSuffix(")") else { return nil }
190
+ return String(trimmed.dropFirst(prefix.count).dropLast())
191
+ }
192
+
193
+ static func splitGradientArgs(_ content: String) -> [String] {
194
+ var args: [String] = []
195
+ var current = ""
196
+ var depth = 0
197
+
198
+ for char in content {
199
+ if char == "(" {
200
+ depth += 1
201
+ } else if char == ")" {
202
+ depth -= 1
203
+ if depth < 0 { return [] }
204
+ }
205
+
206
+ if char == ",", depth == 0 {
207
+ let token = current.trimmingCharacters(in: .whitespacesAndNewlines)
208
+ if token.isEmpty { return [] }
209
+ args.append(token)
210
+ current = ""
211
+ } else {
212
+ current.append(char)
213
+ }
214
+ }
215
+
216
+ guard depth == 0 else { return [] }
217
+
218
+ let token = current.trimmingCharacters(in: .whitespacesAndNewlines)
219
+ if token.isEmpty { return [] }
220
+ args.append(token)
221
+ return args
222
+ }
223
+
224
+ private static func splitByWhitespaceOutsideParentheses(_ value: String) -> [String] {
225
+ var result: [String] = []
226
+ var current = ""
227
+ var depth = 0
228
+
229
+ for char in value {
230
+ if char == "(" {
231
+ depth += 1
232
+ } else if char == ")" {
233
+ depth -= 1
234
+ if depth < 0 { return [] }
235
+ }
236
+
237
+ if char.isWhitespace, depth == 0 {
238
+ let token = current.trimmingCharacters(in: .whitespacesAndNewlines)
239
+ if !token.isEmpty {
240
+ result.append(token)
241
+ }
242
+ current = ""
243
+ } else {
244
+ current.append(char)
245
+ }
246
+ }
247
+
248
+ guard depth == 0 else { return [] }
249
+
250
+ let tail = current.trimmingCharacters(in: .whitespacesAndNewlines)
251
+ if !tail.isEmpty {
252
+ result.append(tail)
253
+ }
254
+ return result
255
+ }
256
+
257
+ // MARK: - Linear helpers
258
+
259
+ private static func parseLinearDirection(_ value: String) -> (start: UnitPoint, end: UnitPoint)? {
260
+ let lower = value.lowercased().trimmingCharacters(in: .whitespacesAndNewlines)
261
+ guard lower.hasPrefix("to ") else { return nil }
262
+ let suffix = lower.dropFirst(3)
263
+ let words = suffix.split(separator: " ").map(String.init)
264
+ guard (1 ... 2).contains(words.count) else { return nil }
265
+
266
+ var horizontal: String?
267
+ var vertical: String?
268
+
269
+ for word in words {
270
+ switch word {
271
+ case "left", "right":
272
+ if horizontal != nil { return nil }
273
+ horizontal = word
274
+ case "top", "bottom":
275
+ if vertical != nil { return nil }
276
+ vertical = word
277
+ default:
278
+ return nil
279
+ }
280
+ }
281
+
282
+ let endX: Double = switch horizontal {
283
+ case "left": 0
284
+ case "right": 1
285
+ default: 0.5
286
+ }
287
+ let endY: Double = switch vertical {
288
+ case "top": 0
289
+ case "bottom": 1
290
+ default: 0.5
291
+ }
292
+ let start = UnitPoint(x: 1 - endX, y: 1 - endY)
293
+ let end = UnitPoint(x: endX, y: endY)
294
+ return (start, end)
295
+ }
296
+
297
+ private static func angleToPoints(_ angle: Angle) -> (start: UnitPoint, end: UnitPoint) {
298
+ let radians = (angle.degrees - 90) * .pi / 180
299
+ let x = cos(radians)
300
+ let y = sin(radians)
301
+
302
+ let startX = 0.5 - x / 2
303
+ let startY = 0.5 + y / 2
304
+ let endX = 0.5 + x / 2
305
+ let endY = 0.5 - y / 2
306
+ return (UnitPoint(x: startX, y: startY), UnitPoint(x: endX, y: endY))
307
+ }
308
+
309
+ // MARK: - Radial helpers
310
+
311
+ private static func parseRadialPrelude(_ value: String) -> (shape: RadialGradientShape, extent: RadialGradientExtent, center: UnitPoint)? {
312
+ let tokens = splitByWhitespaceOutsideParentheses(value.lowercased())
313
+ guard !tokens.isEmpty else { return nil }
314
+
315
+ var shape: RadialGradientShape = .ellipse
316
+ var extent: RadialGradientExtent = .farthestCorner
317
+ var center = UnitPoint.center
318
+ var idx = 0
319
+
320
+ while idx < tokens.count {
321
+ let token = tokens[idx]
322
+ if token == "at" {
323
+ let positionTokens = Array(tokens[(idx + 1)...])
324
+ guard let parsedCenter = parsePosition(positionTokens), !positionTokens.isEmpty else { return nil }
325
+ center = parsedCenter
326
+ idx = tokens.count
327
+ } else if token == "circle" {
328
+ shape = .circle
329
+ idx += 1
330
+ } else if token == "ellipse" {
331
+ shape = .ellipse
332
+ idx += 1
333
+ } else if let parsedExtent = parseRadialExtent(token) {
334
+ extent = parsedExtent
335
+ idx += 1
336
+ } else {
337
+ return nil
338
+ }
339
+ }
340
+
341
+ return (shape, extent, center)
342
+ }
343
+
344
+ private static func parseRadialExtent(_ token: String) -> RadialGradientExtent? {
345
+ switch token {
346
+ case "closest-side":
347
+ return .closestSide
348
+ case "farthest-side":
349
+ return .farthestSide
350
+ case "closest-corner":
351
+ return .closestCorner
352
+ case "farthest-corner":
353
+ return .farthestCorner
354
+ default:
355
+ return nil
356
+ }
357
+ }
358
+
359
+ // MARK: - Conic helpers
360
+
361
+ private static func parseConicPrelude(_ value: String) -> (angle: Angle, center: UnitPoint)? {
362
+ let tokens = splitByWhitespaceOutsideParentheses(value.lowercased())
363
+ guard !tokens.isEmpty else { return nil }
364
+
365
+ var angle = Angle.zero
366
+ var center = UnitPoint.center
367
+ var hasFrom = false
368
+ var hasAt = false
369
+ var idx = 0
370
+
371
+ while idx < tokens.count {
372
+ let token = tokens[idx]
373
+ if token == "from" {
374
+ guard !hasFrom, idx + 1 < tokens.count, let parsedAngle = parseAngle(tokens[idx + 1]) else { return nil }
375
+ angle = parsedAngle
376
+ hasFrom = true
377
+ idx += 2
378
+ } else if token == "at" {
379
+ guard !hasAt else { return nil }
380
+ let positionTokens = Array(tokens[(idx + 1)...])
381
+ guard let parsedCenter = parsePosition(positionTokens), !positionTokens.isEmpty else { return nil }
382
+ center = parsedCenter
383
+ hasAt = true
384
+ idx = tokens.count
385
+ } else {
386
+ return nil
387
+ }
388
+ }
389
+
390
+ return (angle, center)
391
+ }
392
+
393
+ // MARK: - Position helpers
394
+
395
+ private static func parsePosition(_ tokens: [String]) -> UnitPoint? {
396
+ guard !tokens.isEmpty, tokens.count <= 2 else { return nil }
397
+
398
+ if tokens.count == 1 {
399
+ switch tokens[0] {
400
+ case "center":
401
+ return .center
402
+ case "left":
403
+ return UnitPoint(x: 0, y: 0.5)
404
+ case "right":
405
+ return UnitPoint(x: 1, y: 0.5)
406
+ case "top":
407
+ return UnitPoint(x: 0.5, y: 0)
408
+ case "bottom":
409
+ return UnitPoint(x: 0.5, y: 1)
410
+ default:
411
+ return nil
412
+ }
413
+ }
414
+
415
+ var x: Double?
416
+ var y: Double?
417
+
418
+ for token in tokens {
419
+ switch token {
420
+ case "left":
421
+ if x != nil { return nil }
422
+ x = 0
423
+ case "right":
424
+ if x != nil { return nil }
425
+ x = 1
426
+ case "center":
427
+ if x == nil {
428
+ x = 0.5
429
+ } else if y == nil {
430
+ y = 0.5
431
+ } else {
432
+ return nil
433
+ }
434
+ case "top":
435
+ if y != nil { return nil }
436
+ y = 0
437
+ case "bottom":
438
+ if y != nil { return nil }
439
+ y = 1
440
+ default:
441
+ return nil
442
+ }
443
+ }
444
+
445
+ return UnitPoint(x: x ?? 0.5, y: y ?? 0.5)
446
+ }
447
+
448
+ // MARK: - Stop helpers
449
+
450
+ private static func parseStops(_ args: [String], kind: GradientKind) -> [Gradient.Stop]? {
451
+ var tokens: [ColorStopToken] = []
452
+
453
+ for raw in args {
454
+ guard let parsed = parseColorStop(raw, kind: kind) else { return nil }
455
+ tokens.append(parsed)
456
+ }
457
+
458
+ guard tokens.count >= 2 else { return nil }
459
+
460
+ let expanded = expandColorStops(tokens)
461
+ let resolved = resolveStopPositions(expanded)
462
+ guard resolved.count >= 2 else { return nil }
463
+
464
+ return resolved.map { stop in
465
+ Gradient.Stop(color: stop.color, location: CGFloat(stop.position))
466
+ }
467
+ }
468
+
469
+ private static func parseColorStop(_ token: String, kind: GradientKind) -> ColorStopToken? {
470
+ let trimmed = token.trimmingCharacters(in: .whitespacesAndNewlines)
471
+ guard !trimmed.isEmpty else { return nil }
472
+
473
+ // Function color with optional trailing stop positions, e.g. "rgba(...) 0%".
474
+ if let functionSplit = splitFunctionColorAndPositions(trimmed),
475
+ let color = JSColorParser.parse(functionSplit.colorToken)
476
+ {
477
+ var parsedPositions: [Double] = []
478
+ for positionToken in functionSplit.positionTokens {
479
+ guard let position = parseStopPosition(positionToken, kind: kind) else { return nil }
480
+ parsedPositions.append(position)
481
+ }
482
+ return ColorStopToken(
483
+ color: color,
484
+ firstPosition: parsedPositions.first,
485
+ secondPosition: parsedPositions.count == 2 ? parsedPositions[1] : nil
486
+ )
487
+ }
488
+
489
+ // Generic "color + optional trailing positions" split from right side.
490
+ if let split = splitColorAndPositions(trimmed, kind: kind),
491
+ let color = JSColorParser.parse(split.colorToken)
492
+ {
493
+ var parsed: [Double] = []
494
+ for positionToken in split.positionTokens {
495
+ guard let position = parseStopPosition(positionToken, kind: kind) else { return nil }
496
+ parsed.append(position)
497
+ }
498
+
499
+ return ColorStopToken(
500
+ color: color,
501
+ firstPosition: parsed.first,
502
+ secondPosition: parsed.count == 2 ? parsed[1] : nil
503
+ )
504
+ }
505
+
506
+ if let color = JSColorParser.parse(trimmed) {
507
+ return ColorStopToken(color: color, firstPosition: nil, secondPosition: nil)
508
+ }
509
+
510
+ return nil
511
+ }
512
+
513
+ private static func splitFunctionColorAndPositions(_ token: String) -> (colorToken: String, positionTokens: [String])? {
514
+ let lower = token.lowercased()
515
+ let fnPrefixes = ["rgba(", "rgb(", "hsla(", "hsl("]
516
+ guard fnPrefixes.contains(where: { lower.hasPrefix($0) }) else { return nil }
517
+
518
+ var depth = 0
519
+ var closeIndex: String.Index?
520
+ for idx in token.indices {
521
+ let ch = token[idx]
522
+ if ch == "(" {
523
+ depth += 1
524
+ } else if ch == ")" {
525
+ depth -= 1
526
+ if depth == 0 {
527
+ closeIndex = idx
528
+ break
529
+ }
530
+ if depth < 0 {
531
+ return nil
532
+ }
533
+ }
534
+ }
535
+ guard let closeIndex else { return nil }
536
+
537
+ let colorToken = String(token[...closeIndex]).trimmingCharacters(in: .whitespacesAndNewlines)
538
+ let restStart = token.index(after: closeIndex)
539
+ let rest = token[restStart...].trimmingCharacters(in: .whitespacesAndNewlines)
540
+ if rest.isEmpty {
541
+ return (colorToken, [])
542
+ }
543
+ let positionTokens = splitByWhitespaceOutsideParentheses(String(rest))
544
+ guard !positionTokens.isEmpty, positionTokens.count <= 2 else { return nil }
545
+ return (colorToken, positionTokens)
546
+ }
547
+
548
+ private static func splitColorAndPositions(_ token: String, kind: GradientKind) -> (colorToken: String, positionTokens: [String])? {
549
+ let parts = splitByWhitespaceOutsideParentheses(token)
550
+ guard parts.count >= 2 else { return nil }
551
+
552
+ // Try two trailing position tokens first (to support "red 10% 30%").
553
+ if parts.count >= 3,
554
+ let colorToken = join(parts[0 ..< parts.count - 2])
555
+ {
556
+ let two = [parts[parts.count - 2], parts[parts.count - 1]]
557
+ if two.allSatisfy({ parseStopPosition($0, kind: kind) != nil }) {
558
+ return (colorToken, two)
559
+ }
560
+ }
561
+
562
+ // Try one trailing position token.
563
+ if let colorToken = join(parts[0 ..< parts.count - 1]) {
564
+ let one = [parts[parts.count - 1]]
565
+ if one.allSatisfy({ parseStopPosition($0, kind: kind) != nil }) {
566
+ return (colorToken, one)
567
+ }
568
+ }
569
+
570
+ return nil
571
+ }
572
+
573
+ private static func join(_ parts: ArraySlice<String>) -> String? {
574
+ let value = parts.joined(separator: " ").trimmingCharacters(in: .whitespacesAndNewlines)
575
+ return value.isEmpty ? nil : value
576
+ }
577
+
578
+ private static func parseStopPosition(_ token: String, kind: GradientKind) -> Double? {
579
+ let lower = token.lowercased()
580
+ if lower.hasSuffix("%"), let value = Double(lower.dropLast()) {
581
+ return value / 100
582
+ }
583
+
584
+ if kind == .conic, let angle = parseAngle(lower) {
585
+ return angle.degrees / 360
586
+ }
587
+
588
+ return nil
589
+ }
590
+
591
+ private struct ResolvedStop {
592
+ var color: Color
593
+ var position: Double
594
+ }
595
+
596
+ private struct IntermediateStop {
597
+ var color: Color
598
+ var position: Double?
599
+ }
600
+
601
+ private static func expandColorStops(_ stops: [ColorStopToken]) -> [IntermediateStop] {
602
+ var expanded: [IntermediateStop] = []
603
+ for stop in stops {
604
+ expanded.append(.init(color: stop.color, position: stop.firstPosition))
605
+ if let second = stop.secondPosition {
606
+ expanded.append(.init(color: stop.color, position: second))
607
+ }
608
+ }
609
+ return expanded
610
+ }
611
+
612
+ private static func resolveStopPositions(_ stops: [IntermediateStop]) -> [ResolvedStop] {
613
+ guard !stops.isEmpty else { return [] }
614
+
615
+ var positions = stops.map(\.position)
616
+ if positions.first == nil { positions[0] = 0 }
617
+ if positions.last == nil { positions[positions.count - 1] = 1 }
618
+
619
+ var lastDefined: Double?
620
+ for idx in positions.indices {
621
+ if var current = positions[idx] {
622
+ if let previous = lastDefined, current < previous {
623
+ current = previous
624
+ positions[idx] = current
625
+ }
626
+ lastDefined = current
627
+ }
628
+ }
629
+
630
+ var index = 0
631
+ while index < positions.count {
632
+ if positions[index] != nil {
633
+ index += 1
634
+ continue
635
+ }
636
+
637
+ let start = index - 1
638
+ var end = index
639
+ while end < positions.count, positions[end] == nil {
640
+ end += 1
641
+ }
642
+ guard start >= 0 else { return [] }
643
+ guard end < positions.count, let startPos = positions[start], let endPos = positions[end] else { return [] }
644
+
645
+ let gaps = end - start
646
+ for step in 1 ..< gaps {
647
+ let t = Double(step) / Double(gaps)
648
+ positions[start + step] = startPos + (endPos - startPos) * t
649
+ }
650
+ index = end + 1
651
+ }
652
+
653
+ return zip(stops, positions).compactMap { stop, position in
654
+ guard let position else { return nil }
655
+ return ResolvedStop(color: stop.color, position: position)
656
+ }
657
+ }
658
+
659
+ // MARK: - Numeric helpers
660
+
661
+ private static func parseAngle(_ token: String) -> Angle? {
662
+ let trimmed = token.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
663
+ if trimmed.hasSuffix("deg"), let value = Double(trimmed.dropLast(3)) {
664
+ return Angle(degrees: value)
665
+ }
666
+ if trimmed.hasSuffix("rad"), let value = Double(trimmed.dropLast(3)) {
667
+ return Angle(radians: value)
668
+ }
669
+ if trimmed.hasSuffix("turn"), let value = Double(trimmed.dropLast(4)) {
670
+ return Angle(degrees: value * 360)
671
+ }
672
+ return nil
673
+ }
674
+ }