@bpmn-io/properties-panel 3.40.5 → 3.41.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.
package/dist/index.js CHANGED
@@ -7,9 +7,15 @@ var jsxRuntime = require('../preact/jsx-runtime');
7
7
  var preact = require('../preact');
8
8
  var classnames = require('classnames');
9
9
  var minDom = require('min-dom');
10
+ var view = require('@codemirror/view');
11
+ var state = require('@codemirror/state');
12
+ var language = require('@codemirror/language');
13
+ var autocomplete = require('@codemirror/autocomplete');
14
+ var commands = require('@codemirror/commands');
15
+ var langJson = require('@codemirror/lang-json');
16
+ var lint = require('@codemirror/lint');
10
17
  var feelers = require('feelers');
11
18
  var Editor = require('@bpmn-io/feel-editor');
12
- var view = require('@codemirror/view');
13
19
  var focusTrap = require('focus-trap');
14
20
 
15
21
  function _interopNamespaceDefault(e) {
@@ -1760,7 +1766,7 @@ function CheckboxEntry(props) {
1760
1766
  })]
1761
1767
  });
1762
1768
  }
1763
- function isEdited$8(node) {
1769
+ function isEdited$9(node) {
1764
1770
  return node && !!node.checked;
1765
1771
  }
1766
1772
 
@@ -1837,6 +1843,195 @@ function CheckboxGroup(props) {
1837
1843
  });
1838
1844
  }
1839
1845
 
