@bpmn-io/form-js-editor 1.7.2 → 1.8.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.
@@ -211,22 +211,6 @@
211
211
  display: flex;
212
212
  }
213
213
 
214
- .fjs-no-json-lint .cm-lint-marker,
215
- .fjs-no-json-lint .cm-lintPoint-error {
216
- display: none;
217
- }
218
-
219
- .fjs-no-json-lint .cm-activeLine,
220
- .fjs-no-json-lint .cm-activeLineGutter {
221
- background: none;
222
- }
223
-
224
- .fjs-no-json-lint .cm-placeholder {
225
- font-size: 12px;
226
- line-height: 16px;
227
- color: var(--cds-text-placeholder, var(--color-grey-225-10-35));
228
- }
229
-
230
214
  .fjs-editor-container .fjs-form-editor {
231
215
  display: flex;
232
216
  flex: 1;
@@ -279,14 +263,21 @@
279
263
  border-color: var(--color-borders-group);
280
264
  }
281
265
 
266
+ .fjs-editor-container .fjs-children .fjs-element.fjs-dashed-outlined {
267
+ border-color: var(--color-borders-group);
268
+ border-style: dashed;
269
+ }
270
+
282
271
  .fjs-editor-container .fjs-children .fjs-element.fjs-editor-selected {
283
272
  border-color: var(--color-children-selected-border) !important;
284
273
  background-color: var(--color-children-selected-background);
274
+ border-style: solid;
285
275
  }
286
276
 
287
277
  .fjs-editor-container .fjs-children .fjs-element:hover.fjs-editor-hovered,
288
278
  .fjs-editor-container .fjs-children .fjs-element:focus {
289
279
  border-color: var(--color-children-hover-border);
280
+ border-style: solid;
290
281
  }
291
282
 
292
283
  .fjs-editor-container .fjs-layout-column:first-child > .fjs-element[data-field-type="group"],
@@ -722,6 +713,34 @@
722
713
  color: var(--color-palette-text);
723
714
  }
724
715
 
716
+ /**
717
+ * JSON Editors
718
+ */
719
+
720
+ .fjs-json-editor .cm-editor {
721
+ font-size: var(--font-size-label);
722
+ line-height: var(--line-height-label);
723
+ letter-spacing: var(--letter-spacing-label);
724
+ }
725
+
726
+ .fjs-json-editor .cm-placeholder {
727
+ color: var(--cds-text-placeholder, var(--color-grey-225-10-35));
728
+ }
729
+
730
+ .fjs-json-editor .cm-placeholder > :first-child {
731
+ margin-top: 0;
732
+ }
733
+
734
+ .fjs-json-editor.fjs-cm-no-lint .cm-lint-marker,
735
+ .fjs-json-editor.fjs-cm-no-lint .cm-lintPoint-error {
736
+ display: none;
737
+ }
738
+
739
+ .fjs-json-editor.fjs-cm-no-lint .cm-activeLine,
740
+ .fjs-json-editor.fjs-cm-no-lint .cm-activeLineGutter {
741
+ background: none;
742
+ }
743
+
725
744
  /**
726
745
  * Properties Panel
727
746
  */
@@ -189,22 +189,6 @@
189
189
  display: flex;
190
190
  }
191
191
 
192
- .fjs-no-json-lint .cm-lint-marker,
193
- .fjs-no-json-lint .cm-lintPoint-error {
194
- display: none;
195
- }
196
-
197
- .fjs-no-json-lint .cm-activeLine,
198
- .fjs-no-json-lint .cm-activeLineGutter {
199
- background: none;
200
- }
201
-
202
- .fjs-no-json-lint .cm-placeholder {
203
- font-size: 12px;
204
- line-height: 16px;
205
- color: var(--cds-text-placeholder, var(--color-grey-225-10-35));
206
- }
207
-
208
192
  .fjs-editor-container .fjs-form-editor {
209
193
  display: flex;
210
194
  flex: 1;
@@ -257,14 +241,21 @@
257
241
  border-color: var(--color-borders-group);
258
242
  }
259
243
 
