@bpmn-io/form-js-editor 1.4.1 → 1.5.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 (59) hide show
  1. package/dist/assets/form-js-editor-base.css +6 -6
  2. package/dist/assets/form-js-editor.css +6 -6
  3. package/dist/index.cjs +223 -66
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.es.js +224 -67
  6. package/dist/index.es.js.map +1 -1
  7. package/dist/types/core/Debounce.d.ts +1 -1
  8. package/dist/types/core/FormLayoutValidator.d.ts +2 -2
  9. package/dist/types/core/index.d.ts +9 -9
  10. package/dist/types/features/dragging/Dragging.d.ts +2 -2
  11. package/dist/types/features/dragging/index.d.ts +2 -2
  12. package/dist/types/features/editor-actions/FormEditorActions.d.ts +1 -1
  13. package/dist/types/features/editor-actions/index.d.ts +2 -2
  14. package/dist/types/features/expression-language/EditorTemplating.d.ts +1 -1
  15. package/dist/types/features/expression-language/index.d.ts +3 -3
  16. package/dist/types/features/keyboard/FormEditorKeyboardBindings.d.ts +1 -1
  17. package/dist/types/features/keyboard/index.d.ts +3 -3
  18. package/dist/types/features/modeling/FormLayoutUpdater.d.ts +1 -1
  19. package/dist/types/features/modeling/Modeling.d.ts +1 -1
  20. package/dist/types/features/modeling/behavior/IdBehavior.d.ts +1 -1
  21. package/dist/types/features/modeling/behavior/KeyBehavior.d.ts +1 -1
  22. package/dist/types/features/modeling/behavior/PathBehavior.d.ts +1 -1
  23. package/dist/types/features/modeling/behavior/ValidateBehavior.d.ts +1 -1
  24. package/dist/types/features/modeling/behavior/ValuesSourceBehavior.d.ts +1 -1
  25. package/dist/types/features/modeling/behavior/index.d.ts +6 -6
  26. package/dist/types/features/modeling/cmd/AddFormFieldHandler.d.ts +1 -1
  27. package/dist/types/features/modeling/cmd/EditFormFieldHandler.d.ts +1 -1
  28. package/dist/types/features/modeling/cmd/MoveFormFieldHandler.d.ts +4 -2
  29. package/dist/types/features/modeling/cmd/RemoveFormFieldHandler.d.ts +1 -1
  30. package/dist/types/features/modeling/cmd/UpdateIdClaimHandler.d.ts +1 -1
  31. package/dist/types/features/modeling/cmd/UpdateKeyClaimHandler.d.ts +1 -1
  32. package/dist/types/features/modeling/cmd/UpdatePathClaimHandler.d.ts +1 -1
  33. package/dist/types/features/modeling/index.d.ts +4 -4
  34. package/dist/types/features/palette/PaletteModule.d.ts +1 -1
  35. package/dist/types/features/palette/index.d.ts +1 -1
  36. package/dist/types/features/properties-panel/PropertiesPanelRenderer.d.ts +1 -1
  37. package/dist/types/features/properties-panel/PropertiesProvider.d.ts +1 -1
  38. package/dist/types/features/properties-panel/entries/GroupEntries.d.ts +2 -0
  39. package/dist/types/features/properties-panel/entries/HeightEntry.d.ts +12 -0
  40. package/dist/types/features/properties-panel/entries/IFrameHeightEntry.d.ts +10 -0
  41. package/dist/types/features/properties-panel/entries/IFrameUrlEntry.d.ts +10 -0
  42. package/dist/types/features/properties-panel/entries/SelectEntries.d.ts +2 -0
  43. package/dist/types/features/properties-panel/entries/factories/simpleBoolEntryFactory.d.ts +2 -0
  44. package/dist/types/features/properties-panel/entries/index.d.ts +3 -1
  45. package/dist/types/features/properties-panel/groups/GeneralGroup.d.ts +2 -0
  46. package/dist/types/features/properties-panel/index.d.ts +4 -4
  47. package/dist/types/features/render-injection/RenderInjector.d.ts +1 -1
  48. package/dist/types/features/render-injection/index.d.ts +2 -2
  49. package/dist/types/features/selection/Selection.d.ts +1 -1
  50. package/dist/types/features/selection/SelectionBehavior.d.ts +1 -1
  51. package/dist/types/features/selection/index.d.ts +3 -3
  52. package/dist/types/render/Renderer.d.ts +1 -1
  53. package/dist/types/render/components/ModularSection.d.ts +1 -1
  54. package/dist/types/render/components/editor-form-fields/EditorIFrame.d.ts +6 -0
  55. package/dist/types/render/components/editor-form-fields/EditorText.d.ts +1 -1
  56. package/dist/types/render/components/editor-form-fields/index.d.ts +2 -1
  57. package/dist/types/render/index.d.ts +3 -3
  58. package/package.json +3 -3
  59. package/dist/types/features/properties-panel/entries/SpacerEntry.d.ts +0 -10
