@descope/web-components-ui 1.0.60 → 1.0.62
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/dist/cjs/index.cjs.js.map +1 -1
- package/dist/index.esm.js +395 -185
- package/dist/index.esm.js.map +1 -1
- package/dist/umd/442.js +1 -0
- package/dist/umd/942.js +1 -1
- package/dist/umd/descope-button-index-js.js +1 -1
- package/dist/umd/descope-checkbox-index-js.js +1 -1
- package/dist/umd/descope-combo-index-js.js +1 -1
- package/dist/umd/descope-container-index-js.js +1 -1
- package/dist/umd/descope-date-picker-index-js.js +1 -1
- package/dist/umd/descope-divider-index-js.js +1 -1
- package/dist/umd/descope-email-field-index-js.js +1 -1
- package/dist/umd/descope-link-index-js.js +1 -1
- package/dist/umd/descope-loader-linear-index-js.js +1 -1
- package/dist/umd/descope-loader-radial-index-js.js +1 -1
- package/dist/umd/descope-logo-index-js.js +1 -1
- package/dist/umd/descope-number-field-index-js.js +1 -1
- package/dist/umd/descope-passcode-descope-passcode-internal-index-js.js +1 -1
- package/dist/umd/descope-passcode-index-js.js +1 -1
- package/dist/umd/descope-password-field-index-js.js +1 -1
- package/dist/umd/descope-switch-toggle-index-js.js +1 -1
- package/dist/umd/descope-text-area-index-js.js +1 -1
- package/dist/umd/descope-text-field-index-js.js +1 -1
- package/dist/umd/descope-text-index-js.js +1 -1
- package/dist/umd/index.js +1 -1
- package/package.json +1 -1
- package/src/baseClasses/BaseInputClass.js +3 -0
- package/src/components/descope-checkbox/Checkbox.js +2 -2
- package/src/components/descope-combo/index.js +1 -1
- package/src/components/descope-container/Container.js +1 -1
- package/src/components/descope-divider/Divider.js +1 -1
- package/src/components/descope-email-field/EmailField.js +2 -2
- package/src/components/descope-link/Link.js +1 -1
- package/src/components/descope-loader-linear/LoaderLinear.js +1 -1
- package/src/components/descope-loader-radial/LoaderRadial.js +1 -1
- package/src/components/descope-logo/Logo.js +1 -1
- package/src/components/descope-number-field/NumberField.js +2 -2
- package/src/components/descope-passcode/Passcode.js +2 -2
- package/src/components/descope-passcode/descope-passcode-internal/PasscodeInternal.js +42 -70
- package/src/components/descope-password-field/PasswordField.js +2 -2
- package/src/components/descope-switch-toggle/SwitchToggle.js +2 -2
- package/src/components/descope-text/Text.js +1 -1
- package/src/components/descope-text-area/TextArea.js +2 -2
- package/src/components/descope-text-field/TextField.js +2 -2
- package/src/componentsHelpers/compose.js +3 -0
- package/src/componentsHelpers/createProxy/index.js +2 -2
- package/src/componentsHelpers/enforceNestingElementsStylesMixin.js +67 -59
- package/src/componentsHelpers/index.js +2 -6
- package/src/componentsHelpers/inputMixin.js +173 -94
- package/src/componentsHelpers/proxyInputMixin.js +152 -0
- package/src/theme/components/textField.js +1 -1
- package/dist/umd/832.js +0 -1
- /package/src/{components → baseClasses}/DescopeBaseClass.js +0 -0
package/dist/index.esm.js
CHANGED
@@ -256,6 +256,10 @@ const draggableMixin = (superclass) =>
|
|
256
256
|
}
|
257
257
|
};
|
258
258
|
|
259
|
+
var compose = (...fns) =>
|
260
|
+
(val) =>
|
261
|
+
fns.reduceRight((res, fn) => fn(res), val);
|
262
|
+
|
259
263
|
class DescopeBaseClass extends HTMLElement {}
|
260
264
|
|
261
265
|
const hoverableMixin =
|
@@ -438,9 +442,177 @@ const createProxy = ({
|
|
438
442
|
return compose(hoverableMixin())(ProxyElement);
|
439
443
|
};
|
440
444
|
|
441
|
-
const
|
442
|
-
|
443
|
-
|
445
|
+
const upperFirst = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
446
|
+
|
447
|
+
const events = [
|
448
|
+
'change',
|
449
|
+
'input',
|
450
|
+
'blur',
|
451
|
+
'focus',
|
452
|
+
'invalid',
|
453
|
+
'valid',
|
454
|
+
];
|
455
|
+
|
456
|
+
const observedAttributes = [
|
457
|
+
'required',
|
458
|
+
'pattern',
|
459
|
+
];
|
460
|
+
|
461
|
+
const errorAttributes = {
|
462
|
+
valueMissing: 'data-errormessage-value-missing',
|
463
|
+
patternMismatch: 'data-errormessage-pattern-mismatch'
|
464
|
+
};
|
465
|
+
const inputMixin = (superclass) => class InputMixinClass extends superclass {
|
466
|
+
static get observedAttributes() {
|
467
|
+
return [
|
468
|
+
...superclass.observedAttributes || [],
|
469
|
+
...observedAttributes
|
470
|
+
];
|
471
|
+
}
|
472
|
+
|
473
|
+
static get formAssociated() {
|
474
|
+
return true;
|
475
|
+
}
|
476
|
+
|
477
|
+
#internals
|
478
|
+
|
479
|
+
constructor() {
|
480
|
+
super();
|
481
|
+
|
482
|
+
this.#internals = this.attachInternals();
|
483
|
+
|
484
|
+
for (const event of events) {
|
485
|
+
this[`dispatch${upperFirst(event)}`] = function () {
|
486
|
+
this.dispatchInputEvent(event);
|
487
|
+
};
|
488
|
+
}
|
489
|
+
}
|
490
|
+
|
491
|
+
get defaultErrorMsgValueMissing() {
|
492
|
+
return 'Please fill out this field.'
|
493
|
+
}
|
494
|
+
|
495
|
+
get defaultErrorMsgPatternMismatch() {
|
496
|
+
return 'Please match the requested format.'
|
497
|
+
}
|
498
|
+
|
499
|
+
getErrorMessage(flags) {
|
500
|
+
switch (true) {
|
501
|
+
case flags.valueMissing:
|
502
|
+
return this.getAttribute(errorAttributes.valueMissing) ||
|
503
|
+
this.defaultErrorMsgValueMissing
|
504
|
+
case flags.patternMismatch || flags.typeMismatch:
|
505
|
+
return this.getAttribute(errorAttributes.patternMismatch) ||
|
506
|
+
this.defaultErrorMsgPatternMismatch
|
507
|
+
case flags.customError:
|
508
|
+
return this.validationMessage
|
509
|
+
default:
|
510
|
+
return ''
|
511
|
+
}
|
512
|
+
}
|
513
|
+
|
514
|
+
setValidity() {
|
515
|
+
const validity = this.getValidity();
|
516
|
+
this.#internals.setValidity(validity, this.getErrorMessage(validity));
|
517
|
+
}
|
518
|
+
|
519
|
+
get validationMessage() {
|
520
|
+
return this.#internals.validationMessage;
|
521
|
+
}
|
522
|
+
|
523
|
+
getValidity() {
|
524
|
+
throw Error('getValidity', 'is not implemented')
|
525
|
+
}
|
526
|
+
|
527
|
+
checkValidity() {
|
528
|
+
return this.#internals.validity.valid
|
529
|
+
}
|
530
|
+
|
531
|
+
reportValidity() {
|
532
|
+
return this.#internals.reportValidity()
|
533
|
+
}
|
534
|
+
|
535
|
+
get validity() {
|
536
|
+
return this.#internals.validity
|
537
|
+
}
|
538
|
+
|
539
|
+
setCustomValidity(errorMessage) {
|
540
|
+
if(errorMessage){
|
541
|
+
this.#internals.setValidity({customError: true}, errorMessage);
|
542
|
+
} else {
|
543
|
+
this.#internals.setValidity({});
|
544
|
+
this.setValidity();
|
545
|
+
}
|
546
|
+
}
|
547
|
+
|
548
|
+
get isRequired() {
|
549
|
+
return this.hasAttribute('required') && this.getAttribute('required') !== 'false'
|
550
|
+
}
|
551
|
+
|
552
|
+
get pattern() {
|
553
|
+
return this.getAttribute('pattern')
|
554
|
+
}
|
555
|
+
|
556
|
+
get value() {
|
557
|
+
throw Error('get value', 'is not implemented')
|
558
|
+
}
|
559
|
+
|
560
|
+
set value(value) {
|
561
|
+
throw Error('set value', 'is not implemented')
|
562
|
+
}
|
563
|
+
|
564
|
+
handleFocus() {
|
565
|
+
throw Error('handleFocus', 'is not implemented')
|
566
|
+
}
|
567
|
+
|
568
|
+
handleInput() {
|
569
|
+
this.setValidity();
|
570
|
+
this.handleDispatchValidationEvents();
|
571
|
+
}
|
572
|
+
|
573
|
+
handleBlur() {
|
574
|
+
throw Error('handleBlur', 'is not implemented')
|
575
|
+
}
|
576
|
+
|
577
|
+
handleChange() {
|
578
|
+
throw Error('handleChange', 'is not implemented')
|
579
|
+
}
|
580
|
+
|
581
|
+
dispatchInputEvent(eventName) {
|
582
|
+
this[`on${eventName}`]?.(); // in case we got an event callback as property
|
583
|
+
this.dispatchEvent(new InputEvent(eventName));
|
584
|
+
}
|
585
|
+
|
586
|
+
attributeChangedCallback(attrName, oldValue, newValue) {
|
587
|
+
super.attributeChangedCallback?.(attrName, oldValue, newValue);
|
588
|
+
|
589
|
+
if (observedAttributes.includes(attrName)) {
|
590
|
+
this.setValidity();
|
591
|
+
}
|
592
|
+
}
|
593
|
+
|
594
|
+
handleDispatchValidationEvents(){
|
595
|
+
if(this.checkValidity()) {
|
596
|
+
this.dispatchValid();
|
597
|
+
} else {
|
598
|
+
this.dispatchInvalid();
|
599
|
+
}
|
600
|
+
}
|
601
|
+
|
602
|
+
connectedCallback() {
|
603
|
+
super.connectedCallback?.();
|
604
|
+
|
605
|
+
this.setValidity();
|
606
|
+
this.handleDispatchValidationEvents();
|
607
|
+
|
608
|
+
// create proxy replace the addEventListener fn
|
609
|
+
// and we want to be able to access the focus events
|
610
|
+
// of this element and not the nested element's events
|
611
|
+
this.onfocus = this.handleFocus.bind(this);
|
612
|
+
this.addEventListener('input', this.handleInput.bind(this));
|
613
|
+
this.addEventListener('blur', this.handleBlur.bind(this));
|
614
|
+
this.addEventListener('change', this.handleBlur.bind(this));
|
615
|
+
}
|
444
616
|
};
|
445
617
|
|
446
618
|
const errorAttrs = ['invalid', 'has-error-message'];
|
@@ -457,79 +629,140 @@ const propertyObserver = (src, target, property) => {
|
|
457
629
|
});
|
458
630
|
};
|
459
631
|
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
632
|
+
// recursively take the first slot child until it finds an element which is not a slot
|
633
|
+
// stops after "nestingLevel" times
|
634
|
+
const getNestedInput = (ele) => {
|
635
|
+
if (!ele) return;
|
636
|
+
|
637
|
+
const nestingLevel = 10;
|
638
|
+
|
639
|
+
let nonSlotEle = ele;
|
640
|
+
for (let i = 0; i < nestingLevel; i++) {
|
641
|
+
nonSlotEle = nonSlotEle.assignedElements()[0];
|
642
|
+
if (nonSlotEle.localName !== 'slot') return nonSlotEle
|
643
|
+
}
|
644
|
+
};
|
645
|
+
|
646
|
+
const proxyInputMixin = (superclass) =>
|
647
|
+
class proxyInputMixinClass extends inputMixin(superclass) {
|
648
|
+
static get observedAttributes() {
|
649
|
+
return [...superclass.observedAttributes || [], ...errorAttrs];
|
464
650
|
}
|
465
651
|
|
466
|
-
#
|
652
|
+
#inputElement
|
467
653
|
|
468
654
|
constructor() {
|
469
655
|
super();
|
470
656
|
|
471
|
-
this.#
|
657
|
+
this.#inputElement = super.inputElement;
|
658
|
+
|
659
|
+
// this is our way to identify that the form was submitted
|
660
|
+
// in this case, we want the input to be in error state if it's not valid
|
661
|
+
this.addEventListener('focus', (e) => {
|
662
|
+
if (e.relatedTarget?.form) {
|
663
|
+
if (!this.checkValidity()) {
|
664
|
+
this.setAttribute('invalid', 'true');
|
665
|
+
}
|
666
|
+
|
667
|
+
if (this.hasAttribute('invalid')) {
|
668
|
+
this.reportValidityOnInternalInput();
|
669
|
+
}
|
670
|
+
}
|
671
|
+
});
|
672
|
+
|
673
|
+
this.addEventListener('invalid', () => {
|
674
|
+
this.setInternalInputErrorMessage();
|
675
|
+
this.setAttribute('error-message', this.validationMessage);
|
676
|
+
});
|
677
|
+
|
678
|
+
this.addEventListener('valid', () => {
|
679
|
+
this.removeAttribute('invalid');
|
680
|
+
});
|
681
|
+
}
|
682
|
+
|
683
|
+
get inputElement() {
|
684
|
+
const inputSlot = this.baseEle.shadowRoot.querySelector('slot[name="input"]');
|
685
|
+
const textAreaSlot = this.baseEle.shadowRoot.querySelector('slot[name="textarea"]');
|
686
|
+
|
687
|
+
this.#inputElement ??= getNestedInput(inputSlot) || getNestedInput(textAreaSlot);
|
688
|
+
|
689
|
+
if (!this.#inputElement) throw Error('no input was found');
|
690
|
+
|
691
|
+
return this.#inputElement
|
692
|
+
}
|
693
|
+
|
694
|
+
set inputElement(ele) {
|
695
|
+
this.#inputElement = ele;
|
696
|
+
}
|
697
|
+
|
698
|
+
getValidity() {
|
699
|
+
return this.inputElement.validity
|
472
700
|
}
|
473
701
|
|
474
|
-
|
475
|
-
|
702
|
+
reportValidityOnInternalInput() {
|
703
|
+
setTimeout(() => {
|
704
|
+
this.inputElement.reportValidity();
|
705
|
+
}, 0);
|
476
706
|
}
|
477
707
|
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
708
|
+
handleBlur() { }
|
709
|
+
|
710
|
+
handleFocus() {
|
711
|
+
this.inputElement.focus();
|
712
|
+
if (this.hasAttribute('invalid')) {
|
713
|
+
this.reportValidityOnInternalInput();
|
482
714
|
}
|
483
|
-
// normalize vaadin error attributes to have a boolean value
|
484
|
-
errorAttrs.forEach((att) => this.proxyElement.setAttribute(att, 'true'));
|
485
715
|
}
|
486
716
|
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
this.
|
717
|
+
// we want reportValidity to behave like form submission
|
718
|
+
reportValidity() {
|
719
|
+
const isValid = super.reportValidity();
|
720
|
+
if (!isValid) {
|
721
|
+
this.setAttribute('invalid', 'true');
|
722
|
+
this.inputElement.focus();
|
723
|
+
}
|
724
|
+
this.reportValidityOnInternalInput();
|
725
|
+
}
|
726
|
+
|
727
|
+
setInternalInputErrorMessage() {
|
728
|
+
if (!this.checkValidity()) {
|
729
|
+
this.inputElement.setCustomValidity(this.validationMessage);
|
493
730
|
}
|
494
731
|
}
|
495
732
|
|
496
733
|
connectedCallback() {
|
734
|
+
this.baseEle = this.shadowRoot.querySelector(this.baseSelector);
|
735
|
+
|
497
736
|
super.connectedCallback?.();
|
498
737
|
|
499
|
-
this.
|
738
|
+
this.inputElement.addEventListener('input', () => {
|
739
|
+
this.inputElement.setCustomValidity('');
|
740
|
+
if (!this.inputElement.checkValidity())
|
741
|
+
this.setInternalInputErrorMessage();
|
742
|
+
});
|
743
|
+
|
744
|
+
this.inputElement.addEventListener('invalid', () => {
|
745
|
+
this.setValidity();
|
746
|
+
this.setInternalInputErrorMessage();
|
747
|
+
this.setAttribute('error-message', this.validationMessage);
|
748
|
+
});
|
500
749
|
|
501
750
|
// this is needed in order to make sure the form input validation is working
|
502
751
|
if (!this.hasAttribute('tabindex')) {
|
503
752
|
this.setAttribute('tabindex', 0);
|
504
753
|
}
|
505
754
|
|
506
|
-
this.inputElement ??= this.baseEle.shadowRoot.querySelector('slot[name="input"]')?.assignedElements()[0] ||
|
507
|
-
this.baseEle.shadowRoot.querySelector('slot[name="textarea"]')?.assignedElements()[0];
|
508
|
-
if (!this.inputElement) throw Error('no input was found');
|
509
|
-
|
510
755
|
// sync properties
|
511
756
|
propertyObserver(this, this.inputElement, 'value');
|
512
757
|
this.setSelectionRange = this.inputElement.setSelectionRange?.bind(this.inputElement);
|
758
|
+
}
|
513
759
|
|
514
|
-
|
515
|
-
|
516
|
-
this.setValidity = () => {
|
517
|
-
this.#internals.setValidity(this.inputElement.validity, this.inputElement.validationMessage);
|
518
|
-
};
|
519
|
-
|
520
|
-
this.inputElement.oninput = () => {
|
521
|
-
this.value = this.inputElement.value;
|
522
|
-
this.setValidity();
|
523
|
-
};
|
524
|
-
|
525
|
-
this.onfocus = () => {
|
526
|
-
setTimeout(() => this.inputElement.reportValidity(), 0);
|
527
|
-
this.validate();
|
528
|
-
};
|
760
|
+
attributeChangedCallback(attrName, oldValue, newValue) {
|
761
|
+
super.attributeChangedCallback?.(attrName, oldValue, newValue);
|
529
762
|
|
530
|
-
|
531
|
-
this.
|
532
|
-
}
|
763
|
+
if (attrName === 'invalid' && newValue === '') {
|
764
|
+
this.setAttribute('invalid', 'true');
|
765
|
+
}
|
533
766
|
}
|
534
767
|
};
|
535
768
|
|
@@ -561,11 +794,6 @@ const componentNameValidationMixin = (superclass) =>
|
|
561
794
|
|
562
795
|
const getComponentName = (name) => kebabCaseJoin(DESCOPE_PREFIX, name);
|
563
796
|
|
564
|
-
const compose =
|
565
|
-
(...fns) =>
|
566
|
-
(val) =>
|
567
|
-
fns.reduceRight((res, fn) => fn(res), val);
|
568
|
-
|
569
797
|
const componentName$i = getComponentName('button');
|
570
798
|
|
571
799
|
const editorOverrides = `vaadin-button::part(label) { pointer-events: none; }`;
|
@@ -664,7 +892,7 @@ const Checkbox = compose(
|
|
664
892
|
}
|
665
893
|
}),
|
666
894
|
draggableMixin,
|
667
|
-
|
895
|
+
proxyInputMixin,
|
668
896
|
componentNameValidationMixin
|
669
897
|
)(
|
670
898
|
createProxy({
|
@@ -846,7 +1074,7 @@ const TextField = compose(
|
|
846
1074
|
mappings: textFieldMappings
|
847
1075
|
}),
|
848
1076
|
draggableMixin,
|
849
|
-
|
1077
|
+
proxyInputMixin,
|
850
1078
|
componentNameValidationMixin
|
851
1079
|
)(
|
852
1080
|
createProxy({
|
@@ -1019,65 +1247,65 @@ const insertNestingLevel = (srcEle, nestingEle) => {
|
|
1019
1247
|
// to be under the nesting element
|
1020
1248
|
const enforceNestingElementsStylesMixin =
|
1021
1249
|
({ nestingElementTagName, nestingElementDestSlotName, forwardAttrOptions }) =>
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1250
|
+
(superclass) => {
|
1251
|
+
const getChildNodeEle = () =>
|
1252
|
+
document.createElement(nestingElementTagName, {
|
1253
|
+
slot: nestingElementDestSlotName
|
1254
|
+
});
|
1027
1255
|
|
1028
|
-
|
1029
|
-
|
1030
|
-
const getObserver = () => childObserver;
|
1256
|
+
let childObserver;
|
1031
1257
|
|
1032
|
-
|
1033
|
-
constructor() {
|
1034
|
-
super();
|
1258
|
+
const getObserver = () => childObserver;
|
1035
1259
|
|
1036
|
-
|
1037
|
-
// we are going to change the DOM, so we need to disconnect the observer before
|
1038
|
-
// and reconnect it after the child component is added
|
1039
|
-
getObserver().disconnect(this.shadowRoot.host);
|
1040
|
-
|
1041
|
-
const isNestingElementExist = this.shadowRoot.host.querySelector(nestingElementTagName);
|
1042
|
-
const hasNewChildren = this.shadowRoot.host.childNodes.length > 0;
|
1043
|
-
|
1044
|
-
if (!isNestingElementExist && hasNewChildren) {
|
1045
|
-
// if before there were no children and now there are children - insert
|
1046
|
-
insertNestingLevel(this.shadowRoot.host, getChildNodeEle());
|
1047
|
-
} else if (isNestingElementExist && hasNewChildren) {
|
1048
|
-
// if children existed, and they changed -
|
1049
|
-
// we need to update (move) the new children into
|
1050
|
-
// descope-text and remove previous children
|
1051
|
-
this.shadowRoot.host.querySelector(child).remove();
|
1052
|
-
insertNestingLevel(this.shadowRoot.host, getChildNodeEle());
|
1053
|
-
}
|
1054
|
-
else if (isNestingElementExist && !hasNewChildren) {
|
1055
|
-
// if children existed and now there are none -
|
1056
|
-
// we need to remove descope-text completely
|
1057
|
-
this.shadowRoot.host.querySelector(child).remove();
|
1058
|
-
}
|
1260
|
+
let isMutating = false;
|
1059
1261
|
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
this.shadowRoot.host.querySelector(nestingElementTagName),
|
1065
|
-
forwardAttrOptions
|
1066
|
-
);
|
1262
|
+
const filterNestingElement = (node) => node.localName !== nestingElementTagName;
|
1263
|
+
return class EnforceNestingElementsStylesMixinClass extends superclass {
|
1264
|
+
constructor() {
|
1265
|
+
super();
|
1067
1266
|
|
1068
|
-
|
1069
|
-
childList: true
|
1070
|
-
});
|
1071
|
-
};
|
1267
|
+
const childObserverCallback = (mutation, observer) => {
|
1072
1268
|
|
1073
|
-
|
1074
|
-
|
1269
|
+
// we are going to change the DOM, so we need to skip the upcoming mutations
|
1270
|
+
if (isMutating) return;
|
1075
1271
|
|
1076
|
-
|
1077
|
-
|
1272
|
+
isMutating = true;
|
1273
|
+
|
1274
|
+
const { addedNodes, removedNodes } = mutation;
|
1275
|
+
|
1276
|
+
const nestingElement = this.shadowRoot.host.querySelector(nestingElementTagName);
|
1277
|
+
const hasNewChildren = Array.from(addedNodes)
|
1278
|
+
.filter(filterNestingElement)
|
1279
|
+
.length > 0;
|
1280
|
+
const hasRemovedChildren = Array.from(removedNodes)
|
1281
|
+
.filter(filterNestingElement)
|
1282
|
+
.length > 0;
|
1283
|
+
|
1284
|
+
if (!nestingElement && hasNewChildren) {
|
1285
|
+
// if before there were no children and now there are children - insert
|
1286
|
+
this.handleNestingLevelInsertion();
|
1287
|
+
|
1288
|
+
} else if (nestingElement && hasNewChildren) {
|
1289
|
+
// if children existed, and they changed -
|
1290
|
+
// we need to update (move) the new children into
|
1291
|
+
// descope-text and remove previous children
|
1292
|
+
nestingElement.replaceChildren(...addedNodes);
|
1293
|
+
}
|
1294
|
+
else if (nestingElement && !hasNewChildren && hasRemovedChildren) {
|
1295
|
+
// // if children existed and now there are none -
|
1296
|
+
// // we need to remove descope-text completely
|
1297
|
+
nestingElement.remove();
|
1298
|
+
}
|
1078
1299
|
|
1079
|
-
|
1080
|
-
|
1300
|
+
setTimeout(() => {
|
1301
|
+
isMutating = false;
|
1302
|
+
});
|
1303
|
+
};
|
1304
|
+
|
1305
|
+
childObserver = getChildObserver(childObserverCallback);
|
1306
|
+
}
|
1307
|
+
|
1308
|
+
handleNestingLevelInsertion() {
|
1081
1309
|
insertNestingLevel(this.shadowRoot.host, getChildNodeEle());
|
1082
1310
|
|
1083
1311
|
forwardAttrs(
|
@@ -1087,12 +1315,20 @@ const enforceNestingElementsStylesMixin =
|
|
1087
1315
|
);
|
1088
1316
|
}
|
1089
1317
|
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1318
|
+
connectedCallback() {
|
1319
|
+
super.connectedCallback?.();
|
1320
|
+
|
1321
|
+
if (this.shadowRoot.host.childNodes.length > 0) {
|
1322
|
+
// on the first render - we want to move all component's children to be under descope-text
|
1323
|
+
this.handleNestingLevelInsertion();
|
1324
|
+
}
|
1325
|
+
|
1326
|
+
getObserver().observe(this.shadowRoot.host, {
|
1327
|
+
childList: true
|
1328
|
+
});
|
1329
|
+
}
|
1330
|
+
};
|
1094
1331
|
};
|
1095
|
-
};
|
1096
1332
|
|
1097
1333
|
const componentName$a = getComponentName('text');
|
1098
1334
|
|
@@ -1230,7 +1466,7 @@ const EmailField = compose(
|
|
1230
1466
|
}
|
1231
1467
|
}),
|
1232
1468
|
draggableMixin,
|
1233
|
-
|
1469
|
+
proxyInputMixin,
|
1234
1470
|
componentNameValidationMixin
|
1235
1471
|
)(
|
1236
1472
|
createProxy({
|
@@ -1422,7 +1658,7 @@ const NumberField = compose(
|
|
1422
1658
|
}
|
1423
1659
|
}),
|
1424
1660
|
draggableMixin,
|
1425
|
-
|
1661
|
+
proxyInputMixin,
|
1426
1662
|
componentNameValidationMixin
|
1427
1663
|
)(
|
1428
1664
|
createProxy({
|
@@ -1476,6 +1712,8 @@ overrides$4 = `
|
|
1476
1712
|
|
1477
1713
|
customElements.define(componentName$5, NumberField);
|
1478
1714
|
|
1715
|
+
var BaseInputClass = inputMixin(HTMLElement); //todo: maybe we should use base class?
|
1716
|
+
|
1479
1717
|
const focusElement = (ele) => {
|
1480
1718
|
ele?.focus();
|
1481
1719
|
ele?.setSelectionRange(1, 1);
|
@@ -1492,14 +1730,13 @@ const getSanitizedCharacters = (str) => {
|
|
1492
1730
|
|
1493
1731
|
const componentName$4 = getComponentName('passcode-internal');
|
1494
1732
|
|
1495
|
-
class PasscodeInternal extends
|
1733
|
+
class PasscodeInternal extends BaseInputClass {
|
1496
1734
|
static get observedAttributes() {
|
1497
1735
|
return [
|
1736
|
+
...BaseInputClass.observedAttributes,
|
1498
1737
|
'disabled',
|
1499
1738
|
'bordered',
|
1500
|
-
'size'
|
1501
|
-
'required',
|
1502
|
-
'pattern'
|
1739
|
+
'size'
|
1503
1740
|
];
|
1504
1741
|
}
|
1505
1742
|
|
@@ -1507,12 +1744,6 @@ class PasscodeInternal extends HTMLElement {
|
|
1507
1744
|
return componentName$4;
|
1508
1745
|
}
|
1509
1746
|
|
1510
|
-
static get formAssociated() {
|
1511
|
-
return true;
|
1512
|
-
}
|
1513
|
-
|
1514
|
-
#internals
|
1515
|
-
|
1516
1747
|
constructor() {
|
1517
1748
|
super();
|
1518
1749
|
const template = document.createElement('template');
|
@@ -1536,23 +1767,9 @@ class PasscodeInternal extends HTMLElement {
|
|
1536
1767
|
|
1537
1768
|
this.baseSelector = ':host > div';
|
1538
1769
|
|
1539
|
-
this.#internals = this.attachInternals();
|
1540
|
-
|
1541
1770
|
this.inputs = Array.from(this.querySelectorAll('descope-text-field'));
|
1542
1771
|
}
|
1543
1772
|
|
1544
|
-
checkValidity() {
|
1545
|
-
// we need to toggle the has-error-message so the text inside the digits will become red when there is an error
|
1546
|
-
if (this.#internals.validity.valid) {
|
1547
|
-
this.inputs.forEach(input => input.removeAttribute('has-error-message'));
|
1548
|
-
} else {
|
1549
|
-
this.inputs.forEach(input => input.setAttribute('has-error-message', 'true'));
|
1550
|
-
// we need to call it so the has-error-message with have the correct format (="true")
|
1551
|
-
this.oninvalid?.();
|
1552
|
-
}
|
1553
|
-
return this.#internals.validity.valid
|
1554
|
-
}
|
1555
|
-
|
1556
1773
|
get digits() {
|
1557
1774
|
return Number.parseInt(this.getAttribute('digits')) || 6
|
1558
1775
|
}
|
@@ -1561,59 +1778,54 @@ class PasscodeInternal extends HTMLElement {
|
|
1561
1778
|
return this.inputs.map(({ value }) => value).join('')
|
1562
1779
|
}
|
1563
1780
|
|
1564
|
-
set value(val) {
|
1781
|
+
set value(val) {
|
1782
|
+
if(val === this.value) return;
|
1783
|
+
|
1784
|
+
const charArr = getSanitizedCharacters(val);
|
1565
1785
|
|
1566
|
-
|
1567
|
-
|
1786
|
+
if (charArr.length) {
|
1787
|
+
this.fillDigits(charArr, this.inputs[0]);
|
1788
|
+
}
|
1568
1789
|
}
|
1569
1790
|
|
1570
1791
|
get pattern() {
|
1571
1792
|
return `^$|^\\d{${this.digits},}$`
|
1572
1793
|
}
|
1573
1794
|
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
1577
|
-
|
1578
|
-
|
1579
|
-
|
1580
|
-
}
|
1581
|
-
|
1582
|
-
get validity() {
|
1583
|
-
return this.#internals.validity;
|
1584
|
-
}
|
1585
|
-
|
1586
|
-
get validationMessage() {
|
1587
|
-
return this.#internals.validationMessage;
|
1588
|
-
}
|
1589
|
-
|
1590
|
-
reportValidity() {
|
1591
|
-
this.#internals.reportValidity();
|
1795
|
+
handleInputsInvalid() {
|
1796
|
+
setTimeout(() => {
|
1797
|
+
if (this.hasAttribute('invalid')) {
|
1798
|
+
this.inputs.forEach(input => input.setAttribute('invalid', 'true'));
|
1799
|
+
}
|
1800
|
+
});
|
1592
1801
|
}
|
1593
1802
|
|
1594
|
-
|
1595
|
-
this.
|
1803
|
+
handleInputsValid() {
|
1804
|
+
this.inputs.forEach(input => input.removeAttribute('invalid'));
|
1596
1805
|
}
|
1597
1806
|
|
1598
|
-
|
1807
|
+
getValidity() {
|
1599
1808
|
if (this.isRequired && !this.value) {
|
1600
|
-
|
1809
|
+
return { valueMissing: true };
|
1601
1810
|
}
|
1602
1811
|
else if (this.pattern && !new RegExp(this.pattern).test(this.value)) {
|
1603
|
-
|
1812
|
+
return { patternMismatch: true };
|
1604
1813
|
}
|
1605
1814
|
else {
|
1606
|
-
|
1815
|
+
return {}
|
1607
1816
|
}
|
1608
1817
|
};
|
1609
1818
|
|
1819
|
+
handleFocus() {
|
1820
|
+
this.inputs[0].focus();
|
1821
|
+
}
|
1822
|
+
|
1610
1823
|
async connectedCallback() {
|
1611
|
-
|
1824
|
+
super.connectedCallback();
|
1612
1825
|
this.initInputs();
|
1613
1826
|
|
1614
|
-
this.
|
1615
|
-
|
1616
|
-
};
|
1827
|
+
this.addEventListener('invalid', this.handleInputsInvalid);
|
1828
|
+
this.addEventListener('valid', this.handleInputsValid);
|
1617
1829
|
}
|
1618
1830
|
|
1619
1831
|
getInputIdx(inputEle) {
|
@@ -1644,6 +1856,10 @@ class PasscodeInternal extends HTMLElement {
|
|
1644
1856
|
!currentInput.hasAttribute('focused') && focusElement(currentInput);
|
1645
1857
|
};
|
1646
1858
|
|
1859
|
+
handleBlur() {
|
1860
|
+
this.handleInputsInvalid();
|
1861
|
+
}
|
1862
|
+
|
1647
1863
|
initInputs() {
|
1648
1864
|
this.inputs.forEach((input) => {
|
1649
1865
|
|
@@ -1652,7 +1868,7 @@ class PasscodeInternal extends HTMLElement {
|
|
1652
1868
|
// if not, the component is no longer focused and we should simulate blur
|
1653
1869
|
input.addEventListener('blur', () => {
|
1654
1870
|
const timerId = setTimeout(() => {
|
1655
|
-
this.
|
1871
|
+
this.dispatchBlur();
|
1656
1872
|
});
|
1657
1873
|
|
1658
1874
|
this.inputs.forEach((ele) =>
|
@@ -1660,13 +1876,13 @@ class PasscodeInternal extends HTMLElement {
|
|
1660
1876
|
);
|
1661
1877
|
});
|
1662
1878
|
|
1663
|
-
input.oninput = (
|
1879
|
+
input.oninput = () => {
|
1664
1880
|
const charArr = getSanitizedCharacters(input.value);
|
1665
1881
|
|
1666
1882
|
if (!charArr.length) input.value = ''; // if we got an invalid value we want to clear the input
|
1667
1883
|
else this.fillDigits(charArr, input);
|
1668
1884
|
|
1669
|
-
this.
|
1885
|
+
this.dispatchInput();
|
1670
1886
|
};
|
1671
1887
|
|
1672
1888
|
input.onkeydown = ({ key }) => {
|
@@ -1679,27 +1895,21 @@ class PasscodeInternal extends HTMLElement {
|
|
1679
1895
|
!prevInput.hasAttribute('focused') && setTimeout(() => {
|
1680
1896
|
focusElement(prevInput);
|
1681
1897
|
});
|
1898
|
+
|
1899
|
+
this.dispatchInput();
|
1682
1900
|
} else if (key.match(/^(\d)$/g)) { // if input is a digit
|
1683
1901
|
input.value = ''; // we are clearing the previous value so we can override it with the new value
|
1684
1902
|
}
|
1685
1903
|
|
1686
|
-
this.setValidity();
|
1687
1904
|
};
|
1688
1905
|
});
|
1689
1906
|
}
|
1690
1907
|
|
1691
|
-
attributeChangedCallback(
|
1692
|
-
attrName,
|
1693
|
-
oldValue,
|
1694
|
-
newValue
|
1695
|
-
) {
|
1696
|
-
const validationRelatedAttributes = ['required', 'pattern'];
|
1908
|
+
attributeChangedCallback(attrName, oldValue, newValue) {
|
1909
|
+
super.attributeChangedCallback(attrName, oldValue, newValue);
|
1697
1910
|
|
1698
1911
|
if (oldValue !== newValue) {
|
1699
|
-
if (
|
1700
|
-
this.setValidity();
|
1701
|
-
}
|
1702
|
-
else if (PasscodeInternal.observedAttributes.includes(attrName)) {
|
1912
|
+
if (PasscodeInternal.observedAttributes.includes(attrName) && !BaseInputClass.observedAttributes.includes(attrName)) {
|
1703
1913
|
this.inputs.forEach((input) => input.setAttribute(attrName, newValue));
|
1704
1914
|
}
|
1705
1915
|
}
|
@@ -1771,7 +1981,7 @@ const Passcode = compose(
|
|
1771
1981
|
}
|
1772
1982
|
}),
|
1773
1983
|
draggableMixin,
|
1774
|
-
|
1984
|
+
proxyInputMixin,
|
1775
1985
|
componentNameValidationMixin,
|
1776
1986
|
customMixin
|
1777
1987
|
)(
|
@@ -1858,7 +2068,7 @@ const PasswordField = compose(
|
|
1858
2068
|
}
|
1859
2069
|
}),
|
1860
2070
|
draggableMixin,
|
1861
|
-
|
2071
|
+
proxyInputMixin,
|
1862
2072
|
componentNameValidationMixin
|
1863
2073
|
)(
|
1864
2074
|
createProxy({
|
@@ -1924,7 +2134,7 @@ const SwitchToggle = compose(
|
|
1924
2134
|
}
|
1925
2135
|
}),
|
1926
2136
|
draggableMixin,
|
1927
|
-
|
2137
|
+
proxyInputMixin,
|
1928
2138
|
componentNameValidationMixin
|
1929
2139
|
)(
|
1930
2140
|
createProxy({
|
@@ -2015,7 +2225,7 @@ const TextArea = compose(
|
|
2015
2225
|
}
|
2016
2226
|
}),
|
2017
2227
|
draggableMixin,
|
2018
|
-
|
2228
|
+
proxyInputMixin,
|
2019
2229
|
componentNameValidationMixin
|
2020
2230
|
)(
|
2021
2231
|
createProxy({
|
@@ -2442,7 +2652,7 @@ const textField = (vars) => ({
|
|
2442
2652
|
[vars.borderColor]: globalRefs$6.colors.surface.main
|
2443
2653
|
},
|
2444
2654
|
|
2445
|
-
|
2655
|
+
_invalid: {
|
2446
2656
|
[vars.borderColor]: globalRefs$6.colors.error.main,
|
2447
2657
|
[vars.color]: globalRefs$6.colors.error.main,
|
2448
2658
|
[vars.placeholderColor]: globalRefs$6.colors.error.light
|