244
+ .fjs-editor-container .fjs-children .fjs-element.fjs-dashed-outlined {
245
+ border-color: var(--color-borders-group);
246
+ border-style: dashed;
247
+ }
248
+
260
249
  .fjs-editor-container .fjs-children .fjs-element.fjs-editor-selected {
261
250
  border-color: var(--color-children-selected-border) !important;
262
251
  background-color: var(--color-children-selected-background);
252
+ border-style: solid;
263
253
  }
264
254
 
265
255
  .fjs-editor-container .fjs-children .fjs-element:hover.fjs-editor-hovered,
266
256
  .fjs-editor-container .fjs-children .fjs-element:focus {
267
257
  border-color: var(--color-children-hover-border);
258
+ border-style: solid;
268
259
  }
269
260
 
270
261
  .fjs-editor-container .fjs-layout-column:first-child > .fjs-element[data-field-type=group],
@@ -697,6 +688,33 @@
697
688
  color: var(--color-palette-text);
698
689
  }
699
690
 
691
+ /**
692
+ * JSON Editors
693
+ */
694
+ .fjs-json-editor .cm-editor {
695
+ font-size: var(--font-size-label);
696
+ line-height: var(--line-height-label);
697
+ letter-spacing: var(--letter-spacing-label);
698
+ }
699
+
700
+ .fjs-json-editor .cm-placeholder {
701
+ color: var(--cds-text-placeholder, var(--color-grey-225-10-35));
702
+ }
703
+
704
+ .fjs-json-editor .cm-placeholder > :first-child {
705
+ margin-top: 0;
706
+ }
707
+
708
+ .fjs-json-editor.fjs-cm-no-lint .cm-lint-marker,
709
+ .fjs-json-editor.fjs-cm-no-lint .cm-lintPoint-error {
710
+ display: none;
711
+ }
712
+
713
+ .fjs-json-editor.fjs-cm-no-lint .cm-activeLine,
714
+ .fjs-json-editor.fjs-cm-no-lint .cm-activeLineGutter {
715
+ background: none;
716
+ }
717
+
700
718
  /**
701
719
  * Properties Panel
702
720
  */
package/dist/index.cjs CHANGED
@@ -1142,7 +1142,36 @@ function EditorTable(props) {
1142
1142
  }
1143
1143
  EditorTable.config = formJsViewer.Table.config;
1144
1144
 
1145
- const editorFormFields = [EditorIFrame, EditorText, EditorHtml, EditorTable];
1145
+ const type = 'expression';
1146
+ function EditorExpressionField(props) {
1147
+ const {
1148
+ field
1149
+ } = props;
1150
+ const {
1151
+ expression = ''
1152
+ } = field;
1153
+ const Icon = formJsViewer.iconsByType('expression');
1154
+ const expressionLanguage = useService$1('expressionLanguage');
1155
+ let placeholderContent = 'Expression is empty';
1156
+ if (expression.trim() && expressionLanguage.isExpression(expression)) {
1157
+ placeholderContent = 'Expression';
1158
+ }
1159
+ return jsxRuntime.jsx("div", {
1160
+ class: editorFormFieldClasses(type),
1161
+ children: jsxRuntime.jsxs("div", {
1162
+ class: "fjs-form-field-placeholder",
1163
+ children: [jsxRuntime.jsx(Icon, {
1164
+ viewBox: "0 0 54 54"
1165
+ }), placeholderContent]
1166
+ })
1167
+ });
1168
+ }
1169
+ EditorExpressionField.config = {
1170
+ ...formJsViewer.ExpressionField.config,
1171
+ escapeGridRender: false
1172
+ };
1173
+
1174
+ const editorFormFields = [EditorIFrame, EditorText, EditorHtml, EditorTable, EditorExpressionField];
1146
1175
 
