@bpmn-io/form-js-viewer 0.8.0-alpha.1 → 0.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.
Files changed (49) hide show
  1. package/LICENSE +22 -22
  2. package/README.md +158 -158
  3. package/dist/assets/form-js.css +339 -339
  4. package/dist/index.cjs +113 -110
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.es.js +113 -110
  7. package/dist/index.es.js.map +1 -1
  8. package/dist/types/Form.d.ts +136 -136
  9. package/dist/types/core/EventBus.d.ts +1 -1
  10. package/dist/types/core/FormFieldRegistry.d.ts +17 -17
  11. package/dist/types/core/Validator.d.ts +7 -7
  12. package/dist/types/core/index.d.ts +16 -16
  13. package/dist/types/import/Importer.d.ts +43 -43
  14. package/dist/types/import/index.d.ts +5 -5
  15. package/dist/types/index.d.ts +18 -18
  16. package/dist/types/render/FormFields.d.ts +5 -5
  17. package/dist/types/render/Renderer.d.ts +23 -23
  18. package/dist/types/render/components/Description.d.ts +1 -1
  19. package/dist/types/render/components/Errors.d.ts +1 -1
  20. package/dist/types/render/components/FormComponent.d.ts +1 -1
  21. package/dist/types/render/components/FormField.d.ts +1 -1
  22. package/dist/types/render/components/Label.d.ts +1 -1
  23. package/dist/types/render/components/PoweredBy.d.ts +1 -1
  24. package/dist/types/render/components/Sanitizer.d.ts +7 -7
  25. package/dist/types/render/components/Util.d.ts +6 -6
  26. package/dist/types/render/components/form-fields/Button.d.ts +11 -11
  27. package/dist/types/render/components/form-fields/Checkbox.d.ts +13 -13
  28. package/dist/types/render/components/form-fields/Checklist.d.ts +12 -12
  29. package/dist/types/render/components/form-fields/Default.d.ts +9 -9
  30. package/dist/types/render/components/form-fields/Number.d.ts +13 -13
  31. package/dist/types/render/components/form-fields/Radio.d.ts +12 -12
  32. package/dist/types/render/components/form-fields/Select.d.ts +12 -12
  33. package/dist/types/render/components/form-fields/Taglist.d.ts +12 -12
  34. package/dist/types/render/components/form-fields/Text.d.ts +10 -10
  35. package/dist/types/render/components/form-fields/Textfield.d.ts +13 -13
  36. package/dist/types/render/components/form-fields/parts/DropdownList.d.ts +1 -1
  37. package/dist/types/render/components/index.d.ts +13 -13
  38. package/dist/types/render/context/FormContext.d.ts +12 -12
  39. package/dist/types/render/context/FormRenderContext.d.ts +6 -6
  40. package/dist/types/render/context/index.d.ts +2 -2
  41. package/dist/types/render/hooks/useKeyDownAction.d.ts +1 -1
  42. package/dist/types/render/hooks/useService.d.ts +1 -1
  43. package/dist/types/render/hooks/useValuesAsync.d.ts +28 -28
  44. package/dist/types/render/index.d.ts +11 -11
  45. package/dist/types/types.d.ts +35 -35
  46. package/dist/types/util/form.d.ts +6 -6
  47. package/dist/types/util/index.d.ts +24 -24
  48. package/dist/types/util/injector.d.ts +2 -2
  49. package/package.json +3 -3
package/dist/index.cjs CHANGED
@@ -606,10 +606,10 @@ function createInjector(bootstrapModules) {
606
606
  return injector;
607
607
  }
608
608
 
609
- /**
610
- * @param {string?} prefix
611
- *
612
- * @returns Element
609
+ /**
610
+ * @param {string?} prefix
611
+ *
612
+ * @returns Element
613
613
  */
