@elyra/canvas 12.12.2 → 12.14.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 (181) hide show
  1. package/.stylelintrc.json +17 -16
  2. package/README.md +1 -1
  3. package/dist/canvas-controller-8e2bb291.js +2 -0
  4. package/dist/canvas-controller-8e2bb291.js.map +1 -0
  5. package/dist/canvas-controller-bd0d8d59.js +2 -0
  6. package/dist/canvas-controller-bd0d8d59.js.map +1 -0
  7. package/dist/common-canvas-69fe4a67.js +2 -0
  8. package/dist/common-canvas-69fe4a67.js.map +1 -0
  9. package/dist/common-canvas-f5e4af65.js +2 -0
  10. package/dist/common-canvas-f5e4af65.js.map +1 -0
  11. package/dist/common-canvas.es.js +1 -1
  12. package/dist/common-canvas.js +1 -1
  13. package/dist/common-properties-40648163.js +2 -0
  14. package/dist/common-properties-40648163.js.map +1 -0
  15. package/dist/common-properties-6d839df1.js +2 -0
  16. package/dist/common-properties-6d839df1.js.map +1 -0
  17. package/dist/{extends-7fdcdc52.js → extends-1139e06f.js} +2 -2
  18. package/dist/{extends-7fdcdc52.js.map → extends-1139e06f.js.map} +1 -1
  19. package/dist/{flexible-table-a13cb7d0.js → flexible-table-d3598aa8.js} +2 -2
  20. package/dist/flexible-table-d3598aa8.js.map +1 -0
  21. package/dist/{flexible-table-50ce600a.js → flexible-table-fe7fbc13.js} +2 -2
  22. package/dist/flexible-table-fe7fbc13.js.map +1 -0
  23. package/dist/{icon-bf77b2aa.js → icon-918d2dd3.js} +2 -2
  24. package/dist/{icon-bf77b2aa.js.map → icon-918d2dd3.js.map} +1 -1
  25. package/dist/{index-f2c306ba.js → index-669f95a7.js} +2 -2
  26. package/dist/{index-f2c306ba.js.map → index-669f95a7.js.map} +1 -1
  27. package/dist/{index-0e6c8b9c.js → index-6d3404e1.js} +2 -2
  28. package/dist/{index-0e6c8b9c.js.map → index-6d3404e1.js.map} +1 -1
  29. package/dist/lib/canvas-controller.es.js +1 -1
  30. package/dist/lib/canvas-controller.js +1 -1
  31. package/dist/lib/canvas.es.js +1 -1
  32. package/dist/lib/canvas.js +1 -1
  33. package/dist/lib/context-menu.es.js +1 -1
  34. package/dist/lib/properties/field-picker.es.js +1 -1
  35. package/dist/lib/properties/field-picker.js +1 -1
  36. package/dist/lib/properties/flexible-table.es.js +1 -1
  37. package/dist/lib/properties/flexible-table.js +1 -1
  38. package/dist/lib/properties.es.js +1 -1
  39. package/dist/lib/properties.js +1 -1
  40. package/dist/lib/tooltip.es.js +1 -1
  41. package/dist/lib/tooltip.es.js.map +1 -1
  42. package/dist/lib/tooltip.js +1 -1
  43. package/dist/lib/tooltip.js.map +1 -1
  44. package/dist/styles/common-canvas.min.css +1 -1
  45. package/dist/styles/common-canvas.min.css.map +1 -1
  46. package/dist/toolbar-29ec7983.js +2 -0
  47. package/dist/toolbar-29ec7983.js.map +1 -0
  48. package/dist/toolbar-3f4b173f.js +2 -0
  49. package/dist/toolbar-3f4b173f.js.map +1 -0
  50. package/locales/command-actions/locales/de.json +50 -8
  51. package/locales/command-actions/locales/en.json +1 -1
  52. package/locales/command-actions/locales/es.json +50 -8
  53. package/locales/command-actions/locales/fr.json +50 -8
  54. package/locales/command-actions/locales/index.js +2 -2
  55. package/locales/command-actions/locales/it.json +50 -8
  56. package/locales/command-actions/locales/ja.json +50 -8
  57. package/locales/command-actions/locales/ko.json +42 -0
  58. package/locales/command-actions/locales/pt-br.json +50 -8
  59. package/locales/command-actions/locales/zh-CN.json +51 -0
  60. package/locales/command-actions/locales/zh-TW.json +51 -0
  61. package/locales/common-canvas/locales/de.json +36 -26
  62. package/locales/common-canvas/locales/en.json +14 -1
  63. package/locales/common-canvas/locales/eo.json +14 -1
  64. package/locales/common-canvas/locales/es.json +36 -26
  65. package/locales/common-canvas/locales/fr.json +36 -26
  66. package/locales/common-canvas/locales/index.js +2 -2
  67. package/locales/common-canvas/locales/it.json +36 -26
  68. package/locales/common-canvas/locales/ja.json +36 -26
  69. package/locales/common-canvas/locales/ko.json +7 -2
  70. package/locales/common-canvas/locales/pt-br.json +36 -26
  71. package/locales/common-canvas/locales/zh-CN.json +37 -0
  72. package/locales/common-canvas/locales/zh-TW.json +37 -0
  73. package/locales/common-properties/locales/de.json +92 -92
  74. package/locales/common-properties/locales/en.json +1 -1
  75. package/locales/common-properties/locales/es.json +92 -92
  76. package/locales/common-properties/locales/fr.json +92 -92
  77. package/locales/common-properties/locales/index.js +2 -2
  78. package/locales/common-properties/locales/it.json +92 -92
  79. package/locales/common-properties/locales/ja.json +92 -92
  80. package/locales/common-properties/locales/ko.json +1 -1
  81. package/locales/common-properties/locales/pt-br.json +92 -92
  82. package/locales/common-properties/locales/zh-CN.json +93 -0
  83. package/locales/common-properties/locales/zh-TW.json +93 -0
  84. package/locales/palette/locales/de.json +9 -9
  85. package/locales/palette/locales/en.json +6 -6
  86. package/locales/palette/locales/es.json +9 -9
  87. package/locales/palette/locales/fr.json +9 -9
  88. package/locales/palette/locales/index.js +2 -2
  89. package/locales/palette/locales/it.json +9 -9
  90. package/locales/palette/locales/ja.json +9 -9
  91. package/locales/palette/locales/pt-br.json +9 -9
  92. package/locales/palette/locales/zh-CN.json +10 -0
  93. package/locales/palette/locales/zh-TW.json +10 -0
  94. package/locales/toolbar/locales/de.json +7 -7
  95. package/locales/toolbar/locales/en.json +1 -1
  96. package/locales/toolbar/locales/es.json +7 -7
  97. package/locales/toolbar/locales/fr.json +7 -7
  98. package/locales/toolbar/locales/index.js +2 -2
  99. package/locales/toolbar/locales/it.json +7 -7
  100. package/locales/toolbar/locales/ja.json +7 -7
  101. package/locales/toolbar/locales/pt-br.json +7 -7
  102. package/locales/toolbar/locales/zh-CN.json +8 -0
  103. package/locales/toolbar/locales/zh-TW.json +8 -0
  104. package/package.json +3 -2
  105. package/src/common-canvas/canvas-controller.js +19 -3
  106. package/src/common-canvas/cc-bottom-panel.jsx +37 -21
  107. package/src/common-canvas/cc-central-items.jsx +1 -1
  108. package/src/common-canvas/cc-contents.jsx +10 -3
  109. package/src/common-canvas/cc-text-toolbar.jsx +141 -0
  110. package/src/common-canvas/cc-toolbar.jsx +8 -6
  111. package/src/common-canvas/common-canvas.scss +52 -5
  112. package/src/common-canvas/svg-canvas-d3.scss +159 -16
  113. package/src/common-canvas/svg-canvas-renderer.js +204 -26
  114. package/src/common-canvas/svg-canvas-utils-markdown.js +515 -0
  115. package/src/common-properties/components/control-item/control-item.scss +1 -1
  116. package/src/common-properties/components/flexible-table/flexible-table.jsx +14 -3
  117. package/src/common-properties/components/flexible-table/flexible-table.scss +20 -0
  118. package/src/common-properties/controls/abstract-table.jsx +2 -0
  119. package/src/common-properties/controls/checkbox/checkbox.jsx +1 -1
  120. package/src/common-properties/controls/checkboxset/checkboxset.jsx +36 -11
  121. package/src/common-properties/controls/checkboxset/checkboxset.scss +6 -0
  122. package/src/common-properties/controls/list/list.jsx +1 -0
  123. package/src/common-properties/controls/radioset/radioset.jsx +25 -1
  124. package/src/common-properties/controls/radioset/radioset.scss +19 -0
  125. package/src/common-properties/controls/selectcolumns/selectcolumns.jsx +1 -0
  126. package/src/common-properties/controls/someofselect/someofselect.jsx +1 -0
  127. package/src/common-properties/form/ControlInfo.js +3 -0
  128. package/src/common-properties/form/EditorForm.js +45 -3
  129. package/src/common-properties/panels/action-panel/action-panel.jsx +38 -3
  130. package/src/common-properties/panels/action-panel/action-panel.scss +3 -0
  131. package/src/common-properties/panels/text-panel/text-panel.jsx +38 -7
  132. package/src/common-properties/panels/text-panel/text-panel.scss +4 -3
  133. package/src/common-properties/properties-controller.js +39 -12
  134. package/src/common-properties/ui-conditions/conditions-utils.js +14 -8
  135. package/src/common-properties/util/L10nProvider.js +6 -0
  136. package/src/object-model/config-utils.js +1 -0
  137. package/src/object-model/layout-dimensions.js +10 -0
  138. package/src/object-model/object-model.js +12 -0
  139. package/src/object-model/redux/canvas-store.js +4 -1
  140. package/src/object-model/redux/reducers/bottompanel.js +1 -3
  141. package/src/object-model/redux/reducers/texttoolbar.js +29 -0
  142. package/src/palette/palette-content-list-item.jsx +12 -2
  143. package/src/palette/palette-content-list.jsx +11 -19
  144. package/src/palette/palette-dialog-content-grid.jsx +1 -6
  145. package/src/palette/palette-dialog-content.jsx +13 -11
  146. package/src/palette/palette-flyout-content-category.jsx +26 -24
  147. package/src/palette/palette-flyout-content.jsx +4 -24
  148. package/src/palette/palette.scss +71 -43
  149. package/src/toolbar/toolbar-action-item.jsx +9 -6
  150. package/src/toolbar/toolbar-overflow-item.jsx +1 -0
  151. package/src/toolbar/toolbar.jsx +12 -15
  152. package/src/tooltip/tooltip.jsx +14 -5
  153. package/stats.html +1 -1
  154. package/dist/canvas-controller-de76a796.js +0 -2
  155. package/dist/canvas-controller-de76a796.js.map +0 -1
  156. package/dist/canvas-controller-e91d037b.js +0 -2
  157. package/dist/canvas-controller-e91d037b.js.map +0 -1
  158. package/dist/common-canvas-522f6263.js +0 -2
  159. package/dist/common-canvas-522f6263.js.map +0 -1
  160. package/dist/common-canvas-90539c97.js +0 -2
  161. package/dist/common-canvas-90539c97.js.map +0 -1
  162. package/dist/common-properties-245c4711.js +0 -2
  163. package/dist/common-properties-245c4711.js.map +0 -1
  164. package/dist/common-properties-49e6bb67.js +0 -2
  165. package/dist/common-properties-49e6bb67.js.map +0 -1
  166. package/dist/flexible-table-50ce600a.js.map +0 -1
  167. package/dist/flexible-table-a13cb7d0.js.map +0 -1
  168. package/dist/toolbar-1c181339.js +0 -2
  169. package/dist/toolbar-1c181339.js.map +0 -1
  170. package/dist/toolbar-c6fa3cdb.js +0 -2
  171. package/dist/toolbar-c6fa3cdb.js.map +0 -1
  172. package/locales/command-actions/locales/zh-cn.json +0 -9
  173. package/locales/command-actions/locales/zh-tw.json +0 -9
  174. package/locales/common-canvas/locales/zh-cn.json +0 -27
  175. package/locales/common-canvas/locales/zh-tw.json +0 -27
  176. package/locales/common-properties/locales/zh-cn.json +0 -93
  177. package/locales/common-properties/locales/zh-tw.json +0 -93
  178. package/locales/palette/locales/zh-cn.json +0 -10
  179. package/locales/palette/locales/zh-tw.json +0 -10
  180. package/locales/toolbar/locales/zh-cn.json +0 -8
  181. package/locales/toolbar/locales/zh-tw.json +0 -8
