minerva-design 1.4.0 → 1.5.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 (670) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +21 -21
  3. package/custom-elements.json +4047 -1703
  4. package/dist/angular/fesm2022/minerva-angular.mjs +1436 -5
  5. package/dist/angular/fesm2022/minerva-angular.mjs.map +1 -1
  6. package/dist/angular/types/minerva-angular.d.ts +573 -4
  7. package/dist/charts/canvas.d.cts +2 -2
  8. package/dist/charts/canvas.d.ts +2 -2
  9. package/dist/charts/core.cjs +1 -1
  10. package/dist/charts/core.d.cts +6 -4
  11. package/dist/charts/core.d.ts +6 -4
  12. package/dist/charts/core.js +24 -16
  13. package/dist/charts/engine/axis.cjs +1 -1
  14. package/dist/charts/engine/axis.cjs.map +1 -1
  15. package/dist/charts/engine/axis.js +42 -19
  16. package/dist/charts/engine/axis.js.map +1 -1
  17. package/dist/charts/engine/canvas.cjs +1 -1
  18. package/dist/charts/engine/canvas.cjs.map +1 -1
  19. package/dist/charts/engine/canvas.js +154 -127
  20. package/dist/charts/engine/canvas.js.map +1 -1
  21. package/dist/charts/engine/chart.cjs +1 -1
  22. package/dist/charts/engine/chart.cjs.map +1 -1
  23. package/dist/charts/engine/chart.js +365 -251
  24. package/dist/charts/engine/chart.js.map +1 -1
  25. package/dist/charts/engine/color.cjs +1 -1
  26. package/dist/charts/engine/color.cjs.map +1 -1
  27. package/dist/charts/engine/color.d.cts +18 -0
  28. package/dist/charts/engine/color.d.ts +18 -0
  29. package/dist/charts/engine/color.js +48 -2
  30. package/dist/charts/engine/color.js.map +1 -1
  31. package/dist/charts/engine/controller.cjs +2 -2
  32. package/dist/charts/engine/controller.cjs.map +1 -1
  33. package/dist/charts/engine/controller.d.cts +32 -1
  34. package/dist/charts/engine/controller.d.ts +32 -1
  35. package/dist/charts/engine/controller.js +310 -263
  36. package/dist/charts/engine/controller.js.map +1 -1
  37. package/dist/charts/engine/data.cjs +1 -1
  38. package/dist/charts/engine/data.cjs.map +1 -1
  39. package/dist/charts/engine/data.d.cts +3 -1
  40. package/dist/charts/engine/data.d.ts +3 -1
  41. package/dist/charts/engine/data.js +6 -4
  42. package/dist/charts/engine/data.js.map +1 -1
  43. package/dist/charts/engine/defaults.cjs +2 -0
  44. package/dist/charts/engine/defaults.cjs.map +1 -0
  45. package/dist/charts/engine/defaults.d.cts +20 -0
  46. package/dist/charts/engine/defaults.d.ts +20 -0
  47. package/dist/charts/engine/defaults.js +35 -0
  48. package/dist/charts/engine/defaults.js.map +1 -0
  49. package/dist/charts/engine/format.cjs +1 -1
  50. package/dist/charts/engine/format.cjs.map +1 -1
  51. package/dist/charts/engine/format.d.cts +6 -0
  52. package/dist/charts/engine/format.d.ts +6 -0
  53. package/dist/charts/engine/format.js +15 -2
  54. package/dist/charts/engine/format.js.map +1 -1
  55. package/dist/charts/engine/graph/chart.cjs +2 -0
  56. package/dist/charts/engine/graph/chart.cjs.map +1 -0
  57. package/dist/charts/engine/graph/chart.d.cts +3 -0
  58. package/dist/charts/engine/graph/chart.d.ts +3 -0
  59. package/dist/charts/engine/graph/chart.js +1565 -0
  60. package/dist/charts/engine/graph/chart.js.map +1 -0
  61. package/dist/charts/engine/graph/circular.cjs +2 -0
  62. package/dist/charts/engine/graph/circular.cjs.map +1 -0
  63. package/dist/charts/engine/graph/circular.d.cts +16 -0
  64. package/dist/charts/engine/graph/circular.d.ts +16 -0
  65. package/dist/charts/engine/graph/circular.js +62 -0
  66. package/dist/charts/engine/graph/circular.js.map +1 -0
  67. package/dist/charts/engine/graph/dag.cjs +2 -0
  68. package/dist/charts/engine/graph/dag.cjs.map +1 -0
  69. package/dist/charts/engine/graph/dag.d.cts +34 -0
  70. package/dist/charts/engine/graph/dag.d.ts +34 -0
  71. package/dist/charts/engine/graph/dag.js +314 -0
  72. package/dist/charts/engine/graph/dag.js.map +1 -0
  73. package/dist/charts/engine/graph/dom.cjs +2 -0
  74. package/dist/charts/engine/graph/dom.cjs.map +1 -0
  75. package/dist/charts/engine/graph/dom.d.cts +23 -0
  76. package/dist/charts/engine/graph/dom.d.ts +23 -0
  77. package/dist/charts/engine/graph/dom.js +158 -0
  78. package/dist/charts/engine/graph/dom.js.map +1 -0
  79. package/dist/charts/engine/graph/force.cjs +2 -0
  80. package/dist/charts/engine/graph/force.cjs.map +1 -0
  81. package/dist/charts/engine/graph/force.d.cts +67 -0
  82. package/dist/charts/engine/graph/force.d.ts +67 -0
  83. package/dist/charts/engine/graph/force.js +325 -0
  84. package/dist/charts/engine/graph/force.js.map +1 -0
  85. package/dist/charts/engine/graph/geometry.cjs +2 -0
  86. package/dist/charts/engine/graph/geometry.cjs.map +1 -0
  87. package/dist/charts/engine/graph/geometry.d.cts +37 -0
  88. package/dist/charts/engine/graph/geometry.d.ts +37 -0
  89. package/dist/charts/engine/graph/geometry.js +144 -0
  90. package/dist/charts/engine/graph/geometry.js.map +1 -0
  91. package/dist/charts/engine/graph/index.cjs +1 -0
  92. package/dist/charts/engine/graph/index.d.cts +6 -0
  93. package/dist/charts/engine/graph/index.d.ts +6 -0
  94. package/dist/charts/engine/graph/index.js +6 -0
  95. package/dist/charts/engine/graph/labels.cjs +2 -0
  96. package/dist/charts/engine/graph/labels.cjs.map +1 -0
  97. package/dist/charts/engine/graph/labels.d.cts +12 -0
  98. package/dist/charts/engine/graph/labels.d.ts +12 -0
  99. package/dist/charts/engine/graph/labels.js +128 -0
  100. package/dist/charts/engine/graph/labels.js.map +1 -0
  101. package/dist/charts/engine/graph/model.cjs +2 -0
  102. package/dist/charts/engine/graph/model.cjs.map +1 -0
  103. package/dist/charts/engine/graph/model.d.cts +43 -0
  104. package/dist/charts/engine/graph/model.d.ts +43 -0
  105. package/dist/charts/engine/graph/model.js +88 -0
  106. package/dist/charts/engine/graph/model.js.map +1 -0
  107. package/dist/charts/engine/graph/sizing.cjs +2 -0
  108. package/dist/charts/engine/graph/sizing.cjs.map +1 -0
  109. package/dist/charts/engine/graph/sizing.d.cts +33 -0
  110. package/dist/charts/engine/graph/sizing.d.ts +33 -0
  111. package/dist/charts/engine/graph/sizing.js +60 -0
  112. package/dist/charts/engine/graph/sizing.js.map +1 -0
  113. package/dist/charts/engine/graph/tree.cjs +2 -0
  114. package/dist/charts/engine/graph/tree.cjs.map +1 -0
  115. package/dist/charts/engine/graph/tree.d.cts +30 -0
  116. package/dist/charts/engine/graph/tree.d.ts +30 -0
  117. package/dist/charts/engine/graph/tree.js +218 -0
  118. package/dist/charts/engine/graph/tree.js.map +1 -0
  119. package/dist/charts/engine/graph/types.d.cts +626 -0
  120. package/dist/charts/engine/graph/types.d.ts +626 -0
  121. package/dist/charts/engine/graph/worker.cjs +46 -0
  122. package/dist/charts/engine/graph/worker.cjs.map +1 -0
  123. package/dist/charts/engine/graph/worker.d.cts +36 -0
  124. package/dist/charts/engine/graph/worker.d.ts +36 -0
  125. package/dist/charts/engine/graph/worker.js +129 -0
  126. package/dist/charts/engine/graph/worker.js.map +1 -0
  127. package/dist/charts/engine/items.cjs +1 -1
  128. package/dist/charts/engine/items.cjs.map +1 -1
  129. package/dist/charts/engine/items.d.cts +15 -2
  130. package/dist/charts/engine/items.d.ts +15 -2
  131. package/dist/charts/engine/items.js +131 -112
  132. package/dist/charts/engine/items.js.map +1 -1
  133. package/dist/charts/engine/labels.cjs +1 -1
  134. package/dist/charts/engine/labels.cjs.map +1 -1
  135. package/dist/charts/engine/labels.js +28 -4
  136. package/dist/charts/engine/labels.js.map +1 -1
  137. package/dist/charts/engine/layout.cjs +1 -1
  138. package/dist/charts/engine/layout.cjs.map +1 -1
  139. package/dist/charts/engine/layout.d.cts +9 -0
  140. package/dist/charts/engine/layout.d.ts +9 -0
  141. package/dist/charts/engine/layout.js +11 -2
  142. package/dist/charts/engine/layout.js.map +1 -1
  143. package/dist/charts/engine/model.cjs +1 -1
  144. package/dist/charts/engine/model.cjs.map +1 -1
  145. package/dist/charts/engine/model.d.cts +40 -3
  146. package/dist/charts/engine/model.d.ts +40 -3
  147. package/dist/charts/engine/model.js +246 -165
  148. package/dist/charts/engine/model.js.map +1 -1
  149. package/dist/charts/engine/orderbook/format.cjs +1 -1
  150. package/dist/charts/engine/orderbook/format.cjs.map +1 -1
  151. package/dist/charts/engine/orderbook/format.d.cts +3 -2
  152. package/dist/charts/engine/orderbook/format.d.ts +3 -2
  153. package/dist/charts/engine/orderbook/format.js +5 -5
  154. package/dist/charts/engine/orderbook/format.js.map +1 -1
  155. package/dist/charts/engine/orderbook/heatmap.cjs +1 -1
  156. package/dist/charts/engine/orderbook/heatmap.cjs.map +1 -1
  157. package/dist/charts/engine/orderbook/heatmap.js +527 -408
  158. package/dist/charts/engine/orderbook/heatmap.js.map +1 -1
  159. package/dist/charts/engine/orderbook/layout.cjs +2 -0
  160. package/dist/charts/engine/orderbook/layout.cjs.map +1 -0
  161. package/dist/charts/engine/orderbook/layout.d.cts +37 -0
  162. package/dist/charts/engine/orderbook/layout.d.ts +37 -0
  163. package/dist/charts/engine/orderbook/layout.js +70 -0
  164. package/dist/charts/engine/orderbook/layout.js.map +1 -0
  165. package/dist/charts/engine/orderbook/tape.cjs +1 -1
  166. package/dist/charts/engine/orderbook/tape.cjs.map +1 -1
  167. package/dist/charts/engine/orderbook/tape.js +1 -1
  168. package/dist/charts/engine/orderbook/tape.js.map +1 -1
  169. package/dist/charts/engine/orderbook/types.d.cts +18 -2
  170. package/dist/charts/engine/orderbook/types.d.ts +18 -2
  171. package/dist/charts/engine/overlay.cjs +1 -1
  172. package/dist/charts/engine/overlay.cjs.map +1 -1
  173. package/dist/charts/engine/overlay.d.cts +10 -0
  174. package/dist/charts/engine/overlay.d.ts +10 -0
  175. package/dist/charts/engine/overlay.js +6 -0
  176. package/dist/charts/engine/overlay.js.map +1 -1
  177. package/dist/charts/engine/presets.cjs +2 -2
  178. package/dist/charts/engine/presets.cjs.map +1 -1
  179. package/dist/charts/engine/presets.d.cts +25 -3
  180. package/dist/charts/engine/presets.d.ts +25 -3
  181. package/dist/charts/engine/presets.js +115 -101
  182. package/dist/charts/engine/presets.js.map +1 -1
  183. package/dist/charts/engine/renderers/detect.cjs +1 -1
  184. package/dist/charts/engine/renderers/detect.cjs.map +1 -1
  185. package/dist/charts/engine/renderers/detect.d.cts +2 -1
  186. package/dist/charts/engine/renderers/detect.d.ts +2 -1
  187. package/dist/charts/engine/renderers/detect.js +23 -21
  188. package/dist/charts/engine/renderers/detect.js.map +1 -1
  189. package/dist/charts/engine/scene.cjs +1 -1
  190. package/dist/charts/engine/scene.cjs.map +1 -1
  191. package/dist/charts/engine/scene.d.cts +57 -4
  192. package/dist/charts/engine/scene.d.ts +57 -4
  193. package/dist/charts/engine/scene.js +335 -182
  194. package/dist/charts/engine/scene.js.map +1 -1
  195. package/dist/charts/engine/shapes/bullet.cjs +1 -1
  196. package/dist/charts/engine/shapes/bullet.cjs.map +1 -1
  197. package/dist/charts/engine/shapes/bullet.js +110 -110
  198. package/dist/charts/engine/shapes/bullet.js.map +1 -1
  199. package/dist/charts/engine/shapes/chart.cjs +1 -1
  200. package/dist/charts/engine/shapes/chart.cjs.map +1 -1
  201. package/dist/charts/engine/shapes/chart.js +4 -1
  202. package/dist/charts/engine/shapes/chart.js.map +1 -1
  203. package/dist/charts/engine/shapes/chord.cjs +2 -0
  204. package/dist/charts/engine/shapes/chord.cjs.map +1 -0
  205. package/dist/charts/engine/shapes/chord.d.cts +18 -0
  206. package/dist/charts/engine/shapes/chord.d.ts +18 -0
  207. package/dist/charts/engine/shapes/chord.js +414 -0
  208. package/dist/charts/engine/shapes/chord.js.map +1 -0
  209. package/dist/charts/engine/shapes/draw.cjs +1 -1
  210. package/dist/charts/engine/shapes/draw.cjs.map +1 -1
  211. package/dist/charts/engine/shapes/draw.d.cts +5 -1
  212. package/dist/charts/engine/shapes/draw.d.ts +5 -1
  213. package/dist/charts/engine/shapes/draw.js +47 -17
  214. package/dist/charts/engine/shapes/draw.js.map +1 -1
  215. package/dist/charts/engine/shapes/hit.cjs +1 -1
  216. package/dist/charts/engine/shapes/hit.cjs.map +1 -1
  217. package/dist/charts/engine/shapes/hit.d.cts +3 -1
  218. package/dist/charts/engine/shapes/hit.d.ts +3 -1
  219. package/dist/charts/engine/shapes/hit.js +75 -46
  220. package/dist/charts/engine/shapes/hit.js.map +1 -1
  221. package/dist/charts/engine/shapes/index.d.cts +3 -2
  222. package/dist/charts/engine/shapes/index.d.ts +3 -2
  223. package/dist/charts/engine/shapes/labels.cjs +1 -1
  224. package/dist/charts/engine/shapes/labels.cjs.map +1 -1
  225. package/dist/charts/engine/shapes/labels.js +12 -4
  226. package/dist/charts/engine/shapes/labels.js.map +1 -1
  227. package/dist/charts/engine/shapes/layout.cjs +2 -2
  228. package/dist/charts/engine/shapes/layout.cjs.map +1 -1
  229. package/dist/charts/engine/shapes/layout.d.cts +3 -1
  230. package/dist/charts/engine/shapes/layout.d.ts +3 -1
  231. package/dist/charts/engine/shapes/layout.js +106 -78
  232. package/dist/charts/engine/shapes/layout.js.map +1 -1
  233. package/dist/charts/engine/shapes/scene.cjs +1 -1
  234. package/dist/charts/engine/shapes/scene.cjs.map +1 -1
  235. package/dist/charts/engine/shapes/scene.d.cts +33 -3
  236. package/dist/charts/engine/shapes/scene.d.ts +33 -3
  237. package/dist/charts/engine/shapes/scene.js +62 -19
  238. package/dist/charts/engine/shapes/scene.js.map +1 -1
  239. package/dist/charts/engine/shapes/types.d.cts +119 -8
  240. package/dist/charts/engine/shapes/types.d.ts +119 -8
  241. package/dist/charts/engine/signature.cjs +1 -1
  242. package/dist/charts/engine/signature.cjs.map +1 -1
  243. package/dist/charts/engine/signature.js +1 -1
  244. package/dist/charts/engine/signature.js.map +1 -1
  245. package/dist/charts/engine/three-d/canvas2d.cjs +1 -1
  246. package/dist/charts/engine/three-d/canvas2d.cjs.map +1 -1
  247. package/dist/charts/engine/three-d/canvas2d.d.cts +5 -2
  248. package/dist/charts/engine/three-d/canvas2d.d.ts +5 -2
  249. package/dist/charts/engine/three-d/canvas2d.js +89 -65
  250. package/dist/charts/engine/three-d/canvas2d.js.map +1 -1
  251. package/dist/charts/engine/three-d/detect.cjs +1 -1
  252. package/dist/charts/engine/three-d/detect.cjs.map +1 -1
  253. package/dist/charts/engine/three-d/detect.d.cts +3 -2
  254. package/dist/charts/engine/three-d/detect.d.ts +3 -2
  255. package/dist/charts/engine/three-d/detect.js +22 -20
  256. package/dist/charts/engine/three-d/detect.js.map +1 -1
  257. package/dist/charts/engine/three-d/geometry.cjs +1 -1
  258. package/dist/charts/engine/three-d/geometry.cjs.map +1 -1
  259. package/dist/charts/engine/three-d/geometry.d.cts +6 -0
  260. package/dist/charts/engine/three-d/geometry.d.ts +6 -0
  261. package/dist/charts/engine/three-d/geometry.js +106 -90
  262. package/dist/charts/engine/three-d/geometry.js.map +1 -1
  263. package/dist/charts/engine/three-d/model.cjs +1 -1
  264. package/dist/charts/engine/three-d/model.cjs.map +1 -1
  265. package/dist/charts/engine/three-d/model.d.cts +2 -0
  266. package/dist/charts/engine/three-d/model.d.ts +2 -0
  267. package/dist/charts/engine/three-d/model.js +2 -0
  268. package/dist/charts/engine/three-d/model.js.map +1 -1
  269. package/dist/charts/engine/three-d/overlay.cjs +1 -1
  270. package/dist/charts/engine/three-d/overlay.cjs.map +1 -1
  271. package/dist/charts/engine/three-d/overlay.js +43 -36
  272. package/dist/charts/engine/three-d/overlay.js.map +1 -1
  273. package/dist/charts/engine/three-d/render-types.cjs +1 -1
  274. package/dist/charts/engine/three-d/render-types.cjs.map +1 -1
  275. package/dist/charts/engine/three-d/render-types.d.cts +24 -3
  276. package/dist/charts/engine/three-d/render-types.d.ts +24 -3
  277. package/dist/charts/engine/three-d/render-types.js +6 -7
  278. package/dist/charts/engine/three-d/render-types.js.map +1 -1
  279. package/dist/charts/engine/three-d/shaders.cjs +63 -28
  280. package/dist/charts/engine/three-d/shaders.cjs.map +1 -1
  281. package/dist/charts/engine/three-d/shaders.d.cts +2 -3
  282. package/dist/charts/engine/three-d/shaders.d.ts +2 -3
  283. package/dist/charts/engine/three-d/shaders.js +41 -22
  284. package/dist/charts/engine/three-d/shaders.js.map +1 -1
  285. package/dist/charts/engine/three-d/sort.cjs +1 -1
  286. package/dist/charts/engine/three-d/sort.cjs.map +1 -1
  287. package/dist/charts/engine/three-d/sort.d.cts +15 -4
  288. package/dist/charts/engine/three-d/sort.d.ts +15 -4
  289. package/dist/charts/engine/three-d/sort.js +117 -43
  290. package/dist/charts/engine/three-d/sort.js.map +1 -1
  291. package/dist/charts/engine/three-d/types.d.cts +27 -0
  292. package/dist/charts/engine/three-d/types.d.ts +27 -0
  293. package/dist/charts/engine/three-d/webgl.cjs +1 -1
  294. package/dist/charts/engine/three-d/webgl.cjs.map +1 -1
  295. package/dist/charts/engine/three-d/webgl.js +15 -13
  296. package/dist/charts/engine/three-d/webgl.js.map +1 -1
  297. package/dist/charts/engine/three-d/webgpu.cjs +1 -1
  298. package/dist/charts/engine/three-d/webgpu.cjs.map +1 -1
  299. package/dist/charts/engine/three-d/webgpu.js +50 -39
  300. package/dist/charts/engine/three-d/webgpu.js.map +1 -1
  301. package/dist/charts/engine/trading/chart.cjs +1 -1
  302. package/dist/charts/engine/trading/chart.cjs.map +1 -1
  303. package/dist/charts/engine/trading/chart.d.cts +10 -0
  304. package/dist/charts/engine/trading/chart.d.ts +10 -0
  305. package/dist/charts/engine/trading/chart.js +1475 -776
  306. package/dist/charts/engine/trading/chart.js.map +1 -1
  307. package/dist/charts/engine/trading/drawings.cjs +2 -1
  308. package/dist/charts/engine/trading/drawings.cjs.map +1 -1
  309. package/dist/charts/engine/trading/drawings.d.cts +47 -9
  310. package/dist/charts/engine/trading/drawings.d.ts +47 -9
  311. package/dist/charts/engine/trading/drawings.js +338 -75
  312. package/dist/charts/engine/trading/drawings.js.map +1 -1
  313. package/dist/charts/engine/trading/format.cjs +1 -1
  314. package/dist/charts/engine/trading/format.cjs.map +1 -1
  315. package/dist/charts/engine/trading/format.d.cts +13 -0
  316. package/dist/charts/engine/trading/format.d.ts +13 -0
  317. package/dist/charts/engine/trading/format.js +51 -19
  318. package/dist/charts/engine/trading/format.js.map +1 -1
  319. package/dist/charts/engine/trading/index.cjs +1 -1
  320. package/dist/charts/engine/trading/index.d.cts +2 -1
  321. package/dist/charts/engine/trading/index.d.ts +2 -1
  322. package/dist/charts/engine/trading/index.js +4 -3
  323. package/dist/charts/engine/trading/indicators.cjs +1 -1
  324. package/dist/charts/engine/trading/indicators.cjs.map +1 -1
  325. package/dist/charts/engine/trading/indicators.d.cts +180 -10
  326. package/dist/charts/engine/trading/indicators.d.ts +180 -10
  327. package/dist/charts/engine/trading/indicators.js +449 -173
  328. package/dist/charts/engine/trading/indicators.js.map +1 -1
  329. package/dist/charts/engine/trading/labels.cjs +1 -1
  330. package/dist/charts/engine/trading/labels.cjs.map +1 -1
  331. package/dist/charts/engine/trading/labels.js +84 -4
  332. package/dist/charts/engine/trading/labels.js.map +1 -1
  333. package/dist/charts/engine/trading/store.cjs +1 -1
  334. package/dist/charts/engine/trading/store.cjs.map +1 -1
  335. package/dist/charts/engine/trading/store.d.cts +21 -0
  336. package/dist/charts/engine/trading/store.d.ts +21 -0
  337. package/dist/charts/engine/trading/store.js +22 -1
  338. package/dist/charts/engine/trading/store.js.map +1 -1
  339. package/dist/charts/engine/trading/studies.cjs +1 -1
  340. package/dist/charts/engine/trading/studies.cjs.map +1 -1
  341. package/dist/charts/engine/trading/studies.d.cts +41 -8
  342. package/dist/charts/engine/trading/studies.d.ts +41 -8
  343. package/dist/charts/engine/trading/studies.js +349 -93
  344. package/dist/charts/engine/trading/studies.js.map +1 -1
  345. package/dist/charts/engine/trading/sync.cjs +2 -0
  346. package/dist/charts/engine/trading/sync.cjs.map +1 -0
  347. package/dist/charts/engine/trading/sync.d.cts +8 -0
  348. package/dist/charts/engine/trading/sync.d.ts +8 -0
  349. package/dist/charts/engine/trading/sync.js +25 -0
  350. package/dist/charts/engine/trading/sync.js.map +1 -0
  351. package/dist/charts/engine/trading/types.d.cts +484 -9
  352. package/dist/charts/engine/trading/types.d.ts +484 -9
  353. package/dist/charts/engine/types.d.cts +82 -8
  354. package/dist/charts/engine/types.d.ts +82 -8
  355. package/dist/charts/index.cjs +1 -1
  356. package/dist/charts/index.d.cts +3 -2
  357. package/dist/charts/index.d.ts +3 -2
  358. package/dist/charts/index.js +30 -22
  359. package/dist/charts/react/charts.cjs +1 -1
  360. package/dist/charts/react/charts.cjs.map +1 -1
  361. package/dist/charts/react/charts.js +46 -34
  362. package/dist/charts/react/charts.js.map +1 -1
  363. package/dist/charts/react/graph.cjs +2 -0
  364. package/dist/charts/react/graph.cjs.map +1 -0
  365. package/dist/charts/react/graph.d.cts +213 -0
  366. package/dist/charts/react/graph.d.ts +213 -0
  367. package/dist/charts/react/graph.js +159 -0
  368. package/dist/charts/react/graph.js.map +1 -0
  369. package/dist/charts/react/shapes.cjs +1 -1
  370. package/dist/charts/react/shapes.cjs.map +1 -1
  371. package/dist/charts/react/shapes.d.cts +87 -4
  372. package/dist/charts/react/shapes.d.ts +87 -4
  373. package/dist/charts/react/shapes.js +55 -12
  374. package/dist/charts/react/shapes.js.map +1 -1
  375. package/dist/charts/react/trading.cjs +1 -1
  376. package/dist/charts/react/trading.cjs.map +1 -1
  377. package/dist/charts/react/trading.d.cts +53 -1
  378. package/dist/charts/react/trading.d.ts +53 -1
  379. package/dist/charts/react/trading.js +68 -37
  380. package/dist/charts/react/trading.js.map +1 -1
  381. package/dist/charts/react/types.d.cts +11 -0
  382. package/dist/charts/react/types.d.ts +11 -0
  383. package/dist/core/contracts.cjs +1 -1
  384. package/dist/core/contracts.cjs.map +1 -1
  385. package/dist/core/contracts.js +1 -1
  386. package/dist/core/contracts.js.map +1 -1
  387. package/dist/native/charts/src/canvas.cjs +1 -1
  388. package/dist/native/charts/src/canvas.js +3 -3
  389. package/dist/native/charts/src/engine/axis.cjs +1 -1
  390. package/dist/native/charts/src/engine/axis.cjs.map +1 -1
  391. package/dist/native/charts/src/engine/axis.js +42 -19
  392. package/dist/native/charts/src/engine/axis.js.map +1 -1
  393. package/dist/native/charts/src/engine/color.cjs +1 -1
  394. package/dist/native/charts/src/engine/color.cjs.map +1 -1
  395. package/dist/native/charts/src/engine/color.js +47 -5
  396. package/dist/native/charts/src/engine/color.js.map +1 -1
  397. package/dist/native/charts/src/engine/controller.cjs +2 -2
  398. package/dist/native/charts/src/engine/controller.cjs.map +1 -1
  399. package/dist/native/charts/src/engine/controller.js +300 -253
  400. package/dist/native/charts/src/engine/controller.js.map +1 -1
  401. package/dist/native/charts/src/engine/data.cjs +1 -1
  402. package/dist/native/charts/src/engine/data.cjs.map +1 -1
  403. package/dist/native/charts/src/engine/data.js +6 -4
  404. package/dist/native/charts/src/engine/data.js.map +1 -1
  405. package/dist/native/charts/src/engine/format.cjs +1 -1
  406. package/dist/native/charts/src/engine/format.cjs.map +1 -1
  407. package/dist/native/charts/src/engine/format.js +15 -2
  408. package/dist/native/charts/src/engine/format.js.map +1 -1
  409. package/dist/native/charts/src/engine/labels.cjs +1 -1
  410. package/dist/native/charts/src/engine/labels.cjs.map +1 -1
  411. package/dist/native/charts/src/engine/labels.js +28 -4
  412. package/dist/native/charts/src/engine/labels.js.map +1 -1
  413. package/dist/native/charts/src/engine/layout.cjs +1 -1
  414. package/dist/native/charts/src/engine/layout.cjs.map +1 -1
  415. package/dist/native/charts/src/engine/layout.js +11 -2
  416. package/dist/native/charts/src/engine/layout.js.map +1 -1
  417. package/dist/native/charts/src/engine/model.cjs +1 -1
  418. package/dist/native/charts/src/engine/model.cjs.map +1 -1
  419. package/dist/native/charts/src/engine/model.js +252 -171
  420. package/dist/native/charts/src/engine/model.js.map +1 -1
  421. package/dist/native/charts/src/engine/overlay.cjs.map +1 -1
  422. package/dist/native/charts/src/engine/overlay.js.map +1 -1
  423. package/dist/native/charts/src/engine/presets.cjs +2 -2
  424. package/dist/native/charts/src/engine/presets.cjs.map +1 -1
  425. package/dist/native/charts/src/engine/presets.js +104 -90
  426. package/dist/native/charts/src/engine/presets.js.map +1 -1
  427. package/dist/native/charts/src/engine/scene.cjs +1 -1
  428. package/dist/native/charts/src/engine/scene.cjs.map +1 -1
  429. package/dist/native/charts/src/engine/scene.js +341 -188
  430. package/dist/native/charts/src/engine/scene.js.map +1 -1
  431. package/dist/native/charts/src/engine/shapes/bullet.cjs +1 -1
  432. package/dist/native/charts/src/engine/shapes/bullet.cjs.map +1 -1
  433. package/dist/native/charts/src/engine/shapes/bullet.js +110 -110
  434. package/dist/native/charts/src/engine/shapes/bullet.js.map +1 -1
  435. package/dist/native/charts/src/engine/shapes/calendar.cjs +1 -1
  436. package/dist/native/charts/src/engine/shapes/calendar.cjs.map +1 -1
  437. package/dist/native/charts/src/engine/shapes/calendar.js +21 -16
  438. package/dist/native/charts/src/engine/shapes/calendar.js.map +1 -1
  439. package/dist/native/charts/src/engine/shapes/chord.cjs +2 -0
  440. package/dist/native/charts/src/engine/shapes/chord.cjs.map +1 -0
  441. package/dist/native/charts/src/engine/shapes/chord.js +414 -0
  442. package/dist/native/charts/src/engine/shapes/chord.js.map +1 -0
  443. package/dist/native/charts/src/engine/shapes/draw.cjs +1 -1
  444. package/dist/native/charts/src/engine/shapes/draw.cjs.map +1 -1
  445. package/dist/native/charts/src/engine/shapes/draw.js +47 -17
  446. package/dist/native/charts/src/engine/shapes/draw.js.map +1 -1
  447. package/dist/native/charts/src/engine/shapes/hit.cjs +1 -1
  448. package/dist/native/charts/src/engine/shapes/hit.cjs.map +1 -1
  449. package/dist/native/charts/src/engine/shapes/hit.js +73 -44
  450. package/dist/native/charts/src/engine/shapes/hit.js.map +1 -1
  451. package/dist/native/charts/src/engine/shapes/labels.cjs +1 -1
  452. package/dist/native/charts/src/engine/shapes/labels.cjs.map +1 -1
  453. package/dist/native/charts/src/engine/shapes/labels.js +12 -4
  454. package/dist/native/charts/src/engine/shapes/labels.js.map +1 -1
  455. package/dist/native/charts/src/engine/shapes/layout.cjs +2 -2
  456. package/dist/native/charts/src/engine/shapes/layout.cjs.map +1 -1
  457. package/dist/native/charts/src/engine/shapes/layout.js +117 -90
  458. package/dist/native/charts/src/engine/shapes/layout.js.map +1 -1
  459. package/dist/native/charts/src/engine/shapes/scene.cjs +1 -1
  460. package/dist/native/charts/src/engine/shapes/scene.cjs.map +1 -1
  461. package/dist/native/charts/src/engine/shapes/scene.js +62 -19
  462. package/dist/native/charts/src/engine/shapes/scene.js.map +1 -1
  463. package/dist/native/components/Chart/scene.cjs +1 -1
  464. package/dist/native/components/Chart/scene.cjs.map +1 -1
  465. package/dist/native/components/Chart/scene.js +140 -71
  466. package/dist/native/components/Chart/scene.js.map +1 -1
  467. package/dist/native/components/Charts/charts.cjs +1 -1
  468. package/dist/native/components/Charts/charts.cjs.map +1 -1
  469. package/dist/native/components/Charts/charts.js +54 -42
  470. package/dist/native/components/Charts/charts.js.map +1 -1
  471. package/dist/native/components/Charts/types.d.cts +11 -0
  472. package/dist/native/components/Charts/types.d.ts +11 -0
  473. package/dist/native/components/ShapeChart/ShapeChartBase.cjs +1 -1
  474. package/dist/native/components/ShapeChart/ShapeChartBase.cjs.map +1 -1
  475. package/dist/native/components/ShapeChart/ShapeChartBase.js +1 -0
  476. package/dist/native/components/ShapeChart/ShapeChartBase.js.map +1 -1
  477. package/dist/native/components/ShapeChart/charts.cjs +1 -1
  478. package/dist/native/components/ShapeChart/charts.cjs.map +1 -1
  479. package/dist/native/components/ShapeChart/charts.d.cts +6 -1
  480. package/dist/native/components/ShapeChart/charts.d.ts +6 -1
  481. package/dist/native/components/ShapeChart/charts.js +138 -96
  482. package/dist/native/components/ShapeChart/charts.js.map +1 -1
  483. package/dist/native/components/ShapeChart/draw.cjs +1 -1
  484. package/dist/native/components/ShapeChart/draw.cjs.map +1 -1
  485. package/dist/native/components/ShapeChart/draw.d.cts +1 -1
  486. package/dist/native/components/ShapeChart/draw.d.ts +1 -1
  487. package/dist/native/components/ShapeChart/draw.js +26 -17
  488. package/dist/native/components/ShapeChart/draw.js.map +1 -1
  489. package/dist/native/components/ShapeChart/geometry.cjs +1 -1
  490. package/dist/native/components/ShapeChart/geometry.cjs.map +1 -1
  491. package/dist/native/components/ShapeChart/geometry.js +138 -59
  492. package/dist/native/components/ShapeChart/geometry.js.map +1 -1
  493. package/dist/native/components/ShapeChart/index.cjs +1 -1
  494. package/dist/native/components/ShapeChart/index.d.cts +1 -1
  495. package/dist/native/components/ShapeChart/index.d.ts +1 -1
  496. package/dist/native/components/ShapeChart/index.js +2 -2
  497. package/dist/native/components/ShapeChart/recorder.cjs +1 -1
  498. package/dist/native/components/ShapeChart/recorder.cjs.map +1 -1
  499. package/dist/native/components/ShapeChart/recorder.d.cts +10 -1
  500. package/dist/native/components/ShapeChart/recorder.d.ts +10 -1
  501. package/dist/native/components/ShapeChart/recorder.js +19 -10
  502. package/dist/native/components/ShapeChart/recorder.js.map +1 -1
  503. package/dist/native/components/ShapeChart/types.d.cts +92 -7
  504. package/dist/native/components/ShapeChart/types.d.ts +92 -7
  505. package/dist/native/index.cjs +1 -1
  506. package/dist/native/index.js +2 -2
  507. package/dist/native/source/components/Chart/scene.tsx +158 -14
  508. package/dist/native/source/components/Charts/charts.tsx +30 -2
  509. package/dist/native/source/components/Charts/types.ts +11 -0
  510. package/dist/native/source/components/ShapeChart/ShapeChartBase.tsx +2 -0
  511. package/dist/native/source/components/ShapeChart/charts.tsx +91 -35
  512. package/dist/native/source/components/ShapeChart/draw.tsx +39 -8
  513. package/dist/native/source/components/ShapeChart/geometry.ts +189 -8
  514. package/dist/native/source/components/ShapeChart/index.ts +1 -0
  515. package/dist/native/source/components/ShapeChart/recorder.ts +20 -5
  516. package/dist/native/source/components/ShapeChart/types.ts +96 -5
  517. package/dist/native/source/manifest.ts +1 -0
  518. package/dist/taro/charts.d.ts +25 -5
  519. package/dist/taro/index.js +3900 -2836
  520. package/dist/taro/shape-charts.d.ts +96 -4
  521. package/dist/uni/AreaChart.vue.d.ts +5 -1
  522. package/dist/uni/Badge.vue.d.ts +1 -1
  523. package/dist/uni/BarChart.vue.d.ts +5 -1
  524. package/dist/uni/BoxPlotChart.vue.d.ts +8 -0
  525. package/dist/uni/BubbleChart.vue.d.ts +4 -0
  526. package/dist/uni/BulletChart.vue.d.ts +4 -0
  527. package/dist/uni/CalendarHeatmap.vue.d.ts +2 -0
  528. package/dist/uni/CandlestickChart.vue.d.ts +4 -0
  529. package/dist/uni/Chart.vue.d.ts +4 -0
  530. package/dist/uni/ChordChart.vue +93 -0
  531. package/dist/uni/ChordChart.vue.d.ts +136 -0
  532. package/dist/uni/DonutChart.vue.d.ts +4 -0
  533. package/dist/uni/FunnelChart.vue.d.ts +4 -0
  534. package/dist/uni/GanttChart.vue.d.ts +4 -0
  535. package/dist/uni/GaugeChart.vue.d.ts +4 -0
  536. package/dist/uni/HeatmapChart.vue.d.ts +8 -2
  537. package/dist/uni/HistogramChart.vue.d.ts +4 -0
  538. package/dist/uni/HorizontalBarChart.vue.d.ts +3 -1
  539. package/dist/uni/LineChart.vue.d.ts +4 -0
  540. package/dist/uni/MixedChart.vue.d.ts +4 -0
  541. package/dist/uni/PieChart.vue.d.ts +4 -0
  542. package/dist/uni/QuadrantChart.vue.d.ts +4 -0
  543. package/dist/uni/RadarChart.vue.d.ts +4 -0
  544. package/dist/uni/RadialBarChart.vue.d.ts +4 -0
  545. package/dist/uni/RangeAreaChart.vue.d.ts +4 -0
  546. package/dist/uni/SankeyChart.vue.d.ts +4 -0
  547. package/dist/uni/ScatterChart.vue.d.ts +4 -0
  548. package/dist/uni/Sparkline.vue.d.ts +4 -0
  549. package/dist/uni/SunburstChart.vue.d.ts +4 -0
  550. package/dist/uni/ToastProvider.vue.d.ts +1 -1
  551. package/dist/uni/TreemapChart.vue.d.ts +4 -0
  552. package/dist/uni/WaterfallChart.vue.d.ts +9 -0
  553. package/dist/uni/chart-canvas.d.ts +3 -0
  554. package/dist/uni/chart-canvas.js +4 -0
  555. package/dist/uni/chart-types.d.ts +28 -4
  556. package/dist/uni/chart-types.js +26 -2
  557. package/dist/uni/charts-canvas.js +1 -1
  558. package/dist/uni/index.d.ts +2 -1
  559. package/dist/uni/index.js +1 -0
  560. package/dist/uni/manifest.d.ts +7 -0
  561. package/dist/uni/manifest.js +10 -0
  562. package/dist/uni/named-chart-options.d.ts +9 -2
  563. package/dist/uni/named-chart-options.js +18 -1
  564. package/dist/uni/shape-chart-canvas.d.ts +3 -1
  565. package/dist/uni/shape-chart-canvas.js +15 -24
  566. package/dist/uni/shape-chart-types.d.ts +52 -2
  567. package/dist/uni/shape-chart-types.js +44 -0
  568. package/dist/vue/charts-global.d.ts +48 -0
  569. package/dist/vue/charts.d.ts +18 -0
  570. package/dist/vue/charts.js +56 -0
  571. package/dist/vue/charts.js.map +1 -0
  572. package/dist/vue/components/Chart/BoxPlotChart.vue.d.ts +8 -0
  573. package/dist/vue/components/Chart/BoxPlotChart.vue.js.map +1 -1
  574. package/dist/vue/components/Chart/BoxPlotChart.vue_vue_type_script_setup_true_lang.js +8 -2
  575. package/dist/vue/components/Chart/BoxPlotChart.vue_vue_type_script_setup_true_lang.js.map +1 -1
  576. package/dist/vue/components/Chart/ChordChart.vue.d.ts +153 -0
  577. package/dist/vue/components/Chart/ChordChart.vue.js +7 -0
  578. package/dist/vue/components/Chart/ChordChart.vue.js.map +1 -0
  579. package/dist/vue/components/Chart/ChordChart.vue_vue_type_script_setup_true_lang.js +81 -0
  580. package/dist/vue/components/Chart/ChordChart.vue_vue_type_script_setup_true_lang.js.map +1 -0
  581. package/dist/vue/components/Chart/DependencyGraph.vue.d.ts +179 -0
  582. package/dist/vue/components/Chart/DependencyGraph.vue.js +7 -0
  583. package/dist/vue/components/Chart/DependencyGraph.vue.js.map +1 -0
  584. package/dist/vue/components/Chart/DependencyGraph.vue_vue_type_script_setup_true_lang.js +65 -0
  585. package/dist/vue/components/Chart/DependencyGraph.vue_vue_type_script_setup_true_lang.js.map +1 -0
  586. package/dist/vue/components/Chart/GanttChart.vue.d.ts +4 -0
  587. package/dist/vue/components/Chart/GanttChart.vue.js.map +1 -1
  588. package/dist/vue/components/Chart/GanttChart.vue_vue_type_script_setup_true_lang.js +4 -1
  589. package/dist/vue/components/Chart/GanttChart.vue_vue_type_script_setup_true_lang.js.map +1 -1
  590. package/dist/vue/components/Chart/GraphChart.vue.d.ts +184 -0
  591. package/dist/vue/components/Chart/GraphChart.vue.js +7 -0
  592. package/dist/vue/components/Chart/GraphChart.vue.js.map +1 -0
  593. package/dist/vue/components/Chart/GraphChart.vue_vue_type_script_setup_true_lang.js +62 -0
  594. package/dist/vue/components/Chart/GraphChart.vue_vue_type_script_setup_true_lang.js.map +1 -0
  595. package/dist/vue/components/Chart/HeatmapChart.vue.d.ts +9 -5
  596. package/dist/vue/components/Chart/HeatmapChart.vue.js.map +1 -1
  597. package/dist/vue/components/Chart/HeatmapChart.vue_vue_type_script_setup_true_lang.js +3 -1
  598. package/dist/vue/components/Chart/HeatmapChart.vue_vue_type_script_setup_true_lang.js.map +1 -1
  599. package/dist/vue/components/Chart/OrderBookHeatmap.vue.d.ts +2 -0
  600. package/dist/vue/components/Chart/TimeAndSales.vue.d.ts +2 -0
  601. package/dist/vue/components/Chart/TradingChart.vue.d.ts +49 -1
  602. package/dist/vue/components/Chart/TradingChart.vue.js.map +1 -1
  603. package/dist/vue/components/Chart/TradingChart.vue_vue_type_script_setup_true_lang.js +31 -0
  604. package/dist/vue/components/Chart/TradingChart.vue_vue_type_script_setup_true_lang.js.map +1 -1
  605. package/dist/vue/components/Chart/TreeChart.vue.d.ts +172 -0
  606. package/dist/vue/components/Chart/TreeChart.vue.js +7 -0
  607. package/dist/vue/components/Chart/TreeChart.vue.js.map +1 -0
  608. package/dist/vue/components/Chart/TreeChart.vue_vue_type_script_setup_true_lang.js +56 -0
  609. package/dist/vue/components/Chart/TreeChart.vue_vue_type_script_setup_true_lang.js.map +1 -0
  610. package/dist/vue/components/Chart/WaterfallChart.vue.d.ts +12 -1
  611. package/dist/vue/components/Chart/WaterfallChart.vue.js.map +1 -1
  612. package/dist/vue/components/Chart/WaterfallChart.vue_vue_type_script_setup_true_lang.js +8 -2
  613. package/dist/vue/components/Chart/WaterfallChart.vue_vue_type_script_setup_true_lang.js.map +1 -1
  614. package/dist/vue/components/Chart/graph.d.ts +153 -0
  615. package/dist/vue/components/Chart/graph.js +135 -0
  616. package/dist/vue/components/Chart/graph.js.map +1 -0
  617. package/dist/vue/components/Chart/index.d.ts +5 -1
  618. package/dist/vue/components/Chart/index.js +5 -1
  619. package/dist/vue/components/Chart/orderbook.d.ts +5 -1
  620. package/dist/vue/components/Chart/orderbook.js +2 -0
  621. package/dist/vue/components/Chart/orderbook.js.map +1 -1
  622. package/dist/vue/components/Chart/trading.d.ts +24 -2
  623. package/dist/vue/components/Chart/trading.js +8 -0
  624. package/dist/vue/components/Chart/trading.js.map +1 -1
  625. package/dist/vue/components/Chart/types.d.ts +74 -2
  626. package/dist/vue/global.d.ts +2 -38
  627. package/dist/vue/groups/charts.js +10 -2
  628. package/dist/vue/groups/charts.js.map +1 -1
  629. package/dist/vue/index.js +6 -2
  630. package/dist/vue/internal/register.d.ts +7 -0
  631. package/dist/vue/internal/register.js +14 -0
  632. package/dist/vue/internal/register.js.map +1 -0
  633. package/dist/vue/plugin.d.ts +9 -4
  634. package/dist/vue/plugin.js +6 -11
  635. package/dist/vue/plugin.js.map +1 -1
  636. package/dist/weapp/charts/canvas.js +1687 -147
  637. package/dist/weapp/charts/core.js +1 -0
  638. package/dist/weapp/chord-chart/index.js +1 -0
  639. package/dist/weapp/chord-chart/index.json +1 -0
  640. package/dist/weapp/chord-chart/index.wxml +1 -0
  641. package/dist/weapp/chord-chart/index.wxss +1 -0
  642. package/dist/weapp/controls.js +92 -32
  643. package/dist/weapp/types.d.ts +87 -4
  644. package/dist/web-components/components/chart/charts.d.ts +4 -2
  645. package/dist/web-components/components/chart/charts.js +8 -1
  646. package/dist/web-components/components/chart/charts.js.map +1 -1
  647. package/dist/web-components/components/chart/extended.d.ts +17 -7
  648. package/dist/web-components/components/chart/extended.js +23 -9
  649. package/dist/web-components/components/chart/extended.js.map +1 -1
  650. package/dist/web-components/components/chart/shapes-extended.d.ts +37 -1
  651. package/dist/web-components/components/chart/shapes-extended.js +27 -1
  652. package/dist/web-components/components/chart/shapes-extended.js.map +1 -1
  653. package/dist/web-components/components/graph/graph.d.ts +154 -0
  654. package/dist/web-components/components/graph/graph.js +149 -0
  655. package/dist/web-components/components/graph/graph.js.map +1 -0
  656. package/dist/web-components/components/trading-chart/trading-chart.d.ts +49 -2
  657. package/dist/web-components/components/trading-chart/trading-chart.js +62 -0
  658. package/dist/web-components/components/trading-chart/trading-chart.js.map +1 -1
  659. package/dist/web-components/elements/chart.d.ts +1 -1
  660. package/dist/web-components/elements/chart.js +6 -5
  661. package/dist/web-components/elements/chart.js.map +1 -1
  662. package/dist/web-components/elements/graph.d.ts +2 -0
  663. package/dist/web-components/elements/graph.js +12 -0
  664. package/dist/web-components/elements/graph.js.map +1 -0
  665. package/dist/web-components/html-custom-data.json +273 -4
  666. package/dist/web-components/types/react.d.ts +63 -4
  667. package/dist/web-components/types/solid.d.ts +55 -8
  668. package/dist/web-components/types/svelte.d.ts +55 -8
  669. package/dist/web-components/types/vue.d.ts +55 -4
  670. package/package.json +16 -1