614
614
  function createFormContainer(prefix = 'fjs') {
615
615
  const container = document.createElement('div');
@@ -655,22 +655,22 @@ function generateIndexForType(type) {
655
655
  function generateIdForType(type) {
656
656
  return `${type}${generateIndexForType(type)}`;
657
657
  }
658
- /**
659
- * @template T
660
- * @param {T} data
661
- * @param {(this: any, key: string, value: any) => any} [replacer]
662
- * @return {T}
658
+ /**
659
+ * @template T
660
+ * @param {T} data
661
+ * @param {(this: any, key: string, value: any) => any} [replacer]
662
+ * @return {T}
663
663
  */
664
664
 
665
665
  function clone(data, replacer) {
666
666
  return JSON.parse(JSON.stringify(data, replacer));
667
667
  }
668
- /**
669
- * Parse the schema for input variables a form might make use of
670
- *
671
- * @param {any} schema
672
- *
673
- * @return {string[]}
668
+ /**
669
+ * Parse the schema for input variables a form might make use of
670
+ *
671
+ * @param {any} schema
672
+ *
673
+ * @return {string[]}
674
674
  */
675
675
 
676
676
  function getSchemaVariables(schema) {
@@ -702,24 +702,24 @@ function getSchemaVariables(schema) {
702
702
  }
703
703
 
704
704
  class Importer {
705
- /**
706
- * @constructor
707
- * @param { import('../core').FormFieldRegistry } formFieldRegistry
708
- * @param { import('../render/FormFields').default } formFields
705
+ /**
706
+ * @constructor
707
+ * @param { import('../core').FormFieldRegistry } formFieldRegistry
708
+ * @param { import('../render/FormFields').default } formFields
709
709
  */
710
710
  constructor(formFieldRegistry, formFields) {
711
711
  this._formFieldRegistry = formFieldRegistry;
712
712
  this._formFields = formFields;
713
713
  }
714
- /**
715
- * Import schema adding `id`, `_parent` and `_path`
716
- * information to each field and adding it to the
717
- * form field registry.
718
- *
719
- * @param {any} schema
720
- * @param {any} [data]
721
- *
722
- * @return { { warnings: Array<any>, schema: any, data: any } }
714
+ /**
715
+ * Import schema adding `id`, `_parent` and `_path`
716
+ * information to each field and adding it to the
717
+ * form field registry.
718
+ *
719
+ * @param {any} schema
720
+ * @param {any} [data]
721
+ *
722
+ * @return { { warnings: Array<any>, schema: any, data: any } }
723
723
  */
724
724
 
725
725
 
@@ -740,11 +740,11 @@ class Importer {
740
740
  throw err;
741
741
  }
742
742
  }
743
- /**
744
- * @param {any} formField
745
- * @param {string} [parentId]
746
- *
747
- * @return {any} importedField
743
+ /**
744
+ * @param {any} formField
745
+ * @param {string} [parentId]
746
+ *
747
+ * @return {any} importedField
748
748
  */
749
749
 
750
750
 
@@ -806,10 +806,10 @@ class Importer {
806
806
  this.importFormField(component, parentId);
807
807
  });
808
808
  }
809
- /**
810
- * @param {Object} data
811
- *
812
- * @return {Object} importedData
809
+ /**
810
+ * @param {Object} data
811
+ *
812
+ * @return {Object} importedData
813
813
  */
814
814
 
815
815
 
@@ -870,11 +870,11 @@ const ALLOWED_URI_PATTERN = /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^
870
870
  const ATTR_WHITESPACE_PATTERN = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g; // eslint-disable-line no-control-regex
871
871
 
872
872
  const FORM_ELEMENT = document.createElement('form');
873
- /**
874
- * Sanitize a HTML string and return the cleaned, safe version.
875
- *
876
- * @param {string} html
877
- * @return {string}
873
+ /**
874
+ * Sanitize a HTML string and return the cleaned, safe version.
875
+ *
876
+ * @param {string} html
877
+ * @return {string}
878
878
  */
879
879
 
880
880
  function sanitizeHTML(html) {
@@ -893,15 +893,15 @@ function sanitizeHTML(html) {
893
893
  return '';
894
894
  }
895
895
  }
896
- /**
897
- * Recursively sanitize a HTML node, potentially
898
- * removing it, its children or attributes.
899
- *
900
- * Inspired by https://github.com/developit/snarkdown/issues/70
901
- * and https://github.com/cure53/DOMPurify. Simplified
902
- * for our use-case.
903
- *
904
- * @param {Element} node
896
+ /**
897
+ * Recursively sanitize a HTML node, potentially
898
+ * removing it, its children or attributes.
899
+ *
900
+ * Inspired by https://github.com/developit/snarkdown/issues/70
901
+ * and https://github.com/cure53/DOMPurify. Simplified
902
+ * for our use-case.
903
+ *
904
+ * @param {Element} node
905
905
  */
906
906
 
907
907
  function sanitizeNode(node) {
@@ -948,13 +948,13 @@ function sanitizeNode(node) {
948
948
  node.childNodes[i]);
949
949
  }
950
950
  }
951
- /**
952
- * Validates attributes for validity.
953
- *
954
- * @param {string} lcTag
955
- * @param {string} lcName
956
- * @param {string} value
957
- * @return {boolean}
951
+ /**
952
+ * Validates attributes for validity.
953
+ *
954
+ * @param {string} lcTag
955
+ * @param {string} lcName
956
+ * @param {string} value
957
+ * @return {boolean}
958
958
  */
959
959
 
960
960
 
@@ -1094,11 +1094,11 @@ const FormRenderContext = preact.createContext({
1094
1094
  }
1095
1095
  });
1096
1096
 
