@bpmn-io/form-js-playground 0.7.2 → 0.8.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.
- package/LICENSE +22 -22
- package/README.md +15 -5
- package/dist/assets/form-js-playground.css +250 -189
- package/dist/form-playground.umd.js +36542 -30408
- package/dist/index.cjs +204 -116
- package/dist/index.cjs.map +1 -1
- package/dist/index.es.js +197 -110
- package/dist/index.es.js.map +1 -1
- package/dist/types/Playground.d.ts +64 -0
- package/dist/types/components/EmbedModal.d.ts +1 -0
- package/dist/types/components/JSONEditor.d.ts +16 -0
- package/dist/types/components/Modal.d.ts +1 -0
- package/dist/types/components/PlaygroundRoot.d.ts +1 -0
- package/dist/types/components/Section.d.ts +4 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +24 -9
- package/karma.conf.js +0 -100
- package/resources/screenshot.png +0 -0
- package/rollup.config.js +0 -60
- package/src/FileDrop.css +0 -33
- package/src/JSONView.js +0 -78
- package/src/Playground.css +0 -158
- package/src/Playground.js +0 -375
- package/src/index.js +0 -1
- package/test/.eslintrc +0 -8
- package/test/TestHelper.js +0 -26
- package/test/coverageBundle.js +0 -9
- package/test/spec/Playground.spec.js +0 -90
- package/test/spec/form.json +0 -86
- package/test/spec/other-form.json +0 -11
- package/test/test.css +0 -9
- package/test/testBundle.js +0 -4
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, '<').replace(/>/g, '>');
|
|
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
package/test/TestHelper.js
DELETED
|
@@ -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
|
-
}
|
package/test/coverageBundle.js
DELETED
|
@@ -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
|
-
});
|
package/test/spec/form.json
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"components": [
|
|
3
|
-
{
|
|
4
|
-
"type": "text",
|
|
5
|
-
"text": "# Invoice\nLorem _ipsum_ __dolor__ `sit`.\n \n \nA list of BPMN symbols:\n* Start Event\n* Task\nLearn more about [forms](https://bpmn.io).\n \n \nThis [malicious link](javascript:throw onerror=alert,'some string',123,'haha') __should not work__."
|
|
6
|
-
},
|
|
7
|
-
{
|
|
8
|
-
"key": "creditor",
|
|
9
|
-
"label": "Creditor",
|
|
10
|
-
"type": "textfield",
|
|
11
|
-
"validate": {
|
|
12
|
-
"required": true
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"description": "An invoice number in the format: C-123.",
|
|
17
|
-
"key": "invoiceNumber",
|
|
18
|
-
"label": "Invoice Number",
|
|
19
|
-
"type": "textfield",
|
|
20
|
-
"validate": {
|
|
21
|
-
"pattern": "^C-[0-9]+$"
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
"key": "amount",
|
|
26
|
-
"label": "Amount",
|
|
27
|
-
"type": "number",
|
|
28
|
-
"validate": {
|
|
29
|
-
"min": 0,
|
|
30
|
-
"max": 1000
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
"key": "approved",
|
|
35
|
-
"label": "Approved",
|
|
36
|
-
"type": "checkbox"
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
"key": "approvedBy",
|
|
40
|
-
"label": "Approved By",
|
|
41
|
-
"type": "textfield"
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
"key": "product",
|
|
45
|
-
"label": "Product",
|
|
46
|
-
"type": "radio",
|
|
47
|
-
"values": [
|
|
48
|
-
{
|
|
49
|
-
"label": "Camunda Platform",
|
|
50
|
-
"value": "camunda-platform"
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
"label": "Camunda Cloud",
|
|
54
|
-
"value": "camunda-cloud"
|
|
55
|
-
}
|
|
56
|
-
]
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
"key": "language",
|
|
60
|
-
"label": "Language",
|
|
61
|
-
"type": "select",
|
|
62
|
-
"values": [
|
|
63
|
-
{
|
|
64
|
-
"label": "German",
|
|
65
|
-
"value": "german"
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
"label": "English",
|
|
69
|
-
"value": "english"
|
|
70
|
-
}
|
|
71
|
-
]
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
"key": "submit",
|
|
75
|
-
"label": "Submit",
|
|
76
|
-
"type": "button"
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
"action": "reset",
|
|
80
|
-
"key": "reset",
|
|
81
|
-
"label": "Reset",
|
|
82
|
-
"type": "button"
|
|
83
|
-
}
|
|
84
|
-
],
|
|
85
|
-
"type": "default"
|
|
86
|
-
}
|
package/test/test.css
DELETED
package/test/testBundle.js
DELETED