minerva-design 1.1.0 → 1.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 (385) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/charts/canvas.d.cts +10 -0
  3. package/dist/charts/canvas.d.ts +10 -0
  4. package/dist/charts/core.cjs +1 -1
  5. package/dist/charts/core.d.cts +8 -1
  6. package/dist/charts/core.d.ts +8 -1
  7. package/dist/charts/core.js +6 -1
  8. package/dist/charts/engine/canvas.cjs +2 -0
  9. package/dist/charts/engine/canvas.cjs.map +1 -0
  10. package/dist/charts/engine/canvas.d.cts +85 -0
  11. package/dist/charts/engine/canvas.d.ts +85 -0
  12. package/dist/charts/engine/canvas.js +177 -0
  13. package/dist/charts/engine/canvas.js.map +1 -0
  14. package/dist/charts/engine/chart.cjs +1 -2
  15. package/dist/charts/engine/chart.cjs.map +1 -1
  16. package/dist/charts/engine/chart.js +450 -489
  17. package/dist/charts/engine/chart.js.map +1 -1
  18. package/dist/charts/engine/color.cjs +1 -1
  19. package/dist/charts/engine/color.cjs.map +1 -1
  20. package/dist/charts/engine/color.d.cts +27 -0
  21. package/dist/charts/engine/color.d.ts +27 -0
  22. package/dist/charts/engine/color.js +100 -4
  23. package/dist/charts/engine/color.js.map +1 -1
  24. package/dist/charts/engine/controller.cjs +3 -0
  25. package/dist/charts/engine/controller.cjs.map +1 -0
  26. package/dist/charts/engine/controller.d.cts +188 -0
  27. package/dist/charts/engine/controller.d.ts +188 -0
  28. package/dist/charts/engine/controller.js +592 -0
  29. package/dist/charts/engine/controller.js.map +1 -0
  30. package/dist/charts/engine/curve.cjs +2 -0
  31. package/dist/charts/engine/curve.cjs.map +1 -0
  32. package/dist/charts/engine/curve.d.cts +15 -0
  33. package/dist/charts/engine/curve.d.ts +15 -0
  34. package/dist/charts/engine/curve.js +56 -0
  35. package/dist/charts/engine/curve.js.map +1 -0
  36. package/dist/charts/engine/data.cjs +1 -1
  37. package/dist/charts/engine/data.cjs.map +1 -1
  38. package/dist/charts/engine/data.d.cts +15 -2
  39. package/dist/charts/engine/data.d.ts +15 -2
  40. package/dist/charts/engine/data.js +98 -38
  41. package/dist/charts/engine/data.js.map +1 -1
  42. package/dist/charts/engine/dom.cjs +1 -1
  43. package/dist/charts/engine/dom.cjs.map +1 -1
  44. package/dist/charts/engine/dom.d.cts +5 -3
  45. package/dist/charts/engine/dom.d.ts +5 -3
  46. package/dist/charts/engine/dom.js +27 -22
  47. package/dist/charts/engine/dom.js.map +1 -1
  48. package/dist/charts/engine/items.cjs +1 -1
  49. package/dist/charts/engine/items.cjs.map +1 -1
  50. package/dist/charts/engine/items.js +132 -61
  51. package/dist/charts/engine/items.js.map +1 -1
  52. package/dist/charts/engine/model.cjs +1 -1
  53. package/dist/charts/engine/model.cjs.map +1 -1
  54. package/dist/charts/engine/model.d.cts +32 -5
  55. package/dist/charts/engine/model.d.ts +32 -5
  56. package/dist/charts/engine/model.js +226 -109
  57. package/dist/charts/engine/model.js.map +1 -1
  58. package/dist/charts/engine/overlay.cjs +1 -1
  59. package/dist/charts/engine/overlay.cjs.map +1 -1
  60. package/dist/charts/engine/overlay.d.cts +19 -1
  61. package/dist/charts/engine/overlay.d.ts +19 -1
  62. package/dist/charts/engine/overlay.js +77 -63
  63. package/dist/charts/engine/overlay.js.map +1 -1
  64. package/dist/charts/engine/presets.cjs +3 -0
  65. package/dist/charts/engine/presets.cjs.map +1 -0
  66. package/dist/charts/engine/presets.d.cts +169 -0
  67. package/dist/charts/engine/presets.d.ts +169 -0
  68. package/dist/charts/engine/presets.js +240 -0
  69. package/dist/charts/engine/presets.js.map +1 -0
  70. package/dist/charts/engine/renderers/canvas2d.cjs +1 -1
  71. package/dist/charts/engine/renderers/canvas2d.cjs.map +1 -1
  72. package/dist/charts/engine/renderers/canvas2d.d.cts +17 -1
  73. package/dist/charts/engine/renderers/canvas2d.d.ts +17 -1
  74. package/dist/charts/engine/renderers/canvas2d.js +176 -101
  75. package/dist/charts/engine/renderers/canvas2d.js.map +1 -1
  76. package/dist/charts/engine/renderers/range.cjs +1 -1
  77. package/dist/charts/engine/renderers/range.cjs.map +1 -1
  78. package/dist/charts/engine/renderers/range.js +4 -4
  79. package/dist/charts/engine/renderers/range.js.map +1 -1
  80. package/dist/charts/engine/renderers/shaders.cjs +37 -19
  81. package/dist/charts/engine/renderers/shaders.cjs.map +1 -1
  82. package/dist/charts/engine/renderers/shaders.d.cts +2 -2
  83. package/dist/charts/engine/renderers/shaders.d.ts +2 -2
  84. package/dist/charts/engine/renderers/shaders.js +37 -19
  85. package/dist/charts/engine/renderers/shaders.js.map +1 -1
  86. package/dist/charts/engine/renderers/types.cjs.map +1 -1
  87. package/dist/charts/engine/renderers/types.d.cts +11 -4
  88. package/dist/charts/engine/renderers/types.d.ts +11 -4
  89. package/dist/charts/engine/renderers/types.js.map +1 -1
  90. package/dist/charts/engine/renderers/webgl2.cjs +1 -1
  91. package/dist/charts/engine/renderers/webgl2.cjs.map +1 -1
  92. package/dist/charts/engine/renderers/webgl2.js +33 -12
  93. package/dist/charts/engine/renderers/webgl2.js.map +1 -1
  94. package/dist/charts/engine/renderers/webgpu.cjs +1 -1
  95. package/dist/charts/engine/renderers/webgpu.cjs.map +1 -1
  96. package/dist/charts/engine/renderers/webgpu.js +18 -15
  97. package/dist/charts/engine/renderers/webgpu.js.map +1 -1
  98. package/dist/charts/engine/scene.cjs +2 -0
  99. package/dist/charts/engine/scene.cjs.map +1 -0
  100. package/dist/charts/engine/scene.d.cts +102 -0
  101. package/dist/charts/engine/scene.d.ts +102 -0
  102. package/dist/charts/engine/scene.js +353 -0
  103. package/dist/charts/engine/scene.js.map +1 -0
  104. package/dist/charts/engine/shapes/canvas.cjs +2 -0
  105. package/dist/charts/engine/shapes/canvas.cjs.map +1 -0
  106. package/dist/charts/engine/shapes/canvas.d.cts +58 -0
  107. package/dist/charts/engine/shapes/canvas.d.ts +58 -0
  108. package/dist/charts/engine/shapes/canvas.js +159 -0
  109. package/dist/charts/engine/shapes/canvas.js.map +1 -0
  110. package/dist/charts/engine/shapes/chart.cjs +2 -0
  111. package/dist/charts/engine/shapes/chart.cjs.map +1 -0
  112. package/dist/charts/engine/shapes/chart.d.cts +6 -0
  113. package/dist/charts/engine/shapes/chart.d.ts +6 -0
  114. package/dist/charts/engine/shapes/chart.js +273 -0
  115. package/dist/charts/engine/shapes/chart.js.map +1 -0
  116. package/dist/charts/engine/shapes/draw.cjs +2 -0
  117. package/dist/charts/engine/shapes/draw.cjs.map +1 -0
  118. package/dist/charts/engine/shapes/draw.d.cts +20 -0
  119. package/dist/charts/engine/shapes/draw.d.ts +20 -0
  120. package/dist/charts/engine/shapes/draw.js +152 -0
  121. package/dist/charts/engine/shapes/draw.js.map +1 -0
  122. package/dist/charts/engine/shapes/funnel.cjs +2 -0
  123. package/dist/charts/engine/shapes/funnel.cjs.map +1 -0
  124. package/dist/charts/engine/shapes/funnel.d.cts +6 -0
  125. package/dist/charts/engine/shapes/funnel.d.ts +6 -0
  126. package/dist/charts/engine/shapes/funnel.js +149 -0
  127. package/dist/charts/engine/shapes/funnel.js.map +1 -0
  128. package/dist/charts/engine/shapes/gauge.cjs +2 -0
  129. package/dist/charts/engine/shapes/gauge.cjs.map +1 -0
  130. package/dist/charts/engine/shapes/gauge.d.cts +7 -0
  131. package/dist/charts/engine/shapes/gauge.d.ts +7 -0
  132. package/dist/charts/engine/shapes/gauge.js +173 -0
  133. package/dist/charts/engine/shapes/gauge.js.map +1 -0
  134. package/dist/charts/engine/shapes/hit.cjs +2 -0
  135. package/dist/charts/engine/shapes/hit.cjs.map +1 -0
  136. package/dist/charts/engine/shapes/hit.d.cts +28 -0
  137. package/dist/charts/engine/shapes/hit.d.ts +28 -0
  138. package/dist/charts/engine/shapes/hit.js +124 -0
  139. package/dist/charts/engine/shapes/hit.js.map +1 -0
  140. package/dist/charts/engine/shapes/index.d.cts +9 -0
  141. package/dist/charts/engine/shapes/index.d.ts +9 -0
  142. package/dist/charts/engine/shapes/layout.cjs +3 -0
  143. package/dist/charts/engine/shapes/layout.cjs.map +1 -0
  144. package/dist/charts/engine/shapes/layout.d.cts +88 -0
  145. package/dist/charts/engine/shapes/layout.d.ts +88 -0
  146. package/dist/charts/engine/shapes/layout.js +266 -0
  147. package/dist/charts/engine/shapes/layout.js.map +1 -0
  148. package/dist/charts/engine/shapes/pie.cjs +2 -0
  149. package/dist/charts/engine/shapes/pie.cjs.map +1 -0
  150. package/dist/charts/engine/shapes/pie.d.cts +20 -0
  151. package/dist/charts/engine/shapes/pie.d.ts +20 -0
  152. package/dist/charts/engine/shapes/pie.js +302 -0
  153. package/dist/charts/engine/shapes/pie.js.map +1 -0
  154. package/dist/charts/engine/shapes/radar.cjs +2 -0
  155. package/dist/charts/engine/shapes/radar.cjs.map +1 -0
  156. package/dist/charts/engine/shapes/radar.d.cts +8 -0
  157. package/dist/charts/engine/shapes/radar.d.ts +8 -0
  158. package/dist/charts/engine/shapes/radar.js +197 -0
  159. package/dist/charts/engine/shapes/radar.js.map +1 -0
  160. package/dist/charts/engine/shapes/runtime.cjs +2 -0
  161. package/dist/charts/engine/shapes/runtime.cjs.map +1 -0
  162. package/dist/charts/engine/shapes/runtime.d.cts +29 -0
  163. package/dist/charts/engine/shapes/runtime.d.ts +29 -0
  164. package/dist/charts/engine/shapes/runtime.js +97 -0
  165. package/dist/charts/engine/shapes/runtime.js.map +1 -0
  166. package/dist/charts/engine/shapes/scene.cjs +2 -0
  167. package/dist/charts/engine/shapes/scene.cjs.map +1 -0
  168. package/dist/charts/engine/shapes/scene.d.cts +257 -0
  169. package/dist/charts/engine/shapes/scene.d.ts +257 -0
  170. package/dist/charts/engine/shapes/scene.js +123 -0
  171. package/dist/charts/engine/shapes/scene.js.map +1 -0
  172. package/dist/charts/engine/shapes/treemap.cjs +2 -0
  173. package/dist/charts/engine/shapes/treemap.cjs.map +1 -0
  174. package/dist/charts/engine/shapes/treemap.d.cts +14 -0
  175. package/dist/charts/engine/shapes/treemap.d.ts +14 -0
  176. package/dist/charts/engine/shapes/treemap.js +213 -0
  177. package/dist/charts/engine/shapes/treemap.js.map +1 -0
  178. package/dist/charts/engine/shapes/types.d.cts +292 -0
  179. package/dist/charts/engine/shapes/types.d.ts +292 -0
  180. package/dist/charts/engine/signature.cjs +2 -0
  181. package/dist/charts/engine/signature.cjs.map +1 -0
  182. package/dist/charts/engine/signature.d.cts +9 -0
  183. package/dist/charts/engine/signature.d.ts +9 -0
  184. package/dist/charts/engine/signature.js +13 -0
  185. package/dist/charts/engine/signature.js.map +1 -0
  186. package/dist/charts/engine/theme.cjs +1 -1
  187. package/dist/charts/engine/theme.cjs.map +1 -1
  188. package/dist/charts/engine/theme.d.cts +35 -2
  189. package/dist/charts/engine/theme.d.ts +35 -2
  190. package/dist/charts/engine/theme.js +66 -26
  191. package/dist/charts/engine/theme.js.map +1 -1
  192. package/dist/charts/engine/types.d.cts +139 -11
  193. package/dist/charts/engine/types.d.ts +139 -11
  194. package/dist/charts/index.cjs +1 -1
  195. package/dist/charts/index.d.cts +4 -2
  196. package/dist/charts/index.d.ts +4 -2
  197. package/dist/charts/index.js +8 -2
  198. package/dist/charts/react/Chart.cjs +1 -1
  199. package/dist/charts/react/Chart.cjs.map +1 -1
  200. package/dist/charts/react/Chart.d.cts +18 -4
  201. package/dist/charts/react/Chart.d.ts +18 -4
  202. package/dist/charts/react/Chart.js +102 -41
  203. package/dist/charts/react/Chart.js.map +1 -1
  204. package/dist/charts/react/charts.cjs +1 -1
  205. package/dist/charts/react/charts.cjs.map +1 -1
  206. package/dist/charts/react/charts.d.cts +11 -3
  207. package/dist/charts/react/charts.d.ts +11 -3
  208. package/dist/charts/react/charts.js +221 -144
  209. package/dist/charts/react/charts.js.map +1 -1
  210. package/dist/charts/react/shapes.cjs +2 -0
  211. package/dist/charts/react/shapes.cjs.map +1 -0
  212. package/dist/charts/react/shapes.d.cts +255 -0
  213. package/dist/charts/react/shapes.d.ts +255 -0
  214. package/dist/charts/react/shapes.js +242 -0
  215. package/dist/charts/react/shapes.js.map +1 -0
  216. package/dist/charts/react/types.d.cts +100 -63
  217. package/dist/charts/react/types.d.ts +100 -63
  218. package/dist/native/charts/src/canvas.cjs +1 -0
  219. package/dist/native/charts/src/canvas.js +6 -0
  220. package/dist/native/charts/src/engine/axis.cjs +2 -0
  221. package/dist/native/charts/src/engine/axis.cjs.map +1 -0
  222. package/dist/native/charts/src/engine/axis.js +38 -0
  223. package/dist/native/charts/src/engine/axis.js.map +1 -0
  224. package/dist/native/charts/src/engine/canvas.cjs +1 -0
  225. package/dist/native/charts/src/engine/canvas.js +1 -0
  226. package/dist/native/charts/src/engine/color.cjs +2 -0
  227. package/dist/native/charts/src/engine/color.cjs.map +1 -0
  228. package/dist/native/charts/src/engine/color.js +139 -0
  229. package/dist/native/charts/src/engine/color.js.map +1 -0
  230. package/dist/native/charts/src/engine/controller.cjs +3 -0
  231. package/dist/native/charts/src/engine/controller.cjs.map +1 -0
  232. package/dist/native/charts/src/engine/controller.js +592 -0
  233. package/dist/native/charts/src/engine/controller.js.map +1 -0
  234. package/dist/native/charts/src/engine/curve.cjs +2 -0
  235. package/dist/native/charts/src/engine/curve.cjs.map +1 -0
  236. package/dist/native/charts/src/engine/curve.js +56 -0
  237. package/dist/native/charts/src/engine/curve.js.map +1 -0
  238. package/dist/native/charts/src/engine/data.cjs +2 -0
  239. package/dist/native/charts/src/engine/data.cjs.map +1 -0
  240. package/dist/native/charts/src/engine/data.js +164 -0
  241. package/dist/native/charts/src/engine/data.js.map +1 -0
  242. package/dist/native/charts/src/engine/decimate.cjs +2 -0
  243. package/dist/native/charts/src/engine/decimate.cjs.map +1 -0
  244. package/dist/native/charts/src/engine/decimate.js +28 -0
  245. package/dist/native/charts/src/engine/decimate.js.map +1 -0
  246. package/dist/native/charts/src/engine/format.cjs +2 -0
  247. package/dist/native/charts/src/engine/format.cjs.map +1 -0
  248. package/dist/native/charts/src/engine/format.js +34 -0
  249. package/dist/native/charts/src/engine/format.js.map +1 -0
  250. package/dist/native/charts/src/engine/layout.cjs +2 -0
  251. package/dist/native/charts/src/engine/layout.cjs.map +1 -0
  252. package/dist/native/charts/src/engine/layout.js +26 -0
  253. package/dist/native/charts/src/engine/layout.js.map +1 -0
  254. package/dist/native/charts/src/engine/model.cjs +2 -0
  255. package/dist/native/charts/src/engine/model.cjs.map +1 -0
  256. package/dist/native/charts/src/engine/model.js +292 -0
  257. package/dist/native/charts/src/engine/model.js.map +1 -0
  258. package/dist/native/charts/src/engine/overlay.cjs +2 -0
  259. package/dist/native/charts/src/engine/overlay.cjs.map +1 -0
  260. package/dist/native/charts/src/engine/overlay.js +49 -0
  261. package/dist/native/charts/src/engine/overlay.js.map +1 -0
  262. package/dist/native/charts/src/engine/presets.cjs +3 -0
  263. package/dist/native/charts/src/engine/presets.cjs.map +1 -0
  264. package/dist/native/charts/src/engine/presets.js +154 -0
  265. package/dist/native/charts/src/engine/presets.js.map +1 -0
  266. package/dist/native/charts/src/engine/scale.cjs +2 -0
  267. package/dist/native/charts/src/engine/scale.cjs.map +1 -0
  268. package/dist/native/charts/src/engine/scale.js +37 -0
  269. package/dist/native/charts/src/engine/scale.js.map +1 -0
  270. package/dist/native/charts/src/engine/scene.cjs +2 -0
  271. package/dist/native/charts/src/engine/scene.cjs.map +1 -0
  272. package/dist/native/charts/src/engine/scene.js +353 -0
  273. package/dist/native/charts/src/engine/scene.js.map +1 -0
  274. package/dist/native/charts/src/engine/spatial.cjs +2 -0
  275. package/dist/native/charts/src/engine/spatial.cjs.map +1 -0
  276. package/dist/native/charts/src/engine/spatial.js +53 -0
  277. package/dist/native/charts/src/engine/spatial.js.map +1 -0
  278. package/dist/native/charts/src/engine/theme.cjs +2 -0
  279. package/dist/native/charts/src/engine/theme.cjs.map +1 -0
  280. package/dist/native/charts/src/engine/theme.js +62 -0
  281. package/dist/native/charts/src/engine/theme.js.map +1 -0
  282. package/dist/native/charts/src/engine/time.cjs +2 -0
  283. package/dist/native/charts/src/engine/time.cjs.map +1 -0
  284. package/dist/native/charts/src/engine/time.js +189 -0
  285. package/dist/native/charts/src/engine/time.js.map +1 -0
  286. package/dist/native/charts/src/engine/viewport.cjs +2 -0
  287. package/dist/native/charts/src/engine/viewport.cjs.map +1 -0
  288. package/dist/native/charts/src/engine/viewport.js +12 -0
  289. package/dist/native/charts/src/engine/viewport.js.map +1 -0
  290. package/dist/native/components/Chart/ChartBase.cjs +2 -0
  291. package/dist/native/components/Chart/ChartBase.cjs.map +1 -0
  292. package/dist/native/components/Chart/ChartBase.d.cts +29 -0
  293. package/dist/native/components/Chart/ChartBase.d.ts +29 -0
  294. package/dist/native/components/Chart/ChartBase.js +287 -0
  295. package/dist/native/components/Chart/ChartBase.js.map +1 -0
  296. package/dist/native/components/Chart/charts.cjs +2 -0
  297. package/dist/native/components/Chart/charts.cjs.map +1 -0
  298. package/dist/native/components/Chart/charts.d.cts +19 -0
  299. package/dist/native/components/Chart/charts.d.ts +19 -0
  300. package/dist/native/components/Chart/charts.js +173 -0
  301. package/dist/native/components/Chart/charts.js.map +1 -0
  302. package/dist/native/components/Chart/index.cjs +1 -0
  303. package/dist/native/components/Chart/index.d.cts +2 -0
  304. package/dist/native/components/Chart/index.d.ts +2 -0
  305. package/dist/native/components/Chart/index.js +2 -0
  306. package/dist/native/components/Chart/measure.cjs +2 -0
  307. package/dist/native/components/Chart/measure.cjs.map +1 -0
  308. package/dist/native/components/Chart/measure.d.cts +5 -0
  309. package/dist/native/components/Chart/measure.d.ts +5 -0
  310. package/dist/native/components/Chart/measure.js +11 -0
  311. package/dist/native/components/Chart/measure.js.map +1 -0
  312. package/dist/native/components/Chart/scene.cjs +2 -0
  313. package/dist/native/components/Chart/scene.cjs.map +1 -0
  314. package/dist/native/components/Chart/scene.d.cts +41 -0
  315. package/dist/native/components/Chart/scene.d.ts +41 -0
  316. package/dist/native/components/Chart/scene.js +431 -0
  317. package/dist/native/components/Chart/scene.js.map +1 -0
  318. package/dist/native/components/Chart/theme.cjs +2 -0
  319. package/dist/native/components/Chart/theme.cjs.map +1 -0
  320. package/dist/native/components/Chart/theme.d.cts +10 -0
  321. package/dist/native/components/Chart/theme.d.ts +10 -0
  322. package/dist/native/components/Chart/theme.js +10 -0
  323. package/dist/native/components/Chart/theme.js.map +1 -0
  324. package/dist/native/components/Chart/types.d.cts +129 -0
  325. package/dist/native/components/Chart/types.d.ts +129 -0
  326. package/dist/native/index.cjs +1 -1
  327. package/dist/native/index.d.cts +1 -0
  328. package/dist/native/index.d.ts +1 -0
  329. package/dist/native/index.js +6 -4
  330. package/dist/native/manifest.d.cts +7 -0
  331. package/dist/native/manifest.d.ts +7 -0
  332. package/dist/native/source/components/Chart/ChartBase.tsx +545 -0
  333. package/dist/native/source/components/Chart/charts.tsx +291 -0
  334. package/dist/native/source/components/Chart/index.ts +8 -0
  335. package/dist/native/source/components/Chart/measure.ts +50 -0
  336. package/dist/native/source/components/Chart/scene.tsx +1021 -0
  337. package/dist/native/source/components/Chart/theme.ts +16 -0
  338. package/dist/native/source/components/Chart/types.ts +194 -0
  339. package/dist/native/source/index.ts +1 -0
  340. package/dist/native/source/manifest.ts +14 -0
  341. package/dist/taro/charts.d.ts +144 -0
  342. package/dist/taro/index.d.ts +1 -0
  343. package/dist/taro/index.js +3544 -618
  344. package/dist/uni/BarChart.vue +75 -0
  345. package/dist/uni/BarChart.vue.d.ts +111 -0
  346. package/dist/uni/Chart.vue +68 -0
  347. package/dist/uni/Chart.vue.d.ts +100 -0
  348. package/dist/uni/LineChart.vue +75 -0
  349. package/dist/uni/LineChart.vue.d.ts +111 -0
  350. package/dist/uni/ProgressIndicator.vue.d.ts +1 -1
  351. package/dist/uni/QuadrantChart.vue +184 -0
  352. package/dist/uni/QuadrantChart.vue.d.ts +173 -0
  353. package/dist/uni/ScatterChart.vue +69 -0
  354. package/dist/uni/ScatterChart.vue.d.ts +100 -0
  355. package/dist/uni/chart-canvas.d.ts +68 -0
  356. package/dist/uni/chart-canvas.js +363 -0
  357. package/dist/uni/chart-types.d.ts +135 -0
  358. package/dist/uni/chart-types.js +84 -0
  359. package/dist/uni/charts-canvas.d.ts +1 -0
  360. package/dist/uni/charts-canvas.js +10 -0
  361. package/dist/uni/index.d.ts +6 -0
  362. package/dist/uni/index.js +6 -0
  363. package/dist/weapp/bar-chart/index.js +1 -0
  364. package/dist/weapp/bar-chart/index.json +1 -0
  365. package/dist/weapp/bar-chart/index.wxml +1 -0
  366. package/dist/weapp/bar-chart/index.wxss +1 -0
  367. package/dist/weapp/chart/index.js +1 -0
  368. package/dist/weapp/chart/index.json +1 -0
  369. package/dist/weapp/chart/index.wxml +1 -0
  370. package/dist/weapp/chart/index.wxss +1 -0
  371. package/dist/weapp/controls.js +4760 -266
  372. package/dist/weapp/line-chart/index.js +1 -0
  373. package/dist/weapp/line-chart/index.json +1 -0
  374. package/dist/weapp/line-chart/index.wxml +1 -0
  375. package/dist/weapp/line-chart/index.wxss +1 -0
  376. package/dist/weapp/quadrant-chart/index.js +1 -0
  377. package/dist/weapp/quadrant-chart/index.json +1 -0
  378. package/dist/weapp/quadrant-chart/index.wxml +1 -0
  379. package/dist/weapp/quadrant-chart/index.wxss +1 -0
  380. package/dist/weapp/scatter-chart/index.js +1 -0
  381. package/dist/weapp/scatter-chart/index.json +1 -0
  382. package/dist/weapp/scatter-chart/index.wxml +1 -0
  383. package/dist/weapp/scatter-chart/index.wxss +1 -0
  384. package/dist/weapp/types.d.ts +295 -0
  385. package/package.json +21 -1
