@finos/legend-query-builder 4.17.99 → 4.18.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 (268) hide show
  1. package/lib/components/QueryBuilder.d.ts.map +1 -1
  2. package/lib/components/QueryBuilder.js +2 -1
  3. package/lib/components/QueryBuilder.js.map +1 -1
  4. package/lib/components/QueryBuilderSideBar.d.ts.map +1 -1
  5. package/lib/components/QueryBuilderSideBar.js +9 -8
  6. package/lib/components/QueryBuilderSideBar.js.map +1 -1
  7. package/lib/components/explorer/QueryBuilderExplorerPanel.d.ts.map +1 -1
  8. package/lib/components/explorer/QueryBuilderExplorerPanel.js +48 -5
  9. package/lib/components/explorer/QueryBuilderExplorerPanel.js.map +1 -1
  10. package/lib/components/explorer/QueryBuilderRelationExplorerPanel.d.ts +24 -0
  11. package/lib/components/explorer/QueryBuilderRelationExplorerPanel.d.ts.map +1 -0
  12. package/lib/components/explorer/QueryBuilderRelationExplorerPanel.js +202 -0
  13. package/lib/components/explorer/QueryBuilderRelationExplorerPanel.js.map +1 -0
  14. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.d.ts.map +1 -1
  15. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
  16. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js +3 -3
  17. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js.map +1 -1
  18. package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
  19. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +25 -6
  20. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
  21. package/lib/components/result/QueryBuilderResultPanel.d.ts.map +1 -1
  22. package/lib/components/result/QueryBuilderResultPanel.js +1 -1
  23. package/lib/components/result/QueryBuilderResultPanel.js.map +1 -1
  24. package/lib/components/result/tds/QueryBuilderTDSAsyncCellSelectionStats.d.ts +42 -0
  25. package/lib/components/result/tds/QueryBuilderTDSAsyncCellSelectionStats.d.ts.map +1 -0
  26. package/lib/components/result/tds/QueryBuilderTDSAsyncCellSelectionStats.js +212 -0
  27. package/lib/components/result/tds/QueryBuilderTDSAsyncCellSelectionStats.js.map +1 -0
  28. package/lib/components/result/tds/QueryBuilderTDSCellSelectionStats.d.ts +66 -0
  29. package/lib/components/result/tds/QueryBuilderTDSCellSelectionStats.d.ts.map +1 -0
  30. package/lib/components/result/tds/QueryBuilderTDSCellSelectionStats.js +265 -0
  31. package/lib/components/result/tds/QueryBuilderTDSCellSelectionStats.js.map +1 -0
  32. package/lib/components/result/tds/QueryBuilderTDSCellSelectionStatsBar.d.ts +28 -0
  33. package/lib/components/result/tds/QueryBuilderTDSCellSelectionStatsBar.d.ts.map +1 -0
  34. package/lib/components/result/tds/QueryBuilderTDSCellSelectionStatsBar.js +148 -0
  35. package/lib/components/result/tds/QueryBuilderTDSCellSelectionStatsBar.js.map +1 -0
  36. package/lib/components/result/tds/QueryBuilderTDSGridKeyboardShortcuts.d.ts +19 -0
  37. package/lib/components/result/tds/QueryBuilderTDSGridKeyboardShortcuts.d.ts.map +1 -0
  38. package/lib/components/result/tds/QueryBuilderTDSGridKeyboardShortcuts.js +196 -0
  39. package/lib/components/result/tds/QueryBuilderTDSGridKeyboardShortcuts.js.map +1 -0
  40. package/lib/components/result/tds/QueryBuilderTDSGridResult.d.ts +5 -0
  41. package/lib/components/result/tds/QueryBuilderTDSGridResult.d.ts.map +1 -1
  42. package/lib/components/result/tds/QueryBuilderTDSGridResult.js +64 -87
  43. package/lib/components/result/tds/QueryBuilderTDSGridResult.js.map +1 -1
  44. package/lib/components/result/tds/QueryBuilderTDSGridShared.d.ts +26 -0
  45. package/lib/components/result/tds/QueryBuilderTDSGridShared.d.ts.map +1 -0
  46. package/lib/components/result/tds/QueryBuilderTDSGridShared.js +51 -0
  47. package/lib/components/result/tds/QueryBuilderTDSGridShared.js.map +1 -0
  48. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.d.ts +5 -0
  49. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.d.ts.map +1 -1
  50. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.js +169 -60
  51. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.js.map +1 -1
  52. package/lib/components/workflows/AccessorQueryBuilder.d.ts +18 -0
  53. package/lib/components/workflows/AccessorQueryBuilder.d.ts.map +1 -0
  54. package/lib/components/workflows/AccessorQueryBuilder.js +87 -0
  55. package/lib/components/workflows/AccessorQueryBuilder.js.map +1 -0
  56. package/lib/components/workflows/ClassQueryBuilder.js +5 -5
  57. package/lib/components/workflows/ClassQueryBuilder.js.map +1 -1
  58. package/lib/data-access-overview.css +1 -1
  59. package/lib/graph/QueryBuilderMetaModelConst.d.ts +4 -0
  60. package/lib/graph/QueryBuilderMetaModelConst.d.ts.map +1 -1
  61. package/lib/graph/QueryBuilderMetaModelConst.js +4 -0
  62. package/lib/graph/QueryBuilderMetaModelConst.js.map +1 -1
  63. package/lib/graph-manager/protocol/pure/QueryBuilder_PureProtocolProcessorPlugin.d.ts.map +1 -1
  64. package/lib/graph-manager/protocol/pure/QueryBuilder_PureProtocolProcessorPlugin.js +7 -1
  65. package/lib/graph-manager/protocol/pure/QueryBuilder_PureProtocolProcessorPlugin.js.map +1 -1
  66. package/lib/graph-manager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.d.ts +2 -0
  67. package/lib/graph-manager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.d.ts.map +1 -1
  68. package/lib/graph-manager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.js +93 -3
  69. package/lib/graph-manager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.js.map +1 -1
  70. package/lib/index.css +2 -2
  71. package/lib/index.css.map +1 -1
  72. package/lib/index.d.ts +2 -0
  73. package/lib/index.d.ts.map +1 -1
  74. package/lib/index.js +2 -0
  75. package/lib/index.js.map +1 -1
  76. package/lib/package.json +1 -1
  77. package/lib/stores/QueryBuilderConfig.d.ts +3 -0
  78. package/lib/stores/QueryBuilderConfig.d.ts.map +1 -1
  79. package/lib/stores/QueryBuilderConfig.js +3 -0
  80. package/lib/stores/QueryBuilderConfig.js.map +1 -1
  81. package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
  82. package/lib/stores/QueryBuilderResultState.js +13 -3
  83. package/lib/stores/QueryBuilderResultState.js.map +1 -1
  84. package/lib/stores/QueryBuilderState.d.ts +14 -4
  85. package/lib/stores/QueryBuilderState.d.ts.map +1 -1
  86. package/lib/stores/QueryBuilderState.js +41 -13
  87. package/lib/stores/QueryBuilderState.js.map +1 -1
  88. package/lib/stores/QueryBuilderStateBuilder.d.ts +2 -1
  89. package/lib/stores/QueryBuilderStateBuilder.d.ts.map +1 -1
  90. package/lib/stores/QueryBuilderStateBuilder.js +51 -20
  91. package/lib/stores/QueryBuilderStateBuilder.js.map +1 -1
  92. package/lib/stores/QueryBuilderStateHashUtils.d.ts +1 -0
  93. package/lib/stores/QueryBuilderStateHashUtils.d.ts.map +1 -1
  94. package/lib/stores/QueryBuilderStateHashUtils.js +1 -0
  95. package/lib/stores/QueryBuilderStateHashUtils.js.map +1 -1
  96. package/lib/stores/QueryBuilderTypeaheadHelper.js +2 -2
  97. package/lib/stores/QueryBuilderTypeaheadHelper.js.map +1 -1
  98. package/lib/stores/QueryBuilderValueSpecificationBuilder.d.ts +1 -1
  99. package/lib/stores/QueryBuilderValueSpecificationBuilder.d.ts.map +1 -1
  100. package/lib/stores/QueryBuilderValueSpecificationBuilder.js +54 -45
  101. package/lib/stores/QueryBuilderValueSpecificationBuilder.js.map +1 -1
  102. package/lib/stores/__test-utils__/QueryBuilderStateTestUtils.js +1 -1
  103. package/lib/stores/__test-utils__/QueryBuilderStateTestUtils.js.map +1 -1
  104. package/lib/stores/explorer/QueryBuilderExplorerState.d.ts +12 -2
  105. package/lib/stores/explorer/QueryBuilderExplorerState.d.ts.map +1 -1
  106. package/lib/stores/explorer/QueryBuilderExplorerState.js +12 -2
  107. package/lib/stores/explorer/QueryBuilderExplorerState.js.map +1 -1
  108. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.d.ts +2 -2
  109. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.d.ts.map +1 -1
  110. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.js.map +1 -1
  111. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.d.ts +2 -2
  112. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.d.ts.map +1 -1
  113. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js +4 -3
  114. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js.map +1 -1
  115. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeStateBuilder.js +1 -1
  116. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeStateBuilder.js.map +1 -1
  117. package/lib/stores/fetch-structure/tds/QueryBuilderTDSHelper.d.ts +2 -0
  118. package/lib/stores/fetch-structure/tds/QueryBuilderTDSHelper.d.ts.map +1 -1
  119. package/lib/stores/fetch-structure/tds/QueryBuilderTDSHelper.js +19 -0
  120. package/lib/stores/fetch-structure/tds/QueryBuilderTDSHelper.js.map +1 -1
  121. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts +7 -4
  122. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts.map +1 -1
  123. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js +59 -12
  124. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js.map +1 -1
  125. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.d.ts +16 -3
  126. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.d.ts.map +1 -1
  127. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.js +102 -24
  128. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.js.map +1 -1
  129. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionStateBuilder.d.ts +2 -1
  130. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionStateBuilder.d.ts.map +1 -1
  131. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionStateBuilder.js +16 -1
  132. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionStateBuilder.js.map +1 -1
  133. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js +3 -3
  134. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js.map +1 -1
  135. package/lib/stores/fetch-structure/tds/projection/QueryBuilderRelationProjectValueSpecBuilder.d.ts.map +1 -1
  136. package/lib/stores/fetch-structure/tds/projection/QueryBuilderRelationProjectValueSpecBuilder.js +11 -2
  137. package/lib/stores/fetch-structure/tds/projection/QueryBuilderRelationProjectValueSpecBuilder.js.map +1 -1
  138. package/lib/stores/fetch-structure/tds/projection/QueryBuilderTypedProjectionStateBuilder.d.ts.map +1 -1
  139. package/lib/stores/fetch-structure/tds/projection/QueryBuilderTypedProjectionStateBuilder.js +16 -12
  140. package/lib/stores/fetch-structure/tds/projection/QueryBuilderTypedProjectionStateBuilder.js.map +1 -1
  141. package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowState.d.ts +4 -3
  142. package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowState.d.ts.map +1 -1
  143. package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowState.js +19 -9
  144. package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowState.js.map +1 -1
  145. package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowStateBuilder.d.ts +1 -0
  146. package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowStateBuilder.d.ts.map +1 -1
  147. package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowStateBuilder.js +57 -5
  148. package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowStateBuilder.js.map +1 -1
  149. package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowValueSpecificationBuilder.d.ts +4 -3
  150. package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowValueSpecificationBuilder.d.ts.map +1 -1
  151. package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowValueSpecificationBuilder.js +85 -6
  152. package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowValueSpecificationBuilder.js.map +1 -1
  153. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator.d.ts +1 -0
  154. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator.d.ts.map +1 -1
  155. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator.js.map +1 -1
  156. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Average.d.ts +1 -0
  157. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Average.d.ts.map +1 -1
  158. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Average.js +3 -0
  159. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Average.js.map +1 -1
  160. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Count.d.ts +1 -0
  161. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Count.d.ts.map +1 -1
  162. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Count.js +3 -0
  163. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Count.js.map +1 -1
  164. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Max.d.ts +1 -0
  165. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Max.d.ts.map +1 -1
  166. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Max.js +3 -0
  167. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Max.js.map +1 -1
  168. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Min.d.ts +1 -0
  169. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Min.d.ts.map +1 -1
  170. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Min.js +3 -0
  171. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Min.js.map +1 -1
  172. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Sum.d.ts +1 -0
  173. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Sum.d.ts.map +1 -1
  174. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Sum.js +3 -0
  175. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Sum.js.map +1 -1
  176. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_AverageRank.d.ts +1 -0
  177. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_AverageRank.d.ts.map +1 -1
  178. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_AverageRank.js +4 -0
  179. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_AverageRank.js.map +1 -1
  180. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_DenseRank.d.ts +1 -0
  181. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_DenseRank.d.ts.map +1 -1
  182. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_DenseRank.js +3 -0
  183. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_DenseRank.js.map +1 -1
  184. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_Rank.d.ts +1 -0
  185. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_Rank.d.ts.map +1 -1
  186. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_Rank.js +3 -0
  187. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_Rank.js.map +1 -1
  188. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_RowNumber.d.ts +1 -0
  189. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_RowNumber.d.ts.map +1 -1
  190. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_RowNumber.js +3 -0
  191. package/lib/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_RowNumber.js.map +1 -1
  192. package/lib/stores/milestoning/QueryBuilderMilestoningState.js +4 -4
  193. package/lib/stores/milestoning/QueryBuilderMilestoningState.js.map +1 -1
  194. package/lib/stores/workflows/MappingQueryBuilderState.js +2 -2
  195. package/lib/stores/workflows/MappingQueryBuilderState.js.map +1 -1
  196. package/lib/stores/workflows/ServiceQueryBuilderState.js +2 -2
  197. package/lib/stores/workflows/ServiceQueryBuilderState.js.map +1 -1
  198. package/lib/stores/workflows/accessor/AccessorQueryBuilderHelper.d.ts +18 -0
  199. package/lib/stores/workflows/accessor/AccessorQueryBuilderHelper.d.ts.map +1 -0
  200. package/lib/stores/workflows/accessor/AccessorQueryBuilderHelper.js +32 -0
  201. package/lib/stores/workflows/accessor/AccessorQueryBuilderHelper.js.map +1 -0
  202. package/lib/stores/workflows/accessor/AccessorQueryBuilderState.d.ts +57 -0
  203. package/lib/stores/workflows/accessor/AccessorQueryBuilderState.d.ts.map +1 -0
  204. package/lib/stores/workflows/accessor/AccessorQueryBuilderState.js +125 -0
  205. package/lib/stores/workflows/accessor/AccessorQueryBuilderState.js.map +1 -0
  206. package/lib/stores/workflows/dataProduct/DataProductQueryBuilderState.js +4 -4
  207. package/lib/stores/workflows/dataProduct/DataProductQueryBuilderState.js.map +1 -1
  208. package/package.json +7 -7
  209. package/src/components/QueryBuilder.tsx +2 -1
  210. package/src/components/QueryBuilderSideBar.tsx +12 -8
  211. package/src/components/explorer/QueryBuilderExplorerPanel.tsx +77 -14
  212. package/src/components/explorer/QueryBuilderRelationExplorerPanel.tsx +536 -0
  213. package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +1 -0
  214. package/src/components/fetch-structure/QueryBuilderResultModifierPanel.tsx +3 -3
  215. package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +62 -4
  216. package/src/components/result/QueryBuilderResultPanel.tsx +6 -2
  217. package/src/components/result/tds/QueryBuilderTDSAsyncCellSelectionStats.ts +254 -0
  218. package/src/components/result/tds/QueryBuilderTDSCellSelectionStats.ts +397 -0
  219. package/src/components/result/tds/QueryBuilderTDSCellSelectionStatsBar.tsx +439 -0
  220. package/src/components/result/tds/QueryBuilderTDSGridKeyboardShortcuts.ts +270 -0
  221. package/src/components/result/tds/QueryBuilderTDSGridResult.tsx +107 -112
  222. package/src/components/result/tds/QueryBuilderTDSGridShared.ts +76 -0
  223. package/src/components/result/tds/QueryBuilderTDSSimpleGridResult.tsx +272 -99
  224. package/src/components/workflows/AccessorQueryBuilder.tsx +211 -0
  225. package/src/components/workflows/ClassQueryBuilder.tsx +5 -5
  226. package/src/graph/QueryBuilderMetaModelConst.ts +5 -0
  227. package/src/graph-manager/protocol/pure/QueryBuilder_PureProtocolProcessorPlugin.ts +28 -0
  228. package/src/graph-manager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.ts +223 -4
  229. package/src/index.ts +2 -0
  230. package/src/stores/QueryBuilderConfig.ts +3 -0
  231. package/src/stores/QueryBuilderResultState.ts +22 -9
  232. package/src/stores/QueryBuilderState.ts +47 -12
  233. package/src/stores/QueryBuilderStateBuilder.ts +107 -43
  234. package/src/stores/QueryBuilderStateHashUtils.ts +1 -0
  235. package/src/stores/QueryBuilderTypeaheadHelper.ts +2 -2
  236. package/src/stores/QueryBuilderValueSpecificationBuilder.ts +72 -59
  237. package/src/stores/__test-utils__/QueryBuilderStateTestUtils.ts +1 -1
  238. package/src/stores/explorer/QueryBuilderExplorerState.ts +26 -2
  239. package/src/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.ts +1 -2
  240. package/src/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.ts +4 -3
  241. package/src/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeStateBuilder.ts +1 -1
  242. package/src/stores/fetch-structure/tds/QueryBuilderTDSHelper.ts +42 -0
  243. package/src/stores/fetch-structure/tds/QueryBuilderTDSState.ts +135 -19
  244. package/src/stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.ts +197 -38
  245. package/src/stores/fetch-structure/tds/projection/QueryBuilderProjectionStateBuilder.ts +30 -0
  246. package/src/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.ts +3 -3
  247. package/src/stores/fetch-structure/tds/projection/QueryBuilderRelationProjectValueSpecBuilder.ts +21 -0
  248. package/src/stores/fetch-structure/tds/projection/QueryBuilderTypedProjectionStateBuilder.ts +25 -16
  249. package/src/stores/fetch-structure/tds/window/QueryBuilderWindowState.ts +23 -9
  250. package/src/stores/fetch-structure/tds/window/QueryBuilderWindowStateBuilder.ts +146 -4
  251. package/src/stores/fetch-structure/tds/window/QueryBuilderWindowValueSpecificationBuilder.ts +145 -10
  252. package/src/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator.ts +2 -0
  253. package/src/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Average.ts +4 -0
  254. package/src/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Count.ts +4 -0
  255. package/src/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Max.ts +4 -0
  256. package/src/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Min.ts +4 -0
  257. package/src/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator_Sum.ts +4 -0
  258. package/src/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_AverageRank.ts +5 -0
  259. package/src/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_DenseRank.ts +4 -0
  260. package/src/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_Rank.ts +4 -0
  261. package/src/stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowRankOperator_RowNumber.ts +4 -0
  262. package/src/stores/milestoning/QueryBuilderMilestoningState.ts +4 -4
  263. package/src/stores/workflows/MappingQueryBuilderState.ts +2 -2
  264. package/src/stores/workflows/ServiceQueryBuilderState.ts +2 -2
  265. package/src/stores/workflows/accessor/AccessorQueryBuilderHelper.ts +51 -0
  266. package/src/stores/workflows/accessor/AccessorQueryBuilderState.ts +195 -0
  267. package/src/stores/workflows/dataProduct/DataProductQueryBuilderState.ts +4 -4
  268. package/tsconfig.json +9 -0
