@elyra/canvas 12.41.0 → 12.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/dist/{_baseIteratee-05ccf6a8.js → _baseIteratee-148093b7.js} +3 -3
  2. package/dist/{_baseIteratee-05ccf6a8.js.map → _baseIteratee-148093b7.js.map} +1 -1
  3. package/dist/{canvas-constants-079172c0.js → canvas-constants-acb99f64.js} +2 -2
  4. package/dist/{canvas-constants-079172c0.js.map → canvas-constants-acb99f64.js.map} +1 -1
  5. package/dist/canvas-controller-6726b9ac.js +2 -0
  6. package/dist/canvas-controller-6726b9ac.js.map +1 -0
  7. package/dist/canvas-controller-6c6bc68f.js +2 -0
  8. package/dist/canvas-controller-6c6bc68f.js.map +1 -0
  9. package/dist/common-canvas-9374ef35.js +2 -0
  10. package/dist/common-canvas-9374ef35.js.map +1 -0
  11. package/dist/common-canvas-a6435bdb.js +2 -0
  12. package/dist/common-canvas-a6435bdb.js.map +1 -0
  13. package/dist/common-canvas.es.js +1 -1
  14. package/dist/common-canvas.es.js.map +1 -1
  15. package/dist/common-canvas.js +1 -1
  16. package/dist/common-canvas.js.map +1 -1
  17. package/dist/common-properties-08707efe.js +2 -0
  18. package/dist/common-properties-08707efe.js.map +1 -0
  19. package/dist/common-properties-acd55e94.js +2 -0
  20. package/dist/common-properties-acd55e94.js.map +1 -0
  21. package/dist/context-menu-wrapper-271eb2df.js +2 -0
  22. package/dist/context-menu-wrapper-271eb2df.js.map +1 -0
  23. package/dist/context-menu-wrapper-e4a7ab4d.js +2 -0
  24. package/dist/context-menu-wrapper-e4a7ab4d.js.map +1 -0
  25. package/dist/{datarecord-metadata-v3-schema-59505bc5.js → datarecord-metadata-v3-schema-03427296.js} +2 -2
  26. package/dist/{datarecord-metadata-v3-schema-59505bc5.js.map → datarecord-metadata-v3-schema-03427296.js.map} +1 -1
  27. package/dist/{flexible-table-63ffd573.js → flexible-table-107ca2fd.js} +1 -1
  28. package/dist/{flexible-table-63ffd573.js.map → flexible-table-107ca2fd.js.map} +1 -1
  29. package/dist/{flexible-table-43e2d052.js → flexible-table-5cc1ad6b.js} +2 -2
  30. package/dist/{flexible-table-43e2d052.js.map → flexible-table-5cc1ad6b.js.map} +1 -1
  31. package/dist/{icon-0390f1fe.js → icon-2caf035c.js} +2 -2
  32. package/dist/{icon-0390f1fe.js.map → icon-2caf035c.js.map} +1 -1
  33. package/dist/{index-57503b50.js → index-5dac3da8.js} +2 -2
  34. package/dist/{index-57503b50.js.map → index-5dac3da8.js.map} +1 -1
  35. package/dist/{index-1cd54914.js → index-fee06179.js} +2 -2
  36. package/dist/{index-1cd54914.js.map → index-fee06179.js.map} +1 -1
  37. package/dist/{isArrayLikeObject-36898fcb.js → isArrayLikeObject-7a30aa4b.js} +2 -2
  38. package/dist/{isArrayLikeObject-36898fcb.js.map → isArrayLikeObject-7a30aa4b.js.map} +1 -1
  39. package/dist/lib/canvas-controller.es.js +1 -1
  40. package/dist/lib/canvas-controller.js +1 -1
  41. package/dist/lib/canvas.es.js +1 -1
  42. package/dist/lib/canvas.js +1 -1
  43. package/dist/lib/context-menu.es.js +1 -1
  44. package/dist/lib/context-menu.js +1 -1
  45. package/dist/lib/properties/clem.es.js +2 -0
  46. package/dist/lib/properties/clem.es.js.map +1 -0
  47. package/dist/lib/properties/clem.js +2 -0
  48. package/dist/lib/properties/clem.js.map +1 -0
  49. package/dist/lib/properties/field-picker.es.js +1 -1
  50. package/dist/lib/properties/field-picker.js +1 -1
  51. package/dist/lib/properties/flexible-table.es.js +1 -1
  52. package/dist/lib/properties/flexible-table.js +1 -1
  53. package/dist/lib/properties/getPythonHints.es.js +2 -0
  54. package/dist/lib/properties/getPythonHints.es.js.map +1 -0
  55. package/dist/lib/properties/getPythonHints.js +2 -0
  56. package/dist/lib/properties/getPythonHints.js.map +1 -0
  57. package/dist/lib/properties.es.js +1 -1
  58. package/dist/lib/properties.js +1 -1
  59. package/dist/lib/tooltip.es.js +1 -1
  60. package/dist/lib/tooltip.es.js.map +1 -1
  61. package/dist/lib/tooltip.js +1 -1
  62. package/dist/lib/tooltip.js.map +1 -1
  63. package/dist/styles/common-canvas.min.css +1 -1
  64. package/dist/styles/common-canvas.min.css.map +1 -1
  65. package/dist/toolbar-ccc1d600.js +2 -0
  66. package/dist/toolbar-ccc1d600.js.map +1 -0
  67. package/dist/toolbar-e4445bf8.js +2 -0
  68. package/dist/toolbar-e4445bf8.js.map +1 -0
  69. package/package.json +12 -4
  70. package/rollup.config.js +2 -0
  71. package/src/color-picker/color-picker.jsx +96 -17
  72. package/src/command-actions/arrangeLayoutAction.js +7 -6
  73. package/src/command-actions/attachNodeToLinksAction.js +4 -4
  74. package/src/command-actions/collapseSuperNodeInPlaceAction.js +5 -5
  75. package/src/command-actions/colorSelectedObjectsAction.js +4 -4
  76. package/src/command-actions/commonPropertiesAction.js +1 -1
  77. package/src/command-actions/convertSuperNodeExternalToLocalAction.js +4 -4
  78. package/src/command-actions/convertSuperNodeLocalToExternalAction.js +4 -4
  79. package/src/command-actions/createAutoNodeAction.js +14 -5
  80. package/src/command-actions/createCommentAction.js +4 -10
  81. package/src/command-actions/createCommentLinkAction.js +4 -4
  82. package/src/command-actions/createNodeAction.js +13 -4
  83. package/src/command-actions/createNodeAttachLinksAction.js +4 -4
  84. package/src/command-actions/createNodeLinkAction.js +13 -4
  85. package/src/command-actions/createNodeLinkDetachedAction.js +4 -4
  86. package/src/command-actions/createNodeOnLinkAction.js +4 -4
  87. package/src/command-actions/createSuperNodeAction.js +7 -7
  88. package/src/command-actions/deconstructSuperNodeAction.js +5 -5
  89. package/src/command-actions/deleteLinkAction.js +4 -4
  90. package/src/command-actions/deleteObjectsAction.js +15 -6
  91. package/src/command-actions/disconnectObjectsAction.js +13 -4
  92. package/src/command-actions/displayPreviousPipelineAction.js +4 -4
  93. package/src/command-actions/displaySubPipelineAction.js +4 -4
  94. package/src/command-actions/editCommentAction.js +4 -4
  95. package/src/command-actions/editDecorationLabelAction.js +4 -4
  96. package/src/command-actions/expandSuperNodeInPlaceAction.js +5 -5
  97. package/src/command-actions/insertNodeIntoLinkAction.js +4 -4
  98. package/src/command-actions/moveObjectsAction.js +4 -4
  99. package/src/command-actions/pasteAction.js +16 -7
  100. package/src/command-actions/saveToPaletteAction.js +4 -4
  101. package/src/command-actions/setLinksStyleAction.js +4 -4
  102. package/src/command-actions/setNodeLabelAction.js +4 -4
  103. package/src/command-actions/setObjectsStyleAction.js +4 -4
  104. package/src/command-actions/sizeAndPositionObjectsAction.js +4 -4
  105. package/src/command-actions/updateLinkAction.js +4 -4
  106. package/src/common-canvas/canvas-controller-menu-utils.js +1 -1
  107. package/src/common-canvas/canvas-controller.js +116 -62
  108. package/src/common-canvas/cc-central-items.jsx +1 -5
  109. package/src/common-canvas/cc-context-toolbar.jsx +9 -13
  110. package/src/common-canvas/cc-toolbar.jsx +28 -9
  111. package/src/common-canvas/common-canvas.scss +3 -3
  112. package/src/common-canvas/svg-canvas-d3.scss +3 -2
  113. package/src/common-canvas/svg-canvas-renderer.js +50 -23
  114. package/src/common-canvas/svg-canvas-utils-drag-det-link.js +8 -1
  115. package/src/common-canvas/svg-canvas-utils-drag-new-link.js +1 -1
  116. package/src/common-properties/components/field-picker/field-picker.jsx +4 -0
  117. package/src/common-properties/components/table-buttons/table-buttons.scss +0 -1
  118. package/src/common-properties/controls/checkbox/checkbox.scss +0 -1
  119. package/src/common-properties/controls/expression/expression-builder/expression-builder.jsx +32 -26
  120. package/src/common-properties/controls/expression/expression.jsx +143 -116
  121. package/src/common-properties/controls/expression/expression.scss +43 -45
  122. package/src/common-properties/controls/expression/languages/CLEM-hint.js +86 -159
  123. package/src/common-properties/controls/expression/languages/python-hint.js +41 -104
  124. package/src/common-properties/controls/expression/languages/r-hint.js +61 -128
  125. package/src/common-properties/index.js +4 -2
  126. package/src/common-properties/properties-controller.js +5 -0
  127. package/src/context-menu/common-context-menu.jsx +4 -1
  128. package/src/index.js +14 -4
  129. package/src/notification-panel/notification-panel.jsx +82 -56
  130. package/src/notification-panel/notification-panel.scss +42 -40
  131. package/src/object-model/object-model.js +19 -5
  132. package/src/object-model/redux/canvas-store.js +4 -3
  133. package/src/object-model/redux/reducers/canvasinfo.js +7 -11
  134. package/src/object-model/redux/reducers/canvastoolbar.js +5 -6
  135. package/src/palette/palette-dialog-topbar.jsx +27 -38
  136. package/src/palette/palette-flyout-content-category.jsx +25 -6
  137. package/src/palette/palette.scss +8 -40
  138. package/src/toolbar/{toolbar-utils.js → index.js} +3 -18
  139. package/src/toolbar/toolbar-action-item.jsx +122 -316
  140. package/src/toolbar/toolbar-button-item.jsx +381 -0
  141. package/src/toolbar/toolbar-divider-item.jsx +4 -5
  142. package/src/toolbar/toolbar-overflow-item.jsx +85 -37
  143. package/src/toolbar/toolbar-sub-menu-item.jsx +236 -0
  144. package/src/toolbar/toolbar-sub-menu.jsx +252 -0
  145. package/src/toolbar/toolbar-sub-panel.jsx +94 -0
  146. package/src/toolbar/toolbar-sub-utils.js +86 -0
  147. package/src/toolbar/toolbar.jsx +386 -148
  148. package/src/toolbar/toolbar.scss +63 -56
  149. package/src/tooltip/tooltip.jsx +65 -12
  150. package/stats.html +1 -1
  151. package/assets/images/palette/close_32.svg +0 -1
  152. package/assets/images/palette/palette_close.svg +0 -4
  153. package/assets/images/palette/palette_grid_deselected.svg +0 -2
  154. package/assets/images/palette/palette_grid_hover.svg +0 -2
  155. package/assets/images/palette/palette_grid_selected.svg +0 -2
  156. package/assets/images/palette/palette_list_deselected.svg +0 -1
  157. package/assets/images/palette/palette_list_hover.svg +0 -1
  158. package/assets/images/palette/palette_list_selected.svg +0 -1
  159. package/assets/images/palette/palette_open.svg +0 -4
  160. package/assets/images/zoom_to_fit.svg +0 -8
  161. package/dist/canvas-controller-1e71b405.js +0 -2
  162. package/dist/canvas-controller-1e71b405.js.map +0 -1
  163. package/dist/canvas-controller-4bed5320.js +0 -2
  164. package/dist/canvas-controller-4bed5320.js.map +0 -1
  165. package/dist/common-canvas-097c5169.js +0 -2
  166. package/dist/common-canvas-097c5169.js.map +0 -1
  167. package/dist/common-canvas-e13c0858.js +0 -2
  168. package/dist/common-canvas-e13c0858.js.map +0 -1
  169. package/dist/common-properties-706cef87.js +0 -2
  170. package/dist/common-properties-706cef87.js.map +0 -1
  171. package/dist/common-properties-9bd69b61.js +0 -2
  172. package/dist/common-properties-9bd69b61.js.map +0 -1
  173. package/dist/context-menu-wrapper-3a7fdec8.js +0 -2
  174. package/dist/context-menu-wrapper-3a7fdec8.js.map +0 -1
  175. package/dist/context-menu-wrapper-fc85d853.js +0 -2
  176. package/dist/context-menu-wrapper-fc85d853.js.map +0 -1
  177. package/dist/toolbar-918ab52e.js +0 -2
  178. package/dist/toolbar-918ab52e.js.map +0 -1
  179. package/dist/toolbar-fdb750f9.js +0 -2
  180. package/dist/toolbar-fdb750f9.js.map +0 -1
  181. package/src/palette/palette-dialog-topbar-three-way-icon.jsx +0 -82
  182. package/src/toolbar/toolbar-action-sub-area.jsx +0 -126
  183. package/src/toolbar/toolbar-overflow-menu.jsx +0 -77
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2017-2023 Elyra Authors
2
+ * Copyright 2017-2024 Elyra Authors
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -19,11 +19,10 @@
19
19
  import React from "react";
