@valtimo/process-management 13.52.0 → 13.53.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/fesm2022/valtimo-process-management.mjs +46 -6
- package/fesm2022/valtimo-process-management.mjs.map +1 -1
- package/lib/components/process-management-builder/panel/expression-autocomplete.d.ts +4 -0
- package/lib/components/process-management-builder/panel/expression-autocomplete.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1500,7 +1500,12 @@ class ExpressionAutocomplete {
|
|
|
1500
1500
|
this.stylesInjected = false;
|
|
1501
1501
|
this.observer = null;
|
|
1502
1502
|
this.documentClickHandlers = [];
|
|
1503
|
+
this.selectedElementId = null;
|
|
1504
|
+
this.manualModeKeys = new Set();
|
|
1503
1505
|
this.injectStyles();
|
|
1506
|
+
eventBus.on('selection.changed', (event) => {
|
|
1507
|
+
this.selectedElementId = event?.newSelection?.[0]?.id ?? null;
|
|
1508
|
+
});
|
|
1504
1509
|
eventBus.on('diagram.destroy', () => {
|
|
1505
1510
|
this.dispose();
|
|
1506
1511
|
});
|
|
@@ -1512,6 +1517,7 @@ class ExpressionAutocomplete {
|
|
|
1512
1517
|
this.observer = null;
|
|
1513
1518
|
}
|
|
1514
1519
|
this.panelContainer = null;
|
|
1520
|
+
this.manualModeKeys.clear();
|
|
1515
1521
|
}
|
|
1516
1522
|
cleanupClickHandlers() {
|
|
1517
1523
|
for (const handler of this.documentClickHandlers) {
|
|
@@ -1553,7 +1559,8 @@ class ExpressionAutocomplete {
|
|
|
1553
1559
|
}
|
|
1554
1560
|
isExpressionField(input) {
|
|
1555
1561
|
const type = input.type?.toLowerCase();
|
|
1556
|
-
if (input.tagName !== 'TEXTAREA' &&
|
|
1562
|
+
if (input.tagName !== 'TEXTAREA' &&
|
|
1563
|
+
!(input.tagName === 'INPUT' && (!type || type === 'text'))) {
|
|
1557
1564
|
return false;
|
|
1558
1565
|
}
|
|
1559
1566
|
if (input.closest('.expression-editor-simple')) {
|
|
@@ -1597,7 +1604,7 @@ class ExpressionAutocomplete {
|
|
|
1597
1604
|
wrapper.className = 'expression-editor-wrapper';
|
|
1598
1605
|
const parsed = this.parseExpression(input.value);
|
|
1599
1606
|
const canUseDropdown = !input.value || (parsed.beanName !== null && parsed.methodName !== null);
|
|
1600
|
-
const initialMode = canUseDropdown ? 'simple' : 'technical';
|
|
1607
|
+
const initialMode = canUseDropdown && !this.manualModeKeys.has(this.getModeKey(input)) ? 'simple' : 'technical';
|
|
1601
1608
|
wrapper.dataset.mode = initialMode;
|
|
1602
1609
|
input.parentNode?.insertBefore(wrapper, input);
|
|
1603
1610
|
const toggle = document.createElement('div');
|
|
@@ -1628,6 +1635,13 @@ class ExpressionAutocomplete {
|
|
|
1628
1635
|
}
|
|
1629
1636
|
setEditorMode(wrapper, input, mode) {
|
|
1630
1637
|
wrapper.dataset.mode = mode;
|
|
1638
|
+
const modeKey = this.getModeKey(input);
|
|
1639
|
+
if (mode === 'technical') {
|
|
1640
|
+
this.manualModeKeys.add(modeKey);
|
|
1641
|
+
}
|
|
1642
|
+
else {
|
|
1643
|
+
this.manualModeKeys.delete(modeKey);
|
|
1644
|
+
}
|
|
1631
1645
|
wrapper.querySelectorAll('.expression-editor-toggle__btn').forEach(btn => {
|
|
1632
1646
|
btn.classList.toggle('active', btn.dataset.mode === mode);
|
|
1633
1647
|
});
|
|
@@ -1660,6 +1674,11 @@ class ExpressionAutocomplete {
|
|
|
1660
1674
|
setTimeout(() => input.blur(), 0);
|
|
1661
1675
|
}
|
|
1662
1676
|
}
|
|
1677
|
+
// Panel re-renders on save; key survives new input elements
|
|
1678
|
+
getModeKey(input) {
|
|
1679
|
+
const entryId = input.closest('.bio-properties-panel-entry')?.getAttribute('data-entry-id') || '';
|
|
1680
|
+
return `${this.selectedElementId}|${entryId}|${input.name || input.id}`;
|
|
1681
|
+
}
|
|
1663
1682
|
renderSimpleMode(container, input) {
|
|
1664
1683
|
this.cleanupClickHandlers();
|
|
1665
1684
|
const parsed = this.parseExpression(input.value);
|
|
@@ -1845,14 +1864,37 @@ class ExpressionAutocomplete {
|
|
|
1845
1864
|
}
|
|
1846
1865
|
parseExpression(expr) {
|
|
1847
1866
|
const match = expr.match(/^\$\{([a-zA-Z_]\w*)\.([a-zA-Z_]\w*)\((.*)\)\}$/);
|
|
1848
|
-
if (!match)
|
|
1867
|
+
if (!match || !this.isSingleCallArguments(match[3])) {
|
|
1849
1868
|
return { beanName: null, methodName: null, parameters: [] };
|
|
1869
|
+
}
|
|
1850
1870
|
return {
|
|
1851
1871
|
beanName: match[1],
|
|
1852
1872
|
methodName: match[2],
|
|
1853
1873
|
parameters: this.parseParameters(match[3]),
|
|
1854
1874
|
};
|
|
1855
1875
|
}
|
|
1876
|
+
// Chained calls like `a.b(x).c()` close the first call early
|
|
1877
|
+
isSingleCallArguments(paramsStr) {
|
|
1878
|
+
let depth = 0;
|
|
1879
|
+
let inString = false;
|
|
1880
|
+
let stringChar = '';
|
|
1881
|
+
for (const char of paramsStr) {
|
|
1882
|
+
if (!inString && (char === '"' || char === "'")) {
|
|
1883
|
+
inString = true;
|
|
1884
|
+
stringChar = char;
|
|
1885
|
+
}
|
|
1886
|
+
else if (inString && char === stringChar) {
|
|
1887
|
+
inString = false;
|
|
1888
|
+
}
|
|
1889
|
+
else if (!inString && char === '(') {
|
|
1890
|
+
depth++;
|
|
1891
|
+
}
|
|
1892
|
+
else if (!inString && char === ')' && --depth < 0) {
|
|
1893
|
+
return false;
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
return depth === 0;
|
|
1897
|
+
}
|
|
1856
1898
|
parseParameters(paramsStr) {
|
|
1857
1899
|
const params = [];
|
|
1858
1900
|
let current = '';
|
|
@@ -1903,9 +1945,7 @@ class ExpressionAutocomplete {
|
|
|
1903
1945
|
.replace(/>/g, '>');
|
|
1904
1946
|
}
|
|
1905
1947
|
camelCaseToReadable(text) {
|
|
1906
|
-
return text
|
|
1907
|
-
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
1908
|
-
.replace(/^./, str => str.toUpperCase());
|
|
1948
|
+
return text.replace(/([a-z])([A-Z])/g, '$1 $2').replace(/^./, str => str.toUpperCase());
|
|
1909
1949
|
}
|
|
1910
1950
|
injectStyles() {
|
|
1911
1951
|
if (this.stylesInjected)
|