├── .codecov.yml
├── .gitattributes
├── .github
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ ├── ADD_TO_HTO_PROJECT.yml
│ ├── CI.yml
│ ├── DEPLOY_PLAYGROUND_PREVIEW.yml
│ ├── MERGE_MASTER_TO_DEVELOP.yml
│ ├── POST_RELEASE.yml
│ ├── TASKLIST_CARBONISATION.yml
│ ├── TEARDOWN_PLAYGROUND_PREVIEW.yml
│ ├── UPDATE_VISUAL_SNAPSHOTS.yml
│ └── VISUAL_REGRESSION.yml
├── .gitignore
├── .nvmrc
├── .prettierrc.json
├── LICENSE
├── README.md
├── docs
└── FORM_SCHEMA.md
├── e2e
├── README.md
├── carbon
│ ├── carbon.scss
│ ├── index.html
│ ├── index.js
│ └── theme.scss
├── index.html
├── main.js
├── renderSchema.js
├── styles.scss
├── test-fixtures.js
├── theming
│ ├── index.html
│ ├── index.js
│ └── theme.scss
└── visual
│ ├── carbon-styles.spec.js
│ ├── carbon-styles.spec.js-snapshots
│ ├── carbon-styles-1-chromium-linux.png
│ ├── carbon-styles-1-firefox-linux.png
│ └── carbon-styles-1-webkit-linux.png
│ ├── empty-ui.spec.js
│ ├── empty-ui.spec.js-snapshots
│ ├── empty-playground-1-chromium-linux.png
│ ├── empty-playground-1-firefox-linux.png
│ └── empty-playground-1-webkit-linux.png
│ ├── fixtures
│ ├── complex.json
│ ├── empty.json
│ ├── form.json
│ └── groups.json
│ ├── groups-ui.spec.js
│ ├── groups-ui.spec.js-snapshots
│ ├── groups-playground-1-chromium-linux.png
│ ├── groups-playground-1-firefox-linux.png
│ └── groups-playground-1-webkit-linux.png
│ ├── no-theme.spec.js
│ ├── no-theme.spec.js-snapshots
│ ├── no-theme---editor-1-chromium-linux.png
│ ├── no-theme---editor-1-firefox-linux.png
│ ├── no-theme---editor-1-webkit-linux.png
│ ├── no-theme---viewer-1-chromium-linux.png
│ ├── no-theme---viewer-1-firefox-linux.png
│ └── no-theme---viewer-1-webkit-linux.png
│ ├── theming.spec.js
│ └── theming.spec.js-snapshots
│ ├── theming---editor-1-chromium-linux.png
│ ├── theming---editor-1-firefox-linux.png
│ ├── theming---editor-1-webkit-linux.png
│ ├── theming---viewer-1-chromium-linux.png
│ ├── theming---viewer-1-firefox-linux.png
│ └── theming---viewer-1-webkit-linux.png
├── eslint.config.mjs
├── lerna.json
├── package-lock.json
├── package.json
├── packages
├── form-js-carbon-styles
│ ├── LICENSE
│ ├── karma.conf.js
│ ├── package.json
│ ├── src
│ │ ├── carbon-styles.js
│ │ ├── carbon-styles.scss
│ │ └── types
│ │ │ └── carbon-styles.d.ts
│ └── test
│ │ ├── TestHelper.js
│ │ ├── spec
│ │ ├── carbon-styles.spec.js
│ │ ├── complex.json
│ │ └── theme.scss
│ │ ├── test.css
│ │ └── testBundle.js
├── form-js-editor
│ ├── LICENSE
│ ├── README.md
│ ├── assets
│ │ ├── form-js-editor-base.css
│ │ └── index.scss
│ ├── karma.conf.js
│ ├── package.json
│ ├── rollup.config.js
│ ├── src
│ │ ├── FormEditor.js
│ │ ├── core
│ │ │ ├── Debounce.js
│ │ │ ├── EventBus.js
│ │ │ ├── FormFieldRegistry.js
│ │ │ ├── FormLayoutValidator.js
│ │ │ ├── FormLayouter.js
│ │ │ └── index.js
│ │ ├── features
│ │ │ ├── SectionModuleBase.js
│ │ │ ├── dragging
│ │ │ │ ├── Dragging.js
│ │ │ │ └── index.js
│ │ │ ├── editor-actions
│ │ │ │ ├── FormEditorActions.js
│ │ │ │ └── index.js
│ │ │ ├── expression-language
│ │ │ │ ├── EditorTemplating.js
│ │ │ │ └── index.js
│ │ │ ├── keyboard
│ │ │ │ ├── FormEditorKeyboardBindings.js
│ │ │ │ └── index.js
│ │ │ ├── modeling
│ │ │ │ ├── FormLayoutUpdater.js
│ │ │ │ ├── Modeling.js
│ │ │ │ ├── behavior
│ │ │ │ │ ├── ColumnsSourceBehavior.js
│ │ │ │ │ ├── IdBehavior.js
│ │ │ │ │ ├── KeyBehavior.js
│ │ │ │ │ ├── OptionsSourceBehavior.js
│ │ │ │ │ ├── PathBehavior.js
│ │ │ │ │ ├── TableDataSourceBehavior.js
│ │ │ │ │ ├── ValidateBehavior.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── cmd
│ │ │ │ │ ├── AddFormFieldHandler.js
│ │ │ │ │ ├── EditFormFieldHandler.js
│ │ │ │ │ ├── MoveFormFieldHandler.js
│ │ │ │ │ ├── RemoveFormFieldHandler.js
│ │ │ │ │ ├── UpdateIdClaimHandler.js
│ │ │ │ │ ├── UpdateKeyClaimHandler.js
│ │ │ │ │ ├── UpdatePathClaimHandler.js
│ │ │ │ │ └── Util.js
│ │ │ │ └── index.js
│ │ │ ├── palette
│ │ │ │ ├── PaletteRenderer.js
│ │ │ │ ├── components
│ │ │ │ │ ├── Palette.js
│ │ │ │ │ └── PaletteEntry.js
│ │ │ │ └── index.js
│ │ │ ├── properties-panel
│ │ │ │ ├── PropertiesPanel.js
│ │ │ │ ├── PropertiesPanelHeaderProvider.js
│ │ │ │ ├── PropertiesPanelModule.js
│ │ │ │ ├── PropertiesPanelPlaceholderProvider.js
│ │ │ │ ├── PropertiesPanelRenderer.js
│ │ │ │ ├── PropertiesProvider.js
│ │ │ │ ├── Util.js
│ │ │ │ ├── components
│ │ │ │ │ ├── AutoFocusSelect.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── context
│ │ │ │ │ ├── FormPropertiesPanelContext.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── entries
│ │ │ │ │ ├── AcceptEntry.js
│ │ │ │ │ ├── ActionEntry.js
│ │ │ │ │ ├── AdornerEntry.js
│ │ │ │ │ ├── AltTextEntry.js
│ │ │ │ │ ├── ColumnEntry.js
│ │ │ │ │ ├── ColumnsEntry.js
│ │ │ │ │ ├── ColumnsExpressionEntry.js
│ │ │ │ │ ├── ConditionEntry.js
│ │ │ │ │ ├── CustomValueEntry.js
│ │ │ │ │ ├── DateTimeConstraintsEntry.js
│ │ │ │ │ ├── DateTimeEntry.js
│ │ │ │ │ ├── DateTimeFormatEntry.js
│ │ │ │ │ ├── DefaultValueEntry.js
│ │ │ │ │ ├── DescriptionEntry.js
│ │ │ │ │ ├── DisabledEntry.js
│ │ │ │ │ ├── DocumentsDataSource.js
│ │ │ │ │ ├── ExpressionFieldEntries.js
│ │ │ │ │ ├── GroupAppearanceEntry.js
│ │ │ │ │ ├── HeadersSourceSelectEntry.js
│ │ │ │ │ ├── HeightEntry.js
│ │ │ │ │ ├── HtmlEntry.js
│ │ │ │ │ ├── IFrameHeightEntry.js
│ │ │ │ │ ├── IFrameUrlEntry.js
│ │ │ │ │ ├── IdEntry.js
│ │ │ │ │ ├── ImageSourceEntry.js
│ │ │ │ │ ├── InputKeyOptionsSourceEntry.js
│ │ │ │ │ ├── KeyEntry.js
│ │ │ │ │ ├── LabelEntry.js
│ │ │ │ │ ├── LayouterAppearanceEntry.js
│ │ │ │ │ ├── MaxHeightEntry.js
│ │ │ │ │ ├── MultipleEntry.js
│ │ │ │ │ ├── NumberEntries.js
│ │ │ │ │ ├── NumberSerializationEntry.js
│ │ │ │ │ ├── OptionsExpressionEntry.js
│ │ │ │ │ ├── OptionsSourceSelectEntry.js
│ │ │ │ │ ├── PaginationEntry.js
│ │ │ │ │ ├── PathEntry.js
│ │ │ │ │ ├── ReadonlyEntry.js
│ │ │ │ │ ├── RepeatableEntry.js
│ │ │ │ │ ├── RowCountEntry.js
│ │ │ │ │ ├── SelectEntries.js
│ │ │ │ │ ├── StaticColumnsSourceEntry.js
│ │ │ │ │ ├── StaticOptionsSourceEntry.js
│ │ │ │ │ ├── TableDataSourceEntry.js
│ │ │ │ │ ├── TextEntry.js
│ │ │ │ │ ├── ValueEntry.js
│ │ │ │ │ ├── VersionTagEntry.js
│ │ │ │ │ ├── factories
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── simpleBoolEntryFactory.js
│ │ │ │ │ │ ├── simpleRangeIntegerEntryFactory.js
│ │ │ │ │ │ ├── simpleSelectEntryFactory.js
│ │ │ │ │ │ ├── simpleStringEntryFactory.js
│ │ │ │ │ │ └── zeroPositiveIntegerEntryFactory.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── groups
│ │ │ │ │ ├── AppearanceGroup.js
│ │ │ │ │ ├── ConditionGroup.js
│ │ │ │ │ ├── ConstraintsGroup.js
│ │ │ │ │ ├── CustomPropertiesGroup.js
│ │ │ │ │ ├── GeneralGroup.js
│ │ │ │ │ ├── LayoutGroup.js
│ │ │ │ │ ├── OptionsGroups.js
│ │ │ │ │ ├── SecurityAttributesGroup.js
│ │ │ │ │ ├── SerializationGroup.js
│ │ │ │ │ ├── TableHeaderGroups.js
│ │ │ │ │ ├── ValidationGroup.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── hooks
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── usePropertiesPanelService.js
│ │ │ │ │ └── useVariables.js
│ │ │ │ ├── icons
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── pp-checkbox-checked.svg
│ │ │ │ │ ├── pp-checkbox.svg
│ │ │ │ │ ├── pp-create.svg
│ │ │ │ │ ├── pp-fullpanel-off.svg
│ │ │ │ │ ├── pp-fullpanel.svg
│ │ │ │ │ ├── pp-list-arrow.svg
│ │ │ │ │ ├── pp-list-delete.svg
│ │ │ │ │ └── pp-section-arrow.svg
│ │ │ │ └── index.js
│ │ │ ├── render-injection
│ │ │ │ ├── RenderInjector.js
│ │ │ │ ├── components
│ │ │ │ │ └── InjectedRendersRoot.js
│ │ │ │ ├── index.js
│ │ │ │ └── slot-fill
│ │ │ │ │ ├── Fill.js
│ │ │ │ │ ├── FillContext.js
│ │ │ │ │ ├── Slot.js
│ │ │ │ │ ├── SlotContext.js
│ │ │ │ │ ├── SlotFillRoot.js
│ │ │ │ │ └── index.js
│ │ │ ├── repeat-render
│ │ │ │ ├── EditorRepeatRenderManager.js
│ │ │ │ └── index.js
│ │ │ └── selection
│ │ │ │ ├── Selection.js
│ │ │ │ ├── SelectionBehavior.js
│ │ │ │ └── index.js
│ │ ├── index.js
│ │ ├── render
│ │ │ ├── EditorFormFields.js
│ │ │ ├── Renderer.js
│ │ │ ├── components
│ │ │ │ ├── FieldDragPreview.js
│ │ │ │ ├── FieldResizer.js
│ │ │ │ ├── FormEditor.js
│ │ │ │ ├── ModularSection.js
│ │ │ │ ├── Util.js
│ │ │ │ ├── editor-form-fields
│ │ │ │ │ ├── EditorDocumentPreview.js
│ │ │ │ │ ├── EditorExpressionField.js
│ │ │ │ │ ├── EditorHtml.js
│ │ │ │ │ ├── EditorIFrame.js
│ │ │ │ │ ├── EditorTable.js
│ │ │ │ │ ├── EditorText.js
│ │ │ │ │ └── index.js
│ │ │ │ └── icons
│ │ │ │ │ ├── Close.svg
│ │ │ │ │ ├── Delete.svg
│ │ │ │ │ ├── Draggable.svg
│ │ │ │ │ ├── EmptyForm.svg
│ │ │ │ │ ├── Repeat.svg
│ │ │ │ │ ├── Search.svg
│ │ │ │ │ └── index.js
│ │ │ ├── context
│ │ │ │ ├── DragAndDropContext.js
│ │ │ │ ├── FormEditorContext.js
│ │ │ │ └── index.js
│ │ │ ├── hooks
│ │ │ │ ├── index.js
│ │ │ │ ├── useDebounce.js
│ │ │ │ ├── usePrevious.js
│ │ │ │ └── useService.js
│ │ │ ├── index.js
│ │ │ └── util
│ │ │ │ └── Cursor.js
│ │ ├── types.d.ts
│ │ └── types
│ │ │ └── custom.d.ts
│ └── test
│ │ ├── TestHelper.js
│ │ ├── coverageBundle.js
│ │ ├── helper
│ │ ├── index.js
│ │ └── mocks
│ │ │ └── index.js
│ │ ├── spec
│ │ ├── FormEditor.spec.js
│ │ ├── complex.json
│ │ ├── core
│ │ │ ├── FieldFactory.spec.js
│ │ │ ├── FormLayoutValidator.form.json
│ │ │ └── FormLayoutValidator.spec.js
│ │ ├── defaultValues.json
│ │ ├── features
│ │ │ ├── editor-actions
│ │ │ │ └── FormEditorActions.spec.js
│ │ │ ├── keyboard
│ │ │ │ └── FormEditorKeyboardBindings.spec.js
│ │ │ ├── modeling
│ │ │ │ ├── FormLayoutUpdater.spec.js
│ │ │ │ ├── Modeling.spec.js
│ │ │ │ └── behavior
│ │ │ │ │ ├── ColumnsSourceBehavior.spec.js
│ │ │ │ │ ├── IdBehavior.spec.js
│ │ │ │ │ ├── KeyBehavior.spec.js
│ │ │ │ │ ├── OptionsSourceBehavior.spec.js
│ │ │ │ │ ├── PathBehavior.spec.js
│ │ │ │ │ └── ValidateBehavior.spec.js
│ │ │ ├── palette
│ │ │ │ ├── Palette.spec.js
│ │ │ │ └── PaletteModule.spec.js
│ │ │ ├── properties-panel
│ │ │ │ ├── PropertiesPanel.spec.js
│ │ │ │ ├── PropertiesPanelHeaderProvider.spec.js
│ │ │ │ ├── PropertiesPanelModule.spec.js
│ │ │ │ ├── groups
│ │ │ │ │ ├── AppearanceGroup.spec.js
│ │ │ │ │ ├── ConditionGroup.spec.js
│ │ │ │ │ ├── GeneralGroup.spec.js
│ │ │ │ │ ├── LayoutGroup.spec.js
│ │ │ │ │ ├── SecurityAttributesGroup.spec.js
│ │ │ │ │ ├── SerializationGroup.spec.js
│ │ │ │ │ └── ValidationGroup.spec.js
│ │ │ │ └── helper
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── mocks
│ │ │ │ │ └── index.js
│ │ │ ├── render-injection
│ │ │ │ ├── RenderInjector.spec.js
│ │ │ │ └── SlotFill.spec.js
│ │ │ └── selection
│ │ │ │ ├── Selection.spec.js
│ │ │ │ └── SelectionBehavior.spec.js
│ │ ├── form-group.json
│ │ ├── form-no-ids.json
│ │ ├── form-rows.json
│ │ ├── form-table.json
│ │ ├── form.json
│ │ ├── import
│ │ │ └── Importer.spec.js
│ │ ├── other.json
│ │ ├── redundantValues.json
│ │ └── render
│ │ │ └── components
│ │ │ └── form-fields
│ │ │ ├── EditorText.spec.js
│ │ │ └── helper
│ │ │ └── index.js
│ │ ├── test.css
│ │ └── testBundle.js
├── form-js-integration
│ ├── package.json
│ └── src
│ │ └── application.ts
├── form-js-playground
│ ├── LICENSE
│ ├── README.md
│ ├── karma.conf.js
│ ├── package.json
│ ├── resources
│ │ └── screenshot.png
│ ├── rollup.config.js
│ ├── src
│ │ ├── Playground.js
│ │ ├── components
│ │ │ ├── EmbedModal.js
│ │ │ ├── FileDrop.css
│ │ │ ├── JSONEditor.js
│ │ │ ├── Modal.js
│ │ │ ├── PlaygroundRoot.css
│ │ │ ├── PlaygroundRoot.js
│ │ │ ├── Section.js
│ │ │ └── autocompletion
│ │ │ │ ├── VariablesFacet.js
│ │ │ │ └── index.js
│ │ └── index.js
│ └── test
│ │ ├── TestHelper.js
│ │ ├── coverageBundle.js
│ │ ├── custom
│ │ ├── editor.js
│ │ ├── range.svg
│ │ ├── styles.css
│ │ └── viewer.js
│ │ ├── spec
│ │ ├── JSONEditor.spec.js
│ │ ├── Playground.spec.js
│ │ ├── custom.json
│ │ ├── form.json
│ │ ├── other-form.json
│ │ └── rows-form.json
│ │ ├── test.css
│ │ └── testBundle.js
├── form-js-viewer
│ ├── LICENSE
│ ├── README.md
│ ├── assets
│ │ ├── form-js-base.css
│ │ ├── grid.scss
│ │ └── index.scss
│ ├── karma.conf.js
│ ├── package.json
│ ├── rollup.config.js
│ ├── src
│ │ ├── Form.js
│ │ ├── core
│ │ │ ├── EventBus.js
│ │ │ ├── FieldFactory.js
│ │ │ ├── FormFieldInstanceRegistry.js
│ │ │ ├── FormFieldRegistry.js
│ │ │ ├── FormLayouter.js
│ │ │ ├── Importer.js
│ │ │ ├── PathRegistry.js
│ │ │ ├── Validator.js
│ │ │ └── index.js
│ │ ├── features
│ │ │ ├── expressionField
│ │ │ │ ├── ExpressionLoopPreventer.js
│ │ │ │ └── index.js
│ │ │ ├── expressionLanguage
│ │ │ │ ├── ConditionChecker.js
│ │ │ │ ├── FeelExpressionLanguage.js
│ │ │ │ ├── FeelersTemplating.js
│ │ │ │ ├── index.js
│ │ │ │ └── variableExtractionHelpers.js
│ │ │ ├── index.js
│ │ │ ├── markdown
│ │ │ │ ├── MarkdownRenderer.js
│ │ │ │ └── index.js
│ │ │ ├── repeatRender
│ │ │ │ ├── RepeatRenderManager.js
│ │ │ │ └── index.js
│ │ │ └── viewerCommands
│ │ │ │ ├── ViewerCommands.js
│ │ │ │ ├── cmd
│ │ │ │ ├── UpdateFieldInstanceValidationHandler.js
│ │ │ │ └── UpdateFieldValidationHandler.js
│ │ │ │ └── index.js
│ │ ├── index.js
│ │ ├── render
│ │ │ ├── FileRegistry.js
│ │ │ ├── FormFields.js
│ │ │ ├── Renderer.js
│ │ │ ├── components
│ │ │ │ ├── .DS_Store
│ │ │ │ ├── Description.js
│ │ │ │ ├── Errors.js
│ │ │ │ ├── FormComponent.js
│ │ │ │ ├── FormField.js
│ │ │ │ ├── Label.js
│ │ │ │ ├── PoweredBy.js
│ │ │ │ ├── Sanitizer.js
│ │ │ │ ├── Util.js
│ │ │ │ ├── form-fields
│ │ │ │ │ ├── Button.js
│ │ │ │ │ ├── Checkbox.js
│ │ │ │ │ ├── Checklist.js
│ │ │ │ │ ├── Datetime.js
│ │ │ │ │ ├── Default.js
│ │ │ │ │ ├── DocumentPreview.js
│ │ │ │ │ ├── DynamicList.js
│ │ │ │ │ ├── ExpressionField.js
│ │ │ │ │ ├── FilePicker.js
│ │ │ │ │ ├── Group.js
│ │ │ │ │ ├── Html.js
│ │ │ │ │ ├── IFrame.js
│ │ │ │ │ ├── Image.js
│ │ │ │ │ ├── Number.js
│ │ │ │ │ ├── Radio.js
│ │ │ │ │ ├── Select.js
│ │ │ │ │ ├── Separator.js
│ │ │ │ │ ├── Spacer.js
│ │ │ │ │ ├── Table.js
│ │ │ │ │ ├── Taglist.js
│ │ │ │ │ ├── Text.js
│ │ │ │ │ ├── Textarea.js
│ │ │ │ │ ├── Textfield.js
│ │ │ │ │ ├── icons
│ │ │ │ │ │ ├── Add.svg
│ │ │ │ │ │ ├── AngelDown.svg
│ │ │ │ │ │ ├── AngelUp.svg
│ │ │ │ │ │ ├── ArrowDown.svg
│ │ │ │ │ │ ├── ArrowUp.svg
│ │ │ │ │ │ ├── Calendar.svg
│ │ │ │ │ │ ├── CaretLeft.svg
│ │ │ │ │ │ ├── CaretRight.svg
│ │ │ │ │ │ ├── Clock.svg
│ │ │ │ │ │ ├── Collapse.svg
│ │ │ │ │ │ ├── Delete.svg
│ │ │ │ │ │ ├── Download.svg
│ │ │ │ │ │ ├── Expand.svg
│ │ │ │ │ │ ├── ImagePlaceholder.svg
│ │ │ │ │ │ └── XMark.svg
│ │ │ │ │ └── parts
│ │ │ │ │ │ ├── ChildrenRenderer.js
│ │ │ │ │ │ ├── Datepicker.js
│ │ │ │ │ │ ├── DropdownList.js
│ │ │ │ │ │ ├── InputAdorner.js
│ │ │ │ │ │ ├── SearchableSelect.js
│ │ │ │ │ │ ├── SimpleSelect.js
│ │ │ │ │ │ ├── SkipLink.js
│ │ │ │ │ │ ├── TemplatedInputAdorner.js
│ │ │ │ │ │ └── Timepicker.js
│ │ │ │ ├── icons
│ │ │ │ │ ├── Button.svg
│ │ │ │ │ ├── Checkbox.svg
│ │ │ │ │ ├── Checklist.svg
│ │ │ │ │ ├── Datetime.svg
│ │ │ │ │ ├── DocumentPreview.svg
│ │ │ │ │ ├── DynamicList.svg
│ │ │ │ │ ├── ExpressionField.svg
│ │ │ │ │ ├── FilePicker.svg
│ │ │ │ │ ├── Form.svg
│ │ │ │ │ ├── Group.svg
│ │ │ │ │ ├── HTML.svg
│ │ │ │ │ ├── IFrame.svg
│ │ │ │ │ ├── Image.svg
│ │ │ │ │ ├── Number.svg
│ │ │ │ │ ├── Radio.svg
│ │ │ │ │ ├── Select.svg
│ │ │ │ │ ├── Separator.svg
│ │ │ │ │ ├── Spacer.svg
│ │ │ │ │ ├── Table.svg
│ │ │ │ │ ├── Taglist.svg
│ │ │ │ │ ├── Text.svg
│ │ │ │ │ ├── Textarea.svg
│ │ │ │ │ ├── Textfield.svg
│ │ │ │ │ └── index.js
│ │ │ │ ├── index.js
│ │ │ │ └── util
│ │ │ │ │ ├── dateTimeUtil.js
│ │ │ │ │ ├── domUtil.js
│ │ │ │ │ ├── localisationUtil.js
│ │ │ │ │ ├── numberFieldUtil.js
│ │ │ │ │ ├── optionsUtil.js
│ │ │ │ │ └── sanitizerUtil.js
│ │ │ ├── context
│ │ │ │ ├── FormContext.js
│ │ │ │ ├── FormRenderContext.js
│ │ │ │ ├── LocalExpressionContext.js
│ │ │ │ └── index.js
│ │ │ ├── hooks
│ │ │ │ ├── index.js
│ │ │ │ ├── useBooleanExpressionEvaluation.js
│ │ │ │ ├── useCleanupMultiSelectValue.js
│ │ │ │ ├── useCleanupSingleSelectValue.js
│ │ │ │ ├── useCondition.js
│ │ │ │ ├── useDangerousHTMLWrapper.js
│ │ │ │ ├── useDeepCompareMemoize.js
│ │ │ │ ├── useExpressionEvaluation.js
│ │ │ │ ├── useFilteredFormData.js
│ │ │ │ ├── useFlushDebounce.js
│ │ │ │ ├── useGetLabelCorrelation.js
│ │ │ │ ├── useKeyDownAction.js
│ │ │ │ ├── useOptionsAsync.js
│ │ │ │ ├── usePrevious.js
│ │ │ │ ├── useReadonly.js
│ │ │ │ ├── useScrollIntoView.js
│ │ │ │ ├── useSecurityAttributesMap.js
│ │ │ │ ├── useService.js
│ │ │ │ ├── useSingleLineTemplateEvaluation.js
│ │ │ │ └── useTemplateEvaluation.js
│ │ │ └── index.js
│ │ ├── types.d.ts
│ │ └── util
│ │ │ ├── constants
│ │ │ ├── DatetimeConstants.js
│ │ │ ├── FilePickerConstants.js
│ │ │ ├── IFrameConstants.js
│ │ │ ├── OptionsSourceConstants.js
│ │ │ └── index.js
│ │ │ ├── expressions.js
│ │ │ ├── extractFileReferencesFromRemovedData.js
│ │ │ ├── form.js
│ │ │ ├── getSchemaVariables.js
│ │ │ ├── index.js
│ │ │ ├── injector.js
│ │ │ ├── simple.js
│ │ │ └── structure.js
│ └── test
│ │ ├── TestHelper.js
│ │ ├── coverageBundle.js
│ │ ├── helper
│ │ ├── index.js
│ │ └── preactDebuggers.js
│ │ ├── spec
│ │ ├── Form.spec.js
│ │ ├── appearance.json
│ │ ├── chain-expressions.json
│ │ ├── complex-conditions.json
│ │ ├── complex-expressions.json
│ │ ├── condition-errors-dynamic-list.json
│ │ ├── condition-errors.json
│ │ ├── condition-external-variable.json
│ │ ├── condition.json
│ │ ├── core
│ │ │ ├── FormFieldInstanceRegistry.spec.js
│ │ │ ├── FormFieldRegistry.spec.js
│ │ │ ├── FormLayouter.spec.js
│ │ │ ├── PathRegistry.spec.js
│ │ │ └── Validator.spec.js
│ │ ├── custom
│ │ │ ├── custom.css
│ │ │ └── index.js
│ │ ├── customField.json
│ │ ├── cyclical-expressions.json
│ │ ├── defaultValues.json
│ │ ├── descriptions.json
│ │ ├── disabled.json
│ │ ├── documentPreview.json
│ │ ├── dynamic-list-table-filter-interaction.json
│ │ ├── dynamic-list-variables.json
│ │ ├── dynamic.json
│ │ ├── expression-external-variable.json
│ │ ├── expressionField.json
│ │ ├── features
│ │ │ └── expression-language
│ │ │ │ ├── ConditionChecker.spec.js
│ │ │ │ ├── FeelExpressionLanguage.spec.js
│ │ │ │ └── variableExtractionHelpers.spec.js
│ │ ├── filepicker.json
│ │ ├── focusables.json
│ │ ├── form.json
│ │ ├── groups.json
│ │ ├── hidden-fields-conditional.json
│ │ ├── hidden-fields-expression.json
│ │ ├── html.json
│ │ ├── iframes.json
│ │ ├── images.json
│ │ ├── import
│ │ │ └── Importer.spec.js
│ │ ├── labels.json
│ │ ├── nested-complex-context.json
│ │ ├── other.json
│ │ ├── radio-tabbing.json
│ │ ├── readonly-expression.json
│ │ ├── render
│ │ │ ├── components
│ │ │ │ ├── Description.spec.js
│ │ │ │ ├── FormField.spec.js
│ │ │ │ ├── Label.spec.js
│ │ │ │ ├── Sanitizer.spec.js
│ │ │ │ ├── Util.spec.js
│ │ │ │ ├── form-fields
│ │ │ │ │ ├── Button.spec.js
│ │ │ │ │ ├── Checkbox.spec.js
│ │ │ │ │ ├── Checklist.spec.js
│ │ │ │ │ ├── Datetime.spec.js
│ │ │ │ │ ├── Default.spec.js
│ │ │ │ │ ├── DocumentPreview.spec.js
│ │ │ │ │ ├── Dynamiclist.spec.js
│ │ │ │ │ ├── ExpressionField.spec.js
│ │ │ │ │ ├── FilePicker.spec.js
│ │ │ │ │ ├── Group.spec.js
│ │ │ │ │ ├── Html.spec.js
│ │ │ │ │ ├── IFrame.spec.js
│ │ │ │ │ ├── Image.spec.js
│ │ │ │ │ ├── Number.spec.js
│ │ │ │ │ ├── Radio.spec.js
│ │ │ │ │ ├── Select.spec.js
│ │ │ │ │ ├── Separator.spec.js
│ │ │ │ │ ├── Spacer.spec.js
│ │ │ │ │ ├── Table.spec.js
│ │ │ │ │ ├── Taglist.spec.js
│ │ │ │ │ ├── Text.spec.js
│ │ │ │ │ ├── Textarea.spec.js
│ │ │ │ │ ├── Textfield.spec.js
│ │ │ │ │ ├── parts
│ │ │ │ │ │ └── DropdownList.spec.js
│ │ │ │ │ └── util
│ │ │ │ │ │ ├── numberFieldUtil.spec.js
│ │ │ │ │ │ ├── optionsUtil.spec.js
│ │ │ │ │ │ └── sanitizerUtil.spec.js
│ │ │ │ ├── helper
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── mocks
│ │ │ │ │ │ └── index.js
│ │ │ │ └── util
│ │ │ │ │ ├── DateTimeUtil.spec.js
│ │ │ │ │ ├── domUtil.spec.js
│ │ │ │ │ └── localisationUtil.spec.js
│ │ │ └── hooks
│ │ │ │ ├── useCleanupMultiSelectValues.spec.js
│ │ │ │ ├── useCleanupSingleSelectValue.spec.js
│ │ │ │ └── useKeyDownAction.spec.js
│ │ ├── required.json
│ │ ├── rows.json
│ │ ├── ships-example.json
│ │ ├── stress.json
│ │ ├── template-variable-complex.json
│ │ ├── template-variable.json
│ │ ├── text-template.json
│ │ ├── text.json
│ │ ├── util
│ │ │ └── GetSchemaVariables.spec.js
│ │ ├── validate.json
│ │ └── valuesExpression.json
│ │ ├── test.css
│ │ ├── testBundle.js
│ │ └── theme.scss
├── form-js
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── package.json
│ ├── rollup.config.js
│ ├── src
│ │ ├── editor.js
│ │ ├── index.js
│ │ ├── playground.js
│ │ └── viewer.js
│ └── test
│ │ ├── TestHelper.js
│ │ ├── config
│ │ ├── karma.distro.js
│ │ └── karma.unit.js
│ │ ├── coverageBundle.js
│ │ ├── distro
│ │ ├── form-editor.js
│ │ ├── form-playground.js
│ │ └── form-viewer.js
│ │ ├── spec
│ │ ├── Form.spec.js
│ │ ├── FormEditor.spec.js
│ │ ├── FormPlayground.spec.js
│ │ └── form.json
│ │ ├── test.css
│ │ └── testBundle.js
└── form-json-schema
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── package.json
│ ├── src
│ ├── defs
│ │ ├── appearance.json
│ │ ├── columns.json
│ │ ├── component.json
│ │ ├── conditional.json
│ │ ├── examples
│ │ │ └── components.json
│ │ ├── exporter.json
│ │ ├── field-types
│ │ │ ├── containers.json
│ │ │ ├── inputs.json
│ │ │ ├── multi-inputs.json
│ │ │ └── presentation-components.json
│ │ ├── layout.json
│ │ ├── properties.json
│ │ ├── rules
│ │ │ ├── rules-allowed-properties.json
│ │ │ ├── rules-default.json
│ │ │ ├── rules-defaultValue-type.json
│ │ │ └── rules-required-properties.json
│ │ ├── security.json
│ │ ├── type.json
│ │ ├── validate.json
│ │ └── values.json
│ ├── error-messages.json
│ └── index.json
│ ├── tasks
│ ├── generate-error-messages.js
│ └── generate-schema.js
│ └── test
│ ├── fixtures
│ ├── accept-not-allowed.js
│ ├── action-not-allowed.js
│ ├── alt-not-allowed.js
│ ├── appearance-prefixAdorner-not-allowed.js
│ ├── appearance-suffixAdorner-not-allowed.js
│ ├── columns-columnsExpression-exclusive.js
│ ├── columns-not-allowed.js
│ ├── columnsExpression-not-allowed.js
│ ├── complex.js
│ ├── components-not-allowed.js
│ ├── conditional-not-allowed.js
│ ├── content-not-allowed.js
│ ├── dataSource-not-allowed.js
│ ├── dateLabel-not-allowed.js
│ ├── decimalDigits-not-allowed.js
│ ├── defaultValue-no-array.js
│ ├── defaultValue-no-boolean.js
│ ├── defaultValue-no-string-or-number.js
│ ├── defaultValue-no-string.js
│ ├── defaultValue-not-allowed.js
│ ├── description-not-allowed.js
│ ├── disabled-not-allowed.js
│ ├── disallowPassedDates-not-allowed.js
│ ├── documentPreview.js
│ ├── dynamic-list-properties-not-allowed.js
│ ├── dynamic-list-properties.js
│ ├── dynamiclists.js
│ ├── expression-field-expression-required.js
│ ├── expression-properties.js
│ ├── filepicker.js
│ ├── groups.js
│ ├── height-not-allowed.js
│ ├── iframe.js
│ ├── increment-not-allowed.js
│ ├── increment.js
│ ├── key-invalid.js
│ ├── key-not-allowed.js
│ ├── label-not-allowed.js
│ ├── layout-empty-row.js
│ ├── layout-not-allowed.js
│ ├── maxHeight-not-allowed.js
│ ├── multiple-not-allowed.js
│ ├── no-action.js
│ ├── no-key.js
│ ├── no-subtype.js
│ ├── no-values-property.js
│ ├── package-lock.json
│ ├── package.json
│ ├── path-invalid.js
│ ├── path-not-allowed.js
│ ├── properties-not-allowed.js
│ ├── readonly-not-allowed.js
│ ├── rowCount-no-number.js
│ ├── rowCount-not-allowed.js
│ ├── schemaVersion-not-supported.js
│ ├── searchable-not-allowed.js
│ ├── serializeToString-not-allowed.js
│ ├── showOutline-not-allowed.js
│ ├── simple.js
│ ├── source-not-allowed.js
│ ├── subtype-not-allowed.js
│ ├── text-not-allowed.js
│ ├── timeInterval-not-allowed.js
│ ├── timeLabel-not-allowed.js
│ ├── timeSerializingFormat-not-allowed.js
│ ├── use24h-not-allowed.js
│ ├── validate-max-not-allowed.js
│ ├── validate-maxLength-not-allowed.js
│ ├── validate-min-not-allowed.js
│ ├── validate-minLength-not-allowed.js
│ ├── validate-not-allowed.js
│ ├── validate-pattern-not-allowed.js
│ ├── validate-validationType-not-allowed.js
│ ├── validate-validationType.js
│ ├── values-not-allowed.js
│ ├── valuesExpression-not-allowed.js
│ ├── valuesKey-invalid.js
│ ├── valuesKey-not-allowed.js
│ ├── verticalAlignment-invalid.js
│ ├── verticalAlignment-not-allowed.js
│ └── verticalAlignment.js
│ ├── helpers
│ └── index.js
│ └── spec
│ ├── schema.spec.js
│ └── validation.spec.js
├── playwright.config.js
├── renovate.json
├── tasks
└── stages
│ ├── await-published
│ ├── update-demo
│ ├── update-examples
│ └── update-website
├── tsconfig.json
└── vite.config.js
/.codecov.yml:
--------------------------------------------------------------------------------
1 | comment: off
2 |
3 | parsers:
4 | javascript:
5 | enable_partials: yes
6 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto eol=lf
2 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
9 |
10 | Closes #
11 |
12 | - [ ] This PR adds a new `form-js` element or visually changes an existing component.
13 | - => In that case, we need to ensure we follow up on this, e.g. by [creating an issue in Tasklist](https://github.com/camunda/tasklist/issues/new/choose)
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | dist
2 | coverage
3 | node_modules
4 | .vscode
5 | test-results/
6 | playwright-report/
7 | playwright/.cache/
8 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 20
2 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 120,
3 | "tabWidth": 2,
4 | "singleQuote": true,
5 | "bracketSameLine": true,
6 | "endOfLine": "lf"
7 | }
8 |
--------------------------------------------------------------------------------
/e2e/README.md:
--------------------------------------------------------------------------------
1 | # E2E Tests
2 |
3 | ## Visual regression
4 |
5 | To run the visual regression tests follow the steps below:
6 |
7 | 1. Bootstrap the project with `npm ci` and `npm run build`
8 | 2. Run `npm run start:container`
9 | 3. Build the mock website `npm run build:e2e`
10 | 4. Start the local server with `npm run start:visual-preview`
11 | 5. Run the visual regression tests with `npm run test:visual`
12 |
13 | **_If you need to update the screenshots run `npm run test:visual -- --update-snapshots`_**
14 |
15 | **_If you're using Apple silicon and get an error with ESBuild run `npm i vite --force --no-save` inside the Docker container after step 2 to fix it_**
16 |
--------------------------------------------------------------------------------
/e2e/carbon/carbon.scss:
--------------------------------------------------------------------------------
1 | @use '@carbon/styles' as * with (
2 | $font-path: '@ibm/plex'
3 | );
4 | @use '@carbon/styles/scss/themes';
5 | @use '@carbon/styles/scss/theme';
6 |
7 | @import '@bpmn-io/form-js-carbon-styles/src/carbon-styles';
8 |
9 | [data-carbon-theme='g10'] {
10 | @include theme.theme(themes.$g10);
11 | }
12 |
13 | [data-carbon-theme='g100'] {
14 | @include theme.theme(themes.$g100);
15 | }
16 |
--------------------------------------------------------------------------------
/e2e/carbon/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Carbon styles
8 |
11 |
12 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/e2e/carbon/index.js:
--------------------------------------------------------------------------------
1 | import '@bpmn-io/form-js/dist/assets/form-js.css';
2 | import '@bpmn-io/form-js/dist/assets/form-js-editor.css';
3 | import '@bpmn-io/form-js/dist/assets/form-js-playground.css';
4 |
5 | import './carbon.scss';
6 |
7 | import { renderSchema } from '../renderSchema';
8 |
9 | renderSchema();
10 |
--------------------------------------------------------------------------------
/e2e/carbon/theme.scss:
--------------------------------------------------------------------------------
1 | @use '@carbon/styles' as * with (
2 | $font-path: '@ibm/plex'
3 | );
4 | @use '@carbon/styles/scss/themes';
5 | @use '@carbon/styles/scss/theme';
6 |
7 | [data-carbon-theme='g10'] {
8 | @include theme.theme(themes.$g10);
9 | }
10 |
11 | [data-carbon-theme='g100'] {
12 | @include theme.theme(themes.$g100);
13 | }
14 |
--------------------------------------------------------------------------------
/e2e/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Forms playground
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/e2e/main.js:
--------------------------------------------------------------------------------
1 | import '@bpmn-io/form-js/dist/assets/form-js.css';
2 | import '@bpmn-io/form-js/dist/assets/form-js-editor.css';
3 | import '@bpmn-io/form-js/dist/assets/form-js-playground.css';
4 |
5 | import { renderSchema } from './renderSchema';
6 |
7 | renderSchema();
8 |
--------------------------------------------------------------------------------
/e2e/styles.scss:
--------------------------------------------------------------------------------
1 | $font-prefix: '../node_modules/@ibm/plex';
2 | @import '../node_modules/@ibm/plex/scss/ibm-plex.scss';
3 |
4 | html,
5 | body,
6 | #container {
7 | margin: 0;
8 | padding: 0;
9 | width: 100vw;
10 | height: 100vh;
11 | }
12 |
--------------------------------------------------------------------------------
/e2e/test-fixtures.js:
--------------------------------------------------------------------------------
1 | import { test as base } from '@playwright/test';
2 | import AxeBuilder from '@axe-core/playwright';
3 |
4 | const DEFAULT_AXE_TAGS = ['best-practice', 'wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'cat.semantics', 'cat.forms'];
5 |
6 | const DEFAULT_DISABLE_RULES = ['page-has-heading-one'];
7 |
8 | const test = base.extend({
9 | makeAxeBuilder: async ({ page }, use) => {
10 | const makeAxeBuilder = (options = {}) => {
11 | const { tags = DEFAULT_AXE_TAGS, disableRules = DEFAULT_DISABLE_RULES } = options;
12 |
13 | return new AxeBuilder({ page }).withTags(tags).disableRules(disableRules);
14 | };
15 |
16 | await use(makeAxeBuilder);
17 | },
18 | });
19 |
20 | export { test };
21 |
--------------------------------------------------------------------------------
/e2e/theming/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Theming
8 |
11 |
12 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/e2e/theming/index.js:
--------------------------------------------------------------------------------
1 | import '@bpmn-io/form-js/dist/assets/form-js.css';
2 | import '@bpmn-io/form-js/dist/assets/form-js-editor.css';
3 | import '@bpmn-io/form-js/dist/assets/form-js-playground.css';
4 |
5 | import './theme.scss';
6 |
7 | import { renderSchema } from '../renderSchema';
8 |
9 | renderSchema();
10 |
--------------------------------------------------------------------------------
/e2e/theming/theme.scss:
--------------------------------------------------------------------------------
1 | @use '@carbon/styles' as * with (
2 | $font-path: '@ibm/plex'
3 | );
4 | @use '@carbon/styles/scss/themes';
5 | @use '@carbon/styles/scss/theme';
6 |
7 | [data-carbon-theme='g10'] {
8 | @include theme.theme(themes.$g10);
9 | }
10 |
11 | [data-carbon-theme='g100'] {
12 | @include theme.theme(themes.$g100);
13 | }
14 |
--------------------------------------------------------------------------------
/e2e/visual/carbon-styles.spec.js:
--------------------------------------------------------------------------------
1 | const { expect } = require('@playwright/test');
2 |
3 | const { test } = require('../test-fixtures');
4 |
5 | const schema = require('./fixtures/complex.json');
6 |
7 | test('carbon styles', async ({ page, makeAxeBuilder }) => {
8 | // given
9 | await page.route('/form', (route) => {
10 | route.fulfill({
11 | status: 200,
12 | body: JSON.stringify({
13 | data: {
14 | schema,
15 | component: 'viewer',
16 | },
17 | }),
18 | });
19 | });
20 |
21 | // when
22 | await page.goto('/carbon/');
23 |
24 | await page.waitForSelector('#container', {
25 | state: 'visible',
26 | });
27 |
28 | // then
29 | await expect(page).toHaveScreenshot();
30 |
31 | // and then
32 | const results = await makeAxeBuilder().analyze();
33 |
34 | expect(results.violations).toHaveLength(0);
35 | expect(results.passes.length).toBeGreaterThan(0);
36 | });
37 |
--------------------------------------------------------------------------------
/e2e/visual/carbon-styles.spec.js-snapshots/carbon-styles-1-chromium-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/carbon-styles.spec.js-snapshots/carbon-styles-1-chromium-linux.png
--------------------------------------------------------------------------------
/e2e/visual/carbon-styles.spec.js-snapshots/carbon-styles-1-firefox-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/carbon-styles.spec.js-snapshots/carbon-styles-1-firefox-linux.png
--------------------------------------------------------------------------------
/e2e/visual/carbon-styles.spec.js-snapshots/carbon-styles-1-webkit-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/carbon-styles.spec.js-snapshots/carbon-styles-1-webkit-linux.png
--------------------------------------------------------------------------------
/e2e/visual/empty-ui.spec.js:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test';
2 |
3 | import schema from './fixtures/empty.json';
4 |
5 | test('empty playground', async ({ page }) => {
6 | // given
7 | await page.route('/form', (route) => {
8 | route.fulfill({
9 | status: 200,
10 | body: JSON.stringify({
11 | data: {
12 | schema,
13 | component: 'playground',
14 | },
15 | }),
16 | });
17 | });
18 |
19 | // when
20 | await page.goto('/');
21 |
22 | // then
23 | await expect(page).toHaveScreenshot();
24 | });
25 |
--------------------------------------------------------------------------------
/e2e/visual/empty-ui.spec.js-snapshots/empty-playground-1-chromium-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/empty-ui.spec.js-snapshots/empty-playground-1-chromium-linux.png
--------------------------------------------------------------------------------
/e2e/visual/empty-ui.spec.js-snapshots/empty-playground-1-firefox-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/empty-ui.spec.js-snapshots/empty-playground-1-firefox-linux.png
--------------------------------------------------------------------------------
/e2e/visual/empty-ui.spec.js-snapshots/empty-playground-1-webkit-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/empty-ui.spec.js-snapshots/empty-playground-1-webkit-linux.png
--------------------------------------------------------------------------------
/e2e/visual/fixtures/empty.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../../../packages/form-json-schema/resources/schema.json",
3 | "schemaVersion": 8,
4 | "exporter": {
5 | "name": "Camunda Web Modeler",
6 | "version": "0de37f6"
7 | },
8 | "components": [],
9 | "type": "default",
10 | "id": "form_id",
11 | "executionPlatform": "Camunda Cloud",
12 | "executionPlatformVersion": "8.2.0"
13 | }
14 |
--------------------------------------------------------------------------------
/e2e/visual/groups-ui.spec.js:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test';
2 |
3 | import schema from './fixtures/groups.json';
4 |
5 | test('groups playground', async ({ page }) => {
6 | // given
7 | await page.route('/form', (route) => {
8 | route.fulfill({
9 | status: 200,
10 | body: JSON.stringify({
11 | data: {
12 | schema,
13 | component: 'playground',
14 | },
15 | }),
16 | });
17 | });
18 |
19 | // when
20 | await page.goto('/');
21 |
22 | // then
23 | await expect(page).toHaveScreenshot();
24 | });
25 |
--------------------------------------------------------------------------------
/e2e/visual/groups-ui.spec.js-snapshots/groups-playground-1-chromium-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/groups-ui.spec.js-snapshots/groups-playground-1-chromium-linux.png
--------------------------------------------------------------------------------
/e2e/visual/groups-ui.spec.js-snapshots/groups-playground-1-firefox-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/groups-ui.spec.js-snapshots/groups-playground-1-firefox-linux.png
--------------------------------------------------------------------------------
/e2e/visual/groups-ui.spec.js-snapshots/groups-playground-1-webkit-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/groups-ui.spec.js-snapshots/groups-playground-1-webkit-linux.png
--------------------------------------------------------------------------------
/e2e/visual/no-theme.spec.js-snapshots/no-theme---editor-1-chromium-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/no-theme.spec.js-snapshots/no-theme---editor-1-chromium-linux.png
--------------------------------------------------------------------------------
/e2e/visual/no-theme.spec.js-snapshots/no-theme---editor-1-firefox-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/no-theme.spec.js-snapshots/no-theme---editor-1-firefox-linux.png
--------------------------------------------------------------------------------
/e2e/visual/no-theme.spec.js-snapshots/no-theme---editor-1-webkit-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/no-theme.spec.js-snapshots/no-theme---editor-1-webkit-linux.png
--------------------------------------------------------------------------------
/e2e/visual/no-theme.spec.js-snapshots/no-theme---viewer-1-chromium-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/no-theme.spec.js-snapshots/no-theme---viewer-1-chromium-linux.png
--------------------------------------------------------------------------------
/e2e/visual/no-theme.spec.js-snapshots/no-theme---viewer-1-firefox-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/no-theme.spec.js-snapshots/no-theme---viewer-1-firefox-linux.png
--------------------------------------------------------------------------------
/e2e/visual/no-theme.spec.js-snapshots/no-theme---viewer-1-webkit-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/no-theme.spec.js-snapshots/no-theme---viewer-1-webkit-linux.png
--------------------------------------------------------------------------------
/e2e/visual/theming.spec.js-snapshots/theming---editor-1-chromium-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/theming.spec.js-snapshots/theming---editor-1-chromium-linux.png
--------------------------------------------------------------------------------
/e2e/visual/theming.spec.js-snapshots/theming---editor-1-firefox-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/theming.spec.js-snapshots/theming---editor-1-firefox-linux.png
--------------------------------------------------------------------------------
/e2e/visual/theming.spec.js-snapshots/theming---editor-1-webkit-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/theming.spec.js-snapshots/theming---editor-1-webkit-linux.png
--------------------------------------------------------------------------------
/e2e/visual/theming.spec.js-snapshots/theming---viewer-1-chromium-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/theming.spec.js-snapshots/theming---viewer-1-chromium-linux.png
--------------------------------------------------------------------------------
/e2e/visual/theming.spec.js-snapshots/theming---viewer-1-firefox-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/theming.spec.js-snapshots/theming---viewer-1-firefox-linux.png
--------------------------------------------------------------------------------
/e2e/visual/theming.spec.js-snapshots/theming---viewer-1-webkit-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/e2e/visual/theming.spec.js-snapshots/theming---viewer-1-webkit-linux.png
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1.15.2",
3 | "$schema": "node_modules/lerna/schemas/lerna-schema.json"
4 | }
5 |
--------------------------------------------------------------------------------
/packages/form-js-carbon-styles/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@bpmn-io/form-js-carbon-styles",
3 | "version": "1.15.2",
4 | "description": "Custom carbon styles for form-js",
5 | "scripts": {
6 | "all": "run-s test",
7 | "test": "karma start",
8 | "dev": "npm test -- --auto-watch --no-single-run"
9 | },
10 | "license": "SEE LICENSE IN LICENSE",
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/bpmn-io/form-js.git",
14 | "directory": "packages/form-js-carbon-styles"
15 | },
16 | "author": {
17 | "name": "bpmn.io contributors",
18 | "url": "https://github.com/bpmn-io"
19 | },
20 | "devDependencies": {
21 | "@bpmn-io/form-js-viewer": "^1.15.2",
22 | "@carbon/elements": "^11.63.2",
23 | "styled-components": "^6.1.16"
24 | },
25 | "files": [
26 | "src"
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/packages/form-js-carbon-styles/src/types/carbon-styles.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * DEPRECATED: This file is deprecated and will be removed with one of the next releases.
3 | */
4 |
5 | declare module '@bpmn-io/form-js-carbon-styles' {
6 | import { FlattenSimpleInterpolation, GlobalStyleComponent, DefaultTheme } from 'styled-components';
7 |
8 | const CARBON_STYLES: FlattenSimpleInterpolation;
9 | const GlobalFormStyling: GlobalStyleComponent<{}, DefaultTheme>;
10 | }
11 |
--------------------------------------------------------------------------------
/packages/form-js-carbon-styles/test/TestHelper.js:
--------------------------------------------------------------------------------
1 | export function isSingleStart(topic) {
2 | return window.__env__ && window.__env__.SINGLE_START === topic;
3 | }
4 |
5 | export function insertCSS(name, css) {
6 | if (document.querySelector('[data-css-file="' + name + '"]')) {
7 | return;
8 | }
9 |
10 | const head = document.head || document.getElementsByTagName('head')[0];
11 | const style = document.createElement('style');
12 | style.setAttribute('data-css-file', name);
13 |
14 | style.type = 'text/css';
15 | style.appendChild(document.createTextNode(css));
16 |
17 | head.appendChild(style);
18 | }
19 |
20 | export { expectNoViolations } from '../../form-js-viewer/test/helper';
21 |
--------------------------------------------------------------------------------
/packages/form-js-carbon-styles/test/spec/theme.scss:
--------------------------------------------------------------------------------
1 | @use '@carbon/react' as * with (
2 | $font-path: '@ibm/plex'
3 | );
4 |
5 | @use '@carbon/react/scss/themes';
6 | @use '@carbon/react/scss/theme';
7 |
8 | [data-carbon-theme='g10'] {
9 | @include theme.theme(themes.$g10);
10 | }
11 |
12 | [data-carbon-theme='g100'] {
13 | @include theme.theme(themes.$g100);
14 | }
15 |
--------------------------------------------------------------------------------
/packages/form-js-carbon-styles/test/test.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: sans-serif;
3 | font-size: 16px;
4 | margin: 1rem;
5 | }
6 |
7 | h1 {
8 | margin: 0 0 1rem 0;
9 | }
10 |
11 | .form-container {
12 | padding: 20px;
13 | }
14 |
15 | .test-container {
16 | height: 100% !important;
17 | }
18 |
19 | .test-content-container {
20 | overflow: auto !important;
21 | }
22 |
--------------------------------------------------------------------------------
/packages/form-js-carbon-styles/test/testBundle.js:
--------------------------------------------------------------------------------
1 | const allTests = require.context('.', true, /.spec\.js$/);
2 |
3 | allTests.keys().forEach(allTests);
4 |
--------------------------------------------------------------------------------
/packages/form-js-editor/assets/index.scss:
--------------------------------------------------------------------------------
1 | @use 'form-js-editor-base.css';
2 | @use '@bpmn-io/draggle/dist/draggle.css';
3 | @use '@bpmn-io/properties-panel/dist/assets/properties-panel.css';
4 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/core/Debounce.js:
--------------------------------------------------------------------------------
1 | import { debounce } from 'min-dash';
2 |
3 | /**
4 | * A factory to create a configurable debouncer.
5 | *
6 | * @param {number|boolean} [config=true]
7 | */
8 | export function DebounceFactory(config = true) {
9 | const timeout = typeof config === 'number' ? config : config ? 300 : 0;
10 |
11 | if (timeout) {
12 | return (fn) => debounce(fn, timeout);
13 | } else {
14 | return (fn) => fn;
15 | }
16 | }
17 |
18 | DebounceFactory.$inject = ['config.debounce'];
19 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/core/EventBus.js:
--------------------------------------------------------------------------------
1 | export { default as EventBus } from 'diagram-js/lib/core/EventBus';
2 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/core/FormLayouter.js:
--------------------------------------------------------------------------------
1 | export { FormLayouter } from '@bpmn-io/form-js-viewer';
2 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/core/index.js:
--------------------------------------------------------------------------------
1 | import { FieldFactory, Importer, PathRegistry } from '@bpmn-io/form-js-viewer';
2 |
3 | import { EventBus } from './EventBus';
4 | import { DebounceFactory } from './Debounce';
5 | import { FormFieldRegistry } from './FormFieldRegistry';
6 | import { FormLayouter } from './FormLayouter';
7 | import { FormLayoutValidator } from './FormLayoutValidator';
8 |
9 | import { RenderModule } from '../render';
10 |
11 | export const CoreModule = {
12 | __depends__: [RenderModule],
13 | debounce: ['factory', DebounceFactory],
14 | eventBus: ['type', EventBus],
15 | importer: ['type', Importer],
16 | formFieldRegistry: ['type', FormFieldRegistry],
17 | pathRegistry: ['type', PathRegistry],
18 | formLayouter: ['type', FormLayouter],
19 | formLayoutValidator: ['type', FormLayoutValidator],
20 | fieldFactory: ['type', FieldFactory],
21 | };
22 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/dragging/index.js:
--------------------------------------------------------------------------------
1 | import { Dragging } from './Dragging';
2 |
3 | export const DraggingModule = {
4 | __init__: ['dragging'],
5 | dragging: ['type', Dragging],
6 | };
7 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/editor-actions/index.js:
--------------------------------------------------------------------------------
1 | import BaseEditorActionsModule from 'diagram-js/lib/features/editor-actions';
2 |
3 | import { FormEditorActions } from './FormEditorActions';
4 |
5 | export const EditorActionsModule = {
6 | __depends__: [BaseEditorActionsModule],
7 | editorActions: ['type', FormEditorActions],
8 | };
9 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/expression-language/EditorTemplating.js:
--------------------------------------------------------------------------------
1 | import { isString } from 'min-dash';
2 |
3 | export class EditorTemplating {
4 | // same rules as viewer templating
5 | isTemplate(value) {
6 | return isString(value) && (value.startsWith('=') || /{{/.test(value));
7 | }
8 |
9 | // return the template raw, as we usually just want to display that
10 | evaluate(template) {
11 | return template;
12 | }
13 | }
14 |
15 | EditorTemplating.$inject = [];
16 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/expression-language/index.js:
--------------------------------------------------------------------------------
1 | import { FeelExpressionLanguage } from '@bpmn-io/form-js-viewer';
2 | import { EditorTemplating } from './EditorTemplating';
3 |
4 | export const EditorExpressionLanguageModule = {
5 | __init__: ['expressionLanguage', 'templating'],
6 | expressionLanguage: ['type', FeelExpressionLanguage],
7 | templating: ['type', EditorTemplating],
8 | };
9 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/keyboard/index.js:
--------------------------------------------------------------------------------
1 | import KeyboardModule from 'diagram-js/lib/features/keyboard';
2 |
3 | import { FormEditorKeyboardBindings } from './FormEditorKeyboardBindings';
4 |
5 | export const FormEditorKeyboardModule = {
6 | __depends__: [KeyboardModule],
7 | __init__: ['keyboardBindings'],
8 | keyboardBindings: ['type', FormEditorKeyboardBindings],
9 | };
10 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/modeling/behavior/IdBehavior.js:
--------------------------------------------------------------------------------
1 | import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
2 |
3 | export class IdBehavior extends CommandInterceptor {
4 | constructor(eventBus, modeling) {
5 | super(eventBus);
6 |
7 | this.preExecute(
8 | 'formField.remove',
9 | function (context) {
10 | const { formField } = context;
11 |
12 | const { id } = formField;
13 |
14 | modeling.unclaimId(formField, id);
15 | },
16 | true,
17 | );
18 |
19 | this.preExecute(
20 | 'formField.edit',
21 | function (context) {
22 | const { formField, properties } = context;
23 |
24 | if ('id' in properties) {
25 | modeling.unclaimId(formField, formField.id);
26 |
27 | modeling.claimId(formField, properties.id);
28 | }
29 | },
30 | true,
31 | );
32 | }
33 | }
34 |
35 | IdBehavior.$inject = ['eventBus', 'modeling'];
36 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/modeling/behavior/TableDataSourceBehavior.js:
--------------------------------------------------------------------------------
1 | import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
2 |
3 | import { get } from 'min-dash';
4 |
5 | export class TableDataSourceBehavior extends CommandInterceptor {
6 | constructor(eventBus) {
7 | super(eventBus);
8 |
9 | this.preExecute(
10 | 'formField.add',
11 | function (context) {
12 | const { formField } = context;
13 |
14 | if (get(formField, ['type']) !== 'table') {
15 | return;
16 | }
17 |
18 | context.formField = {
19 | ...formField,
20 | dataSource: `=${formField.id}`,
21 | };
22 | },
23 | true,
24 | );
25 | }
26 | }
27 |
28 | TableDataSourceBehavior.$inject = ['eventBus'];
29 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/modeling/behavior/ValidateBehavior.js:
--------------------------------------------------------------------------------
1 | import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
2 |
3 | export class ValidateBehavior extends CommandInterceptor {
4 | constructor(eventBus) {
5 | super(eventBus);
6 |
7 | /**
8 | * Remove custom validation if is about to be added.
9 | */
10 | this.preExecute(
11 | 'formField.edit',
12 | function (context) {
13 | const { properties } = context;
14 |
15 | const { validate = {} } = properties;
16 |
17 | if (validate.validationType) {
18 | const newValidate = {
19 | ...validate,
20 | };
21 |
22 | delete newValidate.minLength;
23 | delete newValidate.maxLength;
24 | delete newValidate.pattern;
25 |
26 | properties['validate'] = newValidate;
27 | }
28 | },
29 | true,
30 | );
31 | }
32 | }
33 |
34 | ValidateBehavior.$inject = ['eventBus'];
35 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/modeling/cmd/UpdateIdClaimHandler.js:
--------------------------------------------------------------------------------
1 | export class UpdateIdClaimHandler {
2 | /**
3 | * @constructor
4 | * @param { import('../../../core/FormFieldRegistry').FormFieldRegistry } formFieldRegistry
5 | */
6 | constructor(formFieldRegistry) {
7 | this._formFieldRegistry = formFieldRegistry;
8 | }
9 |
10 | execute(context) {
11 | const { claiming, formField, id } = context;
12 |
13 | if (claiming) {
14 | this._formFieldRegistry._ids.claim(id, formField);
15 | } else {
16 | this._formFieldRegistry._ids.unclaim(id);
17 | }
18 | }
19 |
20 | revert(context) {
21 | const { claiming, formField, id } = context;
22 |
23 | if (claiming) {
24 | this._formFieldRegistry._ids.unclaim(id);
25 | } else {
26 | this._formFieldRegistry._ids.claim(id, formField);
27 | }
28 | }
29 | }
30 |
31 | UpdateIdClaimHandler.$inject = ['formFieldRegistry'];
32 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/modeling/index.js:
--------------------------------------------------------------------------------
1 | import commandModule from 'diagram-js/lib/command';
2 |
3 | import { BehaviorModule } from './behavior';
4 | import { FormLayoutUpdater } from './FormLayoutUpdater';
5 | import { Modeling } from './Modeling';
6 |
7 | export const ModelingModule = {
8 | __depends__: [BehaviorModule, commandModule],
9 | __init__: ['formLayoutUpdater', 'modeling'],
10 | formLayoutUpdater: ['type', FormLayoutUpdater],
11 | modeling: ['type', Modeling],
12 | };
13 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/palette/PaletteRenderer.js:
--------------------------------------------------------------------------------
1 | import { SectionModuleBase } from '../SectionModuleBase';
2 |
3 | export class PaletteRenderer extends SectionModuleBase {
4 | constructor(eventBus) {
5 | super(eventBus, 'palette');
6 | }
7 | }
8 |
9 | PaletteRenderer.$inject = ['eventBus'];
10 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/palette/index.js:
--------------------------------------------------------------------------------
1 | import { PaletteRenderer } from './PaletteRenderer';
2 |
3 | export const PaletteModule = {
4 | __init__: ['palette'],
5 | palette: ['type', PaletteRenderer],
6 | };
7 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/PropertiesPanelModule.js:
--------------------------------------------------------------------------------
1 | import { SectionModuleBase } from '../SectionModuleBase';
2 |
3 | export class PropertiesPanelModule extends SectionModuleBase {
4 | constructor(eventBus) {
5 | super(eventBus, 'propertiesPanel');
6 | }
7 | }
8 |
9 | PropertiesPanelModule.$inject = ['eventBus'];
10 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/PropertiesPanelPlaceholderProvider.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Provide placeholders for empty and multiple state.
3 | */
4 | export const PropertiesPanelPlaceholderProvider = {
5 | getEmpty: () => {
6 | return {
7 | text: 'Select a form field to edit its properties.',
8 | };
9 | },
10 |
11 | getMultiple: () => {
12 | return {
13 | text: 'Multiple form fields are selected. Select a single form field to edit its properties.',
14 | };
15 | },
16 | };
17 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/components/index.js:
--------------------------------------------------------------------------------
1 | export { AutoFocusSelectEntry } from './AutoFocusSelect';
2 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/context/FormPropertiesPanelContext.js:
--------------------------------------------------------------------------------
1 | import { createContext } from 'preact';
2 |
3 | /**
4 | * @param {string} type
5 | * @param {boolean} [strict]
6 | *
7 | * @returns {any}
8 | */
9 | function getService(type, strict) {}
10 |
11 | export const FormPropertiesPanelContext = createContext({
12 | getService,
13 | });
14 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/context/index.js:
--------------------------------------------------------------------------------
1 | export { FormPropertiesPanelContext } from './FormPropertiesPanelContext';
2 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/entries/GroupAppearanceEntry.js:
--------------------------------------------------------------------------------
1 | import { simpleBoolEntryFactory } from './factories';
2 |
3 | export function GroupAppearanceEntry(props) {
4 | const { field } = props;
5 |
6 | const { type } = field;
7 |
8 | if (!['group', 'dynamiclist'].includes(type)) {
9 | return [];
10 | }
11 |
12 | const entries = [
13 | simpleBoolEntryFactory({
14 | id: 'showOutline',
15 | path: ['showOutline'],
16 | label: 'Show outline',
17 | props,
18 | }),
19 | ];
20 |
21 | return entries;
22 | }
23 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/entries/IFrameHeightEntry.js:
--------------------------------------------------------------------------------
1 | import { HeightEntry } from './HeightEntry';
2 |
3 | export function IFrameHeightEntry(props) {
4 | return [
5 | ...HeightEntry({
6 | ...props,
7 | description: 'Height of the container in pixels.',
8 | isDefaultVisible: (field) => field.type === 'iframe',
9 | }),
10 | ];
11 | }
12 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/entries/LayouterAppearanceEntry.js:
--------------------------------------------------------------------------------
1 | import { simpleSelectEntryFactory } from './factories';
2 |
3 | export function LayouterAppearanceEntry(props) {
4 | const { field } = props;
5 |
6 | if (!['group', 'dynamiclist'].includes(field.type)) {
7 | return [];
8 | }
9 |
10 | const entries = [
11 | simpleSelectEntryFactory({
12 | id: 'verticalAlignment',
13 | path: ['verticalAlignment'],
14 | label: 'Vertical alignment',
15 | optionsArray: [
16 | { value: 'start', label: 'Top' },
17 | { value: 'center', label: 'Center' },
18 | { value: 'end', label: 'Bottom' },
19 | ],
20 | props,
21 | }),
22 | ];
23 |
24 | return entries;
25 | }
26 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/entries/SelectEntries.js:
--------------------------------------------------------------------------------
1 | import { simpleBoolEntryFactory } from './factories';
2 |
3 | export function SelectEntries(props) {
4 | const entries = [
5 | simpleBoolEntryFactory({
6 | id: 'searchable',
7 | path: ['searchable'],
8 | label: 'Searchable',
9 | props,
10 | isDefaultVisible: (field) => field.type === 'select',
11 | }),
12 | ];
13 |
14 | return entries;
15 | }
16 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/entries/factories/index.js:
--------------------------------------------------------------------------------
1 | export { simpleStringEntryFactory } from './simpleStringEntryFactory';
2 | export { simpleBoolEntryFactory } from './simpleBoolEntryFactory';
3 | export { zeroPositiveIntegerEntryFactory } from './zeroPositiveIntegerEntryFactory';
4 | export { simpleSelectEntryFactory } from './simpleSelectEntryFactory';
5 | export { simpleRangeIntegerEntryFactory } from './simpleRangeIntegerEntryFactory';
6 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/groups/AppearanceGroup.js:
--------------------------------------------------------------------------------
1 | import { AdornerEntry, GroupAppearanceEntry, LayouterAppearanceEntry, MaxHeightEntry } from '../entries';
2 |
3 | export function AppearanceGroup(field, editField, getService) {
4 | const entries = [
5 | ...AdornerEntry({ field, editField }),
6 | ...GroupAppearanceEntry({ field, editField }),
7 | ...LayouterAppearanceEntry({ field, editField }),
8 | ...MaxHeightEntry({ field, editField }),
9 | ];
10 |
11 | if (!entries.length) {
12 | return null;
13 | }
14 |
15 | return {
16 | id: 'appearance',
17 | label: 'Appearance',
18 | entries,
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/groups/ConditionGroup.js:
--------------------------------------------------------------------------------
1 | import { ConditionEntry } from '../entries';
2 |
3 | export function ConditionGroup(field, editField) {
4 | const { type } = field;
5 |
6 | if (type === 'default') {
7 | return null;
8 | }
9 |
10 | const entries = [...ConditionEntry({ field, editField })];
11 |
12 | return {
13 | id: 'condition',
14 | label: 'Condition',
15 | entries,
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/groups/ConstraintsGroup.js:
--------------------------------------------------------------------------------
1 | import { DateTimeConstraintsEntry } from '../entries';
2 |
3 | export function ConstraintsGroup(field, editField) {
4 | const entries = [...DateTimeConstraintsEntry({ field, editField })];
5 |
6 | if (!entries.length) {
7 | return null;
8 | }
9 |
10 | return {
11 | id: 'constraints',
12 | label: 'Constraints',
13 | entries,
14 | };
15 | }
16 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/groups/LayoutGroup.js:
--------------------------------------------------------------------------------
1 | import { ColumnsEntry } from '../entries';
2 |
3 | export function LayoutGroup(field, editField) {
4 | const { type } = field;
5 |
6 | if (type === 'default') {
7 | return null;
8 | }
9 |
10 | const entries = [...ColumnsEntry({ field, editField })];
11 |
12 | if (entries.length === 0) {
13 | return null;
14 | }
15 |
16 | return {
17 | id: 'layout',
18 | label: 'Layout',
19 | entries,
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/groups/SerializationGroup.js:
--------------------------------------------------------------------------------
1 | import { NumberSerializationEntry, DateTimeFormatEntry } from '../entries';
2 |
3 | export function SerializationGroup(field, editField) {
4 | const entries = [...NumberSerializationEntry({ field, editField }), ...DateTimeFormatEntry({ field, editField })];
5 |
6 | if (!entries.length) {
7 | return null;
8 | }
9 |
10 | return {
11 | id: 'serialization',
12 | label: 'Serialization',
13 | entries,
14 | };
15 | }
16 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/groups/index.js:
--------------------------------------------------------------------------------
1 | export { GeneralGroup } from './GeneralGroup';
2 | export { SerializationGroup } from './SerializationGroup';
3 | export { ConstraintsGroup } from './ConstraintsGroup';
4 | export { ValidationGroup } from './ValidationGroup';
5 | export { OptionsGroups } from './OptionsGroups';
6 | export { CustomPropertiesGroup } from './CustomPropertiesGroup';
7 | export { AppearanceGroup } from './AppearanceGroup';
8 | export { LayoutGroup } from './LayoutGroup';
9 | export { SecurityAttributesGroup } from './SecurityAttributesGroup';
10 | export { ConditionGroup } from './ConditionGroup';
11 | export { TableHeaderGroups } from './TableHeaderGroups';
12 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/hooks/index.js:
--------------------------------------------------------------------------------
1 | export { useVariables } from './useVariables';
2 | export { useService } from './usePropertiesPanelService';
3 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/hooks/usePropertiesPanelService.js:
--------------------------------------------------------------------------------
1 | import { useContext } from 'preact/hooks';
2 |
3 | import { FormPropertiesPanelContext } from '../context';
4 |
5 | export function useService(type, strict) {
6 | const { getService } = useContext(FormPropertiesPanelContext);
7 |
8 | return getService(type, strict);
9 | }
10 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/hooks/useVariables.js:
--------------------------------------------------------------------------------
1 | import { getSchemaVariables } from '@bpmn-io/form-js-viewer';
2 | import { useService } from './usePropertiesPanelService';
3 |
4 | /**
5 | * Retrieve list of variables from the form schema.
6 | *
7 | * @returns { string[] } list of variables used in form schema
8 | */
9 | export function useVariables() {
10 | const form = useService('formEditor');
11 | const schema = form.getSchema();
12 |
13 | return getSchemaVariables(schema);
14 | }
15 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/icons/index.js:
--------------------------------------------------------------------------------
1 | import CreateIcon from './pp-create.svg';
2 | import ListArrowIcon from './pp-list-arrow.svg';
3 | import ListDeleteIcon from './pp-list-delete.svg';
4 | import SectionArrowIcon from './pp-section-arrow.svg';
5 |
6 | export { CreateIcon, ListArrowIcon, ListDeleteIcon, SectionArrowIcon };
7 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/icons/pp-checkbox-checked.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/icons/pp-checkbox.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/icons/pp-create.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/icons/pp-fullpanel-off.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/icons/pp-fullpanel.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/icons/pp-list-arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/icons/pp-list-delete.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/icons/pp-section-arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/properties-panel/index.js:
--------------------------------------------------------------------------------
1 | import { PropertiesPanelRenderer } from './PropertiesPanelRenderer';
2 | import { PropertiesProvider } from './PropertiesProvider';
3 |
4 | import { FeelPopupModule } from '@bpmn-io/properties-panel';
5 |
6 | export const PropertiesPanelModule = {
7 | __depends__: [FeelPopupModule],
8 | __init__: ['propertiesPanel', 'propertiesProvider'],
9 | propertiesPanel: ['type', PropertiesPanelRenderer],
10 | propertiesProvider: ['type', PropertiesProvider],
11 | };
12 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/render-injection/components/InjectedRendersRoot.js:
--------------------------------------------------------------------------------
1 | import { Fragment } from 'preact';
2 | import { useMemo } from 'preact/hooks';
3 | import { useService } from '../../../render/hooks';
4 | import { Fill, Slot } from '../slot-fill';
5 |
6 | /**
7 | * A functional component that holds all injected renderers.
8 | * @returns {any} The rendered component.
9 | */
10 | export const InjectedRendersRoot = () => {
11 | const renderInjector = useService('renderInjector');
12 |
13 | const injectedRenderers = renderInjector.fetchRenderers();
14 |
15 | const injectedProps = useMemo(
16 | () => ({
17 | useService,
18 | components: {
19 | Fill,
20 | Slot,
21 | },
22 | }),
23 | [],
24 | );
25 |
26 | return (
27 |
28 | {injectedRenderers.map(({ Renderer }, index) => (
29 |
30 | ))}
31 |
32 | );
33 | };
34 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/render-injection/index.js:
--------------------------------------------------------------------------------
1 | import { RenderInjector } from './RenderInjector';
2 |
3 | export const RenderInjectionModule = {
4 | __init__: ['renderInjector'],
5 | renderInjector: ['type', RenderInjector],
6 | };
7 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/render-injection/slot-fill/Fill.js:
--------------------------------------------------------------------------------
1 | import { FillContext } from './FillContext';
2 | import { useContext, useEffect, useRef } from 'preact/compat';
3 |
4 | export const Fill = (props) => {
5 | const uid = useRef(Symbol('fill_uid'));
6 | const fillContext = useContext(FillContext);
7 |
8 | useEffect(() => {
9 | if (!fillContext) {
10 | return;
11 | }
12 |
13 | fillContext.addFill({ id: uid, ...props });
14 | return () => {
15 | fillContext.removeFill(uid);
16 | };
17 | }, [fillContext, props]);
18 |
19 | return null;
20 | };
21 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/render-injection/slot-fill/FillContext.js:
--------------------------------------------------------------------------------
1 | import { createContext } from 'preact';
2 |
3 | export const FillContext = createContext({
4 | addFill(uid, props) {
5 | throw new Error('FillContext.addFill() uninitialized');
6 | },
7 | removeFill(uid) {
8 | throw new Error('FillContext.addFill() uninitialized');
9 | },
10 | });
11 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/render-injection/slot-fill/SlotContext.js:
--------------------------------------------------------------------------------
1 | import { createContext } from 'preact';
2 |
3 | export const SlotContext = createContext({ fills: [] });
4 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/render-injection/slot-fill/index.js:
--------------------------------------------------------------------------------
1 | export { Fill } from './Fill';
2 | export { Slot } from './Slot';
3 | export { SlotFillRoot } from './SlotFillRoot';
4 | export { SlotContext } from './SlotContext';
5 | export { FillContext } from './FillContext';
6 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/repeat-render/index.js:
--------------------------------------------------------------------------------
1 | import { EditorRepeatRenderManager } from './EditorRepeatRenderManager';
2 |
3 | export const RepeatRenderModule = {
4 | __init__: ['repeatRenderManager'],
5 | repeatRenderManager: ['type', EditorRepeatRenderManager],
6 | };
7 |
8 | export { EditorRepeatRenderManager };
9 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/selection/Selection.js:
--------------------------------------------------------------------------------
1 | export class Selection {
2 | constructor(eventBus) {
3 | this._eventBus = eventBus;
4 | this._selection = null;
5 | }
6 |
7 | get() {
8 | return this._selection;
9 | }
10 |
11 | set(selection) {
12 | if (this._selection === selection) {
13 | return;
14 | }
15 |
16 | this._selection = selection;
17 |
18 | this._eventBus.fire('selection.changed', {
19 | selection: this._selection,
20 | });
21 | }
22 |
23 | toggle(selection) {
24 | const newSelection = this._selection === selection ? null : selection;
25 |
26 | this.set(newSelection);
27 | }
28 |
29 | clear() {
30 | this.set(null);
31 | }
32 |
33 | isSelected(formField) {
34 | return this._selection === formField;
35 | }
36 | }
37 |
38 | Selection.$inject = ['eventBus'];
39 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/features/selection/index.js:
--------------------------------------------------------------------------------
1 | import { Selection } from './Selection';
2 | import { SelectionBehavior } from './SelectionBehavior';
3 |
4 | export const SelectionModule = {
5 | __init__: ['selection', 'selectionBehavior'],
6 | selection: ['type', Selection],
7 | selectionBehavior: ['type', SelectionBehavior],
8 | };
9 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/index.js:
--------------------------------------------------------------------------------
1 | import { FormEditor } from './FormEditor';
2 |
3 | import { schemaVersion } from '@bpmn-io/form-js-viewer';
4 |
5 | export { FormEditor, schemaVersion };
6 |
7 | export { useDebounce, usePrevious, useService } from './render/hooks';
8 |
9 | export { useService as usePropertiesPanelService, useVariables } from './features/properties-panel/hooks';
10 |
11 | /**
12 | * @typedef { import('./types').CreateFormEditorOptions } CreateFormEditorOptions
13 | */
14 |
15 | /**
16 | * Create a form editor.
17 | *
18 | * @param {CreateFormEditorOptions} options
19 | *
20 | * @return {Promise}
21 | */
22 | export function createFormEditor(options) {
23 | const { schema, ...rest } = options;
24 |
25 | const formEditor = new FormEditor(rest);
26 |
27 | return formEditor.importSchema(schema).then(() => {
28 | return formEditor;
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/render/EditorFormFields.js:
--------------------------------------------------------------------------------
1 | import { FormFields } from '@bpmn-io/form-js-viewer';
2 | import { editorFormFields } from './components/editor-form-fields/';
3 |
4 | export class EditorFormFields extends FormFields {
5 | constructor() {
6 | super();
7 | editorFormFields.forEach((formField) => {
8 | this.register(formField.config.type, formField);
9 | });
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/render/components/FieldDragPreview.js:
--------------------------------------------------------------------------------
1 | import classNames from 'classnames';
2 |
3 | export function FieldDragPreview(props) {
4 | const { class: className, Icon, label } = props;
5 |
6 | return (
7 |
8 |
9 | {label}
10 |
11 | );
12 | }
13 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/render/components/editor-form-fields/EditorDocumentPreview.js:
--------------------------------------------------------------------------------
1 | import { iconsByType, DocumentPreview, Label } from '@bpmn-io/form-js-viewer';
2 |
3 | import { editorFormFieldClasses } from '../Util';
4 |
5 | export function EditorDocumentPreview(props) {
6 | const { field, domId } = props;
7 |
8 | const { label } = field;
9 |
10 | const Icon = iconsByType(field.type);
11 |
12 | return (
13 |
22 | );
23 | }
24 |
25 | EditorDocumentPreview.config = DocumentPreview.config;
26 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/render/components/editor-form-fields/EditorIFrame.js:
--------------------------------------------------------------------------------
1 | import { iconsByType, IFrame, Label } from '@bpmn-io/form-js-viewer';
2 |
3 | import { editorFormFieldClasses } from '../Util';
4 |
5 | export function EditorIFrame(props) {
6 | const { field, domId } = props;
7 |
8 | const { label } = field;
9 |
10 | const Icon = iconsByType(field.type);
11 |
12 | return (
13 |
22 | );
23 | }
24 |
25 | EditorIFrame.config = IFrame.config;
26 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/render/components/editor-form-fields/index.js:
--------------------------------------------------------------------------------
1 | import { EditorIFrame } from './EditorIFrame';
2 | import { EditorText } from './EditorText';
3 | import { EditorHtml } from './EditorHtml';
4 | import { EditorTable } from './EditorTable';
5 | import { EditorExpressionField } from './EditorExpressionField';
6 | import { EditorDocumentPreview } from './EditorDocumentPreview';
7 |
8 | export const editorFormFields = [
9 | EditorIFrame,
10 | EditorText,
11 | EditorHtml,
12 | EditorTable,
13 | EditorExpressionField,
14 | EditorDocumentPreview,
15 | ];
16 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/render/components/icons/Close.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/render/components/icons/Delete.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/render/components/icons/Draggable.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/render/components/icons/Repeat.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/render/components/icons/index.js:
--------------------------------------------------------------------------------
1 | import CloseIcon from './Close.svg';
2 | import DeleteIcon from './Delete.svg';
3 | import DraggableIcon from './Draggable.svg';
4 | import SearchIcon from './Search.svg';
5 | import EmptyFormIcon from './EmptyForm.svg';
6 |
7 | export { iconsByType } from '@bpmn-io/form-js-viewer';
8 |
9 | export { CloseIcon, DeleteIcon, DraggableIcon, SearchIcon, EmptyFormIcon };
10 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/render/context/DragAndDropContext.js:
--------------------------------------------------------------------------------
1 | import { createContext } from 'preact';
2 |
3 | export const DragAndDropContext = createContext({
4 | drake: null,
5 | });
6 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/render/context/FormEditorContext.js:
--------------------------------------------------------------------------------
1 | import { createContext } from 'preact';
2 |
3 | /**
4 | * @param {string} type
5 | * @param {boolean} [strict]
6 | *
7 | * @returns {any}
8 | */
9 | function getService(type, strict) {}
10 |
11 | export const FormEditorContext = createContext({
12 | getService,
13 | });
14 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/render/context/index.js:
--------------------------------------------------------------------------------
1 | export { DragAndDropContext } from './DragAndDropContext';
2 | export { FormEditorContext } from './FormEditorContext';
3 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/render/hooks/index.js:
--------------------------------------------------------------------------------
1 | export { useService } from './useService';
2 | export { usePrevious } from './usePrevious';
3 | export { useDebounce } from './useDebounce';
4 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/render/hooks/useDebounce.js:
--------------------------------------------------------------------------------
1 | import { useMemo, useEffect } from 'preact/hooks';
2 |
3 | import { useService } from './useService';
4 |
5 | /**
6 | * @param {Function} fn - function to debounce
7 | */
8 | export function useDebounce(fn) {
9 | const debounce = useService('debounce');
10 |
11 | const callback = useMemo(() => {
12 | return debounce(fn);
13 | }, [debounce, fn]);
14 |
15 | // cleanup async side-effect if callback #flush is provided.
16 | useEffect(() => {
17 | return () => {
18 | typeof callback.flush === 'function' && callback.flush();
19 | };
20 | }, [callback]);
21 |
22 | return callback;
23 | }
24 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/render/hooks/usePrevious.js:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from 'preact/hooks';
2 |
3 | export function usePrevious(value, defaultValue = null) {
4 | const ref = useRef(defaultValue);
5 |
6 | useEffect(() => (ref.current = value), [value]);
7 |
8 | return ref.current;
9 | }
10 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/render/hooks/useService.js:
--------------------------------------------------------------------------------
1 | import { useContext } from 'preact/hooks';
2 |
3 | import { FormEditorContext } from '../context';
4 |
5 | export function useService(type, strict) {
6 | const { getService } = useContext(FormEditorContext);
7 |
8 | return getService(type, strict);
9 | }
10 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/render/index.js:
--------------------------------------------------------------------------------
1 | import { EditorFormFields } from './EditorFormFields';
2 | import { Renderer } from './Renderer';
3 |
4 | export const RenderModule = {
5 | __init__: ['formFields', 'renderer'],
6 | formFields: ['type', EditorFormFields],
7 | renderer: ['type', Renderer],
8 | };
9 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/render/util/Cursor.js:
--------------------------------------------------------------------------------
1 | import { classes as domClasses } from 'min-dom';
2 |
3 | const CURSOR_CLS_PATTERN = /^fjs-cursor-.*$/;
4 |
5 | export function set(mode) {
6 | const classes = domClasses(document.body);
7 |
8 | classes.removeMatching(CURSOR_CLS_PATTERN);
9 |
10 | if (mode) {
11 | classes.add('fjs-cursor-' + mode);
12 | }
13 | }
14 |
15 | export function unset() {
16 | set(null);
17 | }
18 |
19 | export function has(mode) {
20 | const classes = domClasses(document.body);
21 |
22 | return classes.has('fjs-cursor-' + mode);
23 | }
24 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/types.d.ts:
--------------------------------------------------------------------------------
1 | import { Injector } from 'didi';
2 |
3 | export type Module = any;
4 | export type Schema = any;
5 |
6 | export interface FormEditorProperties {
7 | [x: string]: any;
8 | }
9 |
10 | export interface FormEditorOptions {
11 | additionalModules?: Module[];
12 | container?: Element | null | string;
13 | exporter?: {
14 | name: string;
15 | version: string;
16 | };
17 | injector?: Injector;
18 | modules?: Module[];
19 | properties?: FormEditorProperties;
20 | [x: string]: any;
21 | }
22 |
23 | export interface CreateFormEditorOptions extends FormEditorOptions {
24 | schema?: Schema;
25 | }
26 |
27 | export { Injector };
28 |
--------------------------------------------------------------------------------
/packages/form-js-editor/src/types/custom.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.svg' {
2 | const content: any;
3 | export default content;
4 | }
5 |
--------------------------------------------------------------------------------
/packages/form-js-editor/test/TestHelper.js:
--------------------------------------------------------------------------------
1 | import 'preact/debug';
2 |
3 | import { insertCSS } from './helper';
4 |
5 | // @ts-ignore-next-line
6 | import formCSS from '@bpmn-io/form-js-viewer/dist/assets/form-js.css';
7 |
8 | // @ts-ignore-next-line
9 | import formEditorCSS from '../dist/assets/form-js-editor.css';
10 |
11 | // @ts-ignore-next-line
12 | import testCSS from './test.css';
13 |
14 | export { expectNoViolations } from '../../form-js-viewer/test/helper';
15 |
16 | export { insertTheme } from '../../form-js-viewer/test/TestHelper';
17 |
18 | export function isSingleStart(topic) {
19 | // @ts-ignore-next-line
20 | return window.__env__ && window.__env__.SINGLE_START === topic;
21 | }
22 |
23 | export function insertStyles() {
24 | insertCSS('form-js.css', formCSS);
25 | insertCSS('form-js-editor.css', formEditorCSS);
26 | insertCSS('test-editor.css', testCSS);
27 | }
28 |
29 | insertStyles();
30 |
31 | export { createFormContainer } from '../../form-js-viewer/test/TestHelper';
32 |
33 | export * from './helper';
34 |
--------------------------------------------------------------------------------
/packages/form-js-editor/test/coverageBundle.js:
--------------------------------------------------------------------------------
1 | const allTests = require.context('.', true, /.spec\.js$/);
2 |
3 | allTests.keys().forEach(allTests);
4 |
5 | const allSources = require.context('../src', true, /.*\.js$/);
6 |
7 | allSources.keys().forEach(allSources);
8 |
--------------------------------------------------------------------------------
/packages/form-js-editor/test/spec/features/properties-panel/helper/mocks/index.js:
--------------------------------------------------------------------------------
1 | export * from '../../../../../helper/mocks';
2 |
--------------------------------------------------------------------------------
/packages/form-js-editor/test/spec/form-group.json:
--------------------------------------------------------------------------------
1 | {
2 | "components": [
3 | {
4 | "id": "Textfield_1",
5 | "key": "invoiceNumber",
6 | "label": "Invoice Number",
7 | "type": "textfield",
8 | "layout": {
9 | "row": "Row_1",
10 | "columns": 16
11 | }
12 | },
13 | {
14 | "components": [
15 | {
16 | "label": "Text field",
17 | "type": "textfield",
18 | "layout": {
19 | "row": "Row_3",
20 | "columns": null
21 | },
22 | "id": "Textfield_2",
23 | "key": "textfield_2"
24 | }
25 | ],
26 | "showOutline": true,
27 | "label": "Group",
28 | "type": "group",
29 | "layout": {
30 | "row": "Row_2",
31 | "columns": null
32 | },
33 | "id": "Group_1"
34 | }
35 | ],
36 | "type": "default",
37 | "id": "Form_1",
38 | "schemaVersion": 11
39 | }
40 |
--------------------------------------------------------------------------------
/packages/form-js-editor/test/spec/form-table.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../../../form-json-schema/resources/schema.json",
3 | "id": "Form_1",
4 | "type": "default",
5 | "components": [
6 | {
7 | "label": "static-headers-table",
8 | "type": "table",
9 | "rowCount": 10,
10 | "columns": [
11 | {
12 | "label": "ID",
13 | "key": "id"
14 | },
15 | {
16 | "label": "Name",
17 | "key": "name"
18 | },
19 | {
20 | "label": "Date",
21 | "key": "date"
22 | }
23 | ],
24 | "id": "Field_0k6resc1",
25 | "dataSource": "Field_0k6resc1"
26 | },
27 | {
28 | "label": "dynamic-headers-table",
29 | "type": "table",
30 | "rowCount": 10,
31 | "columnsExpression": "=tableHeaders",
32 | "id": "Field_0k6resc2",
33 | "dataSource": "Field_0k6resc2"
34 | }
35 | ]
36 | }
37 |
--------------------------------------------------------------------------------
/packages/form-js-editor/test/spec/other.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../../../form-json-schema/resources/schema.json",
3 | "components": [
4 | {
5 | "type": "text",
6 | "text": "# File an Invoice\n\nAdd your invoice details below."
7 | },
8 | {
9 | "key": "creditor",
10 | "label": "Creditor",
11 | "type": "textfield",
12 | "validate": {
13 | "required": true
14 | }
15 | },
16 | {
17 | "description": "An invoice number in the format: C-123.",
18 | "key": "invoiceNumber",
19 | "label": "Invoice Number",
20 | "type": "textfield",
21 | "validate": {
22 | "pattern": "^C-[0-9]+$"
23 | }
24 | },
25 | {
26 | "label": "Submit",
27 | "type": "button"
28 | }
29 | ],
30 | "type": "default"
31 | }
32 |
--------------------------------------------------------------------------------
/packages/form-js-editor/test/spec/redundantValues.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../../../form-json-schema/resources/schema.json",
3 | "components": [
4 | {
5 | "key": "redundantValues",
6 | "label": "Redundant Values",
7 | "type": "radio",
8 | "values": [
9 | {
10 | "label": "Value 2",
11 | "value": "value2"
12 | },
13 | {
14 | "label": "Value 3",
15 | "value": "value3"
16 | }
17 | ],
18 | "properties": {
19 | "key2": "value"
20 | }
21 | }
22 | ],
23 | "type": "default"
24 | }
25 |
--------------------------------------------------------------------------------
/packages/form-js-editor/test/test.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:ital,wght@0,400;0,500;0,600;1,400&display=swap');
2 |
3 | html,
4 | body,
5 | .fjs-editor {
6 | height: 100%;
7 | }
8 |
9 | body {
10 | --font-family: 'IBM Plex Sans', sans-serif;
11 | font-size: 16px;
12 | margin: 0;
13 | }
14 |
15 | .test-container {
16 | height: auto !important;
17 | }
18 |
19 | .bio-properties-panel {
20 | --font-family: inherit;
21 | --font-family-monospace: inherit;
22 | }
23 |
--------------------------------------------------------------------------------
/packages/form-js-editor/test/testBundle.js:
--------------------------------------------------------------------------------
1 | const allTests = require.context('.', true, /.spec\.js$/);
2 |
3 | allTests.keys().forEach(allTests);
4 |
--------------------------------------------------------------------------------
/packages/form-js-integration/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@bpmn-io/form-js-integration",
3 | "version": "1.15.2",
4 | "description": "A set of form-js integration testing resources",
5 | "private": true,
6 | "scripts": {
7 | "test": "run-s test:types",
8 | "test:types": "tsc src/application.ts --outDir dist"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/bpmn-io/form-js.git",
13 | "directory": "packages/form-js-integration"
14 | },
15 | "author": {
16 | "name": "bpmn.io contributors",
17 | "url": "https://github.com/bpmn-io"
18 | },
19 | "dependencies": {
20 | "@bpmn-io/form-js": "^1.15.2"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/packages/form-js-playground/resources/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/form-js/7e3fcd5ea1a8937bc7a7c91972cec45600728105/packages/form-js-playground/resources/screenshot.png
--------------------------------------------------------------------------------
/packages/form-js-playground/src/components/FileDrop.css:
--------------------------------------------------------------------------------
1 | /**
2 | * file-drop.css
3 | */
4 | .drop-overlay {
5 | position: fixed;
6 | top: 0;
7 | left: 0;
8 | bottom: 0;
9 | right: 0;
10 |
11 | padding: 50px;
12 |
13 | background: rgba(255, 255, 255, 0.9);
14 |
15 | z-index: 1000;
16 | }
17 |
18 | .drop-overlay .box {
19 | text-align: center;
20 | border: dashed 4px #ccc;
21 | height: 100%;
22 | width: 100%;
23 | display: table;
24 | }
25 |
26 | .drop-overlay .label {
27 | font-size: 26px;
28 | color: #888;
29 | margin: auto;
30 |
31 | display: table-cell;
32 | vertical-align: middle;
33 | }
34 |
--------------------------------------------------------------------------------
/packages/form-js-playground/src/components/Section.js:
--------------------------------------------------------------------------------
1 | export function Section(props) {
2 | const elements = Array.isArray(props.children) ? props.children : [props.children];
3 |
4 | const { headerItems, children } = elements.reduce(
5 | (_, child) => {
6 | const bucket = child.type === Section.HeaderItem ? _.headerItems : _.children;
7 |
8 | bucket.push(child);
9 |
10 | return _;
11 | },
12 | { headerItems: [], children: [] },
13 | );
14 |
15 | return (
16 |
17 |
20 |
{children}
21 |
22 | );
23 | }
24 |
25 | Section.HeaderItem = function (props) {
26 | return props.children;
27 | };
28 |
--------------------------------------------------------------------------------
/packages/form-js-playground/src/components/autocompletion/VariablesFacet.js:
--------------------------------------------------------------------------------
1 | import { Facet } from '@codemirror/state';
2 |
3 | /**
4 | * @type {Facet} Variables
5 | */
6 | export const variablesFacet = Facet.define();
7 |
--------------------------------------------------------------------------------
/packages/form-js-playground/src/index.js:
--------------------------------------------------------------------------------
1 | export { Playground } from './Playground';
2 |
--------------------------------------------------------------------------------
/packages/form-js-playground/test/TestHelper.js:
--------------------------------------------------------------------------------
1 | import './test.css';
2 |
3 | import '@bpmn-io/form-js-viewer/dist/assets/form-js.css';
4 |
5 | import '@bpmn-io/form-js-editor/dist/assets/form-js-editor.css';
6 |
7 | export { expectNoViolations } from '../../form-js-viewer/test/helper';
8 |
9 | export function isSingleStart(topic) {
10 | return window.__env__ && window.__env__.SINGLE_START === topic;
11 | }
12 |
13 | export function insertCSS(name, css) {
14 | if (document.querySelector('[data-css-file="' + name + '"]')) {
15 | return;
16 | }
17 |
18 | const head = document.head || document.getElementsByTagName('head')[0];
19 | const style = document.createElement('style');
20 | style.setAttribute('data-css-file', name);
21 |
22 | style.type = 'text/css';
23 | style.appendChild(document.createTextNode(css));
24 |
25 | head.appendChild(style);
26 | }
27 |
--------------------------------------------------------------------------------
/packages/form-js-playground/test/coverageBundle.js:
--------------------------------------------------------------------------------
1 | const allTests = require.context('.', true, /.spec\.js$/);
2 |
3 | allTests.keys().forEach(allTests);
4 |
5 | const allSources = require.context('../src', true, /.*\.js$/);
6 |
7 | allSources.keys().forEach(allSources);
8 |
--------------------------------------------------------------------------------
/packages/form-js-playground/test/custom/styles.css:
--------------------------------------------------------------------------------
1 | .range-group {
2 | display: flex;
3 | flex-direction: row;
4 | }
5 |
--------------------------------------------------------------------------------
/packages/form-js-playground/test/spec/custom.json:
--------------------------------------------------------------------------------
1 | {
2 | "components": [
3 | {
4 | "key": "creditor",
5 | "label": "Creditor",
6 | "type": "textfield",
7 | "validate": {
8 | "required": true
9 | }
10 | },
11 | {
12 | "key": "amount",
13 | "type": "range",
14 | "label": "Amount",
15 | "range": {
16 | "min": 0,
17 | "max": 100,
18 | "step": 5
19 | }
20 | },
21 | {
22 | "type": "button",
23 | "action": "submit",
24 | "label": "Submit"
25 | }
26 | ],
27 | "type": "default"
28 | }
29 |
--------------------------------------------------------------------------------
/packages/form-js-playground/test/spec/other-form.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../../../form-json-schema/resources/schema.json",
3 | "components": [
4 | {
5 | "action": "reset",
6 | "id": "foo",
7 | "label": "Reset",
8 | "type": "button"
9 | }
10 | ],
11 | "type": "default"
12 | }
13 |
--------------------------------------------------------------------------------
/packages/form-js-playground/test/test.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: sans-serif;
3 | font-size: 16px;
4 | margin: 1rem;
5 | }
6 |
7 | h1 {
8 | margin: 0 0 1rem 0;
9 | }
10 |
--------------------------------------------------------------------------------
/packages/form-js-playground/test/testBundle.js:
--------------------------------------------------------------------------------
1 | const allTests = require.context('.', true, /.spec\.js$/);
2 |
3 | allTests.keys().forEach(allTests);
4 |
--------------------------------------------------------------------------------
/packages/form-js-viewer/assets/grid.scss:
--------------------------------------------------------------------------------
1 | @use '@carbon/grid';
2 |
3 | // Emit the flex-grid styles
4 | @include grid.flex-grid();
5 |
--------------------------------------------------------------------------------
/packages/form-js-viewer/assets/index.scss:
--------------------------------------------------------------------------------
1 | @use 'form-js-base.css';
2 | @use 'grid.scss';
3 | @use 'flatpickr/dist/themes/light.css';
4 |
--------------------------------------------------------------------------------
/packages/form-js-viewer/src/core/EventBus.js:
--------------------------------------------------------------------------------
1 | export { default as EventBus } from 'diagram-js/lib/core/EventBus';
2 |
--------------------------------------------------------------------------------
/packages/form-js-viewer/src/core/index.js:
--------------------------------------------------------------------------------
1 | import { EventBus } from './EventBus';
2 | import { Validator } from './Validator';
3 | import { Importer } from './Importer';
4 | import { FieldFactory } from './FieldFactory';
5 | import { PathRegistry } from './PathRegistry';
6 | import { FormLayouter } from './FormLayouter';
7 | import { FormFieldRegistry } from './FormFieldRegistry';
8 | import { FormFieldInstanceRegistry } from './FormFieldInstanceRegistry';
9 |
10 | import { RenderModule } from '../render';
11 |
12 | export { Importer, FieldFactory, FormFieldRegistry, PathRegistry, FormLayouter };
13 |
14 | export const CoreModule = {
15 | __depends__: [RenderModule],
16 | eventBus: ['type', EventBus],
17 | importer: ['type', Importer],
18 | fieldFactory: ['type', FieldFactory],
19 | formFieldRegistry: ['type', FormFieldRegistry],
20 | formFieldInstanceRegistry: ['type', FormFieldInstanceRegistry],
21 | pathRegistry: ['type', PathRegistry],
22 | formLayouter: ['type', FormLayouter],
23 | validator: ['type', Validator],
24 | };
25 |
--------------------------------------------------------------------------------
/packages/form-js-viewer/src/features/expressionField/index.js:
--------------------------------------------------------------------------------
1 | import { ExpressionLoopPreventer } from './ExpressionLoopPreventer';
2 |
3 | export const ExpressionFieldModule = {
4 | __init__: ['expressionLoopPreventer'],
5 | expressionLoopPreventer: ['type', ExpressionLoopPreventer],
6 | };
7 |
8 | export { ExpressionLoopPreventer };
9 |
--------------------------------------------------------------------------------
/packages/form-js-viewer/src/features/expressionLanguage/index.js:
--------------------------------------------------------------------------------
1 | import { FeelExpressionLanguage } from './FeelExpressionLanguage';
2 | import { FeelersTemplating } from './FeelersTemplating';
3 | import { ConditionChecker } from './ConditionChecker';
4 |
5 | export const ExpressionLanguageModule = {
6 | __init__: ['expressionLanguage', 'templating', 'conditionChecker'],
7 | expressionLanguage: ['type', FeelExpressionLanguage],
8 | templating: ['type', FeelersTemplating],
9 | conditionChecker: ['type', ConditionChecker],
10 | };
11 |
12 | export { FeelExpressionLanguage, FeelersTemplating, ConditionChecker };
13 |
--------------------------------------------------------------------------------
/packages/form-js-viewer/src/features/index.js:
--------------------------------------------------------------------------------
1 | export { ExpressionLanguageModule } from './expressionLanguage';
2 | export { ExpressionFieldModule } from './expressionField';
3 | export { MarkdownRendererModule } from './markdown';
4 | export { ViewerCommandsModule } from './viewerCommands';
5 | export { RepeatRenderModule } from './repeatRender';
6 |
7 | export * from './expressionLanguage';
8 | export * from './expressionField';
9 | export * from './markdown';
10 | export * from './viewerCommands';
11 | export * from './repeatRender';
12 |
--------------------------------------------------------------------------------
/packages/form-js-viewer/src/features/markdown/MarkdownRenderer.js:
--------------------------------------------------------------------------------
1 | import { marked } from 'marked';
2 |
3 | export class MarkdownRenderer {
4 | /**
5 | * Render markdown to HTML.
6 | *
7 | * @param {string} markdown - The markdown to render
8 | *
9 | * @returns {string} HTML
10 | */
11 | render(markdown) {
12 | // @ts-expect-error
13 | return marked.parse(markdown, {
14 | gfm: true,
15 | breaks: true,
16 | });
17 | }
18 | }
19 |
20 | MarkdownRenderer.$inject = [];
21 |
--------------------------------------------------------------------------------
/packages/form-js-viewer/src/features/markdown/index.js:
--------------------------------------------------------------------------------
1 | import { MarkdownRenderer } from './MarkdownRenderer';
2 |
3 | export const MarkdownRendererModule = {
4 | __init__: ['markdownRenderer'],
5 | markdownRenderer: ['type', MarkdownRenderer],
6 | };
7 |
8 | export { MarkdownRenderer };
9 |
--------------------------------------------------------------------------------
/packages/form-js-viewer/src/features/repeatRender/index.js:
--------------------------------------------------------------------------------
1 | import { RepeatRenderManager } from './RepeatRenderManager';
2 |
3 | export const RepeatRenderModule = {
4 | __init__: ['repeatRenderManager'],
5 | repeatRenderManager: ['type', RepeatRenderManager],
6 | };
7 |
8 | export { RepeatRenderManager };
9 |
--------------------------------------------------------------------------------
/packages/form-js-viewer/src/features/viewerCommands/cmd/UpdateFieldValidationHandler.js:
--------------------------------------------------------------------------------
1 | import { set } from 'min-dash';
2 | import { clone } from '../../../util';
3 |
4 | /**
5 | * @deprecated
6 | */
7 | export class UpdateFieldValidationHandler {
8 | constructor(form, validator) {
9 | this._form = form;
10 | this._validator = validator;
11 | }
12 |
13 | execute(context) {
14 | const { field, value, indexes } = context;
15 | const { errors } = this._form._getState();
16 |
17 | context.oldErrors = clone(errors);
18 |
19 | const fieldErrors = this._validator.validateField(field, value);
20 | const updatedErrors = set(
21 | errors,
22 | [field.id, ...Object.values(indexes || {})],
23 | fieldErrors.length ? fieldErrors : undefined,
24 | );
25 | this._form._setState({ errors: updatedErrors });
26 | }
27 |
28 | revert(context) {
29 | this._form._setState({ errors: context.oldErrors });
30 | }
31 | }
32 |
33 | UpdateFieldValidationHandler.$inject = ['form', 'validator'];
34 |
--------------------------------------------------------------------------------
/packages/form-js-viewer/src/features/viewerCommands/index.js:
--------------------------------------------------------------------------------
1 | import commandModule from 'diagram-js/lib/command';
2 |
3 | import { ViewerCommands } from './ViewerCommands';
4 |
5 | export const ViewerCommandsModule = {
6 | __depends__: [commandModule],
7 | __init__: ['viewerCommands'],
8 | viewerCommands: ['type', ViewerCommands],
9 | };
10 |
11 | export { ViewerCommands };
12 |
--------------------------------------------------------------------------------
/packages/form-js-viewer/src/index.js:
--------------------------------------------------------------------------------
1 | import { Form } from './Form';
2 |
3 | export { FormFieldRegistry, FormLayouter, Importer, FieldFactory, PathRegistry } from './core';
4 | export * from './render';
5 | export * from './util';
6 | export * from './features';
7 |
8 | const schemaVersion = 18;
9 |
10 | export { Form, schemaVersion };
11 |
12 | /**
13 | * @typedef { import('./types').CreateFormOptions } CreateFormOptions
14 | */
15 |
16 | /**
17 | * Create a form.
18 | *
19 | * @param {CreateFormOptions} options
20 | *
21 | * @return {Promise