@sqlrooms/mosaic 0.29.0-rc.2 → 0.29.0-rc.3

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 (312) hide show
  1. package/README.md +120 -0
  2. package/dist/MosaicChartBuilder.d.ts +48 -13
  3. package/dist/MosaicChartBuilder.d.ts.map +1 -1
  4. package/dist/MosaicChartBuilder.js +28 -30
  5. package/dist/MosaicChartBuilder.js.map +1 -1
  6. package/dist/MosaicSlice.d.ts +11 -0
  7. package/dist/MosaicSlice.d.ts.map +1 -1
  8. package/dist/MosaicSlice.js +73 -10
  9. package/dist/MosaicSlice.js.map +1 -1
  10. package/dist/ResponsivePlot.d.ts +23 -0
  11. package/dist/ResponsivePlot.d.ts.map +1 -0
  12. package/dist/ResponsivePlot.js +43 -0
  13. package/dist/ResponsivePlot.js.map +1 -0
  14. package/dist/VgPlotChart.d.ts +18 -2
  15. package/dist/VgPlotChart.d.ts.map +1 -1
  16. package/dist/VgPlotChart.js +112 -26
  17. package/dist/VgPlotChart.js.map +1 -1
  18. package/dist/chart-builders/ChartBuilderActions.d.ts +6 -0
  19. package/dist/chart-builders/ChartBuilderActions.d.ts.map +1 -0
  20. package/dist/chart-builders/ChartBuilderActions.js +28 -0
  21. package/dist/chart-builders/ChartBuilderActions.js.map +1 -0
  22. package/dist/chart-builders/ChartBuilderContent.d.ts +13 -11
  23. package/dist/chart-builders/ChartBuilderContent.d.ts.map +1 -1
  24. package/dist/chart-builders/ChartBuilderContent.js +21 -52
  25. package/dist/chart-builders/ChartBuilderContent.js.map +1 -1
  26. package/dist/chart-builders/ChartBuilderContext.d.ts +9 -4
  27. package/dist/chart-builders/ChartBuilderContext.d.ts.map +1 -1
  28. package/dist/chart-builders/ChartBuilderContext.js +5 -0
  29. package/dist/chart-builders/ChartBuilderContext.js.map +1 -1
  30. package/dist/chart-builders/ChartBuilderDialog.d.ts +31 -6
  31. package/dist/chart-builders/ChartBuilderDialog.d.ts.map +1 -1
  32. package/dist/chart-builders/ChartBuilderDialog.js +25 -10
  33. package/dist/chart-builders/ChartBuilderDialog.js.map +1 -1
  34. package/dist/chart-builders/ChartBuilderFields.d.ts +6 -0
  35. package/dist/chart-builders/ChartBuilderFields.d.ts.map +1 -0
  36. package/dist/chart-builders/ChartBuilderFields.js +25 -0
  37. package/dist/chart-builders/ChartBuilderFields.js.map +1 -0
  38. package/dist/chart-builders/ChartBuilderRoot.d.ts +27 -0
  39. package/dist/chart-builders/ChartBuilderRoot.d.ts.map +1 -0
  40. package/dist/chart-builders/ChartBuilderRoot.js +61 -0
  41. package/dist/chart-builders/ChartBuilderRoot.js.map +1 -0
  42. package/dist/chart-builders/ChartBuilderTypeGrid.d.ts +7 -0
  43. package/dist/chart-builders/ChartBuilderTypeGrid.d.ts.map +1 -0
  44. package/dist/chart-builders/ChartBuilderTypeGrid.js +23 -0
  45. package/dist/chart-builders/ChartBuilderTypeGrid.js.map +1 -0
  46. package/dist/chart-builders/FieldSelectorInput.d.ts.map +1 -1
  47. package/dist/chart-builders/FieldSelectorInput.js +2 -2
  48. package/dist/chart-builders/FieldSelectorInput.js.map +1 -1
  49. package/dist/chart-builders/builders.d.ts +28 -1
  50. package/dist/chart-builders/builders.d.ts.map +1 -1
  51. package/dist/chart-builders/builders.js +44 -273
  52. package/dist/chart-builders/builders.js.map +1 -1
  53. package/dist/chart-builders/chartSpecTitle.d.ts +3 -4
  54. package/dist/chart-builders/chartSpecTitle.d.ts.map +1 -1
  55. package/dist/chart-builders/chartSpecTitle.js +3 -5
  56. package/dist/chart-builders/chartSpecTitle.js.map +1 -1
  57. package/dist/chart-builders/chartTypeUtils.d.ts +17 -0
  58. package/dist/chart-builders/chartTypeUtils.d.ts.map +1 -0
  59. package/dist/chart-builders/chartTypeUtils.js +55 -0
  60. package/dist/chart-builders/chartTypeUtils.js.map +1 -0
  61. package/dist/chart-builders/constants.d.ts +7 -0
  62. package/dist/chart-builders/constants.d.ts.map +1 -0
  63. package/dist/chart-builders/constants.js +34 -0
  64. package/dist/chart-builders/constants.js.map +1 -0
  65. package/dist/chart-builders/createChartBuilderStore.d.ts +11 -0
  66. package/dist/chart-builders/createChartBuilderStore.d.ts.map +1 -0
  67. package/dist/chart-builders/createChartBuilderStore.js +26 -0
  68. package/dist/chart-builders/createChartBuilderStore.js.map +1 -0
  69. package/dist/chart-builders/describeChartSpecs.d.ts +5 -3
  70. package/dist/chart-builders/describeChartSpecs.d.ts.map +1 -1
  71. package/dist/chart-builders/describeChartSpecs.js +11 -8
  72. package/dist/chart-builders/describeChartSpecs.js.map +1 -1
  73. package/dist/chart-builders/hooks/useChartFieldForm.d.ts +13 -0
  74. package/dist/chart-builders/hooks/useChartFieldForm.d.ts.map +1 -0
  75. package/dist/chart-builders/hooks/useChartFieldForm.js +12 -0
  76. package/dist/chart-builders/hooks/useChartFieldForm.js.map +1 -0
  77. package/dist/chart-builders/types.d.ts +12 -29
  78. package/dist/chart-builders/types.d.ts.map +1 -1
  79. package/dist/chart-builders/types.js +16 -1
  80. package/dist/chart-builders/types.js.map +1 -1
  81. package/dist/chart-types/base-types.d.ts +54 -0
  82. package/dist/chart-types/base-types.d.ts.map +1 -0
  83. package/dist/chart-types/base-types.js +6 -0
  84. package/dist/chart-types/base-types.js.map +1 -0
  85. package/dist/chart-types/box-plot/definition.d.ts +4 -0
  86. package/dist/chart-types/box-plot/definition.d.ts.map +1 -0
  87. package/dist/chart-types/box-plot/definition.js +45 -0
  88. package/dist/chart-types/box-plot/definition.js.map +1 -0
  89. package/dist/chart-types/box-plot/index.d.ts +3 -0
  90. package/dist/chart-types/box-plot/index.d.ts.map +1 -0
  91. package/dist/chart-types/box-plot/index.js +3 -0
  92. package/dist/chart-types/box-plot/index.js.map +1 -0
  93. package/dist/chart-types/box-plot/schema.d.ts +17 -0
  94. package/dist/chart-types/box-plot/schema.d.ts.map +1 -0
  95. package/dist/chart-types/box-plot/schema.js +12 -0
  96. package/dist/chart-types/box-plot/schema.js.map +1 -0
  97. package/dist/chart-types/bubble-chart/definition.d.ts +4 -0
  98. package/dist/chart-types/bubble-chart/definition.d.ts.map +1 -0
  99. package/dist/chart-types/bubble-chart/definition.js +48 -0
  100. package/dist/chart-types/bubble-chart/definition.js.map +1 -0
  101. package/dist/chart-types/bubble-chart/index.d.ts +3 -0
  102. package/dist/chart-types/bubble-chart/index.d.ts.map +1 -0
  103. package/dist/chart-types/bubble-chart/index.js +3 -0
  104. package/dist/chart-types/bubble-chart/index.js.map +1 -0
  105. package/dist/chart-types/bubble-chart/schema.d.ts +17 -0
  106. package/dist/chart-types/bubble-chart/schema.d.ts.map +1 -0
  107. package/dist/chart-types/bubble-chart/schema.js +12 -0
  108. package/dist/chart-types/bubble-chart/schema.js.map +1 -0
  109. package/dist/chart-types/count-plot/definition.d.ts +4 -0
  110. package/dist/chart-types/count-plot/definition.d.ts.map +1 -0
  111. package/dist/chart-types/count-plot/definition.js +50 -0
  112. package/dist/chart-types/count-plot/definition.js.map +1 -0
  113. package/dist/chart-types/count-plot/index.d.ts +3 -0
  114. package/dist/chart-types/count-plot/index.d.ts.map +1 -0
  115. package/dist/chart-types/count-plot/index.js +3 -0
  116. package/dist/chart-types/count-plot/index.js.map +1 -0
  117. package/dist/chart-types/count-plot/schema.d.ts +15 -0
  118. package/dist/chart-types/count-plot/schema.d.ts.map +1 -0
  119. package/dist/chart-types/count-plot/schema.js +11 -0
  120. package/dist/chart-types/count-plot/schema.js.map +1 -0
  121. package/dist/chart-types/custom-spec/definition.d.ts +4 -0
  122. package/dist/chart-types/custom-spec/definition.d.ts.map +1 -0
  123. package/dist/chart-types/custom-spec/definition.js +28 -0
  124. package/dist/chart-types/custom-spec/definition.js.map +1 -0
  125. package/dist/chart-types/custom-spec/index.d.ts +3 -0
  126. package/dist/chart-types/custom-spec/index.d.ts.map +1 -0
  127. package/dist/chart-types/custom-spec/index.js +3 -0
  128. package/dist/chart-types/custom-spec/index.js.map +1 -0
  129. package/dist/chart-types/custom-spec/schema.d.ts +11 -0
  130. package/dist/chart-types/custom-spec/schema.d.ts.map +1 -0
  131. package/dist/chart-types/custom-spec/schema.js +9 -0
  132. package/dist/chart-types/custom-spec/schema.js.map +1 -0
  133. package/dist/chart-types/ecdf/definition.d.ts +4 -0
  134. package/dist/chart-types/ecdf/definition.d.ts.map +1 -0
  135. package/dist/chart-types/ecdf/definition.js +47 -0
  136. package/dist/chart-types/ecdf/definition.js.map +1 -0
  137. package/dist/chart-types/ecdf/index.d.ts +3 -0
  138. package/dist/chart-types/ecdf/index.d.ts.map +1 -0
  139. package/dist/chart-types/ecdf/index.js +3 -0
  140. package/dist/chart-types/ecdf/index.js.map +1 -0
  141. package/dist/chart-types/ecdf/schema.d.ts +15 -0
  142. package/dist/chart-types/ecdf/schema.d.ts.map +1 -0
  143. package/dist/chart-types/ecdf/schema.js +11 -0
  144. package/dist/chart-types/ecdf/schema.js.map +1 -0
  145. package/dist/chart-types/heatmap/definition.d.ts +4 -0
  146. package/dist/chart-types/heatmap/definition.d.ts.map +1 -0
  147. package/dist/chart-types/heatmap/definition.js +49 -0
  148. package/dist/chart-types/heatmap/definition.js.map +1 -0
  149. package/dist/chart-types/heatmap/index.d.ts +3 -0
  150. package/dist/chart-types/heatmap/index.d.ts.map +1 -0
  151. package/dist/chart-types/heatmap/index.js +3 -0
  152. package/dist/chart-types/heatmap/index.js.map +1 -0
  153. package/dist/chart-types/heatmap/schema.d.ts +17 -0
  154. package/dist/chart-types/heatmap/schema.d.ts.map +1 -0
  155. package/dist/chart-types/heatmap/schema.js +12 -0
  156. package/dist/chart-types/heatmap/schema.js.map +1 -0
  157. package/dist/chart-types/histogram/definition.d.ts +4 -0
  158. package/dist/chart-types/histogram/definition.d.ts.map +1 -0
  159. package/dist/chart-types/histogram/definition.js +49 -0
  160. package/dist/chart-types/histogram/definition.js.map +1 -0
  161. package/dist/chart-types/histogram/index.d.ts +3 -0
  162. package/dist/chart-types/histogram/index.d.ts.map +1 -0
  163. package/dist/chart-types/histogram/index.js +3 -0
  164. package/dist/chart-types/histogram/index.js.map +1 -0
  165. package/dist/chart-types/histogram/schema.d.ts +15 -0
  166. package/dist/chart-types/histogram/schema.d.ts.map +1 -0
  167. package/dist/chart-types/histogram/schema.js +11 -0
  168. package/dist/chart-types/histogram/schema.js.map +1 -0
  169. package/dist/chart-types/index.d.ts +109 -0
  170. package/dist/chart-types/index.d.ts.map +1 -0
  171. package/dist/chart-types/index.js +70 -0
  172. package/dist/chart-types/index.js.map +1 -0
  173. package/dist/chart-types/line-chart/definition.d.ts +4 -0
  174. package/dist/chart-types/line-chart/definition.d.ts.map +1 -0
  175. package/dist/chart-types/line-chart/definition.js +46 -0
  176. package/dist/chart-types/line-chart/definition.js.map +1 -0
  177. package/dist/chart-types/line-chart/index.d.ts +3 -0
  178. package/dist/chart-types/line-chart/index.d.ts.map +1 -0
  179. package/dist/chart-types/line-chart/index.js +3 -0
  180. package/dist/chart-types/line-chart/index.js.map +1 -0
  181. package/dist/chart-types/line-chart/schema.d.ts +17 -0
  182. package/dist/chart-types/line-chart/schema.d.ts.map +1 -0
  183. package/dist/chart-types/line-chart/schema.js +12 -0
  184. package/dist/chart-types/line-chart/schema.js.map +1 -0
  185. package/dist/chart-types/registry.d.ts +5 -0
  186. package/dist/chart-types/registry.d.ts.map +1 -0
  187. package/dist/chart-types/registry.js +28 -0
  188. package/dist/chart-types/registry.js.map +1 -0
  189. package/dist/dashboard/DashboardPanelErrorBoundary.d.ts +17 -0
  190. package/dist/dashboard/DashboardPanelErrorBoundary.d.ts.map +1 -0
  191. package/dist/dashboard/DashboardPanelErrorBoundary.js +21 -0
  192. package/dist/dashboard/DashboardPanelErrorBoundary.js.map +1 -0
  193. package/dist/dashboard/MosaicDashboard.d.ts +2 -4
  194. package/dist/dashboard/MosaicDashboard.d.ts.map +1 -1
  195. package/dist/dashboard/MosaicDashboard.js +42 -19
  196. package/dist/dashboard/MosaicDashboard.js.map +1 -1
  197. package/dist/dashboard/MosaicDashboardContext.d.ts +1 -0
  198. package/dist/dashboard/MosaicDashboardContext.d.ts.map +1 -1
  199. package/dist/dashboard/MosaicDashboardContext.js.map +1 -1
  200. package/dist/dashboard/MosaicDashboardPanel.d.ts +3 -0
  201. package/dist/dashboard/MosaicDashboardPanel.d.ts.map +1 -0
  202. package/dist/dashboard/MosaicDashboardPanel.js +26 -0
  203. package/dist/dashboard/MosaicDashboardPanel.js.map +1 -0
  204. package/dist/dashboard/MosaicDashboardPanelDragOverlay.d.ts +8 -0
  205. package/dist/dashboard/MosaicDashboardPanelDragOverlay.d.ts.map +1 -0
  206. package/dist/dashboard/MosaicDashboardPanelDragOverlay.js +17 -0
  207. package/dist/dashboard/MosaicDashboardPanelDragOverlay.js.map +1 -0
  208. package/dist/dashboard/MosaicDashboardPanelHeader.d.ts +13 -0
  209. package/dist/dashboard/MosaicDashboardPanelHeader.d.ts.map +1 -0
  210. package/dist/dashboard/MosaicDashboardPanelHeader.js +30 -0
  211. package/dist/dashboard/MosaicDashboardPanelHeader.js.map +1 -0
  212. package/dist/dashboard/MosaicDashboardPanelLayout.d.ts +10 -0
  213. package/dist/dashboard/MosaicDashboardPanelLayout.d.ts.map +1 -0
  214. package/dist/dashboard/MosaicDashboardPanelLayout.js +25 -0
  215. package/dist/dashboard/MosaicDashboardPanelLayout.js.map +1 -0
  216. package/dist/dashboard/MosaicDashboardPanels.d.ts +2 -0
  217. package/dist/dashboard/MosaicDashboardPanels.d.ts.map +1 -0
  218. package/dist/dashboard/MosaicDashboardPanels.js +52 -0
  219. package/dist/dashboard/MosaicDashboardPanels.js.map +1 -0
  220. package/dist/dashboard/MosaicDashboardProfilerPanelRenderer.d.ts +3 -0
  221. package/dist/dashboard/MosaicDashboardProfilerPanelRenderer.d.ts.map +1 -0
  222. package/dist/dashboard/MosaicDashboardProfilerPanelRenderer.js +32 -0
  223. package/dist/dashboard/MosaicDashboardProfilerPanelRenderer.js.map +1 -0
  224. package/dist/dashboard/MosaicDashboardSlice.d.ts +482 -27
  225. package/dist/dashboard/MosaicDashboardSlice.d.ts.map +1 -1
  226. package/dist/dashboard/MosaicDashboardSlice.js +478 -93
  227. package/dist/dashboard/MosaicDashboardSlice.js.map +1 -1
  228. package/dist/dashboard/MosaicDashboardToolbar.d.ts.map +1 -1
  229. package/dist/dashboard/MosaicDashboardToolbar.js +69 -7
  230. package/dist/dashboard/MosaicDashboardToolbar.js.map +1 -1
  231. package/dist/dashboard/MosaicDashboardVgPlotHeaderActions.d.ts +4 -0
  232. package/dist/dashboard/MosaicDashboardVgPlotHeaderActions.d.ts.map +1 -0
  233. package/dist/dashboard/MosaicDashboardVgPlotHeaderActions.js +29 -0
  234. package/dist/dashboard/MosaicDashboardVgPlotHeaderActions.js.map +1 -0
  235. package/dist/dashboard/MosaicDashboardVgPlotPanelRenderer.d.ts +3 -0
  236. package/dist/dashboard/MosaicDashboardVgPlotPanelRenderer.d.ts.map +1 -0
  237. package/dist/dashboard/MosaicDashboardVgPlotPanelRenderer.js +68 -0
  238. package/dist/dashboard/MosaicDashboardVgPlotPanelRenderer.js.map +1 -0
  239. package/dist/dashboard/VgPlotSpecPopoverEditor.d.ts.map +1 -1
  240. package/dist/dashboard/VgPlotSpecPopoverEditor.js +2 -2
  241. package/dist/dashboard/VgPlotSpecPopoverEditor.js.map +1 -1
  242. package/dist/dashboard/chart-settings/ChartSettings.d.ts +39 -0
  243. package/dist/dashboard/chart-settings/ChartSettings.d.ts.map +1 -0
  244. package/dist/dashboard/chart-settings/ChartSettings.js +90 -0
  245. package/dist/dashboard/chart-settings/ChartSettings.js.map +1 -0
  246. package/dist/dashboard/chart-settings/ChartSettingsContext.d.ts +20 -0
  247. package/dist/dashboard/chart-settings/ChartSettingsContext.d.ts.map +1 -0
  248. package/dist/dashboard/chart-settings/ChartSettingsContext.js +14 -0
  249. package/dist/dashboard/chart-settings/ChartSettingsContext.js.map +1 -0
  250. package/dist/dashboard/chart-settings/ChartSettingsPanel.d.ts +11 -0
  251. package/dist/dashboard/chart-settings/ChartSettingsPanel.d.ts.map +1 -0
  252. package/dist/dashboard/chart-settings/ChartSettingsPanel.js +8 -0
  253. package/dist/dashboard/chart-settings/ChartSettingsPanel.js.map +1 -0
  254. package/dist/dashboard/chart-settings/ChartTypeSelector.d.ts +11 -0
  255. package/dist/dashboard/chart-settings/ChartTypeSelector.d.ts.map +1 -0
  256. package/dist/dashboard/chart-settings/ChartTypeSelector.js +17 -0
  257. package/dist/dashboard/chart-settings/ChartTypeSelector.js.map +1 -0
  258. package/dist/dashboard/chart-settings/DynamicChartSettings.d.ts +11 -0
  259. package/dist/dashboard/chart-settings/DynamicChartSettings.d.ts.map +1 -0
  260. package/dist/dashboard/chart-settings/DynamicChartSettings.js +19 -0
  261. package/dist/dashboard/chart-settings/DynamicChartSettings.js.map +1 -0
  262. package/dist/dashboard/chart-settings/index.d.ts +6 -0
  263. package/dist/dashboard/chart-settings/index.d.ts.map +1 -0
  264. package/dist/dashboard/chart-settings/index.js +6 -0
  265. package/dist/dashboard/chart-settings/index.js.map +1 -0
  266. package/dist/dashboard/chart-settings/useTableColumns.d.ts +3 -0
  267. package/dist/dashboard/chart-settings/useTableColumns.d.ts.map +1 -0
  268. package/dist/dashboard/chart-settings/useTableColumns.js +12 -0
  269. package/dist/dashboard/chart-settings/useTableColumns.js.map +1 -0
  270. package/dist/dashboard/defaultPanelRenderers.d.ts +3 -0
  271. package/dist/dashboard/defaultPanelRenderers.d.ts.map +1 -0
  272. package/dist/dashboard/defaultPanelRenderers.js +11 -0
  273. package/dist/dashboard/defaultPanelRenderers.js.map +1 -0
  274. package/dist/dashboard/generateMosaicChartSpec.d.ts +15 -0
  275. package/dist/dashboard/generateMosaicChartSpec.d.ts.map +1 -0
  276. package/dist/dashboard/generateMosaicChartSpec.js +30 -0
  277. package/dist/dashboard/generateMosaicChartSpec.js.map +1 -0
  278. package/dist/editor/MosaicChartDisplay.d.ts.map +1 -1
  279. package/dist/editor/MosaicChartDisplay.js +6 -1
  280. package/dist/editor/MosaicChartDisplay.js.map +1 -1
  281. package/dist/index.d.ts +31 -5
  282. package/dist/index.d.ts.map +1 -1
  283. package/dist/index.js +21 -2
  284. package/dist/index.js.map +1 -1
  285. package/dist/profiler/useMosaicProfiler.d.ts.map +1 -1
  286. package/dist/profiler/useMosaicProfiler.js.map +1 -1
  287. package/dist/tableInterop.js.map +1 -1
  288. package/dist/useMosaicClient.d.ts +4 -15
  289. package/dist/useMosaicClient.d.ts.map +1 -1
  290. package/dist/useMosaicClient.js +10 -4
  291. package/dist/useMosaicClient.js.map +1 -1
  292. package/package.json +15 -9
  293. package/dist/chart-builders/createMosaicChartTool.d.ts +0 -45
  294. package/dist/chart-builders/createMosaicChartTool.d.ts.map +0 -1
  295. package/dist/chart-builders/createMosaicChartTool.js +0 -109
  296. package/dist/chart-builders/createMosaicChartTool.js.map +0 -1
  297. package/dist/dashboard/MosaicDashboardChartPanel.d.ts +0 -3
  298. package/dist/dashboard/MosaicDashboardChartPanel.d.ts.map +0 -1
  299. package/dist/dashboard/MosaicDashboardChartPanel.js +0 -49
  300. package/dist/dashboard/MosaicDashboardChartPanel.js.map +0 -1
  301. package/dist/dashboard/MosaicDashboardCharts.d.ts +0 -3
  302. package/dist/dashboard/MosaicDashboardCharts.d.ts.map +0 -1
  303. package/dist/dashboard/MosaicDashboardCharts.js +0 -45
  304. package/dist/dashboard/MosaicDashboardCharts.js.map +0 -1
  305. package/dist/dashboard/MosaicDashboardProfiler.d.ts +0 -3
  306. package/dist/dashboard/MosaicDashboardProfiler.d.ts.map +0 -1
  307. package/dist/dashboard/MosaicDashboardProfiler.js +0 -21
  308. package/dist/dashboard/MosaicDashboardProfiler.js.map +0 -1
  309. package/dist/use-mosaic.d.ts +0 -11
  310. package/dist/use-mosaic.d.ts.map +0 -1
  311. package/dist/use-mosaic.js +0 -42
  312. package/dist/use-mosaic.js.map +0 -1