1846
+ const ExternalChange = state.Annotation.define();
1847
+
1848
+ /**
1849
+ * A CodeMirror based JSON editor for the properties panel.
1850
+ *
1851
+ * @param {object} props
1852
+ * @param {string} props.id
1853
+ * @param {string} props.label
1854
+ * @param {string} [props.value]
1855
+ * @param {Function} props.onInput
1856
+ * @param {boolean} [props.disabled]
1857
+ * @param {string} [props.placeholder]
1858
+ * @param {string} [props.tooltip]
1859
+ * @param {object} [props.element]
1860
+ */
1861
+ function JsonEditor(props) {
1862
+ const {
1863
+ id,
1864
+ label,
1865
+ debounce,
1866
+ value = '',
1867
+ onInput: commitValue,
1868
+ disabled,
1869
+ placeholder,
1870
+ tooltip,
1871
+ element
1872
+ } = props;
1873
+ const containerRef = hooks.useRef(null);
1874
+ const viewRef = hooks.useRef(null);
1875
+ const editorRef = useShowEntryEvent(id);
1876
+ const onInput = useStaticCallback(newValue => {
1877
+ commitValue(newValue === '' ? undefined : newValue);
1878
+ });
1879
+ const handleChange = useDebounce(onInput, debounce);
1880
+ hooks.useEffect(() => {
1881
+ const view$1 = new view.EditorView({
1882
+ state: state.EditorState.create({
1883
+ doc: value,
1884
+ extensions: [view.highlightSpecialChars(), commands.history(), view.drawSelection(), language.syntaxHighlighting(language.defaultHighlightStyle, {
1885
+ fallback: true
1886
+ }), language.foldGutter(), language.bracketMatching(), autocomplete.closeBrackets(), view.keymap.of([...commands.defaultKeymap, ...commands.historyKeymap, ...autocomplete.closeBracketsKeymap, ...language.foldKeymap]), state.EditorState.tabSize.of(2), view.EditorView.lineWrapping, state.EditorState.readOnly.of(!!disabled), ...(placeholder ? [view.placeholder(placeholder)] : []), view.EditorView.updateListener.of(update => {
1887
+ const isExternal = update.transactions.some(tr => tr.annotation(ExternalChange));
1888
+ if (update.docChanged && !isExternal) {
1889
+ handleChange(update.state.doc.toString());
1890
+ }
1891
+ }), langJson.json(), lint.linter(langJson.jsonParseLinter(), {
1892
+ delay: 300
1893
+ })]
1894
+ }),
1895
+ parent: containerRef.current
1896
+ });
1897
+ viewRef.current = view$1;
1898
+
1899
+ // Allow useShowEntryEvent to focus the editor
1900
+ editorRef.current = view$1.contentDOM;
1901
+ const prefixedId = `bio-properties-panel-${id}`;
1902
+ view$1.contentDOM.setAttribute('id', prefixedId);
1903
+ view$1.contentDOM.setAttribute('aria-label', label);
1904
+ return () => {
1905
+ view$1.destroy();
1906
+ };
1907
+ }, []);
1908
+
1909
+ // Sync external value changes into the editor
1910
+ hooks.useEffect(() => {
1911
+ const view = viewRef.current;
1912
+ if (!view) return;
1913
+ const currentValue = view.state.doc.toString();
1914
+ if (value === currentValue) return;
1915
+ view.dispatch({
1916
+ changes: {
1917
+ from: 0,
1918
+ to: currentValue.length,
1919
+ insert: value || ''
1920
+ },
1921
+ annotations: ExternalChange.of(true)
1922
+ });
1923
+ }, [value]);
1924
+
1925
+ // Focus editor on label click manually, as the native `for`
1926
+ // attribute does not work with contenteditable elements
1927
+ const focusEditor = () => {
1928
+ viewRef.current && viewRef.current.focus();
1929
+ };
1930
+ return jsxRuntime.jsxs("div", {
1931
+ class: "bio-properties-panel-json-editor",
1932
+ children: [jsxRuntime.jsx("label", {
1933
+ class: "bio-properties-panel-label",
1934
+ onClick: focusEditor,
1935
+ children: jsxRuntime.jsx(TooltipWrapper, {
1936
+ value: tooltip,
1937
+ forId: id,
1938
+ element: element,
1939
+ children: label
1940
+ })
1941
+ }), jsxRuntime.jsx("div", {
1942
+ ref: containerRef
1943
+ })]
1944
+ });
1945
+ }
1946
+
1947
+ /**
1948
+ * Entry wrapper for JsonEditor, handles getValue/setValue, built-in JSON validation, error display, and description.
1949
+ *
1950
+ * @param {object} props
1951
+ * @param {object} props.element
1952
+ * @param {string} props.id
1953
+ * @param {string} [props.description]
1954
+ * @param {string} props.label
1955
+ * @param {Function} props.debounce
1956
+ * @param {Function} props.getValue
1957
+ * @param {Function} props.setValue
1958
+ * @param {boolean} [props.disabled]
1959
+ * @param {string} [props.placeholder]
1960
+ * @param {string} [props.tooltip]
1961
+ */
1962
+ function JsonEditorEntry(props) {
1963
+ const {
1964
+ element,
1965
+ id,
1966
+ description,
1967
+ debounce,
1968
+ label,
1969
+ getValue,
1970
+ setValue,
1971
+ disabled,
1972
+ placeholder,
1973
+ tooltip
1974
+ } = props;
1975
+ const globalError = useError(id);
1976
+ let value = getValue(element);
1977
+ const [editorValue, setEditorValue] = hooks.useState(value);
1978
+ hooks.useEffect(() => {
1979
+ if (value === editorValue) {
1980
+ return;
1981
+ }
1982
+ setEditorValue(value);
1983
+ }, [value]);
1984
+ const onInput = useStaticCallback(newValue => {
1985
+ setEditorValue(newValue);
1986
+ const currentValue = getValue(element);
1987
+ if (newValue !== currentValue) {
1988
+ setValue(newValue);
1989
+ }
1990
+ });
1991
+ const error = globalError || validateJson(editorValue);
1992
+ return jsxRuntime.jsxs("div", {
1993
+ class: classnames('bio-properties-panel-entry', error && 'has-error'),
1994
+ "data-entry-id": id,
1995
+ children: [jsxRuntime.jsx(JsonEditor, {
1996
+ id: id,
1997
+ label: label,
1998
+ debounce: debounce,
1999
+ value: value,
2000
+ onInput: onInput,
2001
+ disabled: disabled,
2002
+ placeholder: placeholder,
2003
+ tooltip: tooltip,
2004
+ element: element
2005
+ }, element), error && jsxRuntime.jsx("div", {
2006
+ class: "bio-properties-panel-error",
2007
+ children: error
2008
+ }), jsxRuntime.jsx(Description, {
2009
+ forId: id,
2010
+ element: element,
2011
+ value: description
2012
+ })]
2013
+ });
2014
+ }
2015
+
2016
+ /**
2017
+ * Check if the JSON editor entry has been edited.
2018
+ */
2019
+ function isEdited$8(node) {
2020
+ const cmContent = node && node.querySelector('.cm-content');
2021
+ return cmContent ? cmContent.textContent.trim().length > 0 : false;
2022
+ }
2023
+
2024
+ // helpers /////////////////
2025
+
2026
+ function validateJson(value) {
2027
+ if (!value) return null;
2028
+ try {
2029
+ return minDash.isObject(JSON.parse(value)) ? null : 'JSON contains errors';
2030
+ } catch (e) {
2031
+ return 'JSON contains errors';
2032
+ }
2033
+ }
2034
+
1840
2035
  /**
1841
2036
  * Button to open popups.
1842
2037
  *
@@ -2045,6 +2240,7 @@ const FeelEditor = compat.forwardRef((props, ref) => {
2045
2240
  onKeyDown: onKeyDown,
2046
2241
  onLint: onLint,
2047
2242
  placeholder: placeholder,
2243
+ readOnly: disabled,
2048
2244
  tooltipContainer: tooltipContainer,
2049
2245
  value: localValue,
2050
2246
  variables,
@@ -4946,6 +5142,7 @@ exports.FeelToggleSwitchEntry = FeelToggleSwitchEntry;
4946
5142
  exports.Group = Group;
4947
5143
  exports.Header = Header;
4948
5144
  exports.HeaderButton = HeaderButton;
5145
+ exports.JsonEditorEntry = JsonEditorEntry;
4949
5146
  exports.LaunchIcon = LaunchIcon;
4950
5147
  exports.LayoutContext = LayoutContext;
4951
5148
  exports.ListEntry = List;
@@ -4964,8 +5161,9 @@ exports.TextFieldEntry = TextfieldEntry;
4964
5161
  exports.ToggleSwitchEntry = ToggleSwitchEntry;
4965
5162
  exports.TooltipContext = TooltipContext;
4966
5163
  exports.TooltipEntry = TooltipWrapper;
4967
- exports.isCheckboxEntryEdited = isEdited$8;
5164
+ exports.isCheckboxEntryEdited = isEdited$9;
4968
5165
  exports.isFeelEntryEdited = isEdited$5;
5166
+ exports.isJsonEditorEntryEdited = isEdited$8;
4969
5167
  exports.isNumberFieldEntryEdited = isEdited$6;
4970
5168
  exports.isSelectEntryEdited = isEdited$3;
4971
5169
  exports.isSimpleEntryEdited = isEdited$2;