@bpmn-io/form-js-editor 1.7.3 → 1.8.1

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.
package/dist/index.cjs CHANGED
@@ -147,6 +147,8 @@ var slice = Array.prototype.slice;
147
147
  * var sum = eventBus.fire('sum', 1, 2);
148
148
  * console.log(sum); // 3
149
149
  * ```
150
+ *
151
+ * @template [EventMap=null]
150
152
  */
151
153
  function EventBus() {
152
154
  /**
@@ -160,6 +162,8 @@ function EventBus() {
160
162
  }
161
163
 
162
164
  /**
165
+ * @overlord
166
+ *
163
167
  * Register an event listener for events with the given name.
164
168
  *
165
169
  * The callback will be invoked with `event, ...additionalArguments`
@@ -178,6 +182,25 @@ function EventBus() {
178
182
  * @param {EventBusEventCallback<T>} callback
179
183
  * @param {any} [that] callback context
180
184
  */
185
+ /**
186
+ * Register an event listener for events with the given name.
187
+ *
188
+ * The callback will be invoked with `event, ...additionalArguments`
189
+ * that have been passed to {@link EventBus#fire}.
190
+ *
191
+ * Returning false from a listener will prevent the events default action
192
+ * (if any is specified). To stop an event from being processed further in
193
+ * other listeners execute {@link Event#stopPropagation}.
194
+ *
195
+ * Returning anything but `undefined` from a listener will stop the listener propagation.
196
+ *
197
+ * @template {keyof EventMap} EventName
198
+ *
199
+ * @param {EventName} events to subscribe to
200
+ * @param {number} [priority=1000] listen priority
201
+ * @param {EventBusEventCallback<EventMap[EventName]>} callback
202
+ * @param {any} [that] callback context
203
+ */
181
204
  EventBus.prototype.on = function (events, priority, callback, that) {
182
205
  events = minDash.isArray(events) ? events : [events];
183
206
  if (minDash.isFunction(priority)) {
@@ -208,6 +231,8 @@ EventBus.prototype.on = function (events, priority, callback, that) {
208
231
  };
209
232
 
210
233
  /**
234
+ * @overlord
235
+ *
211
236
  * Register an event listener that is called only once.
212
237
  *
213
238
  * @template T
@@ -217,6 +242,16 @@ EventBus.prototype.on = function (events, priority, callback, that) {
217
242
  * @param {EventBusEventCallback<T>} callback
218
243
  * @param {any} [that] callback context
219
244
  */
245
+ /**
246
+ * Register an event listener that is called only once.
247
+ *
248
+ * @template {keyof EventMap} EventName
249
+ *
250
+ * @param {EventName} events to subscribe to
251
+ * @param {number} [priority=1000] listen priority
252
+ * @param {EventBusEventCallback<EventMap[EventName]>} callback
253
+ * @param {any} [that] callback context
254
+ */
220
255
  EventBus.prototype.once = function (events, priority, callback, that) {
221
256
  var self = this;
222
257
  if (minDash.isFunction(priority)) {
@@ -1142,7 +1177,36 @@ function EditorTable(props) {
1142
1177
  }
1143
1178
  EditorTable.config = formJsViewer.Table.config;
1144
1179
 
1145
- const editorFormFields = [EditorIFrame, EditorText, EditorHtml, EditorTable];
1180
+ const type = 'expression';
1181
+ function EditorExpressionField(props) {
1182
+ const {
1183
+ field
1184
+ } = props;
1185
+ const {
1186
+ expression = ''
1187
+ } = field;
1188
+ const Icon = formJsViewer.iconsByType('expression');
1189
+ const expressionLanguage = useService$1('expressionLanguage');
1190
+ let placeholderContent = 'Expression is empty';
1191
+ if (expression.trim() && expressionLanguage.isExpression(expression)) {
1192
+ placeholderContent = 'Expression';
1193
+ }
1194
+ return jsxRuntime.jsx("div", {
1195
+ class: editorFormFieldClasses(type),
1196
+ children: jsxRuntime.jsxs("div", {
1197
+ class: "fjs-form-field-placeholder",
1198
+ children: [jsxRuntime.jsx(Icon, {
1199
+ viewBox: "0 0 54 54"
1200
+ }), placeholderContent]
1201
+ })
1202
+ });
1203
+ }
1204
+ EditorExpressionField.config = {
1205
+ ...formJsViewer.ExpressionField.config,
1206
+ escapeGridRender: false
1207
+ };
1208
+
1209
+ const editorFormFields = [EditorIFrame, EditorText, EditorHtml, EditorTable, EditorExpressionField];
1146
1210
 
1147
1211
  class EditorFormFields extends formJsViewer.FormFields {
1148
1212
  constructor() {
@@ -1437,7 +1501,7 @@ function getIndefiniteArticle(type) {
1437
1501
  }
1438
1502
 
1439
1503
  const PALETTE_GROUPS = [{
1440
- label: 'Basic input',
1504
+ label: 'Input',
1441
1505
  id: 'basic-input'
1442
1506
  }, {
1443
1507
  label: 'Selection',
@@ -2159,7 +2223,6 @@ function Empty(props) {
2159
2223
  }
2160
2224
  function Element$1(props) {
2161
2225
  const eventBus = useService$1('eventBus'),
2162
- formEditor = useService$1('formEditor'),
2163
2226
  formFieldRegistry = useService$1('formFieldRegistry'),
2164
2227
  formFields = useService$1('formFields'),
2165
2228
  modeling = useService$1('modeling'),
@@ -2181,18 +2244,24 @@ function Element$1(props) {
2181
2244
  function scrollIntoView({
2182
2245
  selection
2183
2246
  }) {
2184
- if (!selection || selection.id !== id || !ref.current) {
2247
+ const scrollContainer = formJsViewer.getScrollContainer(ref.current);
2248
+ if (!selection || selection.type === 'default' || selection.id !== id || !scrollContainer || !ref.current) {
2185
2249
  return;
2186
2250
  }
2187
- const elementBounds = ref.current.getBoundingClientRect(),
2188
- containerBounds = formEditor._container.getBoundingClientRect();
2189
- if (elementBounds.top < 0 || elementBounds.top > containerBounds.bottom) {
2190
- ref.current.scrollIntoView();
2251
+ const elementBounds = ref.current.getBoundingClientRect();
2252
+ const scrollContainerBounds = scrollContainer.getBoundingClientRect();
2253
+ const isElementLarger = elementBounds.height > scrollContainerBounds.height;
2254
+ const isNotFullyVisible = elementBounds.bottom > scrollContainerBounds.bottom || elementBounds.top < scrollContainerBounds.top;
2255
+ if (isNotFullyVisible && !isElementLarger) {
2256
+ ref.current.scrollIntoView({
2257
+ behavior: 'auto',
2258
+ block: 'nearest'
2259
+ });
2191
2260
  }
2192
2261
  }
2193
2262
  eventBus.on('selection.changed', scrollIntoView);
2194
2263
  return () => eventBus.off('selection.changed', scrollIntoView);
2195
- }, [eventBus, formEditor._container, id]);
2264
+ }, [eventBus, id]);
2196
2265
  hooks.useLayoutEffect(() => {
2197
2266
  if (selection.isSelected(field)) {
2198
2267
  ref.current.focus();
@@ -2214,14 +2283,15 @@ function Element$1(props) {
2214
2283
  if (isSelected) {
2215
2284
  classes.push('fjs-editor-selected');
2216
2285
  }
2217
- if (showOutline) {
2218
- classes.push('fjs-outlined');
2286
+ const grouplike = ['group', 'dynamiclist'].includes(type);
2287
+ if (grouplike) {
2288
+ classes.push(showOutline ? 'fjs-outlined' : 'fjs-dashed-outlined');
2219
2289
  }
2220
2290
  if (hovered) {
2221
2291
  classes.push('fjs-editor-hovered');
2222
2292
  }
2223
2293
  return classes.join(' ');
2224
- }, [hovered, isSelected, props.class, showOutline]);
2294
+ }, [hovered, isSelected, props.class, showOutline, type]);
2225
2295
  const onRemove = event => {
2226
2296
  event.stopPropagation();
2227
2297
  const parentField = formFieldRegistry.get(field._parent);
@@ -2853,9 +2923,9 @@ EditorActions.prototype.unregister = function (action) {
2853
2923
  };
2854
2924
 
2855
2925
  /**
2856
- * Returns the number of actions that are currently registered
2926
+ * Returns the identifiers of all currently registered editor actions
2857
2927
  *
2858
- * @return {number}
2928
+ * @return {string[]}
2859
2929
  */
2860
2930
  EditorActions.prototype.getActions = function () {
2861
2931
  return Object.keys(this._actions);
@@ -3108,7 +3178,7 @@ Keyboard.prototype._isEventIgnored = function (event) {
3108
3178
  if (event.defaultPrevented) {
3109
3179
  return true;
3110
3180
  }
3111
- return isInput(event.target) && this._isModifiedKeyIgnored(event);
3181
+ return (isInput(event.target) || isButton(event.target) && isKey([' ', 'Enter'], event)) && this._isModifiedKeyIgnored(event);
3112
3182
  };
3113
3183
  Keyboard.prototype._isModifiedKeyIgnored = function (event) {
3114
3184
  if (!isCmd(event)) {
@@ -3205,6 +3275,9 @@ Keyboard.prototype.isKey = isKey;
3205
3275
  function isInput(target) {
3206
3276
  return target && (minDom.matches(target, 'input, textarea') || target.contentEditable === 'true');
3207
3277
  }
3278
+ function isButton(target) {
3279
+ return target && minDom.matches(target, 'button, input[type=submit], input[type=button], a[href], [aria-role=button]');
3280
+ }
3208
3281
 
3209
3282
  var LOW_PRIORITY$1 = 500;
3210
3283
 
@@ -5179,6 +5252,7 @@ class PaletteRenderer extends SectionModuleBase {
5179
5252
  PaletteRenderer.$inject = ['eventBus'];
5180
5253
 
5181
5254
  const PaletteModule = {
5255
+ __init__: ['palette'],
5182
5256
  palette: ['type', PaletteRenderer]
5183
5257
  };
5184
5258
 
@@ -8974,7 +9048,7 @@ function useVariables() {
8974
9048
  return formJsViewer.getSchemaVariables(schema);
8975
9049
  }
8976
9050
 
8977
- const headerlessTypes = ['spacer', 'separator', 'html'];
9051
+ const headerlessTypes = ['spacer', 'separator', 'expression', 'html'];
8978
9052
  const PropertiesPanelHeaderProvider = {
8979
9053
  getElementLabel: field => {
8980
9054
  const {
@@ -10793,6 +10867,83 @@ const validateNumberEntries = value => {
10793
10867
  }
10794
10868
  };
10795
10869
 
10870
+ function ExpressionFieldEntries(props) {
10871
+ const {
10872
+ editField,
10873
+ field,
10874
+ id
10875
+ } = props;
10876
+ const entries = [];
10877
+ entries.push({
10878
+ id: `${id}-expression`,
10879
+ component: ExpressionFieldExpression,
10880
+ isEdited: isEdited$6,
10881
+ editField,
10882
+ field,
10883
+ isDefaultVisible: field => field.type === 'expression'
10884
+ });
10885
+ entries.push({
10886
+ id: `${id}-computeOn`,
10887
+ component: ExpressionFieldComputeOn,
10888
+ isEdited: isEdited$3,
10889
+ editField,
10890
+ field,
10891
+ isDefaultVisible: field => field.type === 'expression'
10892
+ });
10893
+ return entries;
10894
+ }
10895
+ function ExpressionFieldExpression(props) {
10896
+ const {
10897
+ editField,
10898
+ field,
10899
+ id
10900
+ } = props;
10901
+ const debounce = useService('debounce');
10902
+ const variables = useVariables().map(name => ({
10903
+ name
10904
+ }));
10905
+ const getValue = () => field.expression || '';
10906
+ const setValue = value => {
10907
+ editField(field, ['expression'], value);
10908
+ };
10909
+ return FeelEntry({
10910
+ debounce,
10911
+ description: 'Define an expression to calculate the value of this field',
10912
+ element: field,
10913
+ feel: 'required',
10914
+ getValue,
10915
+ id,
10916
+ label: 'Target value',
10917
+ setValue,
10918
+ variables
10919
+ });
10920
+ }
10921
+ function ExpressionFieldComputeOn(props) {
10922
+ const {
10923
+ editField,
10924
+ field,
10925
+ id
10926
+ } = props;
10927
+ const getValue = () => field.computeOn || '';
10928
+ const setValue = value => {
10929
+ editField(field, ['computeOn'], value);
10930
+ };
10931
+ const getOptions = () => [{
10932
+ value: 'change',
10933
+ label: 'Value changes'
10934
+ }, {
10935
+ value: 'presubmit',
10936
+ label: 'Form submission'
10937
+ }];
10938
+ return SelectEntry({
10939
+ id,
10940
+ label: 'Compute on',
10941
+ getValue,
10942
+ setValue,
10943
+ getOptions
10944
+ });
10945
+ }
10946
+
10796
10947
  function NumberSerializationEntry(props) {
10797
10948
  const {
10798
10949
  editField,
@@ -11753,14 +11904,22 @@ function Condition(props) {
11753
11904
  hide: value
11754
11905
  });
11755
11906
  };
11907
+ let label = 'Hide if';
11908
+ let description = 'Condition under which the field is hidden';
11909
+
11910
+ // special case for expression fields which do not render
11911
+ if (field.type === 'expression') {
11912
+ label = 'Deactivate if';
11913
+ description = 'Condition under which the field is deactivated';
11914
+ }
11756
11915
  return FeelEntry({
11757
11916
  debounce,
11758
- description: 'Condition under which the field is hidden',
11917
+ description,
11759
11918
  element: field,
11760
11919
  feel: 'required',
11761
11920
  getValue,
11762
11921
  id,
11763
- label: 'Hide if',
11922
+ label,
11764
11923
  setValue,
11765
11924
  variables
11766
11925
  });
@@ -12380,6 +12539,9 @@ function GeneralGroup(field, editField, getService) {
12380
12539
  }), ...NumberEntries({
12381
12540
  field,
12382
12541
  editField
12542
+ }), ...ExpressionFieldEntries({
12543
+ field,
12544
+ editField
12383
12545
  }), ...ImageSourceEntry({
12384
12546
  field,
12385
12547
  editField