diff --git a/packages/form-js-carbon-styles/test/spec/complex.json b/packages/form-js-carbon-styles/test/spec/complex.json index 677b76730..8536a545b 100644 --- a/packages/form-js-carbon-styles/test/spec/complex.json +++ b/packages/form-js-carbon-styles/test/spec/complex.json @@ -600,6 +600,15 @@ "suffixAdorner": "suffix" } }, + { + "type": "separator", + "id": "Field_1a82jj4sdsd" + }, + { + "type": "spacer", + "height": 30, + "id": "Field_1a82jjsdasd" + }, { "action": "reset", "label": "reset", diff --git a/packages/form-js-editor/assets/form-js-editor-base.css b/packages/form-js-editor/assets/form-js-editor-base.css index 45ec835a1..426bfe6d4 100644 --- a/packages/form-js-editor/assets/form-js-editor-base.css +++ b/packages/form-js-editor/assets/form-js-editor-base.css @@ -710,6 +710,10 @@ background: repeating-linear-gradient( 45deg, #ffffff, #ffffff 10px, #f5f5f5 10px, #f5f5f5 20px); } +.fjs-editor-container .fjs-form-field-separator hr { + margin: 10px 2px; +} + /** * Custom Dragula Styles */ diff --git a/packages/form-js-editor/src/features/properties-panel/PropertiesPanelHeaderProvider.js b/packages/form-js-editor/src/features/properties-panel/PropertiesPanelHeaderProvider.js index d2a29372e..232a9df10 100644 --- a/packages/form-js-editor/src/features/properties-panel/PropertiesPanelHeaderProvider.js +++ b/packages/form-js-editor/src/features/properties-panel/PropertiesPanelHeaderProvider.js @@ -16,6 +16,7 @@ const labelsByType = { number: 'NUMBER', radio: 'RADIO', select: 'SELECT', + separator: 'SEPARATOR', spacer: 'SPACER', taglist: 'TAGLIST', text: 'TEXT VIEW', diff --git a/packages/form-js-editor/src/features/properties-panel/groups/GeneralGroup.js b/packages/form-js-editor/src/features/properties-panel/groups/GeneralGroup.js index 17b1b431f..4aac5bf3b 100644 --- a/packages/form-js-editor/src/features/properties-panel/groups/GeneralGroup.js +++ b/packages/form-js-editor/src/features/properties-panel/groups/GeneralGroup.js @@ -41,6 +41,10 @@ export default function GeneralGroup(field, editField, getService) { ...ReadonlyEntry({ field, editField }) ]; + if (entries.length === 0) { + return null; + } + return { id: 'general', label: 'General', diff --git a/packages/form-js-editor/test/spec/features/palette/Palette.spec.js b/packages/form-js-editor/test/spec/features/palette/Palette.spec.js index e3ceb630c..d88048c45 100644 --- a/packages/form-js-editor/test/spec/features/palette/Palette.spec.js +++ b/packages/form-js-editor/test/spec/features/palette/Palette.spec.js @@ -44,7 +44,7 @@ describe('palette', function() { const result = createPalette({ container }); // then - expect(result.container.querySelectorAll('.fjs-palette-field')).to.have.length(14); + expect(result.container.querySelectorAll('.fjs-palette-field')).to.have.length(PALETTE_ENTRIES.length); expectEntries(result.container, PALETTE_ENTRIES); }); @@ -56,7 +56,7 @@ describe('palette', function() { const result = createPalette({ container }); // then - expect(result.container.querySelectorAll('.fjs-palette-group')).to.have.length(4); + expect(result.container.querySelectorAll('.fjs-palette-group')).to.have.length(PALETTE_GROUPS.length); expectGroups(result.container, PALETTE_GROUPS); }); diff --git a/packages/form-js-playground/test/spec/form.json b/packages/form-js-playground/test/spec/form.json index 1fd709e04..2181435c5 100644 --- a/packages/form-js-playground/test/spec/form.json +++ b/packages/form-js-playground/test/spec/form.json @@ -50,6 +50,9 @@ "label": "Checkbox", "key": "isGood" }, + { + "type": "separator" + }, { "type": "select", "label": "Select me", diff --git a/packages/form-js-viewer/assets/form-js-base.css b/packages/form-js-viewer/assets/form-js-base.css index 5afe4b159..8e4498527 100644 --- a/packages/form-js-viewer/assets/form-js-base.css +++ b/packages/form-js-viewer/assets/form-js-base.css @@ -430,6 +430,15 @@ justify-content: center; } +.fjs-container hr { + border: none; + border-top: solid 2px var(--color-borders-group); +} + +.fjs-container .fjs-form-field-separator hr { + margin: 7px 2px; +} + .fjs-container .fjs-input[type='text'], .fjs-container .fjs-input[type='email'], .fjs-container .fjs-input[type='tel'], diff --git a/packages/form-js-viewer/src/render/components/form-fields/Separator.js b/packages/form-js-viewer/src/render/components/form-fields/Separator.js new file mode 100644 index 000000000..f89be45f5 --- /dev/null +++ b/packages/form-js-viewer/src/render/components/form-fields/Separator.js @@ -0,0 +1,22 @@ +import { formFieldClasses } from '../Util'; + +const type = 'separator'; + +export default function Separator() { + + return ( +
+
+
+ ); +} + +Separator.config = { + type, + keyed: false, + label: 'Separator', + group: 'presentation', + create: (options = {}) => ({ + ...options + }) +}; diff --git a/packages/form-js-viewer/src/render/components/icons/Separator.svg b/packages/form-js-viewer/src/render/components/icons/Separator.svg new file mode 100644 index 000000000..617caef00 --- /dev/null +++ b/packages/form-js-viewer/src/render/components/icons/Separator.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/form-js-viewer/src/render/components/icons/Spacer.svg b/packages/form-js-viewer/src/render/components/icons/Spacer.svg index ca9baeaad..a70c22286 100644 --- a/packages/form-js-viewer/src/render/components/icons/Spacer.svg +++ b/packages/form-js-viewer/src/render/components/icons/Spacer.svg @@ -1,6 +1,6 @@ - - - - - + + + + + diff --git a/packages/form-js-viewer/src/render/components/icons/index.js b/packages/form-js-viewer/src/render/components/icons/index.js index 1f33ab037..f167672f7 100644 --- a/packages/form-js-viewer/src/render/components/icons/index.js +++ b/packages/form-js-viewer/src/render/components/icons/index.js @@ -8,6 +8,7 @@ import ColumnsIcon from './Group.svg'; import NumberIcon from './Number.svg'; import RadioIcon from './Radio.svg'; import SelectIcon from './Select.svg'; +import SeparatorIcon from './Separator.svg'; import SpacerIcon from './Spacer.svg'; import TextIcon from './Text.svg'; import TextfieldIcon from './Textfield.svg'; @@ -27,6 +28,7 @@ export const iconsByType = (type) => { number: NumberIcon, radio: RadioIcon, select: SelectIcon, + separator: SeparatorIcon, spacer: SpacerIcon, taglist: TaglistIcon, text: TextIcon, diff --git a/packages/form-js-viewer/src/render/components/index.js b/packages/form-js-viewer/src/render/components/index.js index 02300edeb..d37d65637 100644 --- a/packages/form-js-viewer/src/render/components/index.js +++ b/packages/form-js-viewer/src/render/components/index.js @@ -10,6 +10,7 @@ import Image from './form-fields/Image'; import Numberfield from './form-fields/Number'; import Radio from './form-fields/Radio'; import Select from './form-fields/Select'; +import Separator from './form-fields/Separator'; import Spacer from './form-fields/Spacer'; import Taglist from './form-fields/Taglist'; import Text from './form-fields/Text'; @@ -29,6 +30,7 @@ export { Numberfield, Radio, Select, + Separator, Spacer, Taglist, Text, @@ -48,6 +50,7 @@ export const formFields = [ Radio, Select, Spacer, + Separator, Taglist, Text, Textfield, diff --git a/packages/form-js-viewer/test/spec/render/components/form-fields/Separator.spec.js b/packages/form-js-viewer/test/spec/render/components/form-fields/Separator.spec.js new file mode 100644 index 000000000..82b1a4d6b --- /dev/null +++ b/packages/form-js-viewer/test/spec/render/components/form-fields/Separator.spec.js @@ -0,0 +1,69 @@ +import { render } from '@testing-library/preact/pure'; + +import Separator from '../../../../../src/render/components/form-fields/Separator'; + +import { + createFormContainer +} from '../../../../TestHelper'; + +import { WithFormContext } from './helper'; + +let container; + + +describe('Separator', function() { + + beforeEach(function() { + container = createFormContainer(); + }); + + afterEach(function() { + container.remove(); + }); + + it('should render', function() { + + // when + const { container } = createSeparator(); + + // then + const formField = container.querySelector('.fjs-form-field'); + + expect(formField).to.exist; + expect(formField.classList.contains('fjs-form-field-separator')).to.be.true; + + const separator = formField.querySelector('hr'); + expect(separator).to.exist; + + }); + +}); + +// helpers ////////// + +const defaultField = { + type: 'separator' +}; + +function createSeparator(options = {}) { + const { + data = {}, + initialData = {}, + properties = {}, + field = defaultField + } = options; + + return render(WithFormContext( + , + { + ...options, + properties, + initialData, + data + } + ), + { + container: options.container || container.querySelector('.fjs-form') + }); +}