@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.es.js CHANGED
@@ -594,10 +594,10 @@ function createInjector(bootstrapModules) {
594
594
  return injector;
595
595
  }
596
596
 
597
- /**
598
- * @param {string?} prefix
599
- *
600
- * @returns Element
597
+ /**
598
+ * @param {string?} prefix
599
+ *
600
+ * @returns Element
601
601
  */
602
602
  function createFormContainer(prefix = 'fjs') {
603
603
  const container = document.createElement('div');
@@ -643,22 +643,22 @@ function generateIndexForType(type) {
643
643
  function generateIdForType(type) {
644
644
  return `${type}${generateIndexForType(type)}`;
645
645
  }
646
- /**
647
- * @template T
648
- * @param {T} data
649
- * @param {(this: any, key: string, value: any) => any} [replacer]
650
- * @return {T}
646
+ /**
647
+ * @template T
648
+ * @param {T} data
649
+ * @param {(this: any, key: string, value: any) => any} [replacer]
650
+ * @return {T}
651
651
  */
652
652
 
653
653
  function clone(data, replacer) {
654
654
  return JSON.parse(JSON.stringify(data, replacer));
655
655
  }
656
- /**
657
- * Parse the schema for input variables a form might make use of
658
- *
659
- * @param {any} schema
660
- *
661
- * @return {string[]}
656
+ /**
657
+ * Parse the schema for input variables a form might make use of
658
+ *
659
+ * @param {any} schema
660
+ *
661
+ * @return {string[]}
662
662
  */
663
663
 
664
664
  function getSchemaVariables(schema) {
@@ -690,24 +690,24 @@ function getSchemaVariables(schema) {
690
690
  }
691
691
 
692
692
  class Importer {
693
- /**
694
- * @constructor
695
- * @param { import('../core').FormFieldRegistry } formFieldRegistry
696
- * @param { import('../render/FormFields').default } formFields
693
+ /**
694
+ * @constructor
695
+ * @param { import('../core').FormFieldRegistry } formFieldRegistry
696
+ * @param { import('../render/FormFields').default } formFields
697
697
  */
698
698
  constructor(formFieldRegistry, formFields) {
699
699
  this._formFieldRegistry = formFieldRegistry;
700
700
  this._formFields = formFields;
701
701
  }
702
- /**
703
- * Import schema adding `id`, `_parent` and `_path`
704
- * information to each field and adding it to the
705
- * form field registry.
706
- *
707
- * @param {any} schema
708
- * @param {any} [data]
709
- *
710
- * @return { { warnings: Array<any>, schema: any, data: any } }
702
+ /**
703
+ * Import schema adding `id`, `_parent` and `_path`
704
+ * information to each field and adding it to the
705
+ * form field registry.
706
+ *
707
+ * @param {any} schema
708
+ * @param {any} [data]
709
+ *
710
+ * @return { { warnings: Array<any>, schema: any, data: any } }
711
711
  */
712
712
 
713
713
 
@@ -728,11 +728,11 @@ class Importer {
728
728
  throw err;
729
729
  }
730
730
  }
731
- /**
732
- * @param {any} formField
733
- * @param {string} [parentId]
734
- *
735
- * @return {any} importedField
731
+ /**
732
+ * @param {any} formField
733
+ * @param {string} [parentId]
734
+ *
735
+ * @return {any} importedField
736
736
  */
737
737
 
738
738
 
@@ -794,10 +794,10 @@ class Importer {
794
794
  this.importFormField(component, parentId);
795
795
  });
796
796
  }
797
- /**
798
- * @param {Object} data
799
- *
800
- * @return {Object} importedData
797
+ /**
798
+ * @param {Object} data
799
+ *
800
+ * @return {Object} importedData
801
801
  */
802
802
 
803
803
 
@@ -858,11 +858,11 @@ const ALLOWED_URI_PATTERN = /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^
858
858
  const ATTR_WHITESPACE_PATTERN = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g; // eslint-disable-line no-control-regex
859
859
 
860
860
  const FORM_ELEMENT = document.createElement('form');
861
- /**
862
- * Sanitize a HTML string and return the cleaned, safe version.
863
- *
864
- * @param {string} html
865
- * @return {string}
861
+ /**
862
+ * Sanitize a HTML string and return the cleaned, safe version.
863
+ *
864
+ * @param {string} html
865
+ * @return {string}
866
866
  */
867
867
 
868
868
  function sanitizeHTML(html) {
@@ -881,15 +881,15 @@ function sanitizeHTML(html) {
881
881
  return '';
882
882
  }
883
883
  }
884
- /**
885
- * Recursively sanitize a HTML node, potentially
886
- * removing it, its children or attributes.
887
- *
888
- * Inspired by https://github.com/developit/snarkdown/issues/70
889
- * and https://github.com/cure53/DOMPurify. Simplified
890
- * for our use-case.
891
- *
892
- * @param {Element} node
884
+ /**
885
+ * Recursively sanitize a HTML node, potentially
886
+ * removing it, its children or attributes.
887
+ *
888
+ * Inspired by https://github.com/developit/snarkdown/issues/70
889
+ * and https://github.com/cure53/DOMPurify. Simplified
890
+ * for our use-case.
891
+ *
892
+ * @param {Element} node
893
893
  */
894
894
 
895
895
  function sanitizeNode(node) {
@@ -936,13 +936,13 @@ function sanitizeNode(node) {
936
936
  node.childNodes[i]);
937
937
  }
938
938
  }
