@bpmn-io/properties-panel 3.40.6 → 3.41.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.
- package/dist/assets/properties-panel.css +36 -0
- package/dist/index.esm.js +204 -4
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +205 -3
- package/dist/index.js.map +1 -1
- package/package.json +7 -1
|
@@ -569,6 +569,42 @@ textarea.bio-properties-panel-input {
|
|
|
569
569
|
resize: vertical;
|
|
570
570
|
}
|
|
571
571
|
|
|
572
|
+
/**
|
|
573
|
+
* JSON Editor (CodeMirror)
|
|
574
|
+
*/
|
|
575
|
+
|
|
576
|
+
.bio-properties-panel-json-editor .cm-editor {
|
|
577
|
+
border: 1px solid var(--input-border-color);
|
|
578
|
+
border-radius: 2px;
|
|
579
|
+
background-color: var(--input-background-color);
|
|
580
|
+
font-size: var(--text-size-base);
|
|
581
|
+
font-family: var(--font-family-monospace);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
.bio-properties-panel-json-editor .cm-editor.cm-focused {
|
|
585
|
+
outline: none;
|
|
586
|
+
background-color: var(--input-focus-background-color);
|
|
587
|
+
border-color: var(--input-focus-border-color);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
.bio-properties-panel-json-editor .cm-scroller {
|
|
591
|
+
overflow: auto;
|
|
592
|
+
max-height: 215px;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
.bio-properties-panel-json-editor .cm-content {
|
|
596
|
+
padding-right: 18px;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
.bio-properties-panel-entry.has-error .bio-properties-panel-json-editor .cm-editor {
|
|
600
|
+
border-color: var(--input-error-border-color);
|
|
601
|
+
background-color: var(--input-error-background-color);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
.bio-properties-panel-entry.has-error .bio-properties-panel-json-editor .cm-editor.cm-focused {
|
|
605
|
+
border-color: var(--input-error-focus-border-color);
|
|
606
|
+
}
|
|
607
|
+
|
|
572
608
|
.bio-properties-panel-entry.has-error .bio-properties-panel-input,
|
|
573
609
|
.bio-properties-panel-entry.has-error .bio-properties-panel-feel-editor__open-popup-placeholder {
|
|
574
610
|
border-color: var(--input-error-border-color);
|
package/dist/index.esm.js
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { useContext, useState, useRef, useEffect, useLayoutEffect, useCallback, useMemo } from '../preact/hooks';
|
|
2
|
-
import { isFunction, isArray, get, assign, set, isString, isNumber, debounce } from 'min-dash';
|
|
2
|
+
import { isFunction, isArray, get, assign, set, isObject, isString, isNumber, debounce } from 'min-dash';
|
|
3
3
|
import { createPortal, forwardRef } from '../preact/compat';
|
|
4
4
|
import { jsx, jsxs, Fragment } from '../preact/jsx-runtime';
|
|
5
5
|
import { createContext, createElement as createElement$1, render } from '../preact';
|
|
6
6
|
import classnames from 'classnames';
|
|
7
7
|
import { query, domify } from 'min-dom';
|
|
8
|
+
import { EditorView, highlightSpecialChars, drawSelection, keymap, placeholder, lineNumbers } from '@codemirror/view';
|
|
9
|
+
import { Annotation, EditorState } from '@codemirror/state';
|
|
10
|
+
import { syntaxHighlighting, foldGutter, bracketMatching, defaultHighlightStyle, foldKeymap } from '@codemirror/language';
|
|
11
|
+
import { closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete';
|
|
12
|
+
import { history, defaultKeymap, historyKeymap } from '@codemirror/commands';
|
|
13
|
+
import { jsonParseLinter, json } from '@codemirror/lang-json';
|
|
14
|
+
import { linter } from '@codemirror/lint';
|
|
8
15
|
import { FeelersEditor } from 'feelers';
|
|
9
16
|
import Editor from '@bpmn-io/feel-editor';
|
|
10
|
-
import { lineNumbers, EditorView } from '@codemirror/view';
|
|
11
17
|
import * as focusTrap from 'focus-trap';
|
|
12
18
|
|
|
13
19
|
var ArrowIcon = function ArrowIcon(props) {
|
|
@@ -1739,7 +1745,7 @@ function CheckboxEntry(props) {
|
|
|
1739
1745
|
})]
|
|
1740
1746
|
});
|
|
1741
1747
|
}
|
|
1742
|
-
function isEdited$
|
|
1748
|
+
function isEdited$9(node) {
|
|
1743
1749
|
return node && !!node.checked;
|
|
1744
1750
|
}
|
|
1745
1751
|
|
|
@@ -1816,6 +1822,200 @@ function CheckboxGroup(props) {
|
|
|
1816
1822
|
});
|
|
1817
1823
|
}
|
|
1818
1824
|
|
|
1825
|
+
const ExternalChange = Annotation.define();
|
|
1826
|
+
const parseJsonLinter = jsonParseLinter();
|
|
1827
|
+
|
|
1828
|
+
/**
|
|
1829
|
+
* A CodeMirror based JSON editor for the properties panel.
|
|
1830
|
+
*
|
|
1831
|
+
* @param {object} props
|
|
1832
|
+
* @param {string} props.id
|
|
1833
|
+
* @param {string} props.label
|
|
1834
|
+
* @param {string} [props.value]
|
|
1835
|
+
* @param {Function} props.onInput
|
|
1836
|
+
* @param {boolean} [props.disabled]
|
|
1837
|
+
* @param {string} [props.placeholder]
|
|
1838
|
+
* @param {string} [props.tooltip]
|
|
1839
|
+
* @param {object} [props.element]
|
|
1840
|
+
*/
|
|
1841
|
+
function JsonEditor(props) {
|
|
1842
|
+
const {
|
|
1843
|
+
id,
|
|
1844
|
+
label,
|
|
1845
|
+
debounce,
|
|
1846
|
+
value = '',
|
|
1847
|
+
onInput: commitValue,
|
|
1848
|
+
disabled,
|
|
1849
|
+
placeholder: placeholder$1,
|
|
1850
|
+
tooltip,
|
|
1851
|
+
element
|
|
1852
|
+
} = props;
|
|
1853
|
+
const containerRef = useRef(null);
|
|
1854
|
+
const viewRef = useRef(null);
|
|
1855
|
+
const editorRef = useShowEntryEvent(id);
|
|
1856
|
+
const onInput = useStaticCallback(newValue => {
|
|
1857
|
+
commitValue(newValue === '' ? undefined : newValue);
|
|
1858
|
+
});
|
|
1859
|
+
const handleChange = useDebounce(onInput, debounce);
|
|
1860
|
+
useEffect(() => {
|
|
1861
|
+
const view = new EditorView({
|
|
1862
|
+
state: EditorState.create({
|
|
1863
|
+
doc: value,
|
|
1864
|
+
extensions: [highlightSpecialChars(), history(), drawSelection(), syntaxHighlighting(defaultHighlightStyle, {
|
|
1865
|
+
fallback: true
|
|
1866
|
+
}), foldGutter(), bracketMatching(), closeBrackets(), keymap.of([...defaultKeymap, ...historyKeymap, ...closeBracketsKeymap, ...foldKeymap]), EditorState.tabSize.of(2), EditorView.lineWrapping, EditorState.readOnly.of(!!disabled), ...(placeholder$1 ? [placeholder(placeholder$1)] : []), EditorView.updateListener.of(update => {
|
|
1867
|
+
const isExternal = update.transactions.some(tr => tr.annotation(ExternalChange));
|
|
1868
|
+
if (update.docChanged && !isExternal) {
|
|
1869
|
+
handleChange(update.state.doc.toString());
|
|
1870
|
+
}
|
|
1871
|
+
}), json(), linter(view => {
|
|
1872
|
+
const content = view.state.doc.toString();
|
|
1873
|
+
if (!content.trim()) return [];
|
|
1874
|
+
return parseJsonLinter(view);
|
|
1875
|
+
}, {
|
|
1876
|
+
delay: 300
|
|
1877
|
+
})]
|
|
1878
|
+
}),
|
|
1879
|
+
parent: containerRef.current
|
|
1880
|
+
});
|
|
1881
|
+
viewRef.current = view;
|
|
1882
|
+
|
|
1883
|
+
// Allow useShowEntryEvent to focus the editor
|
|
1884
|
+
editorRef.current = view.contentDOM;
|
|
1885
|
+
const prefixedId = `bio-properties-panel-${id}`;
|
|
1886
|
+
view.contentDOM.setAttribute('id', prefixedId);
|
|
1887
|
+
view.contentDOM.setAttribute('aria-label', label);
|
|
1888
|
+
return () => {
|
|
1889
|
+
view.destroy();
|
|
1890
|
+
};
|
|
1891
|
+
}, []);
|
|
1892
|
+
|
|
1893
|
+
// Sync external value changes into the editor
|
|
1894
|
+
useEffect(() => {
|
|
1895
|
+
const view = viewRef.current;
|
|
1896
|
+
if (!view) return;
|
|
1897
|
+
const currentValue = view.state.doc.toString();
|
|
1898
|
+
if (value === currentValue) return;
|
|
1899
|
+
view.dispatch({
|
|
1900
|
+
changes: {
|
|
1901
|
+
from: 0,
|
|
1902
|
+
to: currentValue.length,
|
|
1903
|
+
insert: value || ''
|
|
1904
|
+
},
|
|
1905
|
+
annotations: ExternalChange.of(true)
|
|
1906
|
+
});
|
|
1907
|
+
}, [value]);
|
|
1908
|
+
|
|
1909
|
+
// Focus editor on label click manually, as the native `for`
|
|
1910
|
+
// attribute does not work with contenteditable elements
|
|
1911
|
+
const focusEditor = () => {
|
|
1912
|
+
viewRef.current && viewRef.current.focus();
|
|
1913
|
+
};
|
|
1914
|
+
return jsxs("div", {
|
|
1915
|
+
class: "bio-properties-panel-json-editor",
|
|
1916
|
+
children: [jsx("label", {
|
|
1917
|
+
class: "bio-properties-panel-label",
|
|
1918
|
+
onClick: focusEditor,
|
|
1919
|
+
children: jsx(TooltipWrapper, {
|
|
1920
|
+
value: tooltip,
|
|
1921
|
+
forId: id,
|
|
1922
|
+
element: element,
|
|
1923
|
+
children: label
|
|
1924
|
+
})
|
|
1925
|
+
}), jsx("div", {
|
|
1926
|
+
ref: containerRef
|
|
1927
|
+
})]
|
|
1928
|
+
});
|
|
1929
|
+
}
|
|
1930
|
+
|
|
1931
|
+
/**
|
|
1932
|
+
* Entry wrapper for JsonEditor, handles getValue/setValue, built-in JSON validation, error display, and description.
|
|
1933
|
+
*
|
|
1934
|
+
* @param {object} props
|
|
1935
|
+
* @param {object} props.element
|
|
1936
|
+
* @param {string} props.id
|
|
1937
|
+
* @param {string} [props.description]
|
|
1938
|
+
* @param {string} props.label
|
|
1939
|
+
* @param {Function} props.debounce
|
|
1940
|
+
* @param {Function} props.getValue
|
|
1941
|
+
* @param {Function} props.setValue
|
|
1942
|
+
* @param {boolean} [props.disabled]
|
|
1943
|
+
* @param {string} [props.placeholder]
|
|
1944
|
+
* @param {string} [props.tooltip]
|
|
1945
|
+
*/
|
|
1946
|
+
function JsonEditorEntry(props) {
|
|
1947
|
+
const {
|
|
1948
|
+
element,
|
|
1949
|
+
id,
|
|
1950
|
+
description,
|
|
1951
|
+
debounce,
|
|
1952
|
+
label,
|
|
1953
|
+
getValue,
|
|
1954
|
+
setValue,
|
|
1955
|
+
disabled,
|
|
1956
|
+
placeholder,
|
|
1957
|
+
tooltip
|
|
1958
|
+
} = props;
|
|
1959
|
+
const globalError = useError(id);
|
|
1960
|
+
let value = getValue(element);
|
|
1961
|
+
const [editorValue, setEditorValue] = useState(value);
|
|
1962
|
+
useEffect(() => {
|
|
1963
|
+
if (value === editorValue) {
|
|
1964
|
+
return;
|
|
1965
|
+
}
|
|
1966
|
+
setEditorValue(value);
|
|
1967
|
+
}, [value]);
|
|
1968
|
+
const onInput = useStaticCallback(newValue => {
|
|
1969
|
+
setEditorValue(newValue);
|
|
1970
|
+
const currentValue = getValue(element);
|
|
1971
|
+
if (newValue !== currentValue) {
|
|
1972
|
+
setValue(newValue);
|
|
1973
|
+
}
|
|
1974
|
+
});
|
|
1975
|
+
const error = globalError || validateJson(editorValue);
|
|
1976
|
+
return jsxs("div", {
|
|
1977
|
+
class: classnames('bio-properties-panel-entry', error && 'has-error'),
|
|
1978
|
+
"data-entry-id": id,
|
|
1979
|
+
children: [jsx(JsonEditor, {
|
|
1980
|
+
id: id,
|
|
1981
|
+
label: label,
|
|
1982
|
+
debounce: debounce,
|
|
1983
|
+
value: value,
|
|
1984
|
+
onInput: onInput,
|
|
1985
|
+
disabled: disabled,
|
|
1986
|
+
placeholder: placeholder,
|
|
1987
|
+
tooltip: tooltip,
|
|
1988
|
+
element: element
|
|
1989
|
+
}, element), error && jsx("div", {
|
|
1990
|
+
class: "bio-properties-panel-error",
|
|
1991
|
+
children: error
|
|
1992
|
+
}), jsx(Description, {
|
|
1993
|
+
forId: id,
|
|
1994
|
+
element: element,
|
|
1995
|
+
value: description
|
|
1996
|
+
})]
|
|
1997
|
+
});
|
|
1998
|
+
}
|
|
1999
|
+
|
|
2000
|
+
/**
|
|
2001
|
+
* Check if the JSON editor entry has been edited.
|
|
2002
|
+
*/
|
|
2003
|
+
function isEdited$8(node) {
|
|
2004
|
+
const cmContent = node && node.querySelector('.cm-content');
|
|
2005
|
+
return cmContent ? cmContent.textContent.trim().length > 0 : false;
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
// helpers /////////////////
|
|
2009
|
+
|
|
2010
|
+
function validateJson(value) {
|
|
2011
|
+
if (!value || !value.trim()) return null;
|
|
2012
|
+
try {
|
|
2013
|
+
return isObject(JSON.parse(value)) ? null : 'JSON contains errors';
|
|
2014
|
+
} catch (e) {
|
|
2015
|
+
return 'JSON contains errors';
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
|
|
1819
2019
|
/**
|
|
1820
2020
|
* Button to open popups.
|
|
1821
2021
|
*
|
|
@@ -4899,5 +5099,5 @@ var index = {
|
|
|
4899
5099
|
feelPopupRenderer: ['type', FeelPopupRenderer]
|
|
4900
5100
|
};
|
|
4901
5101
|
|
|
4902
|
-
export { ArrowIcon, CheckboxEntry, CheckboxGroup, CloseIcon, CollapsibleEntry, CreateIcon, index$1 as DebounceInputModule, DeleteIcon, DescriptionContext, Description as DescriptionEntry, DragIcon, DropdownButton, ErrorsContext, EventContext, ExternalLinkIcon, FeelCheckboxEntry, FeelEntry, FeelIcon$1 as FeelIcon, FeelLanguageContext, FeelNumberEntry, index as FeelPopupModule, FeelTemplatingEntry, FeelTextAreaEntry, FeelToggleSwitchEntry, Group, Header, HeaderButton, LaunchIcon, LayoutContext, List as ListEntry, ListGroup, ListItem, NumberFieldEntry, OpenPopupIcon, Placeholder, PropertiesPanel, LayoutContext as PropertiesPanelContext, SelectEntry, Simple as SimpleEntry, TemplatingEntry, TextAreaEntry, TextfieldEntry as TextFieldEntry, ToggleSwitchEntry, TooltipContext, TooltipWrapper as TooltipEntry, isEdited$
|
|
5102
|
+
export { ArrowIcon, CheckboxEntry, CheckboxGroup, CloseIcon, CollapsibleEntry, CreateIcon, index$1 as DebounceInputModule, DeleteIcon, DescriptionContext, Description as DescriptionEntry, DragIcon, DropdownButton, ErrorsContext, EventContext, ExternalLinkIcon, FeelCheckboxEntry, FeelEntry, FeelIcon$1 as FeelIcon, FeelLanguageContext, FeelNumberEntry, index as FeelPopupModule, FeelTemplatingEntry, FeelTextAreaEntry, FeelToggleSwitchEntry, Group, Header, HeaderButton, JsonEditorEntry, LaunchIcon, LayoutContext, List as ListEntry, ListGroup, ListItem, NumberFieldEntry, OpenPopupIcon, Placeholder, PropertiesPanel, LayoutContext as PropertiesPanelContext, SelectEntry, Simple as SimpleEntry, TemplatingEntry, TextAreaEntry, TextfieldEntry as TextFieldEntry, ToggleSwitchEntry, TooltipContext, TooltipWrapper as TooltipEntry, isEdited$9 as isCheckboxEntryEdited, isEdited$5 as isFeelEntryEdited, isEdited$8 as isJsonEditorEntryEdited, isEdited$6 as isNumberFieldEntryEdited, isEdited$3 as isSelectEntryEdited, isEdited$2 as isSimpleEntryEdited, isEdited$4 as isTemplatingEntryEdited, isEdited$1 as isTextAreaEntryEdited, isEdited as isTextFieldEntryEdited, isEdited$7 as isToggleSwitchEntryEdited, useDebounce, useDescriptionContext, useElementVisible, useError, useErrors, useEvent, useKeyFactory, useLayoutState, usePrevious, useShowEntryEvent, useStaticCallback, useStickyIntersectionObserver, useTooltipContext };
|
|
4903
5103
|
//# sourceMappingURL=index.esm.js.map
|