@bpmn-io/form-js-playground 0.7.2 → 0.8.0-alpha.0

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.
@@ -1,158 +0,0 @@
1
- .fjs-pgl-root {
2
- --color-light-gray: #EEE;
3
- --color-default-gray: #AAA;
4
- --color-dark-gray: #999;
5
- --font-family: 'IBM Plex Sans', sans-serif;
6
- }
7
-
8
- .fjs-pgl-root {
9
- width: 100%;
10
- height: 100%;
11
-
12
- position: relative;
13
-
14
- font-family: var(--font-family);
15
- }
16
-
17
- .fjs-pgl-main {
18
- width: 100%;
19
- height: 100%;
20
-
21
- display: grid;
22
- grid-template-columns: 65% 35%;
23
- grid-template-rows: 70% 30%;
24
- }
25
-
26
- /**
27
- * Section
28
- */
29
- .fjs-pgl-section {
30
- display: flex;
31
- flex-direction: column;
32
- justify-content: stretch;
33
- }
34
-
35
- .fjs-pgl-section:nth-child(1),
36
- .fjs-pgl-section:nth-child(2) {
37
- border-bottom: double 3px var(--color-dark-gray);
38
- }
39
-
40
- .fjs-pgl-section:nth-child(1),
41
- .fjs-pgl-section:nth-child(3) {
42
- border-right: double 3px var(--color-dark-gray);
43
- }
44
-
45
- .fjs-pgl-section .header {
46
- background: var(--color-light-gray);
47
- font-size: 1rem;
48
- margin: 0;
49
- line-height: 2em;
50
- padding: 0 .5em;
51
- border-bottom: solid 1px var(--color-default-gray);
52
- }
53
-
54
- .fjs-pgl-section .header-items {
55
- float: right;
56
- }
57
-
58
- .fjs-pgl-section .body {
59
- flex: 1;
60
- overflow: hidden;
61
- }
62
-
63
- .fjs-pgl-modal {
64
- z-index: 5;
65
- }
66
-
67
- .fjs-pgl-modal .fjs-pgl-modal-backdrop {
68
- background: rgba(0 0 0 / .5);
69
- position: absolute;
70
- top: 0;
71
- left: 0;
72
- bottom: 0;
73
- right: 0;
74
- z-index: 5;
75
- }
76
-
77
- .fjs-pgl-modal-content {
78
- position: absolute;
79
- top: 50%;
80
- left: 50%;
81
- max-width: 100%;
82
- width: 500px;
83
- overflow-y: auto;
84
- max-height: 80%;
85
- transform: translate(-40%, -50%);
86
- z-index: 5;
87
-
88
- font-size: 14px;
89
-
90
- padding: 20px;
91
-
92
- background: white;
93
- }
94
-
95
- .fjs-pgl-modal-content textarea {
96
- width: 100%;
97
- height: 300px;
98
- overflow: auto;
99
- }
100
-
101
- .fjs-pgl-modal-footer {
102
- margin-top: 20px;
103
-
104
- text-align: right;
105
- }
106
-
107
- .fjs-pgl-form-container {
108
- height: 100%;
109
- height: 100%;
110
- overflow: hidden;
111
- }
112
-
113
- .fjs-pgl-text-container {
114
- height: 100%;
115
- width: 100%;
116
- box-sizing: border-box;
117
- border: none;
118
- border-radius: 0;
119
- }
120
-
121
- .fjs-pgl-text-container > .cm-editor {
122
- font-size: .9em;
123
- height: 100%;
124
- }
125
-
126
- .fjs-pgl-form-container > .fjs-container {
127
- overflow: auto;
128
- }
129
-
130
- .fjs-pgl-button {
131
-
132
- color: var(--color-text);
133
- background-color: #fff;
134
-
135
- border-width: 1px;
136
- border-style: solid;
137
- border-radius: 3px;
138
- border-color: var(--color-lighter-gray);
139
-
140
- font-family: var(--font-family);
141
- }
142
-
143
- .fjs-pgl-button-default {
144
- padding: 7px 10px;
145
- }
146
-
147
- .fjs-pgl-button:hover {
148
- background-color: var(--color-light-gray);
149
- }
150
-
151
- .fjs-pgl-button + .fjs-pgl-button {
152
- margin-left: 1em;
153
- }
154
-
155
- .fjs-pgl-parent {
156
- width: 100%;
157
- height: 100%;
158
- }
package/src/Playground.js DELETED
@@ -1,375 +0,0 @@
1
- import JSONView from './JSONView';
2
-
3
- import { render } from 'preact';
4
-
5
- import { useRef, useEffect, useState, useCallback } from 'preact/hooks';
6
-
7
- import fileDrop from 'file-drops';
8
-
9
- import mitt from 'mitt';
10
-
11
- import download from 'downloadjs';
12
-
13
- import {
14
- Form,
15
- FormEditor
16
- } from '@bpmn-io/form-js';
17
-
18
- import './FileDrop.css';
19
- import './Playground.css';
20
-
21
-
22
- function Modal(props) {
23
-
24
- useEffect(() => {
25
- function handleKey(event) {
26
-
27
- if (event.key === 'Escape') {
28
- event.stopPropagation();
29
-
30
- props.onClose();
31
- }
32
- }
33
-
34
- document.addEventListener('keydown', handleKey);
35
-
36
- return () => {
37
- document.removeEventListener('keydown', handleKey);
38
- };
39
- });
40
-
41
- return (
42
- <div class="fjs-pgl-modal">
43
- <div class="fjs-pgl-modal-backdrop" onClick={ props.onClose }></div>
44
- <div class="fjs-pgl-modal-content">
45
- <h1 class="fjs-pgl-modal-header">{ props.name }</h1>
46
- <div class="fjs-pgl-modal-body">
47
- { props.children }
48
- </div>
49
- <div class="fjs-pgl-modal-footer">
50
- <button class="fjs-pgl-button fjs-pgl-button-default" onClick={ props.onClose }>Close</button>
51
- </div>
52
- </div>
53
- </div>
54
- );
55
- }
56
-
57
- function Section(props) {
58
-
59
- const elements =
60
- Array.isArray(props.children)
61
- ? props.children :
62
- [ props.children ];
63
-
64
- const {
65
- headerItems,
66
- children
67
- } = elements.reduce((_, child) => {
68
- const bucket =
69
- child.type === Section.HeaderItem
70
- ? _.headerItems
71
- : _.children;
72
-
73
- bucket.push(child);
74
-
75
- return _;
76
- }, { headerItems: [], children: [] });
77
-
78
- return (
79
- <div class="fjs-pgl-section">
80
- <h1 class="header">{ props.name } { headerItems.length ? <span class="header-items">{ headerItems }</span> : null }</h1>
81
- <div class="body">
82
- { children }
83
- </div>
84
- </div>
85
- );
86
- }
87
-
88
- Section.HeaderItem = function(props) {
89
- return props.children;
90
- };
91
-
92
- function serializeValue(obj) {
93
- return JSON.stringify(JSON.stringify(obj)).replace(/</g, '&lt;').replace(/>/g, '&gt;');
94
- }
95
-
96
- function EmbedModal(props) {
97
-
98
- const schema = serializeValue(props.schema);
99
- const data = serializeValue(props.data || {});
100
-
101
- const fieldRef = useRef();
102
-
103
- const snippet = `<!-- styles needed for rendering -->
104
- <link rel="stylesheet" href="https://unpkg.com/@bpmn-io/form-js@0.2.4/dist/assets/form-js.css">
105
-
106
- <!-- container to render the form into -->
107
- <div class="fjs-pgl-form-container"></div>
108
-
109
- <!-- scripts needed for embedding -->
110
- <script src="https://unpkg.com/@bpmn-io/form-js@0.2.4/dist/form-viewer.umd.js"></script>
111
-
112
- <!-- actual script to instantiate the form and load form schema + data -->
113
- <script>
114
- const data = JSON.parse(${data});
115
- const schema = JSON.parse(${schema});
116
-
117
- const form = new FormViewer.Form({
118
- container: document.querySelector(".fjs-pgl-form-container")
119
- });
120
-
121
- form.on("submit", (event) => {
122
- console.log(event.data, event.errors);
123
- });
124
-
125
- form.importSchema(schema, data).catch(err => {
126
- console.error("Failed to render form", err);
127
- });
128
- </script>
129
- `.trim();
130
-
131
- useEffect(() => {
132
- fieldRef.current.select();
133
- });
134
-
135
- return (
136
- <Modal name="Embed form" onClose={ props.onClose }>
137
- <p>Use the following HTML snippet to embed your form with <a href="https://github.com/bpmn-io/form-js">form-js</a>:</p>
138
-
139
- <textarea spellCheck="false" ref={ fieldRef }>{snippet}</textarea>
140
- </Modal>
141
- );
142
- }
143
-
144
- function PlaygroundRoot(props) {
145
-
146
- const editorContainerRef = useRef();
147
- const formContainerRef = useRef();
148
- const dataContainerRef = useRef();
149
- const resultContainerRef = useRef();
150
-
151
- const formEditorRef = useRef();
152
- const formRef = useRef();
153
- const dataEditorRef = useRef();
154
- const resultViewRef = useRef();
155
-
156
- const [ showEmbed, setShowEmbed ] = useState(false);
157
-
158
- const [ initialData ] = useState(props.data || {});
159
- const [ initialSchema, setInitialSchema ] = useState(props.schema);
160
-
161
- const [ data, setData ] = useState(props.data || {});
162
- const [ schema, setSchema ] = useState(props.schema);
163
-
164
- const [ resultData, setResultData ] = useState(props.data || {});
165
-
166
- useEffect(() => {
167
- props.onInit({
168
- setSchema: setInitialSchema
169
- });
170
- });
171
-
172
- useEffect(() => {
173
- setInitialSchema(props.schema || {});
174
- }, [ props.schema ]);
175
-
176
- useEffect(() => {
177
- const dataEditor = dataEditorRef.current = new JSONView({
178
- value: toJSON(data)
179
- });
180
-
181
- const resultView = resultViewRef.current = new JSONView({
182
- readonly: true,
183
- value: toJSON(resultData)
184
- });
185
-
186
- const form = formRef.current = new Form();
187
- const formEditor = formEditorRef.current = new FormEditor({
188
- renderer: {
189
- compact: true
190
- }
191
- });
192
-
193
- formEditor.on('changed', () => {
194
- setSchema(formEditor.getSchema());
195
- });
196
-
197
- form.on('changed', event => {
198
- setResultData(event.data);
199
- });
200
-
201
- dataEditor.on('changed', event => {
202
- try {
203
- setData(JSON.parse(event.value));
204
- } catch (err) {
205
-
206
- // TODO(nikku): indicate JSON parse error
207
- }
208
- });
209
-
210
- const formContainer = formContainerRef.current;
211
- const editorContainer = editorContainerRef.current;
212
- const dataContainer = dataContainerRef.current;
213
- const resultContainer = resultContainerRef.current;
214
-
215
- dataEditor.attachTo(dataContainer);
216
- resultView.attachTo(resultContainer);
217
- form.attachTo(formContainer);
218
- formEditor.attachTo(editorContainer);
219
-
220
- return () => {
221
- dataEditor.destroy();
222
- resultView.destroy();
223
- form.destroy();
224
- formEditor.destroy();
225
- };
226
- }, []);
227
-
228
- useEffect(() => {
229
- dataEditorRef.current.setValue(toJSON(initialData));
230
- }, [ initialData ]);
231
-
232
- useEffect(() => {
233
- formEditorRef.current.importSchema(initialSchema);
234
- }, [ initialSchema ]);
235
-
236
- useEffect(() => {
237
- formRef.current.importSchema(schema, data);
238
- }, [ schema, data ]);
239
-
240
- useEffect(() => {
241
- resultViewRef.current.setValue(toJSON(resultData));
242
- }, [ resultData ]);
243
-
244
- useEffect(() => {
245
- props.onStateChanged({
246
- schema,
247
- data
248
- });
249
- }, [ schema, data ]);
250
-
251
- const handleDownload = useCallback(() => {
252
-
253
- download(JSON.stringify(schema, null, ' '), 'form.json', 'text/json');
254
- }, [ schema ]);
255
-
256
- const hideEmbedModal = useCallback(() => {
257
- setShowEmbed(false);
258
- }, []);
259
-
260
- const showEmbedModal = useCallback(() => {
261
- setShowEmbed(true);
262
- }, []);
263
-
264
- return (
265
- <div class="fjs-pgl-root">
266
- <div class="fjs-pgl-modals">
267
- { showEmbed ? <EmbedModal schema={ schema } data={ data } onClose={ hideEmbedModal } /> : null }
268
- </div>
269
- <div class="fjs-pgl-main">
270
-
271
- <Section name="Form Definition">
272
- <Section.HeaderItem>
273
- <button
274
- class="fjs-pgl-button"
275
- title="Download form definition"
276
- onClick={ handleDownload }
277
- >Download</button>
278
- </Section.HeaderItem>
279
- <Section.HeaderItem>
280
- <button
281
- class="fjs-pgl-button"
282
- onClick={ showEmbedModal }
283
- >Embed</button>
284
- </Section.HeaderItem>
285
- <div ref={ editorContainerRef } class="fjs-pgl-form-container"></div>
286
- </Section>
287
- <Section name="Form Preview">
288
- <div ref={ formContainerRef } class="fjs-pgl-form-container"></div>
289
- </Section>
290
- <Section name="Form Data (Input)">
291
- <div ref={ dataContainerRef } class="fjs-pgl-text-container"></div>
292
- </Section>
293
- <Section name="Form Data (Submit)">
294
- <div ref={ resultContainerRef } class="fjs-pgl-text-container"></div>
295
- </Section>
296
- </div>
297
- </div>
298
- );
299
- }
300
-
301
-
302
- export default function Playground(options) {
303
-
304
- const {
305
- container: parent,
306
- schema,
307
- data
308
- } = options;
309
-
310
- const emitter = mitt();
311
-
312
- let state = { data, schema };
313
- let ref;
314
-
315
- const container = document.createElement('div');
316
-
317
- container.classList.add('fjs-pgl-parent');
318
-
319
- parent.appendChild(container);
320
-
321
- const handleDrop = fileDrop('Drop a form file', function(files) {
322
- const file = files[0];
323
-
324
- if (file) {
325
- try {
326
- ref.setSchema(JSON.parse(file.contents));
327
- } catch (err) {
328
-
329
- // TODO(nikku): indicate JSON parse error
330
- }
331
- }
332
- });
333
-
334
- container.addEventListener('dragover', handleDrop);
335
-
336
- render(
337
- <PlaygroundRoot
338
- schema={ schema }
339
- data={ data }
340
- onStateChanged={ (_state) => state = _state }
341
- onInit={ _ref => ref = _ref }
342
- />,
343
- container
344
- );
345
-
346
- this.on = emitter.on;
347
- this.off = emitter.off;
348
-
349
- this.emit = emitter.emit;
350
-
351
- this.on('destroy', function() {
352
- render(null, container);
353
- });
354
-
355
- this.on('destroy', function() {
356
- parent.removeChild(container);
357
- });
358
-
359
- this.getState = function() {
360
- return state;
361
- };
362
-
363
- this.setSchema = function(schema) {
364
- return ref.setSchema(schema);
365
- };
366
-
367
- this.destroy = function() {
368
- this.emit('destroy');
369
- };
370
- }
371
-
372
-
373
- function toJSON(obj) {
374
- return JSON.stringify(obj, null, ' ');
375
- }
package/src/index.js DELETED
@@ -1 +0,0 @@
1
- export { default as Playground } from './Playground';
package/test/.eslintrc DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "extends": [
3
- "plugin:bpmn-io/mocha"
4
- ],
5
- "globals": {
6
- "sinon": true
7
- }
8
- }
@@ -1,26 +0,0 @@
1
- import './test.css';
2
-
3
- import '@bpmn-io/form-js/dist/assets/form-js.css';
4
- import '@bpmn-io/form-js/dist/assets/form-js-editor.css';
5
- import '@bpmn-io/form-js/dist/assets/dragula.css';
6
-
7
- export function isSingleStart(topic) {
8
-
9
- // @ts-ignore-next-line
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
- }
@@ -1,9 +0,0 @@
1
- // @ts-ignore-next-line
2
- const allTests = require.context('.', true, /.spec\.js$/);
3
-
4
- allTests.keys().forEach(allTests);
5
-
6
- // @ts-ignore-next-line
7
- const allSources = require.context('../src', true, /.*\.js$/);
8
-
9
- allSources.keys().forEach(allSources);
@@ -1,90 +0,0 @@
1
- import 'preact/debug';
2
-
3
- import {
4
- Playground
5
- } from '../../src';
6
-
7
- import schema from './form.json';
8
- import otherSchema from './other-form.json';
9
-
10
- import {
11
- insertCSS,
12
- isSingleStart
13
- } from '../TestHelper';
14
-
15
- insertCSS('Test.css', `
16
- body, html {
17
- margin: 0;
18
- padding: 0;
19
- height: 100%;
20
- width: 100%;
21
- }
22
- `);
23
-
24
- const singleStart = isSingleStart('basic');
25
-
26
-
27
- describe('playground', function() {
28
-
29
- const container = document.body;
30
-
31
- let playground;
32
-
33
- !singleStart && afterEach(function() {
34
- if (playground) {
35
- playground.destroy();
36
- }
37
- });
38
-
39
-
40
- (singleStart ? it.only : it)('should render', async function() {
41
-
42
- // given
43
- const data = {
44
- creditor: 'John Doe Company',
45
- amount: 456,
46
- invoiceNumber: 'C-123',
47
- approved: true,
48
- approvedBy: 'John Doe',
49
- product: 'camunda-cloud',
50
- language: 'english'
51
- };
52
-
53
- // when
54
- playground = new Playground({
55
- container,
56
- schema,
57
- data
58
- });
59
-
60
- // then
61
- expect(playground).to.exist;
62
-
63
- expect(playground.getState()).to.eql({
64
- schema,
65
- data
66
- });
67
-
68
- });
69
-
70
-
71
- it.skip('should set schema', function() {
72
-
73
- // given
74
- const playground = new Playground({
75
- container,
76
- schema
77
- });
78
-
79
- // when
80
- playground.setSchema(otherSchema);
81
-
82
- // then
83
- expect(playground.getState()).to.eql({
84
- schema: otherSchema,
85
- data: {}
86
- });
87
-
88
- });
89
-
90
- });