@@ -0,0 +1,515 @@
1
+ /*
2
+ * Copyright 2022 Elyra Authors
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
+ export default class SvgCanvasUtilsComments {
18
+
19
+ // Processes the action passed in and returns an object containing:
20
+ // newText - new text based on the input text passed in with markdown
21
+ // characters added based on the selected part of the text
22
+ // newStart - a new starting point for selection highlighting
23
+ // newEnd - a new ending point for selection highlighting
24
+ static processMarkdownAction(action, text, inStart, inEnd) {
25
+ let start = inStart;
26
+ let end = inEnd;
27
+ let mdObj = null;
28
+
29
+ if (start === end) {
30
+ start = this.findFirstSpace(text, start);
31
+ end = this.findLastSpace(text, end);
32
+
33
+ } else if (this.allWhiteSpace(text, start, end)) {
34
+ start = end;
35
+
36
+ } else {
37
+ start = this.findFirstNonSpace(text, start, end);
38
+ end = this.findLastNonSpace(text, start, end);
39
+ }
40
+
41
+ switch (action) {
42
+ case "title":
43
+ case "header":
44
+ case "subheader":
45
+ case "body":
46
+ case "increaseHashes":
47
+ case "decreaseHashes": {
48
+ mdObj = this.processHeaderCommand(text, start, end, action);
49
+ break;
50
+ }
51
+ case "bold": {
52
+ mdObj = this.processWrapCommand(text, start, end, "**");
53
+ break;
54
+ }
55
+ case "italics": {
56
+ mdObj = this.processWrapCommand(text, start, end, "_");
57
+ break;
58
+ }
59
+ case "strikethrough": {
60
+ mdObj = this.processWrapCommand(text, start, end, "~~");
61
+ break;
62
+ }
63
+ case "code": {
64
+ mdObj = this.processCodeCommand(text, start, end);
65
+ break;
66
+ }
67
+ case "link": {
68
+ mdObj = this.processLinkCommand(text, start, end);
69
+ break;
70
+ }
71
+ case "quote":
72
+ case "numberedList":
73
+ case "bulletedList": {
74
+ mdObj = this.processMultiLineCommand(text, start, end, action);
75
+ break;
76
+ }
77
+ case "return": {
78
+ mdObj = this.processReturnCommand(text, start, end, inStart, inEnd);
79
+ break;
80
+ }
81
+ default: {
82
+ break;
83
+ }
84
+ }
85
+ return mdObj;
86
+ }
87
+
88
+ static findFirstSpace(text, start) {
89
+ const spacePos = text.lastIndexOf(" ", start - 1) + 1;
90
+ const newLinePos = text.lastIndexOf("\n", start - 1) + 1;
91
+ return Math.max(spacePos, newLinePos, 0);
92
+ }
93
+
94
+ static findLastSpace(text, end) {
95
+ let spacePos = text.indexOf(" ", end);
96
+ let newLinePos = text.indexOf("\n", end);
97
+ spacePos = spacePos === -1 ? text.length : spacePos;
98
+ newLinePos = newLinePos === -1 ? text.length : newLinePos;
99
+ return Math.min(spacePos, newLinePos, text.length);
100
+ }
101
+
102
+ static allWhiteSpace(text, start, end) {
103
+ return text.slice(start, end).trim().length === 0;
104
+ }
105
+
106
+ static findFirstNonSpace(text, start, end) {
107
+ let newStart = start;
108
+ while ((text[newStart] === " " || text[newStart] === "\n") && newStart <= end) {
109
+ newStart++;
110
+ }
111
+ return newStart;
112
+ }
113
+
114
+ static findLastNonSpace(text, start, end) {
115
+ let newEnd = end;
116
+ while ((text[newEnd - 1] === " " || text[newEnd - 1] === "\n") && newEnd >= start) {
117
+ newEnd--;
118
+ }
119
+ return newEnd;
120
+ }
121
+
122
+ static processHeaderCommand(text, inStart, inEnd, action) {
123
+ const start = this.findPrecedingNewLine(text, inStart);
124
+ const end = this.findSuceedingNewLine(text, inEnd);
125
+
126
+ const startText = text.slice(0, start);
127
+ const selectedText = text.slice(start, end);
128
+ const endText = text.slice(end);
129
+
130
+ let newStart = start;
131
+ let newEnd = end;
132
+ let newText = "";
133
+ let tempText = selectedText;
134
+
135
+ // Remove all hashes if any from the line.
136
+ const hashCount = this.getHashCount(selectedText);
137
+ if (hashCount > 0) {
138
+ const firstSpace = selectedText.indexOf(" ");
139
+ tempText = selectedText.slice(firstSpace + 1);
140
+ newText = startText + tempText + endText;
141
+ newEnd -= firstSpace + 1;
142
+ }
143
+
144
+ // Add as many hashes as appropriate for the action.
145
+ const headerSyntax = this.getHeaderSyntax(action, hashCount);
146
+ if (headerSyntax) {
147
+ newText = startText + headerSyntax + tempText + endText;
148
+ newStart += headerSyntax.length;
149
+ newEnd += headerSyntax.length;
150
+ }
151
+ return { newText, newStart, newEnd };
152
+ }
153
+
154
+ static getHeaderSyntax(action, hashCount) {
155
+ switch (action) {
156
+ case "title": return "# ";
157
+ case "header": return "## ";
158
+ case "subheader": return "### ";
159
+ case "body": return false;
160
+ case "increaseHashes": {
161
+ if (hashCount === 0) {
162
+ return "# ";
163
+ } else if (hashCount === 1) {
164
+ return "## ";
165
+ } else if (hashCount === 2) {
166
+ return "### ";
167
+ }
168
+ return false;
169
+ }
170
+ case "decreaseHashes": {
171
+ if (hashCount === 0) {
172
+ return "### ";
173
+ } else if (hashCount === 1) {
174
+ return false;
175
+ } else if (hashCount === 2) {
176
+ return "# ";
177
+ } else if (hashCount === 3) {
178
+ return "## ";
179
+ }
180
+ return "### ";
181
+ }
182
+ default:
183
+ }
184
+ return false;
185
+ }
186
+
187
+ static getHashCount(text) {
188
+ if (text.startsWith("# ")) {
189
+ return 1;
190
+ } else if (text.startsWith("## ")) {
191
+ return 2;
192
+ } else if (text.startsWith("### ")) {
193
+ return 3;
194
+ } else if (text.startsWith("#### ")) {
195
+ return 4;
196
+ } else if (text.startsWith("##### ")) {
197
+ return 5;
198
+ } else if (text.startsWith("###### ")) {
199
+ return 6;
200
+ }
201
+ return 0;
202
+ }
203
+
204
+ static processWrapCommand(text, start, end, chars) {
205
+ let newText = "";
206
+ let newStart = start;
207
+ let newEnd = end;
208
+
209
+ const startText = text.slice(0, start);
210
+ const selectedText = text.slice(start, end);
211
+ const endText = text.slice(end);
212
+ const charsCount = chars.length;
213
+
214
+ if (startText.endsWith(chars) && endText.startsWith(chars)) {
215
+ newText = startText.slice(0, startText.length - charsCount) +
216
+ selectedText +
217
+ endText.slice(charsCount);
218
+ newStart = start - charsCount;
219
+ newEnd = end - charsCount;
220
+
221
+ } else if (selectedText.startsWith(chars) && selectedText.endsWith(chars)) {
222
+ newText = startText +
223
+ selectedText
224
+ .slice(0, selectedText.length - charsCount) // Remove ending chars
225
+ .slice(charsCount) + // Remove beginning chars
226
+ endText;
227
+ newStart = start;
228
+ newEnd = end - (2 * charsCount);
229
+
230
+ } else {
231
+ newText = startText + chars + selectedText + chars + endText;
232
+ newStart = start + charsCount;
233
+ newEnd = end + charsCount;
234
+ }
235
+
236
+ return { newText, newStart, newEnd };
237
+ }
238
+
239
+ static processCodeCommand(text, start, end) {
240
+ const selText = text.slice(start, end);
241
+ if (selText.indexOf("\n") > -1) {
242
+ return this.processTripleBackTicks(text, start, end);
243
+ }
244
+
245
+ return this.processWrapCommand(text, start, end, "`");
246
+ }
247
+
248
+ static processTripleBackTicks(text, inStart, inEnd) {
249
+ const start = this.findPrecedingNewLine(text, inStart);
250
+ const end = this.findSuceedingNewLine(text, inEnd);
251
+
252
+ const startText = text.slice(0, start);
253
+ const selectedText = text.slice(start, end);
254
+ const endText = text.slice(end);
255
+
256
+ let newStart = start;
257
+ let newEnd = end;
258
+ let newText = "";
259
+
260
+ if (startText.endsWith("```\n") && endText.startsWith("\n```")) {
261
+ newText = startText.slice(0, start - 4) + selectedText + endText.slice(4);
262
+ newStart -= 4;
263
+ newEnd -= 4;
264
+
265
+ } else {
266
+ newText = startText + "```\n" + selectedText + "\n```" + endText;
267
+ newStart += 4;
268
+ newEnd += 4;
269
+ }
270
+
271
+ return { newText, newStart, newEnd };
272
+ }
273
+
274
+ static processLinkCommand(text, start, end) {
275
+ let newText = "";
276
+ let newStart = start;
277
+ let newEnd = end;
278
+
279
+ const startText = text.slice(0, start);
280
+ const selectedText = text.slice(start, end);
281
+ const endText = text.slice(end);
282
+
283
+ if (startText.endsWith("[") && endText.startsWith("](url)")) {
284
+ newText = startText.slice(0, startText.length - 1) + selectedText + endText.slice(6);
285
+ newStart = start - 1;
286
+ newEnd = end - 1;
287
+
288
+ } else if (selectedText === "[](url)") {
289
+ newText = startText + endText;
290
+ newStart = start;
291
+ newEnd = newStart;
292
+
293
+ } else if (start === end) {
294
+ newText = startText + "[](url)" + endText;
295
+ newStart = start + 1;
296
+ newEnd = start + 1;
297
+
298
+ } else {
299
+ newText = startText + "[" + selectedText + "](url)" + endText;
300
+ newStart = start + 1;
301
+ newEnd = end + 1;
302
+ }
303
+
304
+ return { newText, newStart, newEnd };
305
+ }
306
+
307
+ static processMultiLineCommand(text, start, end, action) {
308
+ if (this.isMultiLineMarkdown(text, start, end, action)) {
309
+ return this.removeMultiLineMarkdown(text, start, end, action);
310
+ }
311
+ return this.addMultiLineMarkdown(text, start, end, action);
312
+ }
313
+
314
+ static isMultiLineMarkdown(text, inStart, inEnd, action) {
315
+ const start = this.findPrecedingNewLine(text, inStart);
316
+ const end = this.findSuceedingNewLine(text, inEnd);
317
+ const selectedText = text.slice(start, end);
318
+
319
+ const lines = selectedText.split("\n");
320
+ return lines.every((line) => this.isMultiLineItem(line, action));
321
+ }
322
+
323
+ static isMultiLineItem(text, action) {
324
+ switch (action) {
325
+ case "quote":
326
+ return text.startsWith("> ");
327
+ case "bulletedList":
328
+ return text.startsWith("* ");
329
+ case "numberedList": {
330
+ const number = this.getPrefixNumber(text);
331
+ return (!isNaN(number) && number > 0);
332
+ }
333
+ default:
334
+ }
335
+ return false;
336
+ }
337
+
338
+ static getPrefixNumber(text) {
339
+ const firstSpace = text.indexOf(". ");
340
+ const firstText = text.slice(0, firstSpace);
341
+ return Number(firstText);
342
+ }
343
+
344
+ static removeMultiLineMarkdown(text, inStart, inEnd, action) {
345
+ const start = this.findPrecedingNewLine(text, inStart);
346
+ const end = this.findSuceedingNewLine(text, inEnd);
347
+
348
+ const startText = text.slice(0, start);
349
+ const selectedText = text.slice(start, end);
350
+ const endText = text.slice(end);
351
+
352
+ const newStart = start;
353
+ let newEnd = end;
354
+ let newText = startText;
355
+
356
+ const lines = selectedText.split("\n");
357
+ lines.forEach((line, i) => {
358
+ const newLine = this.removeListPrefix(line, action);
359
+ newEnd -= (line.length - newLine.length);
360
+ newText += newLine;
361
+ if (i < lines.length - 1) {
362
+ newText += "\n";
363
+ }
364
+ });
365
+ newText += endText;
366
+
367
+ return { newText, newStart, newEnd };
368
+ }
369
+
370
+ static removeListPrefix(text, action) {
371
+ switch (action) {
372
+ case "quote":
373
+ return text.slice(2); // Remove 2 characters: "> "
374
+ case "bulletedList":
375
+ return text.slice(2); // Remove 2 characters: "* "
376
+ case "numberedList": {
377
+ const firstSpace = text.indexOf(". "); // Remove characters: "5. " or "10. "
378
+ return text.slice(firstSpace + 2);
379
+ }
380
+ default:
381
+ }
382
+ return "";
383
+ }
384
+
385
+ static addMultiLineMarkdown(text, inStart, inEnd, action) {
386
+ const start = this.findPrecedingNewLine(text, inStart);
387
+ const end = this.findSuceedingNewLine(text, inEnd);
388
+
389
+ const startText = text.slice(0, start);
390
+ const selectedText = text.slice(start, end);
391
+ const endText = text.slice(end);
392
+
393
+ let newStart = start;
394
+ let newEnd = end;
395
+ let newText = startText;
396
+
397
+ if (selectedText === "") {
398
+ const itemText = this.getListPrefix(action, 1);
399
+ newText = startText + itemText + endText;
400
+ newStart = start + itemText.length;
401
+ newEnd = newStart;
402
+
403
+ } else {
404
+ const lines = selectedText.split("\n");
405
+ lines.forEach((line, i) => {
406
+ const newLine = this.getListPrefix(action, i + 1, line);
407
+ newEnd += (newLine.length - line.length);
408
+ newText += newLine;
409
+
410
+ if (i === lines.length - 1) {
411
+ if (text[end] !== "\n" || text[end + 1] !== "\n") {
412
+ newText += "\n";
413
+ }
414
+ } else {
415
+ newText += "\n";
416
+ }
417
+ });
418
+ newText += endText;
419
+ }
420
+
421
+ return { newText, newStart, newEnd };
422
+ }
423
+
424
+ static getListPrefix(action, i, suffixText = "") {
425
+ switch (action) {
426
+ case "quote":
427
+ return "> " + suffixText;
428
+ case "bulletedList":
429
+ return "* " + suffixText;
430
+ case "numberedList":
431
+ return i + ". " + suffixText;
432
+ default:
433
+ }
434
+ return null;
435
+ }
436
+
437
+ static findPrecedingNewLine(text, start) {
438
+ let preStart = start;
439
+ while (preStart > 0 && text[preStart - 1] !== "\n") {
440
+ preStart--;
441
+ }
442
+ return preStart;
443
+ }
444
+
445
+ static findSuceedingNewLine(text, end) {
446
+ let sucEnd = end;
447
+ while (sucEnd < text.length && text[sucEnd] !== "\n") {
448
+ sucEnd++;
449
+ }
450
+ return sucEnd;
451
+ }
452
+
453
+ static processReturnCommand(text, inStart, inEnd, originalStart, originalEnd) {
454
+ const start = this.findPrecedingNewLine(text, inStart);
455
+ const end = this.findSuceedingNewLine(text, inEnd);
456
+
457
+ const startText = text.slice(0, start);
458
+ const selectedText = text.slice(start, end);
459
+ const endText = text.slice(end);
460
+
461
+ // If cursor is at the beginning of the line we just let it insert the
462
+ // newline by default, if not we insert a new multi-line element.
463
+ if (!this.isCursorAtBeginningOfLine(start, originalStart, originalEnd)) {
464
+ if (this.isMultiLineItem(selectedText, "quote")) {
465
+ return this.insertMultiLineItem(">", startText, selectedText, endText, end);
466
+
467
+ } else if (this.isMultiLineItem(selectedText, "bulletedList")) {
468
+ return this.insertMultiLineItem("*", startText, selectedText, endText, end);
469
+
470
+ } else if (this.isMultiLineItem(selectedText, "numberedList")) {
471
+ const number = this.getPrefixNumber(selectedText) + 1; // Increment for next multi-line item
472
+ const newEndText = this.renumberEndText(endText, number);
473
+ return this.insertMultiLineItem(number + ".", startText, selectedText, newEndText, end);
474
+ }
475
+ }
476
+
477
+ return null; // Return null is there is nothing to do so key processing is ignored.
478
+ }
479
+
480
+ static isCursorAtBeginningOfLine(start, originalStart, originalEnd) {
481
+ return (originalStart === originalEnd && originalStart === start);
482
+ }
483
+
484
+ static insertMultiLineItem(char, startText, selectedText, endText, end) {
485
+ const newText = startText + selectedText + "\n" + char + " " + endText;
486
+ const newStart = end + 2 + char.length; // Add 2 for newline and space plus length of the char.
487
+ const newEnd = newStart;
488
+ return { newText, newStart, newEnd };
489
+ }
490
+
491
+ static renumberEndText(text, startIndex) {
492
+ const lines = text.split("\n");
493
+ let newText = "";
494
+ let finished = false;
495
+
496
+ lines.forEach((line, i) => {
497
+ if (this.isMultiLineItem(line, "numberedList") && finished === false) {
498
+ newText += this.renumberLine(line, startIndex + i);
499
+ } else {
500
+ newText += line;
501
+ if (i > 0) {
502
+ finished = true; // As soon as we hit a line without a number we finished renumbering
503
+ }
504
+ }
505
+
506
+ newText += "\n";
507
+ });
508
+ return newText;
509
+ }
510
+
511
+ static renumberLine(text, number) {
512
+ const firstSpace = text.indexOf(". ");
513
+ return number + ". " + text.slice(firstSpace + 2);
514
+ }
515
+ }
@@ -52,7 +52,7 @@
52
52
  }
53
53
  }
54
54
 
55
- .properties-label-container, .properties-summary-link-container {
55
+ .properties-label-container, .properties-summary-link-container, .properties-checkbox-tooltip-container, .properties-radioset-panel {
56
56
  .tooltip-container {
57
57
  display: flex;
58
58
  width: 16px;
@@ -25,7 +25,7 @@ import VirtualizedTable from "./../virtualized-table/virtualized-table.jsx";
25
25
  import { SORT_DIRECTION, STATES, ROW_HEIGHT, ROW_SELECTION } from "./../../constants/constants";
26
26
  import ReactResizeDetector from "react-resize-detector";
27
27
  import classNames from "classnames";
28
- import { has } from "lodash";
28
+ import { has, isEmpty } from "lodash";
29
29
  import defaultMessages from "../../../../locales/common-properties/locales/en.json";
30
30
 
31
31
  class FlexibleTable extends React.Component {
@@ -79,7 +79,7 @@ class FlexibleTable extends React.Component {
79
79
  }
80
80
 
81
81
  // Calculate if checkedAllRows is true
82
- if (this.props.selectedRows) {
82
+ if (this.props.selectedRows && !isEmpty(this.props.data)) {
83
83
  this.setCheckedAll(this.props.selectedRows);
84
84
  }
85
85
 
@@ -506,6 +506,14 @@ class FlexibleTable extends React.Component {
506
506
  </div>)
507
507
  : null;
508
508
 
509
+ const emptyTableContent = isEmpty(this.props.data)
510
+ ? (
511
+ <div className="properties-ft-empty-table">
512
+ {this.props.emptyTablePlaceholder}
513
+ </div>
514
+ )
515
+ : null;
516
+
509
517
  return (
510
518
  <div data-id={"properties-ft-" + this.props.scrollKey} className="properties-ft-control-container" ref={ (ref) => (this.flexibleTable = ref) }>
511
519
  {ftHeader}
@@ -543,6 +551,7 @@ class FlexibleTable extends React.Component {
543
551
  </div>
544
552
  </ReactResizeDetector>
545
553
  </div>
554
+ {emptyTableContent}
546
555
  </div>
547
556
  );
548
557
  }
@@ -550,13 +559,15 @@ class FlexibleTable extends React.Component {
550
559
 
551
560
  FlexibleTable.defaultProps = {
552
561
  showHeader: true,
553
- light: true
562
+ light: true,
563
+ emptyTablePlaceholder: ""
554
564
  };
555
565
 
556
566
  FlexibleTable.propTypes = {
557
567
  sortable: PropTypes.array,
558
568
  columns: PropTypes.array.isRequired,
559
569
  data: PropTypes.array.isRequired,
570
+ emptyTablePlaceholder: PropTypes.string,
560
571
  filterable: PropTypes.array,
561
572
  filterBy: PropTypes.string,
562
573
  filterKeyword: PropTypes.string,
@@ -128,3 +128,23 @@ $row-left-padding: $spacing-02;
128
128
  }
129
129
  }
130
130
  }
131
+
132
+ .properties-ft-empty-table {
133
+ height: calc($spacing-11 + $spacing-08);
134
+ display: flex;
135
+ justify-content: center;
136
+ align-items: center;
137
+ @include carbon--type-style("body-long-01");
138
+ }
139
+
140
+ .properties-light-enabled {
141
+ .properties-ft-empty-table {
142
+ background-color: $ui-background;
143
+ }
144
+ }
145
+
146
+ .properties-light-disabled {
147
+ .properties-ft-empty-table {
148
+ background-color: $ui-01;
149
+ }
150
+ }
@@ -458,6 +458,7 @@ export default class AbstractTable extends React.Component {
458
458
  summaryTable
459
459
  rowSelection={ROW_SELECTION.MULTIPLE}
460
460
  light={this.props.controller.getLight()}
461
+ emptyTablePlaceholder={this.props.control.additionalText}
461
462
  />
462
463
  </div>);
463
464
  }
@@ -677,6 +678,7 @@ export default class AbstractTable extends React.Component {
677
678
  selectedRows= {this.props.selectedRows}
678
679
  rowSelection={this.props.control.rowSelection}
679
680
  light={this.props.controller.getLight()}
681
+ emptyTablePlaceholder={this.props.control.additionalText}
680
682
  />);
681
683
  return (
682
684
  <div>
@@ -25,7 +25,7 @@ import { STATES, CARBON_ICONS } from "./../../constants/constants.js";
25
25
  import Tooltip from "./../../../tooltip/tooltip.jsx";
26
26
  import { v4 as uuid4 } from "uuid";
27
27
  import classNames from "classnames";
28
- import Icon from "./../../../icons/icon.jsx";
28
+ import Icon from "./../../../icons/icon";
29
29
 
30
30
  class CheckboxControl extends React.Component {
31
31
 
@@ -21,9 +21,13 @@ import { Checkbox } from "carbon-components-react";
21
21
  import * as ControlUtils from "./../../util/control-utils";
22
22
  import classNames from "classnames";
23
23
  import ValidationMessage from "./../../components/validation-message";
24
- import { STATES } from "./../../constants/constants.js";
25
24
  import { v4 as uuid4 } from "uuid";
26
25
  import { intersection, isEqual } from "lodash";
26
+ import { Information16 } from "@carbon/icons-react";
27
+ import Tooltip from "./../../../tooltip/tooltip.jsx";
28
+ import { STATES } from "./../../constants/constants.js";
29
+ import { isEmpty } from "lodash";
30
+
27
31
 
28
32
  class CheckboxsetControl extends React.Component {
29
33
  constructor(props) {
@@ -74,27 +78,48 @@ class CheckboxsetControl extends React.Component {
74
78
  }
75
79
 
76
80
  render() {
81
+
82
+ const hidden = this.props.state === STATES.HIDDEN;
77
83
  let controlValue = this.props.value;
78
84
  if (typeof controlValue === "undefined" || controlValue === null) {
79
85
  controlValue = [];
80
86
  }
81
87
  const checkboxes = [];
82
88
  for (var i = 0; i < this.props.control.values.length; i++) {
89
+ const val = this.props.control.values[i];
90
+ const disabled = this.props.state === STATES.DISABLED || !this.props.controlOpts.values.includes(val);
91
+ let tooltipIcon = null;
92
+ if (Array.isArray(this.props.control.valueDescs) && !isEmpty(this.props.control.valueDescs[i]) && !this.props.tableControl) {
93
+ const tooltip = (
94
+ <span >{this.props.control.valueDescs[i]}</span>
95
+ );
96
+ tooltipIcon = (<Tooltip
97
+ id={`tooltip-${this.uuid}-${i}`}
98
+ tip={tooltip}
99
+ direction="bottom"
100
+ className="properties-tooltips"
101
+ showToolTipOnClick
102
+ disable={hidden || disabled}
103
+ >
104
+ <Information16 disabled={disabled} className="properties-control-description-icon-info" />
105
+ </Tooltip>);
106
+ }
83
107
  const id = {
84
108
  name: this.props.propertyId.name,
85
109
  row: i
86
110
  };
87
- const val = this.props.control.values[i];
88
111
  const checked = (controlValue.indexOf(val) >= 0);
89
- const disabled = this.props.state === STATES.DISABLED || !this.props.controlOpts.values.includes(val);
90
- checkboxes.push(<Checkbox
91
- disabled={disabled}
92
- id={ControlUtils.getControlId(id, this.uuid)}
93
- key={val + i}
94
- labelText={this.props.control.valueLabels[i]}
95
- onChange={this.handleChange.bind(this, val)}
96
- checked={checked}
97
- />);
112
+ checkboxes.push(<div className="properties-checkbox-tooltip-container" key={ControlUtils.getControlId(id, this.uuid)}>
113
+ <Checkbox
114
+ disabled={disabled}
115
+ id={ControlUtils.getControlId(id, this.uuid)}
116
+ key={val + i}
117
+ labelText={this.props.control.valueLabels[i]}
118
+ onChange={this.handleChange.bind(this, val)}
119
+ checked={checked}
120
+ />
121
+ {tooltipIcon}
122
+ </div>);
98
123
  }
99
124
  return (
100
125
  <fieldset>