diff --git a/package-lock.json b/package-lock.json index e6f766d79..0784e1e02 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "@playwright/test": "^1.43.1", "@rollup/plugin-alias": "^5.1.0", "@rollup/plugin-babel": "^6.0.4", - "@rollup/plugin-commonjs": "^25.0.7", + "@rollup/plugin-commonjs": "^26.0.0", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^15.2.3", "@svgr/rollup": "^8.1.0", @@ -4649,20 +4649,20 @@ } }, "node_modules/@rollup/plugin-commonjs": { - "version": "25.0.7", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.7.tgz", - "integrity": "sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==", + "version": "26.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-26.0.1.tgz", + "integrity": "sha512-UnsKoZK6/aGIH6AdkptXhNvhaqftcjq3zZdT+LY5Ftms6JR06nADcDsYp5hTU9E2lbJUEOhdlY5J4DNTneM+jQ==", "dev": true, "dependencies": { "@rollup/pluginutils": "^5.0.1", "commondir": "^1.0.1", "estree-walker": "^2.0.2", - "glob": "^8.0.3", + "glob": "^10.4.1", "is-reference": "1.2.1", "magic-string": "^0.30.3" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0 || 14 >= 14.17" }, "peerDependencies": { "rollup": "^2.68.0||^3.0.0||^4.0.0" @@ -4683,34 +4683,67 @@ } }, "node_modules/@rollup/plugin-commonjs/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", + "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=12" + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/jackspeak": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", + "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" }, "funding": { "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/@rollup/plugin-commonjs/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" } }, "node_modules/@rollup/plugin-json": { @@ -17028,16 +17061,16 @@ "license": "MIT" }, "node_modules/path-scurry": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", - "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -24541,15 +24574,15 @@ } }, "@rollup/plugin-commonjs": { - "version": "25.0.7", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.7.tgz", - "integrity": "sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==", + "version": "26.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-26.0.1.tgz", + "integrity": "sha512-UnsKoZK6/aGIH6AdkptXhNvhaqftcjq3zZdT+LY5Ftms6JR06nADcDsYp5hTU9E2lbJUEOhdlY5J4DNTneM+jQ==", "dev": true, "requires": { "@rollup/pluginutils": "^5.0.1", "commondir": "^1.0.1", "estree-walker": "^2.0.2", - "glob": "^8.0.3", + "glob": "^10.4.1", "is-reference": "1.2.1", "magic-string": "^0.30.3" }, @@ -24564,26 +24597,42 @@ } }, "glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", + "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" + } + }, + "jackspeak": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", + "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", + "dev": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" } }, "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, "requires": { "brace-expansion": "^2.0.1" } + }, + "minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true } } }, @@ -33247,9 +33296,9 @@ "dev": true }, "path-scurry": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", - "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "requires": { "lru-cache": "^10.2.0", diff --git a/package.json b/package.json index dc578708e..6d8bd9c65 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "@playwright/test": "^1.43.1", "@rollup/plugin-alias": "^5.1.0", "@rollup/plugin-babel": "^6.0.4", - "@rollup/plugin-commonjs": "^25.0.7", + "@rollup/plugin-commonjs": "^26.0.0", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^15.2.3", "@svgr/rollup": "^8.1.0", diff --git a/packages/form-js-editor/src/features/properties-panel/entries/DirectionEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/DirectionEntry.js new file mode 100644 index 000000000..c8ee8f562 --- /dev/null +++ b/packages/form-js-editor/src/features/properties-panel/entries/DirectionEntry.js @@ -0,0 +1,60 @@ +import { get } from 'min-dash'; +import { useService, useDirection } from '../hooks'; +import { SelectEntry, isSelectEntryEdited } from '@bpmn-io/properties-panel'; + +export function DirectionEntry(props) { + const { editField, field } = props; + + const entries = [ + { + id: 'direction', + component: Direction, + editField, + field, + isEdited: isSelectEntryEdited, + isDefaultVisible: (field) => field.type === 'default', + }, + ]; + + return entries; +} + +function Direction(props) { + const { editField, field } = props; + const { setDirection } = useDirection(); + + const debounce = useService('debounce'); + + const path = ['direction']; + + const getValue = () => { + const value = get(field, path, 'ltr'); + return value; + }; + + const setValue = (value) => { + setDirection(value); + return editField(field, path, value || 'ltr'); + }; + + const getOptions = () => [ + { + label: 'Left to Right', + value: 'ltr', + }, + { + label: 'Right to Left', + value: 'rtl', + }, + ]; + + return SelectEntry({ + debounce, + element: field, + getValue, + id: 'direction', + label: 'Direction', + setValue, + getOptions, + }); +} diff --git a/packages/form-js-editor/src/features/properties-panel/entries/index.js b/packages/form-js-editor/src/features/properties-panel/entries/index.js index bb6c79066..7777eac28 100644 --- a/packages/form-js-editor/src/features/properties-panel/entries/index.js +++ b/packages/form-js-editor/src/features/properties-panel/entries/index.js @@ -39,3 +39,4 @@ export { RowCountEntry } from './RowCountEntry'; export { HeadersSourceSelectEntry } from './HeadersSourceSelectEntry'; export { ColumnsExpressionEntry } from './ColumnsExpressionEntry'; export { StaticColumnsSourceEntry } from './StaticColumnsSourceEntry'; +export { DirectionEntry } from './DirectionEntry'; diff --git a/packages/form-js-editor/src/features/properties-panel/groups/AppearanceGroup.js b/packages/form-js-editor/src/features/properties-panel/groups/AppearanceGroup.js index 24d6fb293..909b111bb 100644 --- a/packages/form-js-editor/src/features/properties-panel/groups/AppearanceGroup.js +++ b/packages/form-js-editor/src/features/properties-panel/groups/AppearanceGroup.js @@ -1,10 +1,11 @@ -import { AdornerEntry, GroupAppearanceEntry, LayouterAppearanceEntry } from '../entries'; +import { AdornerEntry, GroupAppearanceEntry, LayouterAppearanceEntry, DirectionEntry } from '../entries'; export function AppearanceGroup(field, editField, getService) { const entries = [ ...AdornerEntry({ field, editField }), ...GroupAppearanceEntry({ field, editField }), ...LayouterAppearanceEntry({ field, editField }), + ...DirectionEntry({ field, editField, getService }), ]; if (!entries.length) { diff --git a/packages/form-js-editor/src/features/properties-panel/hooks/DirectionContext.js b/packages/form-js-editor/src/features/properties-panel/hooks/DirectionContext.js new file mode 100644 index 000000000..141f0a925 --- /dev/null +++ b/packages/form-js-editor/src/features/properties-panel/hooks/DirectionContext.js @@ -0,0 +1,26 @@ +import { useContext } from 'preact/hooks'; +import { createContext } from 'preact'; + +const DirectionContext = createContext({ + direction: 'ltr', + setDirection: (direction) => {}, +}); + +export function useDirection() { + const context = useContext(DirectionContext); + if (!context) { + throw new Error('useDirection must be used within a DirectionProvider'); + } + return context; +} + +// // hooks/useDirection.js +// import { useContext } from 'preact/hooks'; +// import { FormContext } from '../context/FormContext'; // Adjust the path as necessary + +// export function useDirection() { +// const form = useContext(FormContext); +// const { schema } = form._getState(); +// const direction = schema?.direction || 'ltr'; +// return direction; +// } diff --git a/packages/form-js-editor/src/features/properties-panel/hooks/index.js b/packages/form-js-editor/src/features/properties-panel/hooks/index.js index 5849aed34..acdc9546d 100644 --- a/packages/form-js-editor/src/features/properties-panel/hooks/index.js +++ b/packages/form-js-editor/src/features/properties-panel/hooks/index.js @@ -1,2 +1,3 @@ export { useVariables } from './useVariables'; export { useService } from './usePropertiesPanelService'; +export { useDirection } from './DirectionContext'; diff --git a/packages/form-js-editor/src/features/repeat-render/EditorRepeatRenderManager.js b/packages/form-js-editor/src/features/repeat-render/EditorRepeatRenderManager.js index 3063e524f..801d93ff6 100644 --- a/packages/form-js-editor/src/features/repeat-render/EditorRepeatRenderManager.js +++ b/packages/form-js-editor/src/features/repeat-render/EditorRepeatRenderManager.js @@ -1,3 +1,40 @@ +// import RepeatSvg from '../../render/components/icons/Repeat.svg'; + +// export class EditorRepeatRenderManager { +// constructor(formFields, formFieldRegistry) { +// this._formFields = formFields; +// this._formFieldRegistry = formFieldRegistry; +// this.RepeatFooter = this.RepeatFooter.bind(this); +// } + +// /** +// * Checks whether a field should be repeatable. +// * +// * @param {string} id - The id of the field to check +// * @returns {boolean} - True if repeatable, false otherwise +// */ +// isFieldRepeating(id) { +// if (!id) { +// return false; +// } + +// const formField = this._formFieldRegistry.get(id); +// const formFieldDefinition = this._formFields.get(formField.type); +// return formFieldDefinition.config.repeatable && formField.isRepeating; +// } + +// RepeatFooter() { +// return ( +//
+// +// Repeatable +//
+// ); +// } +// } + +// EditorRepeatRenderManager.$inject = ['formFields', 'formFieldRegistry']; + import RepeatSvg from '../../render/components/icons/Repeat.svg'; export class EditorRepeatRenderManager { @@ -23,10 +60,12 @@ export class EditorRepeatRenderManager { return formFieldDefinition.config.repeatable && formField.isRepeating; } - RepeatFooter() { + RepeatFooter({ direction }) { return ( -
- +
+ Repeatable
); diff --git a/packages/form-js-viewer/src/features/repeatRender/RepeatRenderManager.js b/packages/form-js-viewer/src/features/repeatRender/RepeatRenderManager.js index 06dba55a8..a9de05744 100644 --- a/packages/form-js-viewer/src/features/repeatRender/RepeatRenderManager.js +++ b/packages/form-js-viewer/src/features/repeatRender/RepeatRenderManager.js @@ -3,6 +3,7 @@ import { get } from 'min-dash'; import { useContext, useMemo, useRef } from 'preact/hooks'; + import { LocalExpressionContext } from '../../render/context/LocalExpressionContext'; import ExpandSvg from '../../render/components/form-fields/icons/Expand.svg'; @@ -11,7 +12,7 @@ import AddSvg from '../../render/components/form-fields/icons/Add.svg'; import DeleteSvg from '../../render/components/form-fields/icons/Delete.svg'; import { buildExpressionContext } from '../../util'; -import { useScrollIntoView } from '../../render/hooks'; +import { useScrollIntoView, useService } from '../../render/hooks'; import classNames from 'classnames'; export class RepeatRenderManager { @@ -23,7 +24,6 @@ export class RepeatRenderManager { this.Repeater = this.Repeater.bind(this); this.RepeatFooter = this.RepeatFooter.bind(this); } - /** * Checks whether a field is currently repeating its children. * @@ -34,45 +34,33 @@ export class RepeatRenderManager { if (!id) { return false; } - const formField = this._formFieldRegistry.get(id); const formFieldDefinition = this._formFields.get(formField.type); return formFieldDefinition.config.repeatable && formField.isRepeating; } - Repeater(props) { const { RowsRenderer, indexes, useSharedState, ...restProps } = props; - const [sharedRepeatState] = useSharedState; - const { data } = this._form._getState(); - const repeaterField = props.field; const dataPath = this._pathRegistry.getValuePath(repeaterField, { indexes }); const values = get(data, dataPath) || []; - const nonCollapsedItems = this._getNonCollapsedItems(repeaterField); const collapseEnabled = !repeaterField.disableCollapse && values.length > nonCollapsedItems; const isCollapsed = collapseEnabled && sharedRepeatState.isCollapsed; - const hasChildren = repeaterField.components && repeaterField.components.length > 0; const showRemove = repeaterField.allowAddRemove && hasChildren; - const displayValues = isCollapsed ? values.slice(0, nonCollapsedItems) : values; - const onDeleteItem = (index) => { const updatedValues = values.slice(); updatedValues.splice(index, 1); - props.onChange({ field: repeaterField, value: updatedValues, indexes, }); }; - const parentExpressionContextInfo = useContext(LocalExpressionContext); - return ( <> {displayValues.map((itemValue, itemIndex) => ( @@ -92,7 +80,6 @@ export class RepeatRenderManager { ); } - RepeatFooter(props) { const addButtonRef = useRef(null); const { useSharedState, indexes, field: repeaterField, readonly, disabled } = props; @@ -145,11 +132,16 @@ export class RepeatRenderManager { [shouldScroll], ); + const form = useService('form'); + const { schema } = form._getState(); + const direction = schema?.direction || 'ltr'; // Fetch the direction value from the form schema + return (
+ })} + style={{ direction: direction }}> {showAdd ? ( ) : null} {collapseEnabled ? ( @@ -182,13 +179,10 @@ export class RepeatRenderManager { _getNonCollapsedItems(field) { const DEFAULT_NON_COLLAPSED_ITEMS = 5; - const { nonCollapsedItems } = field; - return nonCollapsedItems ? nonCollapsedItems : DEFAULT_NON_COLLAPSED_ITEMS; } } - /** * Individual repetition of a repeated field and context scaffolding. * @@ -202,7 +196,6 @@ export class RepeatRenderManager { * @param {Function} props.onDeleteItem * @param {boolean} props.showRemove */ - const RepetitionScaffold = (props) => { const { itemIndex, @@ -215,7 +208,6 @@ const RepetitionScaffold = (props) => { showRemove, ...restProps } = props; - const elementProps = useMemo( () => ({ ...restProps, @@ -223,7 +215,6 @@ const RepetitionScaffold = (props) => { }), [itemIndex, indexes, repeaterField.id, restProps], ); - const localExpressionContextInfo = useMemo( () => ({ data: parentExpressionContextInfo.data, @@ -233,7 +224,6 @@ const RepetitionScaffold = (props) => { }), [itemIndex, parentExpressionContextInfo, itemValue], ); - return !showRemove ? ( @@ -257,5 +247,4 @@ const RepetitionScaffold = (props) => {
); }; - RepeatRenderManager.$inject = ['form', 'formFields', 'formFieldRegistry', 'pathRegistry']; diff --git a/packages/form-js-viewer/src/render/components/form-fields/Button.js b/packages/form-js-viewer/src/render/components/form-fields/Button.js index 966c88f3c..c57ad4fe4 100644 --- a/packages/form-js-viewer/src/render/components/form-fields/Button.js +++ b/packages/form-js-viewer/src/render/components/form-fields/Button.js @@ -1,17 +1,24 @@ import { formFieldClasses } from '../Util'; -import { useSingleLineTemplateEvaluation } from '../../hooks'; +import { useSingleLineTemplateEvaluation, useService } from '../../hooks'; const type = 'button'; export function Button(props) { const { disabled, onFocus, onBlur, field } = props; - const { action = 'submit' } = field; - const evaluatedLabel = useSingleLineTemplateEvaluation(field.label || '', { debug: true }); + const form = useService('form'); + const { schema } = form._getState(); + + const direction = schema?.direction || 'ltr'; // Fetch the direction value from the form schema + return ( -
+
-
diff --git a/packages/form-js-viewer/src/render/components/form-fields/Radio.js b/packages/form-js-viewer/src/render/components/form-fields/Radio.js index c3a828f0c..1b20b6049 100644 --- a/packages/form-js-viewer/src/render/components/form-fields/Radio.js +++ b/packages/form-js-viewer/src/render/components/form-fields/Radio.js @@ -7,6 +7,7 @@ import classNames from 'classnames'; import { Description } from '../Description'; import { Errors } from '../Errors'; import { Label } from '../Label'; +import { useService } from '../../hooks'; import { sanitizeSingleSelectValue } from '../util/sanitizerUtil'; @@ -59,9 +60,15 @@ export function Radio(props) { const descriptionId = `${domId}-description`; const errorMessageId = `${domId}-error-message`; + const form = useService('form'); + const { schema } = form._getState(); + const direction = schema?.direction || 'ltr'; // Fetch the direction value from the form schema return ( -
+
); diff --git a/packages/form-js-viewer/src/render/components/form-fields/Select.js b/packages/form-js-viewer/src/render/components/form-fields/Select.js index b3107b9f6..4c0058eaf 100644 --- a/packages/form-js-viewer/src/render/components/form-fields/Select.js +++ b/packages/form-js-viewer/src/render/components/form-fields/Select.js @@ -3,6 +3,7 @@ import { Errors } from '../Errors'; import { Label } from '../Label'; import { SearchableSelect } from './parts/SearchableSelect'; import { SimpleSelect } from './parts/SimpleSelect'; +import { useService } from '../../hooks'; import { sanitizeSingleSelectValue } from '../util/sanitizerUtil'; import { createEmptyOptions } from '../util/optionsUtil'; @@ -35,6 +36,10 @@ export function Select(props) { 'aria-describedby': [descriptionId, errorMessageId].join(' '), }; + const form = useService('form'); + const { schema } = form._getState(); + const direction = schema?.direction || 'ltr'; // Fetch the direction value from the form schema + return (
+ }} + style={{ direction: direction }}>