@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,82 @@
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 { CubeEditorState } from '../../stores/CubeEditorState.js';
18
+
19
+ // Drag and drop on the canvas (spec §17.3): palette items and nodes are
20
+ // dragged; nodes and the canvas take drops. The app's HTML5 backend provider
21
+ // wraps every Legend application, so Cube mounts none of its own.
22
+
23
+ export enum CUBE_DND_TYPE {
24
+ PALETTE_ITEM = 'legend-cube.palette-item',
25
+ NODE = 'legend-cube.node',
26
+ }
27
+
28
+ /** A palette item carries the type of node it adds */
29
+ export interface CubePaletteDragItem {
30
+ readonly nodeType: string;
31
+ }
32
+
33
+ /** A node carries only its id */
34
+ export interface CubeNodeDragItem {
35
+ readonly nodeId: string;
36
+ }
37
+
38
+ export type CubeDragItem = CubePaletteDragItem | CubeNodeDragItem;
39
+
40
+ const isNodeDragItem = (item: CubeDragItem): item is CubeNodeDragItem =>
41
+ 'nodeId' in item;
42
+
43
+ /**
44
+ * Whether dropping the item on the node does anything, which also decides
45
+ * whether the node lights up under it: a palette item is spliced in after
46
+ * the node, another node connects to it or else moves after it
47
+ */
48
+ export const canDropOnCubeNode = (
49
+ editorState: CubeEditorState,
50
+ item: CubeDragItem,
51
+ targetId: string,
52
+ ): boolean =>
53
+ isNodeDragItem(item)
54
+ ? editorState.canDropNode(item.nodeId, targetId)
55
+ : editorState.canAddNode(item.nodeType, targetId);
56
+
57
+ export const dropOnCubeNode = (
58
+ editorState: CubeEditorState,
59
+ item: CubeDragItem,
60
+ targetId: string,
61
+ ): void => {
62
+ if (isNodeDragItem(item)) {
63
+ editorState.dropNode(item.nodeId, targetId);
64
+ } else {
65
+ editorState.addNode(item.nodeType, targetId);
66
+ }
67
+ };
68
+
69
+ /**
70
+ * A palette item dropped on the canvas around the nodes: a transform is
71
+ * added unconnected, a source opens the picker. A drop on a node is the
72
+ * node's, taken or refused, never the canvas's.
73
+ */
74
+ export const dropOnCubeCanvas = (
75
+ editorState: CubeEditorState,
76
+ item: CubeDragItem,
77
+ isOverNode: boolean,
78
+ ): void => {
79
+ if (!isOverNode && !isNodeDragItem(item)) {
80
+ editorState.addNode(item.nodeType);
81
+ }
82
+ };
@@ -0,0 +1,57 @@
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 {
18
+ BaseEdge,
19
+ EdgeLabelRenderer,
20
+ type EdgeProps,
21
+ getBezierPath,
22
+ } from '@xyflow/react';
23
+ import { LEGEND_CUBE_TEST_ID } from '../../__lib__/LegendCubeTesting.js';
24
+ import type { CubeCanvasFlowEdge } from './CubeCanvasElements.js';
25
+
26
+ /** The gap between an input's label and the node it feeds */
27
+ const LABEL_GAP = 6;
28
+
29
+ /**
30
+ * A connection, with its port's label (Left or Right on a Join) shown as text
31
+ * beside the input it feeds, not in a tooltip (spec §17.3). The label is HTML:
32
+ * React Flow's own edge label measures SVG text, which jsdom can't.
33
+ */
34
+ export const CubeCanvasEdge: React.FC<EdgeProps<CubeCanvasFlowEdge>> = (
35
+ props,
36
+ ) => {
37
+ const { id, targetX, targetY, markerEnd, data } = props;
38
+ const [path] = getBezierPath(props);
39
+ return (
40
+ <>
41
+ <BaseEdge id={id} path={path} markerEnd={markerEnd} />
42
+ {data?.label && (
43
+ <EdgeLabelRenderer>
44
+ <div
45
+ className="absolute rounded bg-[var(--color-bg-panel)] px-1 text-sm text-[var(--color-text-secondary)]"
46
+ style={{
47
+ transform: `translate(-100%, -100%) translate(${targetX - LABEL_GAP}px, ${targetY - 2}px)`,
48
+ }}
49
+ data-testid={LEGEND_CUBE_TEST_ID.CANVAS_EDGE_LABEL}
50
+ >
51
+ {data.label}
52
+ </div>
53
+ </EdgeLabelRenderer>
54
+ )}
55
+ </>
56
+ );
57
+ };
@@ -0,0 +1,153 @@
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 {
18
+ isIncompleteError,
19
+ isSchemasError,
20
+ type Query,
21
+ type QueryNode,
22
+ } from '@finos/legend-cube';
23
+ import { type Edge, MarkerType, type Node, Position } from '@xyflow/react';
24
+ import type { CubeEditorState } from '../../stores/CubeEditorState.js';
25
+ import {
26
+ CUBE_CANVAS_NODE_HEIGHT,
27
+ CUBE_CANVAS_NODE_WIDTH,
28
+ type CubeCanvasPosition,
29
+ } from './CubeCanvasLayout.js';
30
+
31
+ // The query as React Flow draws it: one node per query node, one edge per
32
+ // connection. Rebuilt from the query on every change; React Flow keeps no
33
+ // state of its own that matters (PLAN §7.2)
34
+
35
+ export const CUBE_CANVAS_NODE_TYPE = 'cube';
36
+ export const CUBE_CANVAS_EDGE_TYPE = 'cube';
37
+ /** The one output of every node; its inputs are named by its ports */
38
+ export const CUBE_OUTPUT_HANDLE_ID = 'output';
39
+
40
+ /** Shown when a node has no validity entry at all, which inference never leaves out */
41
+ export const MISSING_VALIDITY_TOOLTIP =
42
+ 'This node depends on some invalid inputs.';
43
+
44
+ export type CubeCanvasNodeData = { readonly node: QueryNode };
45
+ export type CubeCanvasEdgeData = { readonly label: string | undefined };
46
+ export type CubeCanvasFlowNode = Node<CubeCanvasNodeData, 'cube'>;
47
+ export type CubeCanvasFlowEdge = Edge<CubeCanvasEdgeData, 'cube'>;
48
+ type CubeCanvasHandle = NonNullable<Node['handles']>[number];
49
+
50
+ /** How far down the node's left side each input handle sits: evenly spaced, in port order */
51
+ export const getInputHandleOffset = (index: number, count: number): number =>
52
+ (CUBE_CANVAS_NODE_HEIGHT * (index + 1)) / (count + 1);
53
+
54
+ /**
55
+ * Where the node's handles are, so edges are drawn without measuring the DOM:
56
+ * its inputs down its left side in port order (a Join's Left above its
57
+ * Right), its output in the middle of its right side. New objects each time:
58
+ * React Flow writes into them.
59
+ */
60
+ export const getCubeCanvasHandles = (node: QueryNode): CubeCanvasHandle[] => [
61
+ ...node.ports.map((port, index) => ({
62
+ id: port,
63
+ type: 'target' as const,
64
+ position: Position.Left,
65
+ x: 0,
66
+ y: getInputHandleOffset(index, node.ports.length),
67
+ })),
68
+ {
69
+ id: CUBE_OUTPUT_HANDLE_ID,
70
+ type: 'source' as const,
71
+ position: Position.Right,
72
+ x: CUBE_CANVAS_NODE_WIDTH,
73
+ y: CUBE_CANVAS_NODE_HEIGHT / 2,
74
+ },
75
+ ];
76
+
77
+ export const buildCubeCanvasNodes = (
78
+ query: Query,
79
+ positions: ReadonlyMap<string, CubeCanvasPosition>,
80
+ ): CubeCanvasFlowNode[] =>
81
+ query.nodes.map((node) => ({
82
+ id: node.id,
83
+ type: CUBE_CANVAS_NODE_TYPE,
84
+ position: { ...(positions.get(node.id) ?? { x: 0, y: 0 }) },
85
+ width: CUBE_CANVAS_NODE_WIDTH,
86
+ height: CUBE_CANVAS_NODE_HEIGHT,
87
+ handles: getCubeCanvasHandles(node),
88
+ data: { node },
89
+ }));
90
+
91
+ /** Each connection, labelled with its port's label when the target has one, e.g. Left and Right on a Join */
92
+ export const buildCubeCanvasEdges = (query: Query): CubeCanvasFlowEdge[] =>
93
+ query.connections.map((connection) => {
94
+ const target = query.getNode(connection.target);
95
+ const label = target?.portLabels[target.ports.indexOf(connection.port)];
96
+ return {
97
+ id: connection.toString(),
98
+ type: CUBE_CANVAS_EDGE_TYPE,
99
+ source: connection.source,
100
+ target: connection.target,
101
+ sourceHandle: CUBE_OUTPUT_HANDLE_ID,
102
+ targetHandle: connection.port,
103
+ markerEnd: { type: MarkerType.ArrowClosed },
104
+ data: { label },
105
+ };
106
+ });
107
+
108
+ /** How a node looks on the canvas (spec §17.3): each state is its own class modifier */
109
+ export interface CubeCanvasNodeStatus {
110
+ /** Execute runs the query up to this node */
111
+ readonly isCapture: boolean;
112
+ /** It has errors of its own, the query rules' included; not the engine's */
113
+ readonly isInvalid: boolean;
114
+ /** An input is missing, or an input is invalid */
115
+ readonly isIncomplete: boolean;
116
+ /** The engine is typing its table */
117
+ readonly isResolving: boolean;
118
+ /** The last run failed on it */
119
+ readonly hasEngineError: boolean;
120
+ /** It has a warning, stored (a table that changed) or derived (a lost sort order) */
121
+ readonly hasWarnings: boolean;
122
+ /** Its errors, then its warnings, its description and its id, one a line */
123
+ readonly tooltip: string;
124
+ }
125
+
126
+ export const getCubeCanvasNodeStatus = (
127
+ editorState: CubeEditorState,
128
+ node: QueryNode,
129
+ ): CubeCanvasNodeStatus => {
130
+ const ownErrors = editorState.analysis.validity.get(node.id);
131
+ // the tooltip adds the engine's error; the states keep it apart
132
+ const errors = editorState.getNodeErrors(node.id);
133
+ const warnings = editorState.getNodeWarnings(node);
134
+ return {
135
+ isCapture: editorState.document.query.selected === node.id,
136
+ isInvalid: (ownErrors ?? []).some(
137
+ (error) => !isIncompleteError(error) && !isSchemasError(error),
138
+ ),
139
+ isIncomplete: (ownErrors ?? []).some(
140
+ (error) => isIncompleteError(error) || isSchemasError(error),
141
+ ),
142
+ isResolving: editorState.isPendingSource(node),
143
+ hasEngineError: editorState.hostIssues.has(node.id),
144
+ hasWarnings: warnings.length > 0,
145
+ tooltip: [
146
+ ...(ownErrors ? [] : [MISSING_VALIDITY_TOOLTIP]),
147
+ ...errors,
148
+ ...warnings,
149
+ node.describe(),
150
+ node.id,
151
+ ].join('\n'),
152
+ };
153
+ };
@@ -0,0 +1,88 @@
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 dagre from '@dagrejs/dagre';
18
+ import type { Connection, Query } from '@finos/legend-cube';
19
+
20
+ /** Every node is drawn this size, so edges need no DOM measurement (PLAN §7.2) */
21
+ export const CUBE_CANVAS_NODE_WIDTH = 200;
22
+ export const CUBE_CANVAS_NODE_HEIGHT = 72;
23
+
24
+ const RANK_SEPARATION = 80;
25
+ const NODE_SEPARATION = 32;
26
+
27
+ /** A node's top-left corner on the canvas */
28
+ export interface CubeCanvasPosition {
29
+ readonly x: number;
30
+ readonly y: number;
31
+ }
32
+
33
+ // by code unit, so the order never depends on the locale
34
+ const compareText = (a: string, b: string): number =>
35
+ a < b ? -1 : a > b ? 1 : 0;
36
+
37
+ const compareConnections = (a: Connection, b: Connection): number =>
38
+ compareText(a.port, b.port) ||
39
+ compareText(a.source, b.source) ||
40
+ compareText(a.target, b.target);
41
+
42
+ /**
43
+ * Where each node goes, laid out left to right (spec §17.3): a pure function
44
+ * of the query, recomputed on every change, so undo, import and every edit
45
+ * need no layout state. Nodes go in sorted by id and connections by port,
46
+ * source and target, so an edit that only reorders them moves nothing.
47
+ */
48
+ export const layoutCubeQuery = (
49
+ query: Query,
50
+ ): Map<string, CubeCanvasPosition> => {
51
+ const graph = new dagre.graphlib.Graph<{
52
+ width: number;
53
+ height: number;
54
+ }>({ multigraph: true });
55
+ graph.setGraph({
56
+ rankdir: 'LR',
57
+ ranksep: RANK_SEPARATION,
58
+ nodesep: NODE_SEPARATION,
59
+ });
60
+ graph.setDefaultEdgeLabel(() => ({}));
61
+ [...query.nodes]
62
+ .sort((a, b) => compareText(a.id, b.id))
63
+ .forEach((node) =>
64
+ graph.setNode(node.id, {
65
+ width: CUBE_CANVAS_NODE_WIDTH,
66
+ height: CUBE_CANVAS_NODE_HEIGHT,
67
+ }),
68
+ );
69
+ [...query.connections]
70
+ .sort(compareConnections)
71
+ .forEach((connection) =>
72
+ graph.setEdge(connection.source, connection.target, {}, connection.port),
73
+ );
74
+ dagre.layout(graph);
75
+ return new Map(
76
+ query.nodes.map((node) => {
77
+ // dagre gives each node's centre
78
+ const { x, y } = graph.node(node.id);
79
+ return [
80
+ node.id,
81
+ {
82
+ x: x - CUBE_CANVAS_NODE_WIDTH / 2,
83
+ y: y - CUBE_CANVAS_NODE_HEIGHT / 2,
84
+ },
85
+ ];
86
+ }),
87
+ );
88
+ };
@@ -0,0 +1,149 @@
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, ContextMenu, WarningIcon } from '@finos/legend-art';
18
+ import { Handle, type NodeProps, Position } from '@xyflow/react';
19
+ import { observer } from 'mobx-react-lite';
20
+ import { useRef } from 'react';
21
+ import { useDrag, useDrop } from 'react-dnd';
22
+ import { LEGEND_CUBE_TEST_ID } from '../../__lib__/LegendCubeTesting.js';
23
+ import { CubeNodeIcon } from '../CubeNodeIcon.js';
24
+ import {
25
+ CUBE_OUTPUT_HANDLE_ID,
26
+ type CubeCanvasFlowNode,
27
+ getCubeCanvasNodeStatus,
28
+ getInputHandleOffset,
29
+ } from './CubeCanvasElements.js';
30
+ import { useCubeCanvasEditorState } from './CubeCanvasContext.js';
31
+ import { CubeCanvasContextMenu } from './CubeCanvasContextMenu.js';
32
+ import {
33
+ canDropOnCubeNode,
34
+ CUBE_DND_TYPE,
35
+ type CubeDragItem,
36
+ type CubeNodeDragItem,
37
+ dropOnCubeNode,
38
+ } from './CubeCanvasDnd.js';
39
+
40
+ /**
41
+ * A node on the canvas: its type's icon and its description, never its id,
42
+ * which is in the tooltip (spec §17.3). Its look tells its state at a glance.
43
+ * It can be dragged onto another node, and takes palette items and other
44
+ * nodes, lighting up only for a drop that would do something. Its handles
45
+ * sit beside its draggable body, not in it, so dragging from a handle
46
+ * connects rather than drags the node.
47
+ */
48
+ export const CubeCanvasNode = observer(
49
+ (props: NodeProps<CubeCanvasFlowNode>) => {
50
+ const { node } = props.data;
51
+ const editorState = useCubeCanvasEditorState();
52
+ const status = getCubeCanvasNodeStatus(editorState, node);
53
+ const connectable = !editorState.readOnly && node.acceptsNewInputs;
54
+ const ref = useRef<HTMLDivElement>(null);
55
+ const [, dragConnector] = useDrag<CubeNodeDragItem>(
56
+ () => ({
57
+ type: CUBE_DND_TYPE.NODE,
58
+ item: { nodeId: node.id },
59
+ canDrag: () => !editorState.readOnly,
60
+ }),
61
+ [editorState, node.id],
62
+ );
63
+ const [{ isDropTarget }, dropConnector] = useDrop<
64
+ CubeDragItem,
65
+ void,
66
+ { isDropTarget: boolean }
67
+ >(
68
+ () => ({
69
+ accept: [CUBE_DND_TYPE.NODE, CUBE_DND_TYPE.PALETTE_ITEM],
70
+ canDrop: (item) => canDropOnCubeNode(editorState, item, node.id),
71
+ drop: (item) => dropOnCubeNode(editorState, item, node.id),
72
+ collect: (monitor) => ({
73
+ isDropTarget: monitor.isOver({ shallow: true }) && monitor.canDrop(),
74
+ }),
75
+ }),
76
+ [editorState, node.id],
77
+ );
78
+ dragConnector(dropConnector(ref));
79
+ return (
80
+ <ContextMenu
81
+ className="h-full w-full"
82
+ content={
83
+ <CubeCanvasContextMenu editorState={editorState} nodeId={node.id} />
84
+ }
85
+ menuProps={{ elevation: 7 }}
86
+ >
87
+ {node.ports.map((port, index) => (
88
+ <Handle
89
+ key={port}
90
+ id={port}
91
+ type="target"
92
+ position={Position.Left}
93
+ isConnectable={connectable}
94
+ style={{ top: getInputHandleOffset(index, node.ports.length) }}
95
+ />
96
+ ))}
97
+ <div
98
+ ref={ref}
99
+ className={clsx(
100
+ // React Flow must leave the mouse to the HTML drag: 'nodrag' keeps
101
+ // it from moving the node, 'nopan' from panning the canvas
102
+ 'legend-cube__node nodrag nopan flex h-full w-full items-center gap-2 rounded border bg-[var(--color-bg-panel)] px-2 text-base text-[var(--color-text-primary)]',
103
+ status.isInvalid
104
+ ? 'border-[var(--color-status-error)]'
105
+ : status.isIncomplete
106
+ ? 'border-dashed border-[var(--color-status-warn)]'
107
+ : 'border-[var(--color-border-default)]',
108
+ {
109
+ 'legend-cube__node--selected ring-2 ring-[var(--color-accent)]':
110
+ status.isCapture,
111
+ 'legend-cube__node--invalid': status.isInvalid,
112
+ 'legend-cube__node--incomplete': status.isIncomplete,
113
+ 'legend-cube__node--resolving animate-pulse': status.isResolving,
114
+ 'legend-cube__node--engine-error bg-[var(--color-status-error-bg)]':
115
+ status.hasEngineError,
116
+ 'legend-cube__node--warning': status.hasWarnings,
117
+ 'legend-cube__node--drop-target outline-dashed outline-2 outline-[var(--color-accent)]':
118
+ isDropTarget,
119
+ },
120
+ )}
121
+ title={status.tooltip}
122
+ aria-current={status.isCapture}
123
+ data-testid={LEGEND_CUBE_TEST_ID.CANVAS_NODE}
124
+ >
125
+ <CubeNodeIcon
126
+ icon={editorState.registry.get(node.type)?.icon}
127
+ className="shrink-0 text-lg text-[var(--color-text-secondary)]"
128
+ />
129
+ <span className="line-clamp-2 min-w-0 break-words leading-tight">
130
+ {node.describe()}
131
+ </span>
132
+ {status.hasWarnings && (
133
+ // the warning's text is in the node's tooltip
134
+ <WarningIcon
135
+ className="ml-auto shrink-0 text-[var(--color-status-warn)]"
136
+ aria-hidden={true}
137
+ />
138
+ )}
139
+ </div>
140
+ <Handle
141
+ id={CUBE_OUTPUT_HANDLE_ID}
142
+ type="source"
143
+ position={Position.Right}
144
+ isConnectable={!editorState.readOnly}
145
+ />
146
+ </ContextMenu>
147
+ );
148
+ },
149
+ );
@@ -0,0 +1,138 @@
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 {
18
+ CalendarIcon,
19
+ clsx,
20
+ HashtagIcon,
21
+ ListIcon,
22
+ QuestionIcon,
23
+ StringTypeIcon,
24
+ ToggleIcon,
25
+ } from '@finos/legend-art';
26
+ import {
27
+ type CubeType,
28
+ type Schema,
29
+ type SchemaColumn,
30
+ TypeFamily,
31
+ } from '@finos/legend-cube';
32
+ import { getColumnTypeLabel } from '../../__lib__/LegendCubeLabels.js';
33
+
34
+ const FAMILY_ICONS: Readonly<
35
+ Partial<Record<TypeFamily, React.FC<{ className?: string }>>>
36
+ > = {
37
+ [TypeFamily.STRING]: StringTypeIcon,
38
+ [TypeFamily.BOOLEAN]: ToggleIcon,
39
+ [TypeFamily.INTEGER]: HashtagIcon,
40
+ [TypeFamily.FLOAT]: HashtagIcon,
41
+ [TypeFamily.DECIMAL]: HashtagIcon,
42
+ [TypeFamily.NUMBER]: HashtagIcon,
43
+ [TypeFamily.STRICT_DATE]: CalendarIcon,
44
+ [TypeFamily.DATETIME]: CalendarIcon,
45
+ [TypeFamily.DATE]: CalendarIcon,
46
+ [TypeFamily.ENUM]: ListIcon,
47
+ };
48
+
49
+ /** The icon of a column type's family: text, number, date, ...; a question mark for the rest */
50
+ export const CubeColumnTypeIcon: React.FC<{
51
+ type: CubeType;
52
+ className?: string;
53
+ }> = (props) => {
54
+ const Icon = FAMILY_ICONS[props.type.family] ?? QuestionIcon;
55
+ return <Icon className={clsx('shrink-0', props.className)} />;
56
+ };
57
+
58
+ /**
59
+ * Picks a column of an input schema, in schema order (spec §17.5: only the
60
+ * columns of the actual input). Each option names its type, e.g.
61
+ * `CUSTOMER_ID: Varchar(5)?`; the picked column's type shows beside, with
62
+ * its family's icon and its full type in the tooltip. A column the input
63
+ * doesn't have stays shown, so the problem can be seen and fixed. A column
64
+ * the editor can't take here is shown, with the reason `isColumnDisabled`
65
+ * gives after its type, but can't be picked.
66
+ */
67
+ export const CubeColumnPicker: React.FC<{
68
+ /** What the column is for, e.g. `Left join column 1`: the picker's accessible name */
69
+ label: string;
70
+ schema: Schema;
71
+ /** The picked column's name, `''` or `undefined` for none */
72
+ value: string | undefined;
73
+ onChange: (columnName: string) => void;
74
+ disabled?: boolean | undefined;
75
+ /** Marks the pick as wrong, e.g. a type that doesn't match */
76
+ invalid?: boolean | undefined;
77
+ /**
78
+ * Why a column can't be picked, shown after its type, e.g. a Sort's Variant
79
+ * column, or one another row has; `undefined` when it can be
80
+ */
81
+ isColumnDisabled?: ((column: SchemaColumn) => string | undefined) | undefined;
82
+ }> = (props) => {
83
+ const {
84
+ label,
85
+ schema,
86
+ value,
87
+ onChange,
88
+ disabled,
89
+ invalid,
90
+ isColumnDisabled,
91
+ } = props;
92
+ const picked = value ? schema.lookup(value) : undefined;
93
+ return (
94
+ <div className="flex min-w-0 items-center gap-1">
95
+ <select
96
+ aria-label={label}
97
+ aria-invalid={Boolean(invalid) || (Boolean(value) && !picked)}
98
+ className={clsx(
99
+ 'h-6 min-w-0 flex-1 rounded-sm border bg-[var(--color-bg-input)] px-1 text-base',
100
+ invalid || (value && !picked)
101
+ ? 'border-[var(--color-status-error)]'
102
+ : 'border-[var(--color-border-default)]',
103
+ )}
104
+ value={value ?? ''}
105
+ disabled={disabled}
106
+ onChange={(event) => onChange(event.target.value)}
107
+ >
108
+ {!picked && (
109
+ <option value={value ?? ''} disabled={true}>
110
+ {value ? `${value} (not in the input)` : 'Pick a column'}
111
+ </option>
112
+ )}
113
+ {schema.columns.map((column) => {
114
+ const reason = isColumnDisabled?.(column);
115
+ return (
116
+ <option
117
+ key={column.name}
118
+ value={column.name}
119
+ title={column.type.fullName}
120
+ disabled={reason !== undefined}
121
+ >
122
+ {`${column.name}: ${getColumnTypeLabel(column)}${reason === undefined ? '' : ` (${reason})`}`}
123
+ </option>
124
+ );
125
+ })}
126
+ </select>
127
+ {picked && (
128
+ <span
129
+ className="flex shrink-0 items-center gap-1 text-sm text-[var(--color-text-secondary)]"
130
+ title={picked.type.fullName}
131
+ >
132
+ <CubeColumnTypeIcon type={picked.type} />
133
+ {getColumnTypeLabel(picked)}
134
+ </span>
135
+ )}
136
+ </div>
137
+ );
138
+ };
@@ -0,0 +1,28 @@
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 { observer } from 'mobx-react-lite';
18
+ import { DISTINCT_EDITOR_TEXT } from '../../__lib__/LegendCubeLabels.js';
19
+
20
+ /**
21
+ * The Distinct editor (spec §17.6: "nothing — description only"). Distinct
22
+ * has no settings, so it has no draft, and the panel shows no Apply or Cancel.
23
+ */
24
+ export const CubeDistinctEditor = observer(() => (
25
+ <div className="text-base text-[var(--color-text-secondary)]">
26
+ {DISTINCT_EDITOR_TEXT}
27
+ </div>
28
+ ));