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

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 (577) 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/ButtonParameters.swift +15 -0
  391. package/ios/ui/Generated/Parameters/ChartParameters.swift +33 -0
  392. package/ios/ui/Generated/Parameters/CircularProgressViewParameters.swift +59 -0
  393. package/ios/ui/Generated/Parameters/ComponentParameters.swift +12 -0
  394. package/ios/ui/Generated/Parameters/DividerParameters.swift +12 -0
  395. package/ios/ui/Generated/Parameters/GaugeParameters.swift +54 -0
  396. package/ios/ui/Generated/Parameters/GlassContainerParameters.swift +15 -0
  397. package/ios/ui/Generated/Parameters/GroupBoxParameters.swift +12 -0
  398. package/ios/ui/Generated/Parameters/HStackParameters.swift +34 -0
  399. package/ios/ui/Generated/Parameters/ImageParameters.swift +29 -0
  400. package/ios/ui/Generated/Parameters/LabelParameters.swift +18 -0
  401. package/ios/ui/Generated/Parameters/LinearGradientParameters.swift +27 -0
  402. package/ios/ui/Generated/Parameters/LinearProgressViewParameters.swift +64 -0
  403. package/ios/ui/Generated/Parameters/LinkParameters.swift +15 -0
  404. package/ios/ui/Generated/Parameters/MaskParameters.swift +12 -0
  405. package/ios/ui/Generated/Parameters/SpacerParameters.swift +15 -0
  406. package/ios/ui/Generated/Parameters/SymbolParameters.swift +59 -0
  407. package/ios/ui/Generated/Parameters/TextParameters.swift +18 -0
  408. package/ios/ui/Generated/Parameters/TimerParameters.swift +54 -0
  409. package/ios/ui/Generated/Parameters/ToggleParameters.swift +24 -0
  410. package/ios/ui/Generated/Parameters/VStackParameters.swift +34 -0
  411. package/ios/ui/Generated/Parameters/ViewParameters.swift +12 -0
  412. package/ios/ui/Generated/Parameters/ZStackParameters.swift +15 -0
  413. package/ios/ui/Helpers/VoltraDeepLinkResolver.swift +43 -0
  414. package/ios/ui/Helpers/VoltraProgressDriver.swift +52 -0
  415. package/ios/ui/Layout/FlexContainerHelper.swift +114 -0
  416. package/ios/ui/Layout/VoltraFlexStackLayout.swift +417 -0
  417. package/ios/ui/Protocols/VoltraView.swift +29 -0
  418. package/ios/ui/Style/BackgroundValue.swift +27 -0
  419. package/ios/ui/Style/CompositeStyle.swift +81 -0
  420. package/ios/ui/Style/DecorationStyle.swift +207 -0
  421. package/ios/ui/Style/FlexEnvironment.swift +35 -0
  422. package/ios/ui/Style/FontVariant.swift +4 -0
  423. package/ios/ui/Style/GlassEffect.swift +6 -0
  424. package/ios/ui/Style/JSColorParser.swift +517 -0
  425. package/ios/ui/Style/JSGradientParser.swift +674 -0
  426. package/ios/ui/Style/JSStyleParser.swift +223 -0
  427. package/ios/ui/Style/LayoutStyle.swift +184 -0
  428. package/ios/ui/Style/Overflow.swift +4 -0
  429. package/ios/ui/Style/RenderingStyle.swift +33 -0
  430. package/ios/ui/Style/StyleConverter.swift +202 -0
  431. package/ios/ui/Style/TextDecoration.swift +6 -0
  432. package/ios/ui/Style/TextStyle.swift +50 -0
  433. package/ios/ui/Style/View+applyStyle.swift +38 -0
  434. package/ios/ui/Views/VoltraButton.swift +57 -0
  435. package/ios/ui/Views/VoltraChart.swift +840 -0
  436. package/ios/ui/Views/VoltraCircularProgressView.swift +103 -0
  437. package/ios/ui/Views/VoltraDivider.swift +16 -0
  438. package/ios/ui/Views/VoltraFlexView.swift +33 -0
  439. package/ios/ui/Views/VoltraGauge.swift +65 -0
  440. package/ios/ui/Views/VoltraGlassContainer.swift +29 -0
  441. package/ios/ui/Views/VoltraGroupBox.swift +26 -0
  442. package/ios/ui/Views/VoltraHStack.swift +70 -0
  443. package/ios/ui/Views/VoltraImage.swift +109 -0
  444. package/ios/ui/Views/VoltraLabel.swift +24 -0
  445. package/ios/ui/Views/VoltraLinearGradient.swift +115 -0
  446. package/ios/ui/Views/VoltraLinearProgressView.swift +118 -0
  447. package/ios/ui/Views/VoltraLink.swift +25 -0
  448. package/ios/ui/Views/VoltraMask.swift +23 -0
  449. package/ios/ui/Views/VoltraSpacer.swift +16 -0
  450. package/ios/ui/Views/VoltraSymbol.swift +160 -0
  451. package/ios/ui/Views/VoltraText.swift +87 -0
  452. package/ios/ui/Views/VoltraTimer.swift +131 -0
  453. package/ios/ui/Views/VoltraToggle.swift +39 -0
  454. package/ios/ui/Views/VoltraVStack.swift +68 -0
  455. package/ios/ui/Views/VoltraZStack.swift +33 -0
  456. package/ios/ui/Voltra.swift +86 -0
  457. package/package.json +105 -19
  458. package/src/VoltraModule.ts +2 -0
  459. package/src/components/VoltraLiveActivityPreview.tsx +29 -0
  460. package/src/components/VoltraView.tsx +49 -0
  461. package/src/components/VoltraWidgetPreview.tsx +38 -0
  462. package/src/events.ts +70 -0
  463. package/src/helpers.ts +21 -0
  464. package/src/index.ts +52 -0
  465. package/src/live-activity/api.ts +224 -0
  466. package/src/logger.ts +35 -0
  467. package/src/native/NativeVoltra.ts +118 -0
  468. package/src/native/VoltraRNNativeComponent.ts +9 -0
  469. package/src/preload.ts +50 -0
  470. package/src/types.ts +12 -0
  471. package/src/utils/assertRunningOnApple.ts +10 -0
  472. package/src/utils/helpers.ts +1 -0
  473. package/src/utils/index.ts +2 -0
  474. package/src/utils/useUpdateOnHMR.ts +25 -0
  475. package/src/widgets/server-credentials.ts +16 -0
  476. package/src/widgets/widget-api.ts +65 -0
  477. package/build/cjs/VoltraModule.js +0 -6
  478. package/build/cjs/VoltraModule.js.map +0 -1
  479. package/build/cjs/components/VoltraLiveActivityPreview.js +0 -20
  480. package/build/cjs/components/VoltraLiveActivityPreview.js.map +0 -1
  481. package/build/cjs/components/VoltraView.js +0 -37
  482. package/build/cjs/components/VoltraView.js.map +0 -1
  483. package/build/cjs/components/VoltraWidgetPreview.js +0 -26
  484. package/build/cjs/components/VoltraWidgetPreview.js.map +0 -1
  485. package/build/cjs/events.js +0 -19
  486. package/build/cjs/events.js.map +0 -1
  487. package/build/cjs/helpers.js +0 -30
  488. package/build/cjs/helpers.js.map +0 -1
  489. package/build/cjs/index.js +0 -49
  490. package/build/cjs/index.js.map +0 -1
  491. package/build/cjs/live-activity/api.js +0 -158
  492. package/build/cjs/live-activity/api.js.map +0 -1
  493. package/build/cjs/logger.js +0 -36
  494. package/build/cjs/logger.js.map +0 -1
  495. package/build/cjs/preload.js +0 -54
  496. package/build/cjs/preload.js.map +0 -1
  497. package/build/cjs/utils/assertRunningOnApple.js +0 -13
  498. package/build/cjs/utils/assertRunningOnApple.js.map +0 -1
  499. package/build/cjs/utils/helpers.js +0 -7
  500. package/build/cjs/utils/helpers.js.map +0 -1
  501. package/build/cjs/utils/index.js +0 -19
  502. package/build/cjs/utils/index.js.map +0 -1
  503. package/build/cjs/utils/useUpdateOnHMR.js +0 -22
  504. package/build/cjs/utils/useUpdateOnHMR.js.map +0 -1
  505. package/build/cjs/widgets/server-credentials.js +0 -18
  506. package/build/cjs/widgets/server-credentials.js.map +0 -1
  507. package/build/cjs/widgets/widget-api.js +0 -59
  508. package/build/cjs/widgets/widget-api.js.map +0 -1
  509. package/build/esm/VoltraModule.js +0 -4
  510. package/build/esm/VoltraModule.js.map +0 -1
  511. package/build/esm/components/VoltraLiveActivityPreview.js +0 -17
  512. package/build/esm/components/VoltraLiveActivityPreview.js.map +0 -1
  513. package/build/esm/components/VoltraView.js +0 -34
  514. package/build/esm/components/VoltraView.js.map +0 -1
  515. package/build/esm/components/VoltraWidgetPreview.js +0 -23
  516. package/build/esm/components/VoltraWidgetPreview.js.map +0 -1
  517. package/build/esm/events.js +0 -13
  518. package/build/esm/events.js.map +0 -1
  519. package/build/esm/helpers.js +0 -23
  520. package/build/esm/helpers.js.map +0 -1
  521. package/build/esm/index.js +0 -10
  522. package/build/esm/index.js.map +0 -1
  523. package/build/esm/live-activity/api.js +0 -146
  524. package/build/esm/live-activity/api.js.map +0 -1
  525. package/build/esm/logger.js +0 -33
  526. package/build/esm/logger.js.map +0 -1
  527. package/build/esm/preload.js +0 -46
  528. package/build/esm/preload.js.map +0 -1
  529. package/build/esm/utils/assertRunningOnApple.js +0 -9
  530. package/build/esm/utils/assertRunningOnApple.js.map +0 -1
  531. package/build/esm/utils/helpers.js.map +0 -1
  532. package/build/esm/utils/index.js.map +0 -1
  533. package/build/esm/utils/useUpdateOnHMR.js +0 -18
  534. package/build/esm/utils/useUpdateOnHMR.js.map +0 -1
  535. package/build/esm/widgets/server-credentials.js +0 -11
  536. package/build/esm/widgets/server-credentials.js.map +0 -1
  537. package/build/esm/widgets/widget-api.js +0 -47
  538. package/build/esm/widgets/widget-api.js.map +0 -1
  539. package/build/types/VoltraModule.d.ts +0 -44
  540. package/build/types/VoltraModule.d.ts.map +0 -1
  541. package/build/types/components/VoltraLiveActivityPreview.d.ts.map +0 -1
  542. package/build/types/components/VoltraView.d.ts.map +0 -1
  543. package/build/types/components/VoltraWidgetPreview.d.ts.map +0 -1
  544. package/build/types/events.d.ts.map +0 -1
  545. package/build/types/helpers.d.ts.map +0 -1
  546. package/build/types/index.d.ts.map +0 -1
  547. package/build/types/live-activity/api.d.ts.map +0 -1
  548. package/build/types/logger.d.ts.map +0 -1
  549. package/build/types/preload.d.ts.map +0 -1
  550. package/build/types/types.d.ts.map +0 -1
  551. package/build/types/utils/assertRunningOnApple.d.ts.map +0 -1
  552. package/build/types/utils/helpers.d.ts.map +0 -1
  553. package/build/types/utils/index.d.ts.map +0 -1
  554. package/build/types/utils/useUpdateOnHMR.d.ts.map +0 -1
  555. package/build/types/widgets/server-credentials.d.ts.map +0 -1
  556. package/build/types/widgets/widget-api.d.ts.map +0 -1
  557. /package/build/{types → typescript/commonjs}/components/VoltraLiveActivityPreview.d.ts +0 -0
  558. /package/build/{types → typescript/commonjs}/components/VoltraView.d.ts +0 -0
  559. /package/build/{types → typescript/commonjs}/components/VoltraWidgetPreview.d.ts +0 -0
  560. /package/build/{types → typescript/commonjs}/events.d.ts +0 -0
  561. /package/build/{types → typescript/commonjs}/helpers.d.ts +0 -0
  562. /package/build/{types → typescript/commonjs}/live-activity/api.d.ts +0 -0
  563. /package/build/{types → typescript/commonjs}/logger.d.ts +0 -0
  564. /package/build/{types → typescript/commonjs}/preload.d.ts +0 -0
  565. /package/build/{types → typescript/commonjs}/types.d.ts +0 -0
  566. /package/build/{types → typescript/commonjs}/utils/assertRunningOnApple.d.ts +0 -0
  567. /package/build/{types → typescript/commonjs}/utils/helpers.d.ts +0 -0
  568. /package/build/{types → typescript/commonjs}/utils/index.d.ts +0 -0
  569. /package/build/{types → typescript/commonjs}/utils/useUpdateOnHMR.d.ts +0 -0
  570. /package/build/{types → typescript/commonjs}/widgets/server-credentials.d.ts +0 -0
  571. /package/build/{types → typescript/commonjs}/widgets/widget-api.d.ts +0 -0
  572. /package/{build → expo-plugin/build}/cjs/package.json +0 -0
  573. /package/{build → expo-plugin/build}/cjs/types.js +0 -0
  574. /package/{build → expo-plugin/build}/cjs/types.js.map +0 -0
  575. /package/{build → expo-plugin/build}/esm/package.json +0 -0
  576. /package/{build → expo-plugin/build}/esm/types.js +0 -0
  577. /package/{build → expo-plugin/build}/esm/types.js.map +0 -0
