├── .gitignore
├── codecov.yml
├── resources
└── screenshot.png
├── test
├── testBundle.js
├── coverageBundle.js
├── spec
│ ├── create-append-anything
│ │ ├── create-menu
│ │ │ ├── CreateMenuProvider.bpmn
│ │ │ ├── CreatePaletteProvider.spec.js
│ │ │ └── CreateMenuProvider.spec.js
│ │ ├── append-menu
│ │ │ ├── AppendMenuProvider.bpmn
│ │ │ ├── AppendRules.bpmn
│ │ │ ├── AppendContextPadProvider.spec.js
│ │ │ ├── AppendRules.spec.js
│ │ │ └── AppendMenuProvider.spec.js
│ │ ├── CreateAppendAnything.spec.js
│ │ ├── editor-actions
│ │ │ └── CreateAppendEditorActions.spec.js
│ │ └── keyboard-bindings
│ │ │ └── CreateAppendKeyboardBindings.spec.js
│ └── element-templates
│ │ ├── create-menu
│ │ ├── ElementTemplatesCreateProvider.bpmn
│ │ └── ElementTemplatesCreateProvider.spec.js
│ │ ├── append-menu
│ │ ├── ElementTemplatesAppendProvider.bpmn
│ │ └── ElementTemplatesAppendProvider.spec.js
│ │ ├── replace-menu
│ │ ├── RemoveTemplateReplaceProvider.bpmn
│ │ ├── ElementTemplatesReplaceProvider.bpmn
│ │ ├── RemoveTemplateReplaceProvider.spec.js
│ │ ├── RemoveTemplateReplaceProvider.element-templates.json
│ │ └── ElementTemplatesReplaceProvider.spec.js
│ │ └── CreateAppendElementTemplates.spec.js
├── test.css
├── fixtures
│ ├── simple.bpmn
│ └── element-templates.json
└── TestHelper.js
├── renovate.json
├── lib
├── util
│ ├── ReplaceOptionsUtil.js
│ └── CreateOptionsUtil.js
├── index.js
├── element-templates
│ ├── append-menu
│ │ ├── index.js
│ │ └── ElementTemplatesAppendProvider.js
│ ├── create-menu
│ │ ├── index.js
│ │ └── ElementTemplatesCreateProvider.js
│ ├── remove-templates
│ │ ├── index.js
│ │ └── RemoveTemplateReplaceProvider.js
│ ├── replace-menu
│ │ ├── index.js
│ │ └── ElementTemplatesReplaceProvider.js
│ └── index.js
├── icons
│ ├── resources
│ │ ├── append.svg
│ │ └── create.svg
│ └── Icons.js
└── create-append-anything
│ ├── create-menu
│ ├── index.js
│ ├── CreatePaletteProvider.js
│ └── CreateMenuProvider.js
│ ├── index.js
│ ├── editor-actions
│ ├── index.js
│ └── EditorActions.js
│ ├── keyboard-bindings
│ ├── index.js
│ └── KeyboardBindings.js
│ └── append-menu
│ ├── index.js
│ ├── AppendRules.js
│ ├── AppendContextPadProvider.js
│ └── AppendMenuProvider.js
├── rollup.config.js
├── .github
└── workflows
│ └── CI.yml
├── eslint.config.mjs
├── LICENSE
├── README.md
├── CHANGELOG.md
├── karma.config.js
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | comment: off
2 |
3 | parsers:
4 | javascript:
5 | enable_partials: yes
--------------------------------------------------------------------------------
/resources/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpmn-io/bpmn-js-create-append-anything/HEAD/resources/screenshot.png
--------------------------------------------------------------------------------
/test/testBundle.js:
--------------------------------------------------------------------------------
1 | const allTests = require.context('.', true, /.spec\.js$/);
2 |
3 | allTests.keys().forEach(allTests);
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "github>bpmn-io/renovate-config:recommended"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/test/coverageBundle.js:
--------------------------------------------------------------------------------
1 | const allTests = require.context('.', true, /.spec\.js$/);
2 |
3 | allTests.keys().forEach(allTests);
4 |
5 | const allSources = require.context('../lib', true, /.*\.js$/);
6 |
7 | allSources.keys().forEach(allSources);
--------------------------------------------------------------------------------
/lib/util/ReplaceOptionsUtil.js:
--------------------------------------------------------------------------------
1 | import * as replaceOptions from 'bpmn-js/lib/features/replace/ReplaceOptions';
2 |
3 | const ALL_OPTIONS = Object.values(replaceOptions);
4 |
5 | export function getReplaceOptionGroups() {
6 | return ALL_OPTIONS;
7 | }
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | export { default as CreateAppendAnythingModule } from './create-append-anything';
2 | export { default as CreateAppendElementTemplatesModule } from './element-templates';
3 | export { default as RemoveTemplatesModule } from './element-templates/remove-templates';
--------------------------------------------------------------------------------
/lib/element-templates/append-menu/index.js:
--------------------------------------------------------------------------------
1 | import ElementTemplatesAppendProvider from './ElementTemplatesAppendProvider';
2 |
3 | export default {
4 | __init__: [ 'elementTemplatesAppendProvider' ],
5 | elementTemplatesAppendProvider: [ 'type', ElementTemplatesAppendProvider ]
6 | };
--------------------------------------------------------------------------------
/lib/element-templates/create-menu/index.js:
--------------------------------------------------------------------------------
1 | import ElementTemplatesCreateProvider from './ElementTemplatesCreateProvider';
2 |
3 | export default {
4 | __init__: [ 'elementTemplatesCreateProvider' ],
5 | elementTemplatesCreateProvider: [ 'type', ElementTemplatesCreateProvider ]
6 | };
--------------------------------------------------------------------------------
/lib/element-templates/remove-templates/index.js:
--------------------------------------------------------------------------------
1 | import RemoveTemplateReplaceProvider from './RemoveTemplateReplaceProvider';
2 |
3 | export default {
4 | __init__: [ 'removeTemplateReplaceProvider' ],
5 | removeTemplateReplaceProvider: [ 'type', RemoveTemplateReplaceProvider ]
6 | };
--------------------------------------------------------------------------------
/lib/element-templates/replace-menu/index.js:
--------------------------------------------------------------------------------
1 | import ElementTemplatesReplaceProvider from './ElementTemplatesReplaceProvider';
2 |
3 | export default {
4 | __init__: [
5 | 'elementTemplatesReplaceProvider'
6 | ],
7 | elementTemplatesReplaceProvider: [ 'type', ElementTemplatesReplaceProvider ]
8 | };
--------------------------------------------------------------------------------
/lib/icons/resources/append.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/icons/resources/create.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/create-append-anything/create-menu/index.js:
--------------------------------------------------------------------------------
1 | import CreateMenuProvider from './CreateMenuProvider';
2 | import CreatePaletteProvider from './CreatePaletteProvider';
3 |
4 | export default {
5 | __init__: [
6 | 'createMenuProvider',
7 | 'createPaletteProvider'
8 | ],
9 | createMenuProvider: [ 'type', CreateMenuProvider ],
10 | createPaletteProvider: [ 'type', CreatePaletteProvider ]
11 | };
12 |
--------------------------------------------------------------------------------
/lib/create-append-anything/index.js:
--------------------------------------------------------------------------------
1 | import AppendMenuModule from './append-menu';
2 | import CreateMenuModule from './create-menu';
3 | import EditorActionsModule from './editor-actions';
4 | import KeyboardBindingsModule from './keyboard-bindings';
5 |
6 | export default {
7 | __depends__: [
8 | AppendMenuModule,
9 | CreateMenuModule,
10 | EditorActionsModule,
11 | KeyboardBindingsModule
12 | ],
13 | };
--------------------------------------------------------------------------------
/lib/create-append-anything/editor-actions/index.js:
--------------------------------------------------------------------------------
1 | import AppendMenuModule from '../append-menu';
2 | import CreateMenuModule from '../create-menu';
3 |
4 | import CreateAppendEditorActions from './EditorActions';
5 |
6 | export default {
7 | __depends__: [
8 | AppendMenuModule,
9 | CreateMenuModule
10 | ],
11 | __init__: [
12 | 'createAppendEditorActions'
13 | ],
14 | createAppendEditorActions: [ 'type', CreateAppendEditorActions ]
15 | };
--------------------------------------------------------------------------------
/lib/element-templates/index.js:
--------------------------------------------------------------------------------
1 | import AppendElementTemplatesModule from './append-menu';
2 | import CreateElementTemplatesModule from './create-menu';
3 | import ReplaceElementTemplatesModule from './replace-menu';
4 | import RemoveTemplatesModule from './remove-templates';
5 |
6 | export default {
7 | __depends__: [
8 | AppendElementTemplatesModule,
9 | CreateElementTemplatesModule,
10 | ReplaceElementTemplatesModule,
11 | RemoveTemplatesModule
12 | ]
13 | };
--------------------------------------------------------------------------------
/lib/create-append-anything/keyboard-bindings/index.js:
--------------------------------------------------------------------------------
1 | import AppendMenuModule from '../append-menu';
2 | import CreateMenuModule from '../create-menu';
3 |
4 | import CreateAppendKeyboardBindings from './KeyboardBindings';
5 |
6 | export default {
7 | __depends__: [
8 | AppendMenuModule,
9 | CreateMenuModule
10 | ],
11 | __init__: [
12 | 'createAppendKeyboardBindings'
13 | ],
14 | createAppendKeyboardBindings: [ 'type', CreateAppendKeyboardBindings ]
15 | };
--------------------------------------------------------------------------------
/lib/create-append-anything/append-menu/index.js:
--------------------------------------------------------------------------------
1 | import AppendMenuProvider from './AppendMenuProvider';
2 | import AppendContextPadProvider from './AppendContextPadProvider';
3 | import AppendRules from './AppendRules';
4 |
5 | export default {
6 | __init__: [
7 | 'appendMenuProvider',
8 | 'appendContextPadProvider',
9 | 'appendRules'
10 | ],
11 | appendMenuProvider: [ 'type', AppendMenuProvider ],
12 | appendContextPadProvider: [ 'type', AppendContextPadProvider ],
13 | appendRules: [ 'type', AppendRules ]
14 | };
15 |
--------------------------------------------------------------------------------
/test/spec/create-append-anything/create-menu/CreateMenuProvider.bpmn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 | const commonjs = require('@rollup/plugin-commonjs');
3 | const json = require('@rollup/plugin-json');
4 | const nodeResolve = require('@rollup/plugin-node-resolve');
5 |
6 | const pkg = require('./package.json');
7 | const nonbundledDependencies = Object.keys({ ...pkg.dependencies });
8 |
9 | module.exports = {
10 | input: 'lib/index.js',
11 | output: [ {
12 | file: pkg.main,
13 | format: 'cjs'
14 | },
15 | {
16 | file: pkg.module,
17 | format: 'esm'
18 | } ],
19 | plugins: [
20 | commonjs(),
21 | json(),
22 | nodeResolve(),
23 | ],
24 | external: nonbundledDependencies
25 | };
26 |
--------------------------------------------------------------------------------
/test/spec/element-templates/create-menu/ElementTemplatesCreateProvider.bpmn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/lib/icons/Icons.js:
--------------------------------------------------------------------------------
1 | const appendIcon = ``;
4 | const createIcon = ``;
7 |
8 | export {
9 | appendIcon,
10 | createIcon
11 | };
--------------------------------------------------------------------------------
/test/test.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600&display=swap');
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | html,
8 | body {
9 | height: 100%;
10 | margin: 0;
11 | font-family: 'IBM Plex Sans', sans-serif;
12 | }
13 |
14 | .test-container {
15 | display: flex;
16 | flex-direction: column;
17 | height: 100vh !important;
18 | }
19 |
20 | .test-content-container {
21 | display: flex;
22 | flex: 1;
23 | flex-direction: row;
24 | overflow: hidden;
25 | }
26 |
27 | .modeler-container {
28 | flex: 1;
29 | }
30 |
31 | .properties-container {
32 | flex: none;
33 | width: 300px;
34 | border-left: solid 1px #cccccc;
35 | }
36 |
37 | .properties-container .bio-properties-panel {
38 | --font-family: 'IBM Plex Sans', sans-serif !important;
39 | }
--------------------------------------------------------------------------------
/.github/workflows/CI.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on: [push, pull_request]
3 | jobs:
4 | Build:
5 | strategy:
6 | matrix:
7 | os: [ ubuntu-latest ]
8 | node-version: [ 20 ]
9 |
10 | runs-on: ${{ matrix.os }}
11 |
12 | steps:
13 | - name: Checkout
14 | uses: actions/checkout@v6
15 | - name: Use Node.js
16 | uses: actions/setup-node@v6
17 | with:
18 | node-version: ${{ matrix.node-version }}
19 | cache: 'npm'
20 | - name: Install dependencies
21 | run: npm ci
22 | - name: Setup project
23 | uses: bpmn-io/actions/setup@latest
24 | - name: Build with coverage
25 | run: COVERAGE=1 npm run all
26 | - name: Upload Coverage
27 | uses: codecov/codecov-action@v5
28 | with:
29 | fail_ci_if_error: true
30 | env:
31 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
32 |
--------------------------------------------------------------------------------
/eslint.config.mjs:
--------------------------------------------------------------------------------
1 | import bpmnIoPlugin from 'eslint-plugin-bpmn-io';
2 |
3 | const files = {
4 | build: [
5 | '*.js',
6 | '*.mjs'
7 | ],
8 | ignored: [
9 | 'dist',
10 | 'coverage'
11 | ],
12 | test: [
13 | 'test/**/*.js'
14 | ]
15 | };
16 |
17 |
18 | export default [
19 | {
20 | ignores: files.ignored
21 | },
22 |
23 | // build
24 | ...bpmnIoPlugin.configs.node.map(config => {
25 | return {
26 | ...config,
27 | files: files.build
28 | };
29 | }),
30 |
31 | // lib + test
32 | ...bpmnIoPlugin.configs.browser.map(config => {
33 | return {
34 | ...config,
35 | ignores: files.build
36 | };
37 | }),
38 |
39 | // test
40 | ...bpmnIoPlugin.configs.mocha.map(config => {
41 | return {
42 | ...config,
43 | files: files.test
44 | };
45 | }),
46 | {
47 | languageOptions: {
48 | globals: {
49 | require: false,
50 | sinon: false
51 | }
52 | },
53 | files: files.test
54 | }
55 | ];
56 |
--------------------------------------------------------------------------------
/test/spec/element-templates/append-menu/ElementTemplatesAppendProvider.bpmn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2023-present Camunda Services GmbH
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/test/spec/create-append-anything/create-menu/CreatePaletteProvider.spec.js:
--------------------------------------------------------------------------------
1 | import {
2 | bootstrapModeler,
3 | getBpmnJS,
4 | inject
5 | } from 'test/TestHelper';
6 |
7 | import CreateMenuModule from 'lib/create-append-anything/create-menu';
8 |
9 | import { createMoveEvent } from 'diagram-js/lib/features/mouse/Mouse';
10 |
11 |
12 | describe('features/palette', function() {
13 |
14 | const diagramXML = require('./CreateMenuProvider.bpmn').default;
15 |
16 | beforeEach(bootstrapModeler(diagramXML, {
17 | additionalModules: [ CreateMenuModule ]
18 | }));
19 |
20 | describe('create', function() {
21 |
22 | it('should trigger create menu', inject(function(popupMenu, canvas) {
23 |
24 | // given
25 | const createSpy = sinon.spy(popupMenu, 'open');
26 |
27 | // when
28 | triggerPaletteEntry('create');
29 |
30 | // then
31 | const args = createSpy.getCall(0).args;
32 |
33 | expect(createSpy).to.have.been.called;
34 | expect(args[0]).to.eq(canvas.getRootElement());
35 | expect(args[1]).to.eq('bpmn-create');
36 | }));
37 |
38 | });
39 |
40 | });
41 |
42 |
43 | // helpers //////////
44 |
45 | function triggerPaletteEntry(id) {
46 | getBpmnJS().invoke(function(palette) {
47 | const entry = palette.getEntries()[ id ];
48 |
49 | if (entry && entry.action && entry.action.click) {
50 | entry.action.click(createMoveEvent(0, 0));
51 | }
52 | });
53 | }
--------------------------------------------------------------------------------
/lib/create-append-anything/editor-actions/EditorActions.js:
--------------------------------------------------------------------------------
1 | import { assign } from 'min-dash';
2 |
3 | /**
4 | * Registers and executes BPMN specific editor actions.
5 | *
6 | * @param {Injector} injector
7 | */
8 | export default function CreateAppendEditorActions(injector) {
9 | this._injector = injector;
10 |
11 | this.registerActions();
12 | }
13 |
14 | CreateAppendEditorActions.$inject = [
15 | 'injector'
16 | ];
17 |
18 | /**
19 | * Register actions.
20 | *
21 | * @param {Injector} injector
22 | */
23 | CreateAppendEditorActions.prototype.registerActions = function() {
24 | const editorActions = this._injector.get('editorActions', false);
25 | const selection = this._injector.get('selection', false);
26 | const contextPad = this._injector.get('contextPad', false);
27 | const palette = this._injector.get('palette', false);
28 | const popupMenu = this._injector.get('popupMenu', false);
29 |
30 | const actions = {};
31 |
32 | // append
33 | if (selection && contextPad && palette && popupMenu && palette) {
34 | assign(actions, {
35 | 'appendElement': function(event) {
36 | const selected = selection && selection.get();
37 |
38 | if (selected.length == 1 && !popupMenu.isEmpty(selected[0], 'bpmn-append')) {
39 | contextPad.triggerEntry('append', 'click', event);
40 | } else {
41 | palette.triggerEntry('create', 'click', event);
42 | }
43 | }
44 | });
45 | }
46 |
47 | // create
48 | if (palette) {
49 | assign(actions, {
50 | 'createElement': function(event) {
51 | palette.triggerEntry('create', 'click', event);
52 | } }
53 | );
54 | }
55 |
56 | editorActions && editorActions.register(actions);
57 |
58 | };
59 |
--------------------------------------------------------------------------------
/lib/create-append-anything/append-menu/AppendRules.js:
--------------------------------------------------------------------------------
1 | import {
2 | find,
3 | } from 'min-dash';
4 |
5 | import inherits from 'inherits-browser';
6 |
7 | import {
8 | is,
9 | isAny,
10 | getBusinessObject
11 | } from 'bpmn-js/lib/util/ModelUtil';
12 |
13 | import {
14 | isLabel
15 | } from 'bpmn-js/lib/util/LabelUtil';
16 |
17 | import RuleProvider from 'diagram-js/lib/features/rules/RuleProvider';
18 |
19 |
20 | /**
21 | * Append anything modeling rules
22 | */
23 | export default function AppendRules(eventBus) {
24 | RuleProvider.call(this, eventBus);
25 | }
26 |
27 | inherits(AppendRules, RuleProvider);
28 |
29 | AppendRules.$inject = [
30 | 'eventBus'
31 | ];
32 |
33 | AppendRules.prototype.init = function() {
34 | this.addRule('shape.append', function(context) {
35 |
36 | const source = context.element;
37 |
38 | const businessObject = getBusinessObject(source);
39 |
40 | if (isLabel(source)) {
41 | return false;
42 | }
43 |
44 | if (isAny(source, [
45 | 'bpmn:EndEvent',
46 | 'bpmn:Group',
47 | 'bpmn:TextAnnotation',
48 | 'bpmn:Lane',
49 | 'bpmn:Participant',
50 | 'bpmn:DataStoreReference',
51 | 'bpmn:DataObjectReference'
52 | ])) {
53 | return false;
54 | }
55 |
56 | if (isConnection(source)) {
57 | return false;
58 | }
59 |
60 | if (is(source, 'bpmn:IntermediateThrowEvent') && hasEventDefinition(source, 'bpmn:LinkEventDefinition')) {
61 | return false;
62 | }
63 |
64 | if (is(source, 'bpmn:SubProcess') && businessObject.triggeredByEvent) {
65 | return false;
66 | }
67 | });
68 |
69 | };
70 |
71 |
72 | // helpers //////////////
73 | function hasEventDefinition(element, eventDefinition) {
74 | const bo = getBusinessObject(element);
75 |
76 | return !!find(bo.eventDefinitions || [], function(definition) {
77 | return is(definition, eventDefinition);
78 | });
79 | }
80 |
81 | function isConnection(element) {
82 | return element.waypoints;
83 | }
--------------------------------------------------------------------------------
/test/spec/create-append-anything/append-menu/AppendMenuProvider.bpmn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Flow_0zr9ajj
6 |
7 |
8 | Flow_00dqsyf
9 | Flow_0zr9ajj
10 |
11 |
12 | Flow_00dqsyf
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/test/spec/element-templates/replace-menu/RemoveTemplateReplaceProvider.bpmn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # bpmn-js-create-append-anything
2 |
3 | [](https://github.com/bpmn-io/bpmn-js-create-append-anything/actions/workflows/CI.yml)
4 |
5 | This module extends [bpmn-js](https://github.com/bpmn-io/bpmn-js) with a create and append anything modeling experience.
6 |
7 | 
8 |
9 |
10 | ## Features
11 |
12 | * Create any BPMN element from the palette
13 | * Append any BPMN element from the context pad
14 | * Fully keyboard navigatable (`N` and `A` to open the menus)
15 | * Integration with [element templates](https://github.com/bpmn-io/element-templates) through dedicated extension
16 | * Create or append templated elements
17 | * Apply template through the replace menu
18 |
19 |
20 | ## Installation
21 |
22 | Install via npm:
23 |
24 | ```sh
25 | npm install bpmn-js-create-append-anything
26 | ```
27 |
28 |
29 | ## Usage
30 |
31 | Use as an extension for [bpmn-js](https://github.com/bpmn-io/bpmn-js):
32 |
33 | ```javascript
34 | import {
35 | CreateAppendAnythingModule
36 | } from 'bpmn-js-create-append-anything';
37 |
38 | const modeler = new BpmnModeler({
39 | additionalModules: [
40 | ...,
41 | CreateAppendAnythingModule,
42 | CreateAppendElementTemplatesModule
43 | ]
44 | });
45 | ```
46 |
47 | If desired, integrate with [element templates](https://github.com/bpmn-io/element-templates):
48 |
49 | ```javascript
50 | import {
51 | CreateAppendAnythingModule,
52 | CreateAppendElementTemplatesModule
53 | } from 'bpmn-js-create-append-anything';
54 |
55 | const modeler = new BpmnModeler({
56 | additionalModules: [
57 | ...,
58 | CreateAppendAnythingModule,
59 | CreateAppendElementTemplatesModule
60 | ]
61 | });
62 | ```
63 |
64 | This relies on `elementTemplates` to be provided via an external module, i.e. [bpmn-js-element-templates](https://github.com/bpmn-io/bpmn-js-element-templates).
65 |
66 |
67 | ## Run locally
68 |
69 | To get the development setup make sure to have [NodeJS](https://nodejs.org/en/download/) installed.
70 | As soon as you are set up, clone the project and execute
71 |
72 | ```sh
73 | # install dependencies
74 | npm install
75 |
76 | # start a bpmn-js instance with the extension
77 | npm start
78 |
79 | # for regular BPMN elements only
80 | npm run start:bpmn
81 | ```
82 |
83 |
84 | ## License
85 |
86 | MIT
87 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to [bpmn-js-create-append-anything](https://github.com/bpmn-io/bpmn-js-create-append-anything) are documented here. We use [semantic versioning](http://semver.org/) for releases.
4 |
5 | ## Unreleased
6 |
7 | ___Note:__ Yet to be released changes appear here._
8 |
9 | ## 1.0.1
10 |
11 | * `FIX`: trigger create mode if auto place of element with template not possible ([#56](https://github.com/bpmn-io/bpmn-js-create-append-anything/pull/56))
12 |
13 | ## 1.0.0
14 |
15 | * `FEAT`: source element template `keywords` during search ([#50](https://github.com/bpmn-io/bpmn-js-create-append-anything/pull/50))
16 | * `DEPS`: depend on `diagram-js>=15.3.0` ([#50](https://github.com/bpmn-io/bpmn-js-create-append-anything/pull/50))
17 |
18 | ### Breaking Changes
19 |
20 | * Require `diagram-js>=15.3.0` as a peer dependency ([#50](https://github.com/bpmn-io/bpmn-js-create-append-anything/pull/50))
21 |
22 | ## 0.6.0
23 |
24 | * `FEAT`: add ad-hoc subprocess entry ([#47](https://github.com/bpmn-io/bpmn-js-create-append-anything/pull/47))
25 |
26 | ## 0.5.2
27 |
28 | * `FIX`: correct expanded subprocess icon ([#33](https://github.com/bpmn-io/bpmn-js-create-append-anything/pull/33))
29 |
30 | ## 0.5.1
31 |
32 | * `FIX`: use rule to decide whether to show context pad entry for appending ([#27](https://github.com/bpmn-io/bpmn-js-create-append-anything/pull/27))
33 |
34 | ## 0.5.0
35 |
36 | * `FEAT`: update labels to be sentence case ([#17](https://github.com/bpmn-io/bpmn-js-create-append-anything/pull/17))
37 | * `CHORE`: update dependencies
38 |
39 | ## 0.4.0
40 |
41 | * `FEAT`: move "Call Activity" to "Sub Processes" group in options menu ([#14](https://github.com/bpmn-io/bpmn-js-create-append-anything/pull/14))
42 |
43 | ## 0.3.0
44 |
45 | * `FEAT`: base BPMN element entry removes element template instead of unlinking it ([#11](https://github.com/bpmn-io/bpmn-js-create-append-anything/pull/11))
46 |
47 | ### Breaking Changes
48 |
49 | * `UnlinkTemplatesModule` has been renamed to `RemoveTemplatesModule`. If importing the module directly, update your import accordingly.
50 |
51 | ## 0.2.1
52 |
53 | * `FIX`: apply icon hover colors ([#10](https://github.com/bpmn-io/bpmn-js-create-append-anything/pull/10))
54 |
55 | ## 0.2.0
56 |
57 | * `FEAT`: load palette and context pad icons as html ([#7](https://github.com/bpmn-io/bpmn-js-create-append-anything/pull/7))
58 |
59 | ## 0.1.0
60 |
61 | _Initial release_
62 |
--------------------------------------------------------------------------------
/test/fixtures/simple.bpmn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Flow_0g16wxm
6 |
7 |
8 | Flow_0g16wxm
9 | Flow_0vce4r4
10 |
11 |
12 |
13 | Flow_0vce4r4
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/lib/create-append-anything/create-menu/CreatePaletteProvider.js:
--------------------------------------------------------------------------------
1 | import { createIcon } from '../../icons/Icons';
2 |
3 | import { query as domQuery } from 'min-dom';
4 |
5 | const LOWER_PRIORITY = 900;
6 |
7 | /**
8 | * A palette provider for the create elements menu.
9 | */
10 | export default function CreatePaletteProvider(palette, translate, popupMenu, canvas, mouse) {
11 |
12 | this._palette = palette;
13 | this._translate = translate;
14 | this._popupMenu = popupMenu;
15 | this._canvas = canvas;
16 | this._mouse = mouse;
17 |
18 | this.register();
19 | }
20 |
21 | CreatePaletteProvider.$inject = [
22 | 'palette',
23 | 'translate',
24 | 'popupMenu',
25 | 'canvas',
26 | 'mouse'
27 | ];
28 |
29 | /**
30 | * Register create button provider in the palette
31 | */
32 | CreatePaletteProvider.prototype.register = function() {
33 | this._palette.registerProvider(LOWER_PRIORITY, this);
34 | };
35 |
36 | /**
37 | * Gets the palette create entry
38 | *
39 | * @param {djs.model.Base} element
40 | * @returns {Object}
41 | */
42 | CreatePaletteProvider.prototype.getPaletteEntries = function(element) {
43 | const translate = this._translate,
44 | popupMenu = this._popupMenu,
45 | canvas = this._canvas,
46 | mouse = this._mouse;
47 |
48 | const getPosition = (event) => {
49 | const X_OFFSET = 35;
50 | const Y_OFFSET = 10;
51 |
52 | if (event instanceof KeyboardEvent) {
53 | event = mouse.getLastMoveEvent();
54 | return { x: event.x, y: event.y };
55 | }
56 |
57 | const target = event && event.target || domQuery('.djs-palette [data-action="create"]');
58 | const targetPosition = target.getBoundingClientRect();
59 |
60 | return target && {
61 | x: targetPosition.left + targetPosition.width / 2 + X_OFFSET,
62 | y: targetPosition.top + targetPosition.height / 2 + Y_OFFSET
63 | };
64 | };
65 |
66 | return {
67 | 'create': {
68 | group: 'create',
69 | html: `
${createIcon}
`,
70 | title: translate('Create element'),
71 | action: {
72 | click: function(event) {
73 | const position = getPosition(event);
74 |
75 | const element = canvas.getRootElement();
76 |
77 | popupMenu.open(element, 'bpmn-create', position, {
78 | title: translate('Create element'),
79 | width: 300,
80 | search: true
81 | });
82 | }
83 | }
84 | }
85 | };
86 | };
87 |
--------------------------------------------------------------------------------
/lib/create-append-anything/keyboard-bindings/KeyboardBindings.js:
--------------------------------------------------------------------------------
1 | import inherits from 'inherits-browser';
2 |
3 | import KeyboardBindings from 'diagram-js/lib/features/keyboard/KeyboardBindings';
4 |
5 |
6 | /**
7 | * BPMN 2.0 specific keyboard bindings.
8 | *
9 | * @param {Injector} injector
10 | */
11 | export default function CreateAppendKeyboardBindings(injector) {
12 |
13 | this._injector = injector;
14 | this._keyboard = this._injector.get('keyboard', false);
15 | this._editorActions = this._injector.get('editorActions', false);
16 |
17 | if (this._keyboard) {
18 | this._injector.invoke(KeyboardBindings, this);
19 | }
20 | }
21 |
22 | inherits(CreateAppendKeyboardBindings, KeyboardBindings);
23 |
24 | CreateAppendKeyboardBindings.$inject = [
25 | 'injector'
26 | ];
27 |
28 |
29 | /**
30 | * Register available keyboard bindings.
31 | *
32 | * @param {Keyboard} keyboard
33 | * @param {EditorActions} editorActions
34 | */
35 | CreateAppendKeyboardBindings.prototype.registerBindings = function() {
36 |
37 | const keyboard = this._keyboard;
38 | const editorActions = this._editorActions;
39 |
40 | // inherit default bindings
41 | KeyboardBindings.prototype.registerBindings.call(this, keyboard, editorActions);
42 |
43 | /**
44 | * Add keyboard binding if respective editor action
45 | * is registered.
46 | *
47 | * @param {string} action name
48 | * @param {Function} fn that implements the key binding
49 | */
50 | function addListener(action, fn) {
51 |
52 | if (editorActions && editorActions.isRegistered(action)) {
53 | keyboard && keyboard.addListener(fn);
54 | }
55 | }
56 |
57 | // activate append/create element
58 | // A
59 | addListener('appendElement', function(context) {
60 |
61 | const event = context.keyEvent;
62 |
63 | if (keyboard && keyboard.hasModifier(event)) {
64 | return;
65 | }
66 |
67 | if (keyboard && keyboard.isKey([ 'a', 'A' ], event)) {
68 |
69 | editorActions && editorActions.trigger('appendElement', event);
70 | return true;
71 | }
72 | });
73 |
74 | // N
75 | addListener('createElement', function(context) {
76 |
77 | const event = context.keyEvent;
78 |
79 | if (keyboard && keyboard.hasModifier(event)) {
80 | return;
81 | }
82 |
83 | if (keyboard && keyboard.isKey([ 'n', 'N' ], event)) {
84 | editorActions && editorActions.trigger('createElement', event);
85 |
86 | return true;
87 | }
88 | });
89 |
90 | };
--------------------------------------------------------------------------------
/lib/create-append-anything/append-menu/AppendContextPadProvider.js:
--------------------------------------------------------------------------------
1 | import {
2 | assign
3 | } from 'min-dash';
4 |
5 | import {
6 | appendIcon
7 | } from '../../icons/Icons';
8 |
9 |
10 | /**
11 | * A provider for append context pad button
12 | */
13 | export default function AppendContextPadProvider(contextPad, popupMenu, translate, canvas, rules) {
14 |
15 | this._contextPad = contextPad;
16 | this._popupMenu = popupMenu;
17 | this._translate = translate;
18 | this._canvas = canvas;
19 | this._rules = rules;
20 |
21 | this.register();
22 | }
23 |
24 | AppendContextPadProvider.$inject = [
25 | 'contextPad',
26 | 'popupMenu',
27 | 'translate',
28 | 'canvas',
29 | 'rules'
30 | ];
31 |
32 | /**
33 | * Register append button provider in the context pad
34 | */
35 | AppendContextPadProvider.prototype.register = function() {
36 | this._contextPad.registerProvider(this);
37 | };
38 |
39 | /**
40 | * Gets the append context pad entry
41 | *
42 | * @param {djs.model.Base} element
43 | * @returns {Object} entries
44 | */
45 | AppendContextPadProvider.prototype.getContextPadEntries = function(element) {
46 | const popupMenu = this._popupMenu;
47 | const translate = this._translate;
48 | const rules = this._rules;
49 | const getAppendMenuPosition = this._getAppendMenuPosition.bind(this);
50 |
51 | if (rules.allowed('shape.append', { element })) {
52 |
53 | // append menu entry
54 | return {
55 | 'append': {
56 | group: 'model',
57 | html: `${appendIcon}
`,
58 | title: translate('Append element'),
59 | action: {
60 | click: function(event, element) {
61 |
62 | const position = assign(getAppendMenuPosition(element), {
63 | cursor: { x: event.x, y: event.y }
64 | });
65 |
66 | popupMenu.open(element, 'bpmn-append', position, {
67 | title: translate('Append element'),
68 | width: 300,
69 | search: true
70 | });
71 | }
72 | }
73 | }
74 | };
75 | }
76 | };
77 |
78 | /**
79 | * Calculates the position for the append menu relatively to the element
80 | *
81 | * @param {djs.model.Base} element
82 | * @returns {Object}
83 | */
84 | AppendContextPadProvider.prototype._getAppendMenuPosition = function(element) {
85 | const X_OFFSET = 5;
86 |
87 | const pad = this._canvas.getContainer().querySelector('.djs-context-pad');
88 |
89 | const padRect = pad.getBoundingClientRect();
90 |
91 | const pos = {
92 | x: padRect.right + X_OFFSET,
93 | y: padRect.top
94 | };
95 |
96 | return pos;
97 | };
--------------------------------------------------------------------------------
/karma.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 |
3 | const path = require('path');
4 |
5 | const basePath = '.';
6 |
7 | // configures browsers to run test against
8 | // any of [ 'ChromeHeadless', 'Chrome', 'Firefox', 'IE', 'PhantomJS' ]
9 | const browsers = (process.env.TEST_BROWSERS || 'ChromeHeadless').split(',');
10 |
11 | const singleStart = process.env.SINGLE_START;
12 |
13 | const coverage = process.env.COVERAGE;
14 |
15 | const absoluteBasePath = path.resolve(path.join(__dirname, basePath));
16 |
17 | // use puppeteer provided Chrome for testing
18 | process.env.CHROME_BIN = require('puppeteer').executablePath();
19 |
20 | const suite = coverage ? 'test/coverageBundle.js' : 'test/testBundle.js';
21 |
22 | module.exports = function(karma) {
23 |
24 | const config = {
25 |
26 | basePath,
27 |
28 | frameworks: [
29 | 'webpack',
30 | 'mocha',
31 | 'sinon-chai'
32 | ],
33 |
34 | files: [
35 | suite
36 | ],
37 |
38 | preprocessors: {
39 | [ suite ]: [ 'webpack', 'env' ]
40 | },
41 |
42 | reporters: [ 'progress' ].concat(coverage ? 'coverage' : []),
43 |
44 | coverageReporter: {
45 | reporters: [
46 | { type: 'lcov', subdir: '.' },
47 | ]
48 | },
49 |
50 | browsers,
51 |
52 | singleRun: true,
53 | autoWatch: false,
54 |
55 | webpack: {
56 | mode: 'development',
57 | module: {
58 | rules: [
59 | {
60 | test: /\.(css|bpmn)$/,
61 | use: 'raw-loader'
62 | },
63 | {
64 | test: /\.m?js$/,
65 | exclude: /node_modules/,
66 | use: {
67 | loader: 'babel-loader',
68 | options: {
69 | plugins: coverage ? [
70 | [ 'istanbul', {
71 | include: [
72 | 'lib/**'
73 | ]
74 | } ]
75 | ] : []
76 | }
77 | }
78 | }
79 | ]
80 | },
81 | resolve: {
82 | mainFields: [
83 | 'browser',
84 | 'module',
85 | 'main'
86 | ],
87 | modules: [
88 | 'node_modules',
89 | absoluteBasePath
90 | ]
91 | },
92 | devtool: 'eval-source-map'
93 | }
94 | };
95 |
96 | if (singleStart) {
97 | config.browsers = [].concat(config.browsers, 'Debug');
98 | config.envPreprocessor = [].concat(config.envPreprocessor || [], 'SINGLE_START');
99 | }
100 |
101 | karma.set(config);
102 | };
103 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bpmn-js-create-append-anything",
3 | "version": "1.0.1",
4 | "description": "",
5 | "main": "dist/index.js",
6 | "scripts": {
7 | "all": "run-s lint test build",
8 | "test": "karma start karma.config.js",
9 | "lint": "eslint .",
10 | "dev": "npm test -- --auto-watch --no-single-run",
11 | "start": "npm run start:templates",
12 | "start:bpmn": "cross-env SINGLE_START=BPMN npm run dev",
13 | "start:templates": "cross-env SINGLE_START=templates npm run dev",
14 | "build": "rollup -c --bundleConfigAsCjs",
15 | "build:watch": "rollup -cw",
16 | "prepare": "run-s build"
17 | },
18 | "repository": {
19 | "type": "git",
20 | "url": "git+https://github.com/bpmn-io/bpmn-js-create-append-anything.git"
21 | },
22 | "keywords": [
23 | "bpmn-io"
24 | ],
25 | "author": "bpmn.io",
26 | "license": "MIT",
27 | "bugs": {
28 | "url": "https://github.com/smbea/bpmn-js-create-append-anything/issues"
29 | },
30 | "homepage": "https://github.com/smbea/bpmn-js-create-append-anything#readme",
31 | "publishConfig": {
32 | "access": "public"
33 | },
34 | "contributors": [
35 | {
36 | "name": "bpmn.io contributors",
37 | "url": "https://github.com/bpmn-io"
38 | }
39 | ],
40 | "files": [
41 | "dist"
42 | ],
43 | "module": "dist/index.es.js",
44 | "peerDependencies": {
45 | "diagram-js": ">= 15.3.0"
46 | },
47 | "devDependencies": {
48 | "@bpmn-io/element-template-chooser": "^2.0.0",
49 | "@rollup/plugin-commonjs": "^29.0.0",
50 | "@rollup/plugin-json": "^6.1.0",
51 | "@rollup/plugin-node-resolve": "^16.0.0",
52 | "@testing-library/preact": "^3.2.3",
53 | "babel-loader": "^10.0.0",
54 | "babel-plugin-istanbul": "^7.0.0",
55 | "bpmn-js": "^18.6.0",
56 | "bpmn-js-element-templates": "^2.5.1",
57 | "bpmn-js-properties-panel": "^5.31.1",
58 | "cross-env": "^10.0.0",
59 | "downloadjs": "^1.4.7",
60 | "eslint": "^9.14.0",
61 | "eslint-plugin-bpmn-io": "^2.0.2",
62 | "file-drops": "^0.5.0",
63 | "karma": "^6.4.4",
64 | "karma-chrome-launcher": "^3.2.0",
65 | "karma-coverage": "^2.2.1",
66 | "karma-debug-launcher": "^0.0.5",
67 | "karma-env-preprocessor": "^0.1.1",
68 | "karma-mocha": "^2.0.1",
69 | "karma-sinon-chai": "^2.0.2",
70 | "karma-webpack": "^5.0.1",
71 | "mocha": "^10.8.2",
72 | "mocha-test-container-support": "^0.2.0",
73 | "npm-run-all2": "^8.0.0",
74 | "puppeteer": "^24.0.0",
75 | "raw-loader": "^4.0.2",
76 | "rollup": "^4.24.4",
77 | "sinon": "^18.0.1",
78 | "sinon-chai": "^3.7.0",
79 | "webpack": "^5.96.1",
80 | "zeebe-bpmn-moddle": "^1.9.0"
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/test/spec/create-append-anything/CreateAppendAnything.spec.js:
--------------------------------------------------------------------------------
1 | import TestContainer from 'mocha-test-container-support';
2 |
3 | import {
4 | clearBpmnJS,
5 | setBpmnJS,
6 | insertCoreStyles,
7 | insertBpmnStyles,
8 | enableLogging
9 | } from 'test/TestHelper';
10 |
11 | import Modeler from 'bpmn-js/lib/Modeler';
12 |
13 | import {
14 | BpmnPropertiesPanelModule,
15 | BpmnPropertiesProviderModule
16 | } from 'bpmn-js-properties-panel';
17 |
18 | import { CreateAppendAnythingModule } from 'lib/';
19 |
20 | const singleStart = window.__env__ && window.__env__.SINGLE_START === 'BPMN';
21 |
22 | insertCoreStyles();
23 | insertBpmnStyles();
24 |
25 |
26 | describe('', function() {
27 |
28 | let modelerContainer;
29 |
30 | let propertiesContainer;
31 |
32 | let container;
33 |
34 | beforeEach(function() {
35 | modelerContainer = document.createElement('div');
36 | modelerContainer.classList.add('modeler-container');
37 |
38 | propertiesContainer = document.createElement('div');
39 | propertiesContainer.classList.add('properties-container');
40 |
41 | container = TestContainer.get(this);
42 |
43 | container.appendChild(modelerContainer);
44 | container.appendChild(propertiesContainer);
45 | });
46 |
47 | async function createModeler(xml, options = {}, BpmnJS = Modeler) {
48 | const {
49 | shouldImport = true,
50 | additionalModules = [
51 | BpmnPropertiesPanelModule,
52 | BpmnPropertiesProviderModule,
53 | CreateAppendAnythingModule
54 | ],
55 | description = {},
56 | layout = {}
57 | } = options;
58 |
59 | clearBpmnJS();
60 |
61 | const modeler = new BpmnJS({
62 | container: modelerContainer,
63 | additionalModules,
64 | propertiesPanel: {
65 | parent: propertiesContainer,
66 | feelTooltipContainer: container,
67 | description,
68 | layout
69 | },
70 | ...options
71 | });
72 |
73 | enableLogging && enableLogging(modeler, !!singleStart);
74 |
75 | setBpmnJS(modeler);
76 |
77 | if (!shouldImport) {
78 | return { modeler };
79 | }
80 |
81 | try {
82 | const result = await modeler.importXML(xml);
83 |
84 | return { error: null, warnings: result.warnings, modeler: modeler };
85 | } catch (err) {
86 | return { error: err, warnings: err.warnings, modeler: modeler };
87 | }
88 | }
89 |
90 |
91 | (singleStart ? it.only : it)('should import simple process', async function() {
92 |
93 | // given
94 | const diagramXml = require('test/fixtures/simple.bpmn').default;
95 |
96 | // when
97 | const result = await createModeler(diagramXml);
98 |
99 | // then
100 | expect(result.error).not.to.exist;
101 | });
102 |
103 | });
104 |
--------------------------------------------------------------------------------
/test/spec/element-templates/replace-menu/ElementTemplatesReplaceProvider.bpmn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/lib/create-append-anything/create-menu/CreateMenuProvider.js:
--------------------------------------------------------------------------------
1 | import { CREATE_OPTIONS } from '../../util/CreateOptionsUtil';
2 |
3 | /**
4 | * This module is a create menu provider for the popup menu.
5 | */
6 | export default function CreateMenuProvider(
7 | elementFactory, popupMenu, create,
8 | autoPlace, mouse, translate
9 | ) {
10 | this._elementFactory = elementFactory;
11 | this._popupMenu = popupMenu;
12 | this._create = create;
13 | this._autoPlace = autoPlace;
14 | this._mouse = mouse;
15 | this._translate = translate;
16 |
17 | this.register();
18 | }
19 |
20 | CreateMenuProvider.$inject = [
21 | 'elementFactory',
22 | 'popupMenu',
23 | 'create',
24 | 'autoPlace',
25 | 'mouse',
26 | 'translate'
27 | ];
28 |
29 | /**
30 | * Register create menu provider in the popup menu
31 | */
32 | CreateMenuProvider.prototype.register = function() {
33 | this._popupMenu.registerProvider('bpmn-create', this);
34 | };
35 |
36 | /**
37 | * Returns the create options as menu entries
38 | *
39 | * @param {djs.model.Base} element
40 | *
41 | * @return {Array