@carto/ps-react-ui 4.7.0 → 4.8.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 (578) hide show
  1. package/dist/category-DwaeYjpX.js +656 -0
  2. package/dist/category-DwaeYjpX.js.map +1 -0
  3. package/dist/change-column-Cidl_M-4.js +1110 -0
  4. package/dist/change-column-Cidl_M-4.js.map +1 -0
  5. package/dist/data-zoom-layout-BH0LPwSy.js +28 -0
  6. package/dist/data-zoom-layout-BH0LPwSy.js.map +1 -0
  7. package/dist/echart-CU0KmClP.js +176 -0
  8. package/dist/echart-CU0KmClP.js.map +1 -0
  9. package/dist/exports-Cx-f6m6U.js +63 -0
  10. package/dist/exports-Cx-f6m6U.js.map +1 -0
  11. package/dist/formula-DuC0NQLH.js +79 -0
  12. package/dist/formula-DuC0NQLH.js.map +1 -0
  13. package/dist/markdown-BD1jcknS.js +8326 -0
  14. package/dist/markdown-BD1jcknS.js.map +1 -0
  15. package/dist/merge-options-DCkkHZIf.js +34 -0
  16. package/dist/merge-options-DCkkHZIf.js.map +1 -0
  17. package/dist/{styles-BYTyKQFP.js → option-builders-F-c9ELi1.js} +25 -45
  18. package/dist/option-builders-F-c9ELi1.js.map +1 -0
  19. package/dist/png-item-CS4z1iSH.js +45 -0
  20. package/dist/png-item-CS4z1iSH.js.map +1 -0
  21. package/dist/range-DsqTjSpg.js +186 -0
  22. package/dist/range-DsqTjSpg.js.map +1 -0
  23. package/dist/spread-CTuIXZSM.js +67 -0
  24. package/dist/spread-CTuIXZSM.js.map +1 -0
  25. package/dist/style-DVnT6HC1.js +131 -0
  26. package/dist/style-DVnT6HC1.js.map +1 -0
  27. package/dist/styles-cohnxh9F.js +23 -0
  28. package/dist/styles-cohnxh9F.js.map +1 -0
  29. package/dist/table-HIpXuq4G.js +390 -0
  30. package/dist/table-HIpXuq4G.js.map +1 -0
  31. package/dist/transforms-Cdx4fkU5.js +106 -0
  32. package/dist/transforms-Cdx4fkU5.js.map +1 -0
  33. package/dist/types/widgets/echart/utils.test.d.ts +1 -0
  34. package/dist/types/widgets/formula/config.test.d.ts +1 -0
  35. package/dist/types/widgets/stores/widget-store-branches.test.d.ts +1 -0
  36. package/dist/types/widgets/table/config.test.d.ts +1 -0
  37. package/dist/types/widgets-v2/actions/brush-toggle/brush-toggle.d.ts +56 -0
  38. package/dist/types/widgets-v2/actions/brush-toggle/index.d.ts +3 -0
  39. package/dist/types/widgets-v2/actions/brush-toggle/labels.d.ts +5 -0
  40. package/dist/types/widgets-v2/actions/brush-toggle/style.d.ts +12 -0
  41. package/dist/types/widgets-v2/actions/brush-toggle/transforms.d.ts +11 -0
  42. package/dist/types/widgets-v2/actions/brush-toggle/transforms.test.d.ts +1 -0
  43. package/dist/types/widgets-v2/actions/change-column/change-column-icon.d.ts +2 -0
  44. package/dist/types/widgets-v2/actions/change-column/change-column.d.ts +29 -0
  45. package/dist/types/widgets-v2/actions/change-column/index.d.ts +3 -0
  46. package/dist/types/widgets-v2/actions/change-column/labels.d.ts +5 -0
  47. package/dist/types/widgets-v2/actions/change-column/sortable-column-item.d.ts +14 -0
  48. package/dist/types/widgets-v2/actions/change-column/style.d.ts +33 -0
  49. package/dist/types/widgets-v2/actions/change-column/types.d.ts +10 -0
  50. package/dist/types/widgets-v2/actions/download/download.d.ts +18 -0
  51. package/dist/types/widgets-v2/actions/download/exports.d.ts +37 -0
  52. package/dist/types/widgets-v2/actions/download/icons.d.ts +12 -0
  53. package/dist/types/widgets-v2/actions/download/index.d.ts +6 -0
  54. package/dist/types/widgets-v2/actions/download/labels.d.ts +11 -0
  55. package/dist/types/widgets-v2/actions/download/png-item.d.ts +24 -0
  56. package/dist/types/widgets-v2/actions/download/style.d.ts +1 -0
  57. package/dist/types/widgets-v2/actions/download/types.d.ts +35 -0
  58. package/dist/types/widgets-v2/actions/fullscreen/fullscreen.d.ts +59 -0
  59. package/dist/types/widgets-v2/actions/fullscreen/index.d.ts +3 -0
  60. package/dist/types/widgets-v2/actions/fullscreen/labels.d.ts +5 -0
  61. package/dist/types/widgets-v2/actions/fullscreen/style.d.ts +48 -0
  62. package/dist/types/widgets-v2/actions/fullscreen/types.d.ts +14 -0
  63. package/dist/types/widgets-v2/actions/index.d.ts +9 -0
  64. package/dist/types/widgets-v2/actions/lock-selection/index.d.ts +3 -0
  65. package/dist/types/widgets-v2/actions/lock-selection/labels.d.ts +6 -0
  66. package/dist/types/widgets-v2/actions/lock-selection/lock-selection.d.ts +36 -0
  67. package/dist/types/widgets-v2/actions/lock-selection/style.d.ts +12 -0
  68. package/dist/types/widgets-v2/actions/lock-selection/transforms.d.ts +6 -0
  69. package/dist/types/widgets-v2/actions/relative-data/index.d.ts +3 -0
  70. package/dist/types/widgets-v2/actions/relative-data/labels.d.ts +5 -0
  71. package/dist/types/widgets-v2/actions/relative-data/relative-data.d.ts +39 -0
  72. package/dist/types/widgets-v2/actions/relative-data/style.d.ts +12 -0
  73. package/dist/types/widgets-v2/actions/relative-data/transforms.d.ts +30 -0
  74. package/dist/types/widgets-v2/actions/relative-data/transforms.test.d.ts +1 -0
  75. package/dist/types/widgets-v2/actions/searcher/filter.d.ts +6 -0
  76. package/dist/types/widgets-v2/actions/searcher/index.d.ts +4 -0
  77. package/dist/types/widgets-v2/actions/searcher/labels.d.ts +7 -0
  78. package/dist/types/widgets-v2/actions/searcher/searcher-toggle.d.ts +23 -0
  79. package/dist/types/widgets-v2/actions/searcher/searcher.d.ts +11 -0
  80. package/dist/types/widgets-v2/actions/searcher/style.d.ts +16 -0
  81. package/dist/types/widgets-v2/actions/stack-toggle/index.d.ts +3 -0
  82. package/dist/types/widgets-v2/actions/stack-toggle/labels.d.ts +5 -0
  83. package/dist/types/widgets-v2/actions/stack-toggle/stack-toggle.d.ts +10 -0
  84. package/dist/types/widgets-v2/actions/stack-toggle/style.d.ts +12 -0
  85. package/dist/types/widgets-v2/actions/stack-toggle/transforms.d.ts +13 -0
  86. package/dist/types/widgets-v2/actions/stack-toggle/transforms.test.d.ts +1 -0
  87. package/dist/types/widgets-v2/actions/zoom-toggle/index.d.ts +3 -0
  88. package/dist/types/widgets-v2/actions/zoom-toggle/labels.d.ts +5 -0
  89. package/dist/types/widgets-v2/actions/zoom-toggle/style.d.ts +12 -0
  90. package/dist/types/widgets-v2/actions/zoom-toggle/transforms.d.ts +51 -0
  91. package/dist/types/widgets-v2/actions/zoom-toggle/transforms.test.d.ts +1 -0
  92. package/dist/types/widgets-v2/actions/zoom-toggle/zoom-toggle.d.ts +35 -0
  93. package/dist/types/widgets-v2/bar/download.d.ts +24 -0
  94. package/dist/types/widgets-v2/bar/index.d.ts +4 -0
  95. package/dist/types/widgets-v2/bar/options.d.ts +43 -0
  96. package/dist/types/widgets-v2/bar/options.test.d.ts +1 -0
  97. package/dist/types/widgets-v2/bar/skeleton.d.ts +6 -0
  98. package/dist/types/widgets-v2/bar/types.d.ts +41 -0
  99. package/dist/types/widgets-v2/category/category-ui.d.ts +81 -0
  100. package/dist/types/widgets-v2/category/category.d.ts +48 -0
  101. package/dist/types/widgets-v2/category/components/category-bar-stacked.d.ts +28 -0
  102. package/dist/types/widgets-v2/category/components/category-bar.d.ts +23 -0
  103. package/dist/types/widgets-v2/category/components/category-legend.d.ts +18 -0
  104. package/dist/types/widgets-v2/category/components/category-row-multi.d.ts +31 -0
  105. package/dist/types/widgets-v2/category/components/category-row-other.d.ts +13 -0
  106. package/dist/types/widgets-v2/category/components/category-row-single.d.ts +28 -0
  107. package/dist/types/widgets-v2/category/components/category-row-stacked.d.ts +38 -0
  108. package/dist/types/widgets-v2/category/download.d.ts +16 -0
  109. package/dist/types/widgets-v2/category/download.test.d.ts +1 -0
  110. package/dist/types/widgets-v2/category/index.d.ts +10 -0
  111. package/dist/types/widgets-v2/category/skeleton.d.ts +11 -0
  112. package/dist/types/widgets-v2/category/style.d.ts +166 -0
  113. package/dist/types/widgets-v2/category/types.d.ts +49 -0
  114. package/dist/types/widgets-v2/echart/echart-ui.d.ts +44 -0
  115. package/dist/types/widgets-v2/echart/echart.d.ts +75 -0
  116. package/dist/types/widgets-v2/echart/index.d.ts +4 -0
  117. package/dist/types/widgets-v2/echart/shared-resize-observer.d.ts +5 -0
  118. package/dist/types/widgets-v2/echart/shared-resize-observer.test.d.ts +1 -0
  119. package/dist/types/widgets-v2/echart/style.d.ts +6 -0
  120. package/dist/types/widgets-v2/echart/use-chart-selection.d.ts +51 -0
  121. package/dist/types/widgets-v2/formula/delta.d.ts +22 -0
  122. package/dist/types/widgets-v2/formula/download.d.ts +20 -0
  123. package/dist/types/widgets-v2/formula/formula-ui.d.ts +20 -0
  124. package/dist/types/widgets-v2/formula/formula.d.ts +8 -0
  125. package/dist/types/widgets-v2/formula/index.d.ts +11 -0
  126. package/dist/types/widgets-v2/formula/note.d.ts +11 -0
  127. package/dist/types/widgets-v2/formula/prefix.d.ts +12 -0
  128. package/dist/types/widgets-v2/formula/series.d.ts +16 -0
  129. package/dist/types/widgets-v2/formula/skeleton.d.ts +4 -0
  130. package/dist/types/widgets-v2/formula/style.d.ts +29 -0
  131. package/dist/types/widgets-v2/formula/suffix.d.ts +12 -0
  132. package/dist/types/widgets-v2/formula/types.d.ts +40 -0
  133. package/dist/types/widgets-v2/formula/value.d.ts +14 -0
  134. package/dist/types/widgets-v2/histogram/download.d.ts +17 -0
  135. package/dist/types/widgets-v2/histogram/download.test.d.ts +1 -0
  136. package/dist/types/widgets-v2/histogram/index.d.ts +5 -0
  137. package/dist/types/widgets-v2/histogram/options.d.ts +42 -0
  138. package/dist/types/widgets-v2/histogram/options.test.d.ts +1 -0
  139. package/dist/types/widgets-v2/histogram/skeleton.d.ts +9 -0
  140. package/dist/types/widgets-v2/histogram/transforms.d.ts +17 -0
  141. package/dist/types/widgets-v2/histogram/transforms.test.d.ts +1 -0
  142. package/dist/types/widgets-v2/histogram/types.d.ts +47 -0
  143. package/dist/types/widgets-v2/index.d.ts +107 -0
  144. package/dist/types/widgets-v2/markdown/download.d.ts +16 -0
  145. package/dist/types/widgets-v2/markdown/download.test.d.ts +1 -0
  146. package/dist/types/widgets-v2/markdown/index.d.ts +6 -0
  147. package/dist/types/widgets-v2/markdown/markdown-content.d.ts +34 -0
  148. package/dist/types/widgets-v2/markdown/markdown-ui.d.ts +12 -0
  149. package/dist/types/widgets-v2/markdown/markdown.d.ts +6 -0
  150. package/dist/types/widgets-v2/markdown/skeleton.d.ts +4 -0
  151. package/dist/types/widgets-v2/markdown/style.d.ts +61 -0
  152. package/dist/types/widgets-v2/markdown/types.d.ts +4 -0
  153. package/dist/types/widgets-v2/note/labels.d.ts +5 -0
  154. package/dist/types/widgets-v2/note/style.d.ts +26 -0
  155. package/dist/types/widgets-v2/note/widget-note.d.ts +46 -0
  156. package/dist/types/widgets-v2/pie/download.d.ts +17 -0
  157. package/dist/types/widgets-v2/pie/download.test.d.ts +1 -0
  158. package/dist/types/widgets-v2/pie/index.d.ts +4 -0
  159. package/dist/types/widgets-v2/pie/options.d.ts +35 -0
  160. package/dist/types/widgets-v2/pie/options.test.d.ts +1 -0
  161. package/dist/types/widgets-v2/pie/skeleton.d.ts +4 -0
  162. package/dist/types/widgets-v2/pie/types.d.ts +50 -0
  163. package/dist/types/widgets-v2/provider/widget-provider.d.ts +32 -0
  164. package/dist/types/widgets-v2/range/index.d.ts +4 -0
  165. package/dist/types/widgets-v2/range/range-ui.d.ts +19 -0
  166. package/dist/types/widgets-v2/range/range.d.ts +19 -0
  167. package/dist/types/widgets-v2/range/skeleton.d.ts +9 -0
  168. package/dist/types/widgets-v2/range/style.d.ts +40 -0
  169. package/dist/types/widgets-v2/range/types.d.ts +37 -0
  170. package/dist/types/widgets-v2/scatterplot/download.d.ts +16 -0
  171. package/dist/types/widgets-v2/scatterplot/download.test.d.ts +1 -0
  172. package/dist/types/widgets-v2/scatterplot/index.d.ts +5 -0
  173. package/dist/types/widgets-v2/scatterplot/options.d.ts +42 -0
  174. package/dist/types/widgets-v2/scatterplot/options.test.d.ts +1 -0
  175. package/dist/types/widgets-v2/scatterplot/skeleton.d.ts +12 -0
  176. package/dist/types/widgets-v2/scatterplot/transforms.d.ts +17 -0
  177. package/dist/types/widgets-v2/scatterplot/transforms.test.d.ts +1 -0
  178. package/dist/types/widgets-v2/scatterplot/types.d.ts +50 -0
  179. package/dist/types/widgets-v2/selection-summary/labels.d.ts +6 -0
  180. package/dist/types/widgets-v2/selection-summary/selection-summary.d.ts +22 -0
  181. package/dist/types/widgets-v2/selection-summary/style.d.ts +23 -0
  182. package/dist/types/widgets-v2/spread/download.d.ts +15 -0
  183. package/dist/types/widgets-v2/spread/download.test.d.ts +1 -0
  184. package/dist/types/widgets-v2/spread/index.d.ts +6 -0
  185. package/dist/types/widgets-v2/spread/separator.d.ts +7 -0
  186. package/dist/types/widgets-v2/spread/skeleton.d.ts +9 -0
  187. package/dist/types/widgets-v2/spread/spread-ui.d.ts +18 -0
  188. package/dist/types/widgets-v2/spread/spread.d.ts +5 -0
  189. package/dist/types/widgets-v2/spread/types.d.ts +25 -0
  190. package/dist/types/widgets-v2/state/labels.d.ts +7 -0
  191. package/dist/types/widgets-v2/state/labels.test.d.ts +1 -0
  192. package/dist/types/widgets-v2/state/style.d.ts +19 -0
  193. package/dist/types/widgets-v2/state/widget-state.d.ts +19 -0
  194. package/dist/types/widgets-v2/stores/index.d.ts +8 -0
  195. package/dist/types/widgets-v2/stores/pipeline-middleware.d.ts +5 -0
  196. package/dist/types/widgets-v2/stores/pipeline-middleware.test.d.ts +1 -0
  197. package/dist/types/widgets-v2/stores/transforms.d.ts +4 -0
  198. package/dist/types/widgets-v2/stores/transforms.test.d.ts +1 -0
  199. package/dist/types/widgets-v2/stores/types.d.ts +55 -0
  200. package/dist/types/widgets-v2/stores/use-echart-instance.d.ts +15 -0
  201. package/dist/types/widgets-v2/stores/use-transform-enabled.d.ts +17 -0
  202. package/dist/types/widgets-v2/stores/use-transform.d.ts +12 -0
  203. package/dist/types/widgets-v2/stores/widget-context.d.ts +2 -0
  204. package/dist/types/widgets-v2/stores/widget-store-registry.d.ts +74 -0
  205. package/dist/types/widgets-v2/stores/widget-store-registry.test.d.ts +1 -0
  206. package/dist/types/widgets-v2/subheader/style.d.ts +10 -0
  207. package/dist/types/widgets-v2/subheader/subheader.d.ts +11 -0
  208. package/dist/types/widgets-v2/table/download.d.ts +18 -0
  209. package/dist/types/widgets-v2/table/download.test.d.ts +1 -0
  210. package/dist/types/widgets-v2/table/helpers.d.ts +32 -0
  211. package/dist/types/widgets-v2/table/helpers.test.d.ts +1 -0
  212. package/dist/types/widgets-v2/table/index.d.ts +7 -0
  213. package/dist/types/widgets-v2/table/labels.d.ts +22 -0
  214. package/dist/types/widgets-v2/table/skeleton.d.ts +22 -0
  215. package/dist/types/widgets-v2/table/style.d.ts +44 -0
  216. package/dist/types/widgets-v2/table/table-ui.d.ts +38 -0
  217. package/dist/types/widgets-v2/table/table.d.ts +50 -0
  218. package/dist/types/widgets-v2/table/types.d.ts +37 -0
  219. package/dist/types/widgets-v2/test-utils.d.ts +52 -0
  220. package/dist/types/widgets-v2/timeseries/download.d.ts +17 -0
  221. package/dist/types/widgets-v2/timeseries/download.test.d.ts +1 -0
  222. package/dist/types/widgets-v2/timeseries/index.d.ts +4 -0
  223. package/dist/types/widgets-v2/timeseries/options.d.ts +39 -0
  224. package/dist/types/widgets-v2/timeseries/options.test.d.ts +1 -0
  225. package/dist/types/widgets-v2/timeseries/skeleton.d.ts +8 -0
  226. package/dist/types/widgets-v2/timeseries/types.d.ts +56 -0
  227. package/dist/types/widgets-v2/toolbox/labels.d.ts +5 -0
  228. package/dist/types/widgets-v2/toolbox/style.d.ts +30 -0
  229. package/dist/types/widgets-v2/toolbox/toolbox.d.ts +49 -0
  230. package/dist/types/widgets-v2/utils/data-zoom-layout.d.ts +11 -0
  231. package/dist/types/widgets-v2/utils/index.d.ts +2 -0
  232. package/dist/types/widgets-v2/utils/merge-options.d.ts +12 -0
  233. package/dist/types/widgets-v2/utils/merge-options.test.d.ts +1 -0
  234. package/dist/types/widgets-v2/wrapper/index.d.ts +4 -0
  235. package/dist/types/widgets-v2/wrapper/labels.d.ts +6 -0
  236. package/dist/types/widgets-v2/wrapper/style.d.ts +111 -0
  237. package/dist/types/widgets-v2/wrapper/widget-actions.d.ts +22 -0
  238. package/dist/types/widgets-v2/wrapper/widget-content.d.ts +12 -0
  239. package/dist/types/widgets-v2/wrapper/widget-wrapper.d.ts +51 -0
  240. package/dist/use-transform-DXPN3nY7.js +110 -0
  241. package/dist/use-transform-DXPN3nY7.js.map +1 -0
  242. package/dist/widget-context-DTGO0Yta.js +13 -0
  243. package/dist/widget-context-DTGO0Yta.js.map +1 -0
  244. package/dist/widget-store-registry-_W4Z4xp-.js +178 -0
  245. package/dist/widget-store-registry-_W4Z4xp-.js.map +1 -0
  246. package/dist/widgets/actions.js +688 -668
  247. package/dist/widgets/actions.js.map +1 -1
  248. package/dist/widgets/bar.js +14 -13
  249. package/dist/widgets/bar.js.map +1 -1
  250. package/dist/widgets/histogram.js +38 -37
  251. package/dist/widgets/histogram.js.map +1 -1
  252. package/dist/widgets/pie.js +19 -18
  253. package/dist/widgets/pie.js.map +1 -1
  254. package/dist/widgets/scatterplot.js +8 -7
  255. package/dist/widgets/scatterplot.js.map +1 -1
  256. package/dist/widgets/timeseries.js +11 -10
  257. package/dist/widgets/timeseries.js.map +1 -1
  258. package/dist/widgets/utils.js +8 -7
  259. package/dist/widgets/utils.js.map +1 -1
  260. package/dist/widgets-v2/actions.js +43 -0
  261. package/dist/widgets-v2/actions.js.map +1 -0
  262. package/dist/widgets-v2/bar.js +327 -0
  263. package/dist/widgets-v2/bar.js.map +1 -0
  264. package/dist/widgets-v2/category.js +104 -0
  265. package/dist/widgets-v2/category.js.map +1 -0
  266. package/dist/widgets-v2/echart.js +57 -0
  267. package/dist/widgets-v2/echart.js.map +1 -0
  268. package/dist/widgets-v2/formula.js +74 -0
  269. package/dist/widgets-v2/formula.js.map +1 -0
  270. package/dist/widgets-v2/histogram.js +350 -0
  271. package/dist/widgets-v2/histogram.js.map +1 -0
  272. package/dist/widgets-v2/markdown.js +68 -0
  273. package/dist/widgets-v2/markdown.js.map +1 -0
  274. package/dist/widgets-v2/pie.js +381 -0
  275. package/dist/widgets-v2/pie.js.map +1 -0
  276. package/dist/widgets-v2/range.js +52 -0
  277. package/dist/widgets-v2/range.js.map +1 -0
  278. package/dist/widgets-v2/scatterplot.js +405 -0
  279. package/dist/widgets-v2/scatterplot.js.map +1 -0
  280. package/dist/widgets-v2/spread.js +72 -0
  281. package/dist/widgets-v2/spread.js.map +1 -0
  282. package/dist/widgets-v2/stores.js +42 -0
  283. package/dist/widgets-v2/stores.js.map +1 -0
  284. package/dist/widgets-v2/table.js +78 -0
  285. package/dist/widgets-v2/table.js.map +1 -0
  286. package/dist/widgets-v2/timeseries.js +352 -0
  287. package/dist/widgets-v2/timeseries.js.map +1 -0
  288. package/dist/widgets-v2/utils.js +7 -0
  289. package/dist/widgets-v2/utils.js.map +1 -0
  290. package/dist/widgets-v2.js +953 -0
  291. package/dist/widgets-v2.js.map +1 -0
  292. package/package.json +73 -5
  293. package/src/components/lasso-tool/chip.test.tsx +176 -0
  294. package/src/components/lasso-tool/lasso-tool-inline.test.tsx +171 -0
  295. package/src/components/lasso-tool/lasso-tool.test.tsx +198 -0
  296. package/src/components/list-data/list-data.test.tsx +73 -0
  297. package/src/components/no-data-alert/no-data-alert.test.tsx +38 -0
  298. package/src/components/responsive-drawer/responsive-drawer.test.tsx +68 -0
  299. package/src/widgets/actions/brush-toggle/brush-overlay.test.tsx +465 -0
  300. package/src/widgets/actions/brush-toggle/brush-overlay.tsx +24 -2
  301. package/src/widgets/actions/brush-toggle/brush-toggle.test.tsx +208 -0
  302. package/src/widgets/actions/change-column/change-column-dnd.test.tsx +193 -0
  303. package/src/widgets/actions/change-column/sortable-column-item.test.tsx +124 -0
  304. package/src/widgets/actions/zoom-toggle/zoom-toggle.test.tsx +322 -0
  305. package/src/widgets/category/components/category-rows.test.tsx +213 -0
  306. package/src/widgets/echart/utils.test.ts +277 -0
  307. package/src/widgets/formula/config.test.ts +37 -0
  308. package/src/widgets/histogram/config.ts +1 -3
  309. package/src/widgets/range/components/range-item.test.tsx +243 -0
  310. package/src/widgets/stores/widget-store-branches.test.ts +275 -0
  311. package/src/widgets/table/config.test.ts +65 -0
  312. package/src/widgets/utils/chart-config/option-builders.test.ts +188 -0
  313. package/src/widgets-v2/PERFORMANCE.md +189 -0
  314. package/src/widgets-v2/actions/brush-toggle/brush-toggle.test.tsx +180 -0
  315. package/src/widgets-v2/actions/brush-toggle/brush-toggle.tsx +154 -0
  316. package/src/widgets-v2/actions/brush-toggle/index.ts +3 -0
  317. package/src/widgets-v2/actions/brush-toggle/labels.ts +9 -0
  318. package/src/widgets-v2/actions/brush-toggle/style.ts +11 -0
  319. package/src/widgets-v2/actions/brush-toggle/transforms.test.ts +47 -0
  320. package/src/widgets-v2/actions/brush-toggle/transforms.ts +31 -0
  321. package/src/widgets-v2/actions/change-column/change-column-icon.tsx +14 -0
  322. package/src/widgets-v2/actions/change-column/change-column.test.tsx +59 -0
  323. package/src/widgets-v2/actions/change-column/change-column.tsx +180 -0
  324. package/src/widgets-v2/actions/change-column/index.ts +7 -0
  325. package/src/widgets-v2/actions/change-column/labels.ts +9 -0
  326. package/src/widgets-v2/actions/change-column/sortable-column-item.tsx +56 -0
  327. package/src/widgets-v2/actions/change-column/style.ts +32 -0
  328. package/src/widgets-v2/actions/change-column/types.ts +11 -0
  329. package/src/widgets-v2/actions/download/download.test.tsx +327 -0
  330. package/src/widgets-v2/actions/download/download.tsx +144 -0
  331. package/src/widgets-v2/actions/download/exports.test.tsx +198 -0
  332. package/src/widgets-v2/actions/download/exports.ts +115 -0
  333. package/src/widgets-v2/actions/download/icons.tsx +26 -0
  334. package/src/widgets-v2/actions/download/index.ts +13 -0
  335. package/src/widgets-v2/actions/download/labels.ts +16 -0
  336. package/src/widgets-v2/actions/download/png-item.test.tsx +72 -0
  337. package/src/widgets-v2/actions/download/png-item.tsx +52 -0
  338. package/src/widgets-v2/actions/download/style.ts +3 -0
  339. package/src/widgets-v2/actions/download/types.ts +32 -0
  340. package/src/widgets-v2/actions/fullscreen/fullscreen.test.tsx +150 -0
  341. package/src/widgets-v2/actions/fullscreen/fullscreen.tsx +230 -0
  342. package/src/widgets-v2/actions/fullscreen/index.ts +7 -0
  343. package/src/widgets-v2/actions/fullscreen/labels.ts +9 -0
  344. package/src/widgets-v2/actions/fullscreen/style.ts +59 -0
  345. package/src/widgets-v2/actions/fullscreen/types.ts +15 -0
  346. package/src/widgets-v2/actions/index.ts +82 -0
  347. package/src/widgets-v2/actions/lock-selection/index.ts +10 -0
  348. package/src/widgets-v2/actions/lock-selection/labels.ts +11 -0
  349. package/src/widgets-v2/actions/lock-selection/lock-selection.test.tsx +187 -0
  350. package/src/widgets-v2/actions/lock-selection/lock-selection.tsx +130 -0
  351. package/src/widgets-v2/actions/lock-selection/style.ts +11 -0
  352. package/src/widgets-v2/actions/lock-selection/transforms.ts +27 -0
  353. package/src/widgets-v2/actions/relative-data/index.ts +3 -0
  354. package/src/widgets-v2/actions/relative-data/labels.ts +9 -0
  355. package/src/widgets-v2/actions/relative-data/relative-data.test.tsx +71 -0
  356. package/src/widgets-v2/actions/relative-data/relative-data.tsx +107 -0
  357. package/src/widgets-v2/actions/relative-data/style.ts +11 -0
  358. package/src/widgets-v2/actions/relative-data/transforms.test.ts +151 -0
  359. package/src/widgets-v2/actions/relative-data/transforms.ts +70 -0
  360. package/src/widgets-v2/actions/searcher/filter.ts +28 -0
  361. package/src/widgets-v2/actions/searcher/index.ts +8 -0
  362. package/src/widgets-v2/actions/searcher/labels.ts +13 -0
  363. package/src/widgets-v2/actions/searcher/searcher-toggle.tsx +91 -0
  364. package/src/widgets-v2/actions/searcher/searcher.test.tsx +92 -0
  365. package/src/widgets-v2/actions/searcher/searcher.tsx +112 -0
  366. package/src/widgets-v2/actions/searcher/style.ts +15 -0
  367. package/src/widgets-v2/actions/stack-toggle/index.ts +3 -0
  368. package/src/widgets-v2/actions/stack-toggle/labels.ts +9 -0
  369. package/src/widgets-v2/actions/stack-toggle/stack-toggle.test.tsx +61 -0
  370. package/src/widgets-v2/actions/stack-toggle/stack-toggle.tsx +54 -0
  371. package/src/widgets-v2/actions/stack-toggle/style.ts +11 -0
  372. package/src/widgets-v2/actions/stack-toggle/transforms.test.ts +43 -0
  373. package/src/widgets-v2/actions/stack-toggle/transforms.ts +25 -0
  374. package/src/widgets-v2/actions/zoom-toggle/index.ts +9 -0
  375. package/src/widgets-v2/actions/zoom-toggle/labels.ts +9 -0
  376. package/src/widgets-v2/actions/zoom-toggle/style.ts +11 -0
  377. package/src/widgets-v2/actions/zoom-toggle/transforms.test.ts +148 -0
  378. package/src/widgets-v2/actions/zoom-toggle/transforms.ts +171 -0
  379. package/src/widgets-v2/actions/zoom-toggle/zoom-toggle.test.tsx +107 -0
  380. package/src/widgets-v2/actions/zoom-toggle/zoom-toggle.tsx +106 -0
  381. package/src/widgets-v2/bar/download.test.tsx +91 -0
  382. package/src/widgets-v2/bar/download.tsx +66 -0
  383. package/src/widgets-v2/bar/index.ts +10 -0
  384. package/src/widgets-v2/bar/options.test.ts +317 -0
  385. package/src/widgets-v2/bar/options.ts +326 -0
  386. package/src/widgets-v2/bar/skeleton.test.tsx +19 -0
  387. package/src/widgets-v2/bar/skeleton.tsx +69 -0
  388. package/src/widgets-v2/bar/types.ts +46 -0
  389. package/src/widgets-v2/category/category-ui.test.tsx +746 -0
  390. package/src/widgets-v2/category/category-ui.tsx +389 -0
  391. package/src/widgets-v2/category/category.relative-data.test.tsx +107 -0
  392. package/src/widgets-v2/category/category.stack-toggle.test.tsx +85 -0
  393. package/src/widgets-v2/category/category.test.tsx +305 -0
  394. package/src/widgets-v2/category/category.tsx +121 -0
  395. package/src/widgets-v2/category/components/category-bar-stacked.test.tsx +121 -0
  396. package/src/widgets-v2/category/components/category-bar-stacked.tsx +73 -0
  397. package/src/widgets-v2/category/components/category-bar.test.tsx +64 -0
  398. package/src/widgets-v2/category/components/category-bar.tsx +49 -0
  399. package/src/widgets-v2/category/components/category-legend.test.tsx +51 -0
  400. package/src/widgets-v2/category/components/category-legend.tsx +39 -0
  401. package/src/widgets-v2/category/components/category-row-multi.tsx +86 -0
  402. package/src/widgets-v2/category/components/category-row-other.test.tsx +28 -0
  403. package/src/widgets-v2/category/components/category-row-other.tsx +33 -0
  404. package/src/widgets-v2/category/components/category-row-single.tsx +76 -0
  405. package/src/widgets-v2/category/components/category-row-stacked.test.tsx +244 -0
  406. package/src/widgets-v2/category/components/category-row-stacked.tsx +99 -0
  407. package/src/widgets-v2/category/download.test.ts +71 -0
  408. package/src/widgets-v2/category/download.ts +54 -0
  409. package/src/widgets-v2/category/index.ts +32 -0
  410. package/src/widgets-v2/category/skeleton.test.tsx +26 -0
  411. package/src/widgets-v2/category/skeleton.tsx +74 -0
  412. package/src/widgets-v2/category/style.ts +290 -0
  413. package/src/widgets-v2/category/types.ts +54 -0
  414. package/src/widgets-v2/echart/echart-ui.test.tsx +232 -0
  415. package/src/widgets-v2/echart/echart-ui.tsx +184 -0
  416. package/src/widgets-v2/echart/echart.test.tsx +229 -0
  417. package/src/widgets-v2/echart/echart.tsx +199 -0
  418. package/src/widgets-v2/echart/index.ts +22 -0
  419. package/src/widgets-v2/echart/shared-resize-observer.test.ts +91 -0
  420. package/src/widgets-v2/echart/shared-resize-observer.ts +56 -0
  421. package/src/widgets-v2/echart/style.ts +8 -0
  422. package/src/widgets-v2/echart/use-chart-selection.test.tsx +118 -0
  423. package/src/widgets-v2/echart/use-chart-selection.ts +115 -0
  424. package/src/widgets-v2/formula/delta.tsx +61 -0
  425. package/src/widgets-v2/formula/download.test.tsx +65 -0
  426. package/src/widgets-v2/formula/download.tsx +69 -0
  427. package/src/widgets-v2/formula/formula-ui.test.tsx +91 -0
  428. package/src/widgets-v2/formula/formula-ui.tsx +66 -0
  429. package/src/widgets-v2/formula/formula.test.tsx +50 -0
  430. package/src/widgets-v2/formula/formula.tsx +34 -0
  431. package/src/widgets-v2/formula/index.ts +17 -0
  432. package/src/widgets-v2/formula/note.tsx +25 -0
  433. package/src/widgets-v2/formula/prefix.tsx +25 -0
  434. package/src/widgets-v2/formula/series.tsx +67 -0
  435. package/src/widgets-v2/formula/skeleton.test.tsx +21 -0
  436. package/src/widgets-v2/formula/skeleton.tsx +27 -0
  437. package/src/widgets-v2/formula/style.ts +31 -0
  438. package/src/widgets-v2/formula/subcomponents.test.tsx +107 -0
  439. package/src/widgets-v2/formula/suffix.tsx +25 -0
  440. package/src/widgets-v2/formula/types.ts +44 -0
  441. package/src/widgets-v2/formula/value.tsx +31 -0
  442. package/src/widgets-v2/histogram/download.test.ts +94 -0
  443. package/src/widgets-v2/histogram/download.ts +60 -0
  444. package/src/widgets-v2/histogram/index.ts +10 -0
  445. package/src/widgets-v2/histogram/options.test.ts +304 -0
  446. package/src/widgets-v2/histogram/options.ts +337 -0
  447. package/src/widgets-v2/histogram/skeleton.test.tsx +16 -0
  448. package/src/widgets-v2/histogram/skeleton.tsx +70 -0
  449. package/src/widgets-v2/histogram/transforms.test.ts +46 -0
  450. package/src/widgets-v2/histogram/transforms.ts +30 -0
  451. package/src/widgets-v2/histogram/types.ts +51 -0
  452. package/src/widgets-v2/index.ts +201 -0
  453. package/src/widgets-v2/markdown/download.test.ts +66 -0
  454. package/src/widgets-v2/markdown/download.ts +53 -0
  455. package/src/widgets-v2/markdown/index.ts +6 -0
  456. package/src/widgets-v2/markdown/markdown-content.test.tsx +155 -0
  457. package/src/widgets-v2/markdown/markdown-content.tsx +72 -0
  458. package/src/widgets-v2/markdown/markdown-ui.test.tsx +75 -0
  459. package/src/widgets-v2/markdown/markdown-ui.tsx +55 -0
  460. package/src/widgets-v2/markdown/markdown.test.tsx +39 -0
  461. package/src/widgets-v2/markdown/markdown.tsx +17 -0
  462. package/src/widgets-v2/markdown/skeleton.test.tsx +15 -0
  463. package/src/widgets-v2/markdown/skeleton.tsx +32 -0
  464. package/src/widgets-v2/markdown/style.ts +53 -0
  465. package/src/widgets-v2/markdown/types.ts +4 -0
  466. package/src/widgets-v2/note/labels.ts +9 -0
  467. package/src/widgets-v2/note/style.ts +26 -0
  468. package/src/widgets-v2/note/widget-note.test.tsx +158 -0
  469. package/src/widgets-v2/note/widget-note.tsx +172 -0
  470. package/src/widgets-v2/pie/download.test.ts +78 -0
  471. package/src/widgets-v2/pie/download.ts +55 -0
  472. package/src/widgets-v2/pie/index.ts +10 -0
  473. package/src/widgets-v2/pie/options.test.ts +585 -0
  474. package/src/widgets-v2/pie/options.ts +509 -0
  475. package/src/widgets-v2/pie/skeleton.test.tsx +17 -0
  476. package/src/widgets-v2/pie/skeleton.tsx +32 -0
  477. package/src/widgets-v2/pie/types.ts +55 -0
  478. package/src/widgets-v2/provider/widget-provider.test.tsx +119 -0
  479. package/src/widgets-v2/provider/widget-provider.tsx +111 -0
  480. package/src/widgets-v2/range/index.ts +4 -0
  481. package/src/widgets-v2/range/range-ui.test.tsx +130 -0
  482. package/src/widgets-v2/range/range-ui.tsx +211 -0
  483. package/src/widgets-v2/range/range.test.tsx +68 -0
  484. package/src/widgets-v2/range/range.tsx +46 -0
  485. package/src/widgets-v2/range/skeleton.test.tsx +17 -0
  486. package/src/widgets-v2/range/skeleton.tsx +47 -0
  487. package/src/widgets-v2/range/style.ts +41 -0
  488. package/src/widgets-v2/range/types.ts +37 -0
  489. package/src/widgets-v2/scatterplot/download.test.ts +71 -0
  490. package/src/widgets-v2/scatterplot/download.ts +54 -0
  491. package/src/widgets-v2/scatterplot/index.ts +11 -0
  492. package/src/widgets-v2/scatterplot/options.test.ts +399 -0
  493. package/src/widgets-v2/scatterplot/options.ts +421 -0
  494. package/src/widgets-v2/scatterplot/skeleton.test.tsx +17 -0
  495. package/src/widgets-v2/scatterplot/skeleton.tsx +84 -0
  496. package/src/widgets-v2/scatterplot/transforms.test.ts +97 -0
  497. package/src/widgets-v2/scatterplot/transforms.ts +38 -0
  498. package/src/widgets-v2/scatterplot/types.ts +55 -0
  499. package/src/widgets-v2/selection-summary/labels.ts +11 -0
  500. package/src/widgets-v2/selection-summary/selection-summary.test.tsx +53 -0
  501. package/src/widgets-v2/selection-summary/selection-summary.tsx +62 -0
  502. package/src/widgets-v2/selection-summary/style.ts +23 -0
  503. package/src/widgets-v2/spread/download.test.ts +64 -0
  504. package/src/widgets-v2/spread/download.ts +59 -0
  505. package/src/widgets-v2/spread/index.ts +6 -0
  506. package/src/widgets-v2/spread/separator.tsx +11 -0
  507. package/src/widgets-v2/spread/skeleton.test.tsx +17 -0
  508. package/src/widgets-v2/spread/skeleton.tsx +38 -0
  509. package/src/widgets-v2/spread/spread-ui.test.tsx +108 -0
  510. package/src/widgets-v2/spread/spread-ui.tsx +52 -0
  511. package/src/widgets-v2/spread/spread.test.tsx +50 -0
  512. package/src/widgets-v2/spread/spread.tsx +31 -0
  513. package/src/widgets-v2/spread/types.ts +27 -0
  514. package/src/widgets-v2/state/labels.test.ts +33 -0
  515. package/src/widgets-v2/state/labels.ts +20 -0
  516. package/src/widgets-v2/state/style.ts +25 -0
  517. package/src/widgets-v2/state/widget-state.test.tsx +294 -0
  518. package/src/widgets-v2/state/widget-state.tsx +184 -0
  519. package/src/widgets-v2/stores/index.ts +49 -0
  520. package/src/widgets-v2/stores/pipeline-middleware.test.ts +187 -0
  521. package/src/widgets-v2/stores/pipeline-middleware.ts +91 -0
  522. package/src/widgets-v2/stores/transforms.test.ts +162 -0
  523. package/src/widgets-v2/stores/transforms.ts +70 -0
  524. package/src/widgets-v2/stores/types.ts +64 -0
  525. package/src/widgets-v2/stores/use-echart-instance.test.tsx +91 -0
  526. package/src/widgets-v2/stores/use-echart-instance.ts +29 -0
  527. package/src/widgets-v2/stores/use-transform-enabled.test.tsx +127 -0
  528. package/src/widgets-v2/stores/use-transform-enabled.ts +25 -0
  529. package/src/widgets-v2/stores/use-transform.test.tsx +262 -0
  530. package/src/widgets-v2/stores/use-transform.ts +158 -0
  531. package/src/widgets-v2/stores/widget-context.test.tsx +58 -0
  532. package/src/widgets-v2/stores/widget-context.ts +15 -0
  533. package/src/widgets-v2/stores/widget-store-registry.test.ts +292 -0
  534. package/src/widgets-v2/stores/widget-store-registry.ts +248 -0
  535. package/src/widgets-v2/subheader/style.ts +12 -0
  536. package/src/widgets-v2/subheader/subheader.test.tsx +30 -0
  537. package/src/widgets-v2/subheader/subheader.tsx +16 -0
  538. package/src/widgets-v2/table/download.test.ts +75 -0
  539. package/src/widgets-v2/table/download.ts +47 -0
  540. package/src/widgets-v2/table/helpers.test.ts +214 -0
  541. package/src/widgets-v2/table/helpers.ts +136 -0
  542. package/src/widgets-v2/table/index.ts +23 -0
  543. package/src/widgets-v2/table/labels.tsx +41 -0
  544. package/src/widgets-v2/table/skeleton.test.tsx +26 -0
  545. package/src/widgets-v2/table/skeleton.tsx +65 -0
  546. package/src/widgets-v2/table/style.ts +46 -0
  547. package/src/widgets-v2/table/table-ui.test.tsx +200 -0
  548. package/src/widgets-v2/table/table-ui.tsx +331 -0
  549. package/src/widgets-v2/table/table.test.tsx +119 -0
  550. package/src/widgets-v2/table/table.tsx +174 -0
  551. package/src/widgets-v2/table/types.ts +44 -0
  552. package/src/widgets-v2/test-utils.ts +107 -0
  553. package/src/widgets-v2/timeseries/download.test.ts +95 -0
  554. package/src/widgets-v2/timeseries/download.ts +86 -0
  555. package/src/widgets-v2/timeseries/index.ts +10 -0
  556. package/src/widgets-v2/timeseries/options.test.ts +379 -0
  557. package/src/widgets-v2/timeseries/options.ts +341 -0
  558. package/src/widgets-v2/timeseries/skeleton.test.tsx +13 -0
  559. package/src/widgets-v2/timeseries/skeleton.tsx +76 -0
  560. package/src/widgets-v2/timeseries/types.ts +61 -0
  561. package/src/widgets-v2/toolbox/labels.ts +9 -0
  562. package/src/widgets-v2/toolbox/style.ts +33 -0
  563. package/src/widgets-v2/toolbox/toolbox.test.tsx +200 -0
  564. package/src/widgets-v2/toolbox/toolbox.tsx +309 -0
  565. package/src/widgets-v2/utils/data-zoom-layout.ts +26 -0
  566. package/src/widgets-v2/utils/index.ts +2 -0
  567. package/src/widgets-v2/utils/merge-options.test.ts +52 -0
  568. package/src/widgets-v2/utils/merge-options.ts +50 -0
  569. package/src/widgets-v2/wrapper/index.ts +14 -0
  570. package/src/widgets-v2/wrapper/labels.ts +11 -0
  571. package/src/widgets-v2/wrapper/style.ts +134 -0
  572. package/src/widgets-v2/wrapper/widget-actions.test.tsx +52 -0
  573. package/src/widgets-v2/wrapper/widget-actions.tsx +43 -0
  574. package/src/widgets-v2/wrapper/widget-content.test.tsx +27 -0
  575. package/src/widgets-v2/wrapper/widget-content.tsx +29 -0
  576. package/src/widgets-v2/wrapper/widget-wrapper.test.tsx +159 -0
  577. package/src/widgets-v2/wrapper/widget-wrapper.tsx +178 -0
  578. package/dist/styles-BYTyKQFP.js.map +0 -1
