@use-voltra/ios-client 2.1.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (365) hide show
  1. package/README.md +61 -8
  2. package/Voltra.podspec +1 -0
  3. package/build/commonjs/dynamic-widget/api.js +15 -0
  4. package/build/commonjs/dynamic-widget/api.js.map +1 -0
  5. package/build/commonjs/events.js +23 -0
  6. package/build/commonjs/events.js.map +1 -1
  7. package/build/commonjs/index.js +74 -7
  8. package/build/commonjs/index.js.map +1 -1
  9. package/build/commonjs/live-activity/api.js +3 -1
  10. package/build/commonjs/live-activity/api.js.map +1 -1
  11. package/build/commonjs/live-activity/dynamic-api.js +173 -0
  12. package/build/commonjs/live-activity/dynamic-api.js.map +1 -0
  13. package/build/commonjs/native/NativeVoltra.js.map +1 -1
  14. package/build/commonjs/utils/enableDynamicLiveActivityHotReload.js +47 -0
  15. package/build/commonjs/utils/enableDynamicLiveActivityHotReload.js.map +1 -0
  16. package/build/commonjs/utils/enableWidgetHotReload.js +8 -11
  17. package/build/commonjs/utils/enableWidgetHotReload.js.map +1 -1
  18. package/build/commonjs/utils/useUpdateOnHMR.js +3 -7
  19. package/build/commonjs/utils/useUpdateOnHMR.js.map +1 -1
  20. package/build/commonjs/widgets/server-credentials.js +9 -0
  21. package/build/commonjs/widgets/server-credentials.js.map +1 -1
  22. package/build/commonjs/widgets/server-update.js +78 -0
  23. package/build/commonjs/widgets/server-update.js.map +1 -0
  24. package/build/module/dynamic-widget/api.js +10 -0
  25. package/build/module/dynamic-widget/api.js.map +1 -0
  26. package/build/module/events.js +23 -0
  27. package/build/module/events.js.map +1 -1
  28. package/build/module/index.js +4 -0
  29. package/build/module/index.js.map +1 -1
  30. package/build/module/live-activity/api.js +2 -2
  31. package/build/module/live-activity/api.js.map +1 -1
  32. package/build/module/live-activity/dynamic-api.js +167 -0
  33. package/build/module/live-activity/dynamic-api.js.map +1 -0
  34. package/build/module/native/NativeVoltra.js.map +1 -1
  35. package/build/module/utils/enableDynamicLiveActivityHotReload.js +43 -0
  36. package/build/module/utils/enableDynamicLiveActivityHotReload.js.map +1 -0
  37. package/build/module/utils/enableWidgetHotReload.js +9 -11
  38. package/build/module/utils/enableWidgetHotReload.js.map +1 -1
  39. package/build/module/utils/useUpdateOnHMR.js +3 -7
  40. package/build/module/utils/useUpdateOnHMR.js.map +1 -1
  41. package/build/module/widgets/server-credentials.js +9 -0
  42. package/build/module/widgets/server-credentials.js.map +1 -1
  43. package/build/module/widgets/server-update.js +72 -0
  44. package/build/module/widgets/server-update.js.map +1 -0
  45. package/build/typescript/commonjs/dynamic-widget/api.d.ts +8 -0
  46. package/build/typescript/commonjs/dynamic-widget/api.d.ts.map +1 -0
  47. package/build/typescript/commonjs/events.d.ts +7 -0
  48. package/build/typescript/commonjs/events.d.ts.map +1 -1
  49. package/build/typescript/commonjs/index.d.ts +4 -0
  50. package/build/typescript/commonjs/index.d.ts.map +1 -1
  51. package/build/typescript/commonjs/live-activity/api.d.ts +7 -0
  52. package/build/typescript/commonjs/live-activity/api.d.ts.map +1 -1
  53. package/build/typescript/commonjs/live-activity/dynamic-api.d.ts +54 -0
  54. package/build/typescript/commonjs/live-activity/dynamic-api.d.ts.map +1 -0
  55. package/build/typescript/commonjs/native/NativeVoltra.d.ts +21 -0
  56. package/build/typescript/commonjs/native/NativeVoltra.d.ts.map +1 -1
  57. package/build/typescript/commonjs/types.d.ts +1 -1
  58. package/build/typescript/commonjs/types.d.ts.map +1 -1
  59. package/build/typescript/commonjs/utils/enableDynamicLiveActivityHotReload.d.ts +15 -0
  60. package/build/typescript/commonjs/utils/enableDynamicLiveActivityHotReload.d.ts.map +1 -0
  61. package/build/typescript/commonjs/utils/enableWidgetHotReload.d.ts +5 -7
  62. package/build/typescript/commonjs/utils/enableWidgetHotReload.d.ts.map +1 -1
  63. package/build/typescript/commonjs/utils/useUpdateOnHMR.d.ts +0 -3
  64. package/build/typescript/commonjs/utils/useUpdateOnHMR.d.ts.map +1 -1
  65. package/build/typescript/commonjs/widgets/server-credentials.d.ts +8 -0
  66. package/build/typescript/commonjs/widgets/server-credentials.d.ts.map +1 -1
  67. package/build/typescript/commonjs/widgets/server-update.d.ts +64 -0
  68. package/build/typescript/commonjs/widgets/server-update.d.ts.map +1 -0
  69. package/build/typescript/module/dynamic-widget/api.d.ts +8 -0
  70. package/build/typescript/module/dynamic-widget/api.d.ts.map +1 -0
  71. package/build/typescript/module/events.d.ts +7 -0
  72. package/build/typescript/module/events.d.ts.map +1 -1
  73. package/build/typescript/module/index.d.ts +4 -0
  74. package/build/typescript/module/index.d.ts.map +1 -1
  75. package/build/typescript/module/live-activity/api.d.ts +7 -0
  76. package/build/typescript/module/live-activity/api.d.ts.map +1 -1
  77. package/build/typescript/module/live-activity/dynamic-api.d.ts +54 -0
  78. package/build/typescript/module/live-activity/dynamic-api.d.ts.map +1 -0
  79. package/build/typescript/module/native/NativeVoltra.d.ts +21 -0
  80. package/build/typescript/module/native/NativeVoltra.d.ts.map +1 -1
  81. package/build/typescript/module/types.d.ts +1 -1
  82. package/build/typescript/module/types.d.ts.map +1 -1
  83. package/build/typescript/module/utils/enableDynamicLiveActivityHotReload.d.ts +15 -0
  84. package/build/typescript/module/utils/enableDynamicLiveActivityHotReload.d.ts.map +1 -0
  85. package/build/typescript/module/utils/enableWidgetHotReload.d.ts +5 -7
  86. package/build/typescript/module/utils/enableWidgetHotReload.d.ts.map +1 -1
  87. package/build/typescript/module/utils/useUpdateOnHMR.d.ts +0 -3
  88. package/build/typescript/module/utils/useUpdateOnHMR.d.ts.map +1 -1
  89. package/build/typescript/module/widgets/server-credentials.d.ts +8 -0
  90. package/build/typescript/module/widgets/server-credentials.d.ts.map +1 -1
  91. package/build/typescript/module/widgets/server-update.d.ts +64 -0
  92. package/build/typescript/module/widgets/server-update.d.ts.map +1 -0
  93. package/expo-plugin/build/cjs/constants.js +20 -1
  94. package/expo-plugin/build/cjs/constants.js.map +1 -1
  95. package/expo-plugin/build/cjs/index.js +9 -1
  96. package/expo-plugin/build/cjs/index.js.map +1 -1
  97. package/expo-plugin/build/cjs/ios/index.js +1 -0
  98. package/expo-plugin/build/cjs/ios/index.js.map +1 -1
  99. package/expo-plugin/build/cjs/ios/infoPlist.js +28 -5
  100. package/expo-plugin/build/cjs/ios/infoPlist.js.map +1 -1
  101. package/expo-plugin/build/cjs/ios/serverUpdate.js +25 -0
  102. package/expo-plugin/build/cjs/ios/serverUpdate.js.map +1 -0
  103. package/expo-plugin/build/cjs/ios-widget/clientRendered.js +4 -4
  104. package/expo-plugin/build/cjs/ios-widget/clientRendered.js.map +1 -1
  105. package/expo-plugin/build/cjs/ios-widget/clientRenderedPrerender.js +5 -5
  106. package/expo-plugin/build/cjs/ios-widget/clientRenderedPrerender.js.map +1 -1
  107. package/expo-plugin/build/cjs/ios-widget/dynamic-live-activity/swift.js +130 -0
  108. package/expo-plugin/build/cjs/ios-widget/dynamic-live-activity/swift.js.map +1 -0
  109. package/expo-plugin/build/cjs/ios-widget/files/index.js +9 -2
  110. package/expo-plugin/build/cjs/ios-widget/files/index.js.map +1 -1
  111. package/expo-plugin/build/cjs/ios-widget/files/infoPlist.js +6 -3
  112. package/expo-plugin/build/cjs/ios-widget/files/infoPlist.js.map +1 -1
  113. package/expo-plugin/build/cjs/ios-widget/files/manifest.js +24 -0
  114. package/expo-plugin/build/cjs/ios-widget/files/manifest.js.map +1 -1
  115. package/expo-plugin/build/cjs/ios-widget/files/swift-utils.js +7 -0
  116. package/expo-plugin/build/cjs/ios-widget/files/swift-utils.js.map +1 -0
  117. package/expo-plugin/build/cjs/ios-widget/files/swift.js +56 -26
  118. package/expo-plugin/build/cjs/ios-widget/files/swift.js.map +1 -1
  119. package/expo-plugin/build/cjs/ios-widget/index.js +9 -3
  120. package/expo-plugin/build/cjs/ios-widget/index.js.map +1 -1
  121. package/expo-plugin/build/cjs/ios-widget/podfile.js +38 -12
  122. package/expo-plugin/build/cjs/ios-widget/podfile.js.map +1 -1
  123. package/expo-plugin/build/cjs/ios-widget/widgetPlist.js +34 -22
  124. package/expo-plugin/build/cjs/ios-widget/widgetPlist.js.map +1 -1
  125. package/expo-plugin/build/cjs/ios-widget/xcode/buildPhases.js +194 -118
  126. package/expo-plugin/build/cjs/ios-widget/xcode/buildPhases.js.map +1 -1
  127. package/expo-plugin/build/cjs/ios-widget/xcode/configurationList.js +30 -22
  128. package/expo-plugin/build/cjs/ios-widget/xcode/configurationList.js.map +1 -1
  129. package/expo-plugin/build/cjs/ios-widget/xcode/fileReferences.js +50 -0
  130. package/expo-plugin/build/cjs/ios-widget/xcode/fileReferences.js.map +1 -0
  131. package/expo-plugin/build/cjs/ios-widget/xcode/groups.js +45 -43
  132. package/expo-plugin/build/cjs/ios-widget/xcode/groups.js.map +1 -1
  133. package/expo-plugin/build/cjs/ios-widget/xcode/index.js +93 -91
  134. package/expo-plugin/build/cjs/ios-widget/xcode/index.js.map +1 -1
  135. package/expo-plugin/build/cjs/ios-widget/xcode/mainAppSettings.js +41 -39
  136. package/expo-plugin/build/cjs/ios-widget/xcode/mainAppSettings.js.map +1 -1
  137. package/expo-plugin/build/cjs/ios-widget/xcode/productFile.js +2 -2
  138. package/expo-plugin/build/cjs/ios-widget/xcode/productFile.js.map +1 -1
  139. package/expo-plugin/build/cjs/ios-widget/xcode/target.js +29 -63
  140. package/expo-plugin/build/cjs/ios-widget/xcode/target.js.map +1 -1
  141. package/expo-plugin/build/cjs/utils/urlScheme.js +36 -14
  142. package/expo-plugin/build/cjs/utils/urlScheme.js.map +1 -1
  143. package/expo-plugin/build/cjs/validation.js +54 -0
  144. package/expo-plugin/build/cjs/validation.js.map +1 -1
  145. package/expo-plugin/build/esm/constants.js +17 -0
  146. package/expo-plugin/build/esm/constants.js.map +1 -1
  147. package/expo-plugin/build/esm/index.js +9 -1
  148. package/expo-plugin/build/esm/index.js.map +1 -1
  149. package/expo-plugin/build/esm/ios/index.js +1 -0
  150. package/expo-plugin/build/esm/ios/index.js.map +1 -1
  151. package/expo-plugin/build/esm/ios/infoPlist.js +28 -5
  152. package/expo-plugin/build/esm/ios/infoPlist.js.map +1 -1
  153. package/expo-plugin/build/esm/ios/serverUpdate.js +21 -0
  154. package/expo-plugin/build/esm/ios/serverUpdate.js.map +1 -0
  155. package/expo-plugin/build/esm/ios-widget/clientRendered.js +5 -5
  156. package/expo-plugin/build/esm/ios-widget/clientRendered.js.map +1 -1
  157. package/expo-plugin/build/esm/ios-widget/clientRenderedPrerender.js +6 -6
  158. package/expo-plugin/build/esm/ios-widget/clientRenderedPrerender.js.map +1 -1
  159. package/expo-plugin/build/esm/ios-widget/dynamic-live-activity/swift.js +122 -0
  160. package/expo-plugin/build/esm/ios-widget/dynamic-live-activity/swift.js.map +1 -0
  161. package/expo-plugin/build/esm/ios-widget/files/index.js +10 -3
  162. package/expo-plugin/build/esm/ios-widget/files/index.js.map +1 -1
  163. package/expo-plugin/build/esm/ios-widget/files/infoPlist.js +6 -3
  164. package/expo-plugin/build/esm/ios-widget/files/infoPlist.js.map +1 -1
  165. package/expo-plugin/build/esm/ios-widget/files/manifest.js +23 -1
  166. package/expo-plugin/build/esm/ios-widget/files/manifest.js.map +1 -1
  167. package/expo-plugin/build/esm/ios-widget/files/swift-utils.js +4 -0
  168. package/expo-plugin/build/esm/ios-widget/files/swift-utils.js.map +1 -0
  169. package/expo-plugin/build/esm/ios-widget/files/swift.js +50 -20
  170. package/expo-plugin/build/esm/ios-widget/files/swift.js.map +1 -1
  171. package/expo-plugin/build/esm/ios-widget/index.js +9 -3
  172. package/expo-plugin/build/esm/ios-widget/index.js.map +1 -1
  173. package/expo-plugin/build/esm/ios-widget/podfile.js +36 -11
  174. package/expo-plugin/build/esm/ios-widget/podfile.js.map +1 -1
  175. package/expo-plugin/build/esm/ios-widget/widgetPlist.js +34 -22
  176. package/expo-plugin/build/esm/ios-widget/widgetPlist.js.map +1 -1
  177. package/expo-plugin/build/esm/ios-widget/xcode/buildPhases.js +194 -117
  178. package/expo-plugin/build/esm/ios-widget/xcode/buildPhases.js.map +1 -1
  179. package/expo-plugin/build/esm/ios-widget/xcode/configurationList.js +31 -22
  180. package/expo-plugin/build/esm/ios-widget/xcode/configurationList.js.map +1 -1
  181. package/expo-plugin/build/esm/ios-widget/xcode/fileReferences.js +45 -0
  182. package/expo-plugin/build/esm/ios-widget/xcode/fileReferences.js.map +1 -0
  183. package/expo-plugin/build/esm/ios-widget/xcode/groups.js +45 -42
  184. package/expo-plugin/build/esm/ios-widget/xcode/groups.js.map +1 -1
  185. package/expo-plugin/build/esm/ios-widget/xcode/index.js +97 -96
  186. package/expo-plugin/build/esm/ios-widget/xcode/index.js.map +1 -1
  187. package/expo-plugin/build/esm/ios-widget/xcode/mainAppSettings.js +41 -39
  188. package/expo-plugin/build/esm/ios-widget/xcode/mainAppSettings.js.map +1 -1
  189. package/expo-plugin/build/esm/ios-widget/xcode/productFile.js +3 -2
  190. package/expo-plugin/build/esm/ios-widget/xcode/productFile.js.map +1 -1
  191. package/expo-plugin/build/esm/ios-widget/xcode/target.js +28 -62
  192. package/expo-plugin/build/esm/ios-widget/xcode/target.js.map +1 -1
  193. package/expo-plugin/build/esm/utils/urlScheme.js +34 -14
  194. package/expo-plugin/build/esm/utils/urlScheme.js.map +1 -1
  195. package/expo-plugin/build/esm/validation.js +54 -1
  196. package/expo-plugin/build/esm/validation.js.map +1 -1
  197. package/expo-plugin/build/types/constants.d.ts +10 -1
  198. package/expo-plugin/build/types/constants.d.ts.map +1 -1
  199. package/expo-plugin/build/types/index.d.ts +1 -1
  200. package/expo-plugin/build/types/index.d.ts.map +1 -1
  201. package/expo-plugin/build/types/ios/index.d.ts +2 -0
  202. package/expo-plugin/build/types/ios/index.d.ts.map +1 -1
  203. package/expo-plugin/build/types/ios/infoPlist.d.ts +2 -0
  204. package/expo-plugin/build/types/ios/infoPlist.d.ts.map +1 -1
  205. package/expo-plugin/build/types/ios/serverUpdate.d.ts +11 -0
  206. package/expo-plugin/build/types/ios/serverUpdate.d.ts.map +1 -0
  207. package/expo-plugin/build/types/ios-widget/clientRendered.d.ts.map +1 -1
  208. package/expo-plugin/build/types/ios-widget/clientRenderedPrerender.d.ts.map +1 -1
  209. package/expo-plugin/build/types/ios-widget/dynamic-live-activity/swift.d.ts +7 -0
  210. package/expo-plugin/build/types/ios-widget/dynamic-live-activity/swift.d.ts.map +1 -0
  211. package/expo-plugin/build/types/ios-widget/files/index.d.ts +3 -1
  212. package/expo-plugin/build/types/ios-widget/files/index.d.ts.map +1 -1
  213. package/expo-plugin/build/types/ios-widget/files/infoPlist.d.ts +2 -1
  214. package/expo-plugin/build/types/ios-widget/files/infoPlist.d.ts.map +1 -1
  215. package/expo-plugin/build/types/ios-widget/files/manifest.d.ts +9 -2
  216. package/expo-plugin/build/types/ios-widget/files/manifest.d.ts.map +1 -1
  217. package/expo-plugin/build/types/ios-widget/files/swift-utils.d.ts +2 -0
  218. package/expo-plugin/build/types/ios-widget/files/swift-utils.d.ts.map +1 -0
  219. package/expo-plugin/build/types/ios-widget/files/swift.d.ts +6 -2
  220. package/expo-plugin/build/types/ios-widget/files/swift.d.ts.map +1 -1
  221. package/expo-plugin/build/types/ios-widget/index.d.ts +3 -1
  222. package/expo-plugin/build/types/ios-widget/index.d.ts.map +1 -1
  223. package/expo-plugin/build/types/ios-widget/podfile.d.ts +19 -1
  224. package/expo-plugin/build/types/ios-widget/podfile.d.ts.map +1 -1
  225. package/expo-plugin/build/types/ios-widget/widgetPlist.d.ts.map +1 -1
  226. package/expo-plugin/build/types/ios-widget/xcode/buildPhases.d.ts +6 -8
  227. package/expo-plugin/build/types/ios-widget/xcode/buildPhases.d.ts.map +1 -1
  228. package/expo-plugin/build/types/ios-widget/xcode/configurationList.d.ts +15 -10
  229. package/expo-plugin/build/types/ios-widget/xcode/configurationList.d.ts.map +1 -1
  230. package/expo-plugin/build/types/ios-widget/xcode/fileReferences.d.ts +16 -0
  231. package/expo-plugin/build/types/ios-widget/xcode/fileReferences.d.ts.map +1 -0
  232. package/expo-plugin/build/types/ios-widget/xcode/groups.d.ts +0 -4
  233. package/expo-plugin/build/types/ios-widget/xcode/groups.d.ts.map +1 -1
  234. package/expo-plugin/build/types/ios-widget/xcode/index.d.ts +23 -3
  235. package/expo-plugin/build/types/ios-widget/xcode/index.d.ts.map +1 -1
  236. package/expo-plugin/build/types/ios-widget/xcode/mainAppSettings.d.ts +16 -4
  237. package/expo-plugin/build/types/ios-widget/xcode/mainAppSettings.d.ts.map +1 -1
  238. package/expo-plugin/build/types/ios-widget/xcode/productFile.d.ts +0 -4
  239. package/expo-plugin/build/types/ios-widget/xcode/productFile.d.ts.map +1 -1
  240. package/expo-plugin/build/types/ios-widget/xcode/target.d.ts +11 -26
  241. package/expo-plugin/build/types/ios-widget/xcode/target.d.ts.map +1 -1
  242. package/expo-plugin/build/types/types.d.ts +23 -4
  243. package/expo-plugin/build/types/types.d.ts.map +1 -1
  244. package/expo-plugin/build/types/utils/urlScheme.d.ts +16 -0
  245. package/expo-plugin/build/types/utils/urlScheme.d.ts.map +1 -1
  246. package/expo-plugin/build/types/validation.d.ts +2 -1
  247. package/expo-plugin/build/types/validation.d.ts.map +1 -1
  248. package/expo-plugin/src/constants.ts +24 -1
  249. package/expo-plugin/src/index.ts +14 -1
  250. package/expo-plugin/src/ios/index.ts +3 -0
  251. package/expo-plugin/src/ios/infoPlist.ts +33 -5
  252. package/expo-plugin/src/ios/serverUpdate.ts +29 -0
  253. package/expo-plugin/src/ios-widget/clientRendered.ts +9 -5
  254. package/expo-plugin/src/ios-widget/clientRenderedPrerender.ts +11 -6
  255. package/expo-plugin/src/ios-widget/dynamic-live-activity/swift.ts +138 -0
  256. package/expo-plugin/src/ios-widget/files/index.ts +15 -4
  257. package/expo-plugin/src/ios-widget/files/infoPlist.ts +17 -3
  258. package/expo-plugin/src/ios-widget/files/manifest.ts +42 -2
  259. package/expo-plugin/src/ios-widget/files/swift-utils.ts +3 -0
  260. package/expo-plugin/src/ios-widget/files/swift.ts +69 -22
  261. package/expo-plugin/src/ios-widget/index.ts +13 -3
  262. package/expo-plugin/src/ios-widget/podfile.ts +46 -13
  263. package/expo-plugin/src/ios-widget/widgetPlist.ts +37 -23
  264. package/expo-plugin/src/ios-widget/xcode/__fixtures__/fresh.pbxproj +197 -0
  265. package/expo-plugin/src/ios-widget/xcode/__fixtures__/with-existing-extension.pbxproj +321 -0
  266. package/expo-plugin/src/ios-widget/xcode/__fixtures__/with-per-config-signing.pbxproj +203 -0
  267. package/expo-plugin/src/ios-widget/xcode/__snapshots__/applyXcodeChanges.node.test.ts.snap +363 -0
  268. package/expo-plugin/src/ios-widget/xcode/__tests__/pbxConsistency.ts +130 -0
  269. package/expo-plugin/src/ios-widget/xcode/buildPhases.ts +210 -164
  270. package/expo-plugin/src/ios-widget/xcode/configurationList.ts +52 -35
  271. package/expo-plugin/src/ios-widget/xcode/fileReferences.ts +51 -0
  272. package/expo-plugin/src/ios-widget/xcode/groups.ts +52 -54
  273. package/expo-plugin/src/ios-widget/xcode/index.ts +124 -119
  274. package/expo-plugin/src/ios-widget/xcode/mainAppSettings.ts +59 -54
  275. package/expo-plugin/src/ios-widget/xcode/productFile.ts +3 -2
  276. package/expo-plugin/src/ios-widget/xcode/target.ts +31 -83
  277. package/expo-plugin/src/types.ts +28 -4
  278. package/expo-plugin/src/utils/urlScheme.ts +47 -17
  279. package/expo-plugin/src/validation.ts +76 -1
  280. package/ios/Package.swift +39 -4
  281. package/ios/VoltraWidget.podspec +1 -0
  282. package/ios/app/NativeVoltra.mm +126 -7
  283. package/ios/app/VoltraLiveActivityManager.swift +30 -0
  284. package/ios/app/VoltraLiveActivityService.swift +77 -5
  285. package/ios/app/VoltraModule.swift +117 -1
  286. package/ios/app/VoltraModuleImpl.swift +116 -2
  287. package/ios/app/VoltraViewComponentView.mm +3 -3
  288. package/ios/app/VoltraWidgetService.swift +147 -12
  289. package/ios/app/dynamic-live-activity/VoltraDynamicLiveActivityService.swift +97 -0
  290. package/ios/app/dynamic-live-activity/VoltraLiveActivityChronology.swift +68 -0
  291. package/ios/shared/DynamicWidgetPropsCodec.swift +51 -0
  292. package/ios/shared/DynamicWidgetPropsStorage.swift +53 -0
  293. package/ios/shared/DynamicWidgetPropsStore.swift +117 -0
  294. package/ios/shared/DynamicWidgetRenderCoordinator.swift +31 -0
  295. package/ios/shared/DynamicWidgetServerUpdate/DynamicWidgetServerFetchResolver.swift +34 -0
  296. package/ios/shared/DynamicWidgetServerUpdate/DynamicWidgetServerProps.swift +55 -0
  297. package/ios/shared/DynamicWidgetServerUpdate/DynamicWidgetServerPropsStore.swift +146 -0
  298. package/ios/shared/DynamicWidgetServerUpdate/DynamicWidgetServerUpdateRunner.swift +193 -0
  299. package/ios/shared/DynamicWidgetUpdater.swift +30 -0
  300. package/ios/shared/ServerWidgetContentResolver.swift +60 -0
  301. package/ios/shared/ServerWidgetResponseStore.swift +25 -0
  302. package/ios/shared/ShortNames.swift +6 -0
  303. package/ios/shared/VoltraConfig.swift +41 -0
  304. package/ios/shared/VoltraConstants.swift +19 -0
  305. package/ios/shared/VoltraElement.swift +127 -43
  306. package/ios/shared/VoltraEventBus.swift +52 -7
  307. package/ios/shared/VoltraJSRenderer.swift +93 -23
  308. package/ios/shared/VoltraNode.swift +7 -111
  309. package/ios/shared/VoltraRefreshIntent.swift +1 -1
  310. package/ios/shared/VoltraWidgetDefaults.swift +9 -1
  311. package/ios/shared/VoltraWidgetKind.swift +41 -0
  312. package/ios/shared/VoltraWidgetServerFetcher.swift +52 -107
  313. package/ios/shared/WidgetServer/VoltraWidgetAppearance.swift +17 -0
  314. package/ios/shared/WidgetServer/VoltraWidgetServer.swift +138 -0
  315. package/ios/shared/WidgetServer/WidgetCanonicalConfiguration.swift +77 -0
  316. package/ios/shared/WidgetServer/WidgetScope.swift +55 -0
  317. package/ios/shared/WidgetServer/WidgetServerEtagStore.swift +55 -0
  318. package/ios/shared/WidgetServer/WidgetServerFetcher.swift +179 -0
  319. package/ios/shared/WidgetServer/WidgetServerRequestBuilder.swift +114 -0
  320. package/ios/shared/WidgetServer/WidgetServerSettingsCodec.swift +47 -0
  321. package/ios/shared/WidgetServer/WidgetServerSettingsResolver.swift +129 -0
  322. package/ios/shared/WidgetServer/WidgetServerSettingsStore.swift +170 -0
  323. package/ios/shared/WidgetServer/WidgetServerSettingsValidator.swift +73 -0
  324. package/ios/shared/WidgetServer/WidgetServerUpdateSettings.swift +123 -0
  325. package/ios/shared/WidgetServer/WidgetServerUpdateSettingsJson.swift +115 -0
  326. package/ios/shared/dynamic-live-activity/DynamicLiveActivityPropsCodec.swift +13 -0
  327. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityBundleSource.swift +156 -0
  328. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityObserver.swift +97 -0
  329. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityOperations.swift +105 -0
  330. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityPayloadValidator.swift +55 -0
  331. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityRegistry.swift +143 -0
  332. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityRenderFailureQueue.swift +158 -0
  333. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityRenderFailureReporter.swift +120 -0
  334. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityRenderer.swift +370 -0
  335. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityTypes.swift +87 -0
  336. package/ios/shared/dynamic-live-activity/VoltraLiveActivityOrder.swift +19 -0
  337. package/ios/target/VoltraClientWidgetRuntime.swift +60 -10
  338. package/ios/target/VoltraDynamicWidgetServerUpdateProvider.swift +204 -0
  339. package/ios/target/VoltraHomeWidget.swift +91 -92
  340. package/ios/target/VoltraWidget.swift +3 -1
  341. package/ios/ui/Extensions/VoltraNode+View.swift +113 -0
  342. package/ios/ui/Generated/Parameters/ChartParameters.swift +3 -0
  343. package/ios/ui/Helpers/VoltraDeepLinkResolver.swift +5 -3
  344. package/ios/ui/Helpers/VoltraProgressDriver.swift +6 -2
  345. package/ios/ui/Layout/VoltraFlexStackLayout.swift +9 -3
  346. package/ios/ui/Style/JSColorParser.swift +24 -8
  347. package/ios/ui/Style/JSGradientParser.swift +36 -12
  348. package/ios/ui/Style/JSStyleParser.swift +36 -12
  349. package/ios/ui/Style/LayoutStyle.swift +12 -4
  350. package/ios/ui/Views/VoltraChart.swift +160 -16
  351. package/ios/ui/Views/VoltraLinearGradient.swift +6 -2
  352. package/package.json +5 -5
  353. package/src/dynamic-widget/api.ts +25 -0
  354. package/src/events.ts +34 -0
  355. package/src/index.ts +23 -0
  356. package/src/live-activity/api.ts +2 -2
  357. package/src/live-activity/dynamic-api.ts +240 -0
  358. package/src/native/NativeVoltra.ts +22 -0
  359. package/src/types.ts +4 -0
  360. package/src/utils/enableDynamicLiveActivityHotReload.ts +50 -0
  361. package/src/utils/enableWidgetHotReload.ts +9 -16
  362. package/src/utils/useUpdateOnHMR.ts +3 -12
  363. package/src/widgets/server-credentials.ts +8 -0
  364. package/src/widgets/server-update.ts +84 -0
  365. /package/ios/shared/{VoltraKeychainHelper.swift → WidgetServer/VoltraKeychainHelper.swift} +0 -0