20
20
  import PropTypes from "prop-types";
21
21
  import { connect } from "react-redux";
22
- import { UnControlled as CodeMirror } from "react-codemirror2";
23
22
  import Icon from "./../../../icons/icon.jsx";
24
23
  import { Button } from "carbon-components-react";
25
24
  import classNames from "classnames";
26
- import { isEqual } from "lodash";
25
+ import { isEqual, concat } from "lodash";
27
26
  import ValidationMessage from "./../../components/validation-message";
28
27
  import WideFlyout from "./../../components/wide-flyout";
29
28
  import { formatMessage } from "./../../util/property-utils";
@@ -35,76 +34,66 @@ import { STATES } from "./../../constants/constants";
35
34
  import { get } from "lodash";
36
35
  import ExpressionToggle from "./expression-toggle/expression-toggle";
37
36
 
38
- import { register as registerPython } from "./languages/python-hint";
39
- import { register as registerR } from "./languages/r-hint";
40
- import { register as registerClem } from "./languages/CLEM-hint";
41
-
42
- // required for server side rendering.
43
- let cm = null;
44
- if (typeof window !== "undefined" && typeof window.navigator !== "undefined") {
45
- cm = require("codemirror");
46
- require("codemirror/addon/hint/show-hint");
47
- require("codemirror/addon/display/placeholder");
48
- require("codemirror/addon/display/autorefresh");
49
- require("codemirror/mode/javascript/javascript");
50
- require("codemirror/addon/hint/javascript-hint");
51
- require("codemirror/addon/hint/sql-hint");
52
- require("codemirror/mode/sql/sql");
53
- require("codemirror/mode/python/python");
54
- require("codemirror/mode/r/r");
55
- registerPython(cm);
56
- registerR(cm);
57
- registerClem(cm);
58
- }
37
+ import { keymap, placeholder } from "@codemirror/view";
38
+ import { defaultKeymap, indentWithTab, insertNewline } from "@codemirror/commands";
39
+ import { basicSetup, EditorView } from "codemirror";
40
+ import { Compartment } from "@codemirror/state";
41
+ import { tags } from "@lezer/highlight";
42
+ import { HighlightStyle, syntaxHighlighting } from "@codemirror/language";
43
+ import { python } from "@codemirror/lang-python";
44
+ import { sql } from "@codemirror/lang-sql";
45
+ import { javascript } from "@codemirror/lang-javascript";
59
46
 
