diff --git a/package-lock.json b/package-lock.json
index 6249bc56e..d05164c6a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,7 +14,7 @@
"@babel/core": "^7.18.10",
"@babel/plugin-transform-react-jsx": "^7.14.5",
"@babel/plugin-transform-react-jsx-source": "^7.14.5",
- "@bpmn-io/properties-panel": "^3.13.0",
+ "@bpmn-io/properties-panel": "^3.18.0",
"@carbon/react": "^1.42.1",
"@carbon/styles": "^1.42.1",
"@playwright/test": "^1.40.1",
@@ -2134,14 +2134,14 @@
"link": true
},
"node_modules/@bpmn-io/properties-panel": {
- "version": "3.13.0",
- "resolved": "https://registry.npmjs.org/@bpmn-io/properties-panel/-/properties-panel-3.13.0.tgz",
- "integrity": "sha512-KaeHwZpWDycSj8mDnDT/iO5TvyL9eYw+oHbj/69BDMblDp4xenUasWKrif5chZdt/B9gGnVtJp4vIdvlauC/XA==",
+ "version": "3.18.0",
+ "resolved": "https://registry.npmjs.org/@bpmn-io/properties-panel/-/properties-panel-3.18.0.tgz",
+ "integrity": "sha512-Tn6kbfZR9EVhusMsn1h4sD/mShT11vXB7lKQWZwShu4c7b15flNKoM9T1YXl0ATc9uzDP4W2Fj+XjXRKIB2g2g==",
"dependencies": {
- "@bpmn-io/feel-editor": "^1.0.0",
+ "@bpmn-io/feel-editor": "^1.2.0",
"@codemirror/view": "^6.14.0",
"classnames": "^2.3.1",
- "feelers": "^1.1.0",
+ "feelers": "^1.3.0",
"focus-trap": "^7.5.2",
"min-dash": "^4.1.1",
"min-dom": "^4.0.3"
@@ -22040,7 +22040,7 @@
"dependencies": {
"@bpmn-io/draggle": "^4.0.0",
"@bpmn-io/form-js-viewer": "^1.6.4",
- "@bpmn-io/properties-panel": "^3.13.0",
+ "@bpmn-io/properties-panel": "^3.18.0",
"array-move": "^3.0.1",
"big.js": "^6.2.1",
"ids": "^1.0.0",
@@ -23626,7 +23626,7 @@
"requires": {
"@bpmn-io/draggle": "^4.0.0",
"@bpmn-io/form-js-viewer": "^1.6.4",
- "@bpmn-io/properties-panel": "^3.13.0",
+ "@bpmn-io/properties-panel": "^3.18.0",
"array-move": "^3.0.1",
"big.js": "^6.2.1",
"ids": "^1.0.0",
@@ -23748,14 +23748,14 @@
"version": "file:packages/form-json-schema"
},
"@bpmn-io/properties-panel": {
- "version": "3.13.0",
- "resolved": "https://registry.npmjs.org/@bpmn-io/properties-panel/-/properties-panel-3.13.0.tgz",
- "integrity": "sha512-KaeHwZpWDycSj8mDnDT/iO5TvyL9eYw+oHbj/69BDMblDp4xenUasWKrif5chZdt/B9gGnVtJp4vIdvlauC/XA==",
+ "version": "3.18.0",
+ "resolved": "https://registry.npmjs.org/@bpmn-io/properties-panel/-/properties-panel-3.18.0.tgz",
+ "integrity": "sha512-Tn6kbfZR9EVhusMsn1h4sD/mShT11vXB7lKQWZwShu4c7b15flNKoM9T1YXl0ATc9uzDP4W2Fj+XjXRKIB2g2g==",
"requires": {
- "@bpmn-io/feel-editor": "^1.0.0",
+ "@bpmn-io/feel-editor": "^1.2.0",
"@codemirror/view": "^6.14.0",
"classnames": "^2.3.1",
- "feelers": "^1.1.0",
+ "feelers": "^1.3.0",
"focus-trap": "^7.5.2",
"min-dash": "^4.1.1",
"min-dom": "^4.0.3"
diff --git a/package.json b/package.json
index 951c5daa9..10aeddf15 100644
--- a/package.json
+++ b/package.json
@@ -63,7 +63,7 @@
"@babel/core": "^7.18.10",
"@babel/plugin-transform-react-jsx": "^7.14.5",
"@babel/plugin-transform-react-jsx-source": "^7.14.5",
- "@bpmn-io/properties-panel": "^3.13.0",
+ "@bpmn-io/properties-panel": "^3.18.0",
"@carbon/react": "^1.42.1",
"@carbon/styles": "^1.42.1",
"@playwright/test": "^1.40.1",
diff --git a/packages/form-js-editor/package.json b/packages/form-js-editor/package.json
index 779fdc034..d21338416 100644
--- a/packages/form-js-editor/package.json
+++ b/packages/form-js-editor/package.json
@@ -48,7 +48,7 @@
"dependencies": {
"@bpmn-io/draggle": "^4.0.0",
"@bpmn-io/form-js-viewer": "^1.6.4",
- "@bpmn-io/properties-panel": "^3.13.0",
+ "@bpmn-io/properties-panel": "^3.18.0",
"array-move": "^3.0.1",
"big.js": "^6.2.1",
"ids": "^1.0.0",
diff --git a/packages/form-js-editor/src/features/properties-panel/Util.js b/packages/form-js-editor/src/features/properties-panel/Util.js
index 36428c75f..9e05429a2 100644
--- a/packages/form-js-editor/src/features/properties-panel/Util.js
+++ b/packages/form-js-editor/src/features/properties-panel/Util.js
@@ -27,6 +27,11 @@ export function countDecimals(number) {
return num.toFixed().split('.')[1].length || 0;
}
+/**
+ *
+ * @param {unknown} value
+ * @returns {boolean}
+ */
export function isValidNumber(value) {
return (typeof value === 'number' || typeof value === 'string') && value !== '' && !isNaN(Number(value));
}
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/ColumnEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/ColumnEntry.js
index b91185cc2..3cfb0eebf 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/ColumnEntry.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/ColumnEntry.js
@@ -17,8 +17,7 @@ export function ColumnEntry(props) {
editField,
field,
idPrefix,
- index,
- validateFactory
+ index
} = props;
const entries = [
@@ -28,8 +27,7 @@ export function ColumnEntry(props) {
field,
id: idPrefix + '-label',
idPrefix,
- index,
- validateFactory
+ index
},
{
component: Key,
@@ -37,8 +35,7 @@ export function ColumnEntry(props) {
field,
id: idPrefix + '-key',
idPrefix,
- index,
- validateFactory
+ index
}
];
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/ColumnsEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/ColumnsEntry.js
index 618dfb9ec..56b11c344 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/ColumnsEntry.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/ColumnsEntry.js
@@ -8,6 +8,7 @@ import {
} from '@bpmn-io/properties-panel';
import { MIN_COLUMNS } from '../../../core/FormLayoutValidator';
+import { useCallback } from 'preact/hooks';
export const AUTO_OPTION_VALUE = '';
@@ -41,9 +42,9 @@ function Columns(props) {
const debounce = useService('debounce');
const formLayoutValidator = useService('formLayoutValidator');
- const validate = (value) => {
+ const validate = useCallback((value) => {
return formLayoutValidator.validateField(field, value ? parseInt(value) : null);
- };
+ }, [ field, formLayoutValidator ]);
const setValue = (value, error) => {
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/ColumnsExpressionEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/ColumnsExpressionEntry.js
index 21201a32b..f79951055 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/ColumnsExpressionEntry.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/ColumnsExpressionEntry.js
@@ -54,19 +54,6 @@ function ColumnsExpression(props) {
editField(field, PATH, value);
};
- /**
- * @param {string|void} value
- * @returns {string|null}
- */
- const validate = (value) => {
-
- if (!isString(value) || value.length === 0 || value === '=') {
- return 'Must not be empty.';
- }
-
- return null;
- };
-
const schema = '[\n {\n "key": "column_1",\n "label": "Column 1"\n }\n]';
const tooltip =
@@ -90,3 +77,19 @@ function ColumnsExpression(props) {
validate,
});
}
+
+
+// helpers //////////
+
+/**
+ * @param {string|void} value
+ * @returns {string|null}
+ */
+const validate = (value) => {
+
+ if (!isString(value) || value.length === 0 || value === '=') {
+ return 'Must not be empty.';
+ }
+
+ return null;
+};
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/CustomValueEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/CustomValueEntry.js
index 12c5b259e..80a41b11f 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/CustomValueEntry.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/CustomValueEntry.js
@@ -3,6 +3,7 @@ import { get } from 'min-dash';
import { useService } from '../hooks';
import { TextFieldEntry } from '@bpmn-io/properties-panel';
+import { useCallback } from 'preact/hooks';
export function CustomValueEntry(props) {
@@ -63,6 +64,12 @@ function Key(props) {
return Object.keys(get(field, [ 'properties' ]))[ index ];
};
+ const validate = useCallback(
+ () => validateFactory(Object.keys(get(field, [ 'properties' ]))[index]),
+ [ validateFactory, field, index ],
+ );
+
+
return TextFieldEntry({
debounce,
element: field,
@@ -70,7 +77,7 @@ function Key(props) {
id,
label: 'Key',
setValue,
- validate: validateFactory(getValue())
+ validate
});
}
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/DefaultValueEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/DefaultValueEntry.js
index 080b93500..6ab43462a 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/DefaultValueEntry.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/DefaultValueEntry.js
@@ -14,6 +14,7 @@ import Big from 'big.js';
import { useService } from '../hooks';
import { countDecimals, INPUTS, isValidNumber, OPTIONS_INPUTS } from '../Util';
+import { useCallback } from 'preact/hooks';
export const EMPTY_OPTION = null;
@@ -178,6 +179,22 @@ function DefaultValueNumber(props) {
const decimalDigitsSet = decimalDigits || decimalDigits === 0;
+ const validate = useCallback(
+ (value) => {
+ if (value === undefined || value === null) {
+ return;
+ }
+
+ if (!isValidNumber(value)) {
+ return 'Should be a valid number';
+ }
+ if (decimalDigitsSet && countDecimals(value) > decimalDigits) {
+ return `Should not contain more than ${decimalDigits} decimal digits`;
+ }
+ },
+ [ decimalDigitsSet, decimalDigits ],
+ );
+
return TextFieldEntry({
debounce,
label,
@@ -185,11 +202,7 @@ function DefaultValueNumber(props) {
getValue,
id,
setValue,
- validate: (value) => {
- if (value === undefined || value === null) return;
- if (!isValidNumber(value)) return 'Should be a valid number';
- if (decimalDigitsSet && countDecimals(value) > decimalDigits) return `Should not contain more than ${decimalDigits} decimal digits`;
- }
+ validate
});
}
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/HeightEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/HeightEntry.js
index 586f32a5f..0d1a1179d 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/HeightEntry.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/HeightEntry.js
@@ -65,10 +65,27 @@ function Height(props) {
id,
getValue,
setValue,
- validate: (value) => {
- if (value === undefined || value === null) return;
- if (value < 1) return 'Should be greater than zero.';
- if (!Number.isInteger(value)) return 'Should be an integer.';
- }
+ validate
});
}
+
+// helpers //////////
+
+/**
+ * @param {number|void} value
+ * @returns {string|null}
+ */
+const validate = (value) => {
+ if (typeof value !== 'number') {
+ return null;
+ }
+
+ if (!Number.isInteger(value)) {
+ return 'Should be an integer.';
+ }
+
+ if (value < 1) {
+ return 'Should be greater than zero.';
+ }
+};
+
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/HtmlEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/HtmlEntry.js
index fd722f445..3972dbd4c 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/HtmlEntry.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/HtmlEntry.js
@@ -45,15 +45,7 @@ function Content(props) {
return editField(field, path, value || '');
};
- const validate = (value) => {
- // allow empty state
- if (value === undefined || value === null || value === '') { return null; }
-
- // allow expressions
- if (value.startsWith('=')) { return null; }
-
- };
return FeelTemplatingEntry({
debounce,
@@ -69,4 +61,22 @@ function Content(props) {
});
}
-const description = <>Supports HTML, styling, and templating. Styles are automatically scoped to the HTML component.
Learn more>;
\ No newline at end of file
+// helpers //////////
+
+const description = <>Supports HTML, styling, and templating. Styles are automatically scoped to the HTML component.
Learn more>;
+
+/**
+ * @param {string|void} value
+ * @returns {string|null}
+ */
+const validate = (value) => {
+
+ // allow empty state
+ if (typeof value !== 'string' || value === '') {
+ return null;
+ }
+
+ // allow expressions
+ if (value.startsWith('=')) { return null; }
+
+};
\ No newline at end of file
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/IFrameUrlEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/IFrameUrlEntry.js
index 6d4ec119a..cf4efa3d8 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/IFrameUrlEntry.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/IFrameUrlEntry.js
@@ -47,16 +47,6 @@ function Url(props) {
return editField(field, path, value);
};
- const validate = (value) => {
- if (!value || value.startsWith('=')) {
- return;
- }
-
- if (!HTTPS_PATTERN.test(value)) {
- return 'For security reasons the URL must start with "https".';
- }
- };
-
return FeelTemplatingEntry({
debounce,
element: field,
@@ -88,4 +78,18 @@ function getTooltip() {
>
);
-}
\ No newline at end of file
+}
+
+/**
+ * @param {string|void} value
+ * @returns {string|null}
+ */
+const validate = (value) => {
+ if (!value || value.startsWith('=')) {
+ return;
+ }
+
+ if (!HTTPS_PATTERN.test(value)) {
+ return 'For security reasons the URL must start with "https".';
+ }
+};
\ No newline at end of file
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/IdEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/IdEntry.js
index a982ddce6..d3e7fbbad 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/IdEntry.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/IdEntry.js
@@ -3,6 +3,7 @@ import { get, isUndefined } from 'min-dash';
import { useService } from '../hooks';
import { TextFieldEntry, isTextFieldEntryEdited } from '@bpmn-io/properties-panel';
+import { useCallback } from 'preact/hooks';
export function IdEntry(props) {
@@ -49,7 +50,7 @@ function Id(props) {
return editField(field, path, value);
};
- const validate = (value) => {
+ const validate = useCallback((value) => {
if (isUndefined(value) || !value.length) {
return 'Must not be empty.';
}
@@ -61,7 +62,7 @@ function Id(props) {
}
return validateId(value) || null;
- };
+ }, [ formFieldRegistry, field ]);
return TextFieldEntry({
debounce,
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/InputKeyOptionsSourceEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/InputKeyOptionsSourceEntry.js
index 33cc6a00a..269b0ba2b 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/InputKeyOptionsSourceEntry.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/InputKeyOptionsSourceEntry.js
@@ -1,5 +1,5 @@
import { TextFieldEntry, isTextFieldEntryEdited } from '@bpmn-io/properties-panel';
-import { get, isUndefined } from 'min-dash';
+import { get } from 'min-dash';
import { useService } from '../hooks';
import { OPTIONS_SOURCES, OPTIONS_SOURCES_PATHS } from '@bpmn-io/form-js-viewer';
@@ -50,18 +50,6 @@ function InputValuesKey(props) {
editField(field, path, value || '');
};
- const validate = (value) => {
- if (isUndefined(value) || !value.length) {
- return 'Must not be empty.';
- }
-
- if (/\s/.test(value)) {
- return 'Must not contain spaces.';
- }
-
- return null;
- };
-
return TextFieldEntry({
debounce,
description: 'Define which input property to populate the values from',
@@ -74,3 +62,22 @@ function InputValuesKey(props) {
validate
});
}
+
+
+// helpers //////////
+
+/**
+ * @param {string|void} value
+ * @returns {string|null}
+ */
+const validate = (value) => {
+ if (typeof value !== 'string' || value.length === 0) {
+ return 'Must not be empty.';
+ }
+
+ if (/\s/.test(value)) {
+ return 'Must not contain spaces.';
+ }
+
+ return null;
+};
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/KeyEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/KeyEntry.js
index 9a9fd0128..27c5adcd4 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/KeyEntry.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/KeyEntry.js
@@ -5,6 +5,7 @@ import { hasIntegerPathSegment, isValidDotPath } from '../Util';
import { useService } from '../hooks';
import { TextFieldEntry, isTextFieldEntryEdited } from '@bpmn-io/properties-panel';
+import { useCallback } from 'preact/hooks';
export function KeyEntry(props) {
@@ -57,7 +58,7 @@ function Key(props) {
return editField(field, path, value);
};
- const validate = (value) => {
+ const validate = useCallback((value) => {
if (value === field.key) {
return null;
@@ -88,7 +89,7 @@ function Key(props) {
pathRegistry.claimPath(oldPath, { isClosed: true, claimerId: field.id });
return canClaim ? null : 'Must not conflict with other key/path assignments.';
- };
+ }, [ field, pathRegistry ]);
return TextFieldEntry({
debounce,
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/NumberEntries.js b/packages/form-js-editor/src/features/properties-panel/entries/NumberEntries.js
index b313813b5..214fae2ca 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/NumberEntries.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/NumberEntries.js
@@ -4,6 +4,7 @@ import { useService } from '../hooks';
import { countDecimals, isValidNumber } from '../Util';
import Big from 'big.js';
+import { useCallback } from 'preact/hooks';
export function NumberEntries(props) {
const {
@@ -63,11 +64,7 @@ function NumberDecimalDigits(props) {
getValue,
id,
setValue,
- validate: (value) => {
- if (value === undefined || value === null) return;
- if (value < 0) return 'Should be greater than or equal to zero.';
- if (!Number.isInteger(value)) return 'Should be an integer.';
- }
+ validate: validateNumberEntries
});
}
@@ -111,29 +108,62 @@ function NumberArrowStep(props) {
const decimalDigitsSet = decimalDigits || decimalDigits === 0;
- return TextFieldEntry({
- debounce,
- label: 'Increment',
- element: field,
- getValue,
- id,
- setValue,
- validate: (value) => {
-
- if (value === undefined || value === null) return;
+ const validate = useCallback(
+ (value) => {
+ if (value === undefined || value === null) {
+ return;
+ }
- if (!isValidNumber(value)) return 'Should be a valid number.';
+ if (!isValidNumber(value)) {
+ return 'Should be a valid number.';
+ }
- if (Big(value).cmp(0) <= 0) return 'Should be greater than zero.';
+ if (Big(value).cmp(0) <= 0) {
+ return 'Should be greater than zero.';
+ }
if (decimalDigitsSet) {
const minimumValue = Big(`1e-${decimalDigits}`);
- if (Big(value).cmp(minimumValue) < 0) return `Should be at least ${minimumValue.toString()}.`;
- if (countDecimals(value) > decimalDigits) return `Should not contain more than ${decimalDigits} decimal digits.`;
+ if (Big(value).cmp(minimumValue) < 0) {
+ return `Should be at least ${minimumValue.toString()}.`;
+ }
+ if (countDecimals(value) > decimalDigits) {
+ return `Should not contain more than ${decimalDigits} decimal digits.`;
+ }
}
- }
+ },
+ [ decimalDigitsSet, decimalDigits ],
+ );
+
+ return TextFieldEntry({
+ debounce,
+ label: 'Increment',
+ element: field,
+ getValue,
+ id,
+ setValue,
+ validate
});
+}
-}
\ No newline at end of file
+// helpers //////////
+
+/**
+ * @param {number|void} value
+ * @returns {string|void}
+ */
+const validateNumberEntries = (value) => {
+ if (typeof value !== 'number') {
+ return;
+ }
+
+ if (!Number.isInteger(value)) {
+ return 'Should be an integer.';
+ }
+
+ if (value < 0) {
+ return 'Should be greater than or equal to zero.';
+ }
+};
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/PathEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/PathEntry.js
index bc8137ff9..7eb9d5544 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/PathEntry.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/PathEntry.js
@@ -5,6 +5,7 @@ import { useService } from '../hooks';
import { TextFieldEntry, isTextFieldEntryEdited } from '@bpmn-io/properties-panel';
import { isValidDotPath } from '../Util';
+import { useCallback } from 'preact/hooks';
export function PathEntry(props) {
@@ -61,7 +62,7 @@ function Path(props) {
return editField(field, path, value);
};
- const validate = (value) => {
+ const validate = useCallback((value) => {
if (!value && isRepeating) {
return 'Must not be empty';
@@ -102,7 +103,7 @@ function Path(props) {
// If all checks pass
return null;
- };
+ }, [ field, isRepeating, pathRegistry ]);
const tooltip = isRepeating
? 'Routes the children of this component into a form variable, may be left empty to route at the root level.'
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/RowCountEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/RowCountEntry.js
index 275bcac1e..f39f9bd16 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/RowCountEntry.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/RowCountEntry.js
@@ -51,31 +51,6 @@ function RowCount(props) {
editField(field, path, value);
};
- /**
- * @param {string|void} value
- * @returns {string|null}
- */
- const validate = (value) => {
-
- if (isNil(value)) {
- return null;
- }
-
- if (!isNumber(value)) {
- return 'Must be number';
- }
-
- if (!Number.isInteger(value)) {
- return 'Should be an integer.';
- }
-
- if (value < 1) {
- return 'Should be greater than zero.';
- }
-
- return null;
- };
-
return NumberFieldEntry({
debounce,
label: 'Number of rows per page',
@@ -85,4 +60,32 @@ function RowCount(props) {
setValue,
validate
});
-}
\ No newline at end of file
+}
+
+
+// helpers //////////
+
+/**
+ * @param {string|void} value
+ * @returns {string|null}
+ */
+const validate = (value) => {
+
+ if (isNil(value)) {
+ return null;
+ }
+
+ if (!isNumber(value)) {
+ return 'Must be number';
+ }
+
+ if (!Number.isInteger(value)) {
+ return 'Should be an integer.';
+ }
+
+ if (value < 1) {
+ return 'Should be greater than zero.';
+ }
+
+ return null;
+};
\ No newline at end of file
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/TableDataSourceEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/TableDataSourceEntry.js
index ccaa323a2..d9e7dce7d 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/TableDataSourceEntry.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/TableDataSourceEntry.js
@@ -51,32 +51,6 @@ function Source(props) {
editField(field, path, value);
};
- /**
- * @param {string|void} value
- * @returns {string|null}
- */
- const validate = (value) => {
-
- if (!isString(value) || value.length === 0) {
- return 'Must not be empty.';
- }
-
- if (value.startsWith('=')) {
- return null;
- }
-
- if (!isValidDotPath(value)) {
- return 'Must be a variable or a dot separated path.';
- }
-
- if (hasIntegerPathSegment(value)) {
- return 'Must not contain numerical path segments.';
- }
-
- return null;
- };
-
-
return FeelTemplatingEntry({
debounce,
description: 'Specify the source from which to populate the table',
@@ -92,3 +66,31 @@ function Source(props) {
validate,
});
}
+
+
+// helper ////////////////
+
+/**
+ * @param {string|void} value
+ * @returns {string|null}
+ */
+const validate = (value) => {
+
+ if (!isString(value) || value.length === 0) {
+ return 'Must not be empty.';
+ }
+
+ if (value.startsWith('=')) {
+ return null;
+ }
+
+ if (!isValidDotPath(value)) {
+ return 'Must be a variable or a dot separated path.';
+ }
+
+ if (hasIntegerPathSegment(value)) {
+ return 'Must not contain numerical path segments.';
+ }
+
+ return null;
+};
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/ValueEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/ValueEntry.js
index 67dee370b..7b46a7e2c 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/ValueEntry.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/ValueEntry.js
@@ -6,6 +6,7 @@ import {
import { useService } from '../hooks';
import { TextFieldEntry } from '@bpmn-io/properties-panel';
+import { useCallback } from 'preact/hooks';
export function ValueEntry(props) {
@@ -65,6 +66,15 @@ function Label(props) {
return get(field, [ 'values', index, 'label' ]);
};
+ const validate = useCallback(
+ () =>
+ validateFactory(
+ get(field, [ 'values', index, 'label' ]),
+ (entry) => entry.label,
+ ),
+ [ field, index, validateFactory ],
+ );
+
return TextFieldEntry({
debounce,
element: field,
@@ -72,7 +82,7 @@ function Label(props) {
id,
label: 'Label',
setValue,
- validate: validateFactory(getValue(), (entry) => entry.label)
+ validate
});
}
@@ -100,6 +110,15 @@ function Value(props) {
return get(field, [ 'values', index, 'value' ]);
};
+ const validate = useCallback(
+ () =>
+ validateFactory(
+ get(field, [ 'values', index, 'value' ]),
+ (entry) => entry.value,
+ ),
+ [ field, index, validateFactory ],
+ );
+
return TextFieldEntry({
debounce,
element: field,
@@ -107,6 +126,6 @@ function Value(props) {
id,
label: 'Value',
setValue,
- validate: validateFactory(getValue(), (entry) => entry.value)
+ validate
});
}
\ No newline at end of file
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/factories/simpleRangeIntegerEntryFactory.js b/packages/form-js-editor/src/features/properties-panel/entries/factories/simpleRangeIntegerEntryFactory.js
index 4b0e52121..f45b58704 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/factories/simpleRangeIntegerEntryFactory.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/factories/simpleRangeIntegerEntryFactory.js
@@ -4,6 +4,7 @@ import { TextFieldEntry, isTextFieldEntryEdited } from '@bpmn-io/properties-pane
import { isValidNumber } from '../../Util';
import Big from 'big.js';
+import { useCallback } from 'preact/hooks';
export function simpleRangeIntegerEntryFactory(options) {
const {
@@ -60,6 +61,13 @@ const SimpleRangeIntegerEntry = (props) => {
editField(field, path, Number(value));
};
+ const validate = useCallback((value) => {
+ if (value === undefined || value === null || value === '') { return; }
+ if (!Number.isInteger(Number(value))) { return 'Should be an integer.'; }
+ if (Big(value).cmp(min) < 0) { return `Should be at least ${min}.`; }
+ if (Big(value).cmp(max) > 0) { return `Should be at most ${max}.`; }
+ }, [ min, max ]);
+
return TextFieldEntry({
debounce,
label,
@@ -67,11 +75,6 @@ const SimpleRangeIntegerEntry = (props) => {
getValue,
id,
setValue,
- validate: (value) => {
- if (value === undefined || value === null || value === '') { return; }
- if (!Number.isInteger(Number(value))) { return 'Should be an integer.'; }
- if (Big(value).cmp(min) < 0) { return `Should be at least ${min}.`; }
- if (Big(value).cmp(max) > 0) { return `Should be at most ${max}.`; }
- }
+ validate
});
};