939
- /**
940
- * Validates attributes for validity.
941
- *
942
- * @param {string} lcTag
943
- * @param {string} lcName
944
- * @param {string} value
945
- * @return {boolean}
939
+ /**
940
+ * Validates attributes for validity.
941
+ *
942
+ * @param {string} lcTag
943
+ * @param {string} lcName
944
+ * @param {string} value
945
+ * @return {boolean}
946
946
  */
947
947
 
948
948
 
@@ -1082,11 +1082,11 @@ const FormRenderContext = createContext({
1082
1082
  }
1083
1083
  });
1084
1084
 
1085
- /**
1086
- * @param {string} type
1087
- * @param {boolean} [strict]
1088
- *
1089
- * @returns {any}
1085
+ /**
1086
+ * @param {string} type
1087
+ * @param {boolean} [strict]
1088
+ *
1089
+ * @returns {any}
1090
1090
  */
1091
1091
 
1092
1092
  function getService(type, strict) {}
@@ -1217,8 +1217,8 @@ function useService (type, strict) {
1217
1217
  return getService(type, strict);
1218
1218
  }
1219
1219
 
1220
- /**
1221
- * @enum { String }
1220
+ /**
1221
+ * @enum { String }
1222
1222
  */
1223
1223
 
1224
1224
  const LOAD_STATES = {
@@ -1226,17 +1226,17 @@ const LOAD_STATES = {
1226
1226
  LOADED: 'loaded',
1227
1227
  ERROR: 'error'
1228
1228
  };
1229
- /**
1230
- * @typedef {Object} ValuesGetter
1231
- * @property {Object[]} values - The values data
1232
- * @property {(LOAD_STATES)} state - The values data's loading state, to use for conditional rendering
1229
+ /**
1230
+ * @typedef {Object} ValuesGetter
1231
+ * @property {Object[]} values - The values data
1232
+ * @property {(LOAD_STATES)} state - The values data's loading state, to use for conditional rendering
1233
1233
  */
1234
1234
 
1235
- /**
1236
- * A hook to load values for single and multiselect components.
1237
- *
1238
- * @param {Object} field - The form field to handle values for
1239
- * @return {ValuesGetter} valuesGetter - A values getter object providing loading state and values
1235
+ /**
1236
+ * A hook to load values for single and multiselect components.
1237
+ *
1238
+ * @param {Object} field - The form field to handle values for
1239
+ * @return {ValuesGetter} valuesGetter - A values getter object providing loading state and values
1240
1240
  */
1241
1241
 
1242
1242
  function useValuesAsync (field) {
@@ -1439,10 +1439,10 @@ Default.create = function (options = {}) {
1439
1439
  Default.type = 'default';
1440
1440
  Default.keyed = false;
1441
1441
 
1442
- /**
1443
- * This file must not be changed or exchanged.
1444
- *
1445
- * @see http://bpmn.io/license for more information.
1442
+ /**
1443
+ * This file must not be changed or exchanged.
1444
+ *
1445
+ * @see http://bpmn.io/license for more information.
1446
1446
  */
1447
1447
 
1448
1448
  function Logo() {
@@ -1797,7 +1797,7 @@ Select.keyed = true;
1797
1797
  Select.emptyValue = null;
1798
1798
  Select.sanitizeValue = sanitizeSingleSelectValue;
1799
1799
 
1800
- 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); }
1800
+ 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); }
1801
1801
  var CloseIcon = (({
1802
1802
  styles = {},
1803
1803
  ...props
@@ -1946,35 +1946,30 @@ function Taglist(props) {
1946
1946
  formId
1947
1947
  } = useContext(FormContext);
1948
1948
  const [filter, setFilter] = useState('');
1949
- const [selectedValues, setSelectedValues] = useState([]);
1950
- const [filteredValues, setFilteredValues] = useState([]);
1949
+ const [filteredOptions, setFilteredOptions] = useState([]);
1951
1950
  const [isDropdownExpanded, setIsDropdownExpanded] = useState(false);
1952
- const [hasValuesLeft, setHasValuesLeft] = useState(true);
1951
+ const [hasOptionsLeft, setHasOptionsLeft] = useState(true);
1953
1952
  const [isEscapeClosed, setIsEscapeClose] = useState(false);
1954
1953
  const searchbarRef = useRef();
1955
1954
  const {
1956
1955
  state: loadState,
1957
1956
  values: options
1958
- } = 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
1957
+ } = 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
1958
+
1959
+ const valueToOptionMap = useMemo(() => Object.assign({}, ...options.map((o, x) => ({
1960
+ [o.value]: options[x]
1961
+ }))), [options]); // Usage of stringify is necessary here because we want this effect to only trigger when there is a value change to the array
1959
1962
 
1960
1963
  useEffect(() => {
1961
1964
  if (loadState === LOAD_STATES.LOADED) {
1962
- const selectedValues = values.map(v => options.find(o => o.value === v)).filter(v => v !== undefined);
1963
- setSelectedValues(selectedValues);
1964
- } else {
1965
- setSelectedValues([]);
1966
- }
1967
- }, [JSON.stringify(values), options, loadState]);
1968
- useEffect(() => {
1969
- if (loadState === LOAD_STATES.LOADED) {
1970
- setFilteredValues(options.filter(o => o.label && o.value && o.label.toLowerCase().includes(filter.toLowerCase()) && !values.includes(o.value)));
1965
+ setFilteredOptions(options.filter(o => o.label && o.value && o.label.toLowerCase().includes(filter.toLowerCase()) && !values.includes(o.value)));
1971
1966
  } else {
1972
- setFilteredValues([]);
1967
+ setFilteredOptions([]);
1973
1968
  }
1974
- }, [filter, JSON.stringify(values), options]);
1969
+ }, [filter, JSON.stringify(values), options, loadState]);
1975
1970
  useEffect(() => {
1976
- setHasValuesLeft(selectedValues.length < options.length);
1977
- }, [selectedValues.length, options.length]);
1971
+ setHasOptionsLeft(options.length > values.length);
1972
+ }, [options.length, values.length]);
1978
1973
 