@@ -0,0 +1,187 @@
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
2
+ import { fireEvent, render, screen } from '@testing-library/react'
3
+ import { Provider } from '../../provider/widget-provider'
4
+ import { clearAllWidgetStores, getWidgetStore } from '../../stores'
5
+ import { LockSelection } from './lock-selection'
6
+ import { filterByLockedItems } from './transforms'
7
+
8
+ beforeEach(() => clearAllWidgetStores())
9
+ afterEach(() => clearAllWidgetStores())
10
+
11
+ const DATA = [
12
+ [
13
+ { name: 'A', value: 10 },
14
+ { name: 'B', value: 20 },
15
+ { name: 'C', value: 30 },
16
+ ],
17
+ ]
18
+
19
+ describe('<LockSelection>', () => {
20
+ it('disables the trigger when nothing is selected and nothing is locked', () => {
21
+ render(
22
+ <Provider id='ls1' data={DATA}>
23
+ <LockSelection
24
+ selection={[]}
25
+ lockedItems={[]}
26
+ onLockChange={() => undefined}
27
+ labels={{ disabled: 'Pick rows' }}
28
+ />
29
+ </Provider>,
30
+ )
31
+ const btn = screen.getByRole('button', { name: 'Pick rows' })
32
+ expect(btn.getAttribute('disabled')).not.toBeNull()
33
+ })
34
+
35
+ it('shows the lock label when selection is non-empty and not locked', () => {
36
+ render(
37
+ <Provider id='ls2' data={DATA}>
38
+ <LockSelection
39
+ selection={['A']}
40
+ lockedItems={[]}
41
+ onLockChange={() => undefined}
42
+ labels={{ lock: 'Lock these' }}
43
+ />
44
+ </Provider>,
45
+ )
46
+ const btn = screen.getByRole('button', { name: 'Lock these' })
47
+ expect(btn.getAttribute('aria-pressed')).toBe('false')
48
+ expect(btn.getAttribute('disabled')).toBeNull()
49
+ })
50
+
51
+ it('shows the unlock label when locked and aria-pressed=true', () => {
52
+ render(
53
+ <Provider id='ls3' data={DATA}>
54
+ <LockSelection
55
+ selection={['A']}
56
+ lockedItems={['A']}
57
+ onLockChange={() => undefined}
58
+ labels={{ unlock: 'Release' }}
59
+ />
60
+ </Provider>,
61
+ )
62
+ const btn = screen.getByRole('button', { name: 'Release' })
63
+ expect(btn.getAttribute('aria-pressed')).toBe('true')
64
+ })
65
+
66
+ it('snapshots selection on lock — onLockChange called with current selection', () => {
67
+ const onLockChange = vi.fn()
68
+ render(
69
+ <Provider id='ls4' data={DATA}>
70
+ <LockSelection
71
+ selection={['A', 'B']}
72
+ lockedItems={[]}
73
+ onLockChange={onLockChange}
74
+ labels={{ lock: 'Lock' }}
75
+ />
76
+ </Provider>,
77
+ )
78
+ fireEvent.click(screen.getByRole('button', { name: 'Lock' }))
79
+ expect(onLockChange).toHaveBeenCalledTimes(1)
80
+ expect(onLockChange).toHaveBeenCalledWith(['A', 'B'])
81
+ })
82
+
83
+ it('clears the lock — onLockChange called with empty array', () => {
84
+ const onLockChange = vi.fn()
85
+ render(
86
+ <Provider id='ls5' data={DATA}>
87
+ <LockSelection
88
+ selection={['A']}
89
+ lockedItems={['A', 'B']}
90
+ onLockChange={onLockChange}
91
+ labels={{ unlock: 'Unlock' }}
92
+ />
93
+ </Provider>,
94
+ )
95
+ fireEvent.click(screen.getByRole('button', { name: 'Unlock' }))
96
+ expect(onLockChange).toHaveBeenCalledWith([])
97
+ })
98
+
99
+ it('registers a data transform that filters when locked, restores when unlocked', () => {
100
+ const { rerender } = render(
101
+ <Provider id='ls6' data={DATA}>
102
+ <LockSelection
103
+ selection={['A']}
104
+ lockedItems={['A']}
105
+ onLockChange={() => undefined}
106
+ />
107
+ </Provider>,
108
+ )
109
+ const locked = getWidgetStore('ls6').getState().data as unknown[][]
110
+ expect(locked).toEqual([[{ name: 'A', value: 10 }]])
111
+
112
+ rerender(
113
+ <Provider id='ls6' data={DATA}>
114
+ <LockSelection
115
+ selection={['A']}
116
+ lockedItems={[]}
117
+ onLockChange={() => undefined}
118
+ />
119
+ </Provider>,
120
+ )
121
+ const unlocked = getWidgetStore('ls6').getState().data as unknown[][]
122
+ // With no lockedItems and the transform disabled, the pipeline returns
123
+ // raw data. All three rows should be present.
124
+ expect(unlocked.flat().length).toBe(3)
125
+ })
126
+
127
+ it('lets the destination feed a different lockedItems set later', () => {
128
+ const { rerender } = render(
129
+ <Provider id='ls7' data={DATA}>
130
+ <LockSelection
131
+ selection={['A']}
132
+ lockedItems={['A']}
133
+ onLockChange={() => undefined}
134
+ />
135
+ </Provider>,
136
+ )
137
+ expect(
138
+ (getWidgetStore('ls7').getState().data as unknown[][]).flat(),
139
+ ).toEqual([{ name: 'A', value: 10 }])
140
+
141
+ rerender(
142
+ <Provider id='ls7' data={DATA}>
143
+ <LockSelection
144
+ selection={['A', 'B', 'C']}
145
+ lockedItems={['B', 'C']}
146
+ onLockChange={() => undefined}
147
+ />
148
+ </Provider>,
149
+ )
150
+ expect(
151
+ (getWidgetStore('ls7').getState().data as unknown[][]).flat(),
152
+ ).toEqual([
153
+ { name: 'B', value: 20 },
154
+ { name: 'C', value: 30 },
155
+ ])
156
+ })
157
+ })
158
+
159
+ describe('filterByLockedItems', () => {
160
+ it('returns input unchanged when locked set is empty', () => {
161
+ expect(filterByLockedItems(DATA, [])).toBe(DATA)
162
+ })
163
+
164
+ it('keeps only items whose name is in the locked set, preserving series shape', () => {
165
+ const out = filterByLockedItems(DATA, ['A', 'C']) as unknown[][]
166
+ expect(out).toEqual([
167
+ [
168
+ { name: 'A', value: 10 },
169
+ { name: 'C', value: 30 },
170
+ ],
171
+ ])
172
+ })
173
+
174
+ it('handles numeric names', () => {
175
+ const data = [
176
+ [
177
+ { name: 1, value: 10 },
178
+ { name: 2, value: 20 },
179
+ ],
180
+ ]
181
+ expect(filterByLockedItems(data, [2])).toEqual([[{ name: 2, value: 20 }]])
182
+ })
183
+
184
+ it('returns input unchanged when input is not array-shaped', () => {
185
+ expect(filterByLockedItems('nope', ['A'])).toBe('nope')
186
+ })
187
+ })
@@ -0,0 +1,130 @@
1
+ import { useCallback, useEffect, useMemo, type ComponentType } from 'react'
2
+ import { IconButton, type SvgIconProps } from '@mui/material'
3
+ import LockIcon from '@mui/icons-material/Lock'
4
+ import LockOpenIcon from '@mui/icons-material/LockOpen'
5
+ import { Tooltip } from '../../../components'
6
+ import { useTransform, useWidgetId } from '../../stores'
7
+ import type { TransformPair } from '../../stores'
8
+ import { filterByLockedItems } from './transforms'
9
+ import {
10
+ DEFAULT_LOCK_SELECTION_LABELS,
11
+ type LockSelectionLabels,
12
+ } from './labels'
13
+ import { styles } from './style'
14
+
15
+ const LOCK_SELECTION_DESCRIPTOR = {
16
+ id: 'lock-selection',
17
+ type: 'data' as const,
18
+ order: 30,
19
+ }
20
+
21
+ export type LockSelectionKey = string | number
22
+
23
+ export interface LockSelectionProps {
24
+ /**
25
+ * Currently-selected items (destination-owned). On lock, this set is
26
+ * snapshotted into `lockedItems` via `onLockChange`.
27
+ */
28
+ selection: readonly LockSelectionKey[]
29
+ /**
30
+ * Currently-locked items (destination-owned). When non-empty, the widget's
31
+ * data is filtered to these items via the registered transform.
32
+ */
33
+ lockedItems: readonly LockSelectionKey[]
34
+ /**
35
+ * Fires when the user toggles the lock. The destination is responsible for
36
+ * persisting the new locked set (and re-feeding it via `lockedItems`).
37
+ */
38
+ onLockChange: (next: readonly LockSelectionKey[]) => void
39
+ labels?: Partial<LockSelectionLabels>
40
+ /** Lock icon (default: `LockIcon`). */
41
+ lockIcon?: ComponentType<SvgIconProps>
42
+ /** Unlock icon (default: `LockOpenIcon`). */
43
+ unlockIcon?: ComponentType<SvgIconProps>
44
+ iconProps?: SvgIconProps
45
+ }
46
+
47
+ /**
48
+ * Action that pins the current selection so the widget's data filters down
49
+ * to those items even as the user changes selections. Selection and lock
50
+ * state are destination-owned; this component is a controlled UI + a data
51
+ * transform registered against the widget's pipeline.
52
+ *
53
+ * The trigger is disabled when there is nothing to lock and nothing locked.
54
+ */
55
+ export function LockSelection({
56
+ selection,
57
+ lockedItems,
58
+ onLockChange,
59
+ labels,
60
+ lockIcon: LockSvg = LockIcon,
61
+ unlockIcon: UnlockSvg = LockOpenIcon,
62
+ iconProps,
63
+ }: LockSelectionProps) {
64
+ const id = useWidgetId()
65
+ const _labels = { ...DEFAULT_LOCK_SELECTION_LABELS, ...labels }
66
+ const isLocked = lockedItems.length > 0
67
+ const canToggle = isLocked || selection.length > 0
68
+
69
+ // Pair memoized on lockedItems identity — useTransform re-registers the fn
70
+ // (which closes over the current locked set) whenever the destination feeds
71
+ // a new array. setEnabled drives the middleware-level `enabled` flag.
72
+ const pairs = useMemoPair(lockedItems)
73
+ const { enabled, setEnabled } = useTransform(id, pairs, {
74
+ initialEnabled: isLocked,
75
+ })
76
+
77
+ // Keep middleware `enabled` in sync with destination-owned `isLocked`. The
78
+ // pipeline only short-circuits the transform when enabled === false, so
79
+ // toggling here is what makes lock/unlock actually take effect.
80
+ useEffect(() => {
81
+ if (enabled !== isLocked) setEnabled(isLocked)
82
+ }, [enabled, isLocked, setEnabled])
83
+
84
+ const handleToggle = useCallback(() => {
85
+ if (isLocked) {
86
+ onLockChange([])
87
+ } else {
88
+ onLockChange([...selection])
89
+ }
90
+ }, [isLocked, onLockChange, selection])
91
+
92
+ const tooltip = !canToggle
93
+ ? _labels.disabled
94
+ : isLocked
95
+ ? _labels.unlock
96
+ : _labels.lock
97
+ const Icon = isLocked ? UnlockSvg : LockSvg
98
+
99
+ return (
100
+ <Tooltip title={tooltip}>
101
+ <span>
102
+ <IconButton
103
+ size='small'
104
+ aria-label={tooltip}
105
+ aria-pressed={isLocked}
106
+ disabled={!canToggle}
107
+ onClick={handleToggle}
108
+ sx={{ ...styles.toggle, ...(isLocked && styles.toggleActive) }}
109
+ >
110
+ <Icon fontSize='small' {...iconProps} />
111
+ </IconButton>
112
+ </span>
113
+ </Tooltip>
114
+ )
115
+ }
116
+
117
+ /**
118
+ * Builds a stable `[{ descriptor, fn }]` pair where `fn` closes over the
119
+ * latest `lockedItems`. Re-memoized whenever the array identity changes so
120
+ * `useTransform` re-registers the closure with the freshest data.
121
+ */
122
+ function useMemoPair(
123
+ lockedItems: readonly LockSelectionKey[],
124
+ ): readonly TransformPair[] {
125
+ const fn = useCallback(
126
+ (data: unknown) => filterByLockedItems(data, lockedItems),
127
+ [lockedItems],
128
+ )
129
+ return useMemo(() => [{ descriptor: LOCK_SELECTION_DESCRIPTOR, fn }], [fn])
130
+ }
@@ -0,0 +1,11 @@
1
+ import type { SxProps, Theme } from '@mui/material'
2
+
3
+ export const styles = {
4
+ toggle: {
5
+ p: 0.5,
6
+ '& .MuiSvgIcon-root': { fontSize: 20 },
7
+ },
8
+ toggleActive: {
9
+ background: (theme: Theme) => theme.palette.primary.relatedLight,
10
+ },
11
+ } satisfies Record<string, SxProps<Theme>>
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Filters a 2D series of `{name, ...}` records, keeping only items whose
3
+ * `name` is in the locked set. Multi-series shape is preserved (one inner
4
+ * array per series). Used by the LockSelection action's data transform.
5
+ */
6
+ export function filterByLockedItems(
7
+ input: unknown,
8
+ lockedItems: readonly (string | number)[],
9
+ ): unknown {
10
+ if (lockedItems.length === 0) return input
11
+ if (!Array.isArray(input)) return input
12
+ const set = new Set<string | number>(lockedItems)
13
+ return input.map((series: unknown): unknown => {
14
+ if (!Array.isArray(series)) return series
15
+ return series.filter((item: unknown) => {
16
+ if (item == null) return false
17
+ if (typeof item === 'object' && 'name' in item) {
18
+ const name = (item as { name: unknown }).name
19
+ if (typeof name === 'string' || typeof name === 'number') {
20
+ return set.has(name)
21
+ }
22
+ return false
23
+ }
24
+ return false
25
+ })
26
+ })
27
+ }
@@ -0,0 +1,3 @@
1
+ export { RelativeData, type RelativeDataProps } from './relative-data'
2
+ export { toRelativeData, createPercentFormatter } from './transforms'
3
+ export { DEFAULT_RELATIVE_DATA_LABELS, type RelativeDataLabels } from './labels'
@@ -0,0 +1,9 @@
1
+ export interface RelativeDataLabels {
2
+ on: string
3
+ off: string
4
+ }
5
+
6
+ export const DEFAULT_RELATIVE_DATA_LABELS: RelativeDataLabels = {
7
+ on: 'Show absolute values',
8
+ off: 'Show relative values',
9
+ }
@@ -0,0 +1,71 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest'
2
+ import { render } from '@testing-library/react'
3
+ import { Provider } from '../../provider/widget-provider'
4
+ import { clearAllWidgetStores, getWidgetStore } from '../../stores'
5
+ import { RelativeData } from './relative-data'
6
+
7
+ beforeEach(() => clearAllWidgetStores())
8
+ afterEach(() => clearAllWidgetStores())
9
+
10
+ const fmtA = (n: number) => `A${n}`
11
+ const fmtB = (n: number) => `B${n}`
12
+
13
+ describe('<RelativeData> — rawFormatter-driven restoration', () => {
14
+ it('Provider mirrors the formatter prop into both rawFormatter and formatter', () => {
15
+ render(
16
+ <Provider id='rd1' data={[]} formatter={fmtA}>
17
+ <RelativeData initialEnabled={false} />
18
+ </Provider>,
19
+ )
20
+ const s = getWidgetStore('rd1').getState()
21
+ expect(s.rawFormatter).toBe(fmtA)
22
+ expect(s.formatter).toBe(fmtA)
23
+ })
24
+
25
+ it('initialEnabled=true installs the percent formatter and leaves rawFormatter untouched', () => {
26
+ render(
27
+ <Provider id='rd2' data={[]} formatter={fmtA}>
28
+ <RelativeData initialEnabled={true} />
29
+ </Provider>,
30
+ )
31
+ const s = getWidgetStore('rd2').getState()
32
+ expect(s.rawFormatter).toBe(fmtA)
33
+ expect(typeof s.formatter).toBe('function')
34
+ expect(s.formatter).not.toBe(fmtA)
35
+ // Sanity: the override is the percent formatter (50 → "50%" via Intl).
36
+ expect(s.formatter?.(50)).toMatch(/%$/)
37
+ })
38
+
39
+ it('consumer prop change while enabled updates rawFormatter; effect re-applies percent', () => {
40
+ const { rerender } = render(
41
+ <Provider id='rd3' data={[]} formatter={fmtA}>
42
+ <RelativeData initialEnabled={true} />
43
+ </Provider>,
44
+ )
45
+ const store = getWidgetStore('rd3')
46
+ expect(store.getState().rawFormatter).toBe(fmtA)
47
+ const beforePercent = store.getState().formatter
48
+
49
+ rerender(
50
+ <Provider id='rd3' data={[]} formatter={fmtB}>
51
+ <RelativeData initialEnabled={true} />
52
+ </Provider>,
53
+ )
54
+ const after = store.getState()
55
+ expect(after.rawFormatter).toBe(fmtB)
56
+ // Formatter is still the percent formatter (re-applied via the effect).
57
+ expect(after.formatter).not.toBe(fmtB)
58
+ expect(after.formatter).toBe(beforePercent)
59
+ })
60
+
61
+ it('initialEnabled=false leaves formatter equal to rawFormatter', () => {
62
+ render(
63
+ <Provider id='rd4' data={[]} formatter={fmtA}>
64
+ <RelativeData initialEnabled={false} />
65
+ </Provider>,
66
+ )
67
+ const s = getWidgetStore('rd4').getState()
68
+ expect(s.formatter).toBe(s.rawFormatter)
69
+ expect(s.formatter).toBe(fmtA)
70
+ })
71
+ })
@@ -0,0 +1,107 @@
1
+ import { useEffect, useMemo, type ComponentType } from 'react'
2
+ import { IconButton, type SvgIconProps } from '@mui/material'
3
+ import PercentIcon from '@mui/icons-material/Percent'
4
+ import { Tooltip } from '../../../components'
5
+ import {
6
+ getWidgetStore,
7
+ useSingleTransform,
8
+ useWidget,
9
+ useWidgetId,
10
+ } from '../../stores'
11
+ import { createPercentFormatter, toRelativeData } from './transforms'
12
+ import { DEFAULT_RELATIVE_DATA_LABELS, type RelativeDataLabels } from './labels'
13
+ import { styles } from './style'
14
+
15
+ const DATA_DESCRIPTOR = {
16
+ id: 'relative-data',
17
+ type: 'data' as const,
18
+ order: 15,
19
+ }
20
+
21
+ export interface RelativeDataProps {
22
+ initialEnabled?: boolean
23
+ /**
24
+ * BCP-47 locale tag forwarded to `Intl.NumberFormat`. Defaults to the
25
+ * runtime locale.
26
+ */
27
+ locale?: string
28
+ labels?: Partial<RelativeDataLabels>
29
+ icon?: ComponentType<SvgIconProps>
30
+ iconProps?: SvgIconProps
31
+ /**
32
+ * Data-side transform that rewrites the widget's series into their
33
+ * relative (0–100) form. Defaults to {@link toRelativeData}, which
34
+ * handles the canonical `{ name, value }[]` shape (bar / pie /
35
+ * timeseries / category). Widgets with a different data shape pass
36
+ * their own — `toRelativeHistogramData` for histogram's `number[]`,
37
+ * `toRelativeScatterplotData` for scatter's `[x, y][]`.
38
+ *
39
+ * Should be a stable top-level reference; inline `(data) => ...`
40
+ * literals re-register the transform every render.
41
+ */
42
+ transform?: (data: unknown) => unknown
43
+ }
44
+
45
+ /**
46
+ * Toggle between absolute and relative (percentage) values.
47
+ *
48
+ * - **Data side**: a single data transform ({@link toRelativeData}) registered
49
+ * through `useSingleTransform`. When disabled, the pipeline skips it and the
50
+ * derived `data` reverts to `rawData` automatically.
51
+ * - **Formatter side**: an effect writes directly to `state.formatter`. When
52
+ * enabled it installs the Intl-based percent formatter; when disabled it
53
+ * reads `state.rawFormatter` (the consumer-supplied original, always live)
54
+ * and writes it back to `formatter`. No "original" snapshot is captured —
55
+ * `rawFormatter` is the original.
56
+ */
57
+ export function RelativeData({
58
+ initialEnabled = false,
59
+ locale,
60
+ labels,
61
+ icon: Icon = PercentIcon,
62
+ iconProps,
63
+ transform,
64
+ }: RelativeDataProps) {
65
+ const id = useWidgetId()
66
+ const _labels = { ...DEFAULT_RELATIVE_DATA_LABELS, ...labels }
67
+
68
+ const { enabled, toggle } = useSingleTransform(
69
+ id,
70
+ DATA_DESCRIPTOR,
71
+ transform ?? toRelativeData,
72
+ { initialEnabled },
73
+ )
74
+
75
+ const percentFormatter = useMemo(
76
+ () => createPercentFormatter(locale),
77
+ [locale],
78
+ )
79
+
80
+ // Subscribe to rawFormatter so the effect re-runs and re-applies after the
81
+ // consumer's formatter prop changes (Provider syncs the new prop to both
82
+ // rawFormatter and formatter — re-applying restores the percent override
83
+ // when relative is on, and tracks the new rawFormatter when off).
84
+ const rawFormatter = useWidget(id, (s) => s.rawFormatter)
85
+
86
+ useEffect(() => {
87
+ getWidgetStore(id).setState({
88
+ formatter: enabled ? percentFormatter : rawFormatter,
89
+ })
90
+ }, [id, enabled, percentFormatter, rawFormatter])
91
+
92
+ const tooltip = enabled ? _labels.on : _labels.off
93
+
94
+ return (
95
+ <Tooltip title={tooltip}>
96
+ <IconButton
97
+ size='small'
98
+ aria-label={tooltip}
99
+ aria-pressed={enabled}
100
+ onClick={toggle}
101
+ sx={{ ...styles.toggle, ...(enabled && styles.toggleActive) }}
102
+ >
103
+ <Icon fontSize='small' {...iconProps} />
104
+ </IconButton>
105
+ </Tooltip>
106
+ )
107
+ }
@@ -0,0 +1,11 @@
1
+ import type { SxProps, Theme } from '@mui/material'
2
+
3
+ export const styles = {
4
+ toggle: {
5
+ p: 0.5,
6
+ '& .MuiSvgIcon-root': { fontSize: 20 },
7
+ },
8
+ toggleActive: {
9
+ background: (theme: Theme) => theme.palette.primary.relatedLight,
10
+ },
11
+ } satisfies Record<string, SxProps<Theme>>