@@ -163,12 +163,84 @@ var unpackColor = (packed) => [
163
163
  (packed >>> 16 & 255) / 255,
164
164
  (packed >>> 24 & 255) / 255
165
165
  ];
166
- /** Color at `t` (0-1) of a ramp through `stops` */
167
- var rampColor = (stops, t) => {
168
- if (stops.length === 1) return stops[0];
169
- const p = clamp01(t) * (stops.length - 1);
170
- const i = Math.min(stops.length - 2, Math.floor(p));
171
- return mix(stops[i], stops[i + 1], p - i);
166
+ /** Relative luminance (sRGB approximation) */
167
+ var luminance = (c) => .2126 * c[0] + .7152 * c[1] + .0722 * c[2];
168
+ var toLinear = (v) => v <= .04045 ? v / 12.92 : ((v + .055) / 1.055) ** 2.4;
169
+ var toGamma = (v) => v <= .0031308 ? v * 12.92 : 1.055 * Math.max(0, v) ** (1 / 2.4) - .055;
170
+ /** sRGB -> OKLab (perceptually uniform: even steps look even) */
171
+ var toOklab = (c) => {
172
+ const r = toLinear(c[0]);
173
+ const g = toLinear(c[1]);
174
+ const b = toLinear(c[2]);
175
+ const l = Math.cbrt(.4122214708 * r + .5363325363 * g + .0514459929 * b);
176
+ const m = Math.cbrt(.2119034982 * r + .6806995451 * g + .1073969566 * b);
177
+ const s = Math.cbrt(.0883024619 * r + .2817188376 * g + .6299787005 * b);
178
+ return [
179
+ .2104542553 * l + .793617785 * m - .0040720468 * s,
180
+ 1.9779984951 * l - 2.428592205 * m + .4505937099 * s,
181
+ .0259040371 * l + .7827717662 * m - .808675766 * s,
182
+ c[3]
183
+ ];
184
+ };
185
+ /** OKLab -> sRGB, clamped to the gamut */
186
+ var fromOklab = (c) => {
187
+ const l = (c[0] + .3963377774 * c[1] + .2158037573 * c[2]) ** 3;
188
+ const m = (c[0] - .1055613458 * c[1] - .0638541728 * c[2]) ** 3;
189
+ const s = (c[0] - .0894841775 * c[1] - 1.291485548 * c[2]) ** 3;
190
+ return [
191
+ clamp01(toGamma(4.0767416621 * l - 3.3077115913 * m + .2309699292 * s)),
192
+ clamp01(toGamma(-1.2684380046 * l + 2.6097574011 * m - .3413193965 * s)),
193
+ clamp01(toGamma(-.0041960863 * l - .7034186147 * m + 1.707614701 * s)),
194
+ c[3]
195
+ ];
196
+ };
197
+ /** Mixes two colors in OKLab (no muddy gray middle) */
198
+ var mixOklab = (a, b, t) => {
199
+ const p = toOklab(a);
200
+ const q = toOklab(b);
201
+ return fromOklab([
202
+ p[0] + (q[0] - p[0]) * t,
203
+ p[1] + (q[1] - p[1]) * t,
204
+ p[2] + (q[2] - p[2]) * t,
205
+ p[3] + (q[3] - p[3]) * t
206
+ ]);
207
+ };
208
+ /**
209
+ * A color with another OKLab lightness (0-1) and its chroma scaled by
210
+ * `chroma` (the hue is kept)
211
+ */
212
+ var withLightness = (c, lightness, chroma = 1) => {
213
+ const [, a, b, alpha] = toOklab(c);
214
+ return fromOklab([
215
+ lightness,
216
+ a * chroma,
217
+ b * chroma,
218
+ alpha
219
+ ]);
220
+ };
221
+ /**
222
+ * Packed colors (`packColor`) of `size` even steps along a ramp through
223
+ * `stops`, interpolated in OKLab: a lookup table for many values
224
+ */
225
+ var oklabRamp = (stops, size = 256) => {
226
+ const lut = new Uint32Array(size);
227
+ if (!stops.length) return lut;
228
+ const lab = stops.map(toOklab);
229
+ for (let k = 0; k < size; k++) {
230
+ const p = k / Math.max(1, size - 1) * (lab.length - 1);
231
+ const i = Math.min(lab.length - 2, Math.floor(p));
232
+ const a = lab[Math.max(0, i)];
233
+ const b = lab[Math.min(lab.length - 1, i + 1)];
234
+ const t = lab.length === 1 ? 0 : p - i;
235
+ const c = fromOklab([
236
+ a[0] + (b[0] - a[0]) * t,
237
+ a[1] + (b[1] - a[1]) * t,
238
+ a[2] + (b[2] - a[2]) * t,
239
+ a[3] + (b[3] - a[3]) * t
240
+ ]);
241
+ lut[k] = packColor(c) || 1;
242
+ }
243
+ return lut;
172
244
  };
173
245
  /**
174
246
  * Points of the curve through `x[i], y[i]` (`i` in `[start, end)`), as
@@ -422,7 +494,8 @@ var normalizeData = (data, resolveX, resolveY = toNumber) => {
422
494
  y0: null,
423
495
  q1: null,
424
496
  q3: null,
425
- outliers: null
497
+ outliers: null,
498
+ details: null
426
499
  };
427
500
  if (isColumns(data)) {
428
501
  const count = data.y.length;
@@ -472,6 +545,7 @@ var normalizeData = (data, resolveX, resolveY = toNumber) => {
472
545
  let q1 = null;
473
546
  let q3 = null;
474
547
  let outliers = null;
548
+ let details = null;
475
549
  const nanColumn = () => new Float64Array(count).fill(NaN);
476
550
  for (let i = 0; i < count; i++) {
477
551
  const item = list[i];
@@ -508,6 +582,10 @@ var normalizeData = (data, resolveX, resolveY = toNumber) => {
508
582
  outliers ??= new Array(count);
509
583
  outliers[i] = d.outliers;
510
584
  }
585
+ if (d.details !== void 0 && d.details.length) {
586
+ details ??= new Array(count);
587
+ details[i] = d.details;
588
+ }
511
589
  } else {
512
590
  x[i] = i;
513
591
  y[i] = NaN;
@@ -524,7 +602,8 @@ var normalizeData = (data, resolveX, resolveY = toNumber) => {
524
602
  y0,
525
603
  q1,
526
604
  q3,
527
- outliers
605
+ outliers,
606
+ details
528
607
  });
529
608
  };
530
609
  /** First index whose x is >= value (sorted x) */
@@ -691,6 +770,22 @@ var screenRect = (s, xa, xb, ya, yb) => {
691
770
  height: d - c
692
771
  };
693
772
  };