@@ -8,7 +8,9 @@ enum JSColorParser {
8
8
  // Optimize: standard trim and lowercase
9
9
  let trimmed = string.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
10
10
 
11
- if trimmed.isEmpty { return nil }
11
+ if trimmed.isEmpty {
12
+ return nil
13
+ }
12
14
 
13
15
  // 1. Hex (with or without #)
14
16
  if trimmed.hasPrefix("#") {
@@ -57,7 +59,9 @@ enum JSColorParser {
57
59
  guard let string = value as? String else { return nil }
58
60
 
59
61
  let trimmed = string.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
60
- if trimmed.isEmpty { return nil }
62
+ if trimmed.isEmpty {
63
+ return nil
64
+ }
61
65
 
62
66
  if trimmed.hasPrefix("#") {
63
67
  return parseHexComponents(trimmed)
@@ -477,7 +481,9 @@ enum JSColorParser {
477
481
 
478
482
  private static func normalizeUnit(_ value: Double) -> Double {
479
483
  var result = value.truncatingRemainder(dividingBy: 1)
480
- if result < 0 { result += 1 }
484
+ if result < 0 {
485
+ result += 1
486
+ }
481
487
  return result
482
488
  }
483
489
 
@@ -506,12 +512,22 @@ enum JSColorParser {
506
512
  /// Helper function for HSL to RGB conversion
507
513
  private static func hueToRgb(p: Double, q: Double, t: Double) -> Double {
508
514
  var t = t
509
- if t < 0 { t += 1 }
510
- if t > 1 { t -= 1 }
515
+ if t < 0 {
516
+ t += 1
517
+ }
518
+ if t > 1 {
519
+ t -= 1
520
+ }
511
521
 
512
- if t < 1.0 / 6.0 { return p + (q - p) * 6 * t }
513
- if t < 1.0 / 2.0 { return q }
514
- if t < 2.0 / 3.0 { return p + (q - p) * (2.0 / 3.0 - t) * 6 }
522
+ if t < 1.0 / 6.0 {
523
+ return p + (q - p) * 6 * t
524
+ }
525
+ if t < 1.0 / 2.0 {
526
+ return q
527
+ }
528
+ if t < 2.0 / 3.0 {
529
+ return p + (q - p) * (2.0 / 3.0 - t) * 6
530
+ }
515
531
  return p
516
532
  }
517
533
  }
@@ -200,12 +200,16 @@ enum JSGradientParser {
200
200
  depth += 1
201
201
  } else if char == ")" {
202
202
  depth -= 1
203
- if depth < 0 { return [] }
203
+ if depth < 0 {
204
+ return []
205
+ }
204
206
  }
205
207
 
206
208
  if char == ",", depth == 0 {
207
209
  let token = current.trimmingCharacters(in: .whitespacesAndNewlines)
208
- if token.isEmpty { return [] }
210
+ if token.isEmpty {
211
+ return []
212
+ }
209
213
  args.append(token)
210
214
  current = ""
211
215
  } else {
@@ -216,7 +220,9 @@ enum JSGradientParser {
216
220
  guard depth == 0 else { return [] }
217
221
 
218
222
  let token = current.trimmingCharacters(in: .whitespacesAndNewlines)
219
- if token.isEmpty { return [] }
223
+ if token.isEmpty {
224
+ return []
225
+ }
220
226
  args.append(token)
221
227
  return args
222
228
  }
@@ -231,7 +237,9 @@ enum JSGradientParser {
231
237
  depth += 1
232
238
  } else if char == ")" {
233
239
  depth -= 1
234
- if depth < 0 { return [] }
240
+ if depth < 0 {
241
+ return []
242
+ }
235
243
  }
236
244
 
237
245
  if char.isWhitespace, depth == 0 {
@@ -269,10 +277,14 @@ enum JSGradientParser {
269
277
  for word in words {
270
278
  switch word {
271
279
  case "left", "right":
272
- if horizontal != nil { return nil }
280
+ if horizontal != nil {
281
+ return nil
282
+ }
273
283
  horizontal = word
274
284
  case "top", "bottom":
275
- if vertical != nil { return nil }
285
+ if vertical != nil {
286
+ return nil
287
+ }
276
288
  vertical = word
277
289
  default:
278
290
  return nil
@@ -418,10 +430,14 @@ enum JSGradientParser {
418
430
  for token in tokens {
419
431
  switch token {
420
432
  case "left":
421
- if x != nil { return nil }
433
+ if x != nil {
434
+ return nil
435
+ }
422
436
  x = 0
423
437
  case "right":
424
- if x != nil { return nil }
438
+ if x != nil {
439
+ return nil
440
+ }
425
441
  x = 1
426
442
  case "center":
427
443
  if x == nil {
@@ -432,10 +448,14 @@ enum JSGradientParser {
432
448
  return nil
433
449
  }
434
450
  case "top":
435
- if y != nil { return nil }
451
+ if y != nil {
452
+ return nil
453
+ }
436
454
  y = 0
437
455
  case "bottom":
438
- if y != nil { return nil }
456
+ if y != nil {
457
+ return nil
458
+ }
439
459
  y = 1
440
460
  default:
441
461
  return nil
@@ -613,8 +633,12 @@ enum JSGradientParser {
613
633
  guard !stops.isEmpty else { return [] }
614
634
 
615
635
  var positions = stops.map(\.position)
616
- if positions.first == nil { positions[0] = 0 }
617
- if positions.last == nil { positions[positions.count - 1] = 1 }
636
+ if positions.first == nil {
637
+ positions[0] = 0
638
+ }
639
+ if positions.last == nil {
640
+ positions[positions.count - 1] = 1
641
+ }
618
642
 
619
643
  var lastDefined: Double?
620
644
  for idx in positions.indices {
@@ -2,16 +2,24 @@ import SwiftUI
2
2
 
3
3
  enum JSStyleParser {
4
4
  static func number(_ value: Any?) -> CGFloat? {
5
- if let v = value as? CGFloat { return v }
6
- if let v = value as? Double { return CGFloat(v) }
7
- if let v = value as? Int { return CGFloat(v) }
5
+ if let v = value as? CGFloat {
6
+ return v
7
+ }
8
+ if let v = value as? Double {
9
+ return CGFloat(v)
10
+ }
11
+ if let v = value as? Int {
12
+ return CGFloat(v)
13
+ }
8
14
  // Handle "20.5" strings if necessary, though rarer in raw JSON objects
9
15
  return nil
10
16
  }
11
17
 
12
18
  static func sizeValue(_ value: Any?) -> SizeValue? {
13
19
  // Numeric → Fixed
14
- if let n = number(value) { return .fixed(n) }
20
+ if let n = number(value) {
21
+ return .fixed(n)
22
+ }
15
23
  // String → Fill / Wrap / try numeric
16
24
  guard let str = value as? String else { return nil }
17
25
  switch str {
@@ -19,7 +27,9 @@ enum JSStyleParser {
19
27
  case "auto": return .wrap
20
28
  default:
21
29
  // Try parsing as numeric string
22
- if let n = Double(str) { return .fixed(CGFloat(n)) }
30
+ if let n = Double(str) {
31
+ return .fixed(CGFloat(n))
32
+ }
23
33
  return nil
24
34
  }
25
35
  }
@@ -50,8 +60,12 @@ enum JSStyleParser {
50
60
  static func boolean(_ value: Any?) -> Bool {
51
61
  guard let value = value else { return false }
52
62
 
53
- if let bool = value as? Bool { return bool }
54
- if let int = value as? Int { return int == 1 }
63
+ if let bool = value as? Bool {
64
+ return bool
65
+ }
66
+ if let int = value as? Int {
67
+ return int == 1
68
+ }
55
69
  if let string = value as? String {
56
70
  return string.lowercased() == "true"
57
71
  }
@@ -107,9 +121,15 @@ enum JSStyleParser {
107
121
  let hasUnderline = string.contains("underline")
108
122
  let hasLineThrough = string.contains("line-through") || string.contains("strikethrough")
109
123
 
110
- if hasUnderline, hasLineThrough { return .underlineLineThrough }
111
- if hasUnderline { return .underline }
112
- if hasLineThrough { return .lineThrough }
124
+ if hasUnderline, hasLineThrough {
125
+ return .underlineLineThrough
126
+ }
127
+ if hasUnderline {
128
+ return .underline
129
+ }
130
+ if hasLineThrough {
131
+ return .lineThrough
132
+ }
113
133
  return .none
114
134
  }
115
135
 
@@ -128,8 +148,12 @@ enum JSStyleParser {
128
148
  static func overflow(_ value: Any?) -> Overflow? {
129
149
  guard let string = (value as? String)?.lowercased() else { return nil }
130
150
 
131
- if string == "hidden" { return .hidden }
132
- if string == "visible" { return .visible }
151
+ if string == "hidden" {
152
+ return .hidden
153
+ }
154
+ if string == "visible" {
155
+ return .visible
156
+ }
133
157
  return nil
134
158
  }
135
159
 
@@ -112,15 +112,23 @@ struct LayoutModifier: ViewModifier {
112
112
 
113
113
  /// Derive effective ideal width: explicit width, then flexBasis, then nil
114
114
  private var effectiveIdealWidth: CGFloat? {
115
- if let w = widthValue { return w }
116
- if case let .fixed(v) = style.flexBasis { return v }
115
+ if let w = widthValue {
116
+ return w
117
+ }
118
+ if case let .fixed(v) = style.flexBasis {
119
+ return v
120
+ }
117
121
  return nil
118
122
  }
119
123
 
120
124
  /// Derive effective ideal height: explicit height, then flexBasis, then nil
121
125
  private var effectiveIdealHeight: CGFloat? {
122
- if let h = heightValue { return h }
123
- if case let .fixed(v) = style.flexBasis { return v }
126
+ if let h = heightValue {
127
+ return h
128
+ }
129
+ if case let .fixed(v) = style.flexBasis {
130
+ return v
131
+ }
124
132
  return nil
125
133
  }
126
134
 
@@ -49,7 +49,9 @@ public struct VoltraChart: VoltraView {
49
49
  }
50
50
 
51
51
  private func bool(_ v: JSONValue) -> Bool? {
52
- if case let .bool(value) = v { return value }
52
+ if case let .bool(value) = v {
53
+ return value
54
+ }
53
55
  return nil
54
56
  }
55
57
 
@@ -60,16 +62,22 @@ public struct VoltraChart: VoltraView {
60
62
  else { return nil }
61
63
 
62
64
  let props = dict.compactMapValues { jsonValue(from: $0) }
63
- if props.isEmpty { return nil }
65
+ if props.isEmpty {
66
+ return nil
67
+ }
64
68
 
65
69
  let visible = props["v"].flatMap(bool) ?? props["visible"].flatMap(bool)
66
70
  let color = (props["c"] ?? props["color"]).flatMap {
67
- if case let .string(value) = $0 { return JSColorParser.parse(value) }
71
+ if case let .string(value) = $0 {
72
+ return JSColorParser.parse(value)
73
+ }
68
74
  return nil
69
75
  }
70
76
  let lineWidth = (props["lw"] ?? props["lineWidth"]).flatMap(num).map { CGFloat($0) }
71
77
  let dash = ((props["d"] ?? props["dash"]).flatMap {
72
- if case let .array(values) = $0 { return values.compactMap(num).map { CGFloat($0) } }
78
+ if case let .array(values) = $0 {
79
+ return values.compactMap(num).map { CGFloat($0) }
80
+ }
73
81
  return nil
74
82
  })
75
83
 
@@ -140,7 +148,11 @@ public struct VoltraChart: VoltraView {
140
148
  default: return 0
141
149
  }
142
150
  }()
143
- let series: String? = pt.count >= 3 ? { if case let .string(s) = pt[2] { return s }; return nil }() : nil
151
+ let series: String? = pt.count >= 3 ? {
152
+ if case let .string(s) = pt[2] {
153
+ return s
154
+ }; return nil
155
+ }() : nil
144
156
  switch pt[0] {
145
157
  case let .string(x): return (x, nil, y, series)
146
158
  case let .double(x): return (nil, x, y, series)
@@ -149,6 +161,103 @@ public struct VoltraChart: VoltraView {
149
161
  }
150
162
  }
151
163
 
164
+ // MARK: - Y scale
165
+
166
+ /// Y-axis bounds pinned by the `yScale` prop; either side may be left to the data.
167
+ private struct YScale {
168
+ let min: Double?
169
+ let max: Double?
170
+ }
171
+
172
+ private func parseYScale(from raw: String?) -> YScale? {
173
+ guard let raw,
174
+ let data = raw.data(using: .utf8),
175
+ let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
176
+ else { return nil }
177
+
178
+ let props = dict.compactMapValues { jsonValue(from: $0) }
179
+ let min = (props["mn"] ?? props["min"]).flatMap(num)
180
+ let max = (props["mx"] ?? props["max"]).flatMap(num)
181
+ if min == nil, max == nil {
182
+ return nil
183
+ }
184
+ return YScale(min: min, max: max)
185
+ }
186
+
187
+ /// Domain to hand SwiftUI when `yScale` pins a bound. The open side follows the data exactly as
188
+ /// `computeYDomain` in Android's ChartBitmapRenderer.kt frames it, so both platforms agree.
189
+ private func yScaleDomain(_ marks: [WireMark], pinned: YScale) -> ClosedRange<Double> {
190
+ let auto = autoYDomain(marks)
191
+ var lower = pinned.min ?? auto.lowerBound
192
+ var upper = pinned.max ?? auto.upperBound
193
+
194
+ if upper <= lower {
195
+ // A pin that inverts the domain still has to leave something to draw in: keep the span the
196
+ // data asked for on the side the caller left open, and ignore a pair that cannot be drawn.
197
+ let span = auto.upperBound - auto.lowerBound
198
+ if pinned.max == nil {
199
+ upper = lower + span
200
+ } else if pinned.min == nil {
201
+ lower = upper - span
202
+ } else {
203
+ return auto
204
+ }
205
+ if upper <= lower {
206
+ upper = lower + 1
207
+ }
208
+ }
209
+
210
+ return lower ... upper
211
+ }
212
+
213
+ private func autoYDomain(_ marks: [WireMark]) -> ClosedRange<Double> {
214
+ var values = marks.flatMap { mark -> [Double] in
215
+ guard mark.type != "sector" else { return [] }
216
+ return (mark.data ?? []).map { xy($0).y }
217
+ }
218
+ values += marks.compactMap { $0.type == "rule" ? $0.props["yv"].flatMap(num) : nil }
219
+
220
+ let finite = values.filter(\.isFinite)
221
+ guard let dataMin = finite.min(), let dataMax = finite.max() else { return 0 ... 1 }
222
+
223
+ // Bars and areas measure their value against the baseline, so zero stays in range.
224
+ if marks.contains(where: { $0.type == "bar" || $0.type == "area" }) {
225
+ let lower = Swift.min(dataMin, 0)
226
+ let upper = Swift.max(dataMax, 0)
227
+ return upper > lower ? lower ... upper : lower ... (lower + 1)
228
+ }
229
+
230
+ guard dataMax > dataMin else {
231
+ let padding = dataMin == 0 ? 1 : abs(dataMin) * Self.yDomainPaddingRatio
232
+ return (dataMin - padding) ... (dataMax + padding)
233
+ }
234
+
235
+ let padding = (dataMax - dataMin) * Self.yDomainPaddingRatio
236
+ var lower = dataMin - padding
237
+ var upper = dataMax + padding
238
+
239
+ // Padding must not invent values on the other side of the baseline, and data that almost
240
+ // reaches zero keeps it in view.
241
+ if dataMin >= 0, lower < 0 {
242
+ lower = 0
243
+ }
244
+ if dataMax <= 0, upper > 0 {
245
+ upper = 0
246
+ }
247
+ let span = upper - lower
248
+ if lower > 0, lower < span * Self.zeroSnapRatio {
249
+ lower = 0
250
+ }
251
+ if upper < 0, -upper < span * Self.zeroSnapRatio {
252
+ upper = 0
253
+ }
254
+
255
+ return lower ... upper
256
+ }
257
+
258
+ private static let yDomainPaddingRatio = 0.1
259
+ private static let zeroSnapRatio = 0.25
260
+
152
261
  // MARK: - body
153
262
 
154
263
  public var body: some View {
@@ -159,10 +268,12 @@ public struct VoltraChart: VoltraView {
159
268
  let yAxisGridStyle = parseAxisGridStyle(from: params.yAxisGridStyle)
160
269
  let legendVis = visibility(params.legendVisibility)
161
270
  let legendItems = parseLegendItems(from: params.foregroundStyleScale)
271
+ let yDomain = parseYScale(from: params.yScale).map { yScaleDomain(wireMarks, pinned: $0) }
162
272
 
163
273
  Chart {
164
274
  buildAll(wireMarks)
165
275
  }
276
+ .applyChartYScale(domain: yDomain)
166
277
  .applyForegroundStyleScale(params.foregroundStyleScale)
167
278
  .applyChartStyle(
168
279
  element.style,
@@ -186,12 +297,24 @@ public struct VoltraChart: VoltraView {
186
297
 
187
298
  @ChartContentBuilder
188
299
  private func buildMark(_ m: WireMark) -> some ChartContent {
189
- if m.type == "bar" { barContent(m) }
190
- if m.type == "line" { lineContent(m) }
191
- if m.type == "area" { areaContent(m) }
192
- if m.type == "point" { pointContent(m) }
193
- if m.type == "rule" { ruleContent(m) }
194
- if #available(iOS 17.0, macOS 14.0, *), m.type == "sector" { sectorContent(m) }
300
+ if m.type == "bar" {
301
+ barContent(m)
302
+ }
303
+ if m.type == "line" {
304
+ lineContent(m)
305
+ }
306
+ if m.type == "area" {
307
+ areaContent(m)
308
+ }
309
+ if m.type == "point" {
310
+ pointContent(m)
311
+ }
312
+ if m.type == "rule" {
313
+ ruleContent(m)
314
+ }
315
+ if #available(iOS 17.0, macOS 14.0, *), m.type == "sector" {
316
+ sectorContent(m)
317
+ }
195
318
  }
196
319
 
197
320
  // MARK: Bar
@@ -208,10 +331,16 @@ public struct VoltraChart: VoltraView {
208
331
  let (xStr, xNum, y, series) = xy(pt)
209
332
  let cr: CGFloat? = props["cr"].flatMap(num).map { CGFloat($0) }
210
333
  let barWidth: MarkDimension = {
211
- if let v = props["w"].flatMap(num) { return .fixed(CGFloat(v)) }
334
+ if let v = props["w"].flatMap(num) {
335
+ return .fixed(CGFloat(v))
336
+ }
212
337
  return .automatic
213
338
  }()
214
- let grouped: Bool = { if case let .string(s)? = props["stk"] { return s == "grouped" }; return false }()
339
+ let grouped: Bool = {
340
+ if case let .string(s)? = props["stk"] {
341
+ return s == "grouped"
342
+ }; return false
343
+ }()
215
344
 
216
345
  if let x = xStr {
217
346
  if let series {
@@ -555,15 +684,21 @@ public struct VoltraChart: VoltraView {
555
684
  case let .string(category) = pt[1]
556
685
  {
557
686
  let inner: MarkDimension = {
558
- if let v = props["ir"].flatMap(num) { return .ratio(CGFloat(v)) }
687
+ if let v = props["ir"].flatMap(num) {
688
+ return .ratio(CGFloat(v))
689
+ }
559
690
  return .automatic
560
691
  }()
561
692
  let outer: MarkDimension = {
562
- if let v = props["or"].flatMap(num) { return .ratio(CGFloat(v)) }
693
+ if let v = props["or"].flatMap(num) {
694
+ return .ratio(CGFloat(v))
695
+ }
563
696
  return .automatic
564
697
  }()
565
698
  let inset: CGFloat = {
566
- if let v = props["agin"].flatMap(num) { return CGFloat(v) }
699
+ if let v = props["agin"].flatMap(num) {
700
+ return CGFloat(v)
701
+ }
567
702
  return 0
568
703
  }()
569
704
 
@@ -698,6 +833,15 @@ private extension View {
698
833
  }
699
834
  }
700
835
 
836
+ @ViewBuilder
837
+ func applyChartYScale(domain: ClosedRange<Double>?) -> some View {
838
+ if let domain {
839
+ chartYScale(domain: domain)
840
+ } else {
841
+ self
842
+ }
843
+ }
844
+
701
845
  @ViewBuilder
702
846
  func applyChartClipping(decoration: DecorationStyle, hasClipping: Bool) -> some View {
703
847
  if hasClipping {
@@ -57,12 +57,16 @@ public struct VoltraLinearGradient: VoltraView {
57
57
  }
58
58
  }
59
59
  }
60
- if !stops.isEmpty { return Gradient(stops: stops) }
60
+ if !stops.isEmpty {
61
+ return Gradient(stops: stops)
62
+ }
61
63
  }
62
64
  if let colorsStr = params.colors {
63
65
  let parts = colorsStr.split(separator: "|").map(String.init)
64
66
  let colors: [Color] = parts.compactMap { JSColorParser.parse($0) }
65
- if !colors.isEmpty { return Gradient(colors: colors) }
67
+ if !colors.isEmpty {
68
+ return Gradient(colors: colors)
69
+ }
66
70
  }
67
71
  // Fallback neutral gradient
68
72
  return Gradient(colors: [Color.black.opacity(0.25), Color.black.opacity(0.05)])
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@use-voltra/ios-client",
3
- "version": "2.1.1",
3
+ "version": "2.3.0",
4
4
  "description": "Client-only Voltra APIs for iOS",
5
5
  "main": "./build/commonjs/index.js",
6
6
  "module": "./build/module/index.js",
@@ -39,9 +39,9 @@
39
39
  "@expo/plist": "^0.3.5",
40
40
  "dedent": "^1.7.1",
41
41
  "xcode": "^3.0.1",
42
- "@use-voltra/expo-plugin": "^2.1.1",
43
- "@use-voltra/ios": "^2.1.1",
44
- "@use-voltra/compiler": "^2.1.1"
42
+ "@use-voltra/compiler": "^2.3.0",
43
+ "@use-voltra/ios": "^2.3.0",
44
+ "@use-voltra/expo-plugin": "^2.3.0"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "expo": "*",
@@ -125,7 +125,7 @@
125
125
  "format:swift:fix": "swiftformat ios",
126
126
  "lint": "oxlint src expo-plugin/src",
127
127
  "typecheck": "tsc -p tsconfig.typecheck.json --noEmit && tsc -p expo-plugin/tsconfig.typecheck.json --noEmit",
128
- "test": "jest --config expo-plugin/jest.config.js",
128
+ "test": "jest --config jest.dynamic-widget.config.js && jest --config expo-plugin/jest.config.js",
129
129
  "test:swift": "cd ios && swift test"
130
130
  }
131
131
  }
@@ -0,0 +1,25 @@
1
+ import { getNativeVoltra } from '../native/NativeVoltra.js'
2
+ import { assertRunningOnApple } from '../utils/assertRunningOnApple.js'
3
+
4
+ export type DynamicWidgetPropsValue =
5
+ | string
6
+ | number
7
+ | boolean
8
+ | null
9
+ | ReadonlyArray<DynamicWidgetPropsValue>
10
+ | Readonly<{ [dynamicWidgetPropName: string]: DynamicWidgetPropsValue }>
11
+
12
+ export type DynamicWidgetProps = Readonly<{
13
+ [dynamicWidgetPropName: string]: DynamicWidgetPropsValue
14
+ }>
15
+
16
+ export const updateDynamicWidget = async (
17
+ dynamicWidgetId: string,
18
+ dynamicWidgetProps: DynamicWidgetProps
19
+ ): Promise<void> => {
20
+ if (!assertRunningOnApple()) return Promise.resolve()
21
+
22
+ const dynamicWidgetPropsJson = JSON.stringify(dynamicWidgetProps)
23
+
24
+ return getNativeVoltra().updateDynamicWidget(dynamicWidgetId, dynamicWidgetPropsJson)
25
+ }
package/src/events.ts CHANGED
@@ -30,15 +30,28 @@ export type VoltraInteractionEvent = BasicVoltraEvent & {
30
30
  payload: string
31
31
  }
32
32
 
33
+ export type VoltraDynamicLiveActivityRenderFailedEvent = BasicVoltraEvent & {
34
+ type: 'dynamicLiveActivityRenderFailed'
35
+ activityName: string
36
+ definitionId: string
37
+ message: string
38
+ }
39
+
33
40
  const noopSubscription: EventSubscription = {
34
41
  remove: () => {},
35
42
  }
36
43
 
44
+ // Codegen EventEmitter subscriptions do not tell native code when their last
45
+ // JavaScript listener goes away. Keep this count at the public API boundary so
46
+ // the App Group queue is drained only while it can actually be delivered.
47
+ let dynamicRenderFailureListenerCount = 0
48
+
37
49
  export type VoltraEventMap = {
38
50
  activityTokenReceived: VoltraActivityTokenReceivedEvent
39
51
  activityPushToStartTokenReceived: VoltraActivityPushToStartTokenReceivedEvent
40
52
  stateChange: VoltraActivityUpdateEvent
41
53
  interaction: VoltraInteractionEvent
54
+ dynamicLiveActivityRenderFailed: VoltraDynamicLiveActivityRenderFailedEvent
42
55
  }
43
56
 
44
57
  export function addVoltraListener<K extends keyof VoltraEventMap>(
@@ -63,6 +76,27 @@ export function addVoltraListener<K extends keyof VoltraEventMap>(
63
76
  return voltraModule.onStateChanged(listener as (arg: VoltraActivityUpdateEvent) => void)
64
77
  case 'interaction':
65
78
  return voltraModule.onInteraction(listener as (arg: VoltraInteractionEvent) => void)
79
+ case 'dynamicLiveActivityRenderFailed':
80
+ const subscription = voltraModule.onDynamicLiveActivityRenderFailed(
81
+ listener as (arg: VoltraDynamicLiveActivityRenderFailedEvent) => void
82
+ )
83
+ dynamicRenderFailureListenerCount += 1
84
+ if (dynamicRenderFailureListenerCount === 1) {
85
+ voltraModule.setDynamicLiveActivityRenderFailureListenerActive(true)
86
+ }
87
+
88
+ let removed = false
89
+ return {
90
+ remove: () => {
91
+ if (removed) return
92
+ removed = true
93
+ subscription.remove()
94
+ dynamicRenderFailureListenerCount -= 1
95
+ if (dynamicRenderFailureListenerCount === 0) {
96
+ voltraModule.setDynamicLiveActivityRenderFailureListenerActive(false)
97
+ }
98
+ },
99
+ }
66
100
  default:
67
101
  console.warn(`[Voltra] Event '${event}' is not supported. Returning no-op subscription.`)
68
102
  return noopSubscription