@@ -0,0 +1,840 @@
1
+ import Charts
2
+ import SwiftUI
3
+
4
+ @available(iOS 16.0, macOS 13.0, *)
5
+ public struct VoltraChart: VoltraView {
6
+ public typealias Parameters = ChartParameters
7
+
8
+ public let element: VoltraElement
9
+
10
+ public init(_ element: VoltraElement) {
11
+ self.element = element
12
+ }
13
+
14
+ // MARK: - Wire format
15
+
16
+ private struct WireMark {
17
+ let type: String
18
+ let data: [[JSONValue]]?
19
+ let props: [String: JSONValue]
20
+ }
21
+
22
+ private func parseMarks(from json: String) -> [WireMark] {
23
+ guard
24
+ let data = json.data(using: .utf8),
25
+ let outer = try? JSONSerialization.jsonObject(with: data) as? [[Any]]
26
+ else { return [] }
27
+
28
+ return outer.compactMap { row -> WireMark? in
29
+ guard row.count >= 3,
30
+ let type = row[0] as? String,
31
+ let rawProps = row[2] as? [String: Any]
32
+ else { return nil }
33
+
34
+ let pts: [[JSONValue]]? = (row[1] as? [[Any]])?.map { $0.compactMap { jsonValue(from: $0) } }
35
+ let props = rawProps.compactMapValues { jsonValue(from: $0) }
36
+ return WireMark(type: type, data: pts, props: props)
37
+ }
38
+ }
39
+
40
+ // MARK: - Helpers
41
+
42
+ /// Extract a Double from a JSONValue that may be .int or .double
43
+ private func num(_ v: JSONValue) -> Double? {
44
+ switch v {
45
+ case let .double(d): return d
46
+ case let .int(i): return Double(i)
47
+ default: return nil
48
+ }
49
+ }
50
+
51
+ private func bool(_ v: JSONValue) -> Bool? {
52
+ if case let .bool(value) = v { return value }
53
+ return nil
54
+ }
55
+
56
+ private func parseAxisGridStyle(from raw: String?) -> AxisGridStyle? {
57
+ guard let raw,
58
+ let data = raw.data(using: .utf8),
59
+ let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
60
+ else { return nil }
61
+
62
+ let props = dict.compactMapValues { jsonValue(from: $0) }
63
+ if props.isEmpty { return nil }
64
+
65
+ let visible = props["v"].flatMap(bool) ?? props["visible"].flatMap(bool)
66
+ let color = (props["c"] ?? props["color"]).flatMap {
67
+ if case let .string(value) = $0 { return JSColorParser.parse(value) }
68
+ return nil
69
+ }
70
+ let lineWidth = (props["lw"] ?? props["lineWidth"]).flatMap(num).map { CGFloat($0) }
71
+ let dash = ((props["d"] ?? props["dash"]).flatMap {
72
+ if case let .array(values) = $0 { return values.compactMap(num).map { CGFloat($0) } }
73
+ return nil
74
+ })
75
+
76
+ return AxisGridStyle(visible: visible, color: color, lineWidth: lineWidth, dash: dash)
77
+ }
78
+
79
+ private func wireColor(_ props: [String: JSONValue]) -> Color? {
80
+ guard case let .string(s)? = props["c"] else { return nil }
81
+ return JSColorParser.parse(s)
82
+ }
83
+
84
+ private func symbolShape(_ props: [String: JSONValue]) -> BasicChartSymbolShape? {
85
+ guard case let .string(s)? = props["sym"] else { return nil }
86
+ switch s {
87
+ case "circle": return .circle
88
+ case "square": return .square
89
+ case "triangle": return .triangle
90
+ case "diamond": return .diamond
91
+ case "pentagon": return .pentagon
92
+ case "cross": return .cross
93
+ case "plus": return .plus
94
+ case "asterisk": return .asterisk
95
+ default: return nil
96
+ }
97
+ }
98
+
99
+ private func interpolation(_ props: [String: JSONValue]) -> InterpolationMethod {
100
+ guard case let .string(s)? = props["itp"] else { return .linear }
101
+ switch s {
102
+ case "monotone": return .monotone
103
+ case "stepStart": return .stepStart
104
+ case "stepEnd": return .stepEnd
105
+ case "stepCenter": return .stepCenter
106
+ case "cardinal": return .cardinal
107
+ case "catmullRom": return .catmullRom
108
+ default: return .linear
109
+ }
110
+ }
111
+
112
+ private func visibility(_ raw: String?) -> Visibility {
113
+ switch raw {
114
+ case "visible": return .visible
115
+ case "hidden": return .hidden
116
+ default: return .automatic
117
+ }
118
+ }
119
+
120
+ private func parseLegendItems(from raw: String?) -> [ChartLegendItem] {
121
+ guard let raw,
122
+ let data = raw.data(using: .utf8),
123
+ let pairs = try? JSONSerialization.jsonObject(with: data) as? [[String]],
124
+ !pairs.isEmpty
125
+ else { return [] }
126
+
127
+ return pairs.compactMap { p -> ChartLegendItem? in
128
+ guard p.count >= 2, let color = JSColorParser.parse(p[1]) else { return nil }
129
+ return ChartLegendItem(label: p[0], swatch: color)
130
+ }
131
+ }
132
+
133
+ /// Unpack [x, y] or [x, y, series] tuples into typed values.
134
+ private func xy(_ pt: [JSONValue]) -> (xStr: String?, xNum: Double?, y: Double, series: String?) {
135
+ guard pt.count >= 2 else { return (nil, nil, 0, nil) }
136
+ let y: Double = {
137
+ switch pt[1] {
138
+ case let .double(v): return v
139
+ case let .int(v): return Double(v)
140
+ default: return 0
141
+ }
142
+ }()
143
+ let series: String? = pt.count >= 3 ? { if case let .string(s) = pt[2] { return s }; return nil }() : nil
144
+ switch pt[0] {
145
+ case let .string(x): return (x, nil, y, series)
146
+ case let .double(x): return (nil, x, y, series)
147
+ case let .int(x): return (nil, Double(x), y, series)
148
+ default: return (nil, nil, y, series)
149
+ }
150
+ }
151
+
152
+ // MARK: - body
153
+
154
+ public var body: some View {
155
+ let wireMarks = params.marks.flatMap { parseMarks(from: $0) } ?? []
156
+ let xAxisVis = visibility(params.xAxisVisibility)
157
+ let yAxisVis = visibility(params.yAxisVisibility)
158
+ let xAxisGridStyle = parseAxisGridStyle(from: params.xAxisGridStyle)
159
+ let yAxisGridStyle = parseAxisGridStyle(from: params.yAxisGridStyle)
160
+ let legendVis = visibility(params.legendVisibility)
161
+ let legendItems = parseLegendItems(from: params.foregroundStyleScale)
162
+
163
+ Chart {
164
+ buildAll(wireMarks)
165
+ }
166
+ .applyForegroundStyleScale(params.foregroundStyleScale)
167
+ .applyChartStyle(
168
+ element.style,
169
+ xAxisVisibility: xAxisVis,
170
+ yAxisVisibility: yAxisVis,
171
+ xAxisGridStyle: xAxisGridStyle,
172
+ yAxisGridStyle: yAxisGridStyle,
173
+ legendVisibility: legendVis,
174
+ legendItems: legendItems
175
+ )
176
+ }
177
+
178
+ // MARK: - ChartContent
179
+
180
+ @ChartContentBuilder
181
+ private func buildAll(_ marks: [WireMark]) -> some ChartContent {
182
+ ForEach(Array(marks.enumerated()), id: \.offset) { _, m in
183
+ buildMark(m)
184
+ }
185
+ }
186
+
187
+ @ChartContentBuilder
188
+ 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) }
195
+ }
196
+
197
+ // MARK: Bar
198
+
199
+ @ChartContentBuilder
200
+ private func barContent(_ m: WireMark) -> some ChartContent {
201
+ ForEach(Array((m.data ?? []).enumerated()), id: \.offset) { _, pt in
202
+ barPoint(pt, props: m.props)
203
+ }
204
+ }
205
+
206
+ @ChartContentBuilder
207
+ private func barPoint(_ pt: [JSONValue], props: [String: JSONValue]) -> some ChartContent {
208
+ let (xStr, xNum, y, series) = xy(pt)
209
+ let cr: CGFloat? = props["cr"].flatMap(num).map { CGFloat($0) }
210
+ let barWidth: MarkDimension = {
211
+ if let v = props["w"].flatMap(num) { return .fixed(CGFloat(v)) }
212
+ return .automatic
213
+ }()
214
+ let grouped: Bool = { if case let .string(s)? = props["stk"] { return s == "grouped" }; return false }()
215
+
216
+ if let x = xStr {
217
+ if let series {
218
+ if let cr {
219
+ if grouped {
220
+ Charts.BarMark(x: .value("x", x), y: .value("y", y), width: barWidth).cornerRadius(cr)
221
+ .foregroundStyle(by: .value("series", series))
222
+ .position(by: .value("series", series))
223
+ } else {
224
+ Charts.BarMark(x: .value("x", x), y: .value("y", y), width: barWidth).cornerRadius(cr)
225
+ .foregroundStyle(by: .value("series", series))
226
+ }
227
+ } else {
228
+ if grouped {
229
+ Charts.BarMark(x: .value("x", x), y: .value("y", y), width: barWidth)
230
+ .foregroundStyle(by: .value("series", series))
231
+ .position(by: .value("series", series))
232
+ } else {
233
+ Charts.BarMark(x: .value("x", x), y: .value("y", y), width: barWidth)
234
+ .foregroundStyle(by: .value("series", series))
235
+ }
236
+ }
237
+ } else if let c = wireColor(props) {
238
+ if let cr {
239
+ Charts.BarMark(x: .value("x", x), y: .value("y", y), width: barWidth).cornerRadius(cr).foregroundStyle(c)
240
+ } else {
241
+ Charts.BarMark(x: .value("x", x), y: .value("y", y), width: barWidth).foregroundStyle(c)
242
+ }
243
+ } else {
244
+ if let cr {
245
+ Charts.BarMark(x: .value("x", x), y: .value("y", y), width: barWidth).cornerRadius(cr)
246
+ } else {
247
+ Charts.BarMark(x: .value("x", x), y: .value("y", y), width: barWidth)
248
+ }
249
+ }
250
+ } else if let x = xNum {
251
+ if let series {
252
+ if let cr {
253
+ if grouped {
254
+ Charts.BarMark(x: .value("x", x), y: .value("y", y), width: barWidth).cornerRadius(cr)
255
+ .foregroundStyle(by: .value("series", series))
256
+ .position(by: .value("series", series))
257
+ } else {
258
+ Charts.BarMark(x: .value("x", x), y: .value("y", y), width: barWidth).cornerRadius(cr)
259
+ .foregroundStyle(by: .value("series", series))
260
+ }
261
+ } else {
262
+ if grouped {
263
+ Charts.BarMark(x: .value("x", x), y: .value("y", y), width: barWidth)
264
+ .foregroundStyle(by: .value("series", series))
265
+ .position(by: .value("series", series))
266
+ } else {
267
+ Charts.BarMark(x: .value("x", x), y: .value("y", y), width: barWidth)
268
+ .foregroundStyle(by: .value("series", series))
269
+ }
270
+ }
271
+ } else if let c = wireColor(props) {
272
+ if let cr {
273
+ Charts.BarMark(x: .value("x", x), y: .value("y", y), width: barWidth).cornerRadius(cr).foregroundStyle(c)
274
+ } else {
275
+ Charts.BarMark(x: .value("x", x), y: .value("y", y), width: barWidth).foregroundStyle(c)
276
+ }
277
+ } else {
278
+ if let cr {
279
+ Charts.BarMark(x: .value("x", x), y: .value("y", y), width: barWidth).cornerRadius(cr)
280
+ } else {
281
+ Charts.BarMark(x: .value("x", x), y: .value("y", y), width: barWidth)
282
+ }
283
+ }
284
+ }
285
+ }
286
+
287
+ // MARK: Line
288
+
289
+ @ChartContentBuilder
290
+ private func lineContent(_ m: WireMark) -> some ChartContent {
291
+ ForEach(Array((m.data ?? []).enumerated()), id: \.offset) { _, pt in
292
+ linePoint(pt, props: m.props)
293
+ }
294
+ }
295
+
296
+ @ChartContentBuilder
297
+ private func linePoint(_ pt: [JSONValue], props: [String: JSONValue]) -> some ChartContent {
298
+ let (xStr, xNum, y, series) = xy(pt)
299
+ let itp = interpolation(props)
300
+ let lw: CGFloat? = props["lw"].flatMap(num).map { CGFloat($0) }
301
+ let stroke: StrokeStyle? = lw.map { StrokeStyle(lineWidth: $0) }
302
+ let sym = symbolShape(props)
303
+
304
+ if let x = xStr {
305
+ if let series {
306
+ if let stroke, let sym {
307
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).lineStyle(stroke).symbol(sym).foregroundStyle(by: .value("series", series))
308
+ } else if let stroke {
309
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).lineStyle(stroke).foregroundStyle(by: .value("series", series))
310
+ } else if let sym {
311
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).symbol(sym).foregroundStyle(by: .value("series", series))
312
+ } else {
313
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).foregroundStyle(by: .value("series", series))
314
+ }
315
+ } else if let c = wireColor(props) {
316
+ if let stroke, let sym {
317
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).lineStyle(stroke).symbol(sym).foregroundStyle(c)
318
+ } else if let stroke {
319
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).lineStyle(stroke).foregroundStyle(c)
320
+ } else if let sym {
321
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).symbol(sym).foregroundStyle(c)
322
+ } else {
323
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).foregroundStyle(c)
324
+ }
325
+ } else {
326
+ if let stroke, let sym {
327
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).lineStyle(stroke).symbol(sym)
328
+ } else if let stroke {
329
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).lineStyle(stroke)
330
+ } else if let sym {
331
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).symbol(sym)
332
+ } else {
333
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp)
334
+ }
335
+ }
336
+ } else if let x = xNum {
337
+ if let series {
338
+ if let stroke, let sym {
339
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).lineStyle(stroke).symbol(sym).foregroundStyle(by: .value("series", series))
340
+ } else if let stroke {
341
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).lineStyle(stroke).foregroundStyle(by: .value("series", series))
342
+ } else if let sym {
343
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).symbol(sym).foregroundStyle(by: .value("series", series))
344
+ } else {
345
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).foregroundStyle(by: .value("series", series))
346
+ }
347
+ } else if let c = wireColor(props) {
348
+ if let stroke, let sym {
349
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).lineStyle(stroke).symbol(sym).foregroundStyle(c)
350
+ } else if let stroke {
351
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).lineStyle(stroke).foregroundStyle(c)
352
+ } else if let sym {
353
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).symbol(sym).foregroundStyle(c)
354
+ } else {
355
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).foregroundStyle(c)
356
+ }
357
+ } else {
358
+ if let stroke, let sym {
359
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).lineStyle(stroke).symbol(sym)
360
+ } else if let stroke {
361
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).lineStyle(stroke)
362
+ } else if let sym {
363
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp).symbol(sym)
364
+ } else {
365
+ Charts.LineMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp)
366
+ }
367
+ }
368
+ }
369
+ }
370
+
371
+ // MARK: Area
372
+
373
+ @ChartContentBuilder
374
+ private func areaContent(_ m: WireMark) -> some ChartContent {
375
+ ForEach(Array((m.data ?? []).enumerated()), id: \.offset) { _, pt in
376
+ areaPoint(pt, props: m.props)
377
+ }
378
+ }
379
+
380
+ @ChartContentBuilder
381
+ private func areaPoint(_ pt: [JSONValue], props: [String: JSONValue]) -> some ChartContent {
382
+ let (xStr, xNum, y, series) = xy(pt)
383
+ let itp = interpolation(props)
384
+
385
+ if let x = xStr {
386
+ if let series {
387
+ Charts.AreaMark(x: .value("x", x), y: .value("y", y))
388
+ .interpolationMethod(itp).foregroundStyle(by: .value("series", series))
389
+ } else if let c = wireColor(props) {
390
+ Charts.AreaMark(x: .value("x", x), y: .value("y", y))
391
+ .interpolationMethod(itp).foregroundStyle(c)
392
+ } else {
393
+ Charts.AreaMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp)
394
+ }
395
+ } else if let x = xNum {
396
+ if let series {
397
+ Charts.AreaMark(x: .value("x", x), y: .value("y", y))
398
+ .interpolationMethod(itp).foregroundStyle(by: .value("series", series))
399
+ } else if let c = wireColor(props) {
400
+ Charts.AreaMark(x: .value("x", x), y: .value("y", y))
401
+ .interpolationMethod(itp).foregroundStyle(c)
402
+ } else {
403
+ Charts.AreaMark(x: .value("x", x), y: .value("y", y)).interpolationMethod(itp)
404
+ }
405
+ }
406
+ }
407
+
408
+ // MARK: Point
409
+
410
+ @ChartContentBuilder
411
+ private func pointContent(_ m: WireMark) -> some ChartContent {
412
+ ForEach(Array((m.data ?? []).enumerated()), id: \.offset) { _, pt in
413
+ pointPoint(pt, props: m.props)
414
+ }
415
+ }
416
+
417
+ @ChartContentBuilder
418
+ private func pointPoint(_ pt: [JSONValue], props: [String: JSONValue]) -> some ChartContent {
419
+ let (xStr, xNum, y, series) = xy(pt)
420
+ let sym = symbolShape(props)
421
+ let symSize: CGFloat? = props["syms"].flatMap(num).map { CGFloat($0) }
422
+
423
+ if let x = xStr {
424
+ if let series {
425
+ if let sym, let symSize {
426
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).symbol(sym).symbolSize(symSize).foregroundStyle(by: .value("series", series))
427
+ } else if let sym {
428
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).symbol(sym).foregroundStyle(by: .value("series", series))
429
+ } else if let symSize {
430
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).symbolSize(symSize).foregroundStyle(by: .value("series", series))
431
+ } else {
432
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).foregroundStyle(by: .value("series", series))
433
+ }
434
+ } else if let c = wireColor(props) {
435
+ if let sym, let symSize {
436
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).symbol(sym).symbolSize(symSize).foregroundStyle(c)
437
+ } else if let sym {
438
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).symbol(sym).foregroundStyle(c)
439
+ } else if let symSize {
440
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).symbolSize(symSize).foregroundStyle(c)
441
+ } else {
442
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).foregroundStyle(c)
443
+ }
444
+ } else {
445
+ if let sym, let symSize {
446
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).symbol(sym).symbolSize(symSize)
447
+ } else if let sym {
448
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).symbol(sym)
449
+ } else if let symSize {
450
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).symbolSize(symSize)
451
+ } else {
452
+ Charts.PointMark(x: .value("x", x), y: .value("y", y))
453
+ }
454
+ }
455
+ } else if let x = xNum {
456
+ if let series {
457
+ if let sym, let symSize {
458
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).symbol(sym).symbolSize(symSize).foregroundStyle(by: .value("series", series))
459
+ } else if let sym {
460
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).symbol(sym).foregroundStyle(by: .value("series", series))
461
+ } else if let symSize {
462
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).symbolSize(symSize).foregroundStyle(by: .value("series", series))
463
+ } else {
464
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).foregroundStyle(by: .value("series", series))
465
+ }
466
+ } else if let c = wireColor(props) {
467
+ if let sym, let symSize {
468
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).symbol(sym).symbolSize(symSize).foregroundStyle(c)
469
+ } else if let sym {
470
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).symbol(sym).foregroundStyle(c)
471
+ } else if let symSize {
472
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).symbolSize(symSize).foregroundStyle(c)
473
+ } else {
474
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).foregroundStyle(c)
475
+ }
476
+ } else {
477
+ if let sym, let symSize {
478
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).symbol(sym).symbolSize(symSize)
479
+ } else if let sym {
480
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).symbol(sym)
481
+ } else if let symSize {
482
+ Charts.PointMark(x: .value("x", x), y: .value("y", y)).symbolSize(symSize)
483
+ } else {
484
+ Charts.PointMark(x: .value("x", x), y: .value("y", y))
485
+ }
486
+ }
487
+ }
488
+ }
489
+
490
+ // MARK: Rule
491
+
492
+ @ChartContentBuilder
493
+ private func ruleContent(_ m: WireMark) -> some ChartContent {
494
+ let props = m.props
495
+ let lw: CGFloat? = props["lw"].flatMap(num).map { CGFloat($0) }
496
+ let stroke: StrokeStyle? = lw.map { StrokeStyle(lineWidth: $0) }
497
+ let c = wireColor(props)
498
+
499
+ if let yv = props["yv"].flatMap(num) {
500
+ if let c {
501
+ if let stroke {
502
+ Charts.RuleMark(y: .value("y", yv)).lineStyle(stroke).foregroundStyle(c)
503
+ } else {
504
+ Charts.RuleMark(y: .value("y", yv)).foregroundStyle(c)
505
+ }
506
+ } else if let stroke {
507
+ Charts.RuleMark(y: .value("y", yv)).lineStyle(stroke)
508
+ } else {
509
+ Charts.RuleMark(y: .value("y", yv))
510
+ }
511
+ }
512
+
513
+ if case let .string(xv)? = props["xv"] {
514
+ if let c {
515
+ if let stroke {
516
+ Charts.RuleMark(x: .value("x", xv)).lineStyle(stroke).foregroundStyle(c)
517
+ } else {
518
+ Charts.RuleMark(x: .value("x", xv)).foregroundStyle(c)
519
+ }
520
+ } else if let stroke {
521
+ Charts.RuleMark(x: .value("x", xv)).lineStyle(stroke)
522
+ } else {
523
+ Charts.RuleMark(x: .value("x", xv))
524
+ }
525
+ } else if let xv = props["xv"].flatMap(num) {
526
+ if let c {
527
+ if let stroke {
528
+ Charts.RuleMark(x: .value("x", xv)).lineStyle(stroke).foregroundStyle(c)
529
+ } else {
530
+ Charts.RuleMark(x: .value("x", xv)).foregroundStyle(c)
531
+ }
532
+ } else if let stroke {
533
+ Charts.RuleMark(x: .value("x", xv)).lineStyle(stroke)
534
+ } else {
535
+ Charts.RuleMark(x: .value("x", xv))
536
+ }
537
+ }
538
+ }
539
+
540
+ // MARK: Sector (iOS 17+)
541
+
542
+ @available(iOS 17.0, macOS 14.0, *)
543
+ @ChartContentBuilder
544
+ private func sectorContent(_ m: WireMark) -> some ChartContent {
545
+ ForEach(Array((m.data ?? []).enumerated()), id: \.offset) { _, pt in
546
+ sectorPoint(pt, props: m.props)
547
+ }
548
+ }
549
+
550
+ @available(iOS 17.0, macOS 14.0, *)
551
+ @ChartContentBuilder
552
+ private func sectorPoint(_ pt: [JSONValue], props: [String: JSONValue]) -> some ChartContent {
553
+ if pt.count >= 2,
554
+ let value = num(pt[0]),
555
+ case let .string(category) = pt[1]
556
+ {
557
+ let inner: MarkDimension = {
558
+ if let v = props["ir"].flatMap(num) { return .ratio(CGFloat(v)) }
559
+ return .automatic
560
+ }()
561
+ let outer: MarkDimension = {
562
+ if let v = props["or"].flatMap(num) { return .ratio(CGFloat(v)) }
563
+ return .automatic
564
+ }()
565
+ let inset: CGFloat = {
566
+ if let v = props["agin"].flatMap(num) { return CGFloat(v) }
567
+ return 0
568
+ }()
569
+
570
+ if let c = wireColor(props) {
571
+ Charts.SectorMark(
572
+ angle: .value("value", value),
573
+ innerRadius: inner, outerRadius: outer, angularInset: inset
574
+ )
575
+ .foregroundStyle(c)
576
+ } else {
577
+ Charts.SectorMark(
578
+ angle: .value("value", value),
579
+ innerRadius: inner, outerRadius: outer, angularInset: inset
580
+ )
581
+ .foregroundStyle(by: .value("category", category))
582
+ }
583
+ }
584
+ }
585
+ }
586
+
587
+ // MARK: - Any → JSONValue bridge
588
+
589
+ //
590
+ // JSONSerialization.data(withJSONObject:) throws an ObjC NSException (not a Swift error)
591
+ // when the input is a top-level primitive (NSNumber, NSString, etc.), which try? cannot
592
+ // catch. We avoid it entirely by directly pattern-matching the already-parsed Any values.
593
+
594
+ private func jsonValue(from value: Any) -> JSONValue? {
595
+ switch value {
596
+ case is NSNull:
597
+ return .null
598
+ case let n as NSNumber:
599
+ // Distinguish Bool from numeric types (NSNumber encodes both)
600
+ if CFGetTypeID(n) == CFBooleanGetTypeID() {
601
+ return .bool(n.boolValue)
602
+ }
603
+ // Use integer when the value has no fractional part
604
+ let d = n.doubleValue
605
+ if d == d.rounded(), !d.isInfinite, let i = Int(exactly: d) {
606
+ return .int(i)
607
+ }
608
+ return .double(d)
609
+ case let s as String:
610
+ return .string(s)
611
+ case let arr as [Any]:
612
+ return .array(arr.compactMap { jsonValue(from: $0) })
613
+ case let dict as [String: Any]:
614
+ return .object(dict.compactMapValues { jsonValue(from: $0) })
615
+ default:
616
+ return nil
617
+ }
618
+ }
619
+
620
+ // MARK: - View helpers for chart-level modifiers
621
+
622
+ @available(iOS 16.0, macOS 13.0, *)
623
+ private struct ChartLegendItem: Identifiable {
624
+ let label: String
625
+ let swatch: Color
626
+ var id: String {
627
+ label
628
+ }
629
+ }
630
+
631
+ @available(iOS 16.0, macOS 13.0, *)
632
+ private struct AxisGridStyle {
633
+ let visible: Bool?
634
+ let color: Color?
635
+ let lineWidth: CGFloat?
636
+ let dash: [CGFloat]?
637
+ }
638
+
639
+ @available(iOS 16.0, macOS 13.0, *)
640
+ private extension View {
641
+ @ViewBuilder
642
+ func applyChartStyle(
643
+ _ optionalStyle: [String: JSONValue]?,
644
+ xAxisVisibility: Visibility,
645
+ yAxisVisibility: Visibility,
646
+ xAxisGridStyle: AxisGridStyle?,
647
+ yAxisGridStyle: AxisGridStyle?,
648
+ legendVisibility: Visibility,
649
+ legendItems: [ChartLegendItem]
650
+ ) -> some View {
651
+ if let optionalStyle {
652
+ let anyStyle = optionalStyle.mapValues { $0.toAny() }
653
+ let (layout, decoration, rendering, _) = StyleConverter.convert(anyStyle)
654
+
655
+ // For charts with borderRadius, defer clipping to AFTER insets.
656
+ // Otherwise the negative insets push content past the clip boundary.
657
+ let hasClipping = decoration.cornerRadius != nil || decoration.overflow == .hidden
658
+ let decorationForLayout: DecorationStyle = hasClipping
659
+ ? DecorationStyle(
660
+ backgroundColor: decoration.backgroundColor,
661
+ cornerRadius: nil,
662
+ border: decoration.border,
663
+ shadow: decoration.shadow,
664
+ glassEffect: decoration.glassEffect,
665
+ overflow: nil
666
+ )
667
+ : decoration
668
+
669
+ let styled = modifier(CompositeStyleModifier(
670
+ layout: layout,
671
+ decoration: decorationForLayout,
672
+ rendering: rendering,
673
+ contentAlignment: .topLeading
674
+ ))
675
+ if let color = JSColorParser.parse(anyStyle["color"]) {
676
+ styled
677
+ .applyChartXAxis(visibility: xAxisVisibility, labelColor: color, gridStyle: xAxisGridStyle)
678
+ .applyChartYAxis(visibility: yAxisVisibility, labelColor: color, gridStyle: yAxisGridStyle)
679
+ .applyChartLegend(visibility: legendVisibility, labelColor: color, items: legendItems)
680
+ .applyChartInsets(xAxisVisibility: xAxisVisibility, yAxisVisibility: yAxisVisibility)
681
+ .foregroundStyle(color)
682
+ .foregroundColor(color)
683
+ .tint(color)
684
+ .applyChartClipping(decoration: decoration, hasClipping: hasClipping)
685
+ } else {
686
+ styled
687
+ .applyChartXAxis(visibility: xAxisVisibility, labelColor: nil, gridStyle: xAxisGridStyle)
688
+ .applyChartYAxis(visibility: yAxisVisibility, labelColor: nil, gridStyle: yAxisGridStyle)
689
+ .applyChartLegend(visibility: legendVisibility, labelColor: nil, items: legendItems)
690
+ .applyChartInsets(xAxisVisibility: xAxisVisibility, yAxisVisibility: yAxisVisibility)
691
+ .applyChartClipping(decoration: decoration, hasClipping: hasClipping)
692
+ }
693
+ } else {
694
+ applyChartXAxis(visibility: xAxisVisibility, labelColor: nil, gridStyle: xAxisGridStyle)
695
+ .applyChartYAxis(visibility: yAxisVisibility, labelColor: nil, gridStyle: yAxisGridStyle)
696
+ .applyChartLegend(visibility: legendVisibility, labelColor: nil, items: legendItems)
697
+ .applyChartInsets(xAxisVisibility: xAxisVisibility, yAxisVisibility: yAxisVisibility)
698
+ }
699
+ }
700
+
701
+ @ViewBuilder
702
+ func applyChartClipping(decoration: DecorationStyle, hasClipping: Bool) -> some View {
703
+ if hasClipping {
704
+ voltraIfLet(decoration.cornerRadius) { view, radius in
705
+ view.cornerRadius(radius)
706
+ }
707
+ .voltraIf(decoration.overflow == .hidden) { view in
708
+ view.clipped()
709
+ }
710
+ } else {
711
+ self
712
+ }
713
+ }
714
+
715
+ func applyChartInsets(xAxisVisibility: Visibility, yAxisVisibility: Visibility) -> some View {
716
+ let leading: CGFloat = yAxisVisibility == .hidden ? -8 : 10
717
+ let trailing: CGFloat = yAxisVisibility == .hidden ? -8 : 0
718
+ let top: CGFloat = xAxisVisibility == .hidden ? -8 : (yAxisVisibility == .hidden ? 0 : 8)
719
+ let bottom: CGFloat = xAxisVisibility == .hidden ? -8 : 0
720
+ return padding(.init(top: top, leading: leading, bottom: bottom, trailing: trailing))
721
+ }
722
+
723
+ @ViewBuilder
724
+ func applyChartLegend(visibility: Visibility, labelColor: Color?, items: [ChartLegendItem]) -> some View {
725
+ if visibility == .hidden {
726
+ chartLegend(.hidden)
727
+ } else {
728
+ chartLegend(position: .automatic, alignment: .center, spacing: 8) {
729
+ HStack(spacing: 12) {
730
+ ForEach(items) { item in
731
+ HStack(spacing: 6) {
732
+ Circle()
733
+ .fill(item.swatch)
734
+ .frame(width: 8, height: 8)
735
+ Text(item.label)
736
+ .foregroundStyle(labelColor ?? .primary)
737
+ }
738
+ }
739
+ }
740
+ }
741
+ .chartLegend(visibility)
742
+ }
743
+ }
744
+
745
+ func axisGridStrokeStyle(_ gridStyle: AxisGridStyle?) -> StrokeStyle? {
746
+ guard let gridStyle else { return nil }
747
+ guard gridStyle.lineWidth != nil || (gridStyle.dash?.isEmpty == false) else { return nil }
748
+ return StrokeStyle(lineWidth: gridStyle.lineWidth ?? 1, dash: gridStyle.dash ?? [])
749
+ }
750
+
751
+ @ViewBuilder
752
+ func applyChartXAxis(visibility: Visibility, labelColor: Color?, gridStyle: AxisGridStyle?) -> some View {
753
+ if visibility == .hidden {
754
+ chartXAxis(.hidden)
755
+ } else if gridStyle == nil, labelColor == nil {
756
+ chartXAxis(visibility)
757
+ } else {
758
+ chartXAxis {
759
+ AxisMarks {
760
+ if gridStyle?.visible != false {
761
+ if let stroke = axisGridStrokeStyle(gridStyle) {
762
+ if let color = gridStyle?.color {
763
+ AxisGridLine(stroke: stroke).foregroundStyle(color)
764
+ } else {
765
+ AxisGridLine(stroke: stroke)
766
+ }
767
+ } else if let color = gridStyle?.color {
768
+ AxisGridLine().foregroundStyle(color)
769
+ } else {
770
+ AxisGridLine()
771
+ }
772
+ }
773
+ AxisTick()
774
+ if let labelColor {
775
+ AxisValueLabel()
776
+ .foregroundStyle(labelColor)
777
+ } else {
778
+ AxisValueLabel()
779
+ }
780
+ }
781
+ }
782
+ }
783
+ }
784
+
785
+ @ViewBuilder
786
+ func applyChartYAxis(visibility: Visibility, labelColor: Color?, gridStyle: AxisGridStyle?) -> some View {
787
+ if visibility == .hidden {
788
+ chartYAxis(.hidden)
789
+ } else if visibility != .visible, gridStyle == nil, labelColor == nil {
790
+ chartYAxis(visibility)
791
+ } else {
792
+ chartYAxis {
793
+ AxisMarks(position: .leading) {
794
+ if gridStyle?.visible != false {
795
+ if let stroke = axisGridStrokeStyle(gridStyle) {
796
+ if let color = gridStyle?.color {
797
+ AxisGridLine(stroke: stroke).foregroundStyle(color)
798
+ } else {
799
+ AxisGridLine(stroke: stroke)
800
+ }
801
+ } else if let color = gridStyle?.color {
802
+ AxisGridLine().foregroundStyle(color)
803
+ } else {
804
+ AxisGridLine()
805
+ }
806
+ }
807
+ AxisTick()
808
+ if let labelColor {
809
+ AxisValueLabel()
810
+ .foregroundStyle(labelColor)
811
+ } else {
812
+ AxisValueLabel()
813
+ }
814
+ }
815
+ }
816
+ }
817
+ }
818
+
819
+ @ViewBuilder
820
+ func applyForegroundStyleScale(_ raw: String?) -> some View {
821
+ if let raw,
822
+ let data = raw.data(using: .utf8),
823
+ let pairs = try? JSONSerialization.jsonObject(with: data) as? [[String]],
824
+ !pairs.isEmpty
825
+ {
826
+ let domain = pairs.compactMap(\.first)
827
+ let range: [Color] = pairs.compactMap { p -> Color? in
828
+ guard p.count >= 2 else { return nil }
829
+ return JSColorParser.parse(p[1])
830
+ }
831
+ if domain.count == range.count {
832
+ chartForegroundStyleScale(domain: domain, range: range)
833
+ } else {
834
+ self
835
+ }
836
+ } else {
837
+ self
838
+ }
839
+ }
840
+ }