47
+ import { getPythonHints } from "./languages/python-hint";
48
+ import { rLanguage } from "./languages/r-hint";
49
+ import { clem } from "./languages/CLEM-hint";
60
50
 
61
51
  const pxPerChar = 8.5;
62
52
  const pxPerLine = 26;
63
53
  const defaultCharPerLine = 30;
64
54
  const maxLineHeight = 15 * pxPerLine; // 20 lines
65
55
  const minLineHeight = 4 * pxPerLine; // 4 lines
66
-
67
56
  class ExpressionControl extends React.Component {
68
57
  constructor(props) {
69
58
  super(props);
70
59
  this.state = {
71
60
  showExpressionBuilder: false,
72
- validationInProgress: false
61
+ validationInProgress: false,
62
+ expressionEditorHeight: 0
73
63
  };
74
-
75
- this.origHint = "";
64
+ this.editable = new Compartment; // eslint-disable-line new-parens
65
+ this.editorRef = React.createRef();
66
+ this.origHint = [];
76
67
  this.expressionInfo = this.props.controller.getExpressionInfo();
77
68
  this.handleValidate = this.handleValidate.bind(this);
78
69
  this.hasValidate = this.hasValidate.bind(this);
79
70
  this.cancelExpressionBuilder = this.cancelExpressionBuilder.bind(this);
80
71
  this.hideExpressionBuilder = this.hideExpressionBuilder.bind(this);
81
72
  this.showExpressionBuilder = this.showExpressionBuilder.bind(this);
82
- this.editorDidMount = this.editorDidMount.bind(this);
83
73
  this.addonHints = this.addonHints.bind(this);
84
74
  this.getDatasetFields = this.getDatasetFields.bind(this);
85
75
  this.handleBlur = this.handleBlur.bind(this);
86
- this.handleKeyDown = this.handleKeyDown.bind(this);
87
-
88
- this.handleChange = (editor, data, newValue) => {
89
- // this is needed when characters are added into the expression builder because
90
- // entering chars does not go through onChange() in expression builder.
91
- // This is needed to adjust the selection position in code mirror.
92
- if (Array.isArray(data.text) && data.text.length === 1 && data.text[0].length === 1 && this.props.onSelectionChange) {
93
- // if a string was replaced, need to calc newPos from the 'data.from' otherwise use 'data.to'
94
- const newPos = (data.removed[0].length > 0) ? { line: data.from.line, ch: data.from.ch + 1 } : { line: data.to.line, ch: data.to.ch + 1 };
95
- this.props.onSelectionChange([{ anchor: newPos, head: newPos }]);
96
- }
97
- if (this.state.validateIcon) {
98
- this.setState({
99
- validateIcon: null
100
- });
101
- this.props.controller.updateErrorMessage(this.props.propertyId, DEFAULT_VALIDATION_MESSAGE);
102
- }
103
- };
76
+ this.createCodeMirrorEditor = this.createCodeMirrorEditor.bind(this);
77
+ this.events = this.events.bind(this);
78
+ this.handleUpdate = this.handleUpdate.bind(this);
79
+ this.setCodeMirrorEditable = this.setCodeMirrorEditable.bind(this);
80
+ this.getCodemirrorState = this.getCodemirrorState.bind(this);
81
+ }
82
+
83
+ componentDidMount() {
84
+ this.createCodeMirrorEditor();
104
85
  }
105
86
 
106
87
  // this is needed to ensure expression builder selection works.
107
88
  componentDidUpdate(prevProps) {
89
+ // When code is edited in expression builder, reflect changes in expression flyout
90
+ if (!isEqual(this.getCodemirrorState()?.doc.toString(), this.props.value)) {
91
+ this.editor.dispatch({ changes: { from: 0, to: this.getCodemirrorState()?.doc.length, insert: this.props.value } });
92
+ }
93
+ // Toggle editable mode in Codemirror editor
94
+ if (!isEqual(prevProps.state, this.props.state)) {
95
+ this.setCodeMirrorEditable(!(this.props.state === STATES.DISABLED));
96
+ }
108
97
  if (
109
98
  this.props.selectionRange &&
110
99
  this.props.selectionRange.length > 0 &&
@@ -112,17 +101,21 @@ class ExpressionControl extends React.Component {
112
101
  this.editor
113
102
  ) {
114
103
  this.props.selectionRange.forEach((selected) => {
115
- this.editor.setSelection(selected.anchor, selected.head);
104
+ this.editor.dispatch({ selection: selected });
116
105
  });
117
106
  this.editor.focus();
118
107
  }
119
108
  }
120
109
 
121
- // reset to the original autocomplete handler
122
- componentWillUnmount() {
123
- if (this.origHint && cm) {
124
- cm.registerHelper("hint", this.props.control.language, this.origHint);
125
- }
110
+ getCodemirrorState() {
111
+ return this.editor?.viewState?.state;
112
+ }
113
+
114
+ // Set codemirror editor non-editable when disabled
115
+ setCodeMirrorEditable(value) {
116
+ this.editor.dispatch({
117
+ effects: this.editable.reconfigure(EditorView.editable.of(value))
118
+ });
126
119
  }
127
120
 
128
121
  // get the set of dataset field names
@@ -130,39 +123,24 @@ class ExpressionControl extends React.Component {
130
123
  const results = [];
131
124
  const fields = this.props.controller.getDatasetMetadataFields();
132
125
  for (const field of fields) {
133
- results.push(field.name);
126
+ results.push({ label: field.name, type: "variable" });
134
127
  }
135
128
  return results;
136
129
  }
137
130
 
138
131
  // Add the dataset field names to the autocomplete list
139
- addonHints(editor, options) {
140
- var results = {};
141
- var cur = editor.getCursor();
142
- var token = editor.getTokenAt(cur);
143
- if (this.origHint) {
144
- // get the list of autocomplete names from the language autocomplete handler
145
- results = this.origHint(editor, options);
146
-
147
- // add to the start of the autocomplete list the set of dataset field names that complete the
148
- // string that has been entered.
149
- var parameters = this.getDatasetFields();
150
- for (var i = 0; i < parameters.length; ++i) {
151
- const parameter = parameters[i];
152
- if (parameter.lastIndexOf(token.string, 0) === 0 && results.list.indexOf(parameter) === -1) {
153
- results.list.unshift(parameter);
154
- } else if (token.string === " " && token.type === null) {
155
- results.list.unshift(parameter);
156
- }
157
- }
132
+ addonHints(context) {
133
+ const word = context.matchBefore(/\w*/);
134
+ if (word.from === word.to && !context.explicit) {
135
+ return null;
158
136
  }
159
- return results;
137
+ return {
138
+ from: word.from,
139
+ options: concat(this.origHint, this.getDatasetFields())
140
+ };
160
141
  }
161
142
 
162
- // Save original autocomplete handler and then register our custom handler
163
- // that will add data set filed names to autocomplete list.
164
- editorDidMount(editor, next) {
165
- this.editor = editor;
143
+ createCodeMirrorEditor() {
166
144
  // set the default height, should be between 4 and 20 lines
167
145
  const controlWidth = (this.expressionEditorDiv) ? this.expressionEditorDiv.clientWidth : 0;
168
146
  const charPerLine = (controlWidth > 0) ? controlWidth / pxPerChar : defaultCharPerLine;
@@ -172,9 +150,8 @@ class ExpressionControl extends React.Component {
172
150
  // let an explicit prop override the calculated height
173
151
  height = this.props.control.rows ? pxPerLine * this.props.control.rows : height;
174
152
  height = this.props.height ? this.props.height : height;
175
- this.editor.setSize(null, Math.max(Math.floor(height), minLineHeight));
153
+ this.setState({ expressionEditorHeight: Math.max(Math.floor(height), minLineHeight) });
176
154
 
177
- this.origHint = editor.getHelper({ line: 0, ch: 0 }, "hint");
178
155
  // this next line is a hack to overcome a Codemirror problem. To support SparkSQL, a subset of SQL,
179
156
  // we need to register with Codemirror the language as the value of "text/x-hive". When Codemirror
180
157
  // registers the autocomplete addon it registers is as "sql" not the subset "text/x-hive"
@@ -183,22 +160,60 @@ class ExpressionControl extends React.Component {
183
160
  let language = this.props.control.language;
184
161
  switch (this.props.control.language) {
185
162
  case "text/x-hive":
186
- language = "sql";
163
+ language = sql();
187
164
  break;
188
165
  case "text/x-python":
189
- language = "python";
166
+ language = python();
167
+ this.origHint = getPythonHints();
190
168
  break;
191
169
  case "text/x-rsrc":
192
- language = "r";
170
+ language = rLanguage(); // custom language
171
+ break;
172
+ case "javascript":
173
+ language = javascript();
193
174
  break;
194
175
  default:
195
- }
196
- if (cm) {
197
- cm.registerHelper("hint", language, this.addonHints);
176
+ language = clem(); // custom language
198
177
  }
199
178
 
179
+ // Custom completions add to the language completions
180
+ const customCompletions = language.language.data.of({
181
+ autocomplete: this.addonHints
182
+ });
183
+
184
+ // Syntax highlighting
185
+ const myHighlightStyle = HighlightStyle.define([
186
+ { tag: tags.keyword, class: "cm-keyword" },
187
+ { tag: tags.number, class: "cm-number" },
188
+ { tag: tags.definition(tags.name), class: "cm-def" },
189
+ { tag: tags.comment, class: "cm-comment" },
190
+ { tag: tags.variableName, class: "cm-variable" },
191
+ { tag: tags.punctuation, class: "cm-punctuation" },
192
+ { tag: tags.propertyName, class: "cm-property" },
193
+ { tag: tags.operator, class: "cm-operator" },
194
+ { tag: tags.string, class: "cm-string" },
195
+ { tag: tags.meta, class: "cm-meta" }
196
+ ]);
197
+
198
+ this.editor = new EditorView({
199
+ doc: this.props.value,
200
+ extensions: [
201
+ keymap.of([{ key: "Enter", run: insertNewline }, indentWithTab, defaultKeymap]), // This should be before basicSetup to insertNewLine on "Enter"
202
+ customCompletions,
203
+ syntaxHighlighting(myHighlightStyle),
204
+ basicSetup,
205
+ this.events(),
206
+ language,
207
+ placeholder(this.props.control.additionalText),
208
+ this.handleUpdate(),
209
+ this.editable.of(EditorView.editable.of(!(this.props.state === STATES.DISABLED)))
210
+ ],
211
+ parent: this.editorRef.current
212
+ });
213
+
214
+ // Set editor in the expression-builder
200
215
  if (this.props.editorDidMount) {
201
- this.props.editorDidMount(editor, next);
216
+ this.props.editorDidMount(this.editor);
202
217
  }
203
218
  }
204
219
 
@@ -232,7 +247,6 @@ class ExpressionControl extends React.Component {
232
247
  validateIcon: response.type,
233
248
  validationInProgress: false
234
249
  });
235
- this.editor.display.input.blur();
236
250
  });
237
251
  }
238
252
 
@@ -240,28 +254,56 @@ class ExpressionControl extends React.Component {
240
254
  return typeof this.props.controller.getHandlers().validationHandler === "function";
241
255
  }
242
256
 
243
- handleKeyDown(editor, evt) {
244
- // this is needed to move the cursor to the new line if selection is being used in the expression builder.
245
- if (evt.code === "Enter") {
246
- if (this.props.selectionRange && this.props.selectionRange.length > 0 && this.props.onSelectionChange) {
247
- const newPos = { line: this.props.selectionRange[0].anchor.line + 1, ch: 0 };
248
- this.props.onSelectionChange([{ anchor: newPos, head: newPos }]);
257
+ // Event handlers for CM6
258
+ events() {
259
+ const that = this;
260
+ const eventHandlers = EditorView.domEventHandlers({
261
+ blur(evt, view) {
262
+ that.handleBlur(view, evt);
249
263
  }
250
- }
264
+ });
265
+ return eventHandlers;
251
266
  }
252
267
 
253
268
  handleBlur(editor, evt) {
254
- if (this.props.onBlur) {
269
+ const cancelButtonClicked = evt && evt.relatedTarget && evt.relatedTarget.classList.contains("properties-cancel-button");
270
+ if (this.props.onBlur && !cancelButtonClicked) {
255
271
  // this will ensure the expression builder can save values onBlur
256
272
  this.props.onBlur(editor, evt);
257
273
  } else {
258
- const newValue = this.editor.getValue();
274
+ const newValue = editor?.viewState?.state?.doc.toString();
259
275
  // don't validate when opening the expression builder
260
276
  const skipValidate = evt && evt.relatedTarget && evt.relatedTarget.classList.contains("properties-expression-button");
261
277
  this.props.controller.updatePropertyValue(this.props.propertyId, newValue, skipValidate);
262
278
  }
263
279
  }
264
280
 
281
+ handleUpdate() {
282
+ const onUpdate = EditorView.updateListener.of((viewUpdate) => {
283
+ if (viewUpdate.docChanged) {
284
+ // this is needed when a single character is added into the expression builder because
285
+ // entering chars does not go through onChange() in expression builder.
286
+ // This is needed to adjust the selection position in code mirror.
287
+ if (
288
+ Array.isArray(viewUpdate.changedRanges) &&
289
+ viewUpdate.changedRanges.length === 1 &&
290
+ Math.abs(viewUpdate.changes.newLength - viewUpdate.changes.length) === 1 &&
291
+ this.props.onSelectionChange
292
+ ) {
293
+ const newPos = viewUpdate.changedRanges[0].toB;
294
+ this.props.onSelectionChange([{ anchor: newPos, head: newPos }]);
295
+ }
296
+ if (this.state.validateIcon) {
297
+ this.setState({
298
+ validateIcon: null
299
+ });
300
+ this.props.controller.updateErrorMessage(this.props.propertyId, DEFAULT_VALIDATION_MESSAGE);
301
+ }
302
+ }
303
+ });
304
+ return onUpdate;
305
+ }
306
+
265
307
  _showBuilderButton() {
266
308
  // only show the button if there are function lists available and
267
309
  // not explicitly told not to by the this.props.builder
@@ -276,7 +318,6 @@ class ExpressionControl extends React.Component {
276
318
  messageInfo = null;
277
319
  }
278
320
 
279
- const theme = (this.props.state === STATES.DISABLED) ? "disabled" : messageType;
280
321
  const reactIntl = this.props.controller.getReactIntl();
281
322
 
282
323
  const button = this._showBuilderButton() ? (
@@ -309,15 +350,7 @@ class ExpressionControl extends React.Component {
309
350
  {validateIcon}
310
351
  </div>)
311
352
  : null;
312
- const mirrorOptions = {
313
- mode: this.props.control.language,
314
- placeholder: this.props.control.additionalText,
315
- theme: theme + " custom",
316
- readOnly: (this.props.state === STATES.DISABLED) ? "nocursor" : false,
317
- extraKeys: { "Ctrl-Space": "autocomplete" },
318
- autoRefresh: true,
319
- lineNumbers: true
320
- };
353
+
321
354
  const applyLabel = formatMessage(reactIntl, MESSAGE_KEYS.APPLYBUTTON_LABEL);
322
355
  const rejectLabel = formatMessage(reactIntl, MESSAGE_KEYS.REJECTBUTTON_LABEL);
323
356
  const expressonTitle = formatMessage(reactIntl, MESSAGE_KEYS.EXPRESSION_BUILDER_TITLE);
@@ -367,6 +400,8 @@ class ExpressionControl extends React.Component {
367
400
  />);
368
401
  }
369
402
 
403
+ const codemirrorClassName = classNames(`elyra-CodeMirror ${messageType} ${this.props.state}`);
404
+
370
405
  return (
371
406
  <div className="properties-expression-editor-wrapper" >
372
407
  {this.props.controlItem}
@@ -377,15 +412,7 @@ class ExpressionControl extends React.Component {
377
412
  <div ref={ (ref) => (this.expressionEditorDiv = ref) } data-id={ControlUtils.getDataId(this.props.propertyId)}
378
413
  className={className}
379
414
  >
380
- <CodeMirror
381
- ref= { (ref) => (this.codeMirror = ref)}
382
- options={mirrorOptions}
383
- onChange={this.handleChange}
384
- onKeyDown={this.handleKeyDown}
385
- onBlur={this.handleBlur}
386
- editorDidMount={this.editorDidMount}
387
- value={this.props.value}
388
- />
415
+ <div className={codemirrorClassName} ref={this.editorRef} style={{ height: this.state.expressionEditorHeight }} />
389
416
  <ValidationMessage state={this.props.state} messageInfo={messageInfo} inTable={this.props.tableControl} />
390
417
  </div>
391
418
  </div>
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2017-2023 Elyra Authors
2
+ * Copyright 2017-2024 Elyra Authors
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -17,80 +17,78 @@
17
17
  @import "./expression-builder/expression-builder";
18
18
  @import "./expression-toggle/expression-toggle";
19
19
 
20
- .react-codemirror2 {
21
- .CodeMirror {
20
+ .elyra-CodeMirror {
21
+ .cm-editor {
22
+ height: inherit;
22
23
  width: 100%;
23
24
  background: $field-02;
24
25
  color: $text-01;
25
26
 
26
- .CodeMirror-gutters {
27
+ .cm-gutters {
27
28
  border-right: none;
28
29
  background-color: inherit;
29
30
  }
30
31
 
31
- .CodeMirror-lines {
32
- padding-top: $spacing-05;
33
- .CodeMirror-line-like {
32
+ .cm-content {
33
+ .cm-line {
34
34
  padding-left: $spacing-03;
35
+ @include carbon--type-style("code-02");
35
36
  }
36
- .CodeMirror-placeholder {
37
- opacity: 0.5;
37
+ .cm-placeholder {
38
38
  @include carbon--type-style("code-02");
39
39
  }
40
- .CodeMirror-cursor {
40
+ .cm-cursor {
41
41
  border-left: 1px solid $text-01;
42
42
  }
43
- .CodeMirror-code {
44
-
45
- .CodeMirror-linenumber {
46
- @include carbon--type-style("body-short-01");
47
- }
48
-
49
- .CodeMirror-line {
50
- padding-left: $spacing-03;
43
+ .cm-lineNumbers .cm-gutterElement {
44
+ @include carbon--type-style("body-short-01");
45
+ }
46
+ }
51
47
 
52
- span {
53
- @include carbon--type-style("code-02");
54
- }
55
- }
48
+ .cm-tooltip-autocomplete {
49
+ z-index: 1110;
50
+ ul {
51
+ white-space: normal; // Wraps the long autocompletion text on multiple lines
56
52
  }
57
53
  }
58
54
  }
59
55
 
60
- .cm-s-error.CodeMirror { border: $spacing-01 solid $support-01; }
61
-
62
- .cm-s-warning.CodeMirror { border: $spacing-01 solid $support-03; }
63
-
64
- .cm-s-disabled.CodeMirror { opacity: 0.5}
56
+ .cm-line .cm-keyword { color: $link-01; }
65
57
 
66
- .cm-s-custom .cm-keyword { color: $link-01; }
58
+ .cm-line .cm-number { color: $text-02; }
67
59
 
68
- .cm-s-custom .cm-number { color: $text-02; }
60
+ .cm-line .cm-def { color: $support-01; }
69
61
 
70
- .cm-s-custom .cm-def { color: $support-01; }
62
+ .cm-line .cm-comment { color: $support-02; }
71
63
 
72
- .cm-s-custom .cm-comment { color: $support-02; }
73
-
74
- .cm-s-custom .cm-variable,
75
- .cm-s-custom .cm-punctuation,
76
- .cm-s-custom .cm-property,
77
- .cm-s-custom .cm-operator {
64
+ .cm-line .cm-variable,
65
+ .cm-line .cm-punctuation,
66
+ .cm-line .cm-property,
67
+ .cm-line .cm-operator {
78
68
  color: $text-01;
79
69
  }
80
- .cm-s-custom .cm-variable-2 { color: $text-01; }
81
70
 
82
- .cm-s-custom .cm-variable-3, .cm-s-custom .cm-type { color: $text-01; }
71
+ .cm-line .cm-string { color: $text-error; }
83
72
 
84
- .cm-s-custom .cm-string { color: $text-error; }
73
+ .cm-line .cm-meta { color: $ui-01; }
74
+ }
85
75
 
86
- .cm-s-custom .cm-string-2 { color: $text-error; }
76
+ .elyra-CodeMirror.disabled {
77
+ .cm-editor {
78
+ opacity: 0.5;
79
+ }
80
+ }
87
81
 
88
- .cm-s-custom .cm-meta { color: $ui-01; }
82
+ .elyra-CodeMirror.warning {
83
+ .cm-editor {
84
+ border: $spacing-01 solid $support-03;
85
+ }
89
86
  }
90
87
 
91
- /* Override so Codemirror autocomplete shows up on top */
92
- .CodeMirror-hints {
93
- z-index: 1110;
88
+ .elyra-CodeMirror.error {
89
+ .cm-editor {
90
+ border: $spacing-01 solid $support-01;
91
+ }
94
92
  }
95
93
 
96
94
  .properties-expression-editor {
@@ -104,7 +102,7 @@
104
102
  }
105
103
 
106
104
  .properties-light-disabled {
107
- .CodeMirror {
105
+ .elyra-CodeMirror .cm-editor {
108
106
  background: $field-01;
109
107
  }
110
108
  }