@@ -1,127 +1,387 @@
1
1
  import { createId } from '@paralleldrive/cuid2';
2
- import { LayoutMosaicSubNode as LayoutMosaicSubNodeSchema } from '@sqlrooms/layout-config';
2
+ import { DEFAULT_GRID_COLS, getGridColsForBreakpoint, } from '@sqlrooms/layout';
3
+ import { isLayoutGridNode, isLayoutNodeKey, isLayoutPanelNode, isLayoutSplitNode, LayoutNode as LayoutNodeSchema, } from '@sqlrooms/layout-config';
3
4
  import { createSlice, useBaseRoomStore, } from '@sqlrooms/room-store';
4
5
  import { produce } from 'immer';
5
6
  import { z } from 'zod';
6
- export const DEFAULT_MOSAIC_DASHBOARD_CHART_VGPLOT = JSON.stringify({
7
- $schema: 'https://idl.uw.edu/mosaic/schema/latest.json',
8
- meta: {
9
- title: 'New Chart',
10
- description: 'Use the chart builder or edit the spec directly to visualize DuckDB tables.',
11
- },
12
- data: {
13
- sample: {
14
- type: 'table',
15
- query: `
16
- SELECT * FROM (
17
- VALUES
18
- ('A', 12),
19
- ('B', 26),
20
- ('C', 18),
21
- ('D', 9)
22
- ) AS t(category, amount)
23
- `,
24
- },
25
- },
26
- plot: [
27
- {
28
- mark: 'barY',
29
- data: { from: 'sample' },
30
- x: 'category',
31
- y: 'amount',
32
- fill: 'category',
33
- },
34
- ],
35
- xLabel: 'Category',
36
- yLabel: 'Amount',
37
- width: 560,
38
- height: 320,
39
- }, null, 2);
40
- export const DEFAULT_MOSAIC_DASHBOARD_CHART_SPEC = JSON.parse(DEFAULT_MOSAIC_DASHBOARD_CHART_VGPLOT);
41
- export const MosaicDashboardChartConfig = z.object({
7
+ import { destroyRetainedVgPlotChart, } from '../VgPlotChart';
8
+ import { VgPlotChartConfig } from '../chart-types';
9
+ /**
10
+ * Panel key used for function-form panel definitions registered by
11
+ * `MosaicDashboardPanels`. Individual dashboard panels are represented as
12
+ * `LayoutPanelNode` entries whose `panel` property carries
13
+ * `{ key: MOSAIC_DASHBOARD_PANEL, meta: { dashboardId, panelId } }`.
14
+ */
15
+ export const MOSAIC_DASHBOARD_PANEL = 'mosaic-dashboard-panel';
16
+ export const MOSAIC_DASHBOARD_VGPLOT_PANEL_TYPE = 'vgplot';
17
+ export const MOSAIC_DASHBOARD_PROFILER_PANEL_TYPE = 'profiler';
18
+ export const MosaicDashboardLayoutType = z.enum(['dock', 'grid']);
19
+ export const MosaicDashboardPanelSource = z.object({
20
+ tableName: z.string().optional(),
21
+ sqlQuery: z.string().optional(),
22
+ });
23
+ // Profiler panel config
24
+ export const ProfilerPanelConfig = z.object({
25
+ pageSize: z.number().optional(),
26
+ });
27
+ // Panel configs discriminated by type
28
+ export const VgPlotPanelConfig = z.object({
29
+ id: z.string(),
30
+ type: z.literal(MOSAIC_DASHBOARD_VGPLOT_PANEL_TYPE),
31
+ title: z.string().default('Panel'),
32
+ source: MosaicDashboardPanelSource.optional(),
33
+ config: VgPlotChartConfig,
34
+ });
35
+ export const ProfilerPanel = z.object({
42
36
  id: z.string(),
43
- title: z.string().default('Chart'),
44
- vgplot: z
45
- .object({})
46
- .passthrough()
47
- .default(DEFAULT_MOSAIC_DASHBOARD_CHART_SPEC),
37
+ type: z.literal(MOSAIC_DASHBOARD_PROFILER_PANEL_TYPE),
38
+ title: z.string().default('Panel'),
39
+ source: MosaicDashboardPanelSource.optional(),
40
+ config: ProfilerPanelConfig,
48
41
  });
42
+ // Legacy panel for backward compatibility
43
+ export const LegacyPanelConfig = z.object({
44
+ id: z.string(),
45
+ type: z.string(),
46
+ title: z.string().default('Panel'),
47
+ source: MosaicDashboardPanelSource.optional(),
48
+ config: z.record(z.string(), z.unknown()).default({}),
49
+ });
50
+ // Discriminated union of all panel types
51
+ export const MosaicDashboardPanelConfig = z
52
+ .discriminatedUnion('type', [VgPlotPanelConfig, ProfilerPanel])
53
+ .or(LegacyPanelConfig);
54
+ export function createMosaicDashboardVgPlotPanelConfig(title, config, source) {
55
+ return VgPlotPanelConfig.parse({
56
+ id: createId(),
57
+ type: MOSAIC_DASHBOARD_VGPLOT_PANEL_TYPE,
58
+ title,
59
+ source,
60
+ config,
61
+ });
62
+ }
63
+ export function createMosaicDashboardProfilerPanelConfig(options = {}) {
64
+ return {
65
+ id: createId(),
66
+ type: MOSAIC_DASHBOARD_PROFILER_PANEL_TYPE,
67
+ title: options.title ?? 'Profiler',
68
+ source: options.source,
69
+ config: {
70
+ pageSize: options.pageSize ?? 10,
71
+ },
72
+ };
73
+ }
49
74
  export const MosaicDashboardEntry = z.object({
50
75
  id: z.string(),
51
76
  title: z.string().default('Dashboard'),
77
+ layoutType: MosaicDashboardLayoutType.default('dock'),
52
78
  selectedTable: z.string().optional(),
53
- charts: z.array(MosaicDashboardChartConfig).default([]),
54
- layout: LayoutMosaicSubNodeSchema.nullable().default(null),
79
+ panels: z.array(MosaicDashboardPanelConfig).default([]),
80
+ layout: LayoutNodeSchema.nullable().default(null),
55
81
  updatedAt: z.number().default(0),
56
82
  });
57
83
  export const MosaicDashboardSliceConfig = z.object({
58
84
  dashboardsById: z.record(z.string(), MosaicDashboardEntry).default({}),
59
85
  });
60
- function appendPanelToLayout(layout, panelId) {
86
+ // ---------------------------------------------------------------------------
87
+ // Layout tree helpers (operate on the new LayoutNode types)
88
+ // ---------------------------------------------------------------------------
89
+ function createDashboardPanelNode(dashboardId, panelId) {
90
+ return {
91
+ type: 'panel',
92
+ id: getMosaicDashboardPanelId(dashboardId, panelId),
93
+ minSize: 200,
94
+ panel: {
95
+ key: MOSAIC_DASHBOARD_PANEL,
96
+ meta: { dashboardId, panelId },
97
+ },
98
+ };
99
+ }
100
+ function getDashboardPanelTypesByLayoutId(dashboardId, panels) {
101
+ return Object.fromEntries(panels.map((panel) => [
102
+ getMosaicDashboardPanelId(dashboardId, panel.id),
103
+ panel.type,
104
+ ]));
105
+ }
106
+ function appendPanelToLayout(layout, panelNode) {
61
107
  if (!layout) {
62
- return panelId;
108
+ return panelNode;
63
109
  }
64
110
  return {
65
111
  type: 'split',
112
+ id: `split-${createId()}`,
66
113
  direction: 'row',
67
- children: [layout, panelId],
114
+ children: [layout, panelNode],
68
115
  };
69
116
  }
70
- function removePanelFromLayout(layout, panelId) {
117
+ function createDashboardGridLayout(dashboardId, panelNode) {
118
+ const children = panelNode ? [panelNode] : [];
119
+ const layouts = createDashboardGridLayoutsForChildren(children);
120
+ return {
121
+ type: 'grid',
122
+ id: getMosaicDashboardGridId(dashboardId),
123
+ children,
124
+ rowHeight: 150,
125
+ margin: [12, 12],
126
+ containerPadding: [0, 0],
127
+ compactType: 'vertical',
128
+ preventCollision: false,
129
+ resizeHandles: ['e', 's', 'w', 'se', 'sw'],
130
+ layouts,
131
+ };
132
+ }
133
+ function getLayoutChildId(node) {
134
+ return isLayoutNodeKey(node) ? node : node.id;
135
+ }
136
+ function createDashboardGridItem(panelId, layout, cols = 12, panelType) {
137
+ const effectiveCols = Math.max(1, cols);
138
+ const w = panelType === MOSAIC_DASHBOARD_PROFILER_PANEL_TYPE
139
+ ? effectiveCols
140
+ : Math.max(1, Math.ceil(effectiveCols / 2));
141
+ const h = 2;
142
+ const bottom = layout.reduce((max, item) => Math.max(max, item.y + item.h), 0);
143
+ for (let y = 0; y <= bottom; y += 1) {
144
+ for (let x = 0; x <= effectiveCols - w; x += 1) {
145
+ const overlaps = layout.some((item) => x < item.x + item.w &&
146
+ x + w > item.x &&
147
+ y < item.y + item.h &&
148
+ y + h > item.y);
149
+ if (!overlaps) {
150
+ return {
151
+ i: panelId,
152
+ x,
153
+ y,
154
+ w,
155
+ h,
156
+ };
157
+ }
158
+ }
159
+ }
160
+ return {
161
+ i: panelId,
162
+ x: 0,
163
+ y: bottom,
164
+ w,
165
+ h,
166
+ };
167
+ }
168
+ function createDashboardGridLayoutsForChildren(children, sourceLayouts, cols, panelTypesByLayoutId = {}) {
169
+ const childIds = new Set(children.map((child) => getLayoutChildId(child)));
170
+ const sourceEntries = new Map(Object.keys(DEFAULT_GRID_COLS).map((breakpoint) => [breakpoint, []]));
171
+ for (const [breakpoint, breakpointLayout] of Object.entries(sourceLayouts ?? {})) {
172
+ sourceEntries.set(breakpoint, breakpointLayout);
173
+ }
174
+ return Object.fromEntries([...sourceEntries.entries()].map(([breakpoint, breakpointLayout]) => {
175
+ const nextLayout = breakpointLayout.filter((item) => childIds.has(item.i));
176
+ const layoutItemIds = new Set(nextLayout.map((item) => item.i));
177
+ for (const child of children) {
178
+ const childId = getLayoutChildId(child);
179
+ if (!layoutItemIds.has(childId)) {
180
+ const item = createDashboardGridItem(childId, nextLayout, getGridColsForBreakpoint(cols, breakpoint), panelTypesByLayoutId[childId]);
181
+ nextLayout.push(item);
182
+ layoutItemIds.add(childId);
183
+ }
184
+ }
185
+ return [breakpoint, nextLayout];
186
+ }));
187
+ }
188
+ function isExpectedDashboardPanelNode(node, expectedPanelIds) {
189
+ return expectedPanelIds.has(getLayoutChildId(node));
190
+ }
191
+ function collectDashboardPanelNodes(layout, expectedPanelIds, nodes = [], seen = new Set()) {
71
192
  if (!layout)
72
- return null;
73
- if (typeof layout === 'string') {
74
- return layout === panelId ? null : layout;
193
+ return nodes;
194
+ if (isLayoutNodeKey(layout) || isLayoutPanelNode(layout)) {
195
+ if (isExpectedDashboardPanelNode(layout, expectedPanelIds)) {
196
+ const id = getLayoutChildId(layout);
197
+ if (!seen.has(id)) {
198
+ nodes.push(layout);
199
+ seen.add(id);
200
+ }
201
+ }
202
+ return nodes;
75
203
  }
76
- const nextChildren = layout.children
77
- .map((child) => removePanelFromLayout(child, panelId))
78
- .filter((child) => child !== null);
79
- if (nextChildren.length === 0)
80
- return null;
81
- if (nextChildren.length === 1) {
82
- const onlyChild = nextChildren[0];
83
- return onlyChild ?? null;
204
+ if (isLayoutSplitNode(layout) || isLayoutGridNode(layout)) {
205
+ for (const child of layout.children) {
206
+ collectDashboardPanelNodes(child, expectedPanelIds, nodes, seen);
207
+ }
84
208
  }
209
+ return nodes;
210
+ }
211
+ function normalizeDashboardGridLayout(layout, dashboardId, expectedPanelIds, panelTypesByLayoutId = {}) {
212
+ const collectedPanelIds = collectPanelIds(layout);
213
+ const existingExpectedPanelIds = new Set([...expectedPanelIds].filter((panelId) => collectedPanelIds.has(panelId)));
214
+ const children = collectDashboardPanelNodes(layout, existingExpectedPanelIds);
215
+ const layouts = createDashboardGridLayoutsForChildren(children, isLayoutGridNode(layout) ? layout.layouts : undefined, isLayoutGridNode(layout) ? layout.cols : undefined, panelTypesByLayoutId);
216
+ if (isLayoutGridNode(layout)) {
217
+ return {
218
+ ...layout,
219
+ children,
220
+ layouts,
221
+ };
222
+ }
223
+ return {
224
+ ...createDashboardGridLayout(dashboardId),
225
+ children,
226
+ layouts,
227
+ };
228
+ }
229
+ function appendPanelToGridLayout(layout, dashboardId, panelNode, panelType, panelTypesByLayoutId = {}) {
230
+ const nextPanelTypesByLayoutId = {
231
+ ...panelTypesByLayoutId,
232
+ [panelNode.id]: panelType ?? panelTypesByLayoutId[panelNode.id],
233
+ };
234
+ if (!isLayoutGridNode(layout)) {
235
+ const dashboardPanelPrefix = `dashboard:${dashboardId}:panel:`;
236
+ const expectedPanelIds = new Set([...collectPanelIds(layout)].filter((panelId) => panelId.startsWith(dashboardPanelPrefix)));
237
+ expectedPanelIds.add(panelNode.id);
238
+ const normalizedLayout = normalizeDashboardGridLayout(layout, dashboardId, expectedPanelIds, nextPanelTypesByLayoutId);
239
+ return appendPanelToGridLayout(normalizedLayout, dashboardId, panelNode, panelType, nextPanelTypesByLayoutId);
240
+ }
241
+ const hasChild = layout.children.some((child) => {
242
+ if (isLayoutNodeKey(child))
243
+ return child === panelNode.id;
244
+ return child.id === panelNode.id;
245
+ });
246
+ const children = hasChild ? layout.children : [...layout.children, panelNode];
247
+ const layouts = Object.fromEntries(Object.entries(createDashboardGridLayoutsForChildren(children, layout.layouts, layout.cols, nextPanelTypesByLayoutId) ?? {}).map(([breakpoint, breakpointLayout]) => {
248
+ if (breakpointLayout.some((item) => item.i === panelNode.id)) {
249
+ return [breakpoint, breakpointLayout];
250
+ }
251
+ return [
252
+ breakpoint,
253
+ [
254
+ ...breakpointLayout,
255
+ createDashboardGridItem(panelNode.id, breakpointLayout, getGridColsForBreakpoint(layout.cols, breakpoint), nextPanelTypesByLayoutId[panelNode.id]),
256
+ ],
257
+ ];
258
+ }));
85
259
  return {
86
260
  ...layout,
87
- children: nextChildren,
261
+ children,
262
+ layouts,
88
263
  };
89
264
  }
265
+ function removePanelFromLayout(layout, panelId) {
266
+ if (!layout)
267
+ return null;
268
+ if (isLayoutNodeKey(layout)) {
269
+ return layout === panelId ? null : layout;
270
+ }
271
+ if (isLayoutPanelNode(layout)) {
272
+ return layout.id === panelId ? null : layout;
273
+ }
274
+ if (isLayoutSplitNode(layout)) {
275
+ const nextChildren = layout.children
276
+ .map((child) => removePanelFromLayout(child, panelId))
277
+ .filter((child) => child !== null);
278
+ if (nextChildren.length === 0)
279
+ return null;
280
+ if (nextChildren.length === 1)
281
+ return nextChildren[0] ?? null;
282
+ return { ...layout, children: nextChildren };
283
+ }
284
+ if (isLayoutGridNode(layout)) {
285
+ const nextChildren = layout.children.filter((child) => {
286
+ if (isLayoutNodeKey(child))
287
+ return child !== panelId;
288
+ return child.id !== panelId;
289
+ });
290
+ const nextLayouts = layout.layouts
291
+ ? Object.fromEntries(Object.entries(layout.layouts).map(([breakpoint, breakpointLayout]) => [
292
+ breakpoint,
293
+ breakpointLayout.filter((item) => item.i !== panelId),
294
+ ]))
295
+ : layout.layouts;
296
+ if (nextChildren.length === 0)
297
+ return null;
298
+ return { ...layout, children: nextChildren, layouts: nextLayouts };
299
+ }
300
+ return layout;
301
+ }
90
302
  function collectPanelIds(layout, panelIds = new Set()) {
91
303
  if (!layout)
92
304
  return panelIds;
93
- if (typeof layout === 'string') {
305
+ if (isLayoutNodeKey(layout)) {
94
306
  panelIds.add(layout);
95
307
  return panelIds;
96
308
  }
97
- for (const child of layout.children) {
98
- collectPanelIds(child, panelIds);
309
+ if (isLayoutPanelNode(layout)) {
310
+ panelIds.add(layout.id);
311
+ return panelIds;
312
+ }
313
+ if (isLayoutSplitNode(layout)) {
314
+ for (const child of layout.children) {
315
+ collectPanelIds(child, panelIds);
316
+ }
317
+ }
318
+ if (isLayoutGridNode(layout)) {
319
+ for (const child of layout.children) {
320
+ collectPanelIds(child, panelIds);
321
+ }
99
322
  }
100
323
  return panelIds;
101
324
  }
102
- function ensureLayoutContainsPanels(layout, panelIds) {
325
+ function ensureLayoutContainsDashboardPanels(layout, dashboardId, panelIds, layoutType = 'dock', panelTypesByLayoutId = {}) {
103
326
  let nextLayout = layout;
104
- const existing = collectPanelIds(layout);
327
+ if (layoutType === 'grid') {
328
+ const expectedPanelIds = new Set(panelIds.map((panelId) => getMosaicDashboardPanelId(dashboardId, panelId)));
329
+ nextLayout = normalizeDashboardGridLayout(nextLayout, dashboardId, expectedPanelIds, panelTypesByLayoutId);
330
+ }
331
+ const existing = collectPanelIds(nextLayout);
105
332
  for (const panelId of panelIds) {
106
- if (!existing.has(panelId)) {
107
- nextLayout = appendPanelToLayout(nextLayout, panelId);
108
- existing.add(panelId);
333
+ const layoutPanelId = getMosaicDashboardPanelId(dashboardId, panelId);
334
+ if (!existing.has(layoutPanelId)) {
335
+ const panelNode = createDashboardPanelNode(dashboardId, panelId);
336
+ nextLayout =
337
+ layoutType === 'grid'
338
+ ? appendPanelToGridLayout(nextLayout, dashboardId, panelNode, panelTypesByLayoutId[layoutPanelId], panelTypesByLayoutId)
339
+ : appendPanelToLayout(nextLayout, panelNode);
340
+ existing.add(layoutPanelId);
109
341
  }
110
342
  }
111
343
  return nextLayout;
112
344
  }
113
- export function getMosaicDashboardPanelId(dashboardId, chartId) {
114
- return `dashboard:${dashboardId}:chart:${chartId}`;
345
+ export function isVgPlotPanelConfig(panel) {
346
+ return panel.type === MOSAIC_DASHBOARD_VGPLOT_PANEL_TYPE;
347
+ }
348
+ export function getMosaicDashboardPanelId(dashboardId, panelId) {
349
+ return `dashboard:${dashboardId}:panel:${panelId}`;
115
350
  }
116
- export function getMosaicDashboardMosaicId(dashboardId) {
117
- return `dashboard:${dashboardId}:mosaic`;
351
+ export function getMosaicDashboardDockId(dashboardId) {
352
+ return `dashboard:${dashboardId}:dock`;
353
+ }
354
+ export function getMosaicDashboardGridId(dashboardId) {
355
+ return `dashboard:${dashboardId}:grid`;
118
356
  }
119
357
  export function getMosaicDashboardSelectionName(dashboardId) {
120
358
  return `dashboard:${dashboardId}:brush`;
121
359
  }
122
- export function parseMosaicDashboardChartId(dashboardId, panelId) {
123
- const prefix = `dashboard:${dashboardId}:chart:`;
124
- return panelId.startsWith(prefix) ? panelId.slice(prefix.length) : undefined;
360
+ function destroyDashboardRuntimeChart(chart) {
361
+ if (!chart)
362
+ return;
363
+ destroyRetainedVgPlotChart(chart);
364
+ }
365
+ function evictDashboardSelection(state, dashboardId) {
366
+ state.mosaic.selections[getMosaicDashboardSelectionName(dashboardId)]?.reset();
367
+ }
368
+ function shouldEvictPanelRuntimeForPatch(panel, patch) {
369
+ if (patch.type && patch.type !== panel.type) {
370
+ return true;
371
+ }
372
+ if (panel.type === MOSAIC_DASHBOARD_VGPLOT_PANEL_TYPE) {
373
+ return Boolean(patch.config &&
374
+ Object.prototype.hasOwnProperty.call(patch.config, 'vgplot'));
375
+ }
376
+ return false;
377
+ }
378
+ export function resolveMosaicDashboardPanelSource(dashboard, panel) {
379
+ if (panel.source?.sqlQuery || panel.source?.tableName) {
380
+ return panel.source;
381
+ }
382
+ return dashboard.selectedTable
383
+ ? { tableName: dashboard.selectedTable }
384
+ : undefined;
125
385
  }
126
386
  export function createDefaultMosaicDashboardConfig(props) {
127
387
  return MosaicDashboardSliceConfig.parse({
@@ -133,12 +393,19 @@ export function createMosaicDashboardSlice(props = {}) {
133
393
  return createSlice((set, get) => ({
134
394
  mosaicDashboard: {
135
395
  config: createDefaultMosaicDashboardConfig(props.config),
136
- createDashboard(title) {
396
+ runtime: {
397
+ retainedChartsByPanelId: {},
398
+ },
399
+ chartBuilders: props.chartBuilders,
400
+ chartTypes: props.chartTypes,
401
+ addPanelActions: props.addPanelActions ?? [],
402
+ panelRenderers: props.panelRenderers ?? {},
403
+ createDashboard(title, layoutType) {
137
404
  const dashboardId = createId();
138
- get().mosaicDashboard.ensureDashboard(dashboardId, title);
405
+ get().mosaicDashboard.ensureDashboard(dashboardId, title, layoutType);
139
406
  return dashboardId;
140
407
  },
141
- ensureDashboard(dashboardId, title) {
408
+ ensureDashboard(dashboardId, title, layoutType) {
142
409
  set((state) => produce(state, (draft) => {
143
410
  const existing = draft.mosaicDashboard.config.dashboardsById[dashboardId];
144
411
  if (existing) {
@@ -151,14 +418,20 @@ export function createMosaicDashboardSlice(props = {}) {
151
418
  draft.mosaicDashboard.config.dashboardsById[dashboardId] = {
152
419
  id: dashboardId,
153
420
  title: title ?? 'Dashboard',
421
+ layoutType: layoutType ?? 'dock',
154
422
  selectedTable: undefined,
155
- charts: [],
156
- layout: null,
423
+ panels: [],
424
+ layout: layoutType === 'grid'
425
+ ? createDashboardGridLayout(dashboardId)
426
+ : null,
157
427
  updatedAt: Date.now(),
158
428
  };
159
429
  }));
160
430
  },
161
431
  removeDashboard(dashboardId) {
432
+ get().mosaicDashboard.evictDashboardRuntime(dashboardId, {
433
+ resetSelection: true,
434
+ });
162
435
  set((state) => produce(state, (draft) => {
163
436
  delete draft.mosaicDashboard.config.dashboardsById[dashboardId];
164
437
  }));
@@ -166,6 +439,11 @@ export function createMosaicDashboardSlice(props = {}) {
166
439
  getDashboard(dashboardId) {
167
440
  return get().mosaicDashboard.config.dashboardsById[dashboardId];
168
441
  },
442
+ setConfig(config) {
443
+ set((state) => produce(state, (draft) => {
444
+ draft.mosaicDashboard.config = config;
445
+ }));
446
+ },
169
447
  setSelectedTable(dashboardId, tableName) {
170
448
  get().mosaicDashboard.ensureDashboard(dashboardId);
171
449
  set((state) => produce(state, (draft) => {
@@ -176,48 +454,155 @@ export function createMosaicDashboardSlice(props = {}) {
176
454
  dashboard.updatedAt = Date.now();
177
455
  }));
178
456
  },
179
- addChart(dashboardId, chart) {
457
+ registerPanelRenderer(type, renderer) {
458
+ set((state) => produce(state, (draft) => {
459
+ draft.mosaicDashboard.panelRenderers[type] = renderer;
460
+ }));
461
+ },
462
+ unregisterPanelRenderer(type) {
463
+ set((state) => produce(state, (draft) => {
464
+ delete draft.mosaicDashboard.panelRenderers[type];
465
+ }));
466
+ },
467
+ addPanel(dashboardId, panel) {
180
468
  get().mosaicDashboard.ensureDashboard(dashboardId);
181
469
  set((state) => produce(state, (draft) => {
182
470
  const dashboard = draft.mosaicDashboard.config.dashboardsById[dashboardId];
183
471
  if (!dashboard)
184
472
  return;
185
- dashboard.charts.push(chart);
186
- dashboard.layout = appendPanelToLayout(dashboard.layout, getMosaicDashboardPanelId(dashboardId, chart.id));
473
+ dashboard.panels.push(panel);
474
+ const panelNode = createDashboardPanelNode(dashboardId, panel.id);
475
+ const panelTypesByLayoutId = getDashboardPanelTypesByLayoutId(dashboardId, dashboard.panels);
476
+ dashboard.layout =
477
+ dashboard.layoutType === 'grid'
478
+ ? appendPanelToGridLayout(dashboard.layout, dashboardId, panelNode, panel.type, panelTypesByLayoutId)
479
+ : appendPanelToLayout(dashboard.layout, panelNode);
187
480
  dashboard.updatedAt = Date.now();
188
481
  }));
189
- return chart.id;
482
+ return panel.id;
190
483
  },
191
- updateChart(dashboardId, chartId, patch) {
484
+ updatePanel(dashboardId, panelId, patch) {
485
+ const existing = get().mosaicDashboard.config.dashboardsById[dashboardId]?.panels.find((candidate) => candidate.id === panelId);
486
+ const shouldEvict = existing
487
+ ? shouldEvictPanelRuntimeForPatch(existing, patch)
488
+ : false;
192
489
  set((state) => produce(state, (draft) => {
193
490
  const dashboard = draft.mosaicDashboard.config.dashboardsById[dashboardId];
194
491
  if (!dashboard)
195
492
  return;
196
- const chart = dashboard.charts.find((item) => item.id === chartId);
197
- if (!chart)
493
+ const panel = dashboard.panels.find((candidate) => candidate.id === panelId);
494
+ if (!panel)
198
495
  return;
199
- Object.assign(chart, patch);
496
+ Object.assign(panel, patch);
200
497
  dashboard.updatedAt = Date.now();
201
498
  }));
499
+ if (shouldEvict) {
500
+ get().mosaicDashboard.evictPanelRuntime(dashboardId, panelId);
501
+ }
202
502
  },
203
- removeChart(dashboardId, chartId) {
503
+ removePanel(dashboardId, panelId) {
504
+ get().mosaicDashboard.evictPanelRuntime(dashboardId, panelId);
204
505
  set((state) => produce(state, (draft) => {
205
506
  const dashboard = draft.mosaicDashboard.config.dashboardsById[dashboardId];
206
507
  if (!dashboard)
207
508
  return;
208
- dashboard.charts = dashboard.charts.filter((chart) => chart.id !== chartId);
209
- dashboard.layout = removePanelFromLayout(dashboard.layout, getMosaicDashboardPanelId(dashboardId, chartId));
509
+ dashboard.panels = dashboard.panels.filter((panel) => panel.id !== panelId);
510
+ dashboard.layout = removePanelFromLayout(dashboard.layout, getMosaicDashboardPanelId(dashboardId, panelId));
210
511
  dashboard.updatedAt = Date.now();
211
512
  }));
212
513
  },
514
+ getRetainedChart(dashboardId, panelId) {
515
+ return get().mosaicDashboard.runtime.retainedChartsByPanelId[getMosaicDashboardPanelId(dashboardId, panelId)];
516
+ },
517
+ setRetainedChart(dashboardId, panelId, chart) {
518
+ const runtimePanelId = getMosaicDashboardPanelId(dashboardId, panelId);
519
+ const previous = get().mosaicDashboard.runtime.retainedChartsByPanelId[runtimePanelId];
520
+ if (previous && previous !== chart) {
521
+ destroyDashboardRuntimeChart(previous);
522
+ }
523
+ set((state) => ({
524
+ mosaicDashboard: {
525
+ ...state.mosaicDashboard,
526
+ runtime: {
527
+ ...state.mosaicDashboard.runtime,
528
+ retainedChartsByPanelId: {
529
+ ...state.mosaicDashboard.runtime.retainedChartsByPanelId,
530
+ [runtimePanelId]: chart,
531
+ },
532
+ },
533
+ },
534
+ }));
535
+ },
536
+ evictPanelRuntime(dashboardId, panelId) {
537
+ const runtimePanelId = getMosaicDashboardPanelId(dashboardId, panelId);
538
+ const existing = get().mosaicDashboard.runtime.retainedChartsByPanelId[runtimePanelId];
539
+ destroyDashboardRuntimeChart(existing);
540
+ set((state) => {
541
+ const nextRetainedChartsByPanelId = {
542
+ ...state.mosaicDashboard.runtime.retainedChartsByPanelId,
543
+ };
544
+ delete nextRetainedChartsByPanelId[runtimePanelId];
545
+ return {
546
+ mosaicDashboard: {
547
+ ...state.mosaicDashboard,
548
+ runtime: {
549
+ ...state.mosaicDashboard.runtime,
550
+ retainedChartsByPanelId: nextRetainedChartsByPanelId,
551
+ },
552
+ },
553
+ };
554
+ });
555
+ },
556
+ evictDashboardRuntime(dashboardId, options) {
557
+ const runtimePrefix = `dashboard:${dashboardId}:panel:`;
558
+ const existingEntries = Object.entries(get().mosaicDashboard.runtime.retainedChartsByPanelId).filter(([runtimePanelId]) => runtimePanelId.startsWith(runtimePrefix));
559
+ existingEntries.forEach(([, chart]) => {
560
+ destroyDashboardRuntimeChart(chart);
561
+ });
562
+ if (options?.resetSelection) {
563
+ evictDashboardSelection(get(), dashboardId);
564
+ }
565
+ set((state) => {
566
+ const nextRetainedChartsByPanelId = {
567
+ ...state.mosaicDashboard.runtime.retainedChartsByPanelId,
568
+ };
569
+ for (const [runtimePanelId] of existingEntries) {
570
+ delete nextRetainedChartsByPanelId[runtimePanelId];
571
+ }
572
+ return {
573
+ mosaicDashboard: {
574
+ ...state.mosaicDashboard,
575
+ runtime: {
576
+ ...state.mosaicDashboard.runtime,
577
+ retainedChartsByPanelId: nextRetainedChartsByPanelId,
578
+ },
579
+ },
580
+ };
581
+ });
582
+ },
583
+ clearAllDashboardRuntime() {
584
+ Object.values(get().mosaicDashboard.runtime.retainedChartsByPanelId).forEach((chart) => {
585
+ destroyDashboardRuntimeChart(chart);
586
+ });
587
+ set((state) => ({
588
+ mosaicDashboard: {
589
+ ...state.mosaicDashboard,
590
+ runtime: {
591
+ ...state.mosaicDashboard.runtime,
592
+ retainedChartsByPanelId: {},
593
+ },
594
+ },
595
+ }));
596
+ },
213
597
  setLayout(dashboardId, layout) {
214
598
  get().mosaicDashboard.ensureDashboard(dashboardId);
215
599
  set((state) => produce(state, (draft) => {
216
600
  const dashboard = draft.mosaicDashboard.config.dashboardsById[dashboardId];
217
601
  if (!dashboard)
218
602
  return;
219
- const chartPanelIds = dashboard.charts.map((chart) => getMosaicDashboardPanelId(dashboardId, chart.id));
220
- dashboard.layout = ensureLayoutContainsPanels(layout, chartPanelIds);
603
+ const panelIds = dashboard.panels.map((panel) => panel.id);
604
+ const panelTypesByLayoutId = getDashboardPanelTypesByLayoutId(dashboardId, dashboard.panels);
605
+ dashboard.layout = ensureLayoutContainsDashboardPanels(layout, dashboardId, panelIds, dashboard.layoutType, panelTypesByLayoutId);
221
606
  dashboard.updatedAt = Date.now();
222
607
  }));
223
608
  },