@bpmn-io/form-js-viewer 0.9.8 → 0.10.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.
- package/README.md +6 -0
- package/dist/assets/form-js.css +13 -5
- package/dist/index.cjs +318 -427
- package/dist/index.cjs.map +1 -1
- package/dist/index.es.js +317 -427
- package/dist/index.es.js.map +1 -1
- package/dist/types/Form.d.ts +140 -136
- package/dist/types/core/EventBus.d.ts +1 -1
- package/dist/types/core/FormFieldRegistry.d.ts +17 -17
- package/dist/types/core/Validator.d.ts +7 -7
- package/dist/types/core/index.d.ts +16 -16
- package/dist/types/import/Importer.d.ts +43 -43
- package/dist/types/import/index.d.ts +5 -5
- package/dist/types/index.d.ts +18 -18
- package/dist/types/render/FormFields.d.ts +5 -5
- package/dist/types/render/Renderer.d.ts +23 -23
- package/dist/types/render/components/Description.d.ts +1 -1
- package/dist/types/render/components/Errors.d.ts +1 -1
- package/dist/types/render/components/FormComponent.d.ts +1 -1
- package/dist/types/render/components/FormField.d.ts +1 -1
- package/dist/types/render/components/Label.d.ts +1 -1
- package/dist/types/render/components/PoweredBy.d.ts +1 -1
- package/dist/types/render/components/Sanitizer.d.ts +7 -7
- package/dist/types/render/components/Util.d.ts +9 -6
- package/dist/types/render/components/form-fields/Button.d.ts +11 -11
- package/dist/types/render/components/form-fields/Checkbox.d.ts +13 -13
- package/dist/types/render/components/form-fields/Checklist.d.ts +12 -12
- package/dist/types/render/components/form-fields/Default.d.ts +9 -9
- package/dist/types/render/components/form-fields/Number.d.ts +13 -13
- package/dist/types/render/components/form-fields/Radio.d.ts +12 -12
- package/dist/types/render/components/form-fields/Select.d.ts +12 -12
- package/dist/types/render/components/form-fields/Taglist.d.ts +12 -12
- package/dist/types/render/components/form-fields/Text.d.ts +10 -10
- package/dist/types/render/components/form-fields/Textarea.d.ts +13 -0
- package/dist/types/render/components/form-fields/Textfield.d.ts +13 -13
- package/dist/types/render/components/form-fields/parts/DropdownList.d.ts +1 -1
- package/dist/types/render/components/index.d.ts +14 -13
- package/dist/types/render/context/FormContext.d.ts +12 -12
- package/dist/types/render/context/FormRenderContext.d.ts +6 -6
- package/dist/types/render/context/index.d.ts +2 -2
- package/dist/types/render/hooks/useKeyDownAction.d.ts +1 -1
- package/dist/types/render/hooks/useService.d.ts +1 -1
- package/dist/types/render/hooks/useValuesAsync.d.ts +28 -28
- package/dist/types/render/index.d.ts +11 -11
- package/dist/types/util/form.d.ts +6 -6
- package/dist/types/util/index.d.ts +24 -24
- package/dist/types/util/injector.d.ts +2 -2
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -5,11 +5,11 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var Ids = require('ids');
|
|
6
6
|
var minDash = require('min-dash');
|
|
7
7
|
var snarkdown = require('@bpmn-io/snarkdown');
|
|
8
|
+
var classNames = require('classnames');
|
|
8
9
|
var jsxRuntime = require('preact/jsx-runtime');
|
|
9
10
|
var hooks = require('preact/hooks');
|
|
10
11
|
var preact = require('preact');
|
|
11
12
|
var React = require('preact/compat');
|
|
12
|
-
var classNames = require('classnames');
|
|
13
13
|
var Markup = require('preact-markup');
|
|
14
14
|
var didi = require('didi');
|
|
15
15
|
|
|
@@ -17,13 +17,14 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
|
|
|
17
17
|
|
|
18
18
|
var Ids__default = /*#__PURE__*/_interopDefaultLegacy(Ids);
|
|
19
19
|
var snarkdown__default = /*#__PURE__*/_interopDefaultLegacy(snarkdown);
|
|
20
|
-
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
21
20
|
var classNames__default = /*#__PURE__*/_interopDefaultLegacy(classNames);
|
|
21
|
+
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
22
22
|
var Markup__default = /*#__PURE__*/_interopDefaultLegacy(Markup);
|
|
23
23
|
|
|
24
24
|
var FN_REF = '__fn';
|
|
25
25
|
var DEFAULT_PRIORITY = 1000;
|
|
26
26
|
var slice = Array.prototype.slice;
|
|
27
|
+
|
|
27
28
|
/**
|
|
28
29
|
* A general purpose event bus.
|
|
29
30
|
*
|
|
@@ -107,13 +108,14 @@ var slice = Array.prototype.slice;
|
|
|
107
108
|
* console.log(sum); // 3
|
|
108
109
|
* ```
|
|
109
110
|
*/
|
|
110
|
-
|
|
111
111
|
function EventBus() {
|
|
112
|
-
this._listeners = {};
|
|
113
|
-
// message passing until the bitter end
|
|
112
|
+
this._listeners = {};
|
|
114
113
|
|
|
114
|
+
// cleanup on destroy on lowest priority to allow
|
|
115
|
+
// message passing until the bitter end
|
|
115
116
|
this.on('diagram.destroy', 1, this._destroy, this);
|
|
116
117
|
}
|
|
118
|
+
|
|
117
119
|
/**
|
|
118
120
|
* Register an event listener for events with the given name.
|
|
119
121
|
*
|
|
@@ -131,30 +133,25 @@ function EventBus() {
|
|
|
131
133
|
* @param {Function} callback
|
|
132
134
|
* @param {Object} [that] Pass context (`this`) to the callback
|
|
133
135
|
*/
|
|
134
|
-
|
|
135
136
|
EventBus.prototype.on = function (events, priority, callback, that) {
|
|
136
137
|
events = minDash.isArray(events) ? events : [events];
|
|
137
|
-
|
|
138
138
|
if (minDash.isFunction(priority)) {
|
|
139
139
|
that = callback;
|
|
140
140
|
callback = priority;
|
|
141
141
|
priority = DEFAULT_PRIORITY;
|
|
142
142
|
}
|
|
143
|
-
|
|
144
143
|
if (!minDash.isNumber(priority)) {
|
|
145
144
|
throw new Error('priority must be a number');
|
|
146
145
|
}
|
|
147
|
-
|
|
148
146
|
var actualCallback = callback;
|
|
149
|
-
|
|
150
147
|
if (that) {
|
|
151
|
-
actualCallback = minDash.bind(callback, that);
|
|
148
|
+
actualCallback = minDash.bind(callback, that);
|
|
149
|
+
|
|
150
|
+
// make sure we remember and are able to remove
|
|
152
151
|
// bound callbacks via {@link #off} using the original
|
|
153
152
|
// callback
|
|
154
|
-
|
|
155
153
|
actualCallback[FN_REF] = callback[FN_REF] || callback;
|
|
156
154
|
}
|
|
157
|
-
|
|
158
155
|
var self = this;
|
|
159
156
|
events.forEach(function (e) {
|
|
160
157
|
self._addListener(e, {
|
|
@@ -164,6 +161,7 @@ EventBus.prototype.on = function (events, priority, callback, that) {
|
|
|
164
161
|
});
|
|
165
162
|
});
|
|
166
163
|
};
|
|
164
|
+
|
|
167
165
|
/**
|
|
168
166
|
* Register an event listener that is executed only once.
|
|
169
167
|
*
|
|
@@ -172,34 +170,30 @@ EventBus.prototype.on = function (events, priority, callback, that) {
|
|
|
172
170
|
* @param {Function} callback the callback to execute
|
|
173
171
|
* @param {Object} [that] Pass context (`this`) to the callback
|
|
174
172
|
*/
|
|
175
|
-
|
|
176
|
-
|
|
177
173
|
EventBus.prototype.once = function (event, priority, callback, that) {
|
|
178
174
|
var self = this;
|
|
179
|
-
|
|
180
175
|
if (minDash.isFunction(priority)) {
|
|
181
176
|
that = callback;
|
|
182
177
|
callback = priority;
|
|
183
178
|
priority = DEFAULT_PRIORITY;
|
|
184
179
|
}
|
|
185
|
-
|
|
186
180
|
if (!minDash.isNumber(priority)) {
|
|
187
181
|
throw new Error('priority must be a number');
|
|
188
182
|
}
|
|
189
|
-
|
|
190
183
|
function wrappedCallback() {
|
|
191
184
|
wrappedCallback.__isTomb = true;
|
|
192
185
|
var result = callback.apply(that, arguments);
|
|
193
186
|
self.off(event, wrappedCallback);
|
|
194
187
|
return result;
|
|
195
|
-
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// make sure we remember and are able to remove
|
|
196
191
|
// bound callbacks via {@link #off} using the original
|
|
197
192
|
// callback
|
|
198
|
-
|
|
199
|
-
|
|
200
193
|
wrappedCallback[FN_REF] = callback;
|
|
201
194
|
this.on(event, priority, wrappedCallback);
|
|
202
195
|
};
|
|
196
|
+
|
|
203
197
|
/**
|
|
204
198
|
* Removes event listeners by event and callback.
|
|
205
199
|
*
|
|
@@ -208,8 +202,6 @@ EventBus.prototype.once = function (event, priority, callback, that) {
|
|
|
208
202
|
* @param {string|Array<string>} events
|
|
209
203
|
* @param {Function} [callback]
|
|
210
204
|
*/
|
|
211
|
-
|
|
212
|
-
|
|
213
205
|
EventBus.prototype.off = function (events, callback) {
|
|
214
206
|
events = minDash.isArray(events) ? events : [events];
|
|
215
207
|
var self = this;
|
|
@@ -217,6 +209,7 @@ EventBus.prototype.off = function (events, callback) {
|
|
|
217
209
|
self._removeListener(event, callback);
|
|
218
210
|
});
|
|
219
211
|
};
|
|
212
|
+
|
|
220
213
|
/**
|
|
221
214
|
* Create an EventBus event.
|
|
222
215
|
*
|
|
@@ -224,13 +217,12 @@ EventBus.prototype.off = function (events, callback) {
|
|
|
224
217
|
*
|
|
225
218
|
* @return {Object} event, recognized by the eventBus
|
|
226
219
|
*/
|
|
227
|
-
|
|
228
|
-
|
|
229
220
|
EventBus.prototype.createEvent = function (data) {
|
|
230
221
|
var event = new InternalEvent();
|
|
231
222
|
event.init(data);
|
|
232
223
|
return event;
|
|
233
224
|
};
|
|
225
|
+
|
|
234
226
|
/**
|
|
235
227
|
* Fires a named event.
|
|
236
228
|
*
|
|
@@ -261,45 +253,40 @@ EventBus.prototype.createEvent = function (data) {
|
|
|
261
253
|
* @return {boolean} the events return value, if specified or false if the
|
|
262
254
|
* default action was prevented by listeners
|
|
263
255
|
*/
|
|
264
|
-
|
|
265
|
-
|
|
266
256
|
EventBus.prototype.fire = function (type, data) {
|
|
267
257
|
var event, firstListener, returnValue, args;
|
|
268
258
|
args = slice.call(arguments);
|
|
269
|
-
|
|
270
259
|
if (typeof type === 'object') {
|
|
271
260
|
data = type;
|
|
272
261
|
type = data.type;
|
|
273
262
|
}
|
|
274
|
-
|
|
275
263
|
if (!type) {
|
|
276
264
|
throw new Error('no event type specified');
|
|
277
265
|
}
|
|
278
|
-
|
|
279
266
|
firstListener = this._listeners[type];
|
|
280
|
-
|
|
281
267
|
if (!firstListener) {
|
|
282
268
|
return;
|
|
283
|
-
}
|
|
284
|
-
// events here. We wrap them only once, though
|
|
285
|
-
|
|
269
|
+
}
|
|
286
270
|
|
|
271
|
+
// we make sure we fire instances of our home made
|
|
272
|
+
// events here. We wrap them only once, though
|
|
287
273
|
if (data instanceof InternalEvent) {
|
|
288
274
|
// we are fine, we alread have an event
|
|
289
275
|
event = data;
|
|
290
276
|
} else {
|
|
291
277
|
event = this.createEvent(data);
|
|
292
|
-
}
|
|
293
|
-
|
|
278
|
+
}
|
|
294
279
|
|
|
295
|
-
|
|
280
|
+
// ensure we pass the event as the first parameter
|
|
281
|
+
args[0] = event;
|
|
296
282
|
|
|
297
|
-
|
|
283
|
+
// original event type (in case we delegate)
|
|
284
|
+
var originalType = event.type;
|
|
298
285
|
|
|
286
|
+
// update event type before delegation
|
|
299
287
|
if (type !== originalType) {
|
|
300
288
|
event.type = type;
|
|
301
289
|
}
|
|
302
|
-
|
|
303
290
|
try {
|
|
304
291
|
returnValue = this._invokeListeners(event, args, firstListener);
|
|
305
292
|
} finally {
|
|
@@ -307,60 +294,51 @@ EventBus.prototype.fire = function (type, data) {
|
|
|
307
294
|
if (type !== originalType) {
|
|
308
295
|
event.type = originalType;
|
|
309
296
|
}
|
|
310
|
-
}
|
|
311
|
-
// got prevented and no other return value exists
|
|
312
|
-
|
|
297
|
+
}
|
|
313
298
|
|
|
299
|
+
// set the return value to false if the event default
|
|
300
|
+
// got prevented and no other return value exists
|
|
314
301
|
if (returnValue === undefined && event.defaultPrevented) {
|
|
315
302
|
returnValue = false;
|
|
316
303
|
}
|
|
317
|
-
|
|
318
304
|
return returnValue;
|
|
319
305
|
};
|
|
320
|
-
|
|
321
306
|
EventBus.prototype.handleError = function (error) {
|
|
322
307
|
return this.fire('error', {
|
|
323
308
|
error: error
|
|
324
309
|
}) === false;
|
|
325
310
|
};
|
|
326
|
-
|
|
327
311
|
EventBus.prototype._destroy = function () {
|
|
328
312
|
this._listeners = {};
|
|
329
313
|
};
|
|
330
|
-
|
|
331
314
|
EventBus.prototype._invokeListeners = function (event, args, listener) {
|
|
332
315
|
var returnValue;
|
|
333
|
-
|
|
334
316
|
while (listener) {
|
|
335
317
|
// handle stopped propagation
|
|
336
318
|
if (event.cancelBubble) {
|
|
337
319
|
break;
|
|
338
320
|
}
|
|
339
|
-
|
|
340
321
|
returnValue = this._invokeListener(event, args, listener);
|
|
341
322
|
listener = listener.next;
|
|
342
323
|
}
|
|
343
|
-
|
|
344
324
|
return returnValue;
|
|
345
325
|
};
|
|
346
|
-
|
|
347
326
|
EventBus.prototype._invokeListener = function (event, args, listener) {
|
|
348
327
|
var returnValue;
|
|
349
|
-
|
|
350
328
|
if (listener.callback.__isTomb) {
|
|
351
329
|
return returnValue;
|
|
352
330
|
}
|
|
353
|
-
|
|
354
331
|
try {
|
|
355
332
|
// returning false prevents the default action
|
|
356
|
-
returnValue = invokeFunction(listener.callback, args);
|
|
333
|
+
returnValue = invokeFunction(listener.callback, args);
|
|
357
334
|
|
|
335
|
+
// stop propagation on return value
|
|
358
336
|
if (returnValue !== undefined) {
|
|
359
337
|
event.returnValue = returnValue;
|
|
360
338
|
event.stopPropagation();
|
|
361
|
-
}
|
|
362
|
-
|
|
339
|
+
}
|
|
363
340
|
|
|
341
|
+
// prevent default on return false
|
|
364
342
|
if (returnValue === false) {
|
|
365
343
|
event.preventDefault();
|
|
366
344
|
}
|
|
@@ -370,9 +348,9 @@ EventBus.prototype._invokeListener = function (event, args, listener) {
|
|
|
370
348
|
throw error;
|
|
371
349
|
}
|
|
372
350
|
}
|
|
373
|
-
|
|
374
351
|
return returnValue;
|
|
375
352
|
};
|
|
353
|
+
|
|
376
354
|
/*
|
|
377
355
|
* Add new listener with a certain priority to the list
|
|
378
356
|
* of listeners (for the given event).
|
|
@@ -389,67 +367,54 @@ EventBus.prototype._invokeListener = function (event, args, listener) {
|
|
|
389
367
|
* @param {string} event
|
|
390
368
|
* @param {Object} listener { priority, callback }
|
|
391
369
|
*/
|
|
392
|
-
|
|
393
|
-
|
|
394
370
|
EventBus.prototype._addListener = function (event, newListener) {
|
|
395
371
|
var listener = this._getListeners(event),
|
|
396
|
-
|
|
397
|
-
|
|
372
|
+
previousListener;
|
|
398
373
|
|
|
374
|
+
// no prior listeners
|
|
399
375
|
if (!listener) {
|
|
400
376
|
this._setListeners(event, newListener);
|
|
401
|
-
|
|
402
377
|
return;
|
|
403
|
-
}
|
|
404
|
-
// 0 (high) to n > 0 (low)
|
|
405
|
-
|
|
378
|
+
}
|
|
406
379
|
|
|
380
|
+
// ensure we order listeners by priority from
|
|
381
|
+
// 0 (high) to n > 0 (low)
|
|
407
382
|
while (listener) {
|
|
408
383
|
if (listener.priority < newListener.priority) {
|
|
409
384
|
newListener.next = listener;
|
|
410
|
-
|
|
411
385
|
if (previousListener) {
|
|
412
386
|
previousListener.next = newListener;
|
|
413
387
|
} else {
|
|
414
388
|
this._setListeners(event, newListener);
|
|
415
389
|
}
|
|
416
|
-
|
|
417
390
|
return;
|
|
418
391
|
}
|
|
419
|
-
|
|
420
392
|
previousListener = listener;
|
|
421
393
|
listener = listener.next;
|
|
422
|
-
}
|
|
423
|
-
|
|
394
|
+
}
|
|
424
395
|
|
|
396
|
+
// add new listener to back
|
|
425
397
|
previousListener.next = newListener;
|
|
426
398
|
};
|
|
427
|
-
|
|
428
399
|
EventBus.prototype._getListeners = function (name) {
|
|
429
400
|
return this._listeners[name];
|
|
430
401
|
};
|
|
431
|
-
|
|
432
402
|
EventBus.prototype._setListeners = function (name, listener) {
|
|
433
403
|
this._listeners[name] = listener;
|
|
434
404
|
};
|
|
435
|
-
|
|
436
405
|
EventBus.prototype._removeListener = function (event, callback) {
|
|
437
406
|
var listener = this._getListeners(event),
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
407
|
+
nextListener,
|
|
408
|
+
previousListener,
|
|
409
|
+
listenerCallback;
|
|
442
410
|
if (!callback) {
|
|
443
411
|
// clear listeners
|
|
444
412
|
this._setListeners(event, null);
|
|
445
|
-
|
|
446
413
|
return;
|
|
447
414
|
}
|
|
448
|
-
|
|
449
415
|
while (listener) {
|
|
450
416
|
nextListener = listener.next;
|
|
451
417
|
listenerCallback = listener.callback;
|
|
452
|
-
|
|
453
418
|
if (listenerCallback === callback || listenerCallback[FN_REF] === callback) {
|
|
454
419
|
if (previousListener) {
|
|
455
420
|
previousListener.next = nextListener;
|
|
@@ -458,29 +423,25 @@ EventBus.prototype._removeListener = function (event, callback) {
|
|
|
458
423
|
this._setListeners(event, nextListener);
|
|
459
424
|
}
|
|
460
425
|
}
|
|
461
|
-
|
|
462
426
|
previousListener = listener;
|
|
463
427
|
listener = nextListener;
|
|
464
428
|
}
|
|
465
429
|
};
|
|
430
|
+
|
|
466
431
|
/**
|
|
467
432
|
* A event that is emitted via the event bus.
|
|
468
433
|
*/
|
|
469
|
-
|
|
470
|
-
|
|
471
434
|
function InternalEvent() {}
|
|
472
|
-
|
|
473
435
|
InternalEvent.prototype.stopPropagation = function () {
|
|
474
436
|
this.cancelBubble = true;
|
|
475
437
|
};
|
|
476
|
-
|
|
477
438
|
InternalEvent.prototype.preventDefault = function () {
|
|
478
439
|
this.defaultPrevented = true;
|
|
479
440
|
};
|
|
480
|
-
|
|
481
441
|
InternalEvent.prototype.init = function (data) {
|
|
482
442
|
minDash.assign(this, data || {});
|
|
483
443
|
};
|
|
444
|
+
|
|
484
445
|
/**
|
|
485
446
|
* Invoke function. Be fast...
|
|
486
447
|
*
|
|
@@ -489,50 +450,47 @@ InternalEvent.prototype.init = function (data) {
|
|
|
489
450
|
*
|
|
490
451
|
* @return {Any}
|
|
491
452
|
*/
|
|
492
|
-
|
|
493
|
-
|
|
494
453
|
function invokeFunction(fn, args) {
|
|
495
454
|
return fn.apply(null, args);
|
|
496
455
|
}
|
|
497
456
|
|
|
457
|
+
const EMAIL_PATTERN = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
|
458
|
+
const PHONE_PATTERN = /(\+|00)(297|93|244|1264|358|355|376|971|54|374|1684|1268|61|43|994|257|32|229|226|880|359|973|1242|387|590|375|501|1441|591|55|1246|673|975|267|236|1|61|41|56|86|225|237|243|242|682|57|269|238|506|53|5999|61|1345|357|420|49|253|1767|45|1809|1829|1849|213|593|20|291|212|34|372|251|358|679|500|33|298|691|241|44|995|44|233|350|224|590|220|245|240|30|1473|299|502|594|1671|592|852|504|385|509|36|62|44|91|246|353|98|964|354|972|39|1876|44|962|81|76|77|254|996|855|686|1869|82|383|965|856|961|231|218|1758|423|94|266|370|352|371|853|590|212|377|373|261|960|52|692|389|223|356|95|382|976|1670|258|222|1664|596|230|265|60|262|264|687|227|672|234|505|683|31|47|977|674|64|968|92|507|64|51|63|680|675|48|1787|1939|850|351|595|970|689|974|262|40|7|250|966|249|221|65|500|4779|677|232|503|378|252|508|381|211|239|597|421|386|46|268|1721|248|963|1649|235|228|66|992|690|993|670|676|1868|216|90|688|886|255|256|380|598|1|998|3906698|379|1784|58|1284|1340|84|678|681|685|967|27|260|263)(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\d{4,20}$/;
|
|
498
459
|
class Validator {
|
|
499
460
|
validateField(field, value) {
|
|
500
461
|
const {
|
|
501
462
|
validate
|
|
502
463
|
} = field;
|
|
503
464
|
let errors = [];
|
|
504
|
-
|
|
505
465
|
if (!validate) {
|
|
506
466
|
return errors;
|
|
507
467
|
}
|
|
508
|
-
|
|
509
468
|
if (validate.pattern && value && !new RegExp(validate.pattern).test(value)) {
|
|
510
469
|
errors = [...errors, `Field must match pattern ${validate.pattern}.`];
|
|
511
470
|
}
|
|
512
|
-
|
|
513
471
|
if (validate.required && (minDash.isNil(value) || value === '')) {
|
|
514
472
|
errors = [...errors, 'Field is required.'];
|
|
515
473
|
}
|
|
516
|
-
|
|
517
474
|
if ('min' in validate && value && value < validate.min) {
|
|
518
475
|
errors = [...errors, `Field must have minimum value of ${validate.min}.`];
|
|
519
476
|
}
|
|
520
|
-
|
|
521
477
|
if ('max' in validate && value && value > validate.max) {
|
|
522
478
|
errors = [...errors, `Field must have maximum value of ${validate.max}.`];
|
|
523
479
|
}
|
|
524
|
-
|
|
525
480
|
if ('minLength' in validate && value && value.trim().length < validate.minLength) {
|
|
526
481
|
errors = [...errors, `Field must have minimum length of ${validate.minLength}.`];
|
|
527
482
|
}
|
|
528
|
-
|
|
529
483
|
if ('maxLength' in validate && value && value.trim().length > validate.maxLength) {
|
|
530
484
|
errors = [...errors, `Field must have maximum length of ${validate.maxLength}.`];
|
|
531
485
|
}
|
|
532
|
-
|
|
486
|
+
if ('validationType' in validate && value && validate.validationType === 'phone' && !PHONE_PATTERN.test(value)) {
|
|
487
|
+
errors = [...errors, 'Field must be a valid international phone number. (e.g. +4930664040900)'];
|
|
488
|
+
}
|
|
489
|
+
if ('validationType' in validate && value && validate.validationType === 'email' && !EMAIL_PATTERN.test(value)) {
|
|
490
|
+
errors = [...errors, 'Field must be a valid email.'];
|
|
491
|
+
}
|
|
533
492
|
return errors;
|
|
534
493
|
}
|
|
535
|
-
|
|
536
494
|
}
|
|
537
495
|
Validator.$inject = [];
|
|
538
496
|
|
|
@@ -544,59 +502,44 @@ class FormFieldRegistry {
|
|
|
544
502
|
this._ids = new Ids__default['default']([32, 36, 1]);
|
|
545
503
|
this._keys = new Ids__default['default']([32, 36, 1]);
|
|
546
504
|
}
|
|
547
|
-
|
|
548
505
|
add(formField) {
|
|
549
506
|
const {
|
|
550
507
|
id
|
|
551
508
|
} = formField;
|
|
552
|
-
|
|
553
509
|
if (this._formFields[id]) {
|
|
554
510
|
throw new Error(`form field with ID ${id} already exists`);
|
|
555
511
|
}
|
|
556
|
-
|
|
557
512
|
this._eventBus.fire('formField.add', {
|
|
558
513
|
formField
|
|
559
514
|
});
|
|
560
|
-
|
|
561
515
|
this._formFields[id] = formField;
|
|
562
516
|
}
|
|
563
|
-
|
|
564
517
|
remove(formField) {
|
|
565
518
|
const {
|
|
566
519
|
id
|
|
567
520
|
} = formField;
|
|
568
|
-
|
|
569
521
|
if (!this._formFields[id]) {
|
|
570
522
|
return;
|
|
571
523
|
}
|
|
572
|
-
|
|
573
524
|
this._eventBus.fire('formField.remove', {
|
|
574
525
|
formField
|
|
575
526
|
});
|
|
576
|
-
|
|
577
527
|
delete this._formFields[id];
|
|
578
528
|
}
|
|
579
|
-
|
|
580
529
|
get(id) {
|
|
581
530
|
return this._formFields[id];
|
|
582
531
|
}
|
|
583
|
-
|
|
584
532
|
getAll() {
|
|
585
533
|
return Object.values(this._formFields);
|
|
586
534
|
}
|
|
587
|
-
|
|
588
535
|
forEach(callback) {
|
|
589
536
|
this.getAll().forEach(formField => callback(formField));
|
|
590
537
|
}
|
|
591
|
-
|
|
592
538
|
clear() {
|
|
593
539
|
this._formFields = {};
|
|
594
|
-
|
|
595
540
|
this._ids.clear();
|
|
596
|
-
|
|
597
541
|
this._keys.clear();
|
|
598
542
|
}
|
|
599
|
-
|
|
600
543
|
}
|
|
601
544
|
FormFieldRegistry.$inject = ['eventBus'];
|
|
602
545
|
|
|
@@ -627,7 +570,6 @@ function pathParse(path) {
|
|
|
627
570
|
if (!path) {
|
|
628
571
|
return [];
|
|
629
572
|
}
|
|
630
|
-
|
|
631
573
|
return path.split('.').map(key => {
|
|
632
574
|
return isNaN(parseInt(key)) ? key : parseInt(key);
|
|
633
575
|
});
|
|
@@ -639,7 +581,6 @@ function pathStringify(path) {
|
|
|
639
581
|
if (!path) {
|
|
640
582
|
return '';
|
|
641
583
|
}
|
|
642
|
-
|
|
643
584
|
return path.join('.');
|
|
644
585
|
}
|
|
645
586
|
const indices = {};
|
|
@@ -649,22 +590,22 @@ function generateIndexForType(type) {
|
|
|
649
590
|
} else {
|
|
650
591
|
indices[type] = 1;
|
|
651
592
|
}
|
|
652
|
-
|
|
653
593
|
return indices[type];
|
|
654
594
|
}
|
|
655
595
|
function generateIdForType(type) {
|
|
656
596
|
return `${type}${generateIndexForType(type)}`;
|
|
657
597
|
}
|
|
598
|
+
|
|
658
599
|
/**
|
|
659
600
|
* @template T
|
|
660
601
|
* @param {T} data
|
|
661
602
|
* @param {(this: any, key: string, value: any) => any} [replacer]
|
|
662
603
|
* @return {T}
|
|
663
604
|
*/
|
|
664
|
-
|
|
665
605
|
function clone(data, replacer) {
|
|
666
606
|
return JSON.parse(JSON.stringify(data, replacer));
|
|
667
607
|
}
|
|
608
|
+
|
|
668
609
|
/**
|
|
669
610
|
* Parse the schema for input variables a form might make use of
|
|
670
611
|
*
|
|
@@ -677,26 +618,21 @@ function getSchemaVariables(schema) {
|
|
|
677
618
|
if (!schema.components) {
|
|
678
619
|
return [];
|
|
679
620
|
}
|
|
680
|
-
|
|
681
621
|
return schema.components.reduce((variables, component) => {
|
|
682
622
|
const {
|
|
683
623
|
key,
|
|
684
624
|
valuesKey,
|
|
685
625
|
type
|
|
686
626
|
} = component;
|
|
687
|
-
|
|
688
627
|
if (['text', 'button'].includes(type)) {
|
|
689
628
|
return variables;
|
|
690
629
|
}
|
|
691
|
-
|
|
692
630
|
if (key) {
|
|
693
631
|
variables = [...variables, key];
|
|
694
632
|
}
|
|
695
|
-
|
|
696
633
|
if (valuesKey && !variables.includes(valuesKey)) {
|
|
697
634
|
variables = [...variables, valuesKey];
|
|
698
635
|
}
|
|
699
|
-
|
|
700
636
|
return variables;
|
|
701
637
|
}, []);
|
|
702
638
|
}
|
|
@@ -711,6 +647,7 @@ class Importer {
|
|
|
711
647
|
this._formFieldRegistry = formFieldRegistry;
|
|
712
648
|
this._formFields = formFields;
|
|
713
649
|
}
|
|
650
|
+
|
|
714
651
|
/**
|
|
715
652
|
* Import schema adding `id`, `_parent` and `_path`
|
|
716
653
|
* information to each field and adding it to the
|
|
@@ -721,15 +658,12 @@ class Importer {
|
|
|
721
658
|
*
|
|
722
659
|
* @return { { warnings: Array<any>, schema: any, data: any } }
|
|
723
660
|
*/
|
|
724
|
-
|
|
725
|
-
|
|
726
661
|
importSchema(schema, data = {}) {
|
|
727
662
|
// TODO: Add warnings - https://github.com/bpmn-io/form-js/issues/289
|
|
728
663
|
const warnings = [];
|
|
729
|
-
|
|
730
664
|
try {
|
|
731
665
|
const importedSchema = this.importFormField(clone(schema)),
|
|
732
|
-
|
|
666
|
+
importedData = this.importData(clone(data));
|
|
733
667
|
return {
|
|
734
668
|
warnings,
|
|
735
669
|
schema: importedSchema,
|
|
@@ -740,14 +674,13 @@ class Importer {
|
|
|
740
674
|
throw err;
|
|
741
675
|
}
|
|
742
676
|
}
|
|
677
|
+
|
|
743
678
|
/**
|
|
744
679
|
* @param {any} formField
|
|
745
680
|
* @param {string} [parentId]
|
|
746
681
|
*
|
|
747
682
|
* @return {any} importedField
|
|
748
683
|
*/
|
|
749
|
-
|
|
750
|
-
|
|
751
684
|
importFormField(formField, parentId) {
|
|
752
685
|
const {
|
|
753
686
|
components,
|
|
@@ -755,64 +688,53 @@ class Importer {
|
|
|
755
688
|
type,
|
|
756
689
|
id = generateIdForType(type)
|
|
757
690
|
} = formField;
|
|
758
|
-
|
|
759
691
|
if (parentId) {
|
|
760
692
|
// set form field parent
|
|
761
693
|
formField._parent = parentId;
|
|
762
694
|
}
|
|
763
|
-
|
|
764
695
|
if (!this._formFields.get(type)) {
|
|
765
696
|
throw new Error(`form field of type <${type}> not supported`);
|
|
766
697
|
}
|
|
767
|
-
|
|
768
698
|
if (key) {
|
|
769
699
|
// validate <key> uniqueness
|
|
770
700
|
if (this._formFieldRegistry._keys.assigned(key)) {
|
|
771
701
|
throw new Error(`form field with key <${key}> already exists`);
|
|
772
702
|
}
|
|
703
|
+
this._formFieldRegistry._keys.claim(key, formField);
|
|
773
704
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
705
|
+
// TODO: buttons should not have key
|
|
777
706
|
if (type !== 'button') {
|
|
778
707
|
// set form field path
|
|
779
708
|
formField._path = [key];
|
|
780
709
|
}
|
|
781
710
|
}
|
|
782
|
-
|
|
783
711
|
if (id) {
|
|
784
712
|
// validate <id> uniqueness
|
|
785
713
|
if (this._formFieldRegistry._ids.assigned(id)) {
|
|
786
714
|
throw new Error(`form field with id <${id}> already exists`);
|
|
787
715
|
}
|
|
788
|
-
|
|
789
716
|
this._formFieldRegistry._ids.claim(id, formField);
|
|
790
|
-
}
|
|
791
|
-
|
|
717
|
+
}
|
|
792
718
|
|
|
719
|
+
// set form field ID
|
|
793
720
|
formField.id = id;
|
|
794
|
-
|
|
795
721
|
this._formFieldRegistry.add(formField);
|
|
796
|
-
|
|
797
722
|
if (components) {
|
|
798
723
|
this.importFormFields(components, id);
|
|
799
724
|
}
|
|
800
|
-
|
|
801
725
|
return formField;
|
|
802
726
|
}
|
|
803
|
-
|
|
804
727
|
importFormFields(components, parentId) {
|
|
805
728
|
components.forEach(component => {
|
|
806
729
|
this.importFormField(component, parentId);
|
|
807
730
|
});
|
|
808
731
|
}
|
|
732
|
+
|
|
809
733
|
/**
|
|
810
734
|
* @param {Object} data
|
|
811
735
|
*
|
|
812
736
|
* @return {Object} importedData
|
|
813
737
|
*/
|
|
814
|
-
|
|
815
|
-
|
|
816
738
|
importData(data) {
|
|
817
739
|
return this._formFieldRegistry.getAll().reduce((importedData, formField) => {
|
|
818
740
|
const {
|
|
@@ -820,22 +742,24 @@ class Importer {
|
|
|
820
742
|
_path,
|
|
821
743
|
type,
|
|
822
744
|
valuesKey
|
|
823
|
-
} = formField;
|
|
745
|
+
} = formField;
|
|
746
|
+
|
|
747
|
+
// get values defined via valuesKey
|
|
824
748
|
|
|
825
749
|
if (valuesKey) {
|
|
826
|
-
importedData = {
|
|
750
|
+
importedData = {
|
|
751
|
+
...importedData,
|
|
827
752
|
[valuesKey]: minDash.get(data, [valuesKey])
|
|
828
753
|
};
|
|
829
|
-
}
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// try to get value from data
|
|
830
757
|
// if unavailable - try to get default value from form field
|
|
831
758
|
// if unavailable - get empty value from form field
|
|
832
759
|
|
|
833
|
-
|
|
834
760
|
if (_path) {
|
|
835
761
|
const fieldImplementation = this._formFields.get(type);
|
|
836
|
-
|
|
837
762
|
let valueData = minDash.get(data, _path);
|
|
838
|
-
|
|
839
763
|
if (!minDash.isUndefined(valueData) && fieldImplementation.sanitizeValue) {
|
|
840
764
|
valueData = fieldImplementation.sanitizeValue({
|
|
841
765
|
formField,
|
|
@@ -843,17 +767,15 @@ class Importer {
|
|
|
843
767
|
value: valueData
|
|
844
768
|
});
|
|
845
769
|
}
|
|
846
|
-
|
|
847
770
|
const initialFieldValue = !minDash.isUndefined(valueData) ? valueData : !minDash.isUndefined(defaultValue) ? defaultValue : fieldImplementation.emptyValue;
|
|
848
|
-
importedData = {
|
|
771
|
+
importedData = {
|
|
772
|
+
...importedData,
|
|
849
773
|
[_path[0]]: initialFieldValue
|
|
850
774
|
};
|
|
851
775
|
}
|
|
852
|
-
|
|
853
776
|
return importedData;
|
|
854
777
|
}, {});
|
|
855
778
|
}
|
|
856
|
-
|
|
857
779
|
}
|
|
858
780
|
Importer.$inject = ['formFieldRegistry', 'formFields'];
|
|
859
781
|
|
|
@@ -862,30 +784,26 @@ var importModule = {
|
|
|
862
784
|
};
|
|
863
785
|
|
|
864
786
|
const NODE_TYPE_TEXT = 3,
|
|
865
|
-
|
|
787
|
+
NODE_TYPE_ELEMENT = 1;
|
|
866
788
|
const ALLOWED_NODES = ['h1', 'h2', 'h3', 'h4', 'h5', 'span', 'em', 'a', 'p', 'div', 'ul', 'ol', 'li', 'hr', 'blockquote', 'img', 'pre', 'code', 'br', 'strong'];
|
|
867
789
|
const ALLOWED_ATTRIBUTES = ['align', 'alt', 'class', 'href', 'id', 'name', 'rel', 'target', 'src'];
|
|
868
790
|
const ALLOWED_URI_PATTERN = /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i; // eslint-disable-line no-useless-escape
|
|
869
|
-
|
|
870
791
|
const ATTR_WHITESPACE_PATTERN = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g; // eslint-disable-line no-control-regex
|
|
871
792
|
|
|
872
793
|
const FORM_ELEMENT = document.createElement('form');
|
|
794
|
+
|
|
873
795
|
/**
|
|
874
796
|
* Sanitize a HTML string and return the cleaned, safe version.
|
|
875
797
|
*
|
|
876
798
|
* @param {string} html
|
|
877
799
|
* @return {string}
|
|
878
800
|
*/
|
|
879
|
-
|
|
880
801
|
function sanitizeHTML(html) {
|
|
881
802
|
const doc = new DOMParser().parseFromString(`<!DOCTYPE html>\n<html><body><div>${html}`, 'text/html');
|
|
882
803
|
doc.normalize();
|
|
883
804
|
const element = doc.body.firstChild;
|
|
884
|
-
|
|
885
805
|
if (element) {
|
|
886
|
-
sanitizeNode(
|
|
887
|
-
/** @type Element */
|
|
888
|
-
element);
|
|
806
|
+
sanitizeNode( /** @type Element */element);
|
|
889
807
|
return new XMLSerializer().serializeToString(element);
|
|
890
808
|
} else {
|
|
891
809
|
// handle the case that document parsing
|
|
@@ -893,6 +811,7 @@ function sanitizeHTML(html) {
|
|
|
893
811
|
return '';
|
|
894
812
|
}
|
|
895
813
|
}
|
|
814
|
+
|
|
896
815
|
/**
|
|
897
816
|
* Recursively sanitize a HTML node, potentially
|
|
898
817
|
* removing it, its children or attributes.
|
|
@@ -903,51 +822,48 @@ function sanitizeHTML(html) {
|
|
|
903
822
|
*
|
|
904
823
|
* @param {Element} node
|
|
905
824
|
*/
|
|
906
|
-
|
|
907
825
|
function sanitizeNode(node) {
|
|
908
826
|
// allow text nodes
|
|
909
827
|
if (node.nodeType === NODE_TYPE_TEXT) {
|
|
910
828
|
return;
|
|
911
|
-
}
|
|
912
|
-
|
|
829
|
+
}
|
|
913
830
|
|
|
831
|
+
// disallow all other nodes but Element
|
|
914
832
|
if (node.nodeType !== NODE_TYPE_ELEMENT) {
|
|
915
833
|
return node.remove();
|
|
916
834
|
}
|
|
835
|
+
const lcTag = node.tagName.toLowerCase();
|
|
917
836
|
|
|
918
|
-
|
|
919
|
-
|
|
837
|
+
// disallow non-whitelisted tags
|
|
920
838
|
if (!ALLOWED_NODES.includes(lcTag)) {
|
|
921
839
|
return node.remove();
|
|
922
840
|
}
|
|
841
|
+
const attributes = node.attributes;
|
|
923
842
|
|
|
924
|
-
|
|
925
|
-
|
|
843
|
+
// clean attributes
|
|
926
844
|
for (let i = attributes.length; i--;) {
|
|
927
845
|
const attribute = attributes[i];
|
|
928
846
|
const name = attribute.name;
|
|
929
|
-
const lcName = name.toLowerCase();
|
|
847
|
+
const lcName = name.toLowerCase();
|
|
930
848
|
|
|
849
|
+
// normalize node value
|
|
931
850
|
const value = attribute.value.trim();
|
|
932
851
|
node.removeAttribute(name);
|
|
933
852
|
const valid = isValidAttribute(lcTag, lcName, value);
|
|
934
|
-
|
|
935
853
|
if (valid) {
|
|
936
854
|
node.setAttribute(name, value);
|
|
937
855
|
}
|
|
938
|
-
}
|
|
939
|
-
|
|
856
|
+
}
|
|
940
857
|
|
|
858
|
+
// force noopener on target="_blank" links
|
|
941
859
|
if (lcTag === 'a' && node.getAttribute('target') === '_blank' && node.getAttribute('rel') !== 'noopener') {
|
|
942
860
|
node.setAttribute('rel', 'noopener');
|
|
943
861
|
}
|
|
944
|
-
|
|
945
862
|
for (let i = node.childNodes.length; i--;) {
|
|
946
|
-
sanitizeNode(
|
|
947
|
-
/** @type Element */
|
|
948
|
-
node.childNodes[i]);
|
|
863
|
+
sanitizeNode( /** @type Element */node.childNodes[i]);
|
|
949
864
|
}
|
|
950
865
|
}
|
|
866
|
+
|
|
951
867
|
/**
|
|
952
868
|
* Validates attributes for validity.
|
|
953
869
|
*
|
|
@@ -956,56 +872,51 @@ function sanitizeNode(node) {
|
|
|
956
872
|
* @param {string} value
|
|
957
873
|
* @return {boolean}
|
|
958
874
|
*/
|
|
959
|
-
|
|
960
|
-
|
|
961
875
|
function isValidAttribute(lcTag, lcName, value) {
|
|
962
876
|
// disallow most attributes based on whitelist
|
|
963
877
|
if (!ALLOWED_ATTRIBUTES.includes(lcName)) {
|
|
964
878
|
return false;
|
|
965
|
-
}
|
|
966
|
-
|
|
879
|
+
}
|
|
967
880
|
|
|
881
|
+
// disallow "DOM clobbering" / polution of document and wrapping form elements
|
|
968
882
|
if ((lcName === 'id' || lcName === 'name') && (value in document || value in FORM_ELEMENT)) {
|
|
969
883
|
return false;
|
|
970
884
|
}
|
|
971
|
-
|
|
972
885
|
if (lcName === 'target' && value !== '_blank') {
|
|
973
886
|
return false;
|
|
974
|
-
}
|
|
975
|
-
|
|
887
|
+
}
|
|
976
888
|
|
|
889
|
+
// allow valid url links only
|
|
977
890
|
if (lcName === 'href' && !ALLOWED_URI_PATTERN.test(value.replace(ATTR_WHITESPACE_PATTERN, ''))) {
|
|
978
891
|
return false;
|
|
979
892
|
}
|
|
980
|
-
|
|
981
893
|
return true;
|
|
982
894
|
}
|
|
983
895
|
|
|
984
|
-
function formFieldClasses(type,
|
|
896
|
+
function formFieldClasses(type, {
|
|
897
|
+
errors = [],
|
|
898
|
+
disabled = false
|
|
899
|
+
} = {}) {
|
|
985
900
|
if (!type) {
|
|
986
901
|
throw new Error('type required');
|
|
987
902
|
}
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
classes.push('fjs-has-errors');
|
|
993
|
-
}
|
|
994
|
-
|
|
995
|
-
return classes.join(' ');
|
|
903
|
+
return classNames__default['default']('fjs-form-field', `fjs-form-field-${type}`, {
|
|
904
|
+
'fjs-has-errors': errors.length > 0,
|
|
905
|
+
'fjs-disabled': disabled
|
|
906
|
+
});
|
|
996
907
|
}
|
|
997
908
|
function prefixId(id, formId) {
|
|
998
909
|
if (formId) {
|
|
999
910
|
return `fjs-form-${formId}-${id}`;
|
|
1000
911
|
}
|
|
1001
|
-
|
|
1002
912
|
return `fjs-form-${id}`;
|
|
1003
913
|
}
|
|
1004
914
|
function markdownToHTML(markdown) {
|
|
1005
915
|
const htmls = markdown.split(/(?:\r?\n){2,}/).map(line => /^((\d+.)|[><\s#-*])/.test(line) ? snarkdown__default['default'](line) : `<p>${snarkdown__default['default'](line)}</p>`);
|
|
1006
916
|
return htmls.join('\n\n');
|
|
1007
|
-
}
|
|
917
|
+
}
|
|
1008
918
|
|
|
919
|
+
// see https://github.com/developit/snarkdown/issues/70
|
|
1009
920
|
function safeMarkdown(markdown) {
|
|
1010
921
|
const html = markdownToHTML(markdown);
|
|
1011
922
|
return sanitizeHTML(html);
|
|
@@ -1020,7 +931,6 @@ function sanitizeSingleSelectValue(options) {
|
|
|
1020
931
|
valuesKey,
|
|
1021
932
|
values
|
|
1022
933
|
} = formField;
|
|
1023
|
-
|
|
1024
934
|
try {
|
|
1025
935
|
const validValues = (valuesKey ? minDash.get(data, [valuesKey]) : values).map(v => v.value) || [];
|
|
1026
936
|
return validValues.includes(value) ? value : null;
|
|
@@ -1040,7 +950,6 @@ function sanitizeMultiSelectValue(options) {
|
|
|
1040
950
|
valuesKey,
|
|
1041
951
|
values
|
|
1042
952
|
} = formField;
|
|
1043
|
-
|
|
1044
953
|
try {
|
|
1045
954
|
const validValues = (valuesKey ? minDash.get(data, [valuesKey]) : values).map(v => v.value) || [];
|
|
1046
955
|
return value.filter(v => validValues.includes(v));
|
|
@@ -1051,7 +960,7 @@ function sanitizeMultiSelectValue(options) {
|
|
|
1051
960
|
}
|
|
1052
961
|
}
|
|
1053
962
|
|
|
1054
|
-
const type$
|
|
963
|
+
const type$9 = 'button';
|
|
1055
964
|
function Button(props) {
|
|
1056
965
|
const {
|
|
1057
966
|
disabled,
|
|
@@ -1061,7 +970,7 @@ function Button(props) {
|
|
|
1061
970
|
action = 'submit'
|
|
1062
971
|
} = field;
|
|
1063
972
|
return jsxRuntime.jsx("div", {
|
|
1064
|
-
class: formFieldClasses(type$
|
|
973
|
+
class: formFieldClasses(type$9),
|
|
1065
974
|
children: jsxRuntime.jsx("button", {
|
|
1066
975
|
class: "fjs-button",
|
|
1067
976
|
type: action,
|
|
@@ -1070,15 +979,13 @@ function Button(props) {
|
|
|
1070
979
|
})
|
|
1071
980
|
});
|
|
1072
981
|
}
|
|
1073
|
-
|
|
1074
982
|
Button.create = function (options = {}) {
|
|
1075
983
|
return {
|
|
1076
984
|
action: 'submit',
|
|
1077
985
|
...options
|
|
1078
986
|
};
|
|
1079
987
|
};
|
|
1080
|
-
|
|
1081
|
-
Button.type = type$8;
|
|
988
|
+
Button.type = type$9;
|
|
1082
989
|
Button.label = 'Button';
|
|
1083
990
|
Button.keyed = true;
|
|
1084
991
|
|
|
@@ -1100,9 +1007,7 @@ const FormRenderContext = preact.createContext({
|
|
|
1100
1007
|
*
|
|
1101
1008
|
* @returns {any}
|
|
1102
1009
|
*/
|
|
1103
|
-
|
|
1104
1010
|
function getService(type, strict) {}
|
|
1105
|
-
|
|
1106
1011
|
const FormContext = preact.createContext({
|
|
1107
1012
|
getService,
|
|
1108
1013
|
formId: null
|
|
@@ -1112,11 +1017,9 @@ function Description(props) {
|
|
|
1112
1017
|
const {
|
|
1113
1018
|
description
|
|
1114
1019
|
} = props;
|
|
1115
|
-
|
|
1116
1020
|
if (!description) {
|
|
1117
1021
|
return null;
|
|
1118
1022
|
}
|
|
1119
|
-
|
|
1120
1023
|
return jsxRuntime.jsx("div", {
|
|
1121
1024
|
class: "fjs-form-field-description",
|
|
1122
1025
|
children: description
|
|
@@ -1127,11 +1030,9 @@ function Errors(props) {
|
|
|
1127
1030
|
const {
|
|
1128
1031
|
errors
|
|
1129
1032
|
} = props;
|
|
1130
|
-
|
|
1131
1033
|
if (!errors.length) {
|
|
1132
1034
|
return null;
|
|
1133
1035
|
}
|
|
1134
|
-
|
|
1135
1036
|
return jsxRuntime.jsx("div", {
|
|
1136
1037
|
class: "fjs-form-field-error",
|
|
1137
1038
|
children: jsxRuntime.jsx("ul", {
|
|
@@ -1152,7 +1053,7 @@ function Label(props) {
|
|
|
1152
1053
|
} = props;
|
|
1153
1054
|
return jsxRuntime.jsxs("label", {
|
|
1154
1055
|
for: id,
|
|
1155
|
-
class:
|
|
1056
|
+
class: classNames__default['default']('fjs-form-field-label', props['class']),
|
|
1156
1057
|
children: [props.children, label || '', required && jsxRuntime.jsx("span", {
|
|
1157
1058
|
class: "fjs-asterix",
|
|
1158
1059
|
children: "*"
|
|
@@ -1160,7 +1061,7 @@ function Label(props) {
|
|
|
1160
1061
|
});
|
|
1161
1062
|
}
|
|
1162
1063
|
|
|
1163
|
-
const type$
|
|
1064
|
+
const type$8 = 'checkbox';
|
|
1164
1065
|
function Checkbox(props) {
|
|
1165
1066
|
const {
|
|
1166
1067
|
disabled,
|
|
@@ -1173,7 +1074,6 @@ function Checkbox(props) {
|
|
|
1173
1074
|
id,
|
|
1174
1075
|
label
|
|
1175
1076
|
} = field;
|
|
1176
|
-
|
|
1177
1077
|
const onChange = ({
|
|
1178
1078
|
target
|
|
1179
1079
|
}) => {
|
|
@@ -1182,12 +1082,16 @@ function Checkbox(props) {
|
|
|
1182
1082
|
value: target.checked
|
|
1183
1083
|
});
|
|
1184
1084
|
};
|
|
1185
|
-
|
|
1186
1085
|
const {
|
|
1187
1086
|
formId
|
|
1188
1087
|
} = hooks.useContext(FormContext);
|
|
1189
1088
|
return jsxRuntime.jsxs("div", {
|
|
1190
|
-
class: formFieldClasses(type$
|
|
1089
|
+
class: classNames__default['default'](formFieldClasses(type$8, {
|
|
1090
|
+
errors,
|
|
1091
|
+
disabled
|
|
1092
|
+
}), {
|
|
1093
|
+
'fjs-checked': value
|
|
1094
|
+
}),
|
|
1191
1095
|
children: [jsxRuntime.jsx(Label, {
|
|
1192
1096
|
id: prefixId(id, formId),
|
|
1193
1097
|
label: label,
|
|
@@ -1207,17 +1111,15 @@ function Checkbox(props) {
|
|
|
1207
1111
|
})]
|
|
1208
1112
|
});
|
|
1209
1113
|
}
|
|
1210
|
-
|
|
1211
1114
|
Checkbox.create = function (options = {}) {
|
|
1212
|
-
return {
|
|
1115
|
+
return {
|
|
1116
|
+
...options
|
|
1213
1117
|
};
|
|
1214
1118
|
};
|
|
1215
|
-
|
|
1216
|
-
Checkbox.type = type$7;
|
|
1119
|
+
Checkbox.type = type$8;
|
|
1217
1120
|
Checkbox.label = 'Checkbox';
|
|
1218
1121
|
Checkbox.keyed = true;
|
|
1219
1122
|
Checkbox.emptyValue = false;
|
|
1220
|
-
|
|
1221
1123
|
Checkbox.sanitizeValue = ({
|
|
1222
1124
|
value
|
|
1223
1125
|
}) => value === true;
|
|
@@ -1232,12 +1134,12 @@ function useService (type, strict) {
|
|
|
1232
1134
|
/**
|
|
1233
1135
|
* @enum { String }
|
|
1234
1136
|
*/
|
|
1235
|
-
|
|
1236
1137
|
const LOAD_STATES = {
|
|
1237
1138
|
LOADING: 'loading',
|
|
1238
1139
|
LOADED: 'loaded',
|
|
1239
1140
|
ERROR: 'error'
|
|
1240
1141
|
};
|
|
1142
|
+
|
|
1241
1143
|
/**
|
|
1242
1144
|
* @typedef {Object} ValuesGetter
|
|
1243
1145
|
* @property {Object[]} values - The values data
|
|
@@ -1250,7 +1152,6 @@ const LOAD_STATES = {
|
|
|
1250
1152
|
* @param {Object} field - The form field to handle values for
|
|
1251
1153
|
* @return {ValuesGetter} valuesGetter - A values getter object providing loading state and values
|
|
1252
1154
|
*/
|
|
1253
|
-
|
|
1254
1155
|
function useValuesAsync (field) {
|
|
1255
1156
|
const {
|
|
1256
1157
|
valuesKey,
|
|
@@ -1261,15 +1162,11 @@ function useValuesAsync (field) {
|
|
|
1261
1162
|
error: undefined,
|
|
1262
1163
|
state: LOAD_STATES.LOADING
|
|
1263
1164
|
});
|
|
1264
|
-
|
|
1265
1165
|
const initialData = useService('form')._getState().initialData;
|
|
1266
|
-
|
|
1267
1166
|
hooks.useEffect(() => {
|
|
1268
1167
|
let values = [];
|
|
1269
|
-
|
|
1270
1168
|
if (valuesKey !== undefined) {
|
|
1271
1169
|
const keyedValues = (initialData || {})[valuesKey];
|
|
1272
|
-
|
|
1273
1170
|
if (keyedValues && Array.isArray(keyedValues)) {
|
|
1274
1171
|
values = keyedValues;
|
|
1275
1172
|
}
|
|
@@ -1279,25 +1176,22 @@ function useValuesAsync (field) {
|
|
|
1279
1176
|
setValuesGetter(getErrorState('No values source defined in the form definition'));
|
|
1280
1177
|
return;
|
|
1281
1178
|
}
|
|
1282
|
-
|
|
1283
1179
|
setValuesGetter(buildLoadedState(values));
|
|
1284
1180
|
}, [valuesKey, staticValues, initialData]);
|
|
1285
1181
|
return valuesGetter;
|
|
1286
1182
|
}
|
|
1287
|
-
|
|
1288
1183
|
const getErrorState = error => ({
|
|
1289
1184
|
values: [],
|
|
1290
1185
|
error,
|
|
1291
1186
|
state: LOAD_STATES.ERROR
|
|
1292
1187
|
});
|
|
1293
|
-
|
|
1294
1188
|
const buildLoadedState = values => ({
|
|
1295
1189
|
values,
|
|
1296
1190
|
error: undefined,
|
|
1297
1191
|
state: LOAD_STATES.LOADED
|
|
1298
1192
|
});
|
|
1299
1193
|
|
|
1300
|
-
const type$
|
|
1194
|
+
const type$7 = 'checklist';
|
|
1301
1195
|
function Checklist(props) {
|
|
1302
1196
|
const {
|
|
1303
1197
|
disabled,
|
|
@@ -1310,22 +1204,18 @@ function Checklist(props) {
|
|
|
1310
1204
|
id,
|
|
1311
1205
|
label
|
|
1312
1206
|
} = field;
|
|
1313
|
-
|
|
1314
1207
|
const toggleCheckbox = v => {
|
|
1315
1208
|
let newValue = [...value];
|
|
1316
|
-
|
|
1317
1209
|
if (!newValue.includes(v)) {
|
|
1318
1210
|
newValue.push(v);
|
|
1319
1211
|
} else {
|
|
1320
1212
|
newValue = newValue.filter(x => x != v);
|
|
1321
1213
|
}
|
|
1322
|
-
|
|
1323
1214
|
props.onChange({
|
|
1324
1215
|
field,
|
|
1325
1216
|
value: newValue
|
|
1326
1217
|
});
|
|
1327
1218
|
};
|
|
1328
|
-
|
|
1329
1219
|
const {
|
|
1330
1220
|
state: loadState,
|
|
1331
1221
|
values: options
|
|
@@ -1334,13 +1224,19 @@ function Checklist(props) {
|
|
|
1334
1224
|
formId
|
|
1335
1225
|
} = hooks.useContext(FormContext);
|
|
1336
1226
|
return jsxRuntime.jsxs("div", {
|
|
1337
|
-
class: formFieldClasses(type$
|
|
1227
|
+
class: classNames__default['default'](formFieldClasses(type$7, {
|
|
1228
|
+
errors,
|
|
1229
|
+
disabled
|
|
1230
|
+
})),
|
|
1338
1231
|
children: [jsxRuntime.jsx(Label, {
|
|
1339
1232
|
label: label
|
|
1340
1233
|
}), loadState == LOAD_STATES.LOADED && options.map((v, index) => {
|
|
1341
1234
|
return jsxRuntime.jsx(Label, {
|
|
1342
1235
|
id: prefixId(`${id}-${index}`, formId),
|
|
1343
1236
|
label: v.label,
|
|
1237
|
+
class: classNames__default['default']({
|
|
1238
|
+
'fjs-checked': value.includes(v.value)
|
|
1239
|
+
}),
|
|
1344
1240
|
required: false,
|
|
1345
1241
|
children: jsxRuntime.jsx("input", {
|
|
1346
1242
|
checked: value.includes(v.value),
|
|
@@ -1358,7 +1254,6 @@ function Checklist(props) {
|
|
|
1358
1254
|
})]
|
|
1359
1255
|
});
|
|
1360
1256
|
}
|
|
1361
|
-
|
|
1362
1257
|
Checklist.create = function (options = {}) {
|
|
1363
1258
|
if (options.valuesKey) return options;
|
|
1364
1259
|
return {
|
|
@@ -1369,15 +1264,13 @@ Checklist.create = function (options = {}) {
|
|
|
1369
1264
|
...options
|
|
1370
1265
|
};
|
|
1371
1266
|
};
|
|
1372
|
-
|
|
1373
|
-
Checklist.type = type$6;
|
|
1267
|
+
Checklist.type = type$7;
|
|
1374
1268
|
Checklist.label = 'Checklist';
|
|
1375
1269
|
Checklist.keyed = true;
|
|
1376
1270
|
Checklist.emptyValue = [];
|
|
1377
1271
|
Checklist.sanitizeValue = sanitizeMultiSelectValue;
|
|
1378
1272
|
|
|
1379
1273
|
const noop$1 = () => false;
|
|
1380
|
-
|
|
1381
1274
|
function FormField(props) {
|
|
1382
1275
|
const {
|
|
1383
1276
|
field,
|
|
@@ -1387,29 +1280,26 @@ function FormField(props) {
|
|
|
1387
1280
|
_path
|
|
1388
1281
|
} = field;
|
|
1389
1282
|
const formFields = useService('formFields'),
|
|
1390
|
-
|
|
1391
|
-
|
|
1283
|
+
form = useService('form');
|
|
1392
1284
|
const {
|
|
1393
1285
|
data,
|
|
1394
1286
|
errors,
|
|
1395
1287
|
properties
|
|
1396
1288
|
} = form._getState();
|
|
1397
|
-
|
|
1398
1289
|
const {
|
|
1399
1290
|
Element
|
|
1400
1291
|
} = hooks.useContext(FormRenderContext);
|
|
1401
1292
|
const FormFieldComponent = formFields.get(field.type);
|
|
1402
|
-
|
|
1403
1293
|
if (!FormFieldComponent) {
|
|
1404
1294
|
throw new Error(`cannot render field <${field.type}>`);
|
|
1405
1295
|
}
|
|
1406
|
-
|
|
1407
1296
|
const value = minDash.get(data, _path);
|
|
1408
1297
|
const fieldErrors = findErrors(errors, _path);
|
|
1409
1298
|
const disabled = properties.readOnly || field.disabled || false;
|
|
1410
1299
|
return jsxRuntime.jsx(Element, {
|
|
1411
1300
|
field: field,
|
|
1412
|
-
children: jsxRuntime.jsx(FormFieldComponent, {
|
|
1301
|
+
children: jsxRuntime.jsx(FormFieldComponent, {
|
|
1302
|
+
...props,
|
|
1413
1303
|
disabled: disabled,
|
|
1414
1304
|
errors: fieldErrors,
|
|
1415
1305
|
onChange: disabled ? noop$1 : onChange,
|
|
@@ -1433,21 +1323,20 @@ function Default(props) {
|
|
|
1433
1323
|
class: "fjs-vertical-layout",
|
|
1434
1324
|
field: field,
|
|
1435
1325
|
children: [components.map(childField => {
|
|
1436
|
-
return preact.createElement(FormField, {
|
|
1326
|
+
return preact.createElement(FormField, {
|
|
1327
|
+
...props,
|
|
1437
1328
|
key: childField.id,
|
|
1438
1329
|
field: childField
|
|
1439
1330
|
});
|
|
1440
1331
|
}), components.length ? null : jsxRuntime.jsx(Empty, {})]
|
|
1441
1332
|
});
|
|
1442
1333
|
}
|
|
1443
|
-
|
|
1444
1334
|
Default.create = function (options = {}) {
|
|
1445
1335
|
return {
|
|
1446
1336
|
components: [],
|
|
1447
1337
|
...options
|
|
1448
1338
|
};
|
|
1449
1339
|
};
|
|
1450
|
-
|
|
1451
1340
|
Default.type = 'default';
|
|
1452
1341
|
Default.keyed = false;
|
|
1453
1342
|
|
|
@@ -1456,7 +1345,6 @@ Default.keyed = false;
|
|
|
1456
1345
|
*
|
|
1457
1346
|
* @see http://bpmn.io/license for more information.
|
|
1458
1347
|
*/
|
|
1459
|
-
|
|
1460
1348
|
function Logo() {
|
|
1461
1349
|
return jsxRuntime.jsxs("svg", {
|
|
1462
1350
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -1473,16 +1361,13 @@ function Logo() {
|
|
|
1473
1361
|
})]
|
|
1474
1362
|
});
|
|
1475
1363
|
}
|
|
1476
|
-
|
|
1477
1364
|
function Lightbox(props) {
|
|
1478
1365
|
const {
|
|
1479
1366
|
open
|
|
1480
1367
|
} = props;
|
|
1481
|
-
|
|
1482
1368
|
if (!open) {
|
|
1483
1369
|
return null;
|
|
1484
1370
|
}
|
|
1485
|
-
|
|
1486
1371
|
return jsxRuntime.jsxs("div", {
|
|
1487
1372
|
class: "fjs-powered-by-lightbox",
|
|
1488
1373
|
style: "z-index: 100; position: fixed; top: 0; left: 0;right: 0; bottom: 0",
|
|
@@ -1510,7 +1395,6 @@ function Lightbox(props) {
|
|
|
1510
1395
|
})]
|
|
1511
1396
|
});
|
|
1512
1397
|
}
|
|
1513
|
-
|
|
1514
1398
|
function Link(props) {
|
|
1515
1399
|
return jsxRuntime.jsx("div", {
|
|
1516
1400
|
class: "fjs-powered-by fjs-form-field",
|
|
@@ -1527,17 +1411,14 @@ function Link(props) {
|
|
|
1527
1411
|
})
|
|
1528
1412
|
});
|
|
1529
1413
|
}
|
|
1530
|
-
|
|
1531
1414
|
function PoweredBy(props) {
|
|
1532
1415
|
const [open, setOpen] = hooks.useState(false);
|
|
1533
|
-
|
|
1534
1416
|
function toggleOpen(open) {
|
|
1535
1417
|
return event => {
|
|
1536
1418
|
event.preventDefault();
|
|
1537
1419
|
setOpen(open);
|
|
1538
1420
|
};
|
|
1539
1421
|
}
|
|
1540
|
-
|
|
1541
1422
|
return jsxRuntime.jsxs(preact.Fragment, {
|
|
1542
1423
|
children: [React.createPortal(jsxRuntime.jsx(Lightbox, {
|
|
1543
1424
|
open: open,
|
|
@@ -1549,30 +1430,24 @@ function PoweredBy(props) {
|
|
|
1549
1430
|
}
|
|
1550
1431
|
|
|
1551
1432
|
const noop = () => {};
|
|
1552
|
-
|
|
1553
1433
|
function FormComponent(props) {
|
|
1554
1434
|
const form = useService('form');
|
|
1555
|
-
|
|
1556
1435
|
const {
|
|
1557
1436
|
schema
|
|
1558
1437
|
} = form._getState();
|
|
1559
|
-
|
|
1560
1438
|
const {
|
|
1561
1439
|
onSubmit = noop,
|
|
1562
1440
|
onReset = noop,
|
|
1563
1441
|
onChange = noop
|
|
1564
1442
|
} = props;
|
|
1565
|
-
|
|
1566
1443
|
const handleSubmit = event => {
|
|
1567
1444
|
event.preventDefault();
|
|
1568
1445
|
onSubmit();
|
|
1569
1446
|
};
|
|
1570
|
-
|
|
1571
1447
|
const handleReset = event => {
|
|
1572
1448
|
event.preventDefault();
|
|
1573
1449
|
onReset();
|
|
1574
1450
|
};
|
|
1575
|
-
|
|
1576
1451
|
return jsxRuntime.jsxs("form", {
|
|
1577
1452
|
class: "fjs-form",
|
|
1578
1453
|
onSubmit: handleSubmit,
|
|
@@ -1584,7 +1459,7 @@ function FormComponent(props) {
|
|
|
1584
1459
|
});
|
|
1585
1460
|
}
|
|
1586
1461
|
|
|
1587
|
-
const type$
|
|
1462
|
+
const type$6 = 'number';
|
|
1588
1463
|
function Number(props) {
|
|
1589
1464
|
const {
|
|
1590
1465
|
disabled,
|
|
@@ -1601,7 +1476,6 @@ function Number(props) {
|
|
|
1601
1476
|
const {
|
|
1602
1477
|
required
|
|
1603
1478
|
} = validate;
|
|
1604
|
-
|
|
1605
1479
|
const onChange = ({
|
|
1606
1480
|
target
|
|
1607
1481
|
}) => {
|
|
@@ -1612,12 +1486,14 @@ function Number(props) {
|
|
|
1612
1486
|
})
|
|
1613
1487
|
});
|
|
1614
1488
|
};
|
|
1615
|
-
|
|
1616
1489
|
const {
|
|
1617
1490
|
formId
|
|
1618
1491
|
} = hooks.useContext(FormContext);
|
|
1619
1492
|
return jsxRuntime.jsxs("div", {
|
|
1620
|
-
class: formFieldClasses(type$
|
|
1493
|
+
class: formFieldClasses(type$6, {
|
|
1494
|
+
errors,
|
|
1495
|
+
disabled
|
|
1496
|
+
}),
|
|
1621
1497
|
children: [jsxRuntime.jsx(Label, {
|
|
1622
1498
|
id: prefixId(id, formId),
|
|
1623
1499
|
label: label,
|
|
@@ -1636,25 +1512,23 @@ function Number(props) {
|
|
|
1636
1512
|
})]
|
|
1637
1513
|
});
|
|
1638
1514
|
}
|
|
1639
|
-
|
|
1640
1515
|
Number.create = function (options = {}) {
|
|
1641
|
-
return {
|
|
1516
|
+
return {
|
|
1517
|
+
...options
|
|
1642
1518
|
};
|
|
1643
1519
|
};
|
|
1644
|
-
|
|
1645
1520
|
Number.sanitizeValue = ({
|
|
1646
1521
|
value
|
|
1647
1522
|
}) => {
|
|
1648
1523
|
const parsedValue = parseInt(value, 10);
|
|
1649
1524
|
return isNaN(parsedValue) ? null : parsedValue;
|
|
1650
1525
|
};
|
|
1651
|
-
|
|
1652
|
-
Number.type = type$5;
|
|
1526
|
+
Number.type = type$6;
|
|
1653
1527
|
Number.keyed = true;
|
|
1654
1528
|
Number.label = 'Number';
|
|
1655
1529
|
Number.emptyValue = null;
|
|
1656
1530
|
|
|
1657
|
-
const type$
|
|
1531
|
+
const type$5 = 'radio';
|
|
1658
1532
|
function Radio(props) {
|
|
1659
1533
|
const {
|
|
1660
1534
|
disabled,
|
|
@@ -1671,14 +1545,12 @@ function Radio(props) {
|
|
|
1671
1545
|
const {
|
|
1672
1546
|
required
|
|
1673
1547
|
} = validate;
|
|
1674
|
-
|
|
1675
1548
|
const onChange = v => {
|
|
1676
1549
|
props.onChange({
|
|
1677
1550
|
field,
|
|
1678
1551
|
value: v
|
|
1679
1552
|
});
|
|
1680
1553
|
};
|
|
1681
|
-
|
|
1682
1554
|
const {
|
|
1683
1555
|
state: loadState,
|
|
1684
1556
|
values: options
|
|
@@ -1687,7 +1559,10 @@ function Radio(props) {
|
|
|
1687
1559
|
formId
|
|
1688
1560
|
} = hooks.useContext(FormContext);
|
|
1689
1561
|
return jsxRuntime.jsxs("div", {
|
|
1690
|
-
class: formFieldClasses(type$
|
|
1562
|
+
class: formFieldClasses(type$5, {
|
|
1563
|
+
errors,
|
|
1564
|
+
disabled
|
|
1565
|
+
}),
|
|
1691
1566
|
children: [jsxRuntime.jsx(Label, {
|
|
1692
1567
|
label: label,
|
|
1693
1568
|
required: required
|
|
@@ -1695,6 +1570,9 @@ function Radio(props) {
|
|
|
1695
1570
|
return jsxRuntime.jsx(Label, {
|
|
1696
1571
|
id: prefixId(`${id}-${index}`, formId),
|
|
1697
1572
|
label: option.label,
|
|
1573
|
+
class: classNames__default['default']({
|
|
1574
|
+
'fjs-checked': option.value === value
|
|
1575
|
+
}),
|
|
1698
1576
|
required: false,
|
|
1699
1577
|
children: jsxRuntime.jsx("input", {
|
|
1700
1578
|
checked: option.value === value,
|
|
@@ -1712,7 +1590,6 @@ function Radio(props) {
|
|
|
1712
1590
|
})]
|
|
1713
1591
|
});
|
|
1714
1592
|
}
|
|
1715
|
-
|
|
1716
1593
|
Radio.create = function (options = {}) {
|
|
1717
1594
|
if (options.valuesKey) return options;
|
|
1718
1595
|
return {
|
|
@@ -1723,14 +1600,13 @@ Radio.create = function (options = {}) {
|
|
|
1723
1600
|
...options
|
|
1724
1601
|
};
|
|
1725
1602
|
};
|
|
1726
|
-
|
|
1727
|
-
Radio.type = type$4;
|
|
1603
|
+
Radio.type = type$5;
|
|
1728
1604
|
Radio.label = 'Radio';
|
|
1729
1605
|
Radio.keyed = true;
|
|
1730
1606
|
Radio.emptyValue = null;
|
|
1731
1607
|
Radio.sanitizeValue = sanitizeSingleSelectValue;
|
|
1732
1608
|
|
|
1733
|
-
const type$
|
|
1609
|
+
const type$4 = 'select';
|
|
1734
1610
|
function Select(props) {
|
|
1735
1611
|
const {
|
|
1736
1612
|
disabled,
|
|
@@ -1747,7 +1623,6 @@ function Select(props) {
|
|
|
1747
1623
|
const {
|
|
1748
1624
|
required
|
|
1749
1625
|
} = validate;
|
|
1750
|
-
|
|
1751
1626
|
const onChange = ({
|
|
1752
1627
|
target
|
|
1753
1628
|
}) => {
|
|
@@ -1756,7 +1631,6 @@ function Select(props) {
|
|
|
1756
1631
|
value: target.value === '' ? null : target.value
|
|
1757
1632
|
});
|
|
1758
1633
|
};
|
|
1759
|
-
|
|
1760
1634
|
const {
|
|
1761
1635
|
state: loadState,
|
|
1762
1636
|
values: options
|
|
@@ -1765,7 +1639,10 @@ function Select(props) {
|
|
|
1765
1639
|
formId
|
|
1766
1640
|
} = hooks.useContext(FormContext);
|
|
1767
1641
|
return jsxRuntime.jsxs("div", {
|
|
1768
|
-
class: formFieldClasses(type$
|
|
1642
|
+
class: formFieldClasses(type$4, {
|
|
1643
|
+
errors,
|
|
1644
|
+
disabled
|
|
1645
|
+
}),
|
|
1769
1646
|
children: [jsxRuntime.jsx(Label, {
|
|
1770
1647
|
id: prefixId(id, formId),
|
|
1771
1648
|
label: label,
|
|
@@ -1791,7 +1668,6 @@ function Select(props) {
|
|
|
1791
1668
|
})]
|
|
1792
1669
|
});
|
|
1793
1670
|
}
|
|
1794
|
-
|
|
1795
1671
|
Select.create = function (options = {}) {
|
|
1796
1672
|
if (options.valuesKey) return options;
|
|
1797
1673
|
return {
|
|
@@ -1802,8 +1678,7 @@ Select.create = function (options = {}) {
|
|
|
1802
1678
|
...options
|
|
1803
1679
|
};
|
|
1804
1680
|
};
|
|
1805
|
-
|
|
1806
|
-
Select.type = type$3;
|
|
1681
|
+
Select.type = type$4;
|
|
1807
1682
|
Select.label = 'Select';
|
|
1808
1683
|
Select.keyed = true;
|
|
1809
1684
|
Select.emptyValue = null;
|
|
@@ -1822,7 +1697,7 @@ var CloseIcon = (({
|
|
|
1822
1697
|
fillRule: "evenodd",
|
|
1823
1698
|
clipRule: "evenodd",
|
|
1824
1699
|
d: "M12 4.7l-.7-.7L8 7.3 4.7 4l-.7.7L7.3 8 4 11.3l.7.7L8 8.7l3.3 3.3.7-.7L8.7 8 12 4.7z",
|
|
1825
|
-
fill: "
|
|
1700
|
+
fill: "currentColor"
|
|
1826
1701
|
})));
|
|
1827
1702
|
|
|
1828
1703
|
function useKeyDownAction(targetKey, action, listenerElement = window) {
|
|
@@ -1833,7 +1708,6 @@ function useKeyDownAction(targetKey, action, listenerElement = window) {
|
|
|
1833
1708
|
action();
|
|
1834
1709
|
}
|
|
1835
1710
|
}
|
|
1836
|
-
|
|
1837
1711
|
hooks.useEffect(() => {
|
|
1838
1712
|
listenerElement.addEventListener('keydown', downHandler);
|
|
1839
1713
|
return () => {
|
|
@@ -1843,9 +1717,7 @@ function useKeyDownAction(targetKey, action, listenerElement = window) {
|
|
|
1843
1717
|
}
|
|
1844
1718
|
|
|
1845
1719
|
const DEFAULT_LABEL_GETTER = value => value;
|
|
1846
|
-
|
|
1847
1720
|
const NOOP = () => {};
|
|
1848
|
-
|
|
1849
1721
|
function DropdownList(props) {
|
|
1850
1722
|
const {
|
|
1851
1723
|
keyEventsListener = window,
|
|
@@ -1865,7 +1737,6 @@ function DropdownList(props) {
|
|
|
1865
1737
|
}, [values.length]);
|
|
1866
1738
|
hooks.useEffect(() => {
|
|
1867
1739
|
if (focusedValueIndex === 0) return;
|
|
1868
|
-
|
|
1869
1740
|
if (!focusedValueIndex || !values.length) {
|
|
1870
1741
|
setFocusedValueIndex(0);
|
|
1871
1742
|
} else if (focusedValueIndex >= values.length) {
|
|
@@ -1891,7 +1762,6 @@ function DropdownList(props) {
|
|
|
1891
1762
|
}, keyEventsListener);
|
|
1892
1763
|
hooks.useEffect(() => {
|
|
1893
1764
|
const individualEntries = dropdownContainer.current.children;
|
|
1894
|
-
|
|
1895
1765
|
if (individualEntries.length && !mouseControl) {
|
|
1896
1766
|
individualEntries[focusedValueIndex].scrollIntoView({
|
|
1897
1767
|
block: 'nearest',
|
|
@@ -1899,23 +1769,19 @@ function DropdownList(props) {
|
|
|
1899
1769
|
});
|
|
1900
1770
|
}
|
|
1901
1771
|
}, [focusedValueIndex, mouseControl]);
|
|
1902
|
-
|
|
1903
1772
|
const mouseMove = (e, i) => {
|
|
1904
1773
|
const userMoved = !mouseScreenPos.current || mouseScreenPos.current.x !== e.screenX && mouseScreenPos.current.y !== e.screenY;
|
|
1905
|
-
|
|
1906
1774
|
if (userMoved) {
|
|
1907
1775
|
mouseScreenPos.current = {
|
|
1908
1776
|
x: e.screenX,
|
|
1909
1777
|
y: e.screenY
|
|
1910
1778
|
};
|
|
1911
|
-
|
|
1912
1779
|
if (!mouseControl) {
|
|
1913
1780
|
setMouseControl(true);
|
|
1914
1781
|
setFocusedValueIndex(i);
|
|
1915
1782
|
}
|
|
1916
1783
|
}
|
|
1917
1784
|
};
|
|
1918
|
-
|
|
1919
1785
|
return jsxRuntime.jsxs("div", {
|
|
1920
1786
|
ref: dropdownContainer,
|
|
1921
1787
|
tabIndex: -1,
|
|
@@ -1941,7 +1807,7 @@ function DropdownList(props) {
|
|
|
1941
1807
|
});
|
|
1942
1808
|
}
|
|
1943
1809
|
|
|
1944
|
-
const type$
|
|
1810
|
+
const type$3 = 'taglist';
|
|
1945
1811
|
function Taglist(props) {
|
|
1946
1812
|
const {
|
|
1947
1813
|
disabled,
|
|
@@ -1966,12 +1832,14 @@ function Taglist(props) {
|
|
|
1966
1832
|
const {
|
|
1967
1833
|
state: loadState,
|
|
1968
1834
|
values: options
|
|
1969
|
-
} = useValuesAsync(field);
|
|
1835
|
+
} = useValuesAsync(field);
|
|
1970
1836
|
|
|
1837
|
+
// We cache a map of option values to their index so that we don't need to search the whole options array every time to correlate the label
|
|
1971
1838
|
const valueToOptionMap = hooks.useMemo(() => Object.assign({}, ...options.map((o, x) => ({
|
|
1972
1839
|
[o.value]: options[x]
|
|
1973
|
-
}))), [options]);
|
|
1840
|
+
}))), [options]);
|
|
1974
1841
|
|
|
1842
|
+
// Usage of stringify is necessary here because we want this effect to only trigger when there is a value change to the array
|
|
1975
1843
|
hooks.useEffect(() => {
|
|
1976
1844
|
if (loadState === LOAD_STATES.LOADED) {
|
|
1977
1845
|
setFilteredOptions(options.filter(o => o.label && o.value && o.label.toLowerCase().includes(filter.toLowerCase()) && !values.includes(o.value)));
|
|
@@ -1982,37 +1850,32 @@ function Taglist(props) {
|
|
|
1982
1850
|
hooks.useEffect(() => {
|
|
1983
1851
|
setHasOptionsLeft(options.length > values.length);
|
|
1984
1852
|
}, [options.length, values.length]);
|
|
1985
|
-
|
|
1986
1853
|
const onFilterChange = ({
|
|
1987
1854
|
target
|
|
1988
1855
|
}) => {
|
|
1989
1856
|
setIsEscapeClose(false);
|
|
1990
1857
|
setFilter(target.value);
|
|
1991
1858
|
};
|
|
1992
|
-
|
|
1993
1859
|
const selectValue = value => {
|
|
1994
1860
|
if (filter) {
|
|
1995
1861
|
setFilter('');
|
|
1996
|
-
}
|
|
1997
|
-
|
|
1862
|
+
}
|
|
1998
1863
|
|
|
1864
|
+
// Ensure values cannot be double selected due to latency
|
|
1999
1865
|
if (values.at(-1) === value) {
|
|
2000
1866
|
return;
|
|
2001
1867
|
}
|
|
2002
|
-
|
|
2003
1868
|
props.onChange({
|
|
2004
1869
|
value: [...values, value],
|
|
2005
1870
|
field
|
|
2006
1871
|
});
|
|
2007
1872
|
};
|
|
2008
|
-
|
|
2009
1873
|
const deselectValue = value => {
|
|
2010
1874
|
props.onChange({
|
|
2011
1875
|
value: values.filter(v => v != value),
|
|
2012
1876
|
field
|
|
2013
1877
|
});
|
|
2014
1878
|
};
|
|
2015
|
-
|
|
2016
1879
|
const onInputKeyDown = e => {
|
|
2017
1880
|
switch (e.key) {
|
|
2018
1881
|
case 'ArrowUp':
|
|
@@ -2020,32 +1883,29 @@ function Taglist(props) {
|
|
|
2020
1883
|
// We do not want the cursor to seek in the search field when we press up and down
|
|
2021
1884
|
e.preventDefault();
|
|
2022
1885
|
break;
|
|
2023
|
-
|
|
2024
1886
|
case 'Backspace':
|
|
2025
1887
|
if (!filter && values.length) {
|
|
2026
1888
|
deselectValue(values[values.length - 1]);
|
|
2027
1889
|
}
|
|
2028
|
-
|
|
2029
1890
|
break;
|
|
2030
|
-
|
|
2031
1891
|
case 'Escape':
|
|
2032
1892
|
setIsEscapeClose(true);
|
|
2033
1893
|
break;
|
|
2034
|
-
|
|
2035
1894
|
case 'Enter':
|
|
2036
1895
|
if (isEscapeClosed) {
|
|
2037
1896
|
setIsEscapeClose(false);
|
|
2038
1897
|
}
|
|
2039
|
-
|
|
2040
1898
|
break;
|
|
2041
1899
|
}
|
|
2042
1900
|
};
|
|
2043
|
-
|
|
2044
1901
|
return jsxRuntime.jsxs("div", {
|
|
2045
|
-
class: formFieldClasses(type$
|
|
1902
|
+
class: formFieldClasses(type$3, {
|
|
1903
|
+
errors,
|
|
1904
|
+
disabled
|
|
1905
|
+
}),
|
|
2046
1906
|
children: [jsxRuntime.jsx(Label, {
|
|
2047
1907
|
label: label,
|
|
2048
|
-
id: prefixId(id
|
|
1908
|
+
id: prefixId(`${id}-search`, formId)
|
|
2049
1909
|
}), jsxRuntime.jsxs("div", {
|
|
2050
1910
|
class: classNames__default['default']('fjs-taglist', {
|
|
2051
1911
|
'disabled': disabled
|
|
@@ -2097,7 +1957,6 @@ function Taglist(props) {
|
|
|
2097
1957
|
})]
|
|
2098
1958
|
});
|
|
2099
1959
|
}
|
|
2100
|
-
|
|
2101
1960
|
Taglist.create = function (options = {}) {
|
|
2102
1961
|
if (options.valuesKey) return options;
|
|
2103
1962
|
return {
|
|
@@ -2108,14 +1967,13 @@ Taglist.create = function (options = {}) {
|
|
|
2108
1967
|
...options
|
|
2109
1968
|
};
|
|
2110
1969
|
};
|
|
2111
|
-
|
|
2112
|
-
Taglist.type = type$2;
|
|
1970
|
+
Taglist.type = type$3;
|
|
2113
1971
|
Taglist.label = 'Taglist';
|
|
2114
1972
|
Taglist.keyed = true;
|
|
2115
1973
|
Taglist.emptyValue = [];
|
|
2116
1974
|
Taglist.sanitizeValue = sanitizeMultiSelectValue;
|
|
2117
1975
|
|
|
2118
|
-
const type$
|
|
1976
|
+
const type$2 = 'text';
|
|
2119
1977
|
function Text(props) {
|
|
2120
1978
|
const {
|
|
2121
1979
|
field
|
|
@@ -2124,25 +1982,23 @@ function Text(props) {
|
|
|
2124
1982
|
text = ''
|
|
2125
1983
|
} = field;
|
|
2126
1984
|
return jsxRuntime.jsx("div", {
|
|
2127
|
-
class: formFieldClasses(type$
|
|
1985
|
+
class: formFieldClasses(type$2),
|
|
2128
1986
|
children: jsxRuntime.jsx(Markup__default['default'], {
|
|
2129
1987
|
markup: safeMarkdown(text),
|
|
2130
1988
|
trim: false
|
|
2131
1989
|
})
|
|
2132
1990
|
});
|
|
2133
1991
|
}
|
|
2134
|
-
|
|
2135
1992
|
Text.create = function (options = {}) {
|
|
2136
1993
|
return {
|
|
2137
1994
|
text: '# Text',
|
|
2138
1995
|
...options
|
|
2139
1996
|
};
|
|
2140
1997
|
};
|
|
2141
|
-
|
|
2142
|
-
Text.type = type$1;
|
|
1998
|
+
Text.type = type$2;
|
|
2143
1999
|
Text.keyed = false;
|
|
2144
2000
|
|
|
2145
|
-
const type = 'textfield';
|
|
2001
|
+
const type$1 = 'textfield';
|
|
2146
2002
|
function Textfield(props) {
|
|
2147
2003
|
const {
|
|
2148
2004
|
disabled,
|
|
@@ -2159,7 +2015,6 @@ function Textfield(props) {
|
|
|
2159
2015
|
const {
|
|
2160
2016
|
required
|
|
2161
2017
|
} = validate;
|
|
2162
|
-
|
|
2163
2018
|
const onChange = ({
|
|
2164
2019
|
target
|
|
2165
2020
|
}) => {
|
|
@@ -2168,12 +2023,14 @@ function Textfield(props) {
|
|
|
2168
2023
|
value: target.value
|
|
2169
2024
|
});
|
|
2170
2025
|
};
|
|
2171
|
-
|
|
2172
2026
|
const {
|
|
2173
2027
|
formId
|
|
2174
2028
|
} = hooks.useContext(FormContext);
|
|
2175
2029
|
return jsxRuntime.jsxs("div", {
|
|
2176
|
-
class: formFieldClasses(type,
|
|
2030
|
+
class: formFieldClasses(type$1, {
|
|
2031
|
+
errors,
|
|
2032
|
+
disabled
|
|
2033
|
+
}),
|
|
2177
2034
|
children: [jsxRuntime.jsx(Label, {
|
|
2178
2035
|
id: prefixId(id, formId),
|
|
2179
2036
|
label: label,
|
|
@@ -2192,22 +2049,101 @@ function Textfield(props) {
|
|
|
2192
2049
|
})]
|
|
2193
2050
|
});
|
|
2194
2051
|
}
|
|
2195
|
-
|
|
2196
2052
|
Textfield.create = function (options = {}) {
|
|
2197
|
-
return {
|
|
2053
|
+
return {
|
|
2054
|
+
...options
|
|
2198
2055
|
};
|
|
2199
2056
|
};
|
|
2200
|
-
|
|
2201
|
-
Textfield.
|
|
2202
|
-
Textfield.label = 'Text Field';
|
|
2057
|
+
Textfield.type = type$1;
|
|
2058
|
+
Textfield.label = 'Text field';
|
|
2203
2059
|
Textfield.keyed = true;
|
|
2204
2060
|
Textfield.emptyValue = '';
|
|
2205
|
-
|
|
2206
2061
|
Textfield.sanitizeValue = ({
|
|
2207
2062
|
value
|
|
2208
|
-
}) => minDash.isArray(value) || minDash.isObject(value) ?
|
|
2063
|
+
}) => minDash.isArray(value) || minDash.isObject(value) ? '' : String(value);
|
|
2209
2064
|
|
|
2210
|
-
const
|
|
2065
|
+
const type = 'textarea';
|
|
2066
|
+
function Textarea(props) {
|
|
2067
|
+
const {
|
|
2068
|
+
disabled,
|
|
2069
|
+
errors = [],
|
|
2070
|
+
field,
|
|
2071
|
+
value = ''
|
|
2072
|
+
} = props;
|
|
2073
|
+
const {
|
|
2074
|
+
description,
|
|
2075
|
+
id,
|
|
2076
|
+
label,
|
|
2077
|
+
validate = {}
|
|
2078
|
+
} = field;
|
|
2079
|
+
const {
|
|
2080
|
+
required
|
|
2081
|
+
} = validate;
|
|
2082
|
+
const textareaRef = hooks.useRef();
|
|
2083
|
+
const onInput = ({
|
|
2084
|
+
target
|
|
2085
|
+
}) => {
|
|
2086
|
+
props.onChange({
|
|
2087
|
+
field,
|
|
2088
|
+
value: target.value
|
|
2089
|
+
});
|
|
2090
|
+
};
|
|
2091
|
+
const autoSizeTextarea = hooks.useCallback(textarea => {
|
|
2092
|
+
// Ensures the textarea shrinks back, and improves resizing behavior consistency
|
|
2093
|
+
textarea.style.height = '0px';
|
|
2094
|
+
const computed = window.getComputedStyle(textarea);
|
|
2095
|
+
const calculatedHeight = parseInt(computed.getPropertyValue('border-top-width')) + parseInt(computed.getPropertyValue('padding-top')) + textarea.scrollHeight + parseInt(computed.getPropertyValue('padding-bottom')) + parseInt(computed.getPropertyValue('border-bottom-width'));
|
|
2096
|
+
const minHeight = 75;
|
|
2097
|
+
const maxHeight = 350;
|
|
2098
|
+
const displayHeight = Math.max(Math.min(calculatedHeight, maxHeight), minHeight);
|
|
2099
|
+
textarea.style.height = `${displayHeight}px`;
|
|
2100
|
+
|
|
2101
|
+
// Overflow is hidden by default to hide scrollbar flickering
|
|
2102
|
+
textarea.style.overflow = calculatedHeight > maxHeight ? 'visible' : 'hidden';
|
|
2103
|
+
}, []);
|
|
2104
|
+
hooks.useEffect(() => {
|
|
2105
|
+
autoSizeTextarea(textareaRef.current);
|
|
2106
|
+
}, [autoSizeTextarea, value]);
|
|
2107
|
+
const {
|
|
2108
|
+
formId
|
|
2109
|
+
} = hooks.useContext(FormContext);
|
|
2110
|
+
return jsxRuntime.jsxs("div", {
|
|
2111
|
+
class: formFieldClasses(type, {
|
|
2112
|
+
errors,
|
|
2113
|
+
disabled
|
|
2114
|
+
}),
|
|
2115
|
+
children: [jsxRuntime.jsx(Label, {
|
|
2116
|
+
id: prefixId(id, formId),
|
|
2117
|
+
label: label,
|
|
2118
|
+
required: required
|
|
2119
|
+
}), jsxRuntime.jsx("textarea", {
|
|
2120
|
+
class: "fjs-textarea",
|
|
2121
|
+
disabled: disabled,
|
|
2122
|
+
id: prefixId(id, formId),
|
|
2123
|
+
onInput: onInput,
|
|
2124
|
+
value: value,
|
|
2125
|
+
ref: textareaRef
|
|
2126
|
+
}), jsxRuntime.jsx(Description, {
|
|
2127
|
+
description: description
|
|
2128
|
+
}), jsxRuntime.jsx(Errors, {
|
|
2129
|
+
errors: errors
|
|
2130
|
+
})]
|
|
2131
|
+
});
|
|
2132
|
+
}
|
|
2133
|
+
Textarea.create = function (options = {}) {
|
|
2134
|
+
return {
|
|
2135
|
+
...options
|
|
2136
|
+
};
|
|
2137
|
+
};
|
|
2138
|
+
Textarea.type = type;
|
|
2139
|
+
Textarea.label = 'Text area';
|
|
2140
|
+
Textarea.keyed = true;
|
|
2141
|
+
Textarea.emptyValue = '';
|
|
2142
|
+
Textarea.sanitizeValue = ({
|
|
2143
|
+
value
|
|
2144
|
+
}) => minDash.isArray(value) || minDash.isObject(value) ? '' : String(value);
|
|
2145
|
+
|
|
2146
|
+
const formFields = [Button, Checkbox, Checklist, Default, Number, Radio, Select, Taglist, Text, Textfield, Textarea];
|
|
2211
2147
|
|
|
2212
2148
|
class FormFields {
|
|
2213
2149
|
constructor() {
|
|
@@ -2219,15 +2155,12 @@ class FormFields {
|
|
|
2219
2155
|
this.register(type, formField);
|
|
2220
2156
|
});
|
|
2221
2157
|
}
|
|
2222
|
-
|
|
2223
2158
|
register(type, formField) {
|
|
2224
2159
|
this._formFields[type] = formField;
|
|
2225
2160
|
}
|
|
2226
|
-
|
|
2227
2161
|
get(type) {
|
|
2228
2162
|
return this._formFields[type];
|
|
2229
2163
|
}
|
|
2230
|
-
|
|
2231
2164
|
}
|
|
2232
2165
|
|
|
2233
2166
|
function Renderer(config, eventBus, form, injector) {
|
|
@@ -2237,7 +2170,6 @@ function Renderer(config, eventBus, form, injector) {
|
|
|
2237
2170
|
getService(type, strict = true) {
|
|
2238
2171
|
return injector.get(type, strict);
|
|
2239
2172
|
},
|
|
2240
|
-
|
|
2241
2173
|
formId: form._id
|
|
2242
2174
|
};
|
|
2243
2175
|
eventBus.on('changed', newState => {
|
|
@@ -2259,11 +2191,9 @@ function Renderer(config, eventBus, form, injector) {
|
|
|
2259
2191
|
const {
|
|
2260
2192
|
schema
|
|
2261
2193
|
} = state;
|
|
2262
|
-
|
|
2263
2194
|
if (!schema) {
|
|
2264
2195
|
return null;
|
|
2265
2196
|
}
|
|
2266
|
-
|
|
2267
2197
|
return jsxRuntime.jsx(FormContext.Provider, {
|
|
2268
2198
|
value: formContext,
|
|
2269
2199
|
children: jsxRuntime.jsx(FormComponent, {
|
|
@@ -2273,7 +2203,6 @@ function Renderer(config, eventBus, form, injector) {
|
|
|
2273
2203
|
})
|
|
2274
2204
|
});
|
|
2275
2205
|
};
|
|
2276
|
-
|
|
2277
2206
|
const {
|
|
2278
2207
|
container
|
|
2279
2208
|
} = config;
|
|
@@ -2323,10 +2252,10 @@ var core = {
|
|
|
2323
2252
|
*/
|
|
2324
2253
|
|
|
2325
2254
|
const ids = new Ids__default['default']([32, 36, 1]);
|
|
2255
|
+
|
|
2326
2256
|
/**
|
|
2327
2257
|
* The form.
|
|
2328
2258
|
*/
|
|
2329
|
-
|
|
2330
2259
|
class Form {
|
|
2331
2260
|
/**
|
|
2332
2261
|
* @constructor
|
|
@@ -2338,28 +2267,28 @@ class Form {
|
|
|
2338
2267
|
* @type {OnEventType}
|
|
2339
2268
|
*/
|
|
2340
2269
|
this.on = this._onEvent;
|
|
2270
|
+
|
|
2341
2271
|
/**
|
|
2342
2272
|
* @public
|
|
2343
2273
|
* @type {String}
|
|
2344
2274
|
*/
|
|
2345
|
-
|
|
2346
2275
|
this._id = ids.next();
|
|
2276
|
+
|
|
2347
2277
|
/**
|
|
2348
2278
|
* @private
|
|
2349
2279
|
* @type {Element}
|
|
2350
2280
|
*/
|
|
2351
|
-
|
|
2352
2281
|
this._container = createFormContainer();
|
|
2353
2282
|
const {
|
|
2354
2283
|
container,
|
|
2355
2284
|
injector = this._createInjector(options, this._container),
|
|
2356
2285
|
properties = {}
|
|
2357
2286
|
} = options;
|
|
2287
|
+
|
|
2358
2288
|
/**
|
|
2359
2289
|
* @private
|
|
2360
2290
|
* @type {State}
|
|
2361
2291
|
*/
|
|
2362
|
-
|
|
2363
2292
|
this._state = {
|
|
2364
2293
|
initialData: null,
|
|
2365
2294
|
data: null,
|
|
@@ -2370,33 +2299,31 @@ class Form {
|
|
|
2370
2299
|
this.get = injector.get;
|
|
2371
2300
|
this.invoke = injector.invoke;
|
|
2372
2301
|
this.get('eventBus').fire('form.init');
|
|
2373
|
-
|
|
2374
2302
|
if (container) {
|
|
2375
2303
|
this.attachTo(container);
|
|
2376
2304
|
}
|
|
2377
2305
|
}
|
|
2378
|
-
|
|
2379
2306
|
clear() {
|
|
2380
2307
|
// clear form services
|
|
2381
|
-
this._emit('diagram.clear');
|
|
2382
|
-
|
|
2308
|
+
this._emit('diagram.clear');
|
|
2383
2309
|
|
|
2310
|
+
// clear diagram services (e.g. EventBus)
|
|
2384
2311
|
this._emit('form.clear');
|
|
2385
2312
|
}
|
|
2313
|
+
|
|
2386
2314
|
/**
|
|
2387
2315
|
* Destroy the form, removing it from DOM,
|
|
2388
2316
|
* if attached.
|
|
2389
2317
|
*/
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
2318
|
destroy() {
|
|
2393
2319
|
// destroy form services
|
|
2394
|
-
this.get('eventBus').fire('form.destroy');
|
|
2320
|
+
this.get('eventBus').fire('form.destroy');
|
|
2395
2321
|
|
|
2322
|
+
// destroy diagram services (e.g. EventBus)
|
|
2396
2323
|
this.get('eventBus').fire('diagram.destroy');
|
|
2397
|
-
|
|
2398
2324
|
this._detach(false);
|
|
2399
2325
|
}
|
|
2326
|
+
|
|
2400
2327
|
/**
|
|
2401
2328
|
* Open a form schema with the given initial data.
|
|
2402
2329
|
*
|
|
@@ -2405,8 +2332,6 @@ class Form {
|
|
|
2405
2332
|
*
|
|
2406
2333
|
* @return Promise<{ warnings: Array<any> }>
|
|
2407
2334
|
*/
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
2335
|
importSchema(schema, data = {}) {
|
|
2411
2336
|
return new Promise((resolve, reject) => {
|
|
2412
2337
|
try {
|
|
@@ -2416,18 +2341,15 @@ class Form {
|
|
|
2416
2341
|
data: importedData,
|
|
2417
2342
|
warnings
|
|
2418
2343
|
} = this.get('importer').importSchema(schema, data);
|
|
2419
|
-
|
|
2420
2344
|
this._setState({
|
|
2421
2345
|
data: importedData,
|
|
2422
2346
|
errors: {},
|
|
2423
2347
|
schema: importedSchema,
|
|
2424
2348
|
initialData: clone(importedData)
|
|
2425
2349
|
});
|
|
2426
|
-
|
|
2427
2350
|
this._emit('import.done', {
|
|
2428
2351
|
warnings
|
|
2429
2352
|
});
|
|
2430
|
-
|
|
2431
2353
|
return resolve({
|
|
2432
2354
|
warnings
|
|
2433
2355
|
});
|
|
@@ -2436,168 +2358,124 @@ class Form {
|
|
|
2436
2358
|
error,
|
|
2437
2359
|
warnings: error.warnings || []
|
|
2438
2360
|
});
|
|
2439
|
-
|
|
2440
2361
|
return reject(error);
|
|
2441
2362
|
}
|
|
2442
2363
|
});
|
|
2443
2364
|
}
|
|
2365
|
+
|
|
2444
2366
|
/**
|
|
2445
2367
|
* Submit the form, triggering all field validations.
|
|
2446
2368
|
*
|
|
2447
2369
|
* @returns { { data: Data, errors: Errors } }
|
|
2448
2370
|
*/
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
2371
|
submit() {
|
|
2452
2372
|
const {
|
|
2453
2373
|
properties
|
|
2454
2374
|
} = this._getState();
|
|
2455
|
-
|
|
2456
2375
|
if (properties.readOnly) {
|
|
2457
2376
|
throw new Error('form is read-only');
|
|
2458
2377
|
}
|
|
2459
|
-
|
|
2460
|
-
const formFieldRegistry = this.get('formFieldRegistry');
|
|
2461
|
-
const data = formFieldRegistry.getAll().reduce((data, field) => {
|
|
2462
|
-
const {
|
|
2463
|
-
disabled,
|
|
2464
|
-
_path
|
|
2465
|
-
} = field; // do not submit disabled form fields
|
|
2466
|
-
|
|
2467
|
-
if (disabled || !_path) {
|
|
2468
|
-
return data;
|
|
2469
|
-
}
|
|
2470
|
-
|
|
2471
|
-
const value = minDash.get(this._getState().data, _path);
|
|
2472
|
-
return { ...data,
|
|
2473
|
-
[_path[0]]: value
|
|
2474
|
-
};
|
|
2475
|
-
}, {});
|
|
2378
|
+
const data = this._getSubmitData();
|
|
2476
2379
|
const errors = this.validate();
|
|
2477
|
-
|
|
2478
2380
|
this._emit('submit', {
|
|
2479
2381
|
data,
|
|
2480
2382
|
errors
|
|
2481
2383
|
});
|
|
2482
|
-
|
|
2483
2384
|
return {
|
|
2484
2385
|
data,
|
|
2485
2386
|
errors
|
|
2486
2387
|
};
|
|
2487
2388
|
}
|
|
2488
|
-
|
|
2489
2389
|
reset() {
|
|
2490
2390
|
this._emit('reset');
|
|
2491
|
-
|
|
2492
2391
|
this._setState({
|
|
2493
2392
|
data: clone(this._state.initialData),
|
|
2494
2393
|
errors: {}
|
|
2495
2394
|
});
|
|
2496
2395
|
}
|
|
2396
|
+
|
|
2497
2397
|
/**
|
|
2498
2398
|
* @returns {Errors}
|
|
2499
2399
|
*/
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
2400
|
validate() {
|
|
2503
2401
|
const formFieldRegistry = this.get('formFieldRegistry'),
|
|
2504
|
-
|
|
2505
|
-
|
|
2402
|
+
validator = this.get('validator');
|
|
2506
2403
|
const {
|
|
2507
2404
|
data
|
|
2508
2405
|
} = this._getState();
|
|
2509
|
-
|
|
2510
2406
|
const errors = formFieldRegistry.getAll().reduce((errors, field) => {
|
|
2511
2407
|
const {
|
|
2512
2408
|
disabled,
|
|
2513
2409
|
_path
|
|
2514
2410
|
} = field;
|
|
2515
|
-
|
|
2516
2411
|
if (disabled) {
|
|
2517
2412
|
return errors;
|
|
2518
2413
|
}
|
|
2519
|
-
|
|
2520
2414
|
const value = minDash.get(data, _path);
|
|
2521
2415
|
const fieldErrors = validator.validateField(field, value);
|
|
2522
2416
|
return minDash.set(errors, [pathStringify(_path)], fieldErrors.length ? fieldErrors : undefined);
|
|
2523
|
-
},
|
|
2524
|
-
/** @type {Errors} */
|
|
2525
|
-
{});
|
|
2526
|
-
|
|
2417
|
+
}, /** @type {Errors} */{});
|
|
2527
2418
|
this._setState({
|
|
2528
2419
|
errors
|
|
2529
2420
|
});
|
|
2530
|
-
|
|
2531
2421
|
return errors;
|
|
2532
2422
|
}
|
|
2423
|
+
|
|
2533
2424
|
/**
|
|
2534
2425
|
* @param {Element|string} parentNode
|
|
2535
2426
|
*/
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
2427
|
attachTo(parentNode) {
|
|
2539
2428
|
if (!parentNode) {
|
|
2540
2429
|
throw new Error('parentNode required');
|
|
2541
2430
|
}
|
|
2542
|
-
|
|
2543
2431
|
this.detach();
|
|
2544
|
-
|
|
2545
2432
|
if (minDash.isString(parentNode)) {
|
|
2546
2433
|
parentNode = document.querySelector(parentNode);
|
|
2547
2434
|
}
|
|
2548
|
-
|
|
2549
2435
|
const container = this._container;
|
|
2550
2436
|
parentNode.appendChild(container);
|
|
2551
|
-
|
|
2552
2437
|
this._emit('attach');
|
|
2553
2438
|
}
|
|
2554
|
-
|
|
2555
2439
|
detach() {
|
|
2556
2440
|
this._detach();
|
|
2557
2441
|
}
|
|
2442
|
+
|
|
2558
2443
|
/**
|
|
2559
2444
|
* @private
|
|
2560
2445
|
*
|
|
2561
2446
|
* @param {boolean} [emit]
|
|
2562
2447
|
*/
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
2448
|
_detach(emit = true) {
|
|
2566
2449
|
const container = this._container,
|
|
2567
|
-
|
|
2568
|
-
|
|
2450
|
+
parentNode = container.parentNode;
|
|
2569
2451
|
if (!parentNode) {
|
|
2570
2452
|
return;
|
|
2571
2453
|
}
|
|
2572
|
-
|
|
2573
2454
|
if (emit) {
|
|
2574
2455
|
this._emit('detach');
|
|
2575
2456
|
}
|
|
2576
|
-
|
|
2577
2457
|
parentNode.removeChild(container);
|
|
2578
2458
|
}
|
|
2459
|
+
|
|
2579
2460
|
/**
|
|
2580
2461
|
* @param {FormProperty} property
|
|
2581
2462
|
* @param {any} value
|
|
2582
2463
|
*/
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
2464
|
setProperty(property, value) {
|
|
2586
2465
|
const properties = minDash.set(this._getState().properties, [property], value);
|
|
2587
|
-
|
|
2588
2466
|
this._setState({
|
|
2589
2467
|
properties
|
|
2590
2468
|
});
|
|
2591
2469
|
}
|
|
2470
|
+
|
|
2592
2471
|
/**
|
|
2593
2472
|
* @param {FormEvent} type
|
|
2594
2473
|
* @param {Function} handler
|
|
2595
2474
|
*/
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
2475
|
off(type, handler) {
|
|
2599
2476
|
this.get('eventBus').off(type, handler);
|
|
2600
2477
|
}
|
|
2478
|
+
|
|
2601
2479
|
/**
|
|
2602
2480
|
* @private
|
|
2603
2481
|
*
|
|
@@ -2606,8 +2484,6 @@ class Form {
|
|
|
2606
2484
|
*
|
|
2607
2485
|
* @returns {Injector}
|
|
2608
2486
|
*/
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
2487
|
_createInjector(options, container) {
|
|
2612
2488
|
const {
|
|
2613
2489
|
additionalModules = [],
|
|
@@ -2624,21 +2500,19 @@ class Form {
|
|
|
2624
2500
|
form: ['value', this]
|
|
2625
2501
|
}, core, ...modules, ...additionalModules]);
|
|
2626
2502
|
}
|
|
2503
|
+
|
|
2627
2504
|
/**
|
|
2628
2505
|
* @private
|
|
2629
2506
|
*/
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
2507
|
_emit(type, data) {
|
|
2633
2508
|
this.get('eventBus').fire(type, data);
|
|
2634
2509
|
}
|
|
2510
|
+
|
|
2635
2511
|
/**
|
|
2636
2512
|
* @internal
|
|
2637
2513
|
*
|
|
2638
2514
|
* @param { { add?: boolean, field: any, remove?: number, value?: any } } update
|
|
2639
2515
|
*/
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
2516
|
_update(update) {
|
|
2643
2517
|
const {
|
|
2644
2518
|
field,
|
|
@@ -2647,54 +2521,71 @@ class Form {
|
|
|
2647
2521
|
const {
|
|
2648
2522
|
_path
|
|
2649
2523
|
} = field;
|
|
2650
|
-
|
|
2651
2524
|
let {
|
|
2652
2525
|
data,
|
|
2653
2526
|
errors
|
|
2654
2527
|
} = this._getState();
|
|
2655
|
-
|
|
2656
2528
|
const validator = this.get('validator');
|
|
2657
2529
|
const fieldErrors = validator.validateField(field, value);
|
|
2658
2530
|
minDash.set(data, _path, value);
|
|
2659
2531
|
minDash.set(errors, [pathStringify(_path)], fieldErrors.length ? fieldErrors : undefined);
|
|
2660
|
-
|
|
2661
2532
|
this._setState({
|
|
2662
2533
|
data: clone(data),
|
|
2663
2534
|
errors: clone(errors)
|
|
2664
2535
|
});
|
|
2665
2536
|
}
|
|
2537
|
+
|
|
2666
2538
|
/**
|
|
2667
2539
|
* @internal
|
|
2668
2540
|
*/
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
2541
|
_getState() {
|
|
2672
2542
|
return this._state;
|
|
2673
2543
|
}
|
|
2544
|
+
|
|
2674
2545
|
/**
|
|
2675
2546
|
* @internal
|
|
2676
2547
|
*/
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
2548
|
_setState(state) {
|
|
2680
|
-
this._state = {
|
|
2549
|
+
this._state = {
|
|
2550
|
+
...this._state,
|
|
2681
2551
|
...state
|
|
2682
2552
|
};
|
|
2683
|
-
|
|
2684
2553
|
this._emit('changed', this._getState());
|
|
2685
2554
|
}
|
|
2555
|
+
|
|
2686
2556
|
/**
|
|
2687
2557
|
* @internal
|
|
2688
2558
|
*/
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
2559
|
_onEvent(type, priority, handler) {
|
|
2692
2560
|
this.get('eventBus').on(type, priority, handler);
|
|
2693
2561
|
}
|
|
2694
2562
|
|
|
2563
|
+
/**
|
|
2564
|
+
* @internal
|
|
2565
|
+
*/
|
|
2566
|
+
_getSubmitData() {
|
|
2567
|
+
const formFieldRegistry = this.get('formFieldRegistry');
|
|
2568
|
+
return formFieldRegistry.getAll().reduce((data, field) => {
|
|
2569
|
+
const {
|
|
2570
|
+
disabled,
|
|
2571
|
+
_path
|
|
2572
|
+
} = field;
|
|
2573
|
+
|
|
2574
|
+
// do not submit disabled form fields
|
|
2575
|
+
if (disabled || !_path) {
|
|
2576
|
+
return data;
|
|
2577
|
+
}
|
|
2578
|
+
const value = minDash.get(this._getState().data, _path);
|
|
2579
|
+
return {
|
|
2580
|
+
...data,
|
|
2581
|
+
[_path[0]]: value
|
|
2582
|
+
};
|
|
2583
|
+
}, {});
|
|
2584
|
+
}
|
|
2695
2585
|
}
|
|
2696
2586
|
|
|
2697
|
-
const schemaVersion =
|
|
2587
|
+
const schemaVersion = 6;
|
|
2588
|
+
|
|
2698
2589
|
/**
|
|
2699
2590
|
* @typedef { import('./types').CreateFormOptions } CreateFormOptions
|
|
2700
2591
|
*/
|
|
@@ -2706,7 +2597,6 @@ const schemaVersion = 5;
|
|
|
2706
2597
|
*
|
|
2707
2598
|
* @return {Promise<Form>}
|
|
2708
2599
|
*/
|
|
2709
|
-
|
|
2710
2600
|
function createForm(options) {
|
|
2711
2601
|
const {
|
|
2712
2602
|
data,
|
|
@@ -2734,6 +2624,7 @@ exports.Radio = Radio;
|
|
|
2734
2624
|
exports.Select = Select;
|
|
2735
2625
|
exports.Taglist = Taglist;
|
|
2736
2626
|
exports.Text = Text;
|
|
2627
|
+
exports.Textarea = Textarea;
|
|
2737
2628
|
exports.Textfield = Textfield;
|
|
2738
2629
|
exports.clone = clone;
|
|
2739
2630
|
exports.createForm = createForm;
|