@@ -0,0 +1,1021 @@
1
+ // Draws a chart scene (`ChartController.getScene()`) with plain views: no
2
+ // canvas, SVG or native drawing module. The engine already resolves every
3
+ // position in pixels; this file only turns them into absolutely positioned
4
+ // <View> / <Text> elements, keeping the number of views bounded by the size
5
+ // of the chart (lines decimated per column, dots merged per cell, bars
6
+ // merged per pixel column), whatever the size of the data.
7
+
8
+ import type { ReactElement, ReactNode } from "react";
9
+ import {
10
+ StyleSheet,
11
+ Text,
12
+ View,
13
+ type TextStyle,
14
+ type ViewStyle,
15
+ } from "react-native";
16
+ import {
17
+ scenePrimitives,
18
+ toCss,
19
+ type ChartPrimitive,
20
+ type ChartRect,
21
+ type ChartScene,
22
+ } from "../../../charts/src/canvas.js";
23
+ import { part } from "../../internal/parts";
24
+ import { measureChartText } from "./measure";
25
+
26
+ type Rgba = ChartScene["theme"]["text"];
27
+ type Annotation = ChartScene["annotations"][number];
28
+ type RectAnnotation = Extract<Annotation, { type: "rect" }>;
29
+ type TextAnnotation = Extract<Annotation, { type: "text" }>;
30
+ type Scales = ChartScene["layout"]["scales"];
31
+
32
+ /** Upper bounds of the views drawn for the data of a chart */
33
+ export const SHAPE_BUDGET = {
34
+ /** Points of all the lines (one view per segment) */
35
+ linePoints: 1200,
36
+ /** Dots of one scatter series before they are merged per cell */
37
+ dotsPerSeries: 800,
38
+ /** Dots of all the series */
39
+ dots: 2000,
40
+ /** Bars of one series before neighbors are merged per pixel column */
41
+ barsPerSeries: 600,
42
+ /** Bars of all the series */
43
+ bars: 1500,
44
+ /** Vertical strips filling one area */
45
+ areaColumns: 200,
46
+ /** Dashes of one dashed line */
47
+ dashes: 200,
48
+ } as const;
49
+
50
+ const C = "chart";
51
+
52
+ // ------------------------------------------------------------------ text
53
+
54
+ interface TextOptions {
55
+ size: number;
56
+ color: string;
57
+ weight?: number;
58
+ family?: string;
59
+ /** Halo color: keeps the text readable over the data */
60
+ halo?: string;
61
+ }
62
+
63
+ type Align = "left" | "center" | "right";
64
+ type VAlign = "top" | "middle" | "bottom";
65
+
66
+ const lineHeightOf = (size: number) => Math.ceil(size * 1.35);
67
+
68
+ /** Box wide enough for the estimated width (the real one may differ) */
69
+ const slack = (text: string, o: TextOptions) =>
70
+ Math.ceil(
71
+ measureChartText(text, `${o.weight ?? 400} ${o.size}px sans-serif`) * 1.4 +
72
+ o.size * 2,
73
+ );
74
+
75
+ /**
76
+ * A one-line text anchored at (x, y) of a container `frameWidth` wide:
77
+ * `left` starts there, `right` ends there, `center` is centered on it;
78
+ * `top` / `bottom` place the em box like the canvas text baselines
79
+ */
80
+ function label(
81
+ key: string,
82
+ text: string,
83
+ x: number,
84
+ y: number,
85
+ align: Align,
86
+ valign: VAlign,
87
+ o: TextOptions,
88
+ frameWidth: number,
89
+ extra?: TextStyle,
90
+ ): ReactElement {
91
+ const lh = lineHeightOf(o.size);
92
+ const pad = (lh - o.size) / 2;
93
+ const w = slack(text, o);
94
+ const top =
95
+ valign === "top"
96
+ ? y - pad
97
+ : valign === "bottom"
98
+ ? y - lh + pad
99
+ : y - lh / 2;
100
+ const horizontal: TextStyle =
101
+ align === "left"
102
+ ? { left: x, width: w }
103
+ : align === "right"
104
+ ? { right: frameWidth - x, width: w }
105
+ : { left: x - w / 2, width: w };
106
+ return (
107
+ <Text
108
+ key={key}
109
+ numberOfLines={1}
110
+ style={[
111
+ {
112
+ position: "absolute",
113
+ top,
114
+ ...horizontal,
115
+ textAlign: align,
116
+ fontSize: o.size,
117
+ lineHeight: lh,
118
+ color: o.color,
119
+ fontWeight: String(o.weight ?? 400) as TextStyle["fontWeight"],
120
+ includeFontPadding: false,
121
+ ...(o.family ? { fontFamily: o.family } : null),
122
+ ...(o.halo
123
+ ? {
124
+ textShadowColor: o.halo,
125
+ textShadowRadius: 3,
126
+ textShadowOffset: { width: 0, height: 0 },
127
+ }
128
+ : null),
129
+ },
130
+ extra,
131
+ ]}
132
+ >
133
+ {text}
134
+ </Text>
135
+ );
136
+ }
137
+
138
+ // ---------------------------------------------------------------- shapes
139
+
140
+ const box = (
141
+ key: string,
142
+ x: number,
143
+ y: number,
144
+ width: number,
145
+ height: number,
146
+ color: string,
147
+ extra?: ViewStyle,
148
+ ): ReactElement => (
149
+ <View
150
+ key={key}
151
+ style={[
152
+ {
153
+ position: "absolute",
154
+ left: x,
155
+ top: y,
156
+ width,
157
+ height,
158
+ backgroundColor: color,
159
+ },
160
+ extra,
161
+ ]}
162
+ />
163
+ );
164
+
165
+ const dot = (
166
+ key: string,
167
+ cx: number,
168
+ cy: number,
169
+ d: number,
170
+ color: string,
171
+ extra?: ViewStyle,
172
+ ) =>
173
+ box(key, cx - d / 2, cy - d / 2, d, d, color, {
174
+ borderRadius: d / 2,
175
+ ...extra,
176
+ });
177
+
178
+ /** A straight stroke: one view, rotated around its center */
179
+ const segment = (
180
+ key: string,
181
+ x1: number,
182
+ y1: number,
183
+ x2: number,
184
+ y2: number,
185
+ width: number,
186
+ color: string,
187
+ ) => {
188
+ const dx = x2 - x1;
189
+ const dy = y2 - y1;
190
+ const length = Math.hypot(dx, dy) + width;
191
+ return box(
192
+ key,
193
+ (x1 + x2) / 2 - length / 2,
194
+ (y1 + y2) / 2 - width / 2,
195
+ length,
196
+ width,
197
+ color,
198
+ {
199
+ borderRadius: width / 2,
200
+ transform: [{ rotate: `${Math.atan2(dy, dx)}rad` }],
201
+ },
202
+ );
203
+ };
204
+
205
+ /** Dash runs `[start, length]` along a line (canvas `setLineDash` pattern) */
206
+ export function dashRuns(
207
+ length: number,
208
+ dash: readonly number[],
209
+ max: number = SHAPE_BUDGET.dashes,
210
+ ): [number, number][] {
211
+ let pattern = dash.filter((v) => Number.isFinite(v) && v >= 0);
212
+ // odd patterns repeat twice, like the canvas
213
+ if (pattern.length % 2) pattern = [...pattern, ...pattern];
214
+ const period = pattern.reduce((a, b) => a + b, 0);
215
+ if (!pattern.length || period <= 0) return [[0, length]];
216
+ const runs = (length / period) * (pattern.length / 2);
217
+ const scale = runs > max ? runs / max : 1;
218
+ const out: [number, number][] = [];
219
+ let at = 0;
220
+ for (let i = 0; at < length; i = (i + 1) % pattern.length) {
221
+ const step = pattern[i] * scale;
222
+ if (i % 2 === 0 && step > 0) out.push([at, Math.min(step, length - at)]);
223
+ at += Math.max(step, 0.5);
224
+ }
225
+ return out;
226
+ }
227
+
228
+ const dashedLine = (
229
+ key: string,
230
+ axis: "x" | "y",
231
+ at: number,
232
+ from: number,
233
+ length: number,
234
+ width: number,
235
+ color: string,
236
+ dash: readonly number[],
237
+ ) =>
238
+ dashRuns(length, dash).map(([start, run], i) =>
239
+ axis === "y"
240
+ ? box(`${key}-${i}`, from + start, at, run, width, color)
241
+ : box(`${key}-${i}`, at, from + start, width, run, color),
242
+ );
243
+
244
+ const crisp = (v: number, width = 1) => Math.round(v) + 0.5 - width / 2;
245
+
246
+ // ------------------------------------------------------------------ data
247
+
248
+ /** Thins a run of interleaved points to `max` points and drops sub-pixel steps */
249
+ function thin(run: readonly number[], max: number): number[] {
250
+ const n = run.length / 2;
251
+ const stride = n > max ? Math.ceil(n / max) : 1;
252
+ const out: number[] = [];
253
+ for (let i = 0; i < n; i += stride) {
254
+ const x = run[i * 2];
255
+ const y = run[i * 2 + 1];
256
+ const k = out.length;
257
+ if (k && Math.hypot(x - out[k - 2], y - out[k - 1]) < 1.5) continue;
258
+ out.push(x, y);
259
+ }
260
+ const lx = run[n * 2 - 2];
261
+ const ly = run[n * 2 - 1];
262
+ const k = out.length;
263
+ if (n > 1 && (out[k - 2] !== lx || out[k - 1] !== ly)) out.push(lx, ly);
264
+ return out;
265
+ }
266
+
267
+ /** Vertical strips between the line and the baseline (or the stack below), one per column */
268
+ function areaStrips(
269
+ key: string,
270
+ run: readonly number[],
271
+ baseline: number,
272
+ color: string,
273
+ opacity: number,
274
+ plot: ChartRect,
275
+ /** Y pixel of the bottom edge under every point (stacked areas) */
276
+ bottom?: readonly number[],
277
+ ): ReactElement[] {
278
+ const n = run.length / 2;
279
+ if (n < 2) return [];
280
+ // left to right (reversed axes list their points right to left)
281
+ const forward = run[0] <= run[n * 2 - 2];
282
+ const at = (i: number) => (forward ? i : n - 1 - i);
283
+ const xs = (i: number) => run[at(i) * 2];
284
+ const ys = (i: number) => run[at(i) * 2 + 1];
285
+ const bs = (i: number) => (bottom ? bottom[at(i)] : baseline);
286
+ const from = Math.max(plot.x, xs(0));
287
+ const to = Math.min(plot.x + plot.width, xs(n - 1));
288
+ if (to <= from) return [];
289
+ const column = Math.max(2, plot.width / SHAPE_BUDGET.areaColumns);
290
+ const out: ReactElement[] = [];
291
+ let j = 0;
292
+ for (let left = Math.floor(from), c = 0; left < to; c++) {
293
+ const right = Math.min(Math.ceil(to), Math.round(left + column));
294
+ const mid = (left + right) / 2;
295
+ while (j < n - 2 && xs(j + 1) < mid) j++;
296
+ const x0 = xs(j);
297
+ const x1 = xs(j + 1);
298
+ const t = x1 === x0 ? 0 : Math.max(0, Math.min(1, (mid - x0) / (x1 - x0)));
299
+ const y = ys(j) + (ys(j + 1) - ys(j)) * t;
300
+ const b = bs(j) + (bs(j + 1) - bs(j)) * t;
301
+ if (Number.isFinite(y) && Number.isFinite(b)) {
302
+ const top = Math.min(y, b);
303
+ out.push(
304
+ box(
305
+ `${key}-${c}`,
306
+ left - plot.x,
307
+ top - plot.y,
308
+ right - left,
309
+ Math.abs(b - y),
310
+ color,
311
+ {
312
+ opacity,
313
+ },
314
+ ),
315
+ );
316
+ }
317
+ left = right;
318
+ }
319
+ return out;
320
+ }
321
+
322
+ /** Limits of `scenePrimitives` for the views budget */
323
+ export function primitiveLimits(scene: ChartScene) {
324
+ const { plot } = scene.layout;
325
+ const visible = scene.model.series.filter((s) => !s.hidden);
326
+ const lines = visible.filter(
327
+ (s) => s.type === "line" || s.type === "area",
328
+ ).length;
329
+ const scatters = visible.filter((s) => s.type === "scatter").length;
330
+ const perLine = Math.max(150, SHAPE_BUDGET.linePoints / Math.max(1, lines));
331
+ const maxDots = Math.max(
332
+ 100,
333
+ Math.min(
334
+ SHAPE_BUDGET.dotsPerSeries,
335
+ SHAPE_BUDGET.dots / Math.max(1, scatters),
336
+ ),
337
+ );
338
+ return {
339
+ perLine,
340
+ options: {
341
+ // decimation keeps up to 4 points per column
342
+ columnWidth: Math.max(3, (plot.width * 4) / perLine),
343
+ maxDots,
344
+ maxBars: SHAPE_BUDGET.barsPerSeries,
345
+ dotCell: Math.max(
346
+ 4,
347
+ Math.sqrt((plot.width * plot.height) / maxDots) * 1.15 + 1,
348
+ ),
349
+ },
350
+ };
351
+ }
352
+
353
+ function drawData(scene: ChartScene): ReactElement[] {
354
+ const { plot } = scene.layout;
355
+ const { perLine, options } = primitiveLimits(scene);
356
+ const primitives: ChartPrimitive[] = scenePrimitives(scene, options);
357
+ const ox = plot.x;
358
+ const oy = plot.y;
359
+ const out: ReactElement[] = [];
360
+ let dotsLeft: number = SHAPE_BUDGET.dots;
361
+ let barsLeft: number = SHAPE_BUDGET.bars;
362
+ primitives.forEach((p, k) => {
363
+ const key = `${p.kind}${p.seriesIndex}-${k}`;
364
+ if (p.kind === "area") {
365
+ p.segments.forEach((run, r) =>
366
+ out.push(
367
+ ...areaStrips(
368
+ `${key}-${r}`,
369
+ run,
370
+ p.baseline,
371
+ p.color,
372
+ p.opacity,
373
+ plot,
374
+ p.bottoms?.[r],
375
+ ),
376
+ ),
377
+ );
378
+ return;
379
+ }
380
+ if (p.kind === "line") {
381
+ let total = 0;
382
+ for (const run of p.segments) total += run.length / 2;
383
+ p.segments.forEach((run, r) => {
384
+ const pts = thin(
385
+ run,
386
+ Math.max(
387
+ 2,
388
+ Math.round((perLine * run.length) / 2 / Math.max(1, total)),
389
+ ),
390
+ );
391
+ if (pts.length === 2) {
392
+ out.push(
393
+ dot(
394
+ `${key}-${r}`,
395
+ pts[0] - ox,
396
+ pts[1] - oy,
397
+ p.width * 1.5,
398
+ p.color,
399
+ ),
400
+ );
401
+ return;
402
+ }
403
+ for (let i = 0; i + 3 < pts.length; i += 2) {
404
+ out.push(
405
+ segment(
406
+ `${key}-${r}-${i}`,
407
+ pts[i] - ox,
408
+ pts[i + 1] - oy,
409
+ pts[i + 2] - ox,
410
+ pts[i + 3] - oy,
411
+ p.width,
412
+ p.color,
413
+ ),
414
+ );
415
+ }
416
+ });
417
+ return;
418
+ }
419
+ if (p.kind === "bars") {
420
+ const count = p.rects.length / 4;
421
+ const stride =
422
+ count > barsLeft ? Math.ceil(count / Math.max(1, barsLeft)) : 1;
423
+ for (let i = 0; i < count; i += stride) {
424
+ const [x, y, w, h] = p.rects.slice(i * 4, i * 4 + 4);
425
+ const radius = Math.min(p.radius ?? 0, w / 2, h / 2);
426
+ out.push(
427
+ box(
428
+ `${key}-${i}`,
429
+ x - ox,
430
+ y - oy,
431
+ Math.max(w, 0.5),
432
+ h,
433
+ p.colors?.[i] ?? p.color,
434
+ radius > 0.5 ? { borderRadius: radius } : undefined,
435
+ ),
436
+ );
437
+ }
438
+ barsLeft = Math.max(0, barsLeft - Math.ceil(count / stride));
439
+ return;
440
+ }
441
+ const count = p.dots.length / 3;
442
+ const stride =
443
+ count > dotsLeft ? Math.ceil(count / Math.max(1, dotsLeft)) : 1;
444
+ for (let i = 0; i < count; i += stride) {
445
+ out.push(
446
+ dot(
447
+ `${key}-${i}`,
448
+ p.dots[i * 3] - ox,
449
+ p.dots[i * 3 + 1] - oy,
450
+ p.dots[i * 3 + 2],
451
+ p.colors[i],
452
+ {
453
+ opacity: p.opacity,
454
+ },
455
+ ),
456
+ );
457
+ }
458
+ dotsLeft = Math.max(0, dotsLeft - Math.ceil(count / stride));
459
+ });
460
+ return out;
461
+ }
462
+
463
+ // ------------------------------------------------------------ background
464
+
465
+ const rectOf = (a: RectAnnotation, s: Scales): ChartRect => {
466
+ const { plot } = s;
467
+ const xa = a.x0 === undefined ? -Infinity : s.xToPx(a.x0);
468
+ const xb = a.x1 === undefined ? Infinity : s.xToPx(a.x1);
469
+ const ya = a.y0 === undefined ? Infinity : s.yToPx(a.y0);
470
+ const yb = a.y1 === undefined ? -Infinity : s.yToPx(a.y1);
471
+ const left = Math.max(plot.x, Math.min(xa, xb));
472
+ const right = Math.min(plot.x + plot.width, Math.max(xa, xb));
473
+ const top = Math.max(plot.y, Math.min(ya, yb));
474
+ const bottom = Math.min(plot.y + plot.height, Math.max(ya, yb));
475
+ return { x: left, y: top, width: right - left, height: bottom - top };
476
+ };
477
+
478
+ /** Box of a text annotation, kept inside the plot (engine `textBox`) */
479
+ const textBox = (
480
+ a: TextAnnotation,
481
+ s: Scales,
482
+ width: number,
483
+ height: number,
484
+ ): ChartRect => {
485
+ const { plot } = s;
486
+ const px = a.x === undefined ? plot.x + plot.width / 2 : s.xToPx(a.x);
487
+ const py = a.y === undefined ? plot.y + plot.height / 2 : s.yToPx(a.y);
488
+ const gap = 6;
489
+ let x = px - width / 2;
490
+ let y = py - height / 2;
491
+ if (a.anchor === "top") y = py + gap;
492
+ else if (a.anchor === "bottom") y = py - gap - height;
493
+ else if (a.anchor === "left") x = px + gap;
494
+ else if (a.anchor === "right") x = px - gap - width;
495
+ x = Math.max(plot.x + gap, Math.min(x, plot.x + plot.width - gap - width));
496
+ y = Math.max(plot.y + 2, Math.min(y, plot.y + plot.height - 2 - height));
497
+ return { x, y, width, height };
498
+ };
499
+
500
+ const css = (c: Rgba, alpha?: number) => toCss(c, alpha);
501
+
502
+ function drawBackground(scene: ChartScene, family?: string): ReactElement[] {
503
+ const { width, theme, model, layout, annotations } = scene;
504
+ const { plot, scales, xTicks, yTicks } = layout;
505
+ const fs = theme.fontSize;
506
+ const out: ReactElement[] = [];
507
+
508
+ annotations.forEach((a, i) => {
509
+ if (a.type !== "rect") return;
510
+ const r = rectOf(a, scales);
511
+ if (r.width <= 0 || r.height <= 0) return;
512
+ out.push(
513
+ box(`area-${i}`, r.x, r.y, r.width, r.height, css(a.color, a.opacity)),
514
+ );
515
+ });
516
+
517
+ const grid = css(theme.grid);
518
+ if (model.y.grid) {
519
+ yTicks.values.forEach((v, i) => {
520
+ const py = scales.yToPx(v);
521
+ if (py < plot.y - 1 || py > plot.y + plot.height + 1) return;
522
+ out.push(box(`ygrid-${i}`, plot.x, crisp(py), plot.width, 1, grid));
523
+ });
524
+ }
525
+ if (model.x.grid) {
526
+ xTicks.values.forEach((v, i) => {
527
+ const px = scales.xToPx(v);
528
+ if (px < plot.x - 1 || px > plot.x + plot.width + 1) return;
529
+ out.push(box(`xgrid-${i}`, crisp(px), plot.y, 1, plot.height, grid));
530
+ });
531
+ }
532
+
533
+ const line = Math.ceil(fs * 1.4);
534
+ const tick: TextOptions = { size: fs, color: css(theme.textMuted), family };
535
+ const title: TextOptions = {
536
+ size: fs + 1,
537
+ weight: 500,
538
+ color: css(theme.text, 0.8),
539
+ family,
540
+ };
541
+ const bottom = plot.y + plot.height;
542
+
543
+ if (model.x.visible) {
544
+ out.push(
545
+ box("xaxis", plot.x, crisp(bottom), plot.width, 1, css(theme.axis)),
546
+ );
547
+ let lastRight = -Infinity;
548
+ xTicks.values
549
+ .map((v, i) => ({ px: scales.xToPx(v), text: xTicks.labels[i] ?? "" }))
550
+ .sort((a, b) => a.px - b.px)
551
+ .forEach(({ px, text }, i) => {
552
+ if (!text || px < plot.x - 0.5 || px > plot.x + plot.width + 0.5)
553
+ return;
554
+ const w = measureChartText(text, `400 ${fs}px sans-serif`);
555
+ const left = Math.max(0, Math.min(width - w, px - w / 2));
556
+ if (left < lastRight + 6) return;
557
+ lastRight = left + w;
558
+ out.push(
559
+ label(
560
+ `xtick-${i}`,
561
+ text,
562
+ left + w / 2,
563
+ bottom + 7,
564
+ "center",
565
+ "top",
566
+ tick,
567
+ width,
568
+ ),
569
+ );
570
+ });
571
+ if (model.x.title)
572
+ out.push(
573
+ label(
574
+ "xtitle",
575
+ model.x.title,
576
+ plot.x + plot.width / 2,
577
+ bottom + line + 10,
578
+ "center",
579
+ "top",
580
+ title,
581
+ width,
582
+ ),
583
+ );
584
+ }
585
+
586
+ if (model.y.visible) {
587
+ yTicks.values.forEach((v, i) => {
588
+ const py = scales.yToPx(v);
589
+ const text = yTicks.labels[i];
590
+ if (!text || py < plot.y - 0.5 || py > plot.y + plot.height + 0.5) return;
591
+ out.push(
592
+ label(
593
+ `ytick-${i}`,
594
+ text,
595
+ plot.x - 8,
596
+ py,
597
+ "right",
598
+ "middle",
599
+ tick,
600
+ width,
601
+ ),
602
+ );
603
+ });
604
+ if (model.y.title)
605
+ out.push(
606
+ label(
607
+ "ytitle",
608
+ model.y.title,
609
+ line / 2 + 4,
610
+ plot.y + plot.height / 2,
611
+ "center",
612
+ "middle",
613
+ title,
614
+ width,
615
+ {
616
+ transform: [{ rotate: "-90deg" }],
617
+ },
618
+ ),
619
+ );
620
+ }
621
+
622
+ if (scene.legend) {
623
+ for (const e of scene.legend.entries) {
624
+ // coordinates relative to the entry box
625
+ const cy = e.box.height / 2;
626
+ const swatch =
627
+ e.shape === "dot"
628
+ ? dot("swatch", 5, cy, 8, e.color)
629
+ : e.shape === "line"
630
+ ? box("swatch", 0, cy - 1, 10, 2, e.color)
631
+ : box("swatch", 1, cy - 4, 8, 8, e.color);
632
+ out.push(
633
+ <View
634
+ key={`legend-${e.id}`}
635
+ style={{
636
+ position: "absolute",
637
+ left: e.box.x,
638
+ top: e.box.y,
639
+ width: e.box.width,
640
+ height: e.box.height,
641
+ opacity: e.hidden ? 0.45 : 1,
642
+ }}
643
+ {...part(C, "legend-item", { hidden: e.hidden })}
644
+ >
645
+ {swatch}
646
+ {label(
647
+ "name",
648
+ e.name,
649
+ 14,
650
+ cy,
651
+ "left",
652
+ "middle",
653
+ { size: 12, color: css(theme.textMuted), family },
654
+ e.box.width,
655
+ e.hidden ? { textDecorationLine: "line-through" } : undefined,
656
+ )}
657
+ </View>,
658
+ );
659
+ }
660
+ }
661
+ return out;
662
+ }
663
+
664
+ // ------------------------------------------------------------ foreground
665
+
666
+ function drawForeground(scene: ChartScene, family?: string): ReactElement[] {
667
+ const { theme, annotations, layout } = scene;
668
+ const { plot, scales } = layout;
669
+ const fs = theme.fontSize;
670
+ const ox = plot.x;
671
+ const oy = plot.y;
672
+ const fw = plot.width;
673
+ const halo = css(theme.background, 0.9);
674
+ const labelHeight = fs + 4;
675
+ const out: ReactElement[] = [];
676
+
677
+ annotations.forEach((a, i) => {
678
+ if (a.type !== "line") return;
679
+ const color = css(a.color);
680
+ if (a.axis === "y") {
681
+ const py = scales.yToPx(a.value);
682
+ out.push(
683
+ ...dashedLine(
684
+ `line-${i}`,
685
+ "y",
686
+ crisp(py, a.width) - oy,
687
+ 0,
688
+ plot.width,
689
+ a.width,
690
+ color,
691
+ a.dash,
692
+ ),
693
+ );
694
+ if (a.label)
695
+ out.push(
696
+ label(
697
+ `line-label-${i}`,
698
+ a.label,
699
+ plot.width - 6,
700
+ py - 3 - oy,
701
+ "right",
702
+ "bottom",
703
+ { size: fs, weight: 500, color, halo, family },
704
+ fw,
705
+ ),
706
+ );
707
+ } else {
708
+ const px = scales.xToPx(a.value);
709
+ out.push(
710
+ ...dashedLine(
711
+ `line-${i}`,
712
+ "x",
713
+ crisp(px, a.width) - ox,
714
+ 0,
715
+ plot.height,
716
+ a.width,
717
+ color,
718
+ a.dash,
719
+ ),
720
+ );
721
+ if (a.label)
722
+ out.push(
723
+ label(
724
+ `line-label-${i}`,
725
+ a.label,
726
+ px + 5 - ox,
727
+ 5,
728
+ "left",
729
+ "top",
730
+ { size: fs, weight: 500, color, halo, family },
731
+ fw,
732
+ ),
733
+ );
734
+ }
735
+ });
736
+
737
+ annotations.forEach((a, i) => {
738
+ if (a.type !== "rect" || !a.label) return;
739
+ const r = rectOf(a, scales);
740
+ if (r.width <= 0 || r.height <= 0) return;
741
+ const pad = 10;
742
+ const pos = a.labelPosition;
743
+ const align: Align = pos.endsWith("left")
744
+ ? "left"
745
+ : pos.endsWith("right")
746
+ ? "right"
747
+ : "center";
748
+ const tx =
749
+ align === "left"
750
+ ? r.x + pad
751
+ : align === "right"
752
+ ? r.x + r.width - pad
753
+ : r.x + r.width / 2;
754
+ const ty = pos.startsWith("top")
755
+ ? r.y + pad
756
+ : pos.startsWith("bottom")
757
+ ? r.y + r.height - pad - labelHeight
758
+ : r.y + (r.height - labelHeight) / 2;
759
+ out.push(
760
+ label(
761
+ `area-label-${i}`,
762
+ a.label,
763
+ tx - ox,
764
+ ty - oy,
765
+ align,
766
+ "top",
767
+ { size: fs + 1, weight: 600, color: css(a.labelColor), family },
768
+ fw,
769
+ ),
770
+ );
771
+ });
772
+
773
+ annotations.forEach((a, i) => {
774
+ if (a.type !== "text" || !a.text) return;
775
+ const w = measureChartText(a.text, `${a.weight} ${fs}px sans-serif`);
776
+ const b = textBox(a, scales, w, labelHeight);
777
+ out.push(
778
+ label(
779
+ `text-${i}`,
780
+ a.text,
781
+ b.x - ox,
782
+ b.y + b.height / 2 - oy,
783
+ "left",
784
+ "middle",
785
+ { size: fs, weight: a.weight, color: css(a.color), halo, family },
786
+ fw,
787
+ ),
788
+ );
789
+ });
790
+
791
+ const pointColor = css(theme.text, 0.85);
792
+ scene.pointLabels.forEach(({ label: l, box: b }, i) => {
793
+ out.push(
794
+ label(
795
+ `point-label-${i}`,
796
+ l.text,
797
+ b.x - ox,
798
+ b.y + b.height / 2 - oy,
799
+ "left",
800
+ "middle",
801
+ { size: fs, color: pointColor, halo, family },
802
+ fw,
803
+ ),
804
+ );
805
+ });
806
+ return out;
807
+ }
808
+
809
+ const clip = (plot: ChartRect): ViewStyle => ({
810
+ position: "absolute",
811
+ left: plot.x,
812
+ top: plot.y,
813
+ width: plot.width,
814
+ height: plot.height,
815
+ overflow: "hidden",
816
+ });
817
+
818
+ /**
819
+ * Everything but the hover state: axes, grid, legend, annotations, data and
820
+ * labels (cached by the caller while the model, view and size are the same)
821
+ */
822
+ export function drawStatic(scene: ChartScene, family?: string): ReactNode {
823
+ const { plot } = scene.layout;
824
+ return (
825
+ <>
826
+ {drawBackground(scene, family)}
827
+ <View key="data" style={clip(plot)} {...part(C, "data")}>
828
+ {drawData(scene)}
829
+ </View>
830
+ <View key="labels" style={clip(plot)} {...part(C, "labels")}>
831
+ {drawForeground(scene, family)}
832
+ </View>
833
+ </>
834
+ );
835
+ }
836
+
837
+ /** Crosshair, highlighted points, dragged point and the default tooltip */
838
+ export function drawHover(
839
+ scene: ChartScene,
840
+ family: string | undefined,
841
+ customTooltip: boolean,
842
+ ): ReactNode {
843
+ const { theme, layout, hover, dragging } = scene;
844
+ const { plot } = layout;
845
+ const background = css(theme.background);
846
+ const out: ReactElement[] = [];
847
+ if (hover && hover.crosshairX !== null) {
848
+ out.push(
849
+ <View
850
+ key="crosshair"
851
+ style={StyleSheet.absoluteFill}
852
+ {...part(C, "crosshair")}
853
+ >
854
+ {dashedLine(
855
+ "dash",
856
+ "x",
857
+ Math.round(hover.crosshairX),
858
+ plot.y,
859
+ plot.height,
860
+ 1,
861
+ css(theme.textMuted, 0.55),
862
+ [3, 3],
863
+ )}
864
+ </View>,
865
+ );
866
+ }
867
+ hover?.marks.forEach((m, i) => {
868
+ if (m.kind === "band") {
869
+ out.push(
870
+ box(`mark-${i}`, m.x, m.y, m.width, m.height, css(theme.text, 0.05), {
871
+ borderRadius: 6,
872
+ }),
873
+ );
874
+ return;
875
+ }
876
+ if (m.kind === "cell") {
877
+ out.push(
878
+ box(
879
+ `mark-${i}`,
880
+ m.x - 1.5,
881
+ m.y - 1.5,
882
+ m.width + 3,
883
+ m.height + 3,
884
+ "transparent",
885
+ {
886
+ borderRadius: 4,
887
+ borderWidth: 1.5,
888
+ borderColor: css(theme.text, 0.55),
889
+ },
890
+ ),
891
+ );
892
+ return;
893
+ }
894
+ // soft halo, then the dot with a thin ring in the background color
895
+ out.push(
896
+ dot(`halo-${i}`, m.x, m.y, m.size + 8, m.halo),
897
+ dot(`mark-${i}`, m.x, m.y, m.size, m.color, {
898
+ borderWidth: 2,
899
+ borderColor: background,
900
+ }),
901
+ );
902
+ });
903
+ if (dragging) {
904
+ out.push(
905
+ <View key="drag" {...part(C, "drag")} style={StyleSheet.absoluteFill}>
906
+ {dot(
907
+ "ghost",
908
+ dragging.x,
909
+ dragging.y,
910
+ dragging.size + 2,
911
+ dragging.color,
912
+ {
913
+ opacity: 0.85,
914
+ borderWidth: 2,
915
+ borderColor: background,
916
+ },
917
+ )}
918
+ </View>,
919
+ );
920
+ }
921
+ const tip = hover?.tooltip;
922
+ if (tip && !customTooltip) {
923
+ const { box: b, lineHeight, padding, content } = tip;
924
+ const text = css(theme.text);
925
+ const muted = css(theme.textMuted);
926
+ const font = (weight: number, color: string): TextStyle => ({
927
+ fontSize: 12,
928
+ lineHeight,
929
+ color,
930
+ fontWeight: String(weight) as TextStyle["fontWeight"],
931
+ includeFontPadding: false,
932
+ ...(family ? { fontFamily: family } : null),
933
+ });
934
+ const swatch = (color: string) => (
935
+ <View
936
+ style={{
937
+ width: 8,
938
+ height: 8,
939
+ borderRadius: 4,
940
+ marginRight: 6,
941
+ backgroundColor: color,
942
+ }}
943
+ />
944
+ );
945
+ const row: ViewStyle = {
946
+ height: lineHeight,
947
+ flexDirection: "row",
948
+ alignItems: "center",
949
+ };
950
+ out.push(
951
+ <View
952
+ key="tooltip"
953
+ {...part(C, "tooltip")}
954
+ style={[
955
+ tooltipCard(scene),
956
+ {
957
+ left: b.x,
958
+ top: b.y,
959
+ width: b.width,
960
+ height: b.height,
961
+ paddingHorizontal: padding + 1,
962
+ paddingVertical: padding - 1,
963
+ },
964
+ ]}
965
+ >
966
+ {tip.text
967
+ ? tip.text.map((t, i) => (
968
+ <Text key={i} numberOfLines={1} style={font(400, text)}>
969
+ {t}
970
+ </Text>
971
+ ))
972
+ : [
973
+ <View key="title" style={row}>
974
+ {content.titleColor ? swatch(content.titleColor) : null}
975
+ <Text
976
+ numberOfLines={1}
977
+ style={[font(600, text), { flexShrink: 1 }]}
978
+ >
979
+ {content.title}
980
+ </Text>
981
+ </View>,
982
+ ...content.rows.map((r, i) => (
983
+ <View key={i} style={row}>
984
+ {r.color ? swatch(r.color) : null}
985
+ <Text
986
+ numberOfLines={1}
987
+ style={[font(400, muted), { flexShrink: 1 }]}
988
+ >
989
+ {r.name}
990
+ </Text>
991
+ <Text
992
+ numberOfLines={1}
993
+ style={[
994
+ font(600, text),
995
+ { flexGrow: 1, marginLeft: 16, textAlign: "right" },
996
+ ]}
997
+ >
998
+ {r.value}
999
+ </Text>
1000
+ </View>
1001
+ )),
1002
+ ]}
1003
+ </View>,
1004
+ );
1005
+ }
1006
+ return out;
1007
+ }
1008
+
1009
+ /** Look of the tooltips (default and `renderTooltip` content) */
1010
+ export const tooltipCard = (scene: ChartScene): ViewStyle => ({
1011
+ position: "absolute",
1012
+ backgroundColor: css(scene.theme.background),
1013
+ borderColor: css(scene.theme.axis),
1014
+ borderWidth: 1,
1015
+ borderRadius: 8,
1016
+ shadowColor: "#0f172a",
1017
+ shadowOpacity: 0.18,
1018
+ shadowRadius: 8,
1019
+ shadowOffset: { width: 0, height: 6 },
1020
+ elevation: 6,
1021
+ });