1097
- /**
1098
- * @param {string} type
1099
- * @param {boolean} [strict]
1100
- *
1101
- * @returns {any}
1097
+ /**
1098
+ * @param {string} type
1099
+ * @param {boolean} [strict]
1100
+ *
1101
+ * @returns {any}
1102
1102
  */
1103
1103
 
1104
1104
  function getService(type, strict) {}
@@ -1229,8 +1229,8 @@ function useService (type, strict) {
1229
1229
  return getService(type, strict);
1230
1230
  }
1231
1231
 
1232
- /**
1233
- * @enum { String }
1232
+ /**
1233
+ * @enum { String }
1234
1234
  */
1235
1235
 
1236
1236
  const LOAD_STATES = {
@@ -1238,17 +1238,17 @@ const LOAD_STATES = {
1238
1238
  LOADED: 'loaded',
1239
1239
  ERROR: 'error'
1240
1240
  };
1241
- /**
1242
- * @typedef {Object} ValuesGetter
1243
- * @property {Object[]} values - The values data
1244
- * @property {(LOAD_STATES)} state - The values data's loading state, to use for conditional rendering
1241
+ /**
1242
+ * @typedef {Object} ValuesGetter
1243
+ * @property {Object[]} values - The values data
1244
+ * @property {(LOAD_STATES)} state - The values data's loading state, to use for conditional rendering
1245
1245
  */
1246
1246
 
1247
- /**
1248
- * A hook to load values for single and multiselect components.
1249
- *
1250
- * @param {Object} field - The form field to handle values for
1251
- * @return {ValuesGetter} valuesGetter - A values getter object providing loading state and values
1247
+ /**
1248
+ * A hook to load values for single and multiselect components.
1249
+ *
1250
+ * @param {Object} field - The form field to handle values for
1251
+ * @return {ValuesGetter} valuesGetter - A values getter object providing loading state and values
1252
1252
  */
1253
1253
 
1254
1254
  function useValuesAsync (field) {
@@ -1451,10 +1451,10 @@ Default.create = function (options = {}) {
1451
1451
  Default.type = 'default';
1452
1452
  Default.keyed = false;
1453
1453
 
1454
- /**
1455
- * This file must not be changed or exchanged.
1456
- *
1457
- * @see http://bpmn.io/license for more information.
1454
+ /**
1455
+ * This file must not be changed or exchanged.
1456
+ *
1457
+ * @see http://bpmn.io/license for more information.
1458
1458
  */
1459
1459
 
1460
1460
  function Logo() {
@@ -1809,7 +1809,7 @@ Select.keyed = true;
1809
1809
  Select.emptyValue = null;
1810
1810
  Select.sanitizeValue = sanitizeSingleSelectValue;
1811
1811
 
1812
- function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
1812
+ function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
1813
1813
  var CloseIcon = (({
1814
1814
  styles = {},
1815
1815
  ...props
@@ -1958,35 +1958,30 @@ function Taglist(props) {
1958
1958
  formId
1959
1959
  } = hooks.useContext(FormContext);
1960
1960
  const [filter, setFilter] = hooks.useState('');
1961
- const [selectedValues, setSelectedValues] = hooks.useState([]);
1962
- const [filteredValues, setFilteredValues] = hooks.useState([]);
1961
+ const [filteredOptions, setFilteredOptions] = hooks.useState([]);
1963
1962
  const [isDropdownExpanded, setIsDropdownExpanded] = hooks.useState(false);
1964
- const [hasValuesLeft, setHasValuesLeft] = hooks.useState(true);
1963
+ const [hasOptionsLeft, setHasOptionsLeft] = hooks.useState(true);
1965
1964
  const [isEscapeClosed, setIsEscapeClose] = hooks.useState(false);
1966
1965
  const searchbarRef = hooks.useRef();
1967
1966
  const {
1968
1967
  state: loadState,
1969
1968
  values: options
1970
- } = useValuesAsync(field); // Usage of stringify is necessary here because we want this effect to only trigger when there is a value change to the array
1969
+ } = useValuesAsync(field); // We cache a map of option values to their index so that we don't need to search the whole options array every time to correlate the label
1970
+
1971
+ const valueToOptionMap = hooks.useMemo(() => Object.assign({}, ...options.map((o, x) => ({
1972
+ [o.value]: options[x]
1973
+ }))), [options]); // Usage of stringify is necessary here because we want this effect to only trigger when there is a value change to the array
1971
1974
 
1972
1975
  hooks.useEffect(() => {
1973
1976
  if (loadState === LOAD_STATES.LOADED) {
1974
- const selectedValues = values.map(v => options.find(o => o.value === v)).filter(v => v !== undefined);
1975
- setSelectedValues(selectedValues);
1976
- } else {
1977
- setSelectedValues([]);
1978
- }
1979
- }, [JSON.stringify(values), options, loadState]);
1980
- hooks.useEffect(() => {
1981
- if (loadState === LOAD_STATES.LOADED) {
1982
- setFilteredValues(options.filter(o => o.label && o.value && o.label.toLowerCase().includes(filter.toLowerCase()) && !values.includes(o.value)));
1977
+ setFilteredOptions(options.filter(o => o.label && o.value && o.label.toLowerCase().includes(filter.toLowerCase()) && !values.includes(o.value)));
1983
1978
  } else {
1984
- setFilteredValues([]);
1979
+ setFilteredOptions([]);
1985
1980
  }
1986
- }, [filter, JSON.stringify(values), options]);
1981
+ }, [filter, JSON.stringify(values), options, loadState]);
1987
1982
  hooks.useEffect(() => {
1988
- setHasValuesLeft(selectedValues.length < options.length);
1989
- }, [selectedValues.length, options.length]);
1983
+ setHasOptionsLeft(options.length > values.length);
1984
+ }, [options.length, values.length]);
1990
1985
 
1991
1986
  const onFilterChange = ({
1992
1987
  target
@@ -1995,17 +1990,25 @@ function Taglist(props) {
1995
1990
  setFilter(target.value);
1996
1991
  };
1997
1992
 
1998
- const selectValue = option => {
1999
- setFilter('');
1993
+ const selectValue = value => {
1994
+ if (filter) {
1995
+ setFilter('');
1996
+ } // Ensure values cannot be double selected due to latency
1997
+
1998
+
1999
+ if (values.at(-1) === value) {
2000
+ return;
2001
+ }
2002
+
2000
2003
  props.onChange({
2001
- value: [...values, option.value],
2004
+ value: [...values, value],
2002
2005
  field
2003
2006
  });
2004
2007
  };
2005
2008
 
2006
- const deselectValue = option => {
2009
+ const deselectValue = value => {
2007
2010
  props.onChange({
2008
- value: values.filter(v => v != option.value),
2011
+ value: values.filter(v => v != value),
2009
2012
  field
2010
2013
  });
2011
2014
  };
@@ -2019,8 +2022,8 @@ function Taglist(props) {
2019
2022
  break;
2020
2023
 
2021
2024
  case 'Backspace':
2022
- if (!filter && selectedValues.length) {
2023
- deselectValue(selectedValues[selectedValues.length - 1]);
2025
+ if (!filter && values.length) {
2026
+ deselectValue(values[values.length - 1]);
2024
2027
  }
2025
2028
 
2026
2029
  break;
@@ -2047,16 +2050,16 @@ function Taglist(props) {
2047
2050
  class: classNames__default['default']('fjs-taglist', {
2048
2051
  'disabled': disabled
2049
2052
  }),
2050
- children: [!disabled && loadState === LOAD_STATES.LOADED && selectedValues.map(sv => {
2053
+ children: [!disabled && loadState === LOAD_STATES.LOADED && values.map(v => {
2051
2054
  return jsxRuntime.jsxs("div", {
2052
2055
  class: "fjs-taglist-tag",
2053
2056
  onMouseDown: e => e.preventDefault(),
2054
2057
  children: [jsxRuntime.jsx("span", {
2055
2058
  class: "fjs-taglist-tag-label",
2056
- children: sv.label
2059
+ children: valueToOptionMap[v] ? valueToOptionMap[v].label : `unexpected value{${v}}`
2057
2060
  }), jsxRuntime.jsx("span", {
2058
2061
  class: "fjs-taglist-tag-remove",
2059
- onMouseDown: () => deselectValue(sv),
2062
+ onMouseDown: () => deselectValue(v),
2060
2063
  children: jsxRuntime.jsx(CloseIcon, {})
2061
2064
  })]
2062
2065
  });
@@ -2081,10 +2084,10 @@ function Taglist(props) {
2081
2084
  }), jsxRuntime.jsx("div", {
2082
2085
  class: "fjs-taglist-anchor",
2083
2086
  children: !disabled && loadState === LOAD_STATES.LOADED && isDropdownExpanded && !isEscapeClosed && jsxRuntime.jsx(DropdownList, {
2084
- values: filteredValues,
2085
- getLabel: v => v.label,
2086
- onValueSelected: v => selectValue(v),
2087
- emptyListMessage: hasValuesLeft ? 'No results' : 'All values selected',
2087
+ values: filteredOptions,
2088
+ getLabel: o => o.label,
2089
+ onValueSelected: o => selectValue(o.value),
2090
+ emptyListMessage: hasOptionsLeft ? 'No results' : 'All values selected',
2088
2091
  listenerElement: searchbarRef.current
2089
2092
  })
2090
2093
  }), jsxRuntime.jsx(Description, {