@nanoporetech-digital/components 2.12.0 → 2.13.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/CHANGELOG.md +18 -0
- package/dist/cjs/index.cjs.js +2 -0
- package/dist/cjs/index.cjs.js.map +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/nano-components.cjs.js +1 -1
- package/dist/cjs/nano-field-validator.cjs.entry.js +250 -118
- package/dist/cjs/nano-field-validator.cjs.entry.js.map +1 -1
- package/dist/cjs/nano-file-upload.cjs.entry.js +1 -1
- package/dist/cjs/nano-file-upload.cjs.entry.js.map +1 -1
- package/dist/cjs/nano-input.cjs.entry.js +16 -3
- package/dist/cjs/nano-input.cjs.entry.js.map +1 -1
- package/dist/cjs/nano-nav-item_2.cjs.entry.js +1 -0
- package/dist/cjs/nano-nav-item_2.cjs.entry.js.map +1 -1
- package/dist/collection/components/accordion/accordion.js +1 -1
- package/dist/collection/components/alert/alert.js +1 -1
- package/dist/collection/components/algolia/algolia-filter.js +2 -2
- package/dist/collection/components/algolia/algolia-input.js +5 -5
- package/dist/collection/components/algolia/algolia-results.js +1 -1
- package/dist/collection/components/algolia/algolia.js +6 -6
- package/dist/collection/components/checkbox/checkbox-group.js +2 -2
- package/dist/collection/components/checkbox/checkbox.js +3 -3
- package/dist/collection/components/datalist/datalist.js +1 -1
- package/dist/collection/components/date-input/date-input.js +8 -8
- package/dist/collection/components/date-picker/date-picker.js +5 -5
- package/dist/collection/components/details/details.js +1 -1
- package/dist/collection/components/dialog/dialog.js +1 -1
- package/dist/collection/components/dropdown/dropdown.js +1 -1
- package/dist/collection/components/field-validator/field-validator-interface.js.map +1 -1
- package/dist/collection/components/field-validator/field-validator.js +329 -124
- package/dist/collection/components/field-validator/field-validator.js.map +1 -1
- package/dist/collection/components/file-upload/file-upload.css +0 -1
- package/dist/collection/components/file-upload/file-upload.js +4 -4
- package/dist/collection/components/global-nav/global-nav.js +4 -4
- package/dist/collection/components/grid/grid-item.js +1 -1
- package/dist/collection/components/icon/icon.js +1 -1
- package/dist/collection/components/input/input.js +37 -8
- package/dist/collection/components/input/input.js.map +1 -1
- package/dist/collection/components/nav-item/nav-item.js +4 -4
- package/dist/collection/components/range/range.js +4 -4
- package/dist/collection/components/resize-observe/resize-observe.js +1 -1
- package/dist/collection/components/select/select.js +8 -7
- package/dist/collection/components/select/select.js.map +1 -1
- package/dist/collection/components/slides/slides.js +7 -7
- package/dist/collection/components/tabs/tab-group.js +2 -2
- package/dist/collection/index.js +1 -0
- package/dist/collection/index.js.map +1 -1
- package/dist/components/index.js +1 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/input.js +17 -3
- package/dist/components/input.js.map +1 -1
- package/dist/components/nano-field-validator.js +255 -120
- package/dist/components/nano-field-validator.js.map +1 -1
- package/dist/components/nano-file-upload.js +1 -1
- package/dist/components/nano-file-upload.js.map +1 -1
- package/dist/components/select.js +1 -0
- package/dist/components/select.js.map +1 -1
- package/dist/custom-elements/index.js +270 -124
- package/dist/custom-elements/index.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/nano-components.js +1 -1
- package/dist/esm/nano-field-validator.entry.js +250 -118
- package/dist/esm/nano-field-validator.entry.js.map +1 -1
- package/dist/esm/nano-file-upload.entry.js +1 -1
- package/dist/esm/nano-file-upload.entry.js.map +1 -1
- package/dist/esm/nano-input.entry.js +16 -3
- package/dist/esm/nano-input.entry.js.map +1 -1
- package/dist/esm/nano-nav-item_2.entry.js +1 -0
- package/dist/esm/nano-nav-item_2.entry.js.map +1 -1
- package/dist/esm-es5/index.js +2 -2
- package/dist/esm-es5/index.js.map +1 -1
- package/dist/esm-es5/loader.js +1 -1
- package/dist/esm-es5/loader.js.map +1 -1
- package/dist/esm-es5/nano-components.js +1 -1
- package/dist/esm-es5/nano-components.js.map +1 -1
- package/dist/esm-es5/nano-field-validator.entry.js +2 -2
- package/dist/esm-es5/nano-field-validator.entry.js.map +1 -1
- package/dist/esm-es5/nano-file-upload.entry.js +1 -1
- package/dist/esm-es5/nano-file-upload.entry.js.map +1 -1
- package/dist/esm-es5/nano-input.entry.js +1 -1
- package/dist/esm-es5/nano-input.entry.js.map +1 -1
- package/dist/esm-es5/nano-nav-item_2.entry.js +1 -1
- package/dist/esm-es5/nano-nav-item_2.entry.js.map +1 -1
- package/dist/nano-components/index.esm.js +1 -1
- package/dist/nano-components/index.esm.js.map +1 -1
- package/dist/nano-components/nano-components.esm.js +1 -1
- package/dist/nano-components/nano-components.esm.js.map +1 -1
- package/dist/nano-components/p-0d699368.system.js +5 -0
- package/dist/nano-components/{p-3258c568.system.js.map → p-0d699368.system.js.map} +1 -1
- package/dist/nano-components/p-18863670.system.entry.js +5 -0
- package/dist/nano-components/p-18863670.system.entry.js.map +1 -0
- package/dist/nano-components/p-53957ec6.system.js +1 -1
- package/dist/nano-components/p-53957ec6.system.js.map +1 -1
- package/dist/nano-components/{p-01667573.entry.js → p-634a58f7.entry.js} +2 -2
- package/dist/nano-components/p-634a58f7.entry.js.map +1 -0
- package/dist/nano-components/p-7f051c20.entry.js +5 -0
- package/dist/nano-components/p-7f051c20.entry.js.map +1 -0
- package/dist/nano-components/p-a07cf44c.system.entry.js +5 -0
- package/dist/nano-components/{p-4558a9c6.system.entry.js.map → p-a07cf44c.system.entry.js.map} +1 -1
- package/dist/nano-components/{p-96d9b8b9.system.entry.js → p-c2bbf0fb.system.entry.js} +2 -2
- package/dist/nano-components/p-c2bbf0fb.system.entry.js.map +1 -0
- package/dist/nano-components/{p-72893d12.system.entry.js → p-cb512cff.system.entry.js} +2 -2
- package/dist/nano-components/p-cb512cff.system.entry.js.map +1 -0
- package/dist/nano-components/p-e9fddc1a.entry.js +5 -0
- package/dist/nano-components/{p-91614b43.entry.js.map → p-e9fddc1a.entry.js.map} +1 -1
- package/dist/nano-components/{p-055f7d35.entry.js → p-ed0bdea9.entry.js} +2 -2
- package/dist/nano-components/p-ed0bdea9.entry.js.map +1 -0
- package/dist/themes/nanopore.css +1 -1
- package/dist/themes/nanopore.css.map +1 -1
- package/dist/types/components/field-validator/field-validator-interface.d.ts +5 -1
- package/dist/types/components/field-validator/field-validator.d.ts +61 -12
- package/dist/types/components/input/input.d.ts +6 -1
- package/dist/types/components.d.ts +25 -3
- package/dist/types/index.d.ts +1 -0
- package/docs-json.json +65 -3
- package/docs-vscode.json +6 -2
- package/package.json +2 -2
- package/dist/nano-components/p-01667573.entry.js.map +0 -1
- package/dist/nano-components/p-055f7d35.entry.js.map +0 -1
- package/dist/nano-components/p-2b478ca1.system.entry.js +0 -5
- package/dist/nano-components/p-2b478ca1.system.entry.js.map +0 -1
- package/dist/nano-components/p-3258c568.system.js +0 -5
- package/dist/nano-components/p-4558a9c6.system.entry.js +0 -5
- package/dist/nano-components/p-5f4fc2b4.entry.js +0 -5
- package/dist/nano-components/p-5f4fc2b4.entry.js.map +0 -1
- package/dist/nano-components/p-72893d12.system.entry.js.map +0 -1
- package/dist/nano-components/p-91614b43.entry.js +0 -5
- package/dist/nano-components/p-96d9b8b9.system.entry.js.map +0 -1
@@ -195,8 +195,15 @@ let FieldValidator = class extends HTMLElement {
|
|
195
195
|
this.nanoSubmit = createEvent(this, "nanoSubmit", 7);
|
196
196
|
this.nanoInvalid = createEvent(this, "nanoInvalid", 7);
|
197
197
|
this.submitted = false;
|
198
|
-
this.
|
199
|
-
|
198
|
+
this.allFields = [];
|
199
|
+
this.nanoFieldSelector = `
|
200
|
+
nano-input,
|
201
|
+
nano-select,
|
202
|
+
nano-file-upload,
|
203
|
+
nano-date-input,
|
204
|
+
nano-checkbox
|
205
|
+
`;
|
206
|
+
// annoyingly, whenever we attempt to `checkValidty()` it fires `invalid` events.
|
200
207
|
// this is used to prevent infinite loops / multiple calls
|
201
208
|
this.internalValidate = false;
|
202
209
|
// Public API
|
@@ -205,12 +212,27 @@ let FieldValidator = class extends HTMLElement {
|
|
205
212
|
/** Tries to scroll to the first invalid field on submit */
|
206
213
|
this.scrollToInvalid = true;
|
207
214
|
this._dirty = false;
|
215
|
+
/** By default, `nano-field-validator` will also track all native form field elements.
|
216
|
+
* You can add extra web-component form fields to listen to
|
217
|
+
* (as long as they match the standard form field spec) by using the `fieldSelector` prop.
|
218
|
+
*/
|
219
|
+
this.extraFieldSelector = 'input, select, textarea';
|
208
220
|
// Event handlers
|
209
|
-
/**
|
221
|
+
/**
|
222
|
+
* Fired whenever store values change and potentially checks validity
|
223
|
+
* @param key - the key of the store that's just changed
|
224
|
+
* @param newVal - the incoming, new value
|
225
|
+
*/
|
210
226
|
this.handleStoreChange = async (key, newVal) => {
|
211
|
-
const found = this.
|
212
|
-
|
227
|
+
const found = this.allFields.find((field) => field.name === key);
|
228
|
+
// field update has come programmatically (not from ui),
|
229
|
+
// so let's update the underlying ui field
|
230
|
+
if ((found &&
|
231
|
+
found.tagName === 'NANO-FILE-UPLOAD' &&
|
232
|
+
!this.fileStateEqual(key, found)) ||
|
233
|
+
(found.tagName !== 'NANO-FILE-UPLOAD' && found.value !== newVal)) {
|
213
234
|
this.storeToFields([found]);
|
235
|
+
}
|
214
236
|
if (this.validateOn === 'dirty' && this.dirty) {
|
215
237
|
this.internalValidate = true;
|
216
238
|
await this.validateAllFields();
|
@@ -219,17 +241,40 @@ let FieldValidator = class extends HTMLElement {
|
|
219
241
|
}
|
220
242
|
this.nanoPayloadChange.emit(this._store.state);
|
221
243
|
};
|
222
|
-
/**
|
244
|
+
/**
|
245
|
+
* Handles nano field value changes and passes to store
|
246
|
+
* @param ev - the incoming change event
|
247
|
+
*/
|
223
248
|
this.handleFieldChange = (ev) => {
|
249
|
+
if (!this.nanoFields.includes(ev.target))
|
250
|
+
return;
|
224
251
|
this._dirty = true;
|
225
252
|
this.fieldsToStore([ev.target]);
|
226
253
|
};
|
227
|
-
/**
|
254
|
+
/**
|
255
|
+
* Handles non-nano field value changes and passes to store
|
256
|
+
* @param ev - the incoming change event
|
257
|
+
*/
|
258
|
+
this.handlePlainFieldChange = (ev) => {
|
259
|
+
if (!this.plainFields.includes(ev.target))
|
260
|
+
return;
|
261
|
+
this.fieldsToStore([ev.target]);
|
262
|
+
};
|
263
|
+
/**
|
264
|
+
* Handles default field validation events
|
265
|
+
* @param ev - the invalid event
|
266
|
+
*/
|
228
267
|
this.handleFormInvalid = async (ev) => {
|
229
|
-
|
268
|
+
// if it's a non-nano field, we'll let default html5 validation do it's thing
|
269
|
+
if (!this.plainFields.includes(ev.target)) {
|
270
|
+
ev.preventDefault();
|
271
|
+
}
|
230
272
|
this._valid = false;
|
273
|
+
// whenever `checkValidity` is called, this handler is in-turn called.
|
274
|
+
// this flag is used to stop infinite loops
|
231
275
|
if (this.internalValidate)
|
232
276
|
return;
|
277
|
+
// a submit must have happened to if 'submitThenDirty' turn on 'dirty' checking now
|
233
278
|
if (this.validateOn === 'submitThenDirty')
|
234
279
|
this.validateOn = 'dirty';
|
235
280
|
this.submitted = true;
|
@@ -249,7 +294,10 @@ let FieldValidator = class extends HTMLElement {
|
|
249
294
|
this.scrollToFirstInvalid();
|
250
295
|
this.nanoInvalid.emit();
|
251
296
|
};
|
252
|
-
/**
|
297
|
+
/**
|
298
|
+
* stops default form submission, checks if valid, then submits manually
|
299
|
+
* @param e - a submit event from the nested form element
|
300
|
+
*/
|
253
301
|
this.handleSubmit = async (e) => {
|
254
302
|
e.preventDefault();
|
255
303
|
if (this.validateOn === 'submitThenDirty')
|
@@ -274,6 +322,7 @@ let FieldValidator = class extends HTMLElement {
|
|
274
322
|
return this._activeForm;
|
275
323
|
}
|
276
324
|
set activeForm(form) {
|
325
|
+
// manages event listners on whatever form is used (slotted on created here)
|
277
326
|
if (!form)
|
278
327
|
return;
|
279
328
|
if (this._activeForm) {
|
@@ -284,7 +333,7 @@ let FieldValidator = class extends HTMLElement {
|
|
284
333
|
}
|
285
334
|
/** Sync up validateOn with all fields */
|
286
335
|
validateOnChange() {
|
287
|
-
this.
|
336
|
+
this.nanoFields.forEach((field) => {
|
288
337
|
if (field.tagName === 'NANO-CHECKBOX') {
|
289
338
|
const cbg = field.closest('nano-checkbox-group');
|
290
339
|
if (cbg)
|
@@ -312,7 +361,7 @@ let FieldValidator = class extends HTMLElement {
|
|
312
361
|
get payload() {
|
313
362
|
return this._store.state;
|
314
363
|
}
|
315
|
-
/** Returns true if validation errors will be displayed to the user */
|
364
|
+
/** Returns true if validation errors will be displayed to the user. @readonly */
|
316
365
|
get showValidation() {
|
317
366
|
return (this.validateOn === 'dirty' && this.dirty) || this.submitted;
|
318
367
|
}
|
@@ -329,26 +378,58 @@ let FieldValidator = class extends HTMLElement {
|
|
329
378
|
```
|
330
379
|
*/
|
331
380
|
get validationState() {
|
381
|
+
// TODO - migrate nano-fields away from using proprietary methods in a bid to be closer to the spec
|
382
|
+
// this is big and ugly.
|
383
|
+
// why? Cos' it must unify checking validity state for both
|
384
|
+
// `nano-...` and plain form fields.
|
332
385
|
const validationState = [];
|
333
|
-
this.
|
386
|
+
this.allFields.forEach(async (field) => {
|
334
387
|
const found = validationState.find((v) => v.name === field.name);
|
388
|
+
let pf;
|
389
|
+
let nf;
|
335
390
|
if (found) {
|
336
|
-
|
337
|
-
|
338
|
-
|
391
|
+
if (field.validationMessage) {
|
392
|
+
pf = field;
|
393
|
+
found.validityMessage = pf.validationMessage.length
|
394
|
+
? pf.validationMessage
|
395
|
+
: found.validityMessage;
|
396
|
+
this.internalValidate = true;
|
397
|
+
if (found.valid && !pf.checkValidity())
|
398
|
+
found.valid = false;
|
399
|
+
this.internalValidate = false;
|
400
|
+
}
|
401
|
+
else if (field.validityMessage) {
|
402
|
+
nf = field;
|
403
|
+
found.validityMessage = nf.validityMessage.length
|
404
|
+
? nf.validityMessage
|
405
|
+
: nf.validityMessage;
|
406
|
+
if (found.valid && nf.invalid)
|
407
|
+
found.valid = false;
|
408
|
+
}
|
339
409
|
if (!found.fields.find((f) => f === field))
|
340
410
|
found.fields.push(field);
|
341
|
-
|
342
|
-
|
343
|
-
|
411
|
+
}
|
412
|
+
let valid;
|
413
|
+
let validityMessage;
|
414
|
+
if (field.checkValidity) {
|
415
|
+
pf = field;
|
416
|
+
this.internalValidate = true;
|
417
|
+
valid = pf.checkValidity();
|
418
|
+
this.internalValidate = false;
|
419
|
+
validityMessage = pf.validationMessage;
|
420
|
+
}
|
421
|
+
else {
|
422
|
+
nf = field;
|
423
|
+
valid = !nf.invalid;
|
424
|
+
validityMessage = nf.validityMessage;
|
344
425
|
}
|
345
426
|
validationState.push({
|
346
427
|
fields: [field],
|
347
428
|
name: field.name,
|
348
|
-
valid: !field.invalid,
|
349
429
|
value: this._store.state[field.name],
|
350
430
|
dirty: false,
|
351
|
-
|
431
|
+
valid,
|
432
|
+
validityMessage,
|
352
433
|
});
|
353
434
|
});
|
354
435
|
return validationState;
|
@@ -360,6 +441,24 @@ let FieldValidator = class extends HTMLElement {
|
|
360
441
|
async setStore(state) {
|
361
442
|
Object.entries(state).forEach(([key, val]) => (this.store.state[key] = val));
|
362
443
|
}
|
444
|
+
/**
|
445
|
+
* Sets custom validity for all / some form fields.
|
446
|
+
* @param validity - a validity object of `{fieldName: errorString}` pairs. Set as an empty string to clear the error.
|
447
|
+
*/
|
448
|
+
async setCustomValidity(validity) {
|
449
|
+
return await Promise.all(Object.entries(validity).map(async ([key, err]) => {
|
450
|
+
const field = this.allFields.find((f) => f.name === key);
|
451
|
+
if (!!field)
|
452
|
+
await this.setFieldError(field, err);
|
453
|
+
}));
|
454
|
+
}
|
455
|
+
/**
|
456
|
+
* Clear all custom validation.
|
457
|
+
* @param validity
|
458
|
+
*/
|
459
|
+
async resetValidity() {
|
460
|
+
return await Promise.all(this.allFields.map(async (field) => await this.setFieldError(field, '')));
|
461
|
+
}
|
363
462
|
// private methods
|
364
463
|
attachSlotObserver() {
|
365
464
|
if (!!this.mo)
|
@@ -379,62 +478,66 @@ let FieldValidator = class extends HTMLElement {
|
|
379
478
|
}
|
380
479
|
/** Checks for new `nano-...` fields and adds them to our watch array and value store */
|
381
480
|
setupFields() {
|
382
|
-
let
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
nano-date-input,
|
387
|
-
nano-checkbox
|
388
|
-
`));
|
389
|
-
fields = fields.filter((f) => !!f.name && !!f.name.length);
|
481
|
+
let nanoFields = Array.from(this.host.querySelectorAll(this.nanoFieldSelector));
|
482
|
+
let plainFields = Array.from(this.host.querySelectorAll(this.extraFieldSelector)).filter((e) => !e.closest(this.nanoFieldSelector));
|
483
|
+
nanoFields = nanoFields.filter((f) => !!f.name && !!f.name.length);
|
484
|
+
plainFields = plainFields.filter((f) => !!f.name && !!f.name.length);
|
390
485
|
// do we have any currently un-watched fields?
|
391
|
-
if (!
|
486
|
+
if (![...nanoFields, ...plainFields].filter((f) => !this.allFields.includes(f)).length)
|
392
487
|
return;
|
393
488
|
// setup the initial store state / refresh on new fields
|
394
|
-
this.
|
395
|
-
this.
|
489
|
+
this.nanoFields = nanoFields;
|
490
|
+
this.plainFields = plainFields;
|
491
|
+
this.allFields = [...nanoFields, ...plainFields];
|
492
|
+
this.storeToFields(this.allFields);
|
396
493
|
this.validateOnChange();
|
397
|
-
this.fieldsToStore(this.
|
494
|
+
this.fieldsToStore(this.allFields);
|
398
495
|
this.nanoPayloadChange.emit(this._store.state);
|
399
496
|
}
|
400
497
|
storeToFields(fields) {
|
401
498
|
fields.forEach((field) => {
|
499
|
+
var _a;
|
402
500
|
const fieldName = field.name;
|
403
501
|
if (!fieldName.length ||
|
404
502
|
typeof this._store.state[fieldName] === 'undefined')
|
405
503
|
return;
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
break;
|
434
|
-
default:
|
435
|
-
field.value = this._store.state[fieldName];
|
436
|
-
break;
|
504
|
+
if (field.tagName === 'NANO-CHECKBOX' ||
|
505
|
+
['radio', 'checkbox'].includes(field.type)) {
|
506
|
+
let cb = field;
|
507
|
+
if (cb.type === 'radio' ||
|
508
|
+
cb.type === 'segment' ||
|
509
|
+
cb.type === 'segment-pill') {
|
510
|
+
// single radio type control
|
511
|
+
if (this._store.state[fieldName] === cb.value)
|
512
|
+
cb.checked = true;
|
513
|
+
else
|
514
|
+
cb.checked = false;
|
515
|
+
}
|
516
|
+
else if (Array.isArray(this._store.state[fieldName])) {
|
517
|
+
// multiple checkbox like controls
|
518
|
+
if (this._store.state[fieldName].includes(cb.value))
|
519
|
+
cb.checked = true;
|
520
|
+
else
|
521
|
+
cb.checked = false;
|
522
|
+
}
|
523
|
+
else {
|
524
|
+
// single checkbox like control
|
525
|
+
if (this._store.state[fieldName] === cb.value)
|
526
|
+
cb.checked = true;
|
527
|
+
else
|
528
|
+
cb.checked = false;
|
529
|
+
}
|
530
|
+
return;
|
437
531
|
}
|
532
|
+
if (field.tagName === 'NANO-FILE-UPLOAD') {
|
533
|
+
const ff = field;
|
534
|
+
// this can only work if the field is empty rn... a one-time deal
|
535
|
+
if (!((_a = ff.files) === null || _a === void 0 ? void 0 : _a.length))
|
536
|
+
ff.files = this._store.state[fieldName];
|
537
|
+
return;
|
538
|
+
}
|
539
|
+
// default
|
540
|
+
field.value = this._store.state[fieldName];
|
438
541
|
});
|
439
542
|
}
|
440
543
|
/** Loops through all `nano-...` fields and extracts their values into our store */
|
@@ -443,52 +546,70 @@ let FieldValidator = class extends HTMLElement {
|
|
443
546
|
const fieldName = field.name;
|
444
547
|
if (!fieldName.length)
|
445
548
|
return;
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
if (cb.
|
466
|
-
|
467
|
-
this._store.state[fieldName] = [...currentArr, cb.value];
|
468
|
-
}
|
469
|
-
}
|
470
|
-
else {
|
471
|
-
this._store.state[fieldName] = currentArr.filter((v) => v !== cb.value);
|
549
|
+
if (field.tagName === 'NANO-CHECKBOX' ||
|
550
|
+
['radio', 'checkbox'].includes(field.type)) {
|
551
|
+
let cb = field;
|
552
|
+
if (cb.type === 'radio' ||
|
553
|
+
cb.type === 'segment' ||
|
554
|
+
cb.type === 'segment-pill') {
|
555
|
+
// radio type control - only one can be checked
|
556
|
+
if (cb.checked)
|
557
|
+
this._store.state[fieldName] = cb.value;
|
558
|
+
}
|
559
|
+
else if (this.allFields.filter((f) => f.name === fieldName &&
|
560
|
+
(f.tagName === 'NANO-CHECKBOX' ||
|
561
|
+
f.type === 'checkbox')).length > 1) {
|
562
|
+
// multiple checkbox type control
|
563
|
+
const currentArr = Array.isArray(this._store.state[fieldName])
|
564
|
+
? this._store.state[fieldName]
|
565
|
+
: [];
|
566
|
+
if (cb.checked) {
|
567
|
+
// checked
|
568
|
+
if (!this._store.state[fieldName].includes(cb.value)) {
|
569
|
+
this._store.state[fieldName] = [...currentArr, cb.value];
|
472
570
|
}
|
473
571
|
}
|
474
572
|
else {
|
475
|
-
//
|
476
|
-
|
477
|
-
this._store.state[fieldName] = cb.value;
|
478
|
-
else
|
479
|
-
this._store.state[fieldName] = '';
|
573
|
+
// unchecked
|
574
|
+
this._store.state[fieldName] = currentArr.filter((v) => v !== cb.value);
|
480
575
|
}
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
576
|
+
}
|
577
|
+
else {
|
578
|
+
// single checkbox - on or off
|
579
|
+
if (cb.checked)
|
580
|
+
this._store.state[fieldName] = cb.value;
|
581
|
+
else
|
582
|
+
this._store.state[fieldName] = '';
|
583
|
+
}
|
584
|
+
return;
|
488
585
|
}
|
586
|
+
if (field.tagName === 'NANO-FILE-UPLOAD') {
|
587
|
+
const ff = field;
|
588
|
+
if (!this.fileStateEqual(fieldName, ff))
|
589
|
+
this._store.state[fieldName] = ff.files;
|
590
|
+
return;
|
591
|
+
}
|
592
|
+
// default
|
593
|
+
this._store.state[fieldName] = field.value;
|
489
594
|
});
|
490
595
|
}
|
491
|
-
/**
|
596
|
+
/**
|
597
|
+
* Tries to ascertain whether the current model
|
598
|
+
* value is the same as the `nano-file-upload` value
|
599
|
+
* @param fieldName - the key to access from the data store
|
600
|
+
* @param field - the nano-file-upload field to assess against
|
601
|
+
* @returns true for equal, false for not equal
|
602
|
+
*/
|
603
|
+
fileStateEqual(fieldName, field) {
|
604
|
+
return (JSON.stringify(this._store.state[fieldName]) ===
|
605
|
+
JSON.stringify(field.files) ||
|
606
|
+
this._store.state[fieldName] == field.files);
|
607
|
+
}
|
608
|
+
/**
|
609
|
+
* Checks for user defined validations
|
610
|
+
* @param key - current key of the data model to validate
|
611
|
+
* @param newVal - the newly set, incoming value to validate
|
612
|
+
*/
|
492
613
|
async validate(key, newVal) {
|
493
614
|
if (!this.validation)
|
494
615
|
return;
|
@@ -501,21 +622,33 @@ let FieldValidator = class extends HTMLElement {
|
|
501
622
|
// collection loop into a promise
|
502
623
|
await Promise.all(Object.entries(res).map(async ([key, o]) => {
|
503
624
|
// switch on/off validation messages
|
504
|
-
const field = this.
|
625
|
+
const field = this.allFields.find((f) => f.name === key);
|
505
626
|
let validityTarget = field;
|
506
627
|
if (field.tagName === 'NANO-CHECKBOX') {
|
628
|
+
// if we have a checkbox-group, set the validation message there
|
507
629
|
const cbg = field.closest('nano-checkbox-group');
|
508
630
|
validityTarget = cbg || field;
|
509
631
|
}
|
510
|
-
|
511
|
-
|
632
|
+
if ((validityTarget.validityMessage ||
|
633
|
+
validityTarget.validationMessage) === o.msg &&
|
634
|
+
o.valid) {
|
635
|
+
// status is now valid - clear the error
|
512
636
|
await this.setFieldError(validityTarget, '');
|
513
|
-
|
637
|
+
}
|
514
638
|
else if (!o.valid) {
|
639
|
+
// status is invalid. Set the error
|
515
640
|
await this.setFieldError(validityTarget, o.msg);
|
516
641
|
}
|
517
642
|
}));
|
518
643
|
}
|
644
|
+
/** Loops through all store entries and checks custom validation */
|
645
|
+
async validateAllFields() {
|
646
|
+
// This forces our loop to `await` and finish sequentially ... silly async stencil methods
|
647
|
+
await Object.entries(this._store.state).reduce(async (memo, [key, value]) => {
|
648
|
+
await memo;
|
649
|
+
await this.validate(key, value);
|
650
|
+
}, undefined);
|
651
|
+
}
|
519
652
|
/**
|
520
653
|
* Utility to smooth out setting error messages
|
521
654
|
* (it's a different method on `nano-checkbox` 'cos they don't show errors themselves)
|
@@ -525,16 +658,10 @@ let FieldValidator = class extends HTMLElement {
|
|
525
658
|
async setFieldError(field, msg) {
|
526
659
|
if (field['showError'])
|
527
660
|
await field.showError(msg);
|
528
|
-
else
|
661
|
+
else if (field['setError'])
|
529
662
|
await field.setError(msg);
|
530
|
-
|
531
|
-
|
532
|
-
async validateAllFields() {
|
533
|
-
// This forces our loop to `await` and finish sequentially ... silly async stencil methods
|
534
|
-
await Object.entries(this._store.state).reduce(async (memo, [key, value]) => {
|
535
|
-
await memo;
|
536
|
-
await this.validate(key, value);
|
537
|
-
}, undefined);
|
663
|
+
else
|
664
|
+
field.setCustomValidity(msg);
|
538
665
|
}
|
539
666
|
scrollToFirstInvalid() {
|
540
667
|
if (!this.scrollToInvalid)
|
@@ -563,17 +690,21 @@ let FieldValidator = class extends HTMLElement {
|
|
563
690
|
requestAnimationFrame(() => {
|
564
691
|
this.setupFields();
|
565
692
|
this.attachSlotObserver();
|
566
|
-
this._store.on('set', (key, value) => this.handleStoreChange(key, value));
|
567
693
|
this.host.addEventListener('nanoChange', this.handleFieldChange);
|
694
|
+
this.host.addEventListener('input', this.handlePlainFieldChange);
|
695
|
+
this.host.addEventListener('change', this.handlePlainFieldChange);
|
568
696
|
this.host.addEventListener('submit', this.handleSubmit);
|
697
|
+
this._store.on('set', this.handleStoreChange);
|
569
698
|
});
|
570
699
|
}
|
571
700
|
disconnectedCallback() {
|
572
701
|
if (this.mo)
|
573
702
|
this.mo.disconnect();
|
574
|
-
this._store.reset();
|
575
703
|
this.host.removeEventListener('nanoChange', this.handleFieldChange);
|
704
|
+
this.host.removeEventListener('input', this.handlePlainFieldChange);
|
705
|
+
this.host.removeEventListener('change', this.handlePlainFieldChange);
|
576
706
|
this.host.removeEventListener('submit', this.handleSubmit);
|
707
|
+
this._store.reset();
|
577
708
|
if (this.activeForm)
|
578
709
|
this.activeForm.removeEventListener('invalid', this.handleFormInvalid, true);
|
579
710
|
}
|
@@ -583,7 +714,8 @@ let FieldValidator = class extends HTMLElement {
|
|
583
714
|
get host() { return this; }
|
584
715
|
static get watchers() { return {
|
585
716
|
"userForm": ["userFormChange"],
|
586
|
-
"validateOn": ["validateOnChange"]
|
717
|
+
"validateOn": ["validateOnChange"],
|
718
|
+
"extraFieldSelector": ["attachSlotObserver"]
|
587
719
|
}; }
|
588
720
|
};
|
589
721
|
FieldValidator = /*@__PURE__*/ proxyCustomElement(FieldValidator, [4, "nano-field-validator", {
|
@@ -595,13 +727,16 @@ FieldValidator = /*@__PURE__*/ proxyCustomElement(FieldValidator, [4, "nano-fiel
|
|
595
727
|
"payload": [2064],
|
596
728
|
"showValidation": [2052, "show-validation"],
|
597
729
|
"validationState": [2064],
|
730
|
+
"extraFieldSelector": [1, "extra-field-selector"],
|
598
731
|
"validation": [16],
|
599
|
-
"userForm": [32],
|
600
732
|
"submitted": [32],
|
733
|
+
"userForm": [32],
|
601
734
|
"_dirty": [32],
|
602
735
|
"_valid": [32],
|
603
736
|
"_store": [32],
|
604
|
-
"setStore": [64]
|
737
|
+
"setStore": [64],
|
738
|
+
"setCustomValidity": [64],
|
739
|
+
"resetValidity": [64]
|
605
740
|
}]);
|
606
741
|
function defineCustomElement$1() {
|
607
742
|
if (typeof customElements === "undefined") {
|