@finos/legend-cube-builder 0.0.0-stage → 0.0.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 (379) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +64 -2
  3. package/docs/adding-an-operation.md +92 -0
  4. package/docs/hosting.md +79 -0
  5. package/docs/testing.md +83 -0
  6. package/lib/__lib__/LegendCubeCommand.d.ts +26 -0
  7. package/lib/__lib__/LegendCubeCommand.d.ts.map +1 -0
  8. package/lib/__lib__/LegendCubeCommand.js +40 -0
  9. package/lib/__lib__/LegendCubeCommand.js.map +1 -0
  10. package/lib/__lib__/LegendCubeHelpText.d.ts +19 -0
  11. package/lib/__lib__/LegendCubeHelpText.d.ts.map +1 -0
  12. package/lib/__lib__/LegendCubeHelpText.js +35 -0
  13. package/lib/__lib__/LegendCubeHelpText.js.map +1 -0
  14. package/lib/__lib__/LegendCubeLabels.d.ts +87 -0
  15. package/lib/__lib__/LegendCubeLabels.d.ts.map +1 -0
  16. package/lib/__lib__/LegendCubeLabels.js +128 -0
  17. package/lib/__lib__/LegendCubeLabels.js.map +1 -0
  18. package/lib/__lib__/LegendCubeTesting.d.ts +33 -0
  19. package/lib/__lib__/LegendCubeTesting.d.ts.map +1 -0
  20. package/lib/__lib__/LegendCubeTesting.js +34 -0
  21. package/lib/__lib__/LegendCubeTesting.js.map +1 -0
  22. package/lib/__test-utils__/CubeCanvasTestUtils.d.ts +24 -0
  23. package/lib/__test-utils__/CubeCanvasTestUtils.d.ts.map +1 -0
  24. package/lib/__test-utils__/CubeCanvasTestUtils.js +37 -0
  25. package/lib/__test-utils__/CubeCanvasTestUtils.js.map +1 -0
  26. package/lib/__test-utils__/CubeEngineTestSupport.d.ts +47 -0
  27. package/lib/__test-utils__/CubeEngineTestSupport.d.ts.map +1 -0
  28. package/lib/__test-utils__/CubeEngineTestSupport.js +106 -0
  29. package/lib/__test-utils__/CubeEngineTestSupport.js.map +1 -0
  30. package/lib/__test-utils__/CubeNorthwindTestQueries.d.ts +31 -0
  31. package/lib/__test-utils__/CubeNorthwindTestQueries.d.ts.map +1 -0
  32. package/lib/__test-utils__/CubeNorthwindTestQueries.js +102 -0
  33. package/lib/__test-utils__/CubeNorthwindTestQueries.js.map +1 -0
  34. package/lib/__test-utils__/CubeOperationsTestUtils.d.ts +42 -0
  35. package/lib/__test-utils__/CubeOperationsTestUtils.d.ts.map +1 -0
  36. package/lib/__test-utils__/CubeOperationsTestUtils.js +92 -0
  37. package/lib/__test-utils__/CubeOperationsTestUtils.js.map +1 -0
  38. package/lib/__test-utils__/CubePageTestUtils.d.ts +33 -0
  39. package/lib/__test-utils__/CubePageTestUtils.d.ts.map +1 -0
  40. package/lib/__test-utils__/CubePageTestUtils.js +68 -0
  41. package/lib/__test-utils__/CubePageTestUtils.js.map +1 -0
  42. package/lib/__test-utils__/CubeTestApplication.d.ts +30 -0
  43. package/lib/__test-utils__/CubeTestApplication.d.ts.map +1 -0
  44. package/lib/__test-utils__/CubeTestApplication.js +57 -0
  45. package/lib/__test-utils__/CubeTestApplication.js.map +1 -0
  46. package/lib/__test-utils__/FakeCubeEngine.d.ts +41 -0
  47. package/lib/__test-utils__/FakeCubeEngine.d.ts.map +1 -0
  48. package/lib/__test-utils__/FakeCubeEngine.js +91 -0
  49. package/lib/__test-utils__/FakeCubeEngine.js.map +1 -0
  50. package/lib/components/CubeButton.d.ts +20 -0
  51. package/lib/components/CubeButton.d.ts.map +1 -0
  52. package/lib/components/CubeButton.js +24 -0
  53. package/lib/components/CubeButton.js.map +1 -0
  54. package/lib/components/CubeEditor.d.ts +31 -0
  55. package/lib/components/CubeEditor.d.ts.map +1 -0
  56. package/lib/components/CubeEditor.js +90 -0
  57. package/lib/components/CubeEditor.js.map +1 -0
  58. package/lib/components/CubeNodeIcon.d.ts +23 -0
  59. package/lib/components/CubeNodeIcon.d.ts.map +1 -0
  60. package/lib/components/CubeNodeIcon.js +42 -0
  61. package/lib/components/CubeNodeIcon.js.map +1 -0
  62. package/lib/components/canvas/CubeCanvas.d.ts +37 -0
  63. package/lib/components/canvas/CubeCanvas.d.ts.map +1 -0
  64. package/lib/components/canvas/CubeCanvas.js +137 -0
  65. package/lib/components/canvas/CubeCanvas.js.map +1 -0
  66. package/lib/components/canvas/CubeCanvasContext.d.ts +19 -0
  67. package/lib/components/canvas/CubeCanvasContext.d.ts.map +1 -0
  68. package/lib/components/canvas/CubeCanvasContext.js +22 -0
  69. package/lib/components/canvas/CubeCanvasContext.js.map +1 -0
  70. package/lib/components/canvas/CubeCanvasContextMenu.d.ts +28 -0
  71. package/lib/components/canvas/CubeCanvasContextMenu.d.ts.map +1 -0
  72. package/lib/components/canvas/CubeCanvasContextMenu.js +35 -0
  73. package/lib/components/canvas/CubeCanvasContextMenu.js.map +1 -0
  74. package/lib/components/canvas/CubeCanvasDnd.d.ts +43 -0
  75. package/lib/components/canvas/CubeCanvasDnd.d.ts.map +1 -0
  76. package/lib/components/canvas/CubeCanvasDnd.js +51 -0
  77. package/lib/components/canvas/CubeCanvasDnd.js.map +1 -0
  78. package/lib/components/canvas/CubeCanvasEdge.d.ts +24 -0
  79. package/lib/components/canvas/CubeCanvasEdge.d.ts.map +1 -0
  80. package/lib/components/canvas/CubeCanvasEdge.js +33 -0
  81. package/lib/components/canvas/CubeCanvasEdge.js.map +1 -0
  82. package/lib/components/canvas/CubeCanvasElements.d.ts +66 -0
  83. package/lib/components/canvas/CubeCanvasElements.d.ts.map +1 -0
  84. package/lib/components/canvas/CubeCanvasElements.js +97 -0
  85. package/lib/components/canvas/CubeCanvasElements.js.map +1 -0
  86. package/lib/components/canvas/CubeCanvasLayout.d.ts +32 -0
  87. package/lib/components/canvas/CubeCanvasLayout.d.ts.map +1 -0
  88. package/lib/components/canvas/CubeCanvasLayout.js +63 -0
  89. package/lib/components/canvas/CubeCanvasLayout.js.map +1 -0
  90. package/lib/components/canvas/CubeCanvasNode.d.ts +29 -0
  91. package/lib/components/canvas/CubeCanvasNode.d.ts.map +1 -0
  92. package/lib/components/canvas/CubeCanvasNode.js +75 -0
  93. package/lib/components/canvas/CubeCanvasNode.js.map +1 -0
  94. package/lib/components/editors/CubeColumnPicker.d.ts +47 -0
  95. package/lib/components/editors/CubeColumnPicker.d.ts.map +1 -0
  96. package/lib/components/editors/CubeColumnPicker.js +56 -0
  97. package/lib/components/editors/CubeColumnPicker.js.map +1 -0
  98. package/lib/components/editors/CubeDistinctEditor.d.ts +23 -0
  99. package/lib/components/editors/CubeDistinctEditor.d.ts.map +1 -0
  100. package/lib/components/editors/CubeDistinctEditor.js +24 -0
  101. package/lib/components/editors/CubeDistinctEditor.js.map +1 -0
  102. package/lib/components/editors/CubeFilterEditor.d.ts +26 -0
  103. package/lib/components/editors/CubeFilterEditor.d.ts.map +1 -0
  104. package/lib/components/editors/CubeFilterEditor.js +90 -0
  105. package/lib/components/editors/CubeFilterEditor.js.map +1 -0
  106. package/lib/components/editors/CubeIntegerField.d.ts +29 -0
  107. package/lib/components/editors/CubeIntegerField.d.ts.map +1 -0
  108. package/lib/components/editors/CubeIntegerField.js +30 -0
  109. package/lib/components/editors/CubeIntegerField.js.map +1 -0
  110. package/lib/components/editors/CubeJoinEditor.d.ts +26 -0
  111. package/lib/components/editors/CubeJoinEditor.d.ts.map +1 -0
  112. package/lib/components/editors/CubeJoinEditor.js +84 -0
  113. package/lib/components/editors/CubeJoinEditor.js.map +1 -0
  114. package/lib/components/editors/CubeNodeEditorPanel.d.ts +29 -0
  115. package/lib/components/editors/CubeNodeEditorPanel.d.ts.map +1 -0
  116. package/lib/components/editors/CubeNodeEditorPanel.js +72 -0
  117. package/lib/components/editors/CubeNodeEditorPanel.js.map +1 -0
  118. package/lib/components/editors/CubeNodeEditorRegistry.d.ts +44 -0
  119. package/lib/components/editors/CubeNodeEditorRegistry.d.ts.map +1 -0
  120. package/lib/components/editors/CubeNodeEditorRegistry.js +43 -0
  121. package/lib/components/editors/CubeNodeEditorRegistry.js.map +1 -0
  122. package/lib/components/editors/CubeRenameEditor.d.ts +26 -0
  123. package/lib/components/editors/CubeRenameEditor.d.ts.map +1 -0
  124. package/lib/components/editors/CubeRenameEditor.js +58 -0
  125. package/lib/components/editors/CubeRenameEditor.js.map +1 -0
  126. package/lib/components/editors/CubeRestrictEditor.d.ts +26 -0
  127. package/lib/components/editors/CubeRestrictEditor.d.ts.map +1 -0
  128. package/lib/components/editors/CubeRestrictEditor.js +23 -0
  129. package/lib/components/editors/CubeRestrictEditor.js.map +1 -0
  130. package/lib/components/editors/CubeRowCountEditor.d.ts +25 -0
  131. package/lib/components/editors/CubeRowCountEditor.d.ts.map +1 -0
  132. package/lib/components/editors/CubeRowCountEditor.js +38 -0
  133. package/lib/components/editors/CubeRowCountEditor.js.map +1 -0
  134. package/lib/components/editors/CubeSliceEditor.d.ts +25 -0
  135. package/lib/components/editors/CubeSliceEditor.d.ts.map +1 -0
  136. package/lib/components/editors/CubeSliceEditor.js +40 -0
  137. package/lib/components/editors/CubeSliceEditor.js.map +1 -0
  138. package/lib/components/editors/CubeSortEditor.d.ts +27 -0
  139. package/lib/components/editors/CubeSortEditor.d.ts.map +1 -0
  140. package/lib/components/editors/CubeSortEditor.js +72 -0
  141. package/lib/components/editors/CubeSortEditor.js.map +1 -0
  142. package/lib/components/editors/CubeSourceEditor.d.ts +25 -0
  143. package/lib/components/editors/CubeSourceEditor.d.ts.map +1 -0
  144. package/lib/components/editors/CubeSourceEditor.js +41 -0
  145. package/lib/components/editors/CubeSourceEditor.js.map +1 -0
  146. package/lib/components/editors/CubeValueEditor.d.ts +40 -0
  147. package/lib/components/editors/CubeValueEditor.d.ts.map +1 -0
  148. package/lib/components/editors/CubeValueEditor.js +178 -0
  149. package/lib/components/editors/CubeValueEditor.js.map +1 -0
  150. package/lib/components/grid/CubeGridRegion.d.ts +23 -0
  151. package/lib/components/grid/CubeGridRegion.d.ts.map +1 -0
  152. package/lib/components/grid/CubeGridRegion.js +94 -0
  153. package/lib/components/grid/CubeGridRegion.js.map +1 -0
  154. package/lib/components/grid/CubeGridValues.d.ts +25 -0
  155. package/lib/components/grid/CubeGridValues.d.ts.map +1 -0
  156. package/lib/components/grid/CubeGridValues.js +95 -0
  157. package/lib/components/grid/CubeGridValues.js.map +1 -0
  158. package/lib/components/grid/CubeResultGrid.d.ts +39 -0
  159. package/lib/components/grid/CubeResultGrid.d.ts.map +1 -0
  160. package/lib/components/grid/CubeResultGrid.js +86 -0
  161. package/lib/components/grid/CubeResultGrid.js.map +1 -0
  162. package/lib/components/palette/CubePalette.d.ts +29 -0
  163. package/lib/components/palette/CubePalette.d.ts.map +1 -0
  164. package/lib/components/palette/CubePalette.js +73 -0
  165. package/lib/components/palette/CubePalette.js.map +1 -0
  166. package/lib/components/show-pure/CubeShowPureDialog.d.ts +23 -0
  167. package/lib/components/show-pure/CubeShowPureDialog.d.ts.map +1 -0
  168. package/lib/components/show-pure/CubeShowPureDialog.js +37 -0
  169. package/lib/components/show-pure/CubeShowPureDialog.js.map +1 -0
  170. package/lib/components/source-picker/CubeSourcePicker.d.ts +22 -0
  171. package/lib/components/source-picker/CubeSourcePicker.d.ts.map +1 -0
  172. package/lib/components/source-picker/CubeSourcePicker.js +89 -0
  173. package/lib/components/source-picker/CubeSourcePicker.js.map +1 -0
  174. package/lib/components/spec-transfer/CubeSpecTransferDialog.d.ts +26 -0
  175. package/lib/components/spec-transfer/CubeSpecTransferDialog.d.ts.map +1 -0
  176. package/lib/components/spec-transfer/CubeSpecTransferDialog.js +45 -0
  177. package/lib/components/spec-transfer/CubeSpecTransferDialog.js.map +1 -0
  178. package/lib/graph-manager/CubeEngine.d.ts +128 -0
  179. package/lib/graph-manager/CubeEngine.d.ts.map +1 -0
  180. package/lib/graph-manager/CubeEngine.js +61 -0
  181. package/lib/graph-manager/CubeEngine.js.map +1 -0
  182. package/lib/graph-manager/CubeModelOutlineHelper.d.ts +33 -0
  183. package/lib/graph-manager/CubeModelOutlineHelper.d.ts.map +1 -0
  184. package/lib/graph-manager/CubeModelOutlineHelper.js +45 -0
  185. package/lib/graph-manager/CubeModelOutlineHelper.js.map +1 -0
  186. package/lib/graph-manager/protocol/pure/CubeEngineBuilder.d.ts +26 -0
  187. package/lib/graph-manager/protocol/pure/CubeEngineBuilder.d.ts.map +1 -0
  188. package/lib/graph-manager/protocol/pure/CubeEngineBuilder.js +22 -0
  189. package/lib/graph-manager/protocol/pure/CubeEngineBuilder.js.map +1 -0
  190. package/lib/graph-manager/protocol/pure/v1/V1_CubeEngineErrors.d.ts +27 -0
  191. package/lib/graph-manager/protocol/pure/v1/V1_CubeEngineErrors.d.ts.map +1 -0
  192. package/lib/graph-manager/protocol/pure/v1/V1_CubeEngineErrors.js +76 -0
  193. package/lib/graph-manager/protocol/pure/v1/V1_CubeEngineErrors.js.map +1 -0
  194. package/lib/graph-manager/protocol/pure/v1/V1_CubeExecutionResultReader.d.ts +27 -0
  195. package/lib/graph-manager/protocol/pure/v1/V1_CubeExecutionResultReader.d.ts.map +1 -0
  196. package/lib/graph-manager/protocol/pure/v1/V1_CubeExecutionResultReader.js +82 -0
  197. package/lib/graph-manager/protocol/pure/v1/V1_CubeExecutionResultReader.js.map +1 -0
  198. package/lib/graph-manager/protocol/pure/v1/V1_CubeLambdaSerializer.d.ts +32 -0
  199. package/lib/graph-manager/protocol/pure/v1/V1_CubeLambdaSerializer.d.ts.map +1 -0
  200. package/lib/graph-manager/protocol/pure/v1/V1_CubeLambdaSerializer.js +195 -0
  201. package/lib/graph-manager/protocol/pure/v1/V1_CubeLambdaSerializer.js.map +1 -0
  202. package/lib/graph-manager/protocol/pure/v1/V1_CubeModelOutlineBuilder.d.ts +20 -0
  203. package/lib/graph-manager/protocol/pure/v1/V1_CubeModelOutlineBuilder.d.ts.map +1 -0
  204. package/lib/graph-manager/protocol/pure/v1/V1_CubeModelOutlineBuilder.js +174 -0
  205. package/lib/graph-manager/protocol/pure/v1/V1_CubeModelOutlineBuilder.js.map +1 -0
  206. package/lib/graph-manager/protocol/pure/v1/V1_CubeRelationTypeAdapter.d.ts +24 -0
  207. package/lib/graph-manager/protocol/pure/v1/V1_CubeRelationTypeAdapter.d.ts.map +1 -0
  208. package/lib/graph-manager/protocol/pure/v1/V1_CubeRelationTypeAdapter.js +43 -0
  209. package/lib/graph-manager/protocol/pure/v1/V1_CubeRelationTypeAdapter.js.map +1 -0
  210. package/lib/graph-manager/protocol/pure/v1/V1_LegendCubeEngine.d.ts +45 -0
  211. package/lib/graph-manager/protocol/pure/v1/V1_LegendCubeEngine.d.ts.map +1 -0
  212. package/lib/graph-manager/protocol/pure/v1/V1_LegendCubeEngine.js +171 -0
  213. package/lib/graph-manager/protocol/pure/v1/V1_LegendCubeEngine.js.map +1 -0
  214. package/lib/graph-manager/protocol/pure/v1/__test-utils__/V1_CubeEngineTestUtils.d.ts +22 -0
  215. package/lib/graph-manager/protocol/pure/v1/__test-utils__/V1_CubeEngineTestUtils.d.ts.map +1 -0
  216. package/lib/graph-manager/protocol/pure/v1/__test-utils__/V1_CubeEngineTestUtils.js +79 -0
  217. package/lib/graph-manager/protocol/pure/v1/__test-utils__/V1_CubeEngineTestUtils.js.map +1 -0
  218. package/lib/index.css +17 -0
  219. package/lib/index.css.map +1 -0
  220. package/lib/index.d.ts +25 -0
  221. package/lib/index.d.ts.map +1 -0
  222. package/lib/index.js +24 -0
  223. package/lib/index.js.map +1 -0
  224. package/lib/stores/CubeEditorState.d.ts +236 -0
  225. package/lib/stores/CubeEditorState.d.ts.map +1 -0
  226. package/lib/stores/CubeEditorState.js +632 -0
  227. package/lib/stores/CubeEditorState.js.map +1 -0
  228. package/lib/stores/CubeExecutionState.d.ts +67 -0
  229. package/lib/stores/CubeExecutionState.d.ts.map +1 -0
  230. package/lib/stores/CubeExecutionState.js +212 -0
  231. package/lib/stores/CubeExecutionState.js.map +1 -0
  232. package/lib/stores/CubeGridQuickActions.d.ts +40 -0
  233. package/lib/stores/CubeGridQuickActions.d.ts.map +1 -0
  234. package/lib/stores/CubeGridQuickActions.js +86 -0
  235. package/lib/stores/CubeGridQuickActions.js.map +1 -0
  236. package/lib/stores/CubeHost.d.ts +31 -0
  237. package/lib/stores/CubeHost.d.ts.map +1 -0
  238. package/lib/stores/CubeHost.js +17 -0
  239. package/lib/stores/CubeHost.js.map +1 -0
  240. package/lib/stores/CubeNodeEditorState.d.ts +103 -0
  241. package/lib/stores/CubeNodeEditorState.d.ts.map +1 -0
  242. package/lib/stores/CubeNodeEditorState.js +262 -0
  243. package/lib/stores/CubeNodeEditorState.js.map +1 -0
  244. package/lib/stores/CubeShowPureState.d.ts +41 -0
  245. package/lib/stores/CubeShowPureState.d.ts.map +1 -0
  246. package/lib/stores/CubeShowPureState.js +100 -0
  247. package/lib/stores/CubeShowPureState.js.map +1 -0
  248. package/lib/stores/CubeSourcePickerState.d.ts +98 -0
  249. package/lib/stores/CubeSourcePickerState.d.ts.map +1 -0
  250. package/lib/stores/CubeSourcePickerState.js +334 -0
  251. package/lib/stores/CubeSourcePickerState.js.map +1 -0
  252. package/lib/stores/CubeSpecTransferState.d.ts +60 -0
  253. package/lib/stores/CubeSpecTransferState.d.ts.map +1 -0
  254. package/lib/stores/CubeSpecTransferState.js +167 -0
  255. package/lib/stores/CubeSpecTransferState.js.map +1 -0
  256. package/lib/stores/LocalModelCatalog.d.ts +37 -0
  257. package/lib/stores/LocalModelCatalog.d.ts.map +1 -0
  258. package/lib/stores/LocalModelCatalog.js +49 -0
  259. package/lib/stores/LocalModelCatalog.js.map +1 -0
  260. package/lib/stores/editors/CubeFilterDraft.d.ts +61 -0
  261. package/lib/stores/editors/CubeFilterDraft.d.ts.map +1 -0
  262. package/lib/stores/editors/CubeFilterDraft.js +186 -0
  263. package/lib/stores/editors/CubeFilterDraft.js.map +1 -0
  264. package/lib/stores/editors/CubeIntegerText.d.ts +24 -0
  265. package/lib/stores/editors/CubeIntegerText.d.ts.map +1 -0
  266. package/lib/stores/editors/CubeIntegerText.js +33 -0
  267. package/lib/stores/editors/CubeIntegerText.js.map +1 -0
  268. package/lib/stores/editors/CubeJoinDraft.d.ts +71 -0
  269. package/lib/stores/editors/CubeJoinDraft.d.ts.map +1 -0
  270. package/lib/stores/editors/CubeJoinDraft.js +145 -0
  271. package/lib/stores/editors/CubeJoinDraft.js.map +1 -0
  272. package/lib/stores/editors/CubeNodeDraft.d.ts +38 -0
  273. package/lib/stores/editors/CubeNodeDraft.d.ts.map +1 -0
  274. package/lib/stores/editors/CubeNodeDraft.js +35 -0
  275. package/lib/stores/editors/CubeNodeDraft.js.map +1 -0
  276. package/lib/stores/editors/CubeNodeDraftRegistry.d.ts +35 -0
  277. package/lib/stores/editors/CubeNodeDraftRegistry.d.ts.map +1 -0
  278. package/lib/stores/editors/CubeNodeDraftRegistry.js +55 -0
  279. package/lib/stores/editors/CubeNodeDraftRegistry.js.map +1 -0
  280. package/lib/stores/editors/CubeRenameDraft.d.ts +44 -0
  281. package/lib/stores/editors/CubeRenameDraft.d.ts.map +1 -0
  282. package/lib/stores/editors/CubeRenameDraft.js +79 -0
  283. package/lib/stores/editors/CubeRenameDraft.js.map +1 -0
  284. package/lib/stores/editors/CubeRestrictDraft.d.ts +37 -0
  285. package/lib/stores/editors/CubeRestrictDraft.d.ts.map +1 -0
  286. package/lib/stores/editors/CubeRestrictDraft.js +73 -0
  287. package/lib/stores/editors/CubeRestrictDraft.js.map +1 -0
  288. package/lib/stores/editors/CubeRowCountDraft.d.ts +42 -0
  289. package/lib/stores/editors/CubeRowCountDraft.d.ts.map +1 -0
  290. package/lib/stores/editors/CubeRowCountDraft.js +55 -0
  291. package/lib/stores/editors/CubeRowCountDraft.js.map +1 -0
  292. package/lib/stores/editors/CubeSliceDraft.d.ts +42 -0
  293. package/lib/stores/editors/CubeSliceDraft.d.ts.map +1 -0
  294. package/lib/stores/editors/CubeSliceDraft.js +72 -0
  295. package/lib/stores/editors/CubeSliceDraft.js.map +1 -0
  296. package/lib/stores/editors/CubeSortDraft.d.ts +49 -0
  297. package/lib/stores/editors/CubeSortDraft.d.ts.map +1 -0
  298. package/lib/stores/editors/CubeSortDraft.js +99 -0
  299. package/lib/stores/editors/CubeSortDraft.js.map +1 -0
  300. package/lib/stores/fixtures/CubeNorthwindModel.d.ts +23 -0
  301. package/lib/stores/fixtures/CubeNorthwindModel.d.ts.map +1 -0
  302. package/lib/stores/fixtures/CubeNorthwindModel.js +338 -0
  303. package/lib/stores/fixtures/CubeNorthwindModel.js.map +1 -0
  304. package/package.json +81 -3
  305. package/src/__lib__/LegendCubeCommand.ts +44 -0
  306. package/src/__lib__/LegendCubeHelpText.ts +58 -0
  307. package/src/__lib__/LegendCubeLabels.ts +171 -0
  308. package/src/__lib__/LegendCubeTesting.ts +33 -0
  309. package/src/__test-utils__/CubeCanvasTestUtils.ts +53 -0
  310. package/src/__test-utils__/CubeEngineTestSupport.ts +172 -0
  311. package/src/__test-utils__/CubeNorthwindTestQueries.ts +165 -0
  312. package/src/__test-utils__/CubeOperationsTestUtils.ts +177 -0
  313. package/src/__test-utils__/CubePageTestUtils.tsx +96 -0
  314. package/src/__test-utils__/CubeTestApplication.ts +82 -0
  315. package/src/__test-utils__/FakeCubeEngine.ts +145 -0
  316. package/src/components/CubeButton.tsx +35 -0
  317. package/src/components/CubeEditor.tsx +239 -0
  318. package/src/components/CubeNodeIcon.tsx +64 -0
  319. package/src/components/canvas/CubeCanvas.tsx +262 -0
  320. package/src/components/canvas/CubeCanvasContext.ts +31 -0
  321. package/src/components/canvas/CubeCanvasContextMenu.tsx +89 -0
  322. package/src/components/canvas/CubeCanvasDnd.ts +82 -0
  323. package/src/components/canvas/CubeCanvasEdge.tsx +57 -0
  324. package/src/components/canvas/CubeCanvasElements.ts +153 -0
  325. package/src/components/canvas/CubeCanvasLayout.ts +88 -0
  326. package/src/components/canvas/CubeCanvasNode.tsx +149 -0
  327. package/src/components/editors/CubeColumnPicker.tsx +138 -0
  328. package/src/components/editors/CubeDistinctEditor.tsx +28 -0
  329. package/src/components/editors/CubeFilterEditor.tsx +309 -0
  330. package/src/components/editors/CubeIntegerField.tsx +51 -0
  331. package/src/components/editors/CubeJoinEditor.tsx +247 -0
  332. package/src/components/editors/CubeNodeEditorPanel.tsx +215 -0
  333. package/src/components/editors/CubeNodeEditorRegistry.ts +81 -0
  334. package/src/components/editors/CubeRenameEditor.tsx +143 -0
  335. package/src/components/editors/CubeRestrictEditor.tsx +103 -0
  336. package/src/components/editors/CubeRowCountEditor.tsx +53 -0
  337. package/src/components/editors/CubeSliceEditor.tsx +69 -0
  338. package/src/components/editors/CubeSortEditor.tsx +206 -0
  339. package/src/components/editors/CubeSourceEditor.tsx +106 -0
  340. package/src/components/editors/CubeValueEditor.tsx +333 -0
  341. package/src/components/grid/CubeGridRegion.tsx +275 -0
  342. package/src/components/grid/CubeGridValues.ts +125 -0
  343. package/src/components/grid/CubeResultGrid.tsx +138 -0
  344. package/src/components/palette/CubePalette.tsx +177 -0
  345. package/src/components/show-pure/CubeShowPureDialog.tsx +101 -0
  346. package/src/components/source-picker/CubeSourcePicker.tsx +304 -0
  347. package/src/components/spec-transfer/CubeSpecTransferDialog.tsx +157 -0
  348. package/src/graph-manager/CubeEngine.ts +169 -0
  349. package/src/graph-manager/CubeModelOutlineHelper.ts +58 -0
  350. package/src/graph-manager/protocol/pure/CubeEngineBuilder.ts +34 -0
  351. package/src/graph-manager/protocol/pure/v1/V1_CubeEngineErrors.ts +109 -0
  352. package/src/graph-manager/protocol/pure/v1/V1_CubeExecutionResultReader.ts +115 -0
  353. package/src/graph-manager/protocol/pure/v1/V1_CubeLambdaSerializer.ts +257 -0
  354. package/src/graph-manager/protocol/pure/v1/V1_CubeModelOutlineBuilder.ts +243 -0
  355. package/src/graph-manager/protocol/pure/v1/V1_CubeRelationTypeAdapter.ts +58 -0
  356. package/src/graph-manager/protocol/pure/v1/V1_LegendCubeEngine.ts +278 -0
  357. package/src/graph-manager/protocol/pure/v1/__test-utils__/V1_CubeEngineTestUtils.ts +127 -0
  358. package/src/index.ts +41 -0
  359. package/src/stores/CubeEditorState.ts +807 -0
  360. package/src/stores/CubeExecutionState.ts +288 -0
  361. package/src/stores/CubeGridQuickActions.ts +129 -0
  362. package/src/stores/CubeHost.ts +32 -0
  363. package/src/stores/CubeNodeEditorState.ts +324 -0
  364. package/src/stores/CubeShowPureState.ts +118 -0
  365. package/src/stores/CubeSourcePickerState.ts +426 -0
  366. package/src/stores/CubeSpecTransferState.ts +198 -0
  367. package/src/stores/LocalModelCatalog.ts +70 -0
  368. package/src/stores/editors/CubeFilterDraft.ts +241 -0
  369. package/src/stores/editors/CubeIntegerText.ts +34 -0
  370. package/src/stores/editors/CubeJoinDraft.ts +224 -0
  371. package/src/stores/editors/CubeNodeDraft.ts +46 -0
  372. package/src/stores/editors/CubeNodeDraftRegistry.ts +83 -0
  373. package/src/stores/editors/CubeRenameDraft.ts +110 -0
  374. package/src/stores/editors/CubeRestrictDraft.ts +83 -0
  375. package/src/stores/editors/CubeRowCountDraft.ts +69 -0
  376. package/src/stores/editors/CubeSliceDraft.ts +87 -0
  377. package/src/stores/editors/CubeSortDraft.ts +135 -0
  378. package/src/stores/fixtures/CubeNorthwindModel.ts +355 -0
  379. package/tsconfig.json +133 -0