1147
1176
  class EditorFormFields extends formJsViewer.FormFields {
1148
1177
  constructor() {
@@ -1437,7 +1466,7 @@ function getIndefiniteArticle(type) {
1437
1466
  }
1438
1467
 
1439
1468
  const PALETTE_GROUPS = [{
1440
- label: 'Basic input',
1469
+ label: 'Input',
1441
1470
  id: 'basic-input'
1442
1471
  }, {
1443
1472
  label: 'Selection',
@@ -2159,7 +2188,6 @@ function Empty(props) {
2159
2188
  }
2160
2189
  function Element$1(props) {
2161
2190
  const eventBus = useService$1('eventBus'),
2162
- formEditor = useService$1('formEditor'),
2163
2191
  formFieldRegistry = useService$1('formFieldRegistry'),
2164
2192
  formFields = useService$1('formFields'),
2165
2193
  modeling = useService$1('modeling'),
@@ -2181,18 +2209,24 @@ function Element$1(props) {
2181
2209
  function scrollIntoView({
2182
2210
  selection
2183
2211
  }) {
2184
- if (!selection || selection.id !== id || !ref.current) {
2212
+ const scrollContainer = formJsViewer.getScrollContainer(ref.current);
2213
+ if (!selection || selection.type === 'default' || selection.id !== id || !scrollContainer || !ref.current) {
2185
2214
  return;
2186
2215
  }
2187
- const elementBounds = ref.current.getBoundingClientRect(),
2188
- containerBounds = formEditor._container.getBoundingClientRect();
2189
- if (elementBounds.top < 0 || elementBounds.top > containerBounds.bottom) {
2190
- ref.current.scrollIntoView();
2216
+ const elementBounds = ref.current.getBoundingClientRect();
2217
+ const scrollContainerBounds = scrollContainer.getBoundingClientRect();
2218
+ const isElementLarger = elementBounds.height > scrollContainerBounds.height;
2219
+ const isNotFullyVisible = elementBounds.bottom > scrollContainerBounds.bottom || elementBounds.top < scrollContainerBounds.top;
2220
+ if (isNotFullyVisible && !isElementLarger) {
2221
+ ref.current.scrollIntoView({
2222
+ behavior: 'auto',
2223
+ block: 'nearest'
2224
+ });
2191
2225
  }
2192
2226
  }
2193
2227
  eventBus.on('selection.changed', scrollIntoView);
2194
2228
  return () => eventBus.off('selection.changed', scrollIntoView);
2195
- }, [eventBus, formEditor._container, id]);
2229
+ }, [eventBus, id]);
2196
2230
  hooks.useLayoutEffect(() => {
2197
2231
  if (selection.isSelected(field)) {
2198
2232
  ref.current.focus();
@@ -2214,14 +2248,15 @@ function Element$1(props) {
2214
2248
  if (isSelected) {
2215
2249
  classes.push('fjs-editor-selected');
2216
2250
  }
2217
- if (showOutline) {
2218
- classes.push('fjs-outlined');
2251
+ const grouplike = ['group', 'dynamiclist'].includes(type);
2252
+ if (grouplike) {
2253
+ classes.push(showOutline ? 'fjs-outlined' : 'fjs-dashed-outlined');
2219
2254
  }
2220
2255
  if (hovered) {
2221
2256
  classes.push('fjs-editor-hovered');
2222
2257
  }
2223
2258
  return classes.join(' ');
2224
- }, [hovered, isSelected, props.class, showOutline]);
2259
+ }, [hovered, isSelected, props.class, showOutline, type]);
2225
2260
  const onRemove = event => {
2226
2261
  event.stopPropagation();
2227
2262
  const parentField = formFieldRegistry.get(field._parent);
@@ -5179,6 +5214,7 @@ class PaletteRenderer extends SectionModuleBase {
5179
5214
  PaletteRenderer.$inject = ['eventBus'];
5180
5215
 
5181
5216
  const PaletteModule = {
5217
+ __init__: ['palette'],
5182
5218
  palette: ['type', PaletteRenderer]
5183
5219
  };
5184
5220
 
@@ -8974,7 +9010,7 @@ function useVariables() {
8974
9010
  return formJsViewer.getSchemaVariables(schema);
8975
9011
  }
8976
9012
 
8977
- const headerlessTypes = ['spacer', 'separator', 'html'];
9013
+ const headerlessTypes = ['spacer', 'separator', 'expression', 'html'];
8978
9014
  const PropertiesPanelHeaderProvider = {
8979
9015
  getElementLabel: field => {
8980
9016
  const {
@@ -10793,6 +10829,83 @@ const validateNumberEntries = value => {
10793
10829
  }
10794
10830
  };
10795
10831
 
10832
+ function ExpressionFieldEntries(props) {
10833
+ const {
10834
+ editField,
10835
+ field,
10836
+ id
10837
+ } = props;
10838
+ const entries = [];
10839
+ entries.push({
10840
+ id: `${id}-expression`,
10841
+ component: ExpressionFieldExpression,
10842
+ isEdited: isEdited$6,
10843
+ editField,
10844
+ field,
10845
+ isDefaultVisible: field => field.type === 'expression'
10846
+ });
10847
+ entries.push({
10848
+ id: `${id}-computeOn`,
10849
+ component: ExpressionFieldComputeOn,
10850
+ isEdited: isEdited$3,
10851
+ editField,
10852
+ field,
10853
+ isDefaultVisible: field => field.type === 'expression'
10854
+ });
10855
+ return entries;
10856
+ }
10857
+ function ExpressionFieldExpression(props) {
10858
+ const {
10859
+ editField,
10860
+ field,
10861
+ id
10862
+ } = props;
10863
+ const debounce = useService('debounce');
10864
+ const variables = useVariables().map(name => ({
10865
+ name
10866
+ }));
10867
+ const getValue = () => field.expression || '';
10868
+ const setValue = value => {
10869
+ editField(field, ['expression'], value);
10870
+ };
10871
+ return FeelEntry({
10872
+ debounce,
10873
+ description: 'Define an expression to calculate the value of this field',
10874
+ element: field,
10875
+ feel: 'required',
10876
+ getValue,
10877
+ id,
10878
+ label: 'Target value',
10879
+ setValue,
10880
+ variables
10881
+ });
10882
+ }
10883
+ function ExpressionFieldComputeOn(props) {
10884
+ const {
10885
+ editField,
10886
+ field,
10887
+ id
10888
+ } = props;
10889
+ const getValue = () => field.computeOn || '';
10890
+ const setValue = value => {
10891
+ editField(field, ['computeOn'], value);
10892
+ };
10893
+ const getOptions = () => [{
10894
+ value: 'change',
10895
+ label: 'Value changes'
10896
+ }, {
10897
+ value: 'presubmit',
10898
+ label: 'Form submission'
10899
+ }];
10900
+ return SelectEntry({
10901
+ id,
10902
+ label: 'Compute on',
10903
+ getValue,
10904
+ setValue,
10905
+ getOptions
10906
+ });
10907
+ }
10908
+
10796
10909
  function NumberSerializationEntry(props) {
10797
10910
  const {
10798
10911
  editField,
@@ -11753,14 +11866,22 @@ function Condition(props) {
11753
11866
  hide: value
11754
11867
  });
11755
11868
  };
11869
+ let label = 'Hide if';
11870
+ let description = 'Condition under which the field is hidden';
11871
+
11872
+ // special case for expression fields which do not render
11873
+ if (field.type === 'expression') {
11874
+ label = 'Deactivate if';
11875
+ description = 'Condition under which the field is deactivated';
11876
+ }
11756
11877
  return FeelEntry({
11757
11878
  debounce,
11758
- description: 'Condition under which the field is hidden',
11879
+ description,
11759
11880
  element: field,
11760
11881
  feel: 'required',
11761
11882
  getValue,
11762
11883
  id,
11763
- label: 'Hide if',
11884
+ label,
11764
11885
  setValue,
11765
11886
  variables
11766
11887
  });
@@ -12380,6 +12501,9 @@ function GeneralGroup(field, editField, getService) {
12380
12501
  }), ...NumberEntries({
12381
12502
  field,
12382
12503
  editField
12504
+ }), ...ExpressionFieldEntries({
12505
+ field,
12506
+ editField
12383
12507
  }), ...ImageSourceEntry({
12384
12508
  field,
12385
12509
  editField