@@ -727,10 +727,14 @@ export const QueryBuilderResultPanel = observer(
727
727
 
728
728
  {allowSettingPreviewLimit && (
729
729
  <div className="query-builder__result__limit">
730
- <div className="query-builder__result__limit__label">
730
+ <label
731
+ className="query-builder__result__limit__label"
732
+ htmlFor="query-builder__result__preview-limit-input"
733
+ >
731
734
  preview row limit
732
- </div>
735
+ </label>
733
736
  <input
737
+ id="query-builder__result__preview-limit-input"
734
738
  ref={inputRef}
735
739
  className="input--dark query-builder__result__limit__input"
736
740
  spellCheck={false}
@@ -0,0 +1,254 @@
1
+ /**
2
+ * Copyright (c) 2026-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { type RefObject, useEffect, useRef, useState } from 'react';
18
+ import type { TDSResultCellData, TDSRowDataType } from '@finos/legend-graph';
19
+ import type { DataGridApi } from '@finos/legend-lego/data-grid';
20
+ import {
21
+ computeCellSelectionStats,
22
+ type CellSelectionStats,
23
+ } from './QueryBuilderTDSCellSelectionStats.js';
24
+
25
+ /**
26
+ * Return type for useAsyncCellSelectionStats.
27
+ *
28
+ * When the hook returns non-undefined, the stats bar should be shown.
29
+ *
30
+ * - `cellCount` is 0 until Phase 1 (50 ms) resolves, then the actual count.
31
+ * - `countReady` is false while the count is still being debounced.
32
+ * - `stats` is undefined until Phase 2 (200 ms + rAF) resolves.
33
+ */
34
+ export interface AsyncCellSelectionStatsResult {
35
+ /** Total selected cell count — 0 while Phase 1 debounce is pending. */
36
+ cellCount: number;
37
+ /** True once the 50 ms debounce has resolved and cellCount is accurate. */
38
+ countReady: boolean;
39
+ /** Fully-computed stats, or undefined while Phase 2 is pending. */
40
+ stats: CellSelectionStats | undefined;
41
+ }
42
+
43
+ /**
44
+ * Three-tier debounced stats hook for AG Grid enterprise cell-range selections.
45
+ *
46
+ * The hook is deliberately decoupled from the MobX `selectedCells` array.
47
+ * Instead it takes a lightweight `selectionVersion` counter that is
48
+ * incremented by `onCellSelectionChanged` (O(1)) and reads cell data lazily
49
+ * from the grid API only when the debounce timers fire.
50
+ *
51
+ * Immediate — when quickCount ≥ 2:
52
+ * The bar is shown immediately with spinner placeholders for everything
53
+ * (including the count).
54
+ *
55
+ * Phase 1 — COUNT_DEBOUNCE_MS (50 ms):
56
+ * Reads `getCellRanges()` to get the cell count in O(ranges) time.
57
+ * The count spinner is replaced with the actual number.
58
+ *
59
+ * Phase 2 — STATS_DEBOUNCE_MS (200 ms) + rAF paint guarantee:
60
+ * Reads all cell values from the grid and calls `computeCellSelectionStats`.
61
+ * The remaining spinners are replaced with computed values.
62
+ *
63
+ * Hiding is immediate: when selectionVersion changes and the count drops
64
+ * below 2, the panel is hidden synchronously.
65
+ */
66
+ const COUNT_DEBOUNCE_MS = 50;
67
+ const STATS_DEBOUNCE_MS = 200;
68
+
69
+ /**
70
+ * Fast O(ranges) cell count — just sums rows×cols per range.
71
+ * May overcount with overlapping ranges but that's acceptable for the
72
+ * show-debounce decision (exact count comes later in readSelectedCells).
73
+ */
74
+ const fastCellCount = (api: DataGridApi<TDSRowDataType>): number => {
75
+ try {
76
+ const ranges = api.getCellRanges();
77
+ if (!ranges || ranges.length === 0) {
78
+ return 0;
79
+ }
80
+ let total = 0;
81
+ for (const range of ranges) {
82
+ const start = range.startRow?.rowIndex ?? 0;
83
+ const end = range.endRow?.rowIndex ?? 0;
84
+ const rows = Math.abs(end - start) + 1;
85
+ total += rows * range.columns.length;
86
+ }
87
+ return total;
88
+ } catch {
89
+ return 0;
90
+ }
91
+ };
92
+
93
+ /**
94
+ * Reads all selected cell values from the grid API — called lazily at stats
95
+ * time (Tier 2). Complexity: O(rows) for the node map + O(cells) for the
96
+ * range iteration.
97
+ */
98
+ const readSelectedCells = (
99
+ api: DataGridApi<TDSRowDataType>,
100
+ ): TDSResultCellData[] => {
101
+ const ranges = api.getCellRanges();
102
+ if (!ranges || ranges.length === 0) {
103
+ return [];
104
+ }
105
+ // Build a rowIndex → node map once in O(rows), then look up in O(1) per cell.
106
+ const nodeByRowIndex = new Map<number, TDSRowDataType>();
107
+ api.forEachNode((node) => {
108
+ if (node.rowIndex !== null && node.data) {
109
+ nodeByRowIndex.set(node.rowIndex, node.data);
110
+ }
111
+ });
112
+ // Build a colId → column-index map once in O(columns) instead of calling
113
+ // findIndex inside the inner loop (which would be O(cols) per cell).
114
+ // Uses getColumns() (runtime column state) rather than getColumnDefs() (input config).
115
+ const allColumns = api.getColumns() ?? [];
116
+ const colIndexByColId = new Map<string, number>();
117
+ allColumns.forEach((col, i) => {
118
+ colIndexByColId.set(col.getColId(), i);
119
+ });
120
+ const seen = new Map<string, TDSResultCellData>();
121
+ for (const range of ranges) {
122
+ const start = range.startRow?.rowIndex ?? 0;
123
+ const end = range.endRow?.rowIndex ?? 0;
124
+ const lo = Math.min(start, end);
125
+ const hi = Math.max(start, end);
126
+ for (let r = lo; r <= hi; r++) {
127
+ const rowData = nodeByRowIndex.get(r);
128
+ if (!rowData) {
129
+ continue;
130
+ }
131
+ for (const col of range.columns) {
132
+ const colId = col.getColId();
133
+ const key = `${r}|${colId}`;
134
+ if (!seen.has(key)) {
135
+ seen.set(key, {
136
+ value: (rowData as Record<string, unknown>)[colId],
137
+ columnName: colId,
138
+ coordinates: {
139
+ rowIndex: r,
140
+ colIndex: colIndexByColId.get(colId) ?? -1,
141
+ },
142
+ } as TDSResultCellData);
143
+ }
144
+ }
145
+ }
146
+ }
147
+ return Array.from(seen.values());
148
+ };
149
+
150
+ export const useAsyncCellSelectionStats = (
151
+ /** Incremented O(1) on every onCellSelectionChanged — never the full cell array. */
152
+ selectionVersion: number,
153
+ columnTypes: Map<string, string | undefined>,
154
+ gridApiRef: RefObject<DataGridApi<TDSRowDataType> | null>,
155
+ /** Fallback cell array used when gridApiRef.current is null (simple grid). */
156
+ fallbackCells?: TDSResultCellData[],
157
+ ): AsyncCellSelectionStatsResult | undefined => {
158
+ const [visible, setVisible] = useState(false);
159
+ const [cellCount, setCellCount] = useState(0);
160
+ const [countReady, setCountReady] = useState(false);
161
+ const [stats, setStats] = useState<CellSelectionStats | undefined>(undefined);
162
+
163
+ const columnTypesRef = useRef(columnTypes);
164
+ useEffect(() => {
165
+ columnTypesRef.current = columnTypes;
166
+ });
167
+
168
+ const fallbackCellsRef = useRef(fallbackCells);
169
+ useEffect(() => {
170
+ fallbackCellsRef.current = fallbackCells;
171
+ });
172
+
173
+ useEffect(() => {
174
+ const api = gridApiRef.current;
175
+
176
+ // Immediate check — O(ranges) or O(1) for fallback
177
+ const quickCount = api
178
+ ? fastCellCount(api)
179
+ : (fallbackCellsRef.current?.length ?? 0);
180
+
181
+ if (quickCount < 2) {
182
+ setVisible(false);
183
+ setCellCount(0);
184
+ setCountReady(false);
185
+ setStats(undefined);
186
+ return undefined;
187
+ }
188
+
189
+ // Immediate: show bar with all spinners (count included)
190
+ setVisible(true);
191
+ setCellCount(0);
192
+ setCountReady(false);
193
+ setStats(undefined);
194
+
195
+ let cancelled = false;
196
+
197
+ // Phase 1: resolve count after 50 ms debounce
198
+ const countId = globalThis.setTimeout(() => {
199
+ if (cancelled) {
200
+ return;
201
+ }
202
+ const currentApi = gridApiRef.current;
203
+ const count = currentApi
204
+ ? fastCellCount(currentApi)
205
+ : (fallbackCellsRef.current?.length ?? 0);
206
+ if (count >= 2) {
207
+ setCellCount(count);
208
+ setCountReady(true);
209
+ } else {
210
+ // Selection shrunk below 2 during debounce — hide
211
+ setVisible(false);
212
+ setCellCount(0);
213
+ setCountReady(false);
214
+ }
215
+ }, COUNT_DEBOUNCE_MS);
216
+
217
+ // Phase 2: read cells + compute stats after 200 ms, deferred past a paint
218
+ let rafId = 0;
219
+ const statsId = globalThis.setTimeout(() => {
220
+ if (cancelled) {
221
+ return;
222
+ }
223
+ rafId = requestAnimationFrame(() => {
224
+ if (cancelled) {
225
+ return;
226
+ }
227
+ const currentApi = gridApiRef.current;
228
+ const cells = currentApi
229
+ ? readSelectedCells(currentApi)
230
+ : (fallbackCellsRef.current ?? []);
231
+ const result = computeCellSelectionStats(cells, columnTypesRef.current);
232
+ // Also ensure count is accurate from the actual cell read
233
+ setCellCount(cells.length);
234
+ setCountReady(true);
235
+ setStats(result);
236
+ });
237
+ }, STATS_DEBOUNCE_MS);
238
+
239
+ return () => {
240
+ cancelled = true;
241
+ globalThis.clearTimeout(countId);
242
+ globalThis.clearTimeout(statsId);
243
+ if (rafId !== 0) {
244
+ cancelAnimationFrame(rafId);
245
+ }
246
+ };
247
+ }, [selectionVersion, gridApiRef]);
248
+
249
+ if (!visible) {
250
+ return undefined;
251
+ }
252
+
253
+ return { cellCount, countReady, stats };
254
+ };
@@ -0,0 +1,397 @@
1
+ /**
2
+ * Copyright (c) 2026-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { type TDSResultCellData, PRIMITIVE_TYPE } from '@finos/legend-graph';
18
+
19
+ export interface ValueFrequency {
20
+ /** String representation of the value, or '(other)' / '(empty)' for synthetic buckets */
21
+ label: string;
22
+ count: number;
23
+ /** True for the synthetic '(other)' bucket */
24
+ isOther?: boolean;
25
+ /** True for the synthetic '(empty)' bucket */
26
+ isEmpty?: boolean;
27
+ }
28
+
29
+ export interface DistributionBucket {
30
+ /** Lower bound of the bucket (inclusive) */
31
+ lower: number;
32
+ /** Upper bound of the bucket (exclusive, except the last which is inclusive) */
33
+ upper: number;
34
+ /** Number of values that fall in this bucket */
35
+ count: number;
36
+ /** For date columns: human-readable label for lower bound */
37
+ lowerDateLabel?: string;
38
+ /** For date columns: human-readable label for upper bound */
39
+ upperDateLabel?: string;
40
+ }
41
+
42
+ /** Discriminates how the chart tooltip should describe bucket bounds */
43
+ export type DistributionChartType = 'numeric' | 'string-length' | 'date';
44
+
45
+ export interface CellSelectionStats {
46
+ count: number;
47
+ uniqueCount: number;
48
+ nullCount: number;
49
+ min: number | undefined;
50
+ max: number | undefined;
51
+ sum: number | undefined;
52
+ avg: number | undefined;
53
+ dateMin: string | undefined;
54
+ dateMax: string | undefined;
55
+ strMinLength: number | undefined;
56
+ strMaxLength: number | undefined;
57
+ /** Frequency distribution histogram buckets.
58
+ * Computed for numeric, string (length), and date columns.
59
+ * undefined for other types. */
60
+ distributionBuckets: DistributionBucket[] | undefined;
61
+ /** Describes what the bucket bounds represent, for tooltip formatting */
62
+ distributionChartType: DistributionChartType | undefined;
63
+ /** Top-10 value frequencies for the Unique Count tooltip, plus optional (other) */
64
+ valueFrequencies: ValueFrequency[] | undefined;
65
+ }
66
+
67
+ const NUMERIC_TYPES = new Set<string>([
68
+ PRIMITIVE_TYPE.INTEGER,
69
+ PRIMITIVE_TYPE.FLOAT,
70
+ PRIMITIVE_TYPE.DECIMAL,
71
+ PRIMITIVE_TYPE.NUMBER,
72
+ ]);
73
+
74
+ const DATE_TYPES = new Set<string>([
75
+ PRIMITIVE_TYPE.DATE,
76
+ PRIMITIVE_TYPE.STRICTDATE,
77
+ PRIMITIVE_TYPE.DATETIME,
78
+ ]);
79
+
80
+ const STRING_TYPES = new Set<string>([PRIMITIVE_TYPE.STRING]);
81
+
82
+ const MAX_BUCKETS = 20;
83
+
84
+ /**
85
+ * Build a frequency-distribution histogram for an array of numeric values.
86
+ * ...existing code...
87
+ */
88
+ const computeDistribution = (values: number[]): DistributionBucket[] => {
89
+ if (values.length === 0) {
90
+ return [];
91
+ }
92
+
93
+ const dataMin = Math.min(...values);
94
+ const dataMax = Math.max(...values);
95
+ const range = dataMax - dataMin;
96
+
97
+ if (range === 0) {
98
+ return [{ lower: dataMin, upper: dataMax, count: values.length }];
99
+ }
100
+
101
+ // Use exact integer buckets when range is small enough
102
+ const allIntegers = values.every((v) => Number.isInteger(v));
103
+ const intRange = dataMax - dataMin + 1;
104
+ let bucketCount: number;
105
+ if (allIntegers && intRange <= MAX_BUCKETS) {
106
+ bucketCount = intRange;
107
+ } else {
108
+ // Sturges' rule, capped at MAX_BUCKETS
109
+ bucketCount = Math.min(
110
+ MAX_BUCKETS,
111
+ Math.ceil(Math.log2(values.length) + 1),
112
+ );
113
+ }
114
+
115
+ const bucketSize = range / bucketCount;
116
+ const buckets: DistributionBucket[] = Array.from(
117
+ { length: bucketCount },
118
+ (_, i) => ({
119
+ lower: dataMin + i * bucketSize,
120
+ upper: dataMin + (i + 1) * bucketSize,
121
+ count: 0,
122
+ }),
123
+ );
124
+
125
+ for (const v of values) {
126
+ const idx = Math.min(
127
+ bucketCount - 1,
128
+ Math.floor((v - dataMin) / bucketSize),
129
+ );
130
+ const bucket = buckets[idx];
131
+ if (bucket) {
132
+ bucket.count += 1;
133
+ }
134
+ }
135
+
136
+ return buckets;
137
+ };
138
+
139
+ /**
140
+ * Format an epoch-ms timestamp back to an ISO date/datetime string.
141
+ * Uses date-only format (YYYY-MM-DD) when the time component is midnight UTC.
142
+ */
143
+ const epochToDateLabel = (epochMs: number): string => {
144
+ const d = new Date(epochMs);
145
+ if (
146
+ d.getUTCHours() === 0 &&
147
+ d.getUTCMinutes() === 0 &&
148
+ d.getUTCSeconds() === 0 &&
149
+ d.getUTCMilliseconds() === 0
150
+ ) {
151
+ return d.toISOString().slice(0, 10);
152
+ }
153
+ return d.toISOString().replace('T', ' ').slice(0, 19);
154
+ };
155
+
156
+ /**
157
+ * Build a frequency-distribution histogram for an array of ISO date strings.
158
+ * Buckets are computed over epoch-ms timestamps; each bucket carries
159
+ * human-readable date labels for tooltip display.
160
+ */
161
+ const computeDateDistribution = (
162
+ dateStrings: string[],
163
+ ): DistributionBucket[] => {
164
+ if (dateStrings.length === 0) {
165
+ return [];
166
+ }
167
+
168
+ const epochs = dateStrings
169
+ .map((s) => Date.parse(s))
170
+ .filter((e) => !Number.isNaN(e));
171
+ if (epochs.length === 0) {
172
+ return [];
173
+ }
174
+
175
+ const raw = computeDistribution(epochs);
176
+ return raw.map((b) => ({
177
+ ...b,
178
+ lowerDateLabel: epochToDateLabel(b.lower),
179
+ upperDateLabel: epochToDateLabel(b.upper),
180
+ }));
181
+ };
182
+
183
+ const MAX_FREQ_ENTRIES = 10;
184
+
185
+ /**
186
+ * Safely convert an unknown value to a string key.
187
+ * Objects are serialised with JSON.stringify to avoid '[object Object]'.
188
+ */
189
+ const valueToString = (v: unknown): string => {
190
+ if (typeof v === 'string') {
191
+ return v;
192
+ }
193
+ if (typeof v === 'number' || typeof v === 'boolean') {
194
+ return String(v);
195
+ }
196
+ if (v === null || v === undefined) {
197
+ return '';
198
+ }
199
+ return JSON.stringify(v);
200
+ };
201
+
202
+ /**
203
+ * Build top-N value frequency list from non-null values.
204
+ * Values beyond the top N are collapsed into a single '(other)' entry.
205
+ * If nullCount > 0, an '(empty)' entry is appended at the end.
206
+ */
207
+ const computeValueFrequencies = (
208
+ nonNullValues: unknown[],
209
+ nullCount: number,
210
+ ): ValueFrequency[] => {
211
+ const freq = new Map<string, number>();
212
+ for (const v of nonNullValues) {
213
+ const key = valueToString(v);
214
+ freq.set(key, (freq.get(key) ?? 0) + 1);
215
+ }
216
+
217
+ const sorted = [...freq.entries()].sort((a, b) => b[1] - a[1]);
218
+ const top = sorted.slice(0, MAX_FREQ_ENTRIES);
219
+ const otherCount = sorted
220
+ .slice(MAX_FREQ_ENTRIES)
221
+ .reduce((s, [, c]) => s + c, 0);
222
+
223
+ const result: ValueFrequency[] = top.map(([label, count]) => ({
224
+ label,
225
+ count,
226
+ }));
227
+ if (otherCount > 0) {
228
+ result.push({ label: '(other)', count: otherCount, isOther: true });
229
+ }
230
+ if (nullCount > 0) {
231
+ result.push({ label: '(empty)', count: nullCount, isEmpty: true });
232
+ }
233
+ return result;
234
+ };
235
+
236
+ // ---------------------------------------------------------------------------
237
+ // Private helpers for computeCellSelectionStats
238
+ // ---------------------------------------------------------------------------
239
+
240
+ type ColumnTypeCategory = 'numeric' | 'date' | 'string' | 'mixed';
241
+
242
+ const classifyColumns = (
243
+ columnNames: Set<string>,
244
+ columnTypes: Map<string, string | undefined>,
245
+ ): ColumnTypeCategory => {
246
+ const isType = (typeSet: Set<string>): boolean =>
247
+ [...columnNames].every((col) => {
248
+ const t = columnTypes.get(col);
249
+ return t !== undefined && typeSet.has(t);
250
+ });
251
+ if (isType(NUMERIC_TYPES)) {
252
+ return 'numeric';
253
+ }
254
+ if (isType(DATE_TYPES)) {
255
+ return 'date';
256
+ }
257
+ if (isType(STRING_TYPES)) {
258
+ return 'string';
259
+ }
260
+ return 'mixed';
261
+ };
262
+
263
+ const buildBaseStats = (
264
+ count: number,
265
+ uniqueCount: number,
266
+ nullCount: number,
267
+ valueFrequencies: ValueFrequency[] | undefined,
268
+ ): CellSelectionStats => ({
269
+ count,
270
+ uniqueCount,
271
+ nullCount,
272
+ min: undefined,
273
+ max: undefined,
274
+ sum: undefined,
275
+ avg: undefined,
276
+ dateMin: undefined,
277
+ dateMax: undefined,
278
+ strMinLength: undefined,
279
+ strMaxLength: undefined,
280
+ distributionBuckets: undefined,
281
+ distributionChartType: undefined,
282
+ valueFrequencies,
283
+ });
284
+
285
+ const computeNumericStats = (
286
+ base: CellSelectionStats,
287
+ selectedCells: TDSResultCellData[],
288
+ valueFrequencies: ValueFrequency[] | undefined,
289
+ ): CellSelectionStats => {
290
+ const numericValues = selectedCells
291
+ .map((c) => {
292
+ if (c.value === null || c.value === undefined || c.value === '') {
293
+ return null;
294
+ }
295
+ const n = Number(c.value);
296
+ return Number.isNaN(n) ? null : n;
297
+ })
298
+ .filter((v): v is number => v !== null);
299
+
300
+ if (numericValues.length === 0) {
301
+ return { ...base, valueFrequencies };
302
+ }
303
+
304
+ const sum = numericValues.reduce((acc, n) => acc + n, 0);
305
+ return {
306
+ ...base,
307
+ min: Math.min(...numericValues),
308
+ max: Math.max(...numericValues),
309
+ sum,
310
+ avg: sum / numericValues.length,
311
+ distributionBuckets: computeDistribution(numericValues),
312
+ distributionChartType: 'numeric',
313
+ valueFrequencies,
314
+ };
315
+ };
316
+
317
+ const computeDateStats = (
318
+ base: CellSelectionStats,
319
+ nonNullValues: unknown[],
320
+ valueFrequencies: ValueFrequency[] | undefined,
321
+ ): CellSelectionStats => {
322
+ const dateValues = nonNullValues.map(String).filter((s) => s.length > 0);
323
+ const sorted = [...dateValues].sort((a, b) => a.localeCompare(b));
324
+ const dateBuckets = computeDateDistribution(dateValues);
325
+ return {
326
+ ...base,
327
+ dateMin: sorted[0],
328
+ dateMax: sorted[sorted.length - 1],
329
+ distributionBuckets: dateBuckets.length >= 2 ? dateBuckets : undefined,
330
+ distributionChartType: dateBuckets.length >= 2 ? 'date' : undefined,
331
+ valueFrequencies,
332
+ };
333
+ };
334
+
335
+ const computeStringStats = (
336
+ base: CellSelectionStats,
337
+ nonNullValues: unknown[],
338
+ valueFrequencies: ValueFrequency[] | undefined,
339
+ ): CellSelectionStats => {
340
+ const lengths = nonNullValues
341
+ .map((v) => valueToString(v).length)
342
+ .filter((l) => l > 0);
343
+ return {
344
+ ...base,
345
+ strMinLength: lengths.length > 0 ? Math.min(...lengths) : undefined,
346
+ strMaxLength: lengths.length > 0 ? Math.max(...lengths) : undefined,
347
+ distributionBuckets:
348
+ lengths.length > 0 ? computeDistribution(lengths) : undefined,
349
+ distributionChartType: lengths.length > 0 ? 'string-length' : undefined,
350
+ valueFrequencies,
351
+ };
352
+ };
353
+
354
+ /**
355
+ * Compute summary statistics for a cell selection.
356
+ * ...existing code...
357
+ */
358
+ export const computeCellSelectionStats = (
359
+ selectedCells: TDSResultCellData[],
360
+ columnTypes: Map<string, string | undefined>,
361
+ ): CellSelectionStats | undefined => {
362
+ if (selectedCells.length < 2) {
363
+ return undefined;
364
+ }
365
+
366
+ const count = selectedCells.length;
367
+
368
+ const nullCount = selectedCells.filter(
369
+ (c) => c.value === null || c.value === undefined || c.value === '',
370
+ ).length;
371
+
372
+ const nonNullValues = selectedCells
373
+ .map((c) => c.value)
374
+ .filter((v) => v !== null && v !== undefined && v !== '');
375
+ const uniqueCount = new Set(nonNullValues).size;
376
+
377
+ const selectedColumnNames = new Set(selectedCells.map((c) => c.columnName));
378
+ const columnTypeCategory = classifyColumns(selectedColumnNames, columnTypes);
379
+
380
+ const valueFrequencies =
381
+ nonNullValues.length > 0 || nullCount > 0
382
+ ? computeValueFrequencies(nonNullValues, nullCount)
383
+ : undefined;
384
+
385
+ const base = buildBaseStats(count, uniqueCount, nullCount, valueFrequencies);
386
+
387
+ if (columnTypeCategory === 'numeric') {
388
+ return computeNumericStats(base, selectedCells, valueFrequencies);
389
+ }
390
+ if (columnTypeCategory === 'date') {
391
+ return computeDateStats(base, nonNullValues, valueFrequencies);
392
+ }
393
+ if (columnTypeCategory === 'string') {
394
+ return computeStringStats(base, nonNullValues, valueFrequencies);
395
+ }
396
+ return base;
397
+ };