@@ -0,0 +1,206 @@
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 { ArrowDownIcon, ArrowUpIcon, TimesIcon } from '@finos/legend-art';
18
+ import {
19
+ isSortableType,
20
+ isSortDirection,
21
+ MESSAGE_CANNOT_HAVE_DUPLICATES,
22
+ type Schema,
23
+ type SchemaColumn,
24
+ SORT_DIRECTION_DESCRIPTIONS,
25
+ SORT_DIRECTIONS,
26
+ validateSortKey,
27
+ } from '@finos/legend-cube';
28
+ import { guaranteeType } from '@finos/legend-shared';
29
+ import { observer } from 'mobx-react-lite';
30
+ import { CUBE_SORT_COLUMN_DISABLED_REASON } from '../../__lib__/LegendCubeLabels.js';
31
+ import {
32
+ type CubeSortRow,
33
+ CubeSortDraft,
34
+ } from '../../stores/editors/CubeSortDraft.js';
35
+ import { CubeButton } from '../CubeButton.js';
36
+ import { CubeColumnPicker } from './CubeColumnPicker.js';
37
+ import type { CubeNodeEditorProps } from './CubeNodeEditorRegistry.js';
38
+
39
+ const ROW_BUTTON_CLASS =
40
+ 'flex h-6 w-6 items-center justify-center text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] disabled:text-[var(--color-text-disabled)]';
41
+
42
+ const CubeSortRowEditor = observer(
43
+ (props: {
44
+ draft: CubeSortDraft;
45
+ row: CubeSortRow;
46
+ position: number;
47
+ count: number;
48
+ schema: Schema;
49
+ /** The columns of the other rows, which this row can't take */
50
+ takenColumns: ReadonlySet<string>;
51
+ problem: string | undefined;
52
+ readOnly: boolean;
53
+ }) => {
54
+ const {
55
+ draft,
56
+ row,
57
+ position,
58
+ count,
59
+ schema,
60
+ takenColumns,
61
+ problem,
62
+ readOnly,
63
+ } = props;
64
+ const isColumnDisabled = (column: SchemaColumn): string | undefined =>
65
+ !isSortableType(column.type)
66
+ ? CUBE_SORT_COLUMN_DISABLED_REASON.NOT_SORTABLE
67
+ : takenColumns.has(column.name)
68
+ ? CUBE_SORT_COLUMN_DISABLED_REASON.TAKEN
69
+ : undefined;
70
+ return (
71
+ <li className="flex flex-col gap-1 border-b border-[var(--color-border-subtle)] py-1">
72
+ <div className="grid grid-cols-[1fr_auto_auto_auto_auto] items-center gap-1">
73
+ <CubeColumnPicker
74
+ label={`Sort column ${position}`}
75
+ schema={schema}
76
+ value={row.column}
77
+ disabled={readOnly}
78
+ invalid={problem !== undefined}
79
+ isColumnDisabled={isColumnDisabled}
80
+ onChange={(name) => draft.setColumn(row.key, name)}
81
+ />
82
+ <select
83
+ aria-label={`Sort direction ${position}`}
84
+ className="h-6 rounded-sm border border-[var(--color-border-default)] bg-[var(--color-bg-input)] px-1 text-base"
85
+ value={row.direction}
86
+ disabled={readOnly}
87
+ onChange={(event) => {
88
+ const direction = event.target.value;
89
+ if (isSortDirection(direction)) {
90
+ draft.setDirection(row.key, direction);
91
+ }
92
+ }}
93
+ >
94
+ {SORT_DIRECTIONS.map((direction) => (
95
+ <option key={direction} value={direction}>
96
+ {SORT_DIRECTION_DESCRIPTIONS[direction]}
97
+ </option>
98
+ ))}
99
+ </select>
100
+ <button
101
+ className={ROW_BUTTON_CLASS}
102
+ aria-label={`Move sort column ${position} up`}
103
+ title="Sort by this column before the one above"
104
+ disabled={readOnly || position === 1}
105
+ onClick={() => draft.moveRow(row.key, -1)}
106
+ >
107
+ <ArrowUpIcon />
108
+ </button>
109
+ <button
110
+ className={ROW_BUTTON_CLASS}
111
+ aria-label={`Move sort column ${position} down`}
112
+ title="Sort by this column after the one below"
113
+ disabled={readOnly || position === count}
114
+ onClick={() => draft.moveRow(row.key, 1)}
115
+ >
116
+ <ArrowDownIcon />
117
+ </button>
118
+ <button
119
+ className={ROW_BUTTON_CLASS}
120
+ aria-label={`Remove sort column ${position}`}
121
+ title="Remove this sort column"
122
+ disabled={readOnly}
123
+ onClick={() => draft.removeRow(row.key)}
124
+ >
125
+ <TimesIcon />
126
+ </button>
127
+ </div>
128
+ {problem && (
129
+ <div className="text-sm text-[var(--color-status-error)]">
130
+ {problem}
131
+ </div>
132
+ )}
133
+ </li>
134
+ );
135
+ },
136
+ );
137
+
138
+ /**
139
+ * The Sort editor (spec §17.6: an ordered list of column and direction rows,
140
+ * added, removed and reordered). The first row sorts first. A column that
141
+ * can't be sorted, or that another row has, can't be picked; a saved one
142
+ * stays shown with its problem. The rows scroll on their own, so the editor
143
+ * fits wherever it is shown.
144
+ */
145
+ export const CubeSortEditor = observer((props: CubeNodeEditorProps) => {
146
+ const { readOnly } = props;
147
+ const draft = guaranteeType(props.draft, CubeSortDraft);
148
+ const [schema] = props.inputSchemas as [Schema];
149
+ const { rows } = draft;
150
+ // a row's problem, as the node will judge it; a blank row has none
151
+ const problems = rows.map((row, index) => {
152
+ if (!row.column) {
153
+ return undefined;
154
+ }
155
+ const errors: string[] = [];
156
+ validateSortKey(row, schema, errors);
157
+ return (
158
+ errors[0] ??
159
+ (rows.slice(0, index).some(({ column }) => column === row.column)
160
+ ? MESSAGE_CANNOT_HAVE_DUPLICATES('Sort columns')
161
+ : undefined)
162
+ );
163
+ });
164
+ const sortable = schema.columns.filter((column) =>
165
+ isSortableType(column.type),
166
+ );
167
+ const canAddRow = !readOnly && rows.length < sortable.length;
168
+ return (
169
+ <div className="flex flex-col gap-2 text-base">
170
+ <ul aria-label="Sort columns" className="max-h-80 overflow-auto">
171
+ {rows.map((row, index) => (
172
+ <CubeSortRowEditor
173
+ key={row.key}
174
+ draft={draft}
175
+ row={row}
176
+ position={index + 1}
177
+ count={rows.length}
178
+ schema={schema}
179
+ takenColumns={
180
+ new Set(
181
+ rows
182
+ .filter((other) => other.key !== row.key && other.column)
183
+ .map(({ column }) => column),
184
+ )
185
+ }
186
+ problem={problems[index]}
187
+ readOnly={readOnly}
188
+ />
189
+ ))}
190
+ </ul>
191
+ <div>
192
+ <CubeButton
193
+ title={
194
+ canAddRow
195
+ ? 'Add a column to sort by'
196
+ : 'Every column that can be sorted already has a row'
197
+ }
198
+ disabled={!canAddRow}
199
+ onClick={() => draft.addRow()}
200
+ >
201
+ Add sort column
202
+ </CubeButton>
203
+ </div>
204
+ </div>
205
+ );
206
+ });
@@ -0,0 +1,106 @@
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 { PanelLoadingIndicator } from '@finos/legend-art';
18
+ import {
19
+ getRelationalDisplayName,
20
+ RelationalTableSource,
21
+ } from '@finos/legend-cube';
22
+ import { guaranteeType } from '@finos/legend-shared';
23
+ import { flowResult } from 'mobx';
24
+ import { observer } from 'mobx-react-lite';
25
+ import {
26
+ CUBE_PENDING_LABEL,
27
+ getColumnTypeLabel,
28
+ } from '../../__lib__/LegendCubeLabels.js';
29
+ import { CubeButton } from '../CubeButton.js';
30
+ import { CubeColumnTypeIcon } from './CubeColumnPicker.js';
31
+ import type { CubeNodeEditorProps } from './CubeNodeEditorRegistry.js';
32
+
33
+ /**
34
+ * A table source (spec §17.6): where it reads from, its columns as the engine
35
+ * typed them, and Refresh, which types the table again. Nothing here is
36
+ * edited, so a refresh is no undo step.
37
+ */
38
+ export const CubeSourceEditor = observer((props: CubeNodeEditorProps) => {
39
+ const { editorState } = props;
40
+ const source = guaranteeType(props.draft.original, RelationalTableSource);
41
+ const refreshing = editorState.isPendingSource(source);
42
+ const { resolution } = source;
43
+ return (
44
+ <div className="relative flex flex-col gap-2">
45
+ <dl className="grid grid-cols-[max-content_1fr] gap-x-3 gap-y-1 text-base">
46
+ <dt className="text-[var(--color-text-secondary)]">Database</dt>
47
+ <dd className="min-w-0 break-all">{source.database}</dd>
48
+ <dt className="text-[var(--color-text-secondary)]">Schema</dt>
49
+ <dd>{getRelationalDisplayName(source.schema)}</dd>
50
+ <dt className="text-[var(--color-text-secondary)]">Table</dt>
51
+ <dd>{getRelationalDisplayName(source.table)}</dd>
52
+ </dl>
53
+ <div className="flex items-center gap-2">
54
+ <CubeButton
55
+ title="Type the table again with the engine, e.g. after its columns changed"
56
+ disabled={refreshing}
57
+ onClick={() => {
58
+ flowResult(editorState.refreshSource(source.id)).catch(
59
+ editorState.host.applicationStore.alertUnhandledError,
60
+ );
61
+ }}
62
+ >
63
+ Refresh
64
+ </CubeButton>
65
+ {refreshing && (
66
+ <span className="text-base text-[var(--color-text-secondary)]">
67
+ {CUBE_PENDING_LABEL.REFRESHING_SOURCE}
68
+ </span>
69
+ )}
70
+ </div>
71
+ <PanelLoadingIndicator isLoading={refreshing} />
72
+ {resolution.kind === 'resolved' ? (
73
+ <table className="w-full text-base" aria-label="Columns">
74
+ <thead>
75
+ <tr className="text-left text-[var(--color-text-secondary)]">
76
+ <th className="font-normal">Column</th>
77
+ <th className="font-normal">Type</th>
78
+ </tr>
79
+ </thead>
80
+ <tbody>
81
+ {resolution.schema.columns.map((column) => (
82
+ <tr key={column.name}>
83
+ <td className="break-all pr-2">{column.name}</td>
84
+ <td title={column.type.fullName}>
85
+ <span className="flex items-center gap-1">
86
+ <CubeColumnTypeIcon
87
+ type={column.type}
88
+ className="text-[var(--color-text-secondary)]"
89
+ />
90
+ {getColumnTypeLabel(column)}
91
+ </span>
92
+ </td>
93
+ </tr>
94
+ ))}
95
+ </tbody>
96
+ </table>
97
+ ) : (
98
+ <div className="text-base text-[var(--color-text-secondary)]">
99
+ {resolution.kind === 'failed'
100
+ ? resolution.message
101
+ : 'The table has not been typed yet.'}
102
+ </div>
103
+ )}
104
+ </div>
105
+ );
106
+ });
@@ -0,0 +1,333 @@
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 { clsx, TimesIcon } from '@finos/legend-art';
18
+ import {
19
+ BLANK_PLACEHOLDER,
20
+ checkValue,
21
+ type CubeType,
22
+ type FilterValue,
23
+ type FilterValueItem,
24
+ type FilterValueShape,
25
+ getLiteralText,
26
+ isEnumType,
27
+ isFilterValueList,
28
+ MESSAGE_FILTER_VALUE_INVALID,
29
+ MESSAGE_FILTER_VALUE_OUT_OF_RANGE,
30
+ parseValue,
31
+ TypeFamily,
32
+ } from '@finos/legend-cube';
33
+ import { useEffect, useRef, useState } from 'react';
34
+
35
+ /** Why a value is not one of the type, worded as the validation says it; nothing for a valid one or none */
36
+ export const getValueProblem = (
37
+ item: FilterValueItem | undefined,
38
+ type: CubeType,
39
+ ): string | undefined => {
40
+ const problem = checkValue(item, type);
41
+ if (!problem || problem.reason === 'required') {
42
+ return undefined;
43
+ }
44
+ return problem.reason === 'invalid'
45
+ ? MESSAGE_FILTER_VALUE_INVALID(problem.text, type.displayName)
46
+ : MESSAGE_FILTER_VALUE_OUT_OF_RANGE(problem.text, type.displayName);
47
+ };
48
+
49
+ /** A value as typed and shown: a literal's text, or the text that is not a value */
50
+ const getItemText = (item: FilterValueItem | undefined): string =>
51
+ item === undefined
52
+ ? ''
53
+ : item.kind === 'invalid'
54
+ ? item.text
55
+ : getLiteralText(item);
56
+
57
+ const INPUT_CLASS =
58
+ 'h-6 min-w-0 flex-1 rounded-sm border bg-[var(--color-bg-input)] px-1 text-base';
59
+
60
+ const DATE_TIME_WITHOUT_SECONDS = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/u;
61
+
62
+ /**
63
+ * The text a date-time input gives, with its seconds: a browser leaves out
64
+ * zero seconds (`1997-01-01T10:30`), and the engine truncates a date-time
65
+ * without them
66
+ */
67
+ export const withDateTimeSeconds = (text: string): string =>
68
+ DATE_TIME_WITHOUT_SECONDS.test(text) ? `${text}:00` : text;
69
+
70
+ /** The input a type's values are typed in (spec §17.7) */
71
+ const getInputType = (type: CubeType): string =>
72
+ type.family === TypeFamily.STRICT_DATE
73
+ ? 'date'
74
+ : type.family === TypeFamily.DATETIME
75
+ ? 'datetime-local'
76
+ : 'text';
77
+
78
+ /**
79
+ * Picks one of a fixed set of values, never typed: an enumeration's values,
80
+ * or true and false. A value that is not one of them (e.g. after the column
81
+ * changed) stays shown, marked.
82
+ */
83
+ const CubeValueSelect: React.FC<{
84
+ label: string;
85
+ type: CubeType;
86
+ item: FilterValueItem | undefined;
87
+ onChange: (item: FilterValueItem | undefined) => void;
88
+ disabled: boolean;
89
+ }> = (props) => {
90
+ const { label, type, item, onChange, disabled } = props;
91
+ const choices = isEnumType(type) ? type.values : ['true', 'false'];
92
+ const text = getItemText(item);
93
+ const problem = getValueProblem(item, type);
94
+ return (
95
+ <select
96
+ aria-label={label}
97
+ aria-invalid={problem !== undefined}
98
+ title={problem}
99
+ className={clsx(
100
+ INPUT_CLASS,
101
+ problem
102
+ ? 'border-[var(--color-status-error)]'
103
+ : 'border-[var(--color-border-default)]',
104
+ )}
105
+ value={text}
106
+ disabled={disabled}
107
+ onChange={(event) => onChange(parseValue(event.target.value, type))}
108
+ >
109
+ <option value="">{BLANK_PLACEHOLDER}</option>
110
+ {text && !choices.includes(text) && (
111
+ <option value={text} disabled={true}>
112
+ {text}
113
+ </option>
114
+ )}
115
+ {choices.map((choice) => (
116
+ <option key={choice} value={choice}>
117
+ {choice}
118
+ </option>
119
+ ))}
120
+ </select>
121
+ );
122
+ };
123
+
124
+ /**
125
+ * One typed value (spec §17.7): shown as text, or `(blank)`, until clicked;
126
+ * then typed, and read when the input loses focus or on Enter. Text that is
127
+ * not a value of the type is kept, to be fixed, and marked in both modes.
128
+ * Leaving a blank value without typing keeps it blank; Enter on it confirms
129
+ * an empty text, a value of a STRING column. Enter and Escape give the focus
130
+ * back to the value; leaving it by focus leaves the focus where it went.
131
+ */
132
+ const CubeValueText: React.FC<{
133
+ label: string;
134
+ type: CubeType;
135
+ item: FilterValueItem | undefined;
136
+ onChange: (item: FilterValueItem | undefined) => void;
137
+ disabled: boolean;
138
+ }> = (props) => {
139
+ const { label, type, item, onChange, disabled } = props;
140
+ const [editedText, setEditedText] = useState<string | undefined>(undefined);
141
+ const [returnFocus, setReturnFocus] = useState(false);
142
+ const inputRef = useRef<HTMLInputElement>(null);
143
+ /** Enter and Escape, as the input being typed handles them now */
144
+ const onKeyRef = useRef<(key: string) => void>(() => undefined);
145
+ const isTyping = editedText !== undefined;
146
+ // a native listener: Chrome's date input gives React no Enter keydown
147
+ useEffect(() => {
148
+ const input = inputRef.current;
149
+ if (!isTyping || !input) {
150
+ return undefined;
151
+ }
152
+ const onKeyDown = (event: KeyboardEvent): void => {
153
+ if (event.key === 'Enter' || event.key === 'Escape') {
154
+ // or the key's press would reach the value it gives the focus to,
155
+ // and open it again
156
+ event.preventDefault();
157
+ onKeyRef.current(event.key);
158
+ }
159
+ };
160
+ input.addEventListener('keydown', onKeyDown);
161
+ return () => input.removeEventListener('keydown', onKeyDown);
162
+ }, [isTyping]);
163
+ const text = getItemText(item);
164
+ const problem = getValueProblem(item, type);
165
+ const markClass = problem
166
+ ? 'border-[var(--color-status-error)] text-[var(--color-status-error)]'
167
+ : 'border-[var(--color-border-default)]';
168
+ if (editedText === undefined) {
169
+ return (
170
+ <button
171
+ aria-label={label}
172
+ aria-invalid={problem !== undefined}
173
+ title={problem ?? 'Click to change'}
174
+ className={clsx(INPUT_CLASS, 'truncate text-left', markClass, {
175
+ 'text-[var(--color-text-muted)]': item === undefined,
176
+ })}
177
+ disabled={disabled}
178
+ // back from typing with Enter or Escape
179
+ autoFocus={returnFocus}
180
+ onClick={() => setEditedText(text)}
181
+ >
182
+ {item === undefined
183
+ ? BLANK_PLACEHOLDER
184
+ : item.kind === 'string' && !item.value
185
+ ? '""'
186
+ : text}
187
+ </button>
188
+ );
189
+ }
190
+ const commit = (confirmed: boolean): void => {
191
+ setEditedText(undefined);
192
+ const typed =
193
+ type.family === TypeFamily.DATETIME
194
+ ? withDateTimeSeconds(editedText)
195
+ : editedText;
196
+ if (
197
+ typed !== text ||
198
+ (confirmed && item === undefined && type.family === TypeFamily.STRING)
199
+ ) {
200
+ onChange(parseValue(typed, type));
201
+ }
202
+ };
203
+ onKeyRef.current = (key: string): void => {
204
+ if (key === 'Enter') {
205
+ setReturnFocus(true);
206
+ commit(true);
207
+ } else if (key === 'Escape') {
208
+ setReturnFocus(true);
209
+ setEditedText(undefined);
210
+ }
211
+ };
212
+ return (
213
+ <input
214
+ aria-label={label}
215
+ aria-invalid={problem !== undefined}
216
+ title={problem}
217
+ className={clsx(INPUT_CLASS, markClass)}
218
+ type={getInputType(type)}
219
+ // seconds are needed: the engine truncates a date-time without them
220
+ step={type.family === TypeFamily.DATETIME ? 1 : undefined}
221
+ // the input replaces the button the user just clicked
222
+ autoFocus={true}
223
+ value={editedText}
224
+ onChange={(event) => setEditedText(event.target.value)}
225
+ ref={inputRef}
226
+ onBlur={() => {
227
+ setReturnFocus(false);
228
+ commit(false);
229
+ }}
230
+ />
231
+ );
232
+ };
233
+
234
+ /** One value of a column type, picked or typed as the type wants */
235
+ const CubeSingleValueEditor: React.FC<{
236
+ label: string;
237
+ type: CubeType;
238
+ item: FilterValueItem | undefined;
239
+ onChange: (item: FilterValueItem | undefined) => void;
240
+ disabled: boolean;
241
+ }> = (props) =>
242
+ props.type.family === TypeFamily.ENUM ||
243
+ props.type.family === TypeFamily.BOOLEAN ? (
244
+ <CubeValueSelect {...props} />
245
+ ) : (
246
+ <CubeValueText {...props} />
247
+ );
248
+
249
+ /**
250
+ * The value of a condition, as its operator wants it (spec §17.7): none,
251
+ * one, or a list (In and NotIn), each value entered as its column's type
252
+ * wants (`parseValue`): a date input for dates, a picker for an enumeration
253
+ * or a boolean, text for the rest.
254
+ */
255
+ export const CubeValueEditor: React.FC<{
256
+ /** What the value is for: the editor's accessible name, e.g. `Filter value` */
257
+ label: string;
258
+ type: CubeType;
259
+ shape: FilterValueShape;
260
+ value: FilterValue | undefined;
261
+ onChange: (value: FilterValue | undefined) => void;
262
+ disabled?: boolean | undefined;
263
+ }> = (props) => {
264
+ const { label, type, shape, value, onChange } = props;
265
+ const disabled = Boolean(props.disabled);
266
+ if (shape === 'none') {
267
+ return null;
268
+ }
269
+ if (shape === 'single') {
270
+ return (
271
+ <CubeSingleValueEditor
272
+ label={label}
273
+ type={type}
274
+ item={isFilterValueList(value) ? undefined : value}
275
+ onChange={onChange}
276
+ disabled={disabled}
277
+ />
278
+ );
279
+ }
280
+ const items = isFilterValueList(value) ? value : value ? [value] : [];
281
+ const setItems = (next: readonly FilterValueItem[]): void =>
282
+ onChange(next.length ? next : undefined);
283
+ return (
284
+ <ul aria-label={label} className="flex min-w-0 flex-1 flex-col gap-1">
285
+ {items.map((item, index) => (
286
+ // values can repeat and have no id. A row's only state is its text
287
+ // while typed, which blur commits before another row can be removed
288
+ // eslint-disable-next-line react/no-array-index-key
289
+ <li key={index} className="flex items-center gap-1">
290
+ <CubeSingleValueEditor
291
+ label={`${label} ${index + 1}`}
292
+ type={type}
293
+ item={item}
294
+ disabled={disabled}
295
+ onChange={(changed) =>
296
+ setItems(
297
+ changed === undefined
298
+ ? items.filter((_, other) => other !== index)
299
+ : items.map((other, position) =>
300
+ position === index ? changed : other,
301
+ ),
302
+ )
303
+ }
304
+ />
305
+ <button
306
+ className="flex h-6 w-6 shrink-0 items-center justify-center text-[var(--color-text-secondary)] disabled:text-[var(--color-text-disabled)]"
307
+ aria-label={`Remove ${label.toLowerCase()} ${index + 1}`}
308
+ disabled={disabled}
309
+ onClick={() =>
310
+ setItems(items.filter((_, other) => other !== index))
311
+ }
312
+ >
313
+ <TimesIcon />
314
+ </button>
315
+ </li>
316
+ ))}
317
+ <li className="flex items-center gap-1">
318
+ <CubeSingleValueEditor
319
+ // always blank: what it adds goes to the list above
320
+ label={`Add ${label.toLowerCase()}`}
321
+ type={type}
322
+ item={undefined}
323
+ disabled={disabled}
324
+ onChange={(added) => {
325
+ if (added !== undefined) {
326
+ setItems([...items, added]);
327
+ }
328
+ }}
329
+ />
330
+ </li>
331
+ </ul>
332
+ );
333
+ };