@itfin/components 1.3.21 → 1.3.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,187 @@
1
+ import './bpmn.scss';
2
+ import cloneDeep from 'lodash/cloneDeep';
3
+ import 'bpmn-js/dist/assets/bpmn-js.css';
4
+ import 'bpmn-js/dist/assets/diagram-js.css';
5
+ import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';
6
+
7
+ const icon = '<svg height="24" width="24" viewBox="0 0 2048 2048" xmlns="http://www.w3.org/2000/svg"><path d="m96-593.63783v1280h1856v-1280zm1756 97.69925v1091.54297h-1372v-1091.54103l1372-.002zm-1660 .002 192-.00021v1091.54108l-192 .00021z" transform="translate(0 995.63783)"/></svg>';
8
+ const xml = '<?xml version="1.0" encoding="UTF-8"?>\n' +
9
+ '<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn">\n' +
10
+ ' <bpmn2:process id="Process_1" isExecutable="false">\n' +
11
+ ' <bpmn2:startEvent id="StartEvent_1"/>\n' +
12
+ ' </bpmn2:process>\n' +
13
+ ' <bpmndi:BPMNDiagram id="BPMNDiagram_1">\n' +
14
+ ' <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">\n' +
15
+ ' <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">\n' +
16
+ ' <dc:Bounds height="36.0" width="36.0" x="412.0" y="240.0"/>\n' +
17
+ ' </bpmndi:BPMNShape>\n' +
18
+ ' </bpmndi:BPMNPlane>\n' +
19
+ ' </bpmndi:BPMNDiagram>\n' +
20
+ '</bpmn2:definitions>';
21
+
22
+ export default class Bpmn {
23
+ data = null;
24
+ readOnly = false;
25
+
26
+ static get sanitize(){
27
+ return {
28
+ svg: true,
29
+ files: true,
30
+ caption: {} // only tags from Inline Toolbar
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Allow to use this tool in read only mode
36
+ */
37
+ static get isReadOnlySupported() {
38
+ return true;
39
+ }
40
+
41
+ constructor({ data, readOnly }){
42
+ this.data = data;
43
+ this.readOnly = readOnly;
44
+ }
45
+
46
+ static get toolbox() {
47
+ return {
48
+ title: 'BPMN',
49
+ icon
50
+ };
51
+ }
52
+
53
+ render(){
54
+ const wrapper = createWrapper(this.data, this.readOnly);
55
+ if (!this.readOnly) {
56
+ wrapper.classList.remove('readonly');
57
+ wrapper.addEventListener('dblclick', async () => {
58
+ const modal = document.createElement('div');
59
+ modal.classList.add('itf-modal');
60
+ modal.classList.add('modal');
61
+ modal.classList.add('fade');
62
+ modal.classList.add('editorjs-bpmn-modal');
63
+ const modalDialog = document.createElement('div');
64
+ modalDialog.classList.add('modal-dialog');
65
+ modalDialog.classList.add('modal-fullscreen');
66
+ const modalContent = document.createElement('div');
67
+ modalContent.classList.add('modal-content');
68
+ const modalHeader = document.createElement('div');
69
+ modalHeader.classList.add('modal-header');
70
+ const modalTitle = document.createElement('h5');
71
+ modalTitle.classList.add('modal-title');
72
+ modalTitle.textContent = 'BPMN Editor';
73
+ modalHeader.appendChild(modalTitle);
74
+ const btnHolder = document.createElement('div');
75
+ btnHolder.classList.add('d-flex');
76
+ const modalSaveBtn = document.createElement('button');
77
+ modalSaveBtn.classList.add('btn');
78
+ modalSaveBtn.classList.add('btn-primary');
79
+ modalSaveBtn.classList.add('itf-button');
80
+ modalSaveBtn.textContent = 'Save & Close';
81
+ const modalCancelBtn = document.createElement('button');
82
+ modalCancelBtn.classList.add('btn');
83
+ modalCancelBtn.classList.add('btn-secondary');
84
+ modalCancelBtn.classList.add('itf-button');
85
+ modalCancelBtn.classList.add('me-2');
86
+ modalCancelBtn.textContent = 'Cancel';
87
+ btnHolder.appendChild(modalCancelBtn);
88
+ btnHolder.appendChild(modalSaveBtn);
89
+ modalHeader.appendChild(modalTitle);
90
+ modalHeader.appendChild(btnHolder);
91
+ modalContent.appendChild(modalHeader);
92
+ const modalBody = document.createElement('div');
93
+ modalBody.classList.add('modal-body');
94
+ const frame = document.createElement('div');
95
+ modalBody.appendChild(frame);
96
+ modalContent.appendChild(modalBody);
97
+ modalDialog.appendChild(modalContent);
98
+ modal.appendChild(modalDialog);
99
+ document.body.appendChild(modal);
100
+ const {default: Modal} = await import('../../../modal/modalSrc');
101
+ const modalEl = new Modal(modal, {context: document.body, backdrop: 'static'});
102
+ modalEl.show();
103
+ modal.addEventListener('hidden.bs.modal', () => {
104
+ document.body.removeChild(modal);
105
+ });
106
+
107
+ frame.classList.add('modal-body-content');
108
+
109
+ let modeler;
110
+ setTimeout(async () => {
111
+ const { default: BpmnModeler } = await import('bpmn-js/dist/bpmn-modeler.production.min');
112
+ modeler = new BpmnModeler({
113
+ container: frame,
114
+ keyboard: {
115
+ bindTo: window
116
+ }
117
+ });
118
+
119
+ try {
120
+ await modeler.importXML(this.data?.xml || xml);
121
+ } catch (err) {
122
+ console.error('error loading BPMN 2.0 XML', err);
123
+ }
124
+ }, 500)
125
+
126
+ modalSaveBtn.addEventListener('click', async () => {
127
+ this.data = {
128
+ svg: (await modeler.saveSVG())?.svg,
129
+ xml: (await modeler.saveXML({ format: true }))?.xml
130
+ };
131
+ if (this.data.svg) {
132
+ createSvg(wrapper, this.data, this.readOnly);
133
+ }
134
+ modalEl.hide();
135
+ });
136
+ modalCancelBtn.addEventListener('click', () => {
137
+ modalEl.hide();
138
+ });
139
+ });
140
+ } else {
141
+ wrapper.classList.add('readonly');
142
+ }
143
+ return wrapper;
144
+
145
+ function createWrapper(data, readOnly) {
146
+ const wrapper = document.createElement('div');
147
+ wrapper.classList.add('editorjs-bpmn');
148
+ if (data.svg) {
149
+ wrapper.classList.remove('empty');
150
+ createSvg(wrapper, data, readOnly);
151
+ } else if (!readOnly) {
152
+ wrapper.classList.add('empty');
153
+ wrapper.innerHTML = `<div class="text-muted icon me-2">${icon}</div><div class="text-muted text">Double click to start diagramming your business processes.</div>`;
154
+ }
155
+ return wrapper;
156
+ }
157
+
158
+ function createSvg(wrapper, { svg, caption }, readOnly) {
159
+ const svgContainer = document.createElement('div');
160
+ svgContainer.innerHTML = svg;
161
+
162
+ const divSvg = document.createElement('div');
163
+ wrapper.innerHTML = '';
164
+ wrapper.classList.remove('empty');
165
+ wrapper.appendChild(divSvg);
166
+ divSvg.appendChild(svgContainer);
167
+
168
+ const captionEl = document.createElement('div');
169
+ captionEl.contentEditable = !readOnly;
170
+ captionEl.classList.add('editorjs-bpmn-caption');
171
+ captionEl.textContent = caption;
172
+ if (!readOnly) {
173
+ captionEl.setAttribute('data-text', 'Caption');
174
+ captionEl.addEventListener('dblclick', (e) => {
175
+ e.stopPropagation();
176
+ });
177
+ }
178
+ wrapper.appendChild(captionEl);
179
+ }
180
+ }
181
+ save(blockContent){
182
+ const caption = blockContent.querySelector('[contenteditable]');
183
+ const data = cloneDeep(this.data);
184
+ data.caption = caption ? caption.innerHTML : '';
185
+ return data;
186
+ }
187
+ }
@@ -0,0 +1,63 @@
1
+ .editorjs-bpmn {
2
+ --editorjs-drawing-border: #dcdfe6;
3
+
4
+ &.empty {
5
+ border: 1px dashed var(--editorjs-drawing-border);
6
+ min-height: 150px;
7
+ display: flex;
8
+ align-items: center;
9
+ justify-content: center;
10
+ }
11
+ position: relative;
12
+ z-index: 0;
13
+ margin-bottom: 10px;
14
+ border-radius: 5px;
15
+ height: max-content !important;
16
+
17
+ &:not(.readonly) {
18
+ cursor: pointer;
19
+
20
+ &:hover {
21
+ outline: 3px solid var(--editorjs-drawing-border);
22
+ }
23
+ }
24
+
25
+ .editorjs-bpmn-caption {
26
+ margin-top: 1rem;
27
+ text-align: center;
28
+ &:empty:not(:focus):before {
29
+ content: attr(data-text);
30
+ opacity: .5;
31
+ }
32
+ }
33
+ svg {
34
+ width: 100%;
35
+ height: auto;
36
+ user-select: none;
37
+ pointer-events: none;
38
+ }
39
+ .icon {
40
+ width: 48px;
41
+ height: 48px;
42
+
43
+ path {
44
+ fill: currentColor;
45
+ stroke: none;
46
+ }
47
+ }
48
+ .text {
49
+
50
+ }
51
+ }
52
+
53
+ .editorjs-bpmn-modal .modal-body {
54
+ padding: 0;
55
+ display: flex;
56
+ }
57
+ .editorjs-bpmn-modal .modal-body-content {
58
+ flex: 1;
59
+ display: flex;
60
+ flex-direction: column;
61
+ justify-content: center;
62
+ align-items: center;
63
+ }
@@ -130,7 +130,7 @@ export default class Drawing {
130
130
 
131
131
  function createSvg(wrapper, { svg, caption }, readOnly) {
132
132
  const svgContainer = document.createElement('div');
133
- svgContainer.innerHTML = svg.replace('@undefined', '@0.16.1'); // глючить версія в excalidraw
133
+ svgContainer.innerHTML = svg.replace(/@undefined/g, '@0.16.1'); // глючить версія в excalidraw
134
134
 
135
135
  const divSvg = document.createElement('div');
136
136
  wrapper.innerHTML = '';