773
+ /**
774
+ * Inset (per side) and corner radius of heatmap cells of `width` ×
775
+ * `height` CSS pixels: a hairline apart (1px, 2px on large cells), corners
776
+ * of `radius` at most 20% of the cell; tiny cells touch
777
+ */
778
+ var heatCellStyle = (width, height, radius) => {
779
+ const size = Math.min(Math.abs(width), Math.abs(height));
780
+ if (!(size >= 4)) return {
781
+ inset: 0,
782
+ radius: 0
783
+ };
784
+ return {
785
+ inset: Math.round(Math.min(1, .5 + size / 96) * 4) / 4,
786
+ radius: Math.round(Math.max(0, Math.min(radius, size * .2)) * 4) / 4
787
+ };
788
+ };
694
789
  /** Room for the axes, then the plot area */
695
790
  var computePlot = (input) => {
696
791
  const { width, height, padding, fontSize } = input;
@@ -941,6 +1036,31 @@ var formatValue = (value, locale) => {
941
1036
  };
942
1037
  /** `formatValue` bound to a locale */
943
1038
  var valueFormatter = (locale) => (value) => formatValue(value, locale);
1039
+ var MINUTE$1 = 6e4;
1040
+ var HOUR$1 = 36e5;
1041
+ var DAY$1 = 864e5;
1042
+ /**
1043
+ * Length of a time range in its natural unit, in the words of a locale:
1044
+ * whole weeks (`4 weeks`, `4周`), else days (`26 days`, `26 jours`), hours
1045
+ * or minutes
1046
+ */
1047
+ var formatDuration = (ms, locale) => {
1048
+ if (!Number.isFinite(ms)) return "–";
1049
+ const abs = Math.abs(ms);
1050
+ const days = abs / DAY$1;
1051
+ const weeks = days / 7;
1052
+ const [value, unit] = days >= 7 && Math.abs(weeks - Math.round(weeks)) < 1e-6 ? [Math.round(weeks), "week"] : days >= 1 ? [Math.round(days * 10) / 10, "day"] : abs >= HOUR$1 ? [Math.round(abs / HOUR$1 * 10) / 10, "hour"] : [Math.round(abs / MINUTE$1), "minute"];
1053
+ try {
1054
+ return numberFormat(locale, {
1055
+ style: "unit",
1056
+ unit,
1057
+ unitDisplay: "long",
1058
+ maximumFractionDigits: 1
1059
+ }).format(value);
1060
+ } catch {
1061
+ return `${value} ${unit}${value === 1 ? "" : "s"}`;
1062
+ }
1063
+ };
944
1064
  /**
945
1065
  * `12.5` -> `12.5%` (`12,5 %` in French): one decimal at most, exactly one
946
1066
  * with `fixed` (`75.0%`)
@@ -969,7 +1089,13 @@ var CHART_LABELS = {
969
1089
  y: "y",
970
1090
  series: "Series",
971
1091
  chart: "Chart",
972
- chartOf: "Chart: {series}"
1092
+ chartOf: "Chart: {series}",
1093
+ start: "Start",
1094
+ end: "End",
1095
+ duration: "Duration",
1096
+ progress: "Progress",
1097
+ dependencies: "Depends on",
1098
+ outlier: "Outlier"
973
1099
  },
974
1100
  zh: {
975
1101
  open: "开盘",
@@ -985,7 +1111,13 @@ var CHART_LABELS = {
985
1111
  value: "数值",
986
1112
  series: "系列",
987
1113
  chart: "图表",
988
- chartOf: "图表:{series}"
1114
+ chartOf: "图表:{series}",
1115
+ start: "开始",
1116
+ end: "结束",
1117
+ duration: "时长",
1118
+ progress: "进度",
1119
+ dependencies: "前置任务",
1120
+ outlier: "异常值"
989
1121
  },
990
1122
  ja: {
991
1123
  open: "始値",
@@ -1001,7 +1133,13 @@ var CHART_LABELS = {
1001
1133
  value: "値",
1002
1134
  series: "系列",
1003
1135
  chart: "グラフ",
1004
- chartOf: "グラフ:{series}"
1136
+ chartOf: "グラフ:{series}",
1137
+ start: "開始",
1138
+ end: "終了",
1139
+ duration: "期間",
1140
+ progress: "進捗",
1141
+ dependencies: "先行タスク",
1142
+ outlier: "外れ値"
1005
1143
  },
1006
1144
  fr: {
1007
1145
  open: "Ouverture",
@@ -1017,7 +1155,13 @@ var CHART_LABELS = {
1017
1155
  value: "Valeur",
1018
1156
  series: "Série",
1019
1157
  chart: "Graphique",
1020
- chartOf: "Graphique : {series}"
1158
+ chartOf: "Graphique : {series}",
1159
+ start: "Début",
1160
+ end: "Fin",
1161
+ duration: "Durée",
1162
+ progress: "Avancement",
1163
+ dependencies: "Dépend de",
1164
+ outlier: "Valeur aberrante"
1021
1165
  }
1022
1166
  };
1023
1167
  /** Texts of a locale with the overrides */
@@ -1100,6 +1244,12 @@ var GridIndex = class {
1100
1244
  };
1101
1245
  //#endregion
1102
1246
  //#region ../charts/src/engine/model.ts
1247
+ /** Plotted units of a log axis: the base-10 logarithm of the values */
1248
+ var LOG_MAP = {
1249
+ scale: 1,
1250
+ offset: 0,
1251
+ log: true
1252
+ };
1103
1253
  var firstX = (data) => {
1104
1254
  if (typeof data === "object" && data !== null && !("length" in data)) {
1105
1255
  const xs = data.x;
@@ -1282,13 +1432,11 @@ var alignedDomain = (lo, hi, left, count) => {
1282
1432
  var mapped = /* @__PURE__ */ new WeakMap();
1283
1433
  /** Columns of a right-axis series in left axis units (cached with the data) */
1284
1434
  var mapColumns = (raw, map) => {
1285
- const key = `${map.scale},${map.offset}`;
1435
+ const key = `${map.scale},${map.offset},${!!map.log}`;
1286
1436
  const hit = mapped.get(raw);
1287
1437
  if (hit && hit.key === key) return hit.cols;
1288
- const f = (v) => v * map.scale + map.offset;
1438
+ const f = mapper(map);
1289
1439
  const column = (a) => a ? a.map(f) : null;
1290
- const lo = f(raw.yMin);
1291
- const hi = f(raw.yMax);
1292
1440
  const cols = {
1293
1441
  ...raw,
1294
1442
  y: raw.y.map(f),
@@ -1298,16 +1446,116 @@ var mapColumns = (raw, map) => {
1298
1446
  y0: column(raw.y0),
1299
1447
  q1: column(raw.q1),
1300
1448
  q3: column(raw.q3),
1301
- outliers: raw.outliers ? raw.outliers.map((list) => list?.map(f)) : null,
1302
- yMin: Math.min(lo, hi),
1303
- yMax: Math.max(lo, hi)
1304
- };
1449
+ outliers: raw.outliers ? raw.outliers.map((list) => list?.map(f)) : null
1450
+ };
1451
+ if (map.log) {
1452
+ const range = [Infinity, -Infinity];
1453
+ const add = (a) => {
1454
+ if (!a) return;
1455
+ for (let i = 0; i < a.length; i++) {
1456
+ const v = a[i];
1457
+ if (!Number.isFinite(v)) continue;
1458
+ if (v < range[0]) range[0] = v;
1459
+ if (v > range[1]) range[1] = v;
1460
+ }
1461
+ };
1462
+ for (const c of [
1463
+ cols.y,
1464
+ cols.y0,
1465
+ cols.high,
1466
+ cols.low,
1467
+ cols.q1,
1468
+ cols.q3
1469
+ ]) add(c);
1470
+ cols.outliers?.forEach((list) => add(list));
1471
+ cols.yMin = range[0] <= range[1] ? range[0] : NaN;
1472
+ cols.yMax = range[0] <= range[1] ? range[1] : NaN;
1473
+ } else {
1474
+ const lo = f(raw.yMin);
1475
+ const hi = f(raw.yMax);
1476
+ cols.yMin = Math.min(lo, hi);
1477
+ cols.yMax = Math.max(lo, hi);
1478
+ }
1305
1479
  mapped.set(raw, {
1306
1480
  key,
1307
1481
  cols
1308
1482
  });
1309
1483
  return cols;
1310
1484
  };
1485
+ /** A log range widened to whole decades (`[0.3, 2.4]` -> `[0, 3]`) */
1486
+ var decades = (range) => {
1487
+ const lo = Math.floor(range[0] + 1e-9);
1488
+ const hi = Math.ceil(range[1] - 1e-9);
1489
+ return [lo, hi > lo ? hi : lo + 1];
1490
+ };
1491
+ /**
1492
+ * Plots a series through a map: its columns, bars, stacks and lower
1493
+ * edges (bars / areas of the right axis start at `zero`)
1494
+ */
1495
+ var logColumns = (s, map, zero = -Infinity) => {
1496
+ const f = mapper(map);
1497
+ const column = (a) => a ? a.map(f) : null;
1498
+ const rawBase = s.stackBase;
1499
+ s.cols = mapColumns(s.raw, map);
1500
+ s.barBase = s.barBase && !s.floating ? s.barBase.map((v) => v === 0 ? map.log ? -Infinity : f(0) : f(v)) : column(s.barBase);
1501
+ s.barTop = column(s.barTop);
1502
+ s.stackTop = column(s.stackTop);
1503
+ s.stackBase = rawBase && rawBase === s.raw.y0 ? s.cols.y0 : rawBase ? column(rawBase) : s.type === "area" ? new Float64Array(s.cols.count).fill(zero) : null;
1504
+ };
1505
+ /** Value -> plotted units of a map (`-Infinity` for 0 on log axes) */
1506
+ var mapper = (map) => (v) => (map.log ? Math.log10(v) : v) * map.scale + map.offset;
1507
+ /** Value of the y axis -> plotted y (the logarithm on log axes) */
1508
+ var toPlotY = (model, value) => model.y.type === "log" ? Math.log10(value) : value;
1509
+ /** Plotted y -> value of the y axis */
1510
+ var fromPlotY = (model, value) => model.y.type === "log" ? 10 ** value : value;
1511
+ /** Replaces the bases of bars / areas on log axes (`-Infinity`) by the bottom of the axis */
1512
+ var floorBases = (s, floor) => {
1513
+ for (const a of [s.barBase, s.stackBase]) {
1514
+ if (!a) continue;
1515
+ for (let i = 0; i < a.length; i++) if (a[i] === -Infinity) a[i] = floor;
1516
+ }
1517
+ };
1518
+ /** Position (0-1) of a heatmap value on its color ramp */
1519
+ var heatPosition = (s, v) => {
1520
+ const [lo, hi] = s.valueRange;
1521
+ const mid = s.colorMidpoint;
1522
+ let t;
1523
+ if (mid !== null && mid > lo && mid < hi) t = v < mid ? (v - lo) / (mid - lo) * .5 : .5 + (v - mid) / (hi - mid) * .5;
1524
+ else t = (v - lo) / (hi - lo || 1);
1525
+ return t < 0 ? 0 : t > 1 ? 1 : t;
1526
+ };
1527
+ /**
1528
+ * Built-in ramps of heatmaps, perceptual (OKLab) and theme-aware: light
1529
+ * themes go from a near-white tint to a deep hue, dark themes from a dark
1530
+ * tint of the surface to a bright saturated hue; diverging ramps meet in a
1531
+ * neutral middle
1532
+ */
1533
+ var heatmapStops = (scheme, color, theme, negative) => {
1534
+ const dark = luminance(theme.background) < .4;
1535
+ if (scheme === "diverging") {
1536
+ const neutral = mixOklab(theme.surface, theme.textMuted, dark ? .12 : .08);
1537
+ const end = (c) => dark ? withLightness(c, .7, 1.25) : withLightness(c, .5, 1.05);
1538
+ const side = (c) => mixOklab(neutral, end(c), .5);
1539
+ return [
1540
+ end(negative),
1541
+ side(negative),
1542
+ neutral,
1543
+ side(color),
1544
+ end(color)
1545
+ ];
1546
+ }
1547
+ return dark ? [
1548
+ mixOklab(theme.surface, color, .14),
1549
+ withLightness(color, .46, .95),
1550
+ withLightness(color, .64, 1.2),
1551
+ withLightness(color, .8, 1.15)
1552
+ ] : [
1553
+ mixOklab(theme.surface, color, .06),
1554
+ withLightness(color, .8, .6),
1555
+ withLightness(color, .58, 1),
1556
+ withLightness(color, .36, .9)
1557
+ ];
1558
+ };
1311
1559
  var buildModel = (options, theme, hidden, cache, resolver = null) => {
1312
1560
  const resolve = resolver ?? theme.resolve ?? ((value, fallback) => resolveStaticColor(value, {}, fallback));
1313
1561
  const input = options.series;
@@ -1325,7 +1573,8 @@ var buildModel = (options, theme, hidden, cache, resolver = null) => {
1325
1573
  const yOpts = options.yAxis;
1326
1574
  const heatmapData = input.filter((s) => s.type === "heatmap").map((s) => s.data);
1327
1575
  const yCategories = yOpts?.type === "category" || !yOpts?.type && heatmapData.length ? [...yOpts?.categories ?? collectYCategories(heatmapData)] : [];
1328
- const yType = yOpts?.type === "category" || yCategories.length ? "category" : yOpts?.type === "time" || !yOpts?.type && hasDateY(datas) ? "time" : "linear";
1576
+ const yType = yOpts?.type === "category" || yCategories.length ? "category" : yOpts?.type === "time" || !yOpts?.type && hasDateY(datas) ? "time" : yOpts?.type === "log" ? "log" : "linear";
1577
+ const yLog = yType === "log";
1329
1578
  const yCategoryMap = new Map(yCategories.map((c, i) => [c, i]));
1330
1579
  const resolveY = (v) => typeof v === "number" ? v : typeof v === "string" ? yType === "category" ? yCategoryMap.get(v) ?? NaN : yType === "time" ? Date.parse(v) : Number(v) : v instanceof Date ? v.getTime() : NaN;
1331
1580
  const resolverKey = `${xType}|${categories.join("")}|${yType}|${yCategories.join("")}`;
@@ -1362,20 +1611,36 @@ var buildModel = (options, theme, hidden, cache, resolver = null) => {
1362
1611
  let colorScale = [];
1363
1612
  let valueRange = [0, 1];
1364
1613
  let cellColors = null;
1614
+ let colorMidpoint = null;
1615
+ let colorLut = null;
1365
1616
  if (type === "heatmap") {
1366
- colorScale = s.colorScale && s.colorScale.length ? s.colorScale.map((c) => resolve(c, color)) : [mix(theme.background, color, .08), color];
1617
+ const scale = s.colorScale;
1618
+ const scheme = scale === "diverging" ? "diverging" : "sequential";
1619
+ colorScale = typeof scale === "object" && scale.length ? scale.map((c) => resolve(c, color)) : heatmapStops(scheme, color, theme, resolve(DEFAULT_DOWN, [
1620
+ .86,
1621
+ .15,
1622
+ .15,
1623
+ 1
1624
+ ]));
1367
1625
  valueRange = s.valueRange ? [s.valueRange[0], s.valueRange[1]] : [cols.valueMin, cols.valueMax];
1368
1626
  if (!Number.isFinite(valueRange[0])) valueRange = [0, 1];
1369
- const values = cols.value ?? cols.y;
1370
1627
  const [lo, hi] = valueRange;
1371
- const span = hi - lo || 1;
1628
+ colorMidpoint = s.colorMidpoint ?? (scheme === "diverging" && typeof scale !== "object" ? lo < 0 && hi > 0 ? 0 : (lo + hi) / 2 : null);
1629
+ const lut = oklabRamp(colorScale);
1630
+ colorLut = lut;
1631
+ const values = cols.value ?? cols.y;
1632
+ const ramp = {
1633
+ valueRange,
1634
+ colorMidpoint
1635
+ };
1372
1636
  cellColors = new Uint32Array(cols.count);
1373
1637
  for (let i = 0; i < cols.count; i++) {
1374
1638
  const v = values[i];
1375
1639
  if (!Number.isFinite(v) || !Number.isFinite(cols.y[i])) continue;
1376
- cellColors[i] = packColor(rampColor(colorScale, (v - lo) / span));
1640
+ cellColors[i] = lut[Math.round(heatPosition(ramp, v) * 255)];
1377
1641
  }
1378
1642
  }
1643
+ const connector = s.connector ? typeof s.connector === "object" ? s.connector : {} : null;
1379
1644
  const id = s.id ?? String(index);
1380
1645
  return {
1381
1646
  index,
@@ -1421,6 +1686,16 @@ var buildModel = (options, theme, hidden, cache, resolver = null) => {
1421
1686
  },
1422
1687
  colorScale,
1423
1688
  valueRange,
1689
+ colorMidpoint,
1690
+ colorLut,
1691
+ tooltip: s.tooltip !== false,
1692
+ outlierShape: s.outlierShape ?? "hollow",
1693
+ outlierSize: s.outlierSize ?? s.pointSize ?? 7,
1694
+ connector: connector && type === "bar" ? {
1695
+ color: connector.color ? resolve(connector.color, theme.textMuted) : theme.textMuted,
1696
+ dash: [...connector.dash ?? [3, 3]],
1697
+ width: connector.width ?? 1
1698
+ } : null,
1424
1699
  radius: s.radius ?? (type === "heatmap" ? 2 : type === "boxplot" ? 0 : 3),
1425
1700
  format: s.format,
1426
1701
  valueName: s.valueName
@@ -1521,14 +1796,18 @@ var buildModel = (options, theme, hidden, cache, resolver = null) => {
1521
1796
  if (xOpts?.min !== void 0) xRange[0] = xOpts.min;
1522
1797
  if (xOpts?.max !== void 0) xRange[1] = xOpts.max;
1523
1798
  xRange = ensureSpan(xRange[0], xRange[1]);
1524
- const valuesOf = (list, zero) => {
1799
+ if (yLog) for (const s of series) {
1800
+ if (s.yAxis === "right" || s.type === "heatmap") continue;
1801
+ logColumns(s, LOG_MAP);
1802
+ }
1803
+ const valuesOf = (list, zero, log = false) => {
1525
1804
  const values = [];
1526
1805
  for (const s of list) if (s.type === "bar" && s.barBase && s.barTop) values.push(...extent(s.barBase), ...extent(s.barTop));
1527
1806
  else if (s.stackBase && s.stackTop) values.push(...extent(s.stackBase), ...extent(s.stackTop));
1528
1807
  else if (s.type === "heatmap") values.push(s.cols.yMin - s.cellHalf.y, s.cols.yMax + s.cellHalf.y);
1529
1808
  else values.push(s.cols.yMin, s.cols.yMax);
1530
1809
  const listBars = list.filter((s) => s.type === "bar");
1531
- if (listBars.some((s) => !s.floating) || zero) values.push(0);
1810
+ if (!log && (listBars.some((s) => !s.floating) || zero)) values.push(0);
1532
1811
  if (listBars.some((s) => s.showLabels)) {
1533
1812
  const [lo, hi] = extent(values);
1534
1813
  if (hi > 0) values.push(hi + (hi - Math.min(0, lo)) * .1);
@@ -1542,7 +1821,7 @@ var buildModel = (options, theme, hidden, cache, resolver = null) => {
1542
1821
  let yRange;
1543
1822
  if (yType === "category") yRange = [-.5, Math.max(1, yCategories.length) - .5];
1544
1823
  else {
1545
- const yValues = valuesOf(leftSeries, yOpts?.zero);
1824
+ const yValues = valuesOf(leftSeries, yOpts?.zero, yLog);
1546
1825
  const filled = leftBars.length > 0 || leftSeries.some((s) => s.type === "area");
1547
1826
  yRange = ensureSpan(...extent(yValues));
1548
1827
  if (series.every((s) => s.type === "scatter")) {
@@ -1553,43 +1832,50 @@ var buildModel = (options, theme, hidden, cache, resolver = null) => {
1553
1832
  yRange = [yRange[0] - pad, yRange[1] + pad];
1554
1833
  }
1555
1834
  if ((yOpts?.nice ?? !heatmaps.length) && yType === "linear") yRange = niceDomain(yRange[0], yRange[1], yOpts?.tickCount ?? 5);
1835
+ if (yLog && yOpts?.nice !== false) yRange = decades(yRange);
1556
1836
  if (percent && (bars.length || stackedLines.length)) yRange = [extent(yValues)[0] < 0 ? -100 : 0, 100];
1557
- if (filled && !yOpts?.zero) {
1837
+ if (filled && !yOpts?.zero && !yLog) {
1558
1838
  if (yRange[0] < 0 && extent(yValues)[0] >= 0) yRange[0] = 0;
1559
1839
  }
1560
1840
  }
1561
- if (yOpts?.min !== void 0) yRange[0] = yOpts.min;
1562
- if (yOpts?.max !== void 0) yRange[1] = yOpts.max;
1841
+ const yBound = (v) => yLog ? Math.log10(v) : v;
1842
+ if (yOpts?.min !== void 0) yRange[0] = yBound(yOpts.min);
1843
+ if (yOpts?.max !== void 0) yRange[1] = yBound(yOpts.max);
1563
1844
  yRange = ensureSpan(yRange[0], yRange[1]);
1845
+ if (yLog) {
1846
+ for (const s of series) if (s.yAxis === "left") floorBases(s, yRange[0]);
1847
+ }
1564
1848
  const y2Opts = options.yAxis2;
1565
1849
  let y2 = null;
1566
1850
  let y2Map = null;
1567
1851
  const rightSeries = series.filter((s) => s.yAxis === "right");
1568
1852
  if (rightSeries.length && yType !== "category") {
1569
- const [lo, hi] = ensureSpan(...extent(valuesOf(rightSeries.filter((s) => !s.hidden), y2Opts?.zero)));
1570
- let domain = y2Opts?.nice === false ? [lo, hi] : alignedDomain(lo, hi, yRange, yOpts?.tickCount ?? 5);
1571
- if (y2Opts?.min !== void 0) domain[0] = y2Opts.min;
1572
- if (y2Opts?.max !== void 0) domain[1] = y2Opts.max;
1853
+ const y2Log = y2Opts?.type === "log";
1854
+ const rightVisible = rightSeries.filter((s) => !s.hidden);
1855
+ const [lo, hi] = ensureSpan(...extent(y2Log ? rightVisible.flatMap((s) => {
1856
+ const c = mapColumns(s.raw, LOG_MAP);
1857
+ return [c.yMin, c.yMax];
1858
+ }) : valuesOf(rightVisible, y2Opts?.zero)));
1859
+ let domain = y2Opts?.nice === false ? [lo, hi] : y2Log ? decades([lo, hi]) : alignedDomain(lo, hi, yRange, yOpts?.tickCount ?? 5);
1860
+ const y2Bound = (v) => y2Log ? Math.log10(v) : v;
1861
+ if (y2Opts?.min !== void 0) domain[0] = y2Bound(y2Opts.min);
1862
+ if (y2Opts?.max !== void 0) domain[1] = y2Bound(y2Opts.max);
1573
1863
  domain = ensureSpan(domain[0], domain[1]);
1574
1864
  const scale = (yRange[1] - yRange[0]) / (domain[1] - domain[0]);
1575
1865
  const map = {
1576
1866
  scale,
1577
- offset: yRange[0] - domain[0] * scale
1867
+ offset: yRange[0] - domain[0] * scale,
1868
+ log: y2Log
1578
1869
  };
1579
1870
  y2Map = map;
1580
- const f = (v) => v * map.scale + map.offset;
1581
- const column = (a) => a ? a.map(f) : null;
1582
- const zero = f(Math.min(Math.max(0, domain[0]), domain[1]));
1871
+ const zero = y2Log ? yRange[0] : mapper(map)(Math.min(Math.max(0, domain[0]), domain[1]));
1583
1872
  for (const s of rightSeries) {
1584
- const rawBase = s.stackBase;
1585
- s.cols = mapColumns(s.raw, map);
1586
- s.barBase = column(s.barBase);
1587
- s.barTop = column(s.barTop);
1588
- s.stackTop = column(s.stackTop);
1589
- s.stackBase = rawBase && rawBase === s.raw.y0 ? s.cols.y0 : rawBase ? column(rawBase) : s.type === "area" ? new Float64Array(s.cols.count).fill(zero) : null;
1873
+ logColumns(s, map, zero);
1874
+ floorBases(s, yRange[0]);
1590
1875
  }
1591
- y2 = axisModel(y2Opts, "linear", [], false, locale);
1876
+ y2 = axisModel(y2Opts, y2Log ? "log" : "linear", [], false, locale);
1592
1877
  }
1878
+ const timeline = yType === "time" && series.some((s) => s.type === "bar") && series.every((s) => s.type === "bar" ? s.floating : s.type === "scatter");
1593
1879
  const zoomOption = options.interaction === false ? false : options.interaction === true || options.interaction === void 0 ? true : options.interaction.zoom ?? true;
1594
1880
  const zoomAxes = zoomOption === false ? {
1595
1881
  x: false,
@@ -1621,8 +1907,8 @@ var buildModel = (options, theme, hidden, cache, resolver = null) => {
1621
1907
  },
1622
1908
  allScatter,
1623
1909
  zoom: zoomAxes,
1624
- tooltipMode: tooltipOptions?.mode ?? (allScatter ? "nearest" : "axis"),
1625
- baseline: Math.min(Math.max(0, yRange[0]), yRange[1]),
1910
+ tooltipMode: tooltipOptions?.mode ?? (allScatter ? "nearest" : timeline ? "item" : "axis"),
1911
+ baseline: yLog ? yRange[0] : Math.min(Math.max(0, yRange[0]), yRange[1]),
1626
1912
  minSpan: {
1627
1913
  x: xType === "category" ? 1 : (xRange[1] - xRange[0]) * 1e-7,
1628
1914
  y: yType === "category" ? 1 : (yRange[1] - yRange[0]) * 1e-7
@@ -1892,6 +2178,19 @@ var drawForeground = (ctx, input) => {
1892
2178
  ctx.beginPath();
1893
2179
  ctx.rect(plot.x, plot.y, plot.width, plot.height);
1894
2180
  ctx.clip();
2181
+ for (const c of input.connectors ?? []) {
2182
+ ctx.strokeStyle = c.color;
2183
+ ctx.lineWidth = c.width;
2184
+ ctx.setLineDash([...c.dash]);
2185
+ ctx.beginPath();
2186
+ const along = c.y0 === c.y1;
2187
+ const x0 = along ? c.x0 : crisp(c.x0);
2188
+ const y0 = along ? crisp(c.y0) : c.y0;
2189
+ ctx.moveTo(x0, y0);
2190
+ ctx.lineTo(along ? c.x1 : x0, along ? y0 : c.y1);
2191
+ ctx.stroke();
2192
+ }
2193
+ ctx.setLineDash([]);
1895
2194
  const halo = toCss(theme.background, .9);
1896
2195
  const occupied = [];
1897
2196
  const labelHeight = theme.fontSize + 4;
@@ -2302,6 +2601,7 @@ var axisTicks = (axis, range, count) => {
2302
2601
  }
2303
2602
  const values = linearTicks(min, max, count);
2304
2603
  const step = tickStep(min, max, count);
2604
+ if (axis.type === "log") return logTicks(axis, min, max, count);
2305
2605
  const tick = axis.format ?? tickFormatter(step, Math.max(Math.abs(min), Math.abs(max)), axis.locale);
2306
2606
  return {
2307
2607
  values,
@@ -2309,6 +2609,41 @@ var axisTicks = (axis, range, count) => {
2309
2609
  formatValue: axis.format ?? ((value) => formatValue(value, axis.locale))
2310
2610
  };
2311
2611
  };
2612
+ /**
2613
+ * Ticks of a log axis (`min` / `max` are exponents): every decade, with 2
2614
+ * and 5 between them on short ranges, every few decades on long ones;
2615
+ * labelled with the values (`1k`, `10k`)
2616
+ */
2617
+ var logTicks = (axis, min, max, count) => {
2618
+ const span = max - min;
2619
+ const values = [];
2620
+ const raw = [];
2621
+ const push = (v) => {
2622
+ const e = Math.log10(v);
2623
+ if (e >= min - 1e-9 && e <= max + 1e-9) {
2624
+ values.push(e);
2625
+ raw.push(v);
2626
+ }
2627
+ };
2628
+ if (span < 1) {
2629
+ for (const v of linearTicks(10 ** min, 10 ** max, count)) if (v > 0) push(v);
2630
+ } else {
2631
+ const every = Math.max(1, Math.ceil(span / Math.max(1, count)));
2632
+ const between = span * 3 <= count * 1.6 ? [2, 5] : [];
2633
+ for (let e = Math.floor(min); e <= Math.ceil(max); e++) {
2634
+ if (e % every !== 0) continue;
2635
+ const decade = Number((10 ** e).toPrecision(12));
2636
+ push(decade);
2637
+ for (const m of between) push(Number((m * decade).toPrecision(12)));
2638
+ }
2639
+ }
2640
+ const label = axis.format ?? ((v) => formatCompact(v, 2, axis.locale));
2641
+ return {
2642
+ values,
2643
+ labels: raw.map(label),
2644
+ formatValue: axis.format ?? ((value) => formatValue(value, axis.locale))
2645
+ };
2646
+ };
2312
2647
  var DEFAULT_PADDING = {
2313
2648
  top: 12,
2314
2649
  right: 16,
@@ -2316,9 +2651,13 @@ var DEFAULT_PADDING = {
2316
2651
  left: 4
2317
2652
  };
2318
2653
  var fallbackResolve = (_value, fallback) => fallback;
2319
- /** Annotation colors resolved against the theme */
2320
- var resolveAnnotations = (annotations, theme) => {
2654
+ /**
2655
+ * Annotation colors resolved against the theme; `mapY` turns y values into
2656
+ * plotted units (log axes)
2657
+ */
2658
+ var resolveAnnotations = (annotations, theme, mapY) => {
2321
2659
  const resolve = theme.resolve ?? fallbackResolve;
2660
+ const y = (v) => mapY && v !== void 0 ? mapY(v) : v;
2322
2661
  return (annotations ?? []).map((a) => {
2323
2662
  if (a.type === "rect") {
2324
2663
  const color = a.color ? resolve(a.color, theme.primary) : theme.primary;
@@ -2326,8 +2665,8 @@ var resolveAnnotations = (annotations, theme) => {
2326
2665
  type: "rect",
2327
2666
  x0: a.x0,
2328
2667
  x1: a.x1,
2329
- y0: a.y0,
2330
- y1: a.y1,
2668
+ y0: y(a.y0),
2669
+ y1: y(a.y1),
2331
2670
  color,
2332
2671
  opacity: a.opacity ?? .08,
2333
2672
  label: a.label,
@@ -2338,7 +2677,7 @@ var resolveAnnotations = (annotations, theme) => {
2338
2677
  if (a.type === "text") return {
2339
2678
  type: "text",
2340
2679
  x: a.x,
2341
- y: a.y,
2680
+ y: y(a.y),
2342
2681
  text: a.text,
2343
2682
  anchor: a.anchor ?? "center",
2344
2683
  color: a.color ? resolve(a.color, theme.textMuted) : theme.textMuted,
@@ -2347,7 +2686,7 @@ var resolveAnnotations = (annotations, theme) => {
2347
2686
  return {
2348
2687
  type: "line",
2349
2688
  axis: a.axis,
2350
- value: a.value,
2689
+ value: a.axis === "y" ? y(a.value) : a.value,
2351
2690
  color: a.color ? resolve(a.color, theme.textMuted) : theme.textMuted,
2352
2691
  width: a.width ?? 1,
2353
2692
  dash: [...a.dash ?? [4, 4]],
@@ -2363,7 +2702,7 @@ var layoutChart = (input) => {
2363
2702
  const yTicks = axisTicks(model.y, view.y, yCount);
2364
2703
  let yLabelWidth = 0;
2365
2704
  if (model.y.visible) for (const label of yTicks.labels) yLabelWidth = Math.max(yLabelWidth, measure(label));
2366
- const y2Ticks = rightTicks(model, yTicks);
2705
+ const y2Ticks = rightTicks(model, yTicks, view.y, yCount);
2367
2706
  let y2LabelWidth = 0;
2368
2707
  if (y2Ticks && model.y2?.visible) for (const label of y2Ticks.labels) y2LabelWidth = Math.max(y2LabelWidth, measure(label));
2369
2708
  let categoryWidth = 48;
@@ -2398,11 +2737,23 @@ var layoutChart = (input) => {
2398
2737
  y2Ticks
2399
2738
  };
2400
2739
  };
2401
- /** Right axis ticks: the left ticks labelled in right axis units */
2402
- var rightTicks = (model, yTicks) => {
2740
+ /**
2741
+ * Right axis ticks: the left ticks labelled in right axis units; log axes
2742
+ * get their own decades
2743
+ */
2744
+ var rightTicks = (model, yTicks, view, count) => {
2403
2745
  const axis = model.y2;
2404
2746
  const map = model.y2Map;
2405
2747
  if (!axis || !map || !map.scale) return null;
2748
+ if (map.log) {
2749
+ const a = (view[0] - map.offset) / map.scale;
2750
+ const b = (view[1] - map.offset) / map.scale;
2751
+ const ticks = axisTicks(axis, [Math.min(a, b), Math.max(a, b)], count);
2752
+ return {
2753
+ ...ticks,
2754
+ values: ticks.values.map((e) => e * map.scale + map.offset)
2755
+ };
2756
+ }
2406
2757
  const raw = yTicks.values.map((v) => (v - map.offset) / map.scale);
2407
2758
  const step = raw.length > 1 ? Math.abs(raw[1] - raw[0]) : 1;
2408
2759
  let maxAbs = 0;
@@ -2546,6 +2897,25 @@ var candidateOf = (s, i, px, py, sc) => {
2546
2897
  inside
2547
2898
  };
2548
2899
  };
2900
+ /** Outlier of a box under a pixel (`undefined` when none is in reach) */
2901
+ var outlierAt = (s, i, px, py, sc, slop) => {
2902
+ const list = s.cols.outliers?.[i];
2903
+ if (!list) return void 0;
2904
+ const center = sc.xToPx(s.cols.x[i] + slotOffset(s));
2905
+ const ax = alongX(sc, px, py) - center;
2906
+ const ay = alongY(sc, px, py);
2907
+ const reach = s.outlierSize / 2 + 4 + slop;
2908
+ let best;
2909
+ let bestDist = reach;
2910
+ list.forEach((v, k) => {
2911
+ const d = Math.hypot(ax, sc.yToPx(v) - ay);
2912
+ if (d <= bestDist) {
2913
+ bestDist = d;
2914
+ best = s.raw.outliers?.[i]?.[k] ?? v;
2915
+ }
2916
+ });
2917
+ return best;
2918
+ };
2549
2919
  /** Diameter of a scatter dot */
2550
2920
  var dotSize = (s, i) => s.cols.size && s.cols.size[i] > 0 ? s.cols.size[i] : s.pointSize;
2551
2921
  var maxSizes = /* @__PURE__ */ new WeakMap();
@@ -2648,7 +3018,11 @@ var hoverItemOf = (s, index) => {
2648
3018
  var eventOf = (candidates, xTicks) => {
2649
3019
  if (!candidates.length) return null;
2650
3020
  candidates.sort((a, b) => a.series.index - b.series.index);
2651
- const items = candidates.map((c) => hoverItemOf(c.series, c.index));
3021
+ const items = candidates.map((c) => {
3022
+ const item = hoverItemOf(c.series, c.index);
3023
+ if (c.outlier !== void 0) item.outlier = c.outlier;
3024
+ return item;
3025
+ });
2652
3026
  const x = items[0].x;
2653
3027
  return {
2654
3028
  items,
@@ -2669,7 +3043,7 @@ var hitTest = (model, sc, xTicks, px, py, slop = 0) => {
2669
3043
  const scatter = [];
2670
3044
  const others = [];
2671
3045
  for (const s of model.series) {
2672
- if (s.hidden || s.cols.count === 0) continue;
3046
+ if (s.hidden || !s.tooltip || s.cols.count === 0) continue;
2673
3047
  if (s.type === "scatter") {
2674
3048
  const i = nearestScatter(s, px, py, sc, slop);
2675
3049
  if (i >= 0) scatter.push(candidateOf(s, i, px, py, sc));
@@ -2683,9 +3057,23 @@ var hitTest = (model, sc, xTicks, px, py, slop = 0) => {
2683
3057
  }
2684
3058
  } else {
2685
3059
  const i = nearestX(s, at.x);
2686
- if (i >= 0) others.push(candidateOf(s, i, px, py, sc));
3060
+ if (i < 0) continue;
3061
+ const c = candidateOf(s, i, px, py, sc);
3062
+ if (s.type === "boxplot") {
3063
+ c.outlier = outlierAt(s, i, px, py, sc, slop);
3064
+ if (c.outlier !== void 0) {
3065
+ c.inside = true;
3066
+ c.dist = 0;
3067
+ }
3068
+ }
3069
+ others.push(c);
2687
3070
  }
2688
3071
  }
3072
+ if (model.tooltipMode === "item") {
3073
+ const all = [...scatter, ...others].filter((c) => c.inside || c.series.type === "scatter" || (c.series.type === "line" || c.series.type === "area") && c.dist <= 8 + slop);
3074
+ if (!all.length) return null;
3075
+ return eventOf([all.reduce((a, b) => b.dist < a.dist || b.dist === a.dist && b.series.index > a.series.index ? b : a)], xTicks);
3076
+ }
2689
3077
  if (model.tooltipMode === "nearest") {
2690
3078
  const all = [...scatter, ...others].filter((c) => c.inside || c.series.type === "scatter" || c.dist <= 32 + slop);
2691
3079
  if (!all.length) return null;
@@ -2718,6 +3106,12 @@ var CHANGE_PERCENT = {
2718
3106
  minimumFractionDigits: 2,
2719
3107
  maximumFractionDigits: 2
2720
3108
  };
3109
+ /** Extra rows of a point (`details` of its datum) */
3110
+ var detailRows = (s, index) => s.raw.details?.[index]?.map((d) => ({
3111
+ color: null,
3112
+ name: d.name,
3113
+ value: d.value
3114
+ })) ?? [];
2721
3115
  /**
2722
3116
  * Default tooltip content of a hover payload; `y2Ticks` formats the values
2723
3117
  * of the right axis series
@@ -2728,6 +3122,32 @@ var tooltipContent$1 = (model, event, yTicks, y2Ticks = null) => {
2728
3122
  const names = model.labels;
2729
3123
  const first = event.items[0];
2730
3124
  const firstSeries = first ? model.series[first.seriesIndex] : null;
3125
+ if (event.items.length === 1 && first && firstSeries?.type === "bar" && first.y0 !== void 0 && model.y.type === "time") {
3126
+ const format = formatOf(firstSeries);
3127
+ return {
3128
+ title: first.label ?? event.xLabel,
3129
+ titleColor: first.color,
3130
+ subtitle: first.label !== void 0 ? `${event.xLabel} · ${firstSeries.name}` : firstSeries.name,
3131
+ rows: [
3132
+ {
3133
+ color: null,
3134
+ name: names.start,
3135
+ value: format(first.y0)
3136
+ },
3137
+ {
3138
+ color: null,
3139
+ name: names.end,
3140
+ value: format(first.y)
3141
+ },
3142
+ {
3143
+ color: null,
3144
+ name: names.duration,
3145
+ value: formatDuration(first.y - first.y0, model.locale)
3146
+ },
3147
+ ...detailRows(firstSeries, first.index)
3148
+ ]
3149
+ };
3150
+ }
2731
3151
  if (event.items.length === 1 && firstSeries?.type === "heatmap") {
2732
3152
  const yName = model.y.type === "category" ? model.y.categories[Math.round(first.y)] ?? yFormat(first.y) : yFormat(first.y);
2733
3153
  return {
@@ -2737,7 +3157,7 @@ var tooltipContent$1 = (model, event, yTicks, y2Ticks = null) => {
2737
3157
  color: first.color,
2738
3158
  name: first.label ?? firstSeries.name,
2739
3159
  value: first.value === void 0 ? "–" : (firstSeries.format ?? model.formatValue)(first.value)
2740
- }]
3160
+ }, ...detailRows(firstSeries, first.index)]
2741
3161
  };
2742
3162
  }
2743
3163
  if (event.items.every((it) => model.series[it.seriesIndex].type === "scatter") && event.items.length === 1) {
@@ -2751,11 +3171,15 @@ var tooltipContent$1 = (model, event, yTicks, y2Ticks = null) => {
2751
3171
  if (model.x.type === "category") return {
2752
3172
  title: it.label ?? event.xLabel,
2753
3173
  titleColor: null,
2754
- rows: [{
2755
- color: it.color,
2756
- name: it.seriesName,
2757
- value: formatOf(s)(it.y)
2758
- }, ...valueRow]
3174
+ rows: [
3175
+ {
3176
+ color: it.color,
3177
+ name: it.seriesName,
3178
+ value: formatOf(s)(it.y)
3179
+ },
3180
+ ...valueRow,
3181
+ ...detailRows(s, it.index)
3182
+ ]
2759
3183
  };
2760
3184
  const rows = [
2761
3185
  {
@@ -2768,7 +3192,8 @@ var tooltipContent$1 = (model, event, yTicks, y2Ticks = null) => {
2768
3192
  name: (s.yAxis === "right" ? model.y2?.title : model.y.title) ?? names.y,
2769
3193
  value: formatOf(s)(it.y)
2770
3194
  },
2771
- ...valueRow
3195
+ ...valueRow,
3196
+ ...detailRows(s, it.index)
2772
3197
  ];
2773
3198
  if (it.label !== void 0 && model.series.length > 1) rows.push({
2774
3199
  color: null,
@@ -2810,6 +3235,18 @@ var tooltipContent$1 = (model, event, yTicks, y2Ticks = null) => {
2810
3235
  continue;
2811
3236
  }
2812
3237
  if (s.type === "boxplot") {
3238
+ if (it.outlier !== void 0) {
3239
+ rows.push({
3240
+ color: it.color,
3241
+ name: it.label ? `${it.seriesName} · ${it.label}` : it.seriesName,
3242
+ value: ""
3243
+ }, {
3244
+ color: null,
3245
+ name: names.outlier,
3246
+ value: format(it.outlier)
3247
+ });
3248
+ continue;
3249
+ }
2813
3250
  rows.push({
2814
3251
  color: it.color,
2815
3252
  name: it.label ? `${it.seriesName} · ${it.label}` : it.seriesName,
@@ -2844,6 +3281,7 @@ var tooltipContent$1 = (model, event, yTicks, y2Ticks = null) => {
2844
3281
  name: it.label && binTitle === null ? `${it.seriesName} · ${it.label}` : it.seriesName,
2845
3282
  value
2846
3283
  });
3284
+ rows.push(...detailRows(s, it.index));
2847
3285
  }
2848
3286
  if (model.percent) {
2849
3287
  const totals = /* @__PURE__ */ new Map();
@@ -2874,6 +3312,18 @@ var hoverMarks = (model, sc, event) => {
2874
3312
  let bandHi = -Infinity;
2875
3313
  for (const it of event.items) {
2876
3314
  const s = model.series[it.seriesIndex];
3315
+ if (s.type === "boxplot" && it.outlier !== void 0) {
3316
+ const p = toScreen(sc, it.x + slotOffset(s), plottedOutlier(s, it));
3317
+ marks.push({
3318
+ kind: "dot",
3319
+ x: p.x,
3320
+ y: p.y,
3321
+ size: s.outlierSize + 3,
3322
+ color: it.color,
3323
+ halo: toCss(s.pointColors?.[it.index] ?? s.color, .2)
3324
+ });
3325
+ continue;
3326
+ }
2877
3327
  if (s.type === "bar" || s.type === "candlestick" || s.type === "boxplot") {
2878
3328
  const c = sc.xToPx(it.x + slotOffset(s));
2879
3329
  const half = Math.max(s.barHalfWidth / Math.abs(sc.xPerPx), 1);
@@ -2886,9 +3336,37 @@ var hoverMarks = (model, sc, event) => {
2886
3336
  const cy = sc.yToPx(it.y);
2887
3337
  const hw = Math.abs(s.cellHalf.x / sc.xPerPx);
2888
3338
  const hh = Math.abs(s.cellHalf.y / sc.yPerPx);
3339
+ const cell = screenRect(sc, cx - hw, cx + hw, cy - hh, cy + hh);
3340
+ const style = heatCellStyle(cell.width, cell.height, s.radius);
3341
+ const top = Math.max(plot.y, cell.y);
3342
+ const bottom = Math.min(plot.y + plot.height, cell.y + cell.height);
3343
+ const left = Math.max(plot.x, cell.x);
3344
+ const right = Math.min(plot.x + plot.width, cell.x + cell.width);
3345
+ if (bottom > top) marks.push({
3346
+ kind: "guide",
3347
+ x: plot.x,
3348
+ y: top,
3349
+ width: plot.width,
3350
+ height: bottom - top
3351
+ });
3352
+ if (right > left) marks.push({
3353
+ kind: "guide",
3354
+ x: left,
3355
+ y: plot.y,
3356
+ width: right - left,
3357
+ height: plot.height
3358
+ });
3359
+ const packed = s.cellColors?.[it.index];
3360
+ const fill = packed ? unpackColor(packed) : s.color;
2889
3361
  marks.push({
2890
3362
  kind: "cell",
2891
- ...screenRect(sc, cx - hw, cx + hw, cy - hh, cy + hh)
3363
+ x: cell.x + style.inset,
3364
+ y: cell.y + style.inset,
3365
+ width: Math.max(1, cell.width - style.inset * 2),
3366
+ height: Math.max(1, cell.height - style.inset * 2),
3367
+ color: it.color,
3368
+ ring: contrastRing(fill),
3369
+ radius: style.radius
2892
3370
  });
2893
3371
  continue;
2894
3372
  }
@@ -2928,6 +3406,86 @@ var hoverMarks = (model, sc, event) => {
2928
3406
  }
2929
3407
  return marks;
2930
3408
  };
3409
+ /** Ring of a hovered cell: light on dark fills, dark on light ones */
3410
+ var contrastRing = (fill) => luminance(fill) > .45 ? "rgba(15, 23, 42, 0.78)" : "rgba(255, 255, 255, 0.9)";
3411
+ /** Plotted value of the hovered outlier of a box */
3412
+ var plottedOutlier = (s, it) => {
3413
+ const raw = s.raw.outliers?.[it.index];
3414
+ const k = raw ? raw.indexOf(it.outlier ?? NaN) : -1;
3415
+ return (k >= 0 ? s.cols.outliers?.[it.index]?.[k] : void 0) ?? it.outlier ?? 0;
3416
+ };
3417
+ /**
3418
+ * Connectors of the bar series (`connector`, waterfalls): from the end of
3419
+ * every bar to the next bar, at the value where the next one starts
3420
+ */
3421
+ var connectorSegments = (model, sc) => {
3422
+ const out = [];
3423
+ for (const s of model.series) {
3424
+ const c = s.connector;
3425
+ if (!c || s.hidden || s.type !== "bar" || !s.barTop) continue;
3426
+ const { x, count } = s.cols;
3427
+ const top = s.barTop;
3428
+ const half = s.barHalfWidth;
3429
+ const [v0, v1] = sc.view.x[0] <= sc.view.x[1] ? sc.view.x : [sc.view.x[1], sc.view.x[0]];
3430
+ const color = toCss(c.color, .75);
3431
+ let prev = -1;
3432
+ for (let i = 0; i < count && out.length < 1200; i++) {
3433
+ if (!Number.isFinite(top[i]) || !Number.isFinite(x[i])) continue;
3434
+ if (prev >= 0 && x[i] + half >= v0 && x[prev] - half <= v1) {
3435
+ const a = toScreen(sc, x[prev] + s.barOffset + half, top[prev]);
3436
+ const b = toScreen(sc, x[i] + s.barOffset - half, top[prev]);
3437
+ out.push({
3438
+ x0: a.x,
3439
+ y0: a.y,
3440
+ x1: b.x,
3441
+ y1: b.y,
3442
+ color,
3443
+ width: c.width,
3444
+ dash: c.dash
3445
+ });
3446
+ }
3447
+ prev = i;
3448
+ }
3449
+ }
3450
+ return out;
3451
+ };
3452
+ var COLOR_STOPS = 12;
3453
+ /**
3454
+ * Color legend of a heatmap chart (every series is a heatmap; the first
3455
+ * visible one), `null` otherwise
3456
+ */
3457
+ var colorLegend = (model) => {
3458
+ if (!model.series.length || model.series.some((s) => s.type !== "heatmap")) return null;
3459
+ const s = model.series.find((it) => !it.hidden && it.colorLut);
3460
+ const lut = s?.colorLut;
3461
+ if (!s || !lut) return null;
3462
+ const stops = [];
3463
+ for (let k = 0; k < COLOR_STOPS; k++) {
3464
+ const packed = lut[Math.round(k / 11 * (lut.length - 1))];
3465
+ stops.push(toCss(unpackColor(packed ?? 0)));
3466
+ }
3467
+ const format = s.format ?? model.formatValue;
3468
+ const [lo, hi] = s.valueRange;
3469
+ const labels = [{
3470
+ at: 0,
3471
+ text: format(lo)
3472
+ }, {
3473
+ at: 1,
3474
+ text: format(hi)
3475
+ }];
3476
+ const mid = s.colorMidpoint;
3477
+ if (mid !== null && mid > lo && mid < hi) labels.splice(1, 0, {
3478
+ at: .5,
3479
+ text: format(mid)
3480
+ });
3481
+ return {
3482
+ seriesIndex: s.index,
3483
+ stops,
3484
+ labels
3485
+ };
3486
+ };
3487
+ /** Whether the legend shows (`legend` option; heatmaps get their color legend) */
3488
+ var legendShown = (option, model, named) => option === void 0 ? named > 1 || colorLegend(model) !== null : !!option;
2931
3489
  /** Swatch of a series in the legend */
2932
3490
  var legendShape = (type) => type === "scatter" ? "dot" : type === "line" ? "line" : "square";
2933
3491
  /** Whether the guide line follows the pointer */
@@ -3112,7 +3670,7 @@ var createChartController = (config) => {
3112
3670
  };
3113
3671
  zoomed = !sameRange(view.x, base.x) || !sameRange(view.y, base.y);
3114
3672
  }
3115
- annotations = resolveAnnotations(options.annotations, theme);
3673
+ annotations = resolveAnnotations(options.annotations, theme, model.y.type === "log" ? Math.log10 : void 0);
3116
3674
  if (hover) {
3117
3675
  if (!hover.event.items.every((it) => model.series[it.seriesIndex] && !model.series[it.seriesIndex].hidden && it.index < model.series[it.seriesIndex].cols.count)) setHover(null);
3118
3676
  }
@@ -3121,9 +3679,46 @@ var createChartController = (config) => {
3121
3679
  const legendLayout = () => {
3122
3680
  const option = options.legend;
3123
3681
  const named = options.series.filter((s) => s.name).length;
3124
- if (!(option === void 0 ? named > 1 : !!option)) return null;
3682
+ if (!legendShown(option, model, named)) return null;
3125
3683
  const cfg = typeof option === "object" ? option : {};
3126
3684
  const position = cfg.position === "bottom" ? "bottom" : "top";
3685
+ const ramp = colorLegend(model);
3686
+ if (ramp) {
3687
+ const first = ramp.labels[0]?.text ?? "";
3688
+ const last = ramp.labels[ramp.labels.length - 1]?.text ?? "";
3689
+ const barWidth = Math.max(60, Math.min(160, width * .32));
3690
+ const right = width - 4 - measure(last, 11) - 8;
3691
+ const barX = right - barWidth;
3692
+ const cy = (position === "bottom" ? height - LEGEND_ROW$1 : 0) + LEGEND_ROW$1 / 2;
3693
+ return {
3694
+ entries: [],
3695
+ colors: {
3696
+ bar: {
3697
+ x: barX,
3698
+ y: cy - 4,
3699
+ width: barWidth,
3700
+ height: 8
3701
+ },
3702
+ stops: ramp.stops,
3703
+ labels: [{
3704
+ text: first,
3705
+ x: barX - 8,
3706
+ y: cy,
3707
+ align: "right"
3708
+ }, {
3709
+ text: last,
3710
+ x: right + 8,
3711
+ y: cy,
3712
+ align: "left"
3713
+ }],
3714
+ ticks: ramp.labels.filter((l) => l.at > 0 && l.at < 1).map((l) => barX + l.at * barWidth),
3715
+ caret: null
3716
+ },
3717
+ position,
3718
+ toggle: false,
3719
+ height: 26
3720
+ };
3721
+ }
3127
3722
  const entries = [];
3128
3723
  let x = 4;
3129
3724
  let row = 0;
@@ -3152,6 +3747,7 @@ var createChartController = (config) => {
3152
3747
  if (position === "bottom") for (const e of entries) e.box.y += height - legendHeight + 6;
3153
3748
  return {
3154
3749
  entries,
3750
+ colors: null,
3155
3751
  position,
3156
3752
  toggle: cfg.toggle ?? true,
3157
3753
  height: legendHeight
@@ -3172,13 +3768,21 @@ var createChartController = (config) => {
3172
3768
  const padding = 8;
3173
3769
  let w = 0;
3174
3770
  let lines;
3771
+ const swatchWidth = content.rows.some((row) => row.color) ? 14 : 0;
3175
3772
  if (text) {
3176
3773
  for (const line of text) w = Math.max(w, measure(line, 12));
3177
3774
  lines = text.length;
3178
3775
  } else {
3179
3776
  w = measure(content.title, 12, 600) + (content.titleColor ? 14 : 0);
3180
- for (const row of content.rows) w = Math.max(w, (row.color ? 14 : 0) + measure(row.name, 12) + 16 + measure(row.value, 12, 600));
3181
- lines = 1 + content.rows.length;
3777
+ if (content.subtitle) w = Math.max(w, measure(content.subtitle, 11) + (content.titleColor ? 14 : 0));
3778
+ let names = 0;
3779
+ let values = 0;
3780
+ for (const row of content.rows) {
3781
+ names = Math.max(names, measure(row.name, 12));
3782
+ values = Math.max(values, measure(row.value, 12, 600));
3783
+ }
3784
+ if (content.rows.length) w = Math.max(w, swatchWidth + names + 16 + values);
3785
+ lines = 1 + (content.subtitle ? 1 : 0) + content.rows.length;
3182
3786
  }
3183
3787
  const boxW = Math.ceil(Math.max(w, 96) + 16 + 4);
3184
3788
  const boxH = lines * lineHeight + 16;
@@ -3196,7 +3800,8 @@ var createChartController = (config) => {
3196
3800
  height: boxH
3197
3801
  },
3198
3802
  lineHeight,
3199
- padding
3803
+ padding,
3804
+ swatchWidth
3200
3805
  };
3201
3806
  };
3202
3807
  const computeScene = () => {
@@ -3245,7 +3850,8 @@ var createChartController = (config) => {
3245
3850
  pointLabels,
3246
3851
  legend,
3247
3852
  hover: null,
3248
- dragging: null
3853
+ dragging: null,
3854
+ connectors: connectorSegments(model, layout.scales)
3249
3855
  };
3250
3856
  scene = next;
3251
3857
  if (hover) {
@@ -3258,6 +3864,10 @@ var createChartController = (config) => {
3258
3864
  crosshairY: horizontal ? guide : null,
3259
3865
  tooltip: gesture?.kind === "pan" || gesture?.kind === "point" ? null : tooltipLayout(hover.event, hover.x, hover.y)
3260
3866
  };
3867
+ const colors = legend?.colors;
3868
+ const it = hover.event.items[0];
3869
+ const s = it ? model.series[it.seriesIndex] : void 0;
3870
+ if (colors && it && s?.type === "heatmap" && it.value !== void 0) colors.caret = colors.bar.x + heatPosition(s, it.value) * colors.bar.width;
3261
3871
  }
3262
3872
  if (gesture?.kind === "point") {
3263
3873
  const s = model.series[gesture.item.seriesIndex];
@@ -3302,7 +3912,11 @@ var createChartController = (config) => {
3302
3912
  const sc = scales();
3303
3913
  if (!sc) return null;
3304
3914
  const { plot } = sc;
3305
- return toData(sc, Math.max(plot.x, Math.min(plot.x + plot.width, x)), Math.max(plot.y, Math.min(plot.y + plot.height, y)));
3915
+ const p = toData(sc, Math.max(plot.x, Math.min(plot.x + plot.width, x)), Math.max(plot.y, Math.min(plot.y + plot.height, y)));
3916
+ return {
3917
+ x: p.x,
3918
+ y: fromPlotY(model, p.y)
3919
+ };
3306
3920
  };
3307
3921
  const setViewInternal = (next, notify) => {
3308
3922
  const { base, minSpan } = model;
@@ -3592,11 +4206,16 @@ var createChartController = (config) => {
3592
4206
  },
3593
4207
  toPixel(x, y) {
3594
4208
  const sc = scales();
3595
- return sc ? toScreen(sc, x, y) : null;
4209
+ return sc ? toScreen(sc, x, toPlotY(model, y)) : null;
3596
4210
  },
3597
4211
  fromPixel(x, y) {
3598
4212
  const sc = scales();
3599
- return sc ? toData(sc, x, y) : null;
4213
+ if (!sc) return null;
4214
+ const p = toData(sc, x, y);
4215
+ return {
4216
+ x: p.x,
4217
+ y: fromPlotY(model, p.y)
4218
+ };
3600
4219
  },
3601
4220
  on(type, listener) {
3602
4221
  let set = listeners[type];
@@ -3853,7 +4472,8 @@ var scenePrimitives = (scene, limits = {}) => {
3853
4472
  const hh = Math.abs(s.cellHalf.y / sc.yPerPx);
3854
4473
  const rects = [];
3855
4474
  const colors = [];
3856
- const inset = hw > 3 && hh > 3 ? 1 : 0;
4475
+ const style = heatCellStyle(hw * 2, hh * 2, s.radius);
4476
+ const inset = style.inset;
3857
4477
  for (let i = 0; i < count && rects.length / 4 < maxBars * 4; i++) {
3858
4478
  const c = s.cellColors?.[i];
3859
4479
  if (!c) continue;
@@ -3868,7 +4488,7 @@ var scenePrimitives = (scene, limits = {}) => {
3868
4488
  color: s.colorCss,
3869
4489
  rects,
3870
4490
  colors,
3871
- radius: s.radius
4491
+ radius: style.radius
3872
4492
  });
3873
4493
  continue;
3874
4494
  }
@@ -3970,7 +4590,7 @@ var boxPrimitives = (s, sc, range, xLo, xHi, maxBars) => {
3970
4590
  x: cx,
3971
4591
  y: sc.yToPx(v)
3972
4592
  };
3973
- dots.push(p.x, p.y, s.pointSize);
4593
+ dots.push(p.x, p.y, s.outlierSize);
3974
4594
  dotColors.push(color);
3975
4595
  }
3976
4596
  }
@@ -3991,9 +4611,10 @@ var boxPrimitives = (s, sc, range, xLo, xHi, maxBars) => {
3991
4611
  if (dots.length) prims.push({
3992
4612
  kind: "dots",
3993
4613
  seriesIndex: s.index,
3994
- opacity: .85,
4614
+ opacity: s.outlierShape === "hollow" ? 0 : .85,
3995
4615
  dots,
3996
- colors: dotColors
4616
+ colors: dotColors,
4617
+ stroke: 1.25
3997
4618
  });
3998
4619
  return prims;
3999
4620
  };
@@ -4049,8 +4670,39 @@ var barItem = (key, version, s, count, write, extra) => {
4049
4670
  ...extra
4050
4671
  };
4051
4672
  };
4052
- /** Render items of the visible series, back to front */
4053
- var buildItems = (model, origin, version) => {
4673
+ /**
4674
+ * Inset and radius of the cells of a heatmap at a pixel density; the
4675
+ * renderers fade small insets out and overlap tiny cells (no seams)
4676
+ */
4677
+ var cellStyleOf = (s, density) => {
4678
+ if (!density) return {
4679
+ inset: .5,
4680
+ radius: Math.min(s.radius, 2)
4681
+ };
4682
+ const style = heatCellStyle(s.cellHalf.x * 2 * density.x, s.cellHalf.y * 2 * density.y, s.radius);
4683
+ return {
4684
+ inset: Math.max(.5, style.inset),
4685
+ radius: style.radius
4686
+ };
4687
+ };
4688
+ /**
4689
+ * What the heatmap items depend on besides the model: their cell style at
4690
+ * the current pixel density (`""` without heatmaps)
4691
+ */
4692
+ var cellStyleKey = (model, density) => {
4693
+ let key = "";
4694
+ for (const s of model.series) {
4695
+ if (s.type !== "heatmap" || s.hidden) continue;
4696
+ const style = cellStyleOf(s, density);
4697
+ key += `${style.inset}/${style.radius};`;
4698
+ }
4699
+ return key;
4700
+ };
4701
+ /**
4702
+ * Render items of the visible series, back to front; `density` sizes the
4703
+ * gaps and corners of heatmap cells
4704
+ */
4705
+ var buildItems = (model, origin, version, density) => {
4054
4706
  const items = [];
4055
4707
  /** Outlines of the areas are drawn with the lines, above the bars */
4056
4708
  const outlines = [];
@@ -4195,6 +4847,7 @@ var buildItems = (model, origin, version) => {
4195
4847
  case "heatmap": {
4196
4848
  const colors = s.cellColors;
4197
4849
  const hy = s.cellHalf.y;
4850
+ const style = cellStyleOf(s, density);
4198
4851
  items.push(barItem(`${s.key}:cells`, version, s, count, (i, f, u) => {
4199
4852
  const c = colors ? colors[i] : 0;
4200
4853
  const valid = c !== 0 && Number.isFinite(x[i]);
@@ -4204,8 +4857,8 @@ var buildItems = (model, origin, version) => {
4204
4857
  u[i * 4 + 3] = c;
4205
4858
  }, {
4206
4859
  halfWidth: s.cellHalf.x,
4207
- radius: s.radius,
4208
- inset: 1,
4860
+ radius: style.radius,
4861
+ inset: style.inset,
4209
4862
  minHalf: 0,
4210
4863
  sorted
4211
4864
  }));
@@ -4395,7 +5048,7 @@ var boxItems = (s, origin, version) => {
4395
5048
  const valid = Number.isFinite(v) && Number.isFinite(x[i]);
4396
5049
  f[j * 4] = valid ? ox(i) : GAP;
4397
5050
  f[j * 4 + 1] = valid ? oy(v) : GAP;
4398
- f[j * 4 + 2] = s.pointSize;
5051
+ f[j * 4 + 2] = s.outlierSize;
4399
5052
  u[j * 4 + 3] = colorAt(i);
4400
5053
  j++;
4401
5054
  }
@@ -4407,8 +5060,8 @@ var boxItems = (s, origin, version) => {
4407
5060
  color: s.color,
4408
5061
  instances: buffer,
4409
5062
  count: n,
4410
- opacity: .85,
4411
- stroke: n <= 5e3 ? 1.25 : 0
5063
+ opacity: s.outlierShape === "hollow" ? 0 : .85,
5064
+ stroke: s.outlierShape === "hollow" || n <= 5e3 ? 1.25 : 0
4412
5065
  });
4413
5066
  }
4414
5067
  }
@@ -4806,7 +5459,8 @@ var itemsSignature = (model, themeKey, stackOf) => {
4806
5459
  for (const s of model.series) {
4807
5460
  signature += `\n${s.key}|${s.type}|${idOf(s.cols)}|${s.colorCss}|${s.hidden}|${s.lineWidth}|${s.pointSize}|${s.opacity}|${s.barOffset}|${s.barHalfWidth}|${stackOf(s.index) ?? ""}|${s.curve}|${s.radius}`;
4808
5461
  if (s.type === "candlestick") signature += `|${s.upColor}/${s.downColor}`;
4809
- else if (s.type === "heatmap") signature += `|${s.colorScale.join(";")}/${s.valueRange[0]},${s.valueRange[1]}/${s.cellHalf.x},${s.cellHalf.y}`;
5462
+ else if (s.type === "heatmap") signature += `|${s.colorScale.join(";")}/${s.valueRange[0]},${s.valueRange[1]}/${s.colorMidpoint}/${s.cellHalf.x},${s.cellHalf.y}`;
5463
+ else if (s.type === "boxplot") signature += `|${s.outlierShape}/${s.outlierSize}`;
4810
5464
  }
4811
5465
  return signature;
4812
5466
  };
@@ -4882,17 +5536,64 @@ var drawPrimitives = (ctx, primitives, plot) => {
4882
5536
  }
4883
5537
  ctx.globalAlpha = 1;
4884
5538
  } else {
4885
- ctx.globalAlpha = p.opacity;
5539
+ const stroke = p.stroke ?? 0;
4886
5540
  for (let k = 0; k < p.dots.length; k += 3) {
4887
- ctx.fillStyle = p.colors[k / 3] ?? "#888";
5541
+ const color = p.colors[k / 3] ?? "#888";
5542
+ const r = p.dots[k + 2] / 2;
4888
5543
  ctx.beginPath();
4889
- ctx.arc(p.dots[k], p.dots[k + 1], p.dots[k + 2] / 2, 0, Math.PI * 2);
4890
- ctx.fill();
5544
+ ctx.arc(p.dots[k], p.dots[k + 1], Math.max(0, r - stroke / 2), 0, Math.PI * 2);
5545
+ if (p.opacity > 0) {
5546
+ ctx.globalAlpha = p.opacity;
5547
+ ctx.fillStyle = color;
5548
+ ctx.fill();
5549
+ }
5550
+ if (stroke > 0) {
5551
+ ctx.globalAlpha = 1;
5552
+ ctx.lineWidth = stroke;
5553
+ ctx.strokeStyle = color;
5554
+ ctx.stroke();
5555
+ }
4891
5556
  }
4892
5557
  ctx.globalAlpha = 1;
4893
5558
  }
4894
5559
  ctx.restore();
4895
5560
  };
5561
+ /** The visual map of a heatmap: gradient bar, value labels, hover caret */
5562
+ var drawColorLegend = (ctx, ramp, scene) => {
5563
+ const { theme } = scene;
5564
+ const { bar, stops } = ramp;
5565
+ const n = stops.length;
5566
+ if (typeof ctx.createLinearGradient === "function") {
5567
+ const gradient = ctx.createLinearGradient(bar.x, 0, bar.x + bar.width, 0);
5568
+ stops.forEach((c, k) => gradient.addColorStop(k / Math.max(1, n - 1), c));
5569
+ ctx.fillStyle = gradient;
5570
+ roundedRect(ctx, bar.x, bar.y, bar.width, bar.height, bar.height / 2);
5571
+ ctx.fill();
5572
+ } else {
5573
+ const w = bar.width / n;
5574
+ stops.forEach((c, k) => {
5575
+ ctx.fillStyle = c;
5576
+ ctx.fillRect(bar.x + k * w, bar.y, w + .5, bar.height);
5577
+ });
5578
+ }
5579
+ ctx.fillStyle = toCss(theme.text, .35);
5580
+ for (const t of ramp.ticks) ctx.fillRect(Math.round(t), bar.y - 2, 1, bar.height + 4);
5581
+ ctx.font = font(theme, 11);
5582
+ ctx.textBaseline = "middle";
5583
+ ctx.fillStyle = toCss(theme.textMuted);
5584
+ for (const l of ramp.labels) {
5585
+ ctx.textAlign = l.align;
5586
+ ctx.fillText(l.text, l.x, l.y);
5587
+ }
5588
+ if (ramp.caret !== null) {
5589
+ roundedRect(ctx, ramp.caret - 2, bar.y - 3, 4, bar.height + 6, 2);
5590
+ ctx.fillStyle = toCss(theme.text);
5591
+ ctx.fill();
5592
+ ctx.lineWidth = 1.5;
5593
+ ctx.strokeStyle = toCss(theme.background);
5594
+ ctx.stroke();
5595
+ }
5596
+ };
4896
5597
  /** Draws a scene (legend, axes, data, labels, hover) on a 2D context */
4897
5598
  var drawScene = (ctx, scene, items, origin, pixelRatio, painter = createCanvas2dPainter(ctx)) => {
4898
5599
  const { width, height, theme, model, view, layout } = scene;
@@ -4914,6 +5615,8 @@ var drawScene = (ctx, scene, items, origin, pixelRatio, painter = createCanvas2d
4914
5615
  theme,
4915
5616
  annotations: scene.annotations
4916
5617
  });
5618
+ const ramp = scene.legend?.colors;
5619
+ if (ramp) drawColorLegend(ctx, ramp, scene);
4917
5620
  if (scene.legend) {
4918
5621
  ctx.font = font(theme, 12);
4919
5622
  ctx.textBaseline = "middle";
@@ -4966,6 +5669,11 @@ var drawScene = (ctx, scene, items, origin, pixelRatio, painter = createCanvas2d
4966
5669
  }, Math.round(plot.x * dpr), Math.round(plot.y * dpr));
4967
5670
  }
4968
5671
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
5672
+ for (const mark of scene.hover?.marks ?? []) {
5673
+ if (mark.kind !== "guide") continue;
5674
+ ctx.fillStyle = toCss(theme.text, .06);
5675
+ ctx.fillRect(mark.x, mark.y, mark.width, mark.height);
5676
+ }
4969
5677
  drawForeground(ctx, {
4970
5678
  width,
4971
5679
  height,
@@ -4973,7 +5681,8 @@ var drawScene = (ctx, scene, items, origin, pixelRatio, painter = createCanvas2d
4973
5681
  theme,
4974
5682
  annotations: scene.annotations,
4975
5683
  pointLabels: [],
4976
- clear: false
5684
+ clear: false,
5685
+ connectors: scene.connectors
4977
5686
  });
4978
5687
  if (scene.pointLabels.length) {
4979
5688
  ctx.save();
@@ -5017,15 +5726,25 @@ var drawScene = (ctx, scene, items, origin, pixelRatio, painter = createCanvas2d
5017
5726
  ctx.restore();
5018
5727
  }
5019
5728
  for (const mark of hover.marks) {
5020
- if (mark.kind === "band") continue;
5729
+ if (mark.kind === "band" || mark.kind === "guide") continue;
5021
5730
  if (mark.kind === "cell") {
5022
- roundedRect(ctx, mark.x, mark.y, mark.width, mark.height, 3);
5023
- ctx.lineWidth = 3;
5024
- ctx.strokeStyle = toCss(theme.background);
5025
- ctx.stroke();
5026
- ctx.lineWidth = 1.5;
5027
- ctx.strokeStyle = toCss(theme.text, .55);
5028
- ctx.stroke();
5731
+ const grow = Math.min(3, mark.width * .06, mark.height * .06);
5732
+ const r = Math.max(2, mark.radius);
5733
+ ctx.save();
5734
+ ctx.shadowColor = "rgba(15, 23, 42, 0.4)";
5735
+ ctx.shadowBlur = 12;
5736
+ ctx.shadowOffsetY = 4;
5737
+ roundedRect(ctx, mark.x - grow, mark.y - grow, mark.width + grow * 2, mark.height + grow * 2, r);
5738
+ ctx.fillStyle = mark.color;
5739
+ ctx.fill();
5740
+ ctx.restore();
5741
+ const inset = Math.min(2.75, mark.width / 5, mark.height / 5);
5742
+ if (mark.width > 8 && mark.height > 8) {
5743
+ roundedRect(ctx, mark.x + inset, mark.y + inset, mark.width - inset * 2, mark.height - inset * 2, Math.max(1, r - inset / 2));
5744
+ ctx.lineWidth = 1.5;
5745
+ ctx.strokeStyle = mark.ring;
5746
+ ctx.stroke();
5747
+ }
5029
5748
  continue;
5030
5749
  }
5031
5750
  ctx.beginPath();
@@ -5095,6 +5814,12 @@ var drawScene = (ctx, scene, items, origin, pixelRatio, painter = createCanvas2d
5095
5814
  ctx.textAlign = "left";
5096
5815
  ctx.fillText(content.title, x, y);
5097
5816
  y += lineHeight;
5817
+ if (content.subtitle) {
5818
+ ctx.font = font(theme, 11);
5819
+ ctx.fillStyle = toCss(theme.textMuted);
5820
+ ctx.fillText(content.subtitle, x, y - 2);
5821
+ y += lineHeight;
5822
+ }
5098
5823
  for (const row of content.rows) {
5099
5824
  x = left;
5100
5825
  if (row.color) {
@@ -5102,8 +5827,8 @@ var drawScene = (ctx, scene, items, origin, pixelRatio, painter = createCanvas2d
5102
5827
  ctx.beginPath();
5103
5828
  ctx.arc(x + 4, y, 4, 0, Math.PI * 2);
5104
5829
  ctx.fill();
5105
- x += 14;
5106
5830
  }
5831
+ x += tip.swatchWidth;
5107
5832
  ctx.font = font(theme, 12);
5108
5833
  ctx.textAlign = "left";
5109
5834
  ctx.fillStyle = toCss(theme.textMuted);
@@ -5133,6 +5858,7 @@ var createCanvasChart = (config) => {
5133
5858
  let frameId = null;
5134
5859
  let items = [];
5135
5860
  let itemsModel = null;
5861
+ let itemsKey0 = "";
5136
5862
  let itemsKey = "";
5137
5863
  let options = config.options;
5138
5864
  /** Ids of the themes seen (the controller replaces its theme on changes) */
@@ -5171,15 +5897,21 @@ var createCanvasChart = (config) => {
5171
5897
  fontSet = "";
5172
5898
  if (itemsModel !== scene.model) {
5173
5899
  itemsModel = scene.model;
5174
- const key = itemsSignature(scene.model, themeId(scene.theme), (index) => options.series[index]?.stack);
5175
- if (key !== itemsKey) {
5176
- itemsKey = key;
5177
- origin = {
5178
- x: mid(scene.model.base.x),
5179
- y: mid(scene.model.base.y)
5180
- };
5181
- items = buildItems(scene.model, origin, ++version);
5182
- }
5900
+ itemsKey0 = itemsSignature(scene.model, themeId(scene.theme), (index) => options.series[index]?.stack);
5901
+ }
5902
+ const sc = scene.layout.scales;
5903
+ const density = {
5904
+ x: 1 / Math.abs(sc.xPerPx),
5905
+ y: 1 / Math.abs(sc.yPerPx)
5906
+ };
5907
+ const key = `${itemsKey0}|${cellStyleKey(scene.model, density)}`;
5908
+ if (key !== itemsKey) {
5909
+ itemsKey = key;
5910
+ origin = {
5911
+ x: mid(scene.model.base.x),
5912
+ y: mid(scene.model.base.y)
5913
+ };
5914
+ items = buildItems(scene.model, origin, ++version, density);
5183
5915
  }
5184
5916
  drawScene(ctx, scene, items, origin, dpr, painter);
5185
5917
  fontSet = "";
@@ -5347,6 +6079,7 @@ var heatmapChartOptions = (config, base = {}) => {
5347
6079
  })),
5348
6080
  colorScale: config.colorScale,
5349
6081
  valueRange: config.valueRange,
6082
+ colorMidpoint: config.colorMidpoint,
5350
6083
  radius: config.radius,
5351
6084
  format: config.format
5352
6085
  }],
@@ -5366,7 +6099,7 @@ var heatmapChartOptions = (config, base = {}) => {
5366
6099
  grid: false,
5367
6100
  ...base.yAxis
5368
6101
  },
5369
- legend: base.legend ?? false,
6102
+ legend: base.legend ?? true,
5370
6103
  interaction: base.interaction ?? { zoom: false },
5371
6104
  tooltip: base.tooltip ?? { mode: "nearest" }
5372
6105
  };
@@ -5811,7 +6544,8 @@ var waterfallSeries = (steps, options = {}) => {
5811
6544
  color: total,
5812
6545
  data,
5813
6546
  showLabels: options.labels ?? false,
5814
- format: options.format
6547
+ format: options.format,
6548
+ connector: options.connector ?? true
5815
6549
  };
5816
6550
  };
5817
6551
  /**
@@ -5920,7 +6654,10 @@ var time = (v) => v instanceof Date ? v.getTime() : v === void 0 ? NaN : v;
5920
6654
  var ganttSeries = (tasks, options = {}) => {
5921
6655
  const locale = resolveLocale(options.locale);
5922
6656
  const names = presetLabels(locale);
6657
+ const rows = chartLabels(locale);
5923
6658
  const taskName = options.taskName ?? names.tasks;
6659
+ const progressName = options.progressName ?? names.progress;
6660
+ const separator = /^(zh|ja)\b/i.test(locale) ? "、" : ", ";
5924
6661
  const groups = [];
5925
6662
  for (const t of tasks) {
5926
6663
  const g = t.group ?? taskName;
@@ -5943,19 +6680,32 @@ var ganttSeries = (tasks, options = {}) => {
5943
6680
  opacity: .3,
5944
6681
  barWidth: .62,
5945
6682
  radius: 4,
5946
- data: tasks.filter((t) => !t.milestone && (t.group ?? taskName) === g).map((t) => ({
5947
- x: t.name,
5948
- y0: time(t.start),
5949
- y: time(t.end ?? t.start),
5950
- ...t.color ? { color: t.color } : {}
5951
- }))
6683
+ data: tasks.filter((t) => !t.milestone && (t.group ?? taskName) === g).map((t) => {
6684
+ const details = [];
6685
+ if (t.progress !== void 0) details.push({
6686
+ name: progressName,
6687
+ value: formatProgress(Math.min(1, Math.max(0, t.progress)))
6688
+ });
6689
+ if (t.dependencies?.length) details.push({
6690
+ name: options.dependenciesName ?? rows.dependencies,
6691
+ value: t.dependencies.join(separator)
6692
+ });
6693
+ return {
6694
+ x: t.name,
6695
+ y0: time(t.start),
6696
+ y: time(t.end ?? t.start),
6697
+ ...t.color ? { color: t.color } : {},
6698
+ ...details.length ? { details } : {}
6699
+ };
6700
+ })
5952
6701
  }));
5953
6702
  const progress = tasks.filter((t) => !t.milestone && t.progress !== void 0 && t.progress > 0);
5954
6703
  if (progress.length) series.push({
5955
6704
  id: "gantt:progress",
5956
- name: options.progressName ?? names.progress,
6705
+ name: progressName,
5957
6706
  type: "bar",
5958
6707
  stack: "gantt",
6708
+ tooltip: false,
5959
6709
  color: "var(--text-secondary-color, #6b7280)",
5960
6710
  radius: 4,
5961
6711
  data: progress.map((t) => {
@@ -6055,6 +6805,65 @@ var ellipsize = (text, max, font, measure) => {
6055
6805
  }
6056
6806
  return lo ? text.slice(0, lo).trimEnd() + "…" : "";
6057
6807
  };
6808
+ /** Characters that must not start a line (closing brackets and punctuation) */
6809
+ var NO_LINE_START = /^[)\]}、。,.:;!?)」』】》〉,.:;!?%…]/;
6810
+ /** Greedy line breaking at `max` pixels, without a line limit */
6811
+ var breakLines = (text, max, font, measure) => {
6812
+ const lines = [];
6813
+ let rest = text.trim();
6814
+ while (rest) {
6815
+ if (measure(rest, font) <= max) {
6816
+ lines.push(rest);
6817
+ break;
6818
+ }
6819
+ let lo = 0;
6820
+ let hi = rest.length;
6821
+ while (lo < hi) {
6822
+ const mid = lo + hi + 1 >> 1;
6823
+ if (measure(rest.slice(0, mid), font) <= max) lo = mid;
6824
+ else hi = mid - 1;
6825
+ }
6826
+ if (!lo) return null;
6827
+ let cut = lo;
6828
+ if (rest[lo] !== " ") {
6829
+ const space = rest.lastIndexOf(" ", lo);
6830
+ if (space > lo * .4) cut = space;
6831
+ else while (cut > 1 && NO_LINE_START.test(rest.slice(cut))) cut--;
6832
+ }
6833
+ lines.push(rest.slice(0, cut).trimEnd());
6834
+ rest = rest.slice(cut).trimStart();
6835
+ }
6836
+ return lines;
6837
+ };
6838
+ /**
6839
+ * Breaks a text into at most `maxLines` lines of `max` pixels, at spaces when
6840
+ * possible (anywhere otherwise, e.g. CJK, never before closing punctuation);
6841
+ * a text that fits is balanced across its lines, one that does not ends the
6842
+ * last line with an ellipsis
6843
+ */
6844
+ var wrapText = (text, max, font, measure, maxLines = 2) => {
6845
+ const whole = text.trim();
6846
+ if (!whole || maxLines < 1) return [];
6847
+ const lines = breakLines(whole, max, font, measure);
6848
+ if (!lines) {
6849
+ const last = ellipsize(whole, max, font, measure);
6850
+ return last ? [last] : [];
6851
+ }
6852
+ if (lines.length > maxLines) {
6853
+ const head = lines.slice(0, maxLines - 1);
6854
+ let rest = whole;
6855
+ for (const line of head) rest = rest.slice(line.length).trimStart();
6856
+ const tail = ellipsize(rest, max, font, measure);
6857
+ return tail ? [...head, tail] : head;
6858
+ }
6859
+ if (lines.length < 2) return lines;
6860
+ const lo = measure(whole, font) / lines.length;
6861
+ for (let k = 0; k <= 8; k++) {
6862
+ const balanced = breakLines(whole, lo + (max - lo) * k / 8, font, measure);
6863
+ if (balanced && balanced.length <= lines.length) return balanced;
6864
+ }
6865
+ return lines;
6866
+ };
6058
6867
  /** Stable keys of named values: the name, `name#2` for duplicates */
6059
6868
  var uniqueKeys = (names) => {
6060
6869
  const seen = /* @__PURE__ */ new Map();
@@ -6342,6 +7151,56 @@ var linkStyle = (ctx, node) => {
6342
7151
  gradient.addColorStop(1, node.color1);
6343
7152
  return gradient;
6344
7153
  };
7154
+ /** Whether a chord ribbon joins an arc to itself (a self flow) */
7155
+ var ribbonIsLoop = (node) => Math.abs(node.s0 - node.t0) < 1e-9 && Math.abs(node.s1 - node.t1) < 1e-9;
7156
+ /** Control point of the inward bulge of a self-flow ribbon */
7157
+ var loopControl = (node) => {
7158
+ const m = (node.s0 + node.s1) / 2;
7159
+ return [node.cx + node.r * .4 * Math.cos(m), node.cy + node.r * .4 * Math.sin(m)];
7160
+ };
7161
+ /** Outline of a chord ribbon: source arc, curve, target arc or arrowhead, curve */
7162
+ var ribbonPath = (ctx, node) => {
7163
+ const { cx, cy, r } = node;
7164
+ const at = (a, radius = r) => [cx + radius * Math.cos(a), cy + radius * Math.sin(a)];
7165
+ ctx.beginPath();
7166
+ const s = at(node.s0);
7167
+ ctx.moveTo(s[0], s[1]);
7168
+ if (node.s1 > node.s0) ctx.arc(cx, cy, r, node.s0, node.s1);
7169
+ if (ribbonIsLoop(node)) {
7170
+ const [qx, qy] = loopControl(node);
7171
+ ctx.quadraticCurveTo(qx, qy, s[0], s[1]);
7172
+ ctx.closePath();
7173
+ return;
7174
+ }
7175
+ if (node.head > 0) {
7176
+ const p0 = at(node.t0, r - node.head);
7177
+ const tip = at((node.t0 + node.t1) / 2);
7178
+ const p1 = at(node.t1, r - node.head);
7179
+ ctx.quadraticCurveTo(cx, cy, p0[0], p0[1]);
7180
+ ctx.lineTo(tip[0], tip[1]);
7181
+ ctx.lineTo(p1[0], p1[1]);
7182
+ } else {
7183
+ const t = at(node.t0);
7184
+ ctx.quadraticCurveTo(cx, cy, t[0], t[1]);
7185
+ if (node.t1 > node.t0) ctx.arc(cx, cy, r, node.t0, node.t1);
7186
+ }
7187
+ ctx.quadraticCurveTo(cx, cy, s[0], s[1]);
7188
+ ctx.closePath();
7189
+ };
7190
+ var ribbonStyle = (ctx, node) => {
7191
+ if (node.color0 === node.color1 || typeof ctx.createLinearGradient !== "function") return node.color0;
7192
+ const ms = (node.s0 + node.s1) / 2;
7193
+ const mt = (node.t0 + node.t1) / 2;
7194
+ const x0 = node.cx + node.r * Math.cos(ms);
7195
+ const y0 = node.cy + node.r * Math.sin(ms);
7196
+ const x1 = node.cx + node.r * Math.cos(mt);
7197
+ const y1 = node.cy + node.r * Math.sin(mt);
7198
+ if (Math.hypot(x1 - x0, y1 - y0) < 1) return node.color0;
7199
+ const gradient = ctx.createLinearGradient(x0, y0, x1, y1);
7200
+ gradient.addColorStop(0, node.color0);
7201
+ gradient.addColorStop(1, node.color1);
7202
+ return gradient;
7203
+ };
6345
7204
  /**
6346
7205
  * Draws a scene in CSS pixels (the caller sets the pixel-ratio transform and
6347
7206
  * clears the canvas). `hover` emphasizes an item and dims the others.
@@ -6494,6 +7353,17 @@ var drawShapeScene = (ctx, scene, hover) => {
6494
7353
  ctx.stroke();
6495
7354
  ctx.lineCap = "round";
6496
7355
  break;
7356
+ case "ribbon":
7357
+ if (active && node.activeAlpha !== void 0) ctx.globalAlpha = base * node.activeAlpha;
7358
+ ribbonPath(ctx, node);
7359
+ ctx.fillStyle = ribbonStyle(ctx, node);
7360
+ ctx.fill();
7361
+ if (focused) {
7362
+ ctx.strokeStyle = node.color0;
7363
+ ctx.lineWidth = 1;
7364
+ ctx.stroke();
7365
+ }
7366
+ break;
6497
7367
  case "guide": {
6498
7368
  const k = hover?.indicator;
6499
7369
  if (k === void 0 || !node.ends[k]) break;
@@ -6571,8 +7441,10 @@ var drawShapeTooltip = (ctx, theme, box) => {
6571
7441
  ctx.font = font(theme, 12, 600);
6572
7442
  ctx.fillStyle = toCss(theme.text);
6573
7443
  ctx.textAlign = "left";
6574
- ctx.fillText(content.title, x, y);
6575
- y += lineHeight;
7444
+ for (const line of box.titleLines ?? [content.title]) {
7445
+ ctx.fillText(line, x, y);
7446
+ y += lineHeight;
7447
+ }
6576
7448
  for (const row of content.rows) {
6577
7449
  x = left;
6578
7450
  if (row.color) {
@@ -6656,6 +7528,7 @@ var nodeContains = (node, x, y) => {
6656
7528
  return wrapFrom(Math.atan2(y - node.cy, x - node.cx), node.a0) <= node.a1;
6657
7529
  }
6658
7530
  case "link": return pointNearLink(x, y, node);
7531
+ case "ribbon": return Math.hypot(x - node.cx, y - node.cy) <= node.r + 1 && pointInPolygon(x, y, ribbonOutline(node));
6659
7532
  default: return false;
6660
7533
  }
6661
7534
  };
@@ -6691,6 +7564,46 @@ var pointNearLink = (x, y, node) => {
6691
7564
  return false;
6692
7565
  };
6693
7566
  var clampUnit = (v) => v < 0 ? 0 : v > 1 ? 1 : v;
7567
+ /** Polygon (flat x, y list) approximating a chord ribbon, as drawn */
7568
+ var ribbonOutline = (node) => {
7569
+ const { cx, cy, r } = node;
7570
+ const pts = [];
7571
+ const arc = (a0, a1, radius = r) => {
7572
+ const steps = Math.max(1, Math.ceil((a1 - a0) / .06));
7573
+ for (let k = 0; k <= steps; k++) {
7574
+ const a = a0 + (a1 - a0) * k / steps;
7575
+ pts.push(cx + radius * Math.cos(a), cy + radius * Math.sin(a));
7576
+ }
7577
+ };
7578
+ const quad = (qx, qy, x, y) => {
7579
+ const x0 = pts[pts.length - 2];
7580
+ const y0 = pts[pts.length - 1];
7581
+ for (let k = 1; k <= 16; k++) {
7582
+ const t = k / 16;
7583
+ const u = 1 - t;
7584
+ pts.push(u * u * x0 + 2 * u * t * qx + t * t * x, u * u * y0 + 2 * u * t * qy + t * t * y);
7585
+ }
7586
+ };
7587
+ const at = (a, radius = r) => [cx + radius * Math.cos(a), cy + radius * Math.sin(a)];
7588
+ arc(node.s0, Math.max(node.s0, node.s1));
7589
+ const s = at(node.s0);
7590
+ if (ribbonIsLoop(node)) {
7591
+ const [qx, qy] = loopControl(node);
7592
+ quad(qx, qy, s[0], s[1]);
7593
+ return pts;
7594
+ }
7595
+ if (node.head > 0) {
7596
+ const p0 = at(node.t0, r - node.head);
7597
+ quad(cx, cy, p0[0], p0[1]);
7598
+ pts.push(...at((node.t0 + node.t1) / 2), ...at(node.t1, r - node.head));
7599
+ } else {
7600
+ const t = at(node.t0);
7601
+ quad(cx, cy, t[0], t[1]);
7602
+ arc(node.t0, Math.max(node.t0, node.t1));
7603
+ }
7604
+ quad(cx, cy, s[0], s[1]);
7605
+ return pts;
7606
+ };
6694
7607
  /** Radar: the vertex under the pointer, else the smallest polygon containing it */
6695
7608
  var hitRadar = (scene, x, y) => {
6696
7609
  const radar = scene.radar;
@@ -6811,6 +7724,8 @@ var rangeFills = (o, c, count) => {
6811
7724
  return own ? resolveWith(theme, own, gray) : gray;
6812
7725
  });
6813
7726
  };
7727
+ /** Line height of the wrapped names */
7728
+ var NAME_LINE = 15;
6814
7729
  var layoutBullet = (o, c) => {
6815
7730
  const { theme, area, measure, hidden } = c;
6816
7731
  const keys = keysOf$3(o);
@@ -6834,9 +7749,14 @@ var layoutBullet = (o, c) => {
6834
7749
  const items = [];
6835
7750
  const hasSubtitle = o.data.some((d, i) => !!d.subtitle && weights[i] > 0);
6836
7751
  const valueText = o.data.map((d) => c.format(finite(d.value)));
6837
- const labelW = vertical ? 0 : Math.min(area.width * .32, Math.max(0, ...o.data.map((d) => Math.max(measure(d.name, nameFont), d.subtitle ? measure(d.subtitle, subFont) : 0))) + 14);
7752
+ const nameW = o.data.map((d) => measure(d.name, nameFont));
7753
+ const labelCap = area.width * (area.width < 420 ? .34 : .4);
7754
+ const lineW = o.data.map((d, i) => nameW[i] <= labelCap - 14 ? nameW[i] : Math.max(0, ...wrapText(d.name, labelCap - 14, nameFont, measure, 2).map((l) => measure(l, nameFont))));
7755
+ const labelW = vertical ? 0 : Math.min(labelCap, Math.max(0, ...o.data.map((d, i) => Math.max(lineW[i], d.subtitle ? measure(d.subtitle, subFont) : 0))) + 14);
6838
7756
  const valueW = vertical ? 0 : Math.min(area.width * .2, Math.max(0, ...valueText.map((t) => measure(t, valueFont))) + 12);
6839
- const labelH = vertical ? 22 + (hasSubtitle ? 14 : 0) : 0;
7757
+ const columnW = area.width / total;
7758
+ const wraps = vertical && o.data.some((_, i) => weights[i] > 0 && nameW[i] > columnW - 8);
7759
+ const labelH = vertical ? 22 + (wraps ? NAME_LINE : 0) + (hasSubtitle ? 14 : 0) : 0;
6840
7760
  const valueH = vertical ? 20 : 0;
6841
7761
  const unit = (vertical ? area.width : area.height) / total;
6842
7762
  let offset = 0;
@@ -6970,25 +7890,25 @@ var layoutBullet = (o, c) => {
6970
7890
  }
6971
7891
  if (vertical) {
6972
7892
  const room = Math.max(0, slot - 8);
6973
- const name = ellipsize(d.name, room, nameFont, measure);
7893
+ const lines = wrapText(d.name, room, nameFont, measure, wraps ? 2 : 1);
6974
7894
  const bottom = area.y + area.height;
6975
- if (name) nodes.push({
7895
+ lines.forEach((line, k) => nodes.push({
6976
7896
  kind: "text",
6977
7897
  x: mid,
6978
- y: bottom - labelH + 16,
6979
- text: name,
7898
+ y: bottom - labelH + 16 + k * NAME_LINE,
7899
+ text: line,
6980
7900
  font: nameFont,
6981
7901
  color: text,
6982
7902
  align: "center",
6983
7903
  baseline: "middle",
6984
7904
  hit: i,
6985
7905
  alpha
6986
- });
7906
+ }));
6987
7907
  const sub = d.subtitle ? ellipsize(d.subtitle, room, subFont, measure) : "";
6988
7908
  if (sub) nodes.push({
6989
7909
  kind: "text",
6990
7910
  x: mid,
6991
- y: bottom - labelH + 31,
7911
+ y: bottom - labelH + 31 + (wraps ? NAME_LINE : 0),
6992
7912
  text: sub,
6993
7913
  font: subFont,
6994
7914
  color: muted,
@@ -7012,25 +7932,28 @@ var layoutBullet = (o, c) => {
7012
7932
  });
7013
7933
  } else {
7014
7934
  const room = Math.max(0, labelW - 14);
7015
- const name = ellipsize(d.name, room, nameFont, measure);
7016
- const sub = d.subtitle && slot >= 34 ? ellipsize(d.subtitle, room, subFont, measure) : "";
7935
+ const avail = slot - 4;
7936
+ const sub = d.subtitle && avail >= 29 ? ellipsize(d.subtitle, room, subFont, measure) : "";
7937
+ const subH = sub ? 13 : 0;
7938
+ const lines = wrapText(d.name, room, nameFont, measure, avail >= 30 + subH ? 2 : 1);
7939
+ const top = mid - (lines.length * NAME_LINE + subH) / 2;
7017
7940
  const x = area.x + labelW - 14;
7018
- if (name) nodes.push({
7941
+ lines.forEach((line, k) => nodes.push({
7019
7942
  kind: "text",
7020
7943
  x,
7021
- y: sub ? mid - 7 : mid,
7022
- text: name,
7944
+ y: top + NAME_LINE / 2 + k * NAME_LINE,
7945
+ text: line,
7023
7946
  font: nameFont,
7024
7947
  color: text,
7025
7948
  align: "right",
7026
7949
  baseline: "middle",
7027
7950
  hit: i,
7028
7951
  alpha
7029
- });
7952
+ }));
7030
7953
  if (sub) nodes.push({
7031
7954
  kind: "text",
7032
7955
  x,
7033
- y: mid + 8,
7956
+ y: top + lines.length * NAME_LINE + subH / 2,
7034
7957
  text: sub,
7035
7958
  font: subFont,
7036
7959
  color: muted,
@@ -7112,6 +8035,7 @@ var SHAPE_LABELS = {
7112
8035
  target: "Target",
7113
8036
  ofTarget: "Of target",
7114
8037
  range: "Range",
8038
+ reverse: "Reverse",
7115
8039
  series: "Series {index}",
7116
8040
  pieChart: "Pie chart",
7117
8041
  donutChart: "Donut chart",
@@ -7125,7 +8049,8 @@ var SHAPE_LABELS = {
7125
8049
  sunburstChart: "Sunburst chart",
7126
8050
  radialBarChart: "Radial bar chart",
7127
8051
  calendarHeatmap: "Calendar heatmap",
7128
- bulletChart: "Bullet chart"
8052
+ bulletChart: "Bullet chart",
8053
+ chordChart: "Chord diagram"
7129
8054
  },
7130
8055
  zh: {
7131
8056
  noData: "暂无数据",
@@ -7142,6 +8067,7 @@ var SHAPE_LABELS = {
7142
8067
  target: "目标",
7143
8068
  ofTarget: "目标达成",
7144
8069
  range: "区间",
8070
+ reverse: "反向",
7145
8071
  series: "系列 {index}",
7146
8072
  pieChart: "饼图",
7147
8073
  donutChart: "环形图",
@@ -7155,7 +8081,8 @@ var SHAPE_LABELS = {
7155
8081
  sunburstChart: "旭日图",
7156
8082
  radialBarChart: "径向条形图",
7157
8083
  calendarHeatmap: "日历热力图",
7158
- bulletChart: "子弹图"
8084
+ bulletChart: "子弹图",
8085
+ chordChart: "弦图"
7159
8086
  },
7160
8087
  ja: {
7161
8088
  noData: "データなし",
@@ -7172,6 +8099,7 @@ var SHAPE_LABELS = {
7172
8099
  target: "目標",
7173
8100
  ofTarget: "目標達成率",
7174
8101
  range: "範囲",
8102
+ reverse: "逆方向",
7175
8103
  series: "系列 {index}",
7176
8104
  pieChart: "円グラフ",
7177
8105
  donutChart: "ドーナツグラフ",
@@ -7185,7 +8113,8 @@ var SHAPE_LABELS = {
7185
8113
  sunburstChart: "サンバースト図",
7186
8114
  radialBarChart: "円形棒グラフ",
7187
8115
  calendarHeatmap: "カレンダーヒートマップ",
7188
- bulletChart: "ブレットグラフ"
8116
+ bulletChart: "ブレットグラフ",
8117
+ chordChart: "コードダイアグラム"
7189
8118
  },
7190
8119
  fr: {
7191
8120
  noData: "Aucune donnée",
@@ -7202,6 +8131,7 @@ var SHAPE_LABELS = {
7202
8131
  target: "Objectif",
7203
8132
  ofTarget: "Atteinte de l’objectif",
7204
8133
  range: "Plage",
8134
+ reverse: "Sens inverse",
7205
8135
  series: "Série {index}",
7206
8136
  pieChart: "Graphique circulaire",
7207
8137
  donutChart: "Graphique en anneau",
@@ -7215,7 +8145,8 @@ var SHAPE_LABELS = {
7215
8145
  sunburstChart: "Diagramme en rayons de soleil",
7216
8146
  radialBarChart: "Graphique à barres radiales",
7217
8147
  calendarHeatmap: "Calendrier thermique",
7218
- bulletChart: "Graphique à puces"
8148
+ bulletChart: "Graphique à puces",
8149
+ chordChart: "Diagramme d’accords"
7219
8150
  }
7220
8151
  };
7221
8152
  /** Texts of a chart: its `locale` (the page language by default) and `texts` overrides */
@@ -7787,6 +8718,581 @@ var layoutCalendar = (o, c) => {
7787
8718
  };
7788
8719
  };
7789
8720
  //#endregion
8721
+ //#region ../charts/src/engine/shapes/chord.ts
8722
+ /**
8723
+ * Resolves the groups (declared, then the ones only named by links) and
8724
+ * the square flow matrix (from `links`, else `matrix`)
8725
+ */
8726
+ var resolveChord = (o) => {
8727
+ const names = [];
8728
+ const colors = [];
8729
+ const byName = /* @__PURE__ */ new Map();
8730
+ for (const g of o.groups ?? []) {
8731
+ const group = typeof g === "string" ? { name: g } : g;
8732
+ if (!group || typeof group.name !== "string") continue;
8733
+ if (!byName.has(group.name)) byName.set(group.name, names.length);
8734
+ names.push(group.name);
8735
+ colors.push(group.color);
8736
+ }
8737
+ const cellColors = /* @__PURE__ */ new Map();
8738
+ if (o.links) {
8739
+ const declared = names.length;
8740
+ const resolve = (end) => {
8741
+ if (typeof end === "number") return Number.isInteger(end) && end >= 0 && end < declared ? end : -1;
8742
+ if (typeof end !== "string") return -1;
8743
+ const known = byName.get(end);
8744
+ if (known !== void 0) return known;
8745
+ byName.set(end, names.length);
8746
+ names.push(end);
8747
+ colors.push(void 0);
8748
+ return names.length - 1;
8749
+ };
8750
+ const flows = [];
8751
+ for (const l of o.links) {
8752
+ if (!l) continue;
8753
+ const s = resolve(l.source);
8754
+ const t = resolve(l.target);
8755
+ if (s < 0 || t < 0) continue;
8756
+ flows.push([
8757
+ s,
8758
+ t,
8759
+ positive(l.value),
8760
+ l.color
8761
+ ]);
8762
+ }
8763
+ const n = names.length;
8764
+ const matrix = names.map(() => new Array(n).fill(0));
8765
+ for (const [s, t, v, color] of flows) {
8766
+ matrix[s][t] += v;
8767
+ if (color) cellColors.set(s * n + t, color);
8768
+ }
8769
+ return {
8770
+ names,
8771
+ colors,
8772
+ matrix,
8773
+ cellColors
8774
+ };
8775
+ }
8776
+ const rows = o.matrix ?? [];
8777
+ const n = Math.max(names.length, rows.length);
8778
+ for (let i = names.length; i < n; i++) {
8779
+ names.push(String(i + 1));
8780
+ colors.push(void 0);
8781
+ }
8782
+ return {
8783
+ names,
8784
+ colors,
8785
+ matrix: names.map((_, i) => names.map((__, j) => positive(rows[i]?.[j]))),
8786
+ cellColors
8787
+ };
8788
+ };
8789
+ /** Keys of the animated quantities: `~group` (shown 0-1) and `group→group` */
8790
+ var chordKeys = (m) => {
8791
+ const keys = uniqueKeys(m.names);
8792
+ return {
8793
+ group: (i) => `~${keys[i]}`,
8794
+ cell: (i, j) => `${keys[i]}\u2192${keys[j]}`
8795
+ };
8796
+ };
8797
+ /** Whether a cell is a flow of the diagram (directed: self flows are ignored) */
8798
+ var isFlow = (m, directed, i, j) => m.matrix[i][j] > 0 && !(directed && i === j);
8799
+ var chordValues = (o, hidden, out) => {
8800
+ const m = resolveChord(o);
8801
+ const k = chordKeys(m);
8802
+ const directed = !!o.directed;
8803
+ m.names.forEach((_, i) => {
8804
+ out.set(k.group(i), hidden.has(i) ? 0 : 1);
8805
+ m.names.forEach((__, j) => {
8806
+ if (isFlow(m, directed, i, j)) out.set(k.cell(i, j), hidden.has(i) || hidden.has(j) ? 0 : m.matrix[i][j]);
8807
+ });
8808
+ });
8809
+ };
8810
+ /** Totals of a matrix: outgoing, incoming and arc value of every group */
8811
+ var totals = (matrix, directed) => {
8812
+ const n = matrix.length;
8813
+ const out = new Array(n).fill(0);
8814
+ const inc = new Array(n).fill(0);
8815
+ for (let i = 0; i < n; i++) for (let j = 0; j < n; j++) {
8816
+ if (directed && i === j) continue;
8817
+ out[i] += matrix[i][j];
8818
+ inc[j] += matrix[i][j];
8819
+ }
8820
+ return {
8821
+ out,
8822
+ inc,
8823
+ value: out.map((v, i) => directed ? v + inc[i] : v)
8824
+ };
8825
+ };
8826
+ /** Smallest of 1, 2, 5 × 10^k not below `raw` */
8827
+ var niceCeil = (raw) => {
8828
+ if (!(raw > 0) || !Number.isFinite(raw)) return 0;
8829
+ const base = Math.pow(10, Math.floor(Math.log10(raw)));
8830
+ for (const f of [
8831
+ 1,
8832
+ 2,
8833
+ 5,
8834
+ 10
8835
+ ]) if (f * base >= raw * (1 - 1e-9)) return f * base;
8836
+ return 10 * base;
8837
+ };
8838
+ var LABEL_FONT_SIZE = 12;
8839
+ var TICK_BAND = 22;
8840
+ var layoutChord = (o, c) => {
8841
+ const { theme, area, measure, hidden } = c;
8842
+ const model = resolveChord(o);
8843
+ const { names, matrix: raw } = model;
8844
+ const n = names.length;
8845
+ if (!n) return emptyLayout(c);
8846
+ const directed = !!o.directed;
8847
+ const keys = chordKeys(model);
8848
+ const flow = (i, j) => isFlow(model, directed, i, j);
8849
+ const shown = raw.map((row, i) => row.map((v, j) => flow(i, j) ? Math.max(0, c.value(keys.cell(i, j), hidden.has(i) || hidden.has(j) ? 0 : v)) : 0));
8850
+ const target = raw.map((row, i) => row.map((v, j) => flow(i, j) && !hidden.has(i) && !hidden.has(j) ? v : 0));
8851
+ const now = totals(shown, directed);
8852
+ const goal = totals(target, directed);
8853
+ const whole = goal.value.reduce((a, b) => a + b, 0);
8854
+ const visibleWeight = names.map((_, i) => goal.value[i] > 0 || now.value[i] > 1e-9 ? clamp(c.value(keys.group(i), hidden.has(i) ? 0 : 1), 0, 1) : 0);
8855
+ const sumNow = now.value.reduce((a, b) => a + b, 0);
8856
+ if (sumNow <= 1e-12) return emptyLayout(c);
8857
+ const allGoal = totals(raw.map((row, i) => row.map((v, j) => flow(i, j) ? v : 0)), directed).value;
8858
+ const order = names.map((_, i) => i);
8859
+ if (o.sortGroups === "ascending" || o.sortGroups === "descending") {
8860
+ const sign = o.sortGroups === "ascending" ? 1 : -1;
8861
+ order.sort((a, b) => sign * (allGoal[a] - allGoal[b]) || a - b);
8862
+ }
8863
+ const pos = new Array(n);
8864
+ order.forEach((g, p) => pos[g] = p);
8865
+ const cx = area.x + area.width / 2;
8866
+ const cy = area.y + area.height / 2;
8867
+ const half = Math.min(area.width, area.height) / 2;
8868
+ const labelMode = o.labels ?? "auto";
8869
+ const nameFont = font(theme, LABEL_FONT_SIZE, 500);
8870
+ const tickFont = font(theme, 10);
8871
+ const tickOption = o.ticks;
8872
+ const showTicks = tickOption === false ? false : typeof tickOption === "number" ? tickOption > 0 : half >= 150;
8873
+ const tickBand = showTicks ? TICK_BAND : 0;
8874
+ const pad = clamp(finite(o.padAngle, 2), 0, 45) * (Math.PI / 180);
8875
+ const padTotal = pad * visibleWeight.reduce((a, b) => a + b, 0);
8876
+ const padScale = padTotal > TAU * .5 ? TAU * .5 / padTotal : 1;
8877
+ const k = (TAU - padTotal * padScale) / sumNow;
8878
+ const start = -Math.PI / 2 + finite(o.startAngle) * Math.PI / 180;
8879
+ const arcs = new Array(n);
8880
+ {
8881
+ let a = start + pad * padScale * (visibleWeight[order[0]] ?? 0) / 2;
8882
+ for (const g of order) {
8883
+ const a0 = a;
8884
+ const a1 = a0 + now.value[g] * k;
8885
+ arcs[g] = {
8886
+ a0,
8887
+ a1
8888
+ };
8889
+ a = a1 + pad * padScale * visibleWeight[g];
8890
+ }
8891
+ }
8892
+ const drawnGroup = (g) => arcs[g].a1 - arcs[g].a0 > 1e-6;
8893
+ const nameW = names.map((name) => measure(name, nameFont));
8894
+ const fitsTangential = (r) => order.every((g) => !drawnGroup(g) || nameW[g] + 6 <= (arcs[g].a1 - arcs[g].a0 + pad * padScale * .8) * r);
8895
+ let mode = labelMode === "none" ? "none" : labelMode === "radial" ? "radial" : "tangential";
8896
+ const tangentialRoom = 22;
8897
+ if (labelMode === "auto" && !fitsTangential(Math.max(1, half - 12))) mode = "radial";
8898
+ const reach = (a) => {
8899
+ const cos = Math.abs(Math.cos(a));
8900
+ const sin = Math.abs(Math.sin(a));
8901
+ return Math.min(cos > 1e-6 ? (area.width / 2 - 2) / cos : Infinity, sin > 1e-6 ? (area.height / 2 - LABEL_FONT_SIZE / 2 - 1) / sin : Infinity);
8902
+ };
8903
+ const midOf = (g) => (arcs[g].a0 + arcs[g].a1) / 2;
8904
+ const horizontal = (a) => Math.abs(Math.sin(a)) > .92;
8905
+ let outer;
8906
+ if (mode === "radial") {
8907
+ outer = half - tickBand - 8;
8908
+ for (const g of order) if (drawnGroup(g) && visibleWeight[g] > .5) {
8909
+ const a = midOf(g);
8910
+ const need = horizontal(a) ? 14 : nameW[g];
8911
+ outer = Math.min(outer, reach(a) - need - tickBand - 10);
8912
+ }
8913
+ outer = Math.max(half * .5, outer);
8914
+ } else outer = half - tickBand - (mode === "none" ? 0 : tangentialRoom) - 2;
8915
+ outer = Math.max(16, outer);
8916
+ const arcWidth = clamp(finite(o.arcWidth, clamp(outer * .06, 8, 18)), 2, outer * .5);
8917
+ const inner = outer - arcWidth;
8918
+ const ribbonR = Math.max(4, inner - 2);
8919
+ const segments = names.map(() => []);
8920
+ for (let i = 0; i < n; i++) for (let j = 0; j < n; j++) if (directed) {
8921
+ if (flow(i, j)) {
8922
+ segments[i].push({
8923
+ j,
8924
+ dir: "out",
8925
+ raw: raw[i][j],
8926
+ a0: 0,
8927
+ a1: 0
8928
+ });
8929
+ segments[j].push({
8930
+ j: i,
8931
+ dir: "in",
8932
+ raw: raw[i][j],
8933
+ a0: 0,
8934
+ a1: 0
8935
+ });
8936
+ }
8937
+ } else if (flow(i, j) || flow(j, i)) segments[i].push({
8938
+ j,
8939
+ dir: "out",
8940
+ raw: raw[i][j],
8941
+ a0: 0,
8942
+ a1: 0
8943
+ });
8944
+ const sortSub = o.sortSubgroups ?? "auto";
8945
+ segments.forEach((list, i) => {
8946
+ const offset = (j) => {
8947
+ const d = (pos[j] - pos[i] + n) % n;
8948
+ return d === 0 ? n / 2 : d;
8949
+ };
8950
+ list.sort((a, b) => {
8951
+ const dir = Number(a.dir === "in") - Number(b.dir === "in");
8952
+ if (sortSub === "ascending" || sortSub === "descending") return (sortSub === "ascending" ? 1 : -1) * (a.raw - b.raw) || pos[a.j] - pos[b.j] || dir;
8953
+ if (sortSub === "none") return pos[a.j] - pos[b.j] || dir;
8954
+ return offset(b.j) - offset(a.j) || dir;
8955
+ });
8956
+ let a = arcs[i].a0;
8957
+ for (const s of list) {
8958
+ const v = s.dir === "out" ? shown[i][s.j] : shown[s.j][i];
8959
+ s.a0 = a;
8960
+ s.a1 = a + v * k;
8961
+ a = s.a1;
8962
+ }
8963
+ });
8964
+ const segment = (g, j, dir) => segments[g].find((s) => s.j === j && s.dir === dir);
8965
+ const css = names.map((_, i) => c.color(model.colors[i], i)).map((col) => toCss(col));
8966
+ const neutral = toCss(mix(theme.grid, theme.textMuted, .45));
8967
+ const colorMode = o.ribbonColor ?? "gradient";
8968
+ const opacity = clamp(finite(o.ribbonOpacity, .65), .02, 1);
8969
+ const activeAlpha = Math.min(1, opacity + .25);
8970
+ const head = o.arrows ?? directed ? clamp(ribbonR * .07, 5, 12) : 0;
8971
+ const ribbons = [];
8972
+ const ribbonIndex = (s, t) => n + s * n + t;
8973
+ for (let i = 0; i < n; i++) for (let j = directed ? 0 : i; j < n; j++) if (directed) {
8974
+ if (!flow(i, j)) continue;
8975
+ const src = segment(i, j, "out");
8976
+ const tgt = segment(j, i, "in");
8977
+ if (src && tgt) ribbons.push({
8978
+ index: ribbonIndex(i, j),
8979
+ s: i,
8980
+ t: j,
8981
+ src,
8982
+ tgt
8983
+ });
8984
+ } else {
8985
+ if (!flow(i, j) && !flow(j, i)) continue;
8986
+ const [s, t] = raw[j][i] > raw[i][j] ? [j, i] : [i, j];
8987
+ const src = segment(s, t, "out");
8988
+ const tgt = segment(t, s, "out");
8989
+ if (src && tgt) ribbons.push({
8990
+ index: ribbonIndex(s, t),
8991
+ s,
8992
+ t,
8993
+ src,
8994
+ tgt
8995
+ });
8996
+ }
8997
+ const ribbonsOf = names.map(() => []);
8998
+ for (const r of ribbons) {
8999
+ ribbonsOf[r.s].push(r.index);
9000
+ if (r.t !== r.s) ribbonsOf[r.t].push(r.index);
9001
+ }
9002
+ const nodes = [];
9003
+ const width = (r) => r.src.a1 - r.src.a0 + (r.tgt.a1 - r.tgt.a0);
9004
+ for (const r of ribbons.slice().sort((a, b) => width(b) - width(a))) {
9005
+ if (width(r) <= 1e-6) continue;
9006
+ const own = model.cellColors.get(r.s * n + r.t) ?? (directed ? void 0 : model.cellColors.get(r.t * n + r.s));
9007
+ let c0;
9008
+ let c1;
9009
+ if (own) c0 = c1 = toCss(c.color(own, r.s));
9010
+ else if (colorMode === "source") c0 = c1 = css[r.s];
9011
+ else if (colorMode === "target") c0 = c1 = css[r.t];
9012
+ else if (colorMode === "neutral") c0 = c1 = neutral;
9013
+ else {
9014
+ c0 = css[r.s];
9015
+ c1 = css[r.t];
9016
+ }
9017
+ nodes.push({
9018
+ kind: "ribbon",
9019
+ cx,
9020
+ cy,
9021
+ r: ribbonR,
9022
+ s0: r.src.a0,
9023
+ s1: r.src.a1,
9024
+ t0: r.tgt.a0,
9025
+ t1: r.tgt.a1,
9026
+ head: r.s === r.t ? 0 : head,
9027
+ color0: c0,
9028
+ color1: c1,
9029
+ alpha: opacity,
9030
+ activeAlpha,
9031
+ hit: r.index,
9032
+ also: r.s === r.t ? [r.s] : [r.s, r.t]
9033
+ });
9034
+ }
9035
+ for (const g of order) {
9036
+ if (!drawnGroup(g)) continue;
9037
+ nodes.push({
9038
+ kind: "sector",
9039
+ cx,
9040
+ cy,
9041
+ r0: inner,
9042
+ r1: outer,
9043
+ a0: arcs[g].a0,
9044
+ a1: arcs[g].a1,
9045
+ pad: 0,
9046
+ corner: Math.min(2, arcWidth / 4),
9047
+ fill: css[g],
9048
+ hit: g,
9049
+ also: ribbonsOf[g],
9050
+ alpha: visibleWeight[g]
9051
+ });
9052
+ }
9053
+ const muted = toCss(theme.textMuted);
9054
+ const tickColor = toCss(theme.textMuted, .7);
9055
+ if (showTicks) {
9056
+ const unitPx = k * outer;
9057
+ const tickFormat = o.tickFormat ?? localeFormat(c.locale);
9058
+ const labelPx = measure(tickFormat(Math.max(...allGoal)), tickFont) + 14;
9059
+ let major = typeof tickOption === "number" ? tickOption : niceCeil(labelPx / Math.max(unitPx, 1e-12));
9060
+ const count = sumNow / Math.max(major, 1e-12);
9061
+ if (!(major > 0) || count > 240) major = niceCeil(sumNow / 240);
9062
+ const minor = major / 5 * unitPx >= 5 ? major / 5 : major / 2 * unitPx >= 5 ? major / 2 : major;
9063
+ const perMajor = Math.round(major / minor);
9064
+ const tickR = outer + 2;
9065
+ const labelR = outer + 15;
9066
+ let lastEnd = -Infinity;
9067
+ let firstStart = null;
9068
+ for (const g of order) {
9069
+ if (!drawnGroup(g)) continue;
9070
+ const { a0, a1 } = arcs[g];
9071
+ const also = ribbonsOf[g];
9072
+ for (let m = 0;; m++) {
9073
+ const a = a0 + m * minor * k;
9074
+ if (a > a1 + 1e-9) break;
9075
+ const isMajor = m % perMajor === 0;
9076
+ const len = isMajor ? 5 : 3;
9077
+ if (unitPx * minor >= 3 || isMajor) nodes.push({
9078
+ kind: "line",
9079
+ points: [
9080
+ cx + tickR * Math.cos(a),
9081
+ cy + tickR * Math.sin(a),
9082
+ cx + (tickR + len) * Math.cos(a),
9083
+ cy + (tickR + len) * Math.sin(a)
9084
+ ],
9085
+ color: tickColor,
9086
+ width: 1,
9087
+ hit: g,
9088
+ also
9089
+ });
9090
+ if (!isMajor) continue;
9091
+ const text = tickFormat(m * minor);
9092
+ const halfAngle = (measure(text, tickFont) / 2 + 3) / labelR;
9093
+ if (a - halfAngle < lastEnd) continue;
9094
+ if (firstStart !== null && a + halfAngle > firstStart + TAU) continue;
9095
+ if (firstStart === null) firstStart = a - halfAngle;
9096
+ lastEnd = a + halfAngle;
9097
+ nodes.push({
9098
+ kind: "text",
9099
+ x: cx + labelR * Math.cos(a),
9100
+ y: cy + labelR * Math.sin(a),
9101
+ text,
9102
+ font: tickFont,
9103
+ color: muted,
9104
+ align: "center",
9105
+ baseline: "middle",
9106
+ rotate: upright(a + Math.PI / 2),
9107
+ hit: g,
9108
+ also
9109
+ });
9110
+ }
9111
+ }
9112
+ }
9113
+ if (mode !== "none") {
9114
+ const nameR = outer + tickBand + 6;
9115
+ const color = toCss(theme.text);
9116
+ const placed = [];
9117
+ const lineGap = 15;
9118
+ const samples = (x, y, dx, dy, length) => {
9119
+ const pts = [];
9120
+ const steps = Math.max(1, Math.ceil(length / 6));
9121
+ for (let s = 0; s <= steps; s++) pts.push([x + dx * length * s / steps, y + dy * length * s / steps]);
9122
+ return pts;
9123
+ };
9124
+ const collides = (pts) => placed.some((other) => other.some(([x, y]) => pts.some(([u, v]) => Math.hypot(x - u, y - v) < lineGap)));
9125
+ const byValue = order.filter((g) => drawnGroup(g) && visibleWeight[g] > .5).sort((a, b) => now.value[b] - now.value[a]);
9126
+ for (const g of byValue) {
9127
+ const { a0, a1 } = arcs[g];
9128
+ const mid = (a0 + a1) / 2;
9129
+ if (mode === "tangential") {
9130
+ const room = (a1 - a0 + pad * padScale * .8) * (nameR + 6) - 6;
9131
+ const text = ellipsize(names[g], room, nameFont, measure);
9132
+ if (!text) continue;
9133
+ nodes.push({
9134
+ kind: "text",
9135
+ x: cx + (nameR + 6) * Math.cos(mid),
9136
+ y: cy + (nameR + 6) * Math.sin(mid),
9137
+ text,
9138
+ font: nameFont,
9139
+ color,
9140
+ align: "center",
9141
+ baseline: "middle",
9142
+ rotate: upright(mid + Math.PI / 2),
9143
+ hit: g,
9144
+ also: ribbonsOf[g]
9145
+ });
9146
+ continue;
9147
+ }
9148
+ const ax = cx + nameR * Math.cos(mid);
9149
+ const ay = cy + nameR * Math.sin(mid);
9150
+ if (horizontal(mid)) {
9151
+ const y = ay + Math.sign(Math.sin(mid)) * 7;
9152
+ const outward = Math.cos(mid) >= 0 ? "left" : "right";
9153
+ const aligns = [
9154
+ "center",
9155
+ outward,
9156
+ outward === "left" ? "right" : "left"
9157
+ ];
9158
+ const clear = (pts) => pts.every(([x, py]) => Math.hypot(x - cx, py - cy) >= nameR + 2);
9159
+ for (const align of aligns) {
9160
+ const room = align === "center" ? 2 * Math.min(ax - area.x, area.x + area.width - ax) - 4 : align === "left" ? area.x + area.width - ax - 2 : ax - area.x - 2;
9161
+ const text = ellipsize(names[g], room, nameFont, measure);
9162
+ if (!text) continue;
9163
+ const w = measure(text, nameFont);
9164
+ const pts = samples(align === "left" ? ax : align === "right" ? ax - w : ax - w / 2, y, 1, 0, w);
9165
+ if (!clear(pts) || collides(pts)) continue;
9166
+ placed.push(pts);
9167
+ nodes.push({
9168
+ kind: "text",
9169
+ x: ax,
9170
+ y,
9171
+ text,
9172
+ font: nameFont,
9173
+ color,
9174
+ align,
9175
+ baseline: "middle",
9176
+ hit: g,
9177
+ also: ribbonsOf[g]
9178
+ });
9179
+ break;
9180
+ }
9181
+ continue;
9182
+ }
9183
+ const text = ellipsize(names[g], reach(mid) - nameR - 2, nameFont, measure);
9184
+ if (!text) continue;
9185
+ const pts = samples(ax, ay, Math.cos(mid), Math.sin(mid), measure(text, nameFont));
9186
+ if (collides(pts)) continue;
9187
+ placed.push(pts);
9188
+ const right = Math.cos(mid) >= 0;
9189
+ nodes.push({
9190
+ kind: "text",
9191
+ x: ax,
9192
+ y: ay,
9193
+ text,
9194
+ font: nameFont,
9195
+ color,
9196
+ align: right ? "left" : "right",
9197
+ baseline: "middle",
9198
+ rotate: right ? mid : mid + Math.PI,
9199
+ hit: g,
9200
+ also: ribbonsOf[g]
9201
+ });
9202
+ }
9203
+ }
9204
+ const items = [];
9205
+ const asymmetric = directed || raw.some((row, i) => row.some((v, j) => Math.abs(v - raw[j][i]) > 1e-12));
9206
+ for (const g of order) {
9207
+ const value = goal.value[g];
9208
+ if (!(value > 0) || hidden.has(g)) continue;
9209
+ const percent = whole > 0 ? value / whole : 0;
9210
+ const mid = (arcs[g].a0 + arcs[g].a1) / 2;
9211
+ items.push({
9212
+ index: g,
9213
+ name: names[g],
9214
+ value,
9215
+ percent,
9216
+ share: c.percent(percent),
9217
+ color: css[g],
9218
+ x: cx + outer * Math.cos(mid),
9219
+ y: cy + outer * Math.sin(mid),
9220
+ rows: [
9221
+ ...directed || !asymmetric ? [{
9222
+ name: c.labels.value,
9223
+ value: c.format(value)
9224
+ }] : [],
9225
+ ...asymmetric ? [{
9226
+ name: c.labels.outgoing,
9227
+ value: c.format(goal.out[g])
9228
+ }, {
9229
+ name: c.labels.incoming,
9230
+ value: c.format(goal.inc[g])
9231
+ }] : [],
9232
+ {
9233
+ name: c.labels.share,
9234
+ value: c.percent(percent)
9235
+ }
9236
+ ]
9237
+ });
9238
+ }
9239
+ const flowTotal = target.reduce((s, row) => s + row.reduce((a, b) => a + b, 0), 0);
9240
+ const ribbonItems = ribbons.filter((r) => target[r.s][r.t] > 0 || target[r.t][r.s] > 0).sort((a, b) => pos[a.s] - pos[b.s] || a.src.a0 - b.src.a0 || pos[a.t] - pos[b.t]);
9241
+ for (const r of ribbonItems) {
9242
+ const value = target[r.s][r.t];
9243
+ const reverse = r.s !== r.t && target[r.s][r.t] + target[r.t][r.s] > 0 ? raw[r.t][r.s] : 0;
9244
+ const percent = flowTotal > 0 ? value / flowTotal : 0;
9245
+ const source = names[r.s];
9246
+ const tgt = names[r.t];
9247
+ const ms = (r.src.a0 + r.src.a1) / 2;
9248
+ const mt = (r.tgt.a0 + r.tgt.a1) / 2;
9249
+ const x = r.s === r.t ? cx + ribbonR * .7 * Math.cos(ms) : .25 * (cx + ribbonR * Math.cos(ms)) + .5 * cx + .25 * (cx + ribbonR * Math.cos(mt));
9250
+ const y = r.s === r.t ? cy + ribbonR * .7 * Math.sin(ms) : .25 * (cy + ribbonR * Math.sin(ms)) + .5 * cy + .25 * (cy + ribbonR * Math.sin(mt));
9251
+ items.push({
9252
+ index: r.index,
9253
+ name: r.s === r.t ? source : `${source} \u2192 ${tgt}`,
9254
+ value,
9255
+ percent,
9256
+ share: c.percent(percent),
9257
+ color: css[r.s],
9258
+ x,
9259
+ y,
9260
+ rows: [
9261
+ {
9262
+ name: c.labels.value,
9263
+ value: c.format(value)
9264
+ },
9265
+ ...r.s !== r.t && (!directed || reverse > 0) ? [{
9266
+ name: c.labels.reverse,
9267
+ value: c.format(reverse)
9268
+ }] : [],
9269
+ {
9270
+ name: c.labels.share,
9271
+ value: c.percent(percent)
9272
+ }
9273
+ ],
9274
+ event: {
9275
+ source,
9276
+ target: tgt,
9277
+ reverseValue: reverse
9278
+ }
9279
+ });
9280
+ }
9281
+ const enter = clamp(c.enter, 0, 1);
9282
+ return {
9283
+ nodes,
9284
+ items,
9285
+ dim: .25,
9286
+ empty: false,
9287
+ ...enter < 1 ? { enter: {
9288
+ alpha: enter,
9289
+ scale: .94 + .06 * enter,
9290
+ cx,
9291
+ cy
9292
+ } } : {}
9293
+ };
9294
+ };
9295
+ //#endregion
7790
9296
  //#region ../charts/src/engine/shapes/funnel.ts
7791
9297
  var keysOf$2 = (o) => uniqueKeys(o.data.map((d) => d.name));
7792
9298
  var funnelValues = (o, hidden, out) => {
@@ -10430,6 +11936,9 @@ var layoutShapeScene = (input) => {
10430
11936
  case "bullet":
10431
11937
  result = layoutBullet(o, c);
10432
11938
  break;
11939
+ case "chord":
11940
+ result = layoutChord(o, c);
11941
+ break;
10433
11942
  default: result = layoutTreemap(o, c);
10434
11943
  }
10435
11944
  return {
@@ -10472,6 +11981,9 @@ var shapeValues = (o, hidden = NO_HIDDEN, focus = NO_FOCUS) => {
10472
11981
  case "bullet":
10473
11982
  bulletValues(o, hidden, out);
10474
11983
  break;
11984
+ case "chord":
11985
+ chordValues(o, hidden, out);
11986
+ break;
10475
11987
  default: treemapValues(o, hidden, out);
10476
11988
  }
10477
11989
  return out;
@@ -10575,12 +12087,24 @@ var shapeLegend = (o, theme, hidden = NO_HIDDEN) => {
10575
12087
  case "calendarHeatmap":
10576
12088
  shown = true;
10577
12089
  entries = calendarLegend(o, theme, hidden);
12090
+ break;
12091
+ case "chord": {
12092
+ shown = true;
12093
+ const m = resolveChord(o);
12094
+ entries = m.names.map((name, i) => ({
12095
+ index: i,
12096
+ name,
12097
+ color: color(m.colors[i], i),
12098
+ hidden: hidden.has(i)
12099
+ }));
12100
+ break;
12101
+ }
10578
12102
  }
10579
12103
  return shown && entries.length ? entries : null;
10580
12104
  };
10581
12105
  /**
10582
12106
  * Number of toggleable entries (slices, stages, series, top-level nodes,
10583
- * sankey nodes, bars, rows, calendar levels)
12107
+ * sankey nodes, bars, rows, calendar levels, chord groups)
10584
12108
  */
10585
12109
  var toggleCount = (o) => {
10586
12110
  switch (o.type) {
@@ -10588,6 +12112,7 @@ var toggleCount = (o) => {
10588
12112
  case "gauge": return 0;
10589
12113
  case "sankey": return resolveSankey(o).names.length;
10590
12114
  case "calendarHeatmap": return calendarModel(o)?.count ?? 0;
12115
+ case "chord": return resolveChord(o).names.length;
10591
12116
  default: return o.data.length;
10592
12117
  }
10593
12118
  };
@@ -10758,6 +12283,7 @@ var layoutShapeTooltip = (value, anchorX, anchorY, width, height, theme, measure
10758
12283
  let lines;
10759
12284
  let content;
10760
12285
  let text;
12286
+ let titleLines;
10761
12287
  if (typeof value === "string") {
10762
12288
  text = value.split("\n");
10763
12289
  const f = font(theme, 12);
@@ -10765,9 +12291,14 @@ var layoutShapeTooltip = (value, anchorX, anchorY, width, height, theme, measure
10765
12291
  lines = text.length;
10766
12292
  } else {
10767
12293
  content = value;
10768
- w = (value.color ? 14 : 0) + measure(value.title, font(theme, 12, 600));
12294
+ const titleFont = font(theme, 12, 600);
12295
+ const dot = value.color ? 14 : 0;
12296
+ const maxTitle = Math.max(60, Math.min(260, width - 16 - 18) - dot);
12297
+ titleLines = wrapText(value.title, maxTitle, titleFont, measure, 3);
12298
+ if (!titleLines.length) titleLines = [value.title];
12299
+ for (const line of titleLines) w = Math.max(w, dot + measure(line, titleFont));
10769
12300
  for (const row of value.rows) w = Math.max(w, (row.color ? 14 : 0) + measure(row.name, font(theme, 12)) + 16 + measure(row.value, font(theme, 12, 600)));
10770
- lines = 1 + value.rows.length;
12301
+ lines = titleLines.length + value.rows.length;
10771
12302
  }
10772
12303
  const bw = Math.max(96, Math.ceil(w + 18 + 4));
10773
12304
  const bh = lines * lineHeight + 18;
@@ -10782,7 +12313,10 @@ var layoutShapeTooltip = (value, anchorX, anchorY, width, height, theme, measure
10782
12313
  height: bh,
10783
12314
  padding,
10784
12315
  lineHeight,
10785
- ...content ? { content } : {},
12316
+ ...content ? {
12317
+ content,
12318
+ titleLines
12319
+ } : {},
10786
12320
  ...text ? { text } : {}
10787
12321
  };
10788
12322
  };
@@ -11308,6 +12842,12 @@ Object.defineProperty(exports, "formatCompact", {
11308
12842
  return formatCompact;
11309
12843
  }
11310
12844
  });
12845
+ Object.defineProperty(exports, "formatDuration", {
12846
+ enumerable: true,
12847
+ get: function() {
12848
+ return formatDuration;
12849
+ }
12850
+ });
11311
12851
  Object.defineProperty(exports, "formatValue", {
11312
12852
  enumerable: true,
11313
12853
  get: function() {