1979
1974
  const onFilterChange = ({
1980
1975
  target
@@ -1983,17 +1978,25 @@ function Taglist(props) {
1983
1978
  setFilter(target.value);
1984
1979
  };
1985
1980
 
1986
- const selectValue = option => {
1987
- setFilter('');
1981
+ const selectValue = value => {
1982
+ if (filter) {
1983
+ setFilter('');
1984
+ } // Ensure values cannot be double selected due to latency
1985
+
1986
+
1987
+ if (values.at(-1) === value) {
1988
+ return;
1989
+ }
1990
+
1988
1991
  props.onChange({
1989
- value: [...values, option.value],
1992
+ value: [...values, value],
1990
1993
  field
1991
1994
  });
1992
1995
  };
1993
1996
 
1994
- const deselectValue = option => {
1997
+ const deselectValue = value => {
1995
1998
  props.onChange({
1996
- value: values.filter(v => v != option.value),
1999
+ value: values.filter(v => v != value),
1997
2000
  field
1998
2001
  });
1999
2002
  };
@@ -2007,8 +2010,8 @@ function Taglist(props) {
2007
2010
  break;
2008
2011
 
2009
2012
  case 'Backspace':
2010
- if (!filter && selectedValues.length) {
2011
- deselectValue(selectedValues[selectedValues.length - 1]);
2013
+ if (!filter && values.length) {
2014
+ deselectValue(values[values.length - 1]);
2012
2015
  }
2013
2016
 
2014
2017
  break;
@@ -2035,16 +2038,16 @@ function Taglist(props) {
2035
2038
  class: classNames('fjs-taglist', {
2036
2039
  'disabled': disabled
2037
2040
  }),
2038
- children: [!disabled && loadState === LOAD_STATES.LOADED && selectedValues.map(sv => {
2041
+ children: [!disabled && loadState === LOAD_STATES.LOADED && values.map(v => {
2039
2042
  return jsxs("div", {
2040
2043
  class: "fjs-taglist-tag",
2041
2044
  onMouseDown: e => e.preventDefault(),
2042
2045
  children: [jsx("span", {
2043
2046
  class: "fjs-taglist-tag-label",
2044
- children: sv.label
2047
+ children: valueToOptionMap[v] ? valueToOptionMap[v].label : `unexpected value{${v}}`
2045
2048
  }), jsx("span", {
2046
2049
  class: "fjs-taglist-tag-remove",
2047
- onMouseDown: () => deselectValue(sv),
2050
+ onMouseDown: () => deselectValue(v),
2048
2051
  children: jsx(CloseIcon, {})
2049
2052
  })]
2050
2053
  });
@@ -2069,10 +2072,10 @@ function Taglist(props) {
2069
2072
  }), jsx("div", {
2070
2073
  class: "fjs-taglist-anchor",
2071
2074
  children: !disabled && loadState === LOAD_STATES.LOADED && isDropdownExpanded && !isEscapeClosed && jsx(DropdownList, {
2072
- values: filteredValues,
2073
- getLabel: v => v.label,
2074
- onValueSelected: v => selectValue(v),
2075
- emptyListMessage: hasValuesLeft ? 'No results' : 'All values selected',
2075
+ values: filteredOptions,
2076
+ getLabel: o => o.label,
2077
+ onValueSelected: o => selectValue(o.value),
2078
+ emptyListMessage: hasOptionsLeft ? 'No results' : 'All values selected',
2076
2079
  listenerElement: searchbarRef.current
2077
2080
  })
2078
2081
  }), jsx(Description, {