package/dist/index.es.js CHANGED
@@ -1,9 +1,9 @@
1
- import { FormFieldRegistry as FormFieldRegistry$1, iconsByType, Text as Text$1, FormFields, sanitizeImageSource, FormContext, FormRenderContext, FormComponent, Importer, PathRegistry, FormLayouter, FieldFactory, runRecursively, clone, VALUES_SOURCES, VALUES_SOURCES_PATHS, getSchemaVariables, DATETIME_SUBTYPES, DATE_LABEL_PATH, TIME_LABEL_PATH, DATETIME_SUBTYPE_PATH, DATETIME_SUBTYPES_LABELS, TIME_SERIALISING_FORMAT_PATH, TIME_SERIALISING_FORMATS, TIME_INTERVAL_PATH, TIME_USE24H_PATH, DATE_DISALLOW_PAST_PATH, TIME_SERIALISINGFORMAT_LABELS, getValuesSource, VALUES_SOURCES_DEFAULTS, VALUES_SOURCES_LABELS, FeelExpressionLanguage, createFormContainer, createInjector, MarkdownModule, schemaVersion } from '@bpmn-io/form-js-viewer';
1
+ import { FormFieldRegistry as FormFieldRegistry$1, iconsByType, IFrame, Text as Text$1, FormFields, sanitizeImageSource, FormContext, FormRenderContext, FormComponent, Importer, PathRegistry, FormLayouter, FieldFactory, runRecursively, clone, VALUES_SOURCES, VALUES_SOURCES_PATHS, getSchemaVariables, DATETIME_SUBTYPES, DATE_LABEL_PATH, TIME_LABEL_PATH, DATETIME_SUBTYPE_PATH, DATETIME_SUBTYPES_LABELS, TIME_SERIALISING_FORMAT_PATH, TIME_SERIALISING_FORMATS, TIME_INTERVAL_PATH, TIME_USE24H_PATH, DATE_DISALLOW_PAST_PATH, TIME_SERIALISINGFORMAT_LABELS, getValuesSource, VALUES_SOURCES_DEFAULTS, VALUES_SOURCES_LABELS, FeelExpressionLanguage, createFormContainer, createInjector, MarkdownModule, schemaVersion } from '@bpmn-io/form-js-viewer';
2
2
  export { schemaVersion } from '@bpmn-io/form-js-viewer';
3
3
  import Ids from 'ids';
4
4
  import { isArray, isFunction, isNumber, bind, assign, debounce, forEach, get, isObject, uniqueBy, sortBy, find, isString, set as set$1, reduce, isUndefined, without, has } from 'min-dash';
5
- import classnames from 'classnames';
6
5
  import { jsx, jsxs, Fragment as Fragment$1 } from 'preact/jsx-runtime';
6
+ import classnames from 'classnames';
7
7
  import { useContext, useRef, useEffect, useMemo, useState, useCallback, useLayoutEffect } from 'preact/hooks';
