@bpmn-io/properties-panel 1.4.0 → 1.5.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.
@@ -446,6 +446,21 @@
446
446
  text-decoration: underline;
447
447
  }
448
448
 
449
+ .bio-properties-panel-feelers-editor.bio-properties-panel-input {
450
+ padding: 0;
451
+ }
452
+
453
+ .bio-properties-panel-feelers-input .cm-editor
454
+ {
455
+ min-height: 32px;
456
+ max-height: 215px;
457
+ background-color: transparent;
458
+ }
459
+
460
+ .bio-properties-panel-feelers-input .cm-editor.cm-focused {
461
+ outline: none;
462
+ }
463
+
449
464
  .bio-properties-panel-input {
450
465
  padding: 3px 6px 2px;
451
466
  border: 1px solid var(--input-border-color);
package/dist/index.esm.js CHANGED
@@ -6,6 +6,7 @@ import { jsx, jsxs } from '../preact/jsx-runtime';
6
6
  import { query } from 'min-dom';
7
7
  import { createContext, createElement } from '../preact';
8
8
  import FeelEditor from '@bpmn-io/feel-editor';
9
+ import { FeelersEditor } from 'feelers';
9
10
 
10
11
  var ArrowIcon = function ArrowIcon(props) {
11
12
  return jsx("svg", {
@@ -952,7 +953,7 @@ function ListItem(props) {
952
953
  });
953
954
  }
954
955
 
955
- const noop$2 = () => {};
956
+ const noop$3 = () => {};
956
957
 
957
958
  /**
958
959
  * @param {import('../PropertiesPanel').ListGroupDefinition} props
@@ -1061,7 +1062,7 @@ function ListGroup(props) {
1061
1062
  ref: groupRef,
1062
1063
  children: [jsxs("div", {
1063
1064
  class: classnames('bio-properties-panel-group-header', hasItems ? '' : 'empty', hasItems && open ? 'open' : '', sticky && open ? 'sticky' : ''),
1064
- onClick: hasItems ? toggleOpen : noop$2,
1065
+ onClick: hasItems ? toggleOpen : noop$3,
1065
1066
  children: [jsx("div", {
1066
1067
  title: label,
1067
1068
  class: "bio-properties-panel-group-header-title",
@@ -1242,7 +1243,7 @@ function CheckboxEntry(props) {
1242
1243
  })]
1243
1244
  });
1244
1245
  }
1245
- function isEdited$7(node) {
1246
+ function isEdited$8(node) {
1246
1247
  return node && !!node.checked;
1247
1248
  }
1248
1249
 
@@ -1252,7 +1253,7 @@ function prefixId$7(id) {
1252
1253
  return `bio-properties-panel-${id}`;
1253
1254
  }
1254
1255
 
1255
- const useBufferedFocus = function (editor, ref) {
1256
+ const useBufferedFocus$1 = function (editor, ref) {
1256
1257
  const [buffer, setBuffer] = useState(undefined);
1257
1258
  ref.current = useMemo(() => ({
1258
1259
  focus: offset => {
@@ -1273,7 +1274,7 @@ const useBufferedFocus = function (editor, ref) {
1273
1274
  }
1274
1275
  }, [editor, buffer]);
1275
1276
  };
1276
- const CodeEditor = forwardRef((props, ref) => {
1277
+ const CodeEditor$1 = forwardRef((props, ref) => {
1277
1278
  const {
1278
1279
  value,
1279
1280
  onInput,
@@ -1286,7 +1287,7 @@ const CodeEditor = forwardRef((props, ref) => {
1286
1287
  const inputRef = useRef();
1287
1288
  const [editor, setEditor] = useState();
1288
1289
  const [localValue, setLocalValue] = useState(value || '');
1289
- useBufferedFocus(editor, ref);
1290
+ useBufferedFocus$1(editor, ref);
1290
1291
  const handleInput = useStaticCallback(newValue => {
1291
1292
  onInput(newValue);
1292
1293
  setLocalValue(newValue);
@@ -1368,7 +1369,7 @@ function FeelIndicator(props) {
1368
1369
  });
1369
1370
  }
1370
1371
 
1371
- const noop$1 = () => {};
1372
+ const noop$2 = () => {};
1372
1373
 
1373
1374
  /**
1374
1375
  * @param {Object} props
@@ -1381,7 +1382,7 @@ function FeelIcon(props) {
1381
1382
  feel = false,
1382
1383
  active,
1383
1384
  disabled = false,
1384
- onClick = noop$1
1385
+ onClick = noop$2
1385
1386
  } = props;
1386
1387
  const feelRequiredLabel = ' must be a FEEL expression';
1387
1388
  const feelOptionalLabel = ' can optionally be a FEEL expression';
@@ -1402,7 +1403,7 @@ function FeelIcon(props) {
1402
1403
  });
1403
1404
  }
1404
1405
 
1405
- const noop = () => {};
1406
+ const noop$1 = () => {};
1406
1407
  function FeelTextfield(props) {
1407
1408
  const {
1408
1409
  debounce,
@@ -1542,7 +1543,7 @@ function FeelTextfield(props) {
1542
1543
  active: feelActive,
1543
1544
  disabled: feel !== 'optional' || disabled,
1544
1545
  onClick: handleFeelToggle
1545
- }), feelActive ? jsx(CodeEditor, {
1546
+ }), feelActive ? jsx(CodeEditor$1, {
1546
1547
  id: prefixId$6(id),
1547
1548
  name: id,
1548
1549
  onInput: handleLocalInput,
@@ -1655,10 +1656,17 @@ const OptionalFeelTextArea = forwardRef((props, ref) => {
1655
1656
  * @param {String} props.description
1656
1657
  * @param {Boolean} props.debounce
1657
1658
  * @param {Boolean} props.disabled
1659
+ * @param {Boolean} props.feel
1658
1660
  * @param {String} props.label
1659
1661
  * @param {Function} props.getValue
1660
1662
  * @param {Function} props.setValue
1663
+ * @param {Function} props.tooltipContainer
1661
1664
  * @param {Function} props.validate
1665
+ * @param {Function} props.show
1666
+ * @param {Function} props.example
1667
+ * @param {Function} props.variables
1668
+ * @param {Function} props.onFocus
1669
+ * @param {Function} props.onBlur
1662
1670
  */
1663
1671
  function FeelEntry(props) {
1664
1672
  const {
@@ -1673,7 +1681,7 @@ function FeelEntry(props) {
1673
1681
  setValue,
1674
1682
  tooltipContainer,
1675
1683
  validate,
1676
- show = noop,
1684
+ show = noop$1,
1677
1685
  example,
1678
1686
  variables,
1679
1687
  onFocus,
@@ -1750,12 +1758,17 @@ function FeelEntry(props) {
1750
1758
  * @param {String} props.description
1751
1759
  * @param {Boolean} props.debounce
1752
1760
  * @param {Boolean} props.disabled
1761
+ * @param {Boolean} props.feel
1753
1762
  * @param {String} props.label
1754
1763
  * @param {Function} props.getValue
1755
1764
  * @param {Function} props.setValue
1765
+ * @param {Function} props.tooltipContainer
1766
+ * @param {Function} props.validate
1767
+ * @param {Function} props.show
1768
+ * @param {Function} props.example
1769
+ * @param {Function} props.variables
1756
1770
  * @param {Function} props.onFocus
1757
1771
  * @param {Function} props.onBlur
1758
- * @param {Function} props.validate
1759
1772
  */
1760
1773
  function FeelTextArea(props) {
1761
1774
  return jsx(FeelEntry, {
@@ -1764,7 +1777,7 @@ function FeelTextArea(props) {
1764
1777
  ...props
1765
1778
  });
1766
1779
  }
1767
- function isEdited$6(node) {
1780
+ function isEdited$7(node) {
1768
1781
  return node && (!!node.value || node.classList.contains('edited'));
1769
1782
  }
1770
1783
 
@@ -1774,6 +1787,260 @@ function prefixId$6(id) {
1774
1787
  return `bio-properties-panel-${id}`;
1775
1788
  }
1776
1789
 
1790
+ const useBufferedFocus = function (editor, ref) {
1791
+ const [buffer, setBuffer] = useState(undefined);
1792
+ ref.current = useMemo(() => ({
1793
+ focus: offset => {
1794
+ if (editor) {
1795
+ editor.focus(offset);
1796
+ } else {
1797
+ if (typeof offset === 'undefined') {
1798
+ offset = Infinity;
1799
+ }
1800
+ setBuffer(offset);
1801
+ }
1802
+ }
1803
+ }), [editor]);
1804
+ useEffect(() => {
1805
+ if (typeof buffer !== 'undefined' && editor) {
1806
+ editor.focus(buffer);
1807
+ setBuffer(false);
1808
+ }
1809
+ }, [editor, buffer]);
1810
+ };
1811
+ const CodeEditor = forwardRef((props, ref) => {
1812
+ const {
1813
+ value,
1814
+ onInput,
1815
+ onLint = () => {},
1816
+ contentAttributes = {},
1817
+ disabled,
1818
+ tooltipContainer,
1819
+ useGutters = false,
1820
+ darkMode = false
1821
+ } = props;
1822
+ const inputRef = useRef();
1823
+ const [editor, setEditor] = useState();
1824
+ const [localValue, setLocalValue] = useState(value || '');
1825
+ useBufferedFocus(editor, ref);
1826
+ const handleInput = useStaticCallback(newValue => {
1827
+ onInput(newValue);
1828
+ setLocalValue(newValue);
1829
+ });
1830
+ useEffect(() => {
1831
+ let editor;
1832
+ editor = new FeelersEditor({
1833
+ container: inputRef.current,
1834
+ onChange: handleInput,
1835
+ onLint: onLint,
1836
+ contentAttributes: contentAttributes,
1837
+ tooltipContainer: tooltipContainer,
1838
+ value: localValue,
1839
+ darkMode: darkMode,
1840
+ enableGutters: useGutters
1841
+ });
1842
+ setEditor(editor);
1843
+ return () => {
1844
+ onLint([]);
1845
+ inputRef.current.innerHTML = '';
1846
+ setEditor(null);
1847
+ };
1848
+ }, []);
1849
+ useEffect(() => {
1850
+ if (!editor) {
1851
+ return;
1852
+ }
1853
+ if (value === localValue) {
1854
+ return;
1855
+ }
1856
+ editor.setValue(value);
1857
+ setLocalValue(value);
1858
+ }, [value]);
1859
+ const handleClick = () => {
1860
+ ref.current.focus();
1861
+ };
1862
+ return jsx("div", {
1863
+ name: props.name,
1864
+ class: classnames('bio-properties-panel-feelers-editor bio-properties-panel-input', localValue ? 'edited' : null, disabled ? 'disabled' : null),
1865
+ ref: inputRef,
1866
+ onClick: handleClick
1867
+ });
1868
+ });
1869
+
1870
+ const noop = () => {};
1871
+
1872
+ /**
1873
+ * @param {Object} props
1874
+ * @param {Object} props.element
1875
+ * @param {String} props.id
1876
+ * @param {String} props.description
1877
+ * @param {Boolean} props.debounce
1878
+ * @param {Boolean} props.disabled
1879
+ * @param {String} props.label
1880
+ * @param {Function} props.getValue
1881
+ * @param {Function} props.setValue
1882
+ * @param {Function} props.tooltipContainer
1883
+ * @param {Function} props.validate
1884
+ * @param {Function} props.show
1885
+ */
1886
+ function FeelTemplatingEntry(props) {
1887
+ const {
1888
+ element,
1889
+ id,
1890
+ description,
1891
+ debounce,
1892
+ disabled,
1893
+ label,
1894
+ getValue,
1895
+ setValue,
1896
+ tooltipContainer,
1897
+ validate,
1898
+ show = noop
1899
+ } = props;
1900
+ const [cachedInvalidValue, setCachedInvalidValue] = useState(null);
1901
+ const [validationError, setValidationError] = useState(null);
1902
+ const [localError, setLocalError] = useState(null);
1903
+ let value = getValue(element);
1904
+ const previousValue = usePrevious(value);
1905
+ useEffect(() => {
1906
+ if (isFunction(validate)) {
1907
+ const newValidationError = validate(value) || null;
1908
+ setValidationError(newValidationError);
1909
+ }
1910
+ }, [value]);
1911
+ const onInput = useStaticCallback(newValue => {
1912
+ let newValidationError = null;
1913
+ if (isFunction(validate)) {
1914
+ newValidationError = validate(newValue) || null;
1915
+ }
1916
+ if (newValidationError) {
1917
+ setCachedInvalidValue(newValue);
1918
+ } else {
1919
+ // don't create multiple commandStack entries for the same value
1920
+ if (newValue !== value) {
1921
+ setValue(newValue);
1922
+ }
1923
+ }
1924
+ setValidationError(newValidationError);
1925
+ });
1926
+ const onError = useCallback(err => {
1927
+ setLocalError(err);
1928
+ }, []);
1929
+ if (previousValue === value && validationError) {
1930
+ value = cachedInvalidValue;
1931
+ }
1932
+ const temporaryError = useError(id);
1933
+ const error = localError || temporaryError || validationError;
1934
+ return jsxs("div", {
1935
+ class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
1936
+ "data-entry-id": id,
1937
+ children: [jsx(FeelTemplating, {
1938
+ debounce: debounce,
1939
+ disabled: disabled,
1940
+ id: id,
1941
+ label: label,
1942
+ onInput: onInput,
1943
+ onError: onError,
1944
+ show: show,
1945
+ value: value,
1946
+ tooltipContainer: tooltipContainer
1947
+ }, element), error && jsx("div", {
1948
+ class: "bio-properties-panel-error",
1949
+ children: error
1950
+ }), jsx(Description, {
1951
+ forId: id,
1952
+ element: element,
1953
+ value: description
1954
+ })]
1955
+ });
1956
+ }
1957
+ function FeelTemplating(props) {
1958
+ const {
1959
+ debounce,
1960
+ id,
1961
+ label,
1962
+ onInput,
1963
+ onError,
1964
+ value = '',
1965
+ disabled = false,
1966
+ tooltipContainer
1967
+ } = props;
1968
+ const [localValue, setLocalValue] = useState(value);
1969
+ const editorRef = useShowEntryEvent(id);
1970
+ const containerRef = useRef();
1971
+ const [focus, _setFocus] = useState(undefined);
1972
+ const setFocus = (offset = 0) => {
1973
+ const hasFocus = containerRef.current.contains(document.activeElement);
1974
+
1975
+ // Keep caret position if it is already focused, otherwise focus at the end
1976
+ const position = hasFocus ? document.activeElement.selectionStart : Infinity;
1977
+ _setFocus(position + offset);
1978
+ };
1979
+ const handleInputCallback = useMemo(() => {
1980
+ return debounce(newValue => onInput(newValue.length ? newValue : undefined));
1981
+ }, [onInput, debounce]);
1982
+ const handleInput = newValue => {
1983
+ handleInputCallback(newValue);
1984
+ setLocalValue(newValue);
1985
+ };
1986
+ const handleLint = useStaticCallback(lint => {
1987
+ const errors = lint && lint.length && lint.filter(e => e.severity === 'error') || [];
1988
+ if (!errors.length) {
1989
+ onError(undefined);
1990
+ return;
1991
+ }
1992
+ const error = lint[0];
1993
+ const message = `${error.source}: ${error.message}`;
1994
+ onError(message);
1995
+ });
1996
+ useEffect(() => {
1997
+ if (typeof focus !== 'undefined') {
1998
+ editorRef.current.focus(focus);
1999
+ _setFocus(undefined);
2000
+ }
2001
+ }, [focus]);
2002
+ useEffect(() => {
2003
+ if (value === localValue) {
2004
+ return;
2005
+ }
2006
+ setLocalValue(value ? value : '');
2007
+ }, [value]);
2008
+ return jsxs("div", {
2009
+ class: "bio-properties-panel-feelers",
2010
+ children: [jsx("label", {
2011
+ id: prefixIdLabel(id),
2012
+ class: "bio-properties-panel-label",
2013
+ onClick: () => setFocus(),
2014
+ children: label
2015
+ }), jsx("div", {
2016
+ class: "bio-properties-panel-feelers-input",
2017
+ ref: containerRef,
2018
+ children: jsx(CodeEditor, {
2019
+ name: id,
2020
+ onInput: handleInput,
2021
+ contentAttributes: {
2022
+ 'aria-labelledby': prefixIdLabel(id)
2023
+ },
2024
+ disabled: disabled,
2025
+ onLint: handleLint,
2026
+ value: localValue,
2027
+ useGutters: false,
2028
+ ref: editorRef,
2029
+ tooltipContainer: tooltipContainer
2030
+ })
2031
+ })]
2032
+ });
2033
+ }
2034
+ function isEdited$6(node) {
2035
+ return node && (!!node.value || node.classList.contains('edited'));
2036
+ }
2037
+
2038
+ // helpers /////////////////
2039
+
2040
+ function prefixIdLabel(id) {
2041
+ return `bio-properties-panel-feelers-${id}-label`;
2042
+ }
2043
+
1777
2044
  function List(props) {
1778
2045
  const {
1779
2046
  id,
@@ -2691,5 +2958,5 @@ var index = {
2691
2958
  debounceInput: ['factory', debounceInput]
2692
2959
  };
2693
2960
 
2694
- export { ArrowIcon, CheckboxEntry, CollapsibleEntry, CreateIcon, index as DebounceInputModule, DeleteIcon, DescriptionContext, Description as DescriptionEntry, DropdownButton, ErrorsContext, EventContext, ExternalLinkIcon, FeelEntry, FeelOptionalIcon, FeelRequiredIcon, FeelTextArea as FeelTextAreaEntry, Group, Header, HeaderButton, LayoutContext, List as ListEntry, ListGroup, ListItem, NumberFieldEntry, Placeholder, PropertiesPanel, LayoutContext as PropertiesPanelContext, SelectEntry, Simple as SimpleEntry, TextAreaEntry, TextfieldEntry as TextFieldEntry, ToggleSwitchEntry, isEdited$7 as isCheckboxEntryEdited, isEdited$6 as isFeelEntryEdited, isEdited$5 as isNumberFieldEntryEdited, isEdited$4 as isSelectEntryEdited, isEdited$3 as isSimpleEntryEdited, isEdited$2 as isTextAreaEntryEdited, isEdited$1 as isTextFieldEntryEdited, isEdited as isToggleSwitchEntryEdited, useDescriptionContext, useError, useEvent, useKeyFactory, useLayoutState, usePrevious, useShowEntryEvent, useStaticCallback, useStickyIntersectionObserver };
2961
+ export { ArrowIcon, CheckboxEntry, CollapsibleEntry, CreateIcon, index as DebounceInputModule, DeleteIcon, DescriptionContext, Description as DescriptionEntry, DropdownButton, ErrorsContext, EventContext, ExternalLinkIcon, FeelEntry, FeelOptionalIcon, FeelRequiredIcon, FeelTemplatingEntry, FeelTextArea as FeelTextAreaEntry, Group, Header, HeaderButton, LayoutContext, List as ListEntry, ListGroup, ListItem, NumberFieldEntry, Placeholder, PropertiesPanel, LayoutContext as PropertiesPanelContext, SelectEntry, Simple as SimpleEntry, TextAreaEntry, TextfieldEntry as TextFieldEntry, ToggleSwitchEntry, isEdited$8 as isCheckboxEntryEdited, isEdited$7 as isFeelEntryEdited, isEdited$6 as isFeelTemplatingEntryEdited, isEdited$5 as isNumberFieldEntryEdited, isEdited$4 as isSelectEntryEdited, isEdited$3 as isSimpleEntryEdited, isEdited$2 as isTextAreaEntryEdited, isEdited$1 as isTextFieldEntryEdited, isEdited as isToggleSwitchEntryEdited, useDescriptionContext, useError, useEvent, useKeyFactory, useLayoutState, usePrevious, useShowEntryEvent, useStaticCallback, useStickyIntersectionObserver };
2695
2962
  //# sourceMappingURL=index.esm.js.map