8
8
  import { createContext, Fragment, render, createElement } from 'preact';
9
9
  import * as React from 'preact/compat';
@@ -644,6 +644,25 @@ function calculateMaxColumnsWithAuto(autoCols) {
644
644
  return MAX_COLUMNS_PER_ROW - autoCols * 2;
645
645
  }
646
646
 
647
+ function EditorIFrame(props) {
648
+ const {
649
+ field
650
+ } = props;
651
+ const Icon = iconsByType(field.type);
652
+ return jsx("div", {
653
+ class: "fjs-iframe-placeholder",
654
+ children: jsxs("p", {
655
+ class: "fjs-iframe-placeholder-text",
656
+ children: [jsx(Icon, {
657
+ width: "32",
658
+ height: "24",
659
+ viewBox: "0 0 56 56"
660
+ }), "iFrame"]
661
+ })
662
+ });
663
+ }
664
+ EditorIFrame.config = IFrame.config;
665
+
647
666
  const emptyImage = createEmptyImage();
648
667
  function editorFormFieldClasses(type, {
649
668
  disabled = false
@@ -979,7 +998,7 @@ function EditorText(props) {
979
998
  }
980
999
  EditorText.config = Text$1.config;
981
1000
 
982
- const editorFormFields = [EditorText];
1001
+ const editorFormFields = [EditorIFrame, EditorText];
983
1002
 
984
1003
  class EditorFormFields extends FormFields {
985
1004
  constructor() {
@@ -1278,6 +1297,9 @@ const PALETTE_GROUPS = [{
1278
1297
  }, {
1279
1298
  label: 'Presentation',
1280
1299
  id: 'presentation'
1300
+ }, {
1301
+ label: 'Containers',
1302
+ id: 'container'
1281
1303
  }, {
1282
1304
  label: 'Action',
1283
1305
  id: 'action'
@@ -3300,11 +3322,13 @@ class MoveFormFieldHandler {
3300
3322
  * @param { import('../../../FormEditor').default } formEditor
3301
3323
  * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3302
3324
  * @param { import('@bpmn-io/form-js-viewer').PathRegistry } pathRegistry
3325
+ * @param { import('@bpmn-io/form-js-viewer').FormLayouter } formLayouter
3303
3326
  */
3304
- constructor(formEditor, formFieldRegistry, pathRegistry) {
3327
+ constructor(formEditor, formFieldRegistry, pathRegistry, formLayouter) {
3305
3328
  this._formEditor = formEditor;
3306
3329
  this._formFieldRegistry = formFieldRegistry;
3307
3330
  this._pathRegistry = pathRegistry;
3331
+ this._formLayouter = formLayouter;
3308
3332
  }
3309
3333
  execute(context) {
3310
3334
  this.moveFormField(context);
@@ -3351,8 +3375,8 @@ class MoveFormFieldHandler {
3351
3375
  }
3352
3376
  const formField = get(schema, [...sourcePath, sourceIndex]);
3353
3377
 
3354
- // (1) Add to row
3355
- updateRow(formField, targetRow ? targetRow.id : null);
3378
+ // (1) Add to row or create new one
3379
+ updateRow(formField, targetRow ? targetRow.id : this._formLayouter.nextRowId());
3356
3380
 
3357
3381
  // (2) Move form field
3358
3382
  mutate(get(schema, sourcePath), sourceIndex, targetIndex);
@@ -3377,8 +3401,8 @@ class MoveFormFieldHandler {
3377
3401
  get(schema, sourcePath).forEach((formField, index) => updatePath(this._formFieldRegistry, formField, index));
3378
3402
  const targetPath = [...targetFormField._path, 'components'];
3379
3403
 
3380
- // (4) Add to row
3381
- updateRow(formField, targetRow ? targetRow.id : null);
3404
+ // (4) Add to row or create new one
3405
+ updateRow(formField, targetRow ? targetRow.id : this._formLayouter.nextRowId());
3382
3406
 
3383
3407
  // (5) Add form field
3384
3408
  arrayAdd$1(get(schema, targetPath), targetIndex, formField);
@@ -3401,7 +3425,7 @@ class MoveFormFieldHandler {
3401
3425
  });
3402
3426
  }
3403
3427
  }
3404
- MoveFormFieldHandler.$inject = ['formEditor', 'formFieldRegistry', 'pathRegistry'];
3428
+ MoveFormFieldHandler.$inject = ['formEditor', 'formFieldRegistry', 'pathRegistry', 'formLayouter'];
3405
3429
 
3406
3430
  class RemoveFormFieldHandler {
3407
3431
  /**
@@ -3991,12 +4015,21 @@ class FormLayoutUpdater extends CommandInterceptor {
3991
4015
  const {
3992
4016
  schema
3993
4017
  } = this._formEditor._getState();
4018
+ const setRowIds = parent => {
4019
+ if (!parent.components || !parent.components.length) {
4020
+ return;
4021
+ }
4022
+ parent.components.forEach(formField => {
4023
+ const row = this._formLayouter.getRowForField(formField);
4024
+ updateRow(formField, row.id);
4025
+
4026
+ // handle children recursively
4027
+ setRowIds(formField);
4028
+ });
4029
+ };
3994
4030
 
3995
4031
  // make sure rows are persisted in schema (e.g. for migration case)
3996
- schema.components.forEach(formField => {
3997
- const row = this._formLayouter.getRowForField(formField);
3998
- updateRow(formField, row.id);
3999
- });
4032
+ setRowIds(schema);
4000
4033
  }
4001
4034
  }
4002
4035
  FormLayoutUpdater.$inject = ['eventBus', 'formLayouter', 'modeling', 'formEditor'];
@@ -9540,6 +9573,8 @@ function simpleBoolEntryFactory(options) {
9540
9573
  description,
9541
9574
  path,
9542
9575
  props,
9576
+ getValue,
9577
+ setValue,
9543
9578
  isDefaultVisible
9544
9579
  } = options;
9545
9580
  const {
@@ -9554,8 +9589,10 @@ function simpleBoolEntryFactory(options) {
9554
9589
  editField,
9555
9590
  description,
9556
9591
  component: SimpleBoolComponent,
9557
- isEdited: isEdited$5,
9558
- isDefaultVisible
9592
+ isEdited: isEdited$8,
9593
+ isDefaultVisible,
9594
+ getValue,
9595
+ setValue
9559
9596
  };
9560
9597
  }
9561
9598
  const SimpleBoolComponent = props => {
@@ -9565,16 +9602,17 @@ const SimpleBoolComponent = props => {
9565
9602
  path,
9566
9603
  field,
9567
9604
  editField,
9605
+ getValue = () => get(field, path, ''),
9606
+ setValue = value => editField(field, path, value || false),
9568
9607
  description
9569
9608
  } = props;
9570
- const getValue = () => get(field, path, '');
9571
- const setValue = value => editField(field, path, value || false);
9572
- return CheckboxEntry({
9609
+ return ToggleSwitchEntry({
9573
9610
  element: field,
9574
9611
  getValue,
9575
9612
  id,
9576
9613
  label,
9577
9614
  setValue,
9615
+ inline: true,
9578
9616
  description
9579
9617
  });
9580
9618
  };
@@ -9630,7 +9668,7 @@ function LabelEntry(props) {
9630
9668
  editField,
9631
9669
  field,
9632
9670
  isEdited: isEdited$6,
9633
- isDefaultVisible: field => INPUTS.includes(field.type) || field.type === 'button' || field.type === 'group'
9671
+ isDefaultVisible: field => INPUTS.includes(field.type) || field.type === 'button' || field.type === 'group' || field.type === 'iframe'
9634
9672
  });
9635
9673
  return entries;
9636
9674
  }
@@ -9651,7 +9689,7 @@ function Label$1(props) {
9651
9689
  const setValue = value => {
9652
9690
  return editField(field, path, value || '');
9653
9691
  };
9654
- const label = field.type === 'group' ? 'Group label' : 'Field label';
9692
+ const label = getLabelText(field);
9655
9693
  return FeelTemplatingEntry({
9656
9694
  debounce,
9657
9695
  element: field,
@@ -9720,6 +9758,165 @@ function TimeLabel(props) {
9720
9758
  });
9721
9759
  }
9722
9760
 
9761
+ // helpers //////////
9762
+
9763
+ function getLabelText(field) {
9764
+ const {
9765
+ type
9766
+ } = field;
9767
+ if (type === 'group') {
9768
+ return 'Group label';
9769
+ }
9770
+ if (type === 'iframe') {
9771
+ return 'Title';
9772
+ }
9773
+ return 'Field label';
9774
+ }
9775
+
9776
+ function HeightEntry(props) {
9777
+ const {
9778
+ editField,
9779
+ field,
9780
+ id,
9781
+ description,
9782
+ isDefaultVisible,
9783
+ defaultValue
9784
+ } = props;
9785
+ const entries = [];
9786
+ entries.push({
9787
+ id: id + '-height',
9788
+ component: Height,
9789
+ description,
9790
+ isEdited: isEdited$7,
9791
+ editField,
9792
+ field,
9793
+ defaultValue,
9794
+ isDefaultVisible: field => {
9795
+ if (isFunction(isDefaultVisible)) {
9796
+ return isDefaultVisible(field);
9797
+ }
9798
+ return field.type === 'spacer';
9799
+ }
9800
+ });
9801
+ return entries;
9802
+ }
9803
+ function Height(props) {
9804
+ const {
9805
+ description,
9806
+ editField,
9807
+ field,
9808
+ id,
9809
+ defaultValue = 60 // default value for spacer
9810
+ } = props;
9811
+ const debounce = useService('debounce');
9812
+ const getValue = e => get(field, ['height'], defaultValue);
9813
+ const setValue = (value, error) => {
9814
+ if (error) {
9815
+ return;
9816
+ }
9817
+ editField(field, ['height'], value);
9818
+ };
9819
+ return NumberFieldEntry({
9820
+ debounce,
9821
+ description,
9822
+ label: 'Height',
9823
+ element: field,
9824
+ id,
9825
+ getValue,
9826
+ setValue,
9827
+ validate: value => {
9828
+ if (value === undefined || value === null) return;
9829
+ if (value < 1) return 'Should be greater than zero.';
9830
+ if (!Number.isInteger(value)) return 'Should be an integer.';
9831
+ }
9832
+ });
9833
+ }
9834
+
9835
+ function IFrameHeightEntry(props) {
9836
+ return [...HeightEntry({
9837
+ ...props,
9838
+ defaultValue: 300,
9839
+ description: 'Height of the container in pixels.',
9840
+ isDefaultVisible: field => field.type === 'iframe'
9841
+ })];
9842
+ }
9843
+
9844
+ const HTTPS_PATTERN = /^(https):\/\/*/i; // eslint-disable-line no-useless-escape
9845
+
9846
+ function IFrameUrlEntry(props) {
9847
+ const {
9848
+ editField,
9849
+ field
9850
+ } = props;
9851
+ const entries = [];
9852
+ entries.push({
9853
+ id: 'url',
9854
+ component: Url,
9855
+ editField: editField,
9856
+ field: field,
9857
+ isEdited: isEdited$6,
9858
+ isDefaultVisible: field => field.type === 'iframe'
9859
+ });
9860
+ return entries;
9861
+ }
9862
+ function Url(props) {
9863
+ const {
9864
+ editField,
9865
+ field,
9866
+ id
9867
+ } = props;
9868
+ const debounce = useService('debounce');
9869
+ const variables = useVariables().map(name => ({
9870
+ name
9871
+ }));
9872
+ const path = ['url'];
9873
+ const getValue = () => {
9874
+ return get(field, path, '');
9875
+ };
9876
+ const setValue = value => {
9877
+ return editField(field, path, value);
9878
+ };
9879
+ const validate = value => {
9880
+ if (!value) {
9881
+ return;
9882
+ }
9883
+ if (!HTTPS_PATTERN.test(value)) {
9884
+ return 'For security reasons the URL must start with "https".';
9885
+ }
9886
+ };
9887
+ return FeelTemplatingEntry({
9888
+ debounce,
9889
+ element: field,
9890
+ feel: 'optional',
9891
+ getValue,
9892
+ id,
9893
+ label: 'URL',
9894
+ setValue,
9895
+ singleLine: true,
9896
+ tooltip: getTooltip(),
9897
+ validate,
9898
+ variables
9899
+ });
9900
+ }
9901
+
9902
+ // helper //////////////////////
9903
+
9904
+ function getTooltip() {
9905
+ return jsxs(Fragment$1, {
9906
+ children: [jsx("p", {
9907
+ children: "Enter a HTTPS URL to a source or populate it dynamically via a template or an expression (e.g., to pass a value from the variable)."
9908
+ }), jsx("p", {
9909
+ children: "Please make sure that the URL is safe as it might impose security risks."
9910
+ }), jsxs("p", {
9911
+ children: ["Not all external sources can be displayed in the iFrame. Read more about it in the ", jsx("a", {
9912
+ target: "_blank",
9913
+ href: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options",
9914
+ children: "X-FRAME-OPTIONS documentation"
9915
+ }), "."]
9916
+ })]
9917
+ });
9918
+ }
9919
+
9723
9920
  function SourceEntry(props) {
9724
9921
  const {
9725
9922
  editField,
@@ -9832,52 +10029,6 @@ function Text(props) {
9832
10029
  });
9833
10030
  }
9834
10031
 
9835
- function SpacerEntry(props) {
9836
- const {
9837
- editField,
9838
- field,
9839
- id
9840
- } = props;
9841
- const entries = [];
9842
- entries.push({
9843
- id: id + '-height',
9844
- component: SpacerHeight,
9845
- isEdited: isEdited$7,
9846
- editField,
9847
- field,
9848
- isDefaultVisible: field => field.type === 'spacer'
9849
- });
9850
- return entries;
9851
- }
9852
- function SpacerHeight(props) {
9853
- const {
9854
- editField,
9855
- field,
9856
- id
9857
- } = props;
9858
- const debounce = useService('debounce');
9859
- const getValue = e => get(field, ['height']);
9860
- const setValue = (value, error) => {
9861
- if (error) {
9862
- return;
9863
- }
9864
- editField(field, ['height'], value);
9865
- };
9866
- return NumberFieldEntry({
9867
- debounce,
9868
- label: 'Height',
9869
- element: field,
9870
- id,
9871
- getValue,
9872
- setValue,
9873
- validate: value => {
9874
- if (value === undefined || value === null) return;
9875
- if (value < 1) return 'Should be greater than zero.';
9876
- if (!Number.isInteger(value)) return 'Should be an integer.';
9877
- }
9878
- });
9879
- }
9880
-
9881
10032
  function NumberEntries(props) {
9882
10033
  const {
9883
10034
  editField,
@@ -10948,7 +11099,13 @@ function GeneralGroup(field, editField, getService) {
10948
11099
  field,
10949
11100
  editField,
10950
11101
  getService
10951
- }), ...SpacerEntry({
11102
+ }), ...IFrameUrlEntry({
11103
+ field,
11104
+ editField
11105
+ }), ...IFrameHeightEntry({
11106
+ field,
11107
+ editField
11108
+ }), ...HeightEntry({
10952
11109
  field,
10953
11110
  editField
10954
11111
  }), ...NumberEntries({