@descope/web-components-ui 1.0.77 → 1.0.79
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/index.esm.js +149 -152
- package/dist/index.esm.js.map +1 -1
- package/dist/umd/878.js +1 -1
- package/dist/umd/988.js +1 -0
- 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-box-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-image-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-phone-field-descope-phone-field-internal-index-js.js +1 -1
- package/dist/umd/descope-phone-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/createBaseClass.js +3 -1
- package/src/baseClasses/createBaseInputClass.js +4 -3
- package/src/components/descope-combo-box/ComboBox.js +2 -2
- package/src/components/descope-passcode/descope-passcode-internal/PasscodeInternal.js +2 -31
- package/src/components/descope-phone-field/descope-phone-field-internal/PhoneFieldInternal.js +8 -32
- package/src/mixins/index.js +1 -1
- package/src/mixins/inputEventsDispatchingMixin.js +71 -0
- package/src/mixins/proxyInputMixin.js +7 -5
- package/dist/umd/744.js +0 -1
- package/src/mixins/focusMixin.js +0 -23
package/dist/index.esm.js
CHANGED
@@ -421,6 +421,65 @@ const draggableMixin = (superclass) =>
|
|
421
421
|
}
|
422
422
|
};
|
423
423
|
|
424
|
+
const componentNameValidationMixin = (superclass) =>
|
425
|
+
class ComponentNameValidationMixinClass extends superclass {
|
426
|
+
#checkComponentName() {
|
427
|
+
const currentComponentName = this.localName;
|
428
|
+
|
429
|
+
if (!superclass.componentName) {
|
430
|
+
throw Error(
|
431
|
+
`component name is not defined on super class, make sure you have a static get for "componentName"`
|
432
|
+
);
|
433
|
+
}
|
434
|
+
|
435
|
+
if (currentComponentName !== superclass.componentName) {
|
436
|
+
throw Error(
|
437
|
+
`component name mismatch, expected "${superclass.componentName}", current "${currentComponentName}"`
|
438
|
+
);
|
439
|
+
}
|
440
|
+
}
|
441
|
+
|
442
|
+
init() {
|
443
|
+
super.init?.();
|
444
|
+
this.#checkComponentName();
|
445
|
+
}
|
446
|
+
};
|
447
|
+
|
448
|
+
const hoverableMixin = (superclass) =>
|
449
|
+
class HoverableMixinClass extends superclass {
|
450
|
+
init() {
|
451
|
+
super.init?.();
|
452
|
+
|
453
|
+
this.baseElement.addEventListener('mouseover', (e) => {
|
454
|
+
this.setAttribute('hover', 'true');
|
455
|
+
e.target.addEventListener(
|
456
|
+
'mouseleave',
|
457
|
+
() => this.removeAttribute('hover'),
|
458
|
+
{ once: true }
|
459
|
+
);
|
460
|
+
});
|
461
|
+
}
|
462
|
+
};
|
463
|
+
|
464
|
+
// we want all the valueless attributes to have "true" value
|
465
|
+
// and all the falsy attribute to be removed
|
466
|
+
const normalizeBooleanAttributesMixin = (superclass) => class NormalizeBooleanAttributesMixinClass extends superclass {
|
467
|
+
init() {
|
468
|
+
super.init?.();
|
469
|
+
|
470
|
+
observeAttributes(this, (attrs) =>
|
471
|
+
attrs.forEach(attr => {
|
472
|
+
const attrVal = this.getAttribute(attr);
|
473
|
+
|
474
|
+
if (attrVal === '') {
|
475
|
+
this.setAttribute(attr, 'true');
|
476
|
+
} else if (attrVal === 'false') {
|
477
|
+
this.removeAttribute(attr);
|
478
|
+
}
|
479
|
+
}), {});
|
480
|
+
}
|
481
|
+
};
|
482
|
+
|
424
483
|
const createBaseClass = ({ componentName, baseSelector = '' }) => {
|
425
484
|
class DescopeBaseClass extends HTMLElement {
|
426
485
|
static get componentName() {
|
@@ -757,13 +816,14 @@ const proxyInputMixin = (superclass) =>
|
|
757
816
|
|
758
817
|
reportValidityOnInternalInput() {
|
759
818
|
setTimeout(() => {
|
819
|
+
this.inputElement.focus();
|
760
820
|
this.inputElement.reportValidity();
|
761
821
|
});
|
762
822
|
}
|
763
823
|
|
764
824
|
// we want reportValidity to behave like form submission
|
765
825
|
reportValidity() {
|
766
|
-
if (!
|
826
|
+
if (!this.checkValidity()) {
|
767
827
|
this.setAttribute('invalid', 'true');
|
768
828
|
this.reportValidityOnInternalInput();
|
769
829
|
}
|
@@ -811,9 +871,10 @@ const proxyInputMixin = (superclass) =>
|
|
811
871
|
});
|
812
872
|
|
813
873
|
this.addEventListener('focus', (e) => {
|
814
|
-
// when clicking on the form submit button and the input is invalid
|
815
|
-
// we
|
816
|
-
|
874
|
+
// when clicking on the form submit button and the input is invalid, we want it to appear as invalid
|
875
|
+
// this is a best effort, we cannot identify it for sure without listening to the form submission event
|
876
|
+
// this will also be triggered when the focus is moving from the submit button to the input by pressing TAB key
|
877
|
+
if (e.relatedTarget?.form && e.relatedTarget?.form === this.form && e.relatedTarget?.nodeName === 'BUTTON') {
|
817
878
|
if (!this.checkValidity()) {
|
818
879
|
this.setAttribute('invalid', 'true');
|
819
880
|
}
|
@@ -841,70 +902,6 @@ const proxyInputMixin = (superclass) =>
|
|
841
902
|
}
|
842
903
|
};
|
843
904
|
|
844
|
-
const componentNameValidationMixin = (superclass) =>
|
845
|
-
class ComponentNameValidationMixinClass extends superclass {
|
846
|
-
#checkComponentName() {
|
847
|
-
const currentComponentName = this.localName;
|
848
|
-
|
849
|
-
if (!superclass.componentName) {
|
850
|
-
throw Error(
|
851
|
-
`component name is not defined on super class, make sure you have a static get for "componentName"`
|
852
|
-
);
|
853
|
-
}
|
854
|
-
|
855
|
-
if (currentComponentName !== superclass.componentName) {
|
856
|
-
throw Error(
|
857
|
-
`component name mismatch, expected "${superclass.componentName}", current "${currentComponentName}"`
|
858
|
-
);
|
859
|
-
}
|
860
|
-
}
|
861
|
-
|
862
|
-
init() {
|
863
|
-
super.init?.();
|
864
|
-
this.#checkComponentName();
|
865
|
-
}
|
866
|
-
};
|
867
|
-
|
868
|
-
const hoverableMixin = (superclass) =>
|
869
|
-
class HoverableMixinClass extends superclass {
|
870
|
-
init() {
|
871
|
-
super.init?.();
|
872
|
-
|
873
|
-
this.baseElement.addEventListener('mouseover', (e) => {
|
874
|
-
this.setAttribute('hover', 'true');
|
875
|
-
e.target.addEventListener(
|
876
|
-
'mouseleave',
|
877
|
-
() => this.removeAttribute('hover'),
|
878
|
-
{ once: true }
|
879
|
-
);
|
880
|
-
});
|
881
|
-
}
|
882
|
-
};
|
883
|
-
|
884
|
-
const focusMixin = (superclass) => class FocusMixinClass extends superclass {
|
885
|
-
// we want to block all native events,
|
886
|
-
// so the input can control when to dispatch it based on its internal behavior
|
887
|
-
init() {
|
888
|
-
super.init?.();
|
889
|
-
|
890
|
-
this.addEventListener('blur', (e) => {
|
891
|
-
e.isTrusted && e.stopImmediatePropagation();
|
892
|
-
});
|
893
|
-
|
894
|
-
this.addEventListener('focus', (e) => {
|
895
|
-
e.isTrusted && e.stopImmediatePropagation();
|
896
|
-
});
|
897
|
-
|
898
|
-
this.addEventListener('focusout', (e) => {
|
899
|
-
e.isTrusted && e.stopImmediatePropagation();
|
900
|
-
});
|
901
|
-
|
902
|
-
this.addEventListener('focusin', (e) => {
|
903
|
-
e.isTrusted && e.stopImmediatePropagation();
|
904
|
-
});
|
905
|
-
}
|
906
|
-
};
|
907
|
-
|
908
905
|
// this is needed because we might generate the same css vars names
|
909
906
|
// e.g. "overlayColor" attribute in style mixin's mapping,
|
910
907
|
// will generate the same var as "color" attribute in portals's mapping
|
@@ -991,25 +988,6 @@ const changeMixin = (superclass) => class ChangeMixinClass extends superclass {
|
|
991
988
|
}
|
992
989
|
};
|
993
990
|
|
994
|
-
// we want all the valueless attributes to have "true" value
|
995
|
-
// and all the falsy attribute to be removed
|
996
|
-
const normalizeBooleanAttributesMixin = (superclass) => class NormalizeBooleanAttributesMixinClass extends superclass {
|
997
|
-
init() {
|
998
|
-
super.init?.();
|
999
|
-
|
1000
|
-
observeAttributes(this, (attrs) =>
|
1001
|
-
attrs.forEach(attr => {
|
1002
|
-
const attrVal = this.getAttribute(attr);
|
1003
|
-
|
1004
|
-
if (attrVal === '') {
|
1005
|
-
this.setAttribute(attr, 'true');
|
1006
|
-
} else if (attrVal === 'false') {
|
1007
|
-
this.removeAttribute(attr);
|
1008
|
-
}
|
1009
|
-
}), {});
|
1010
|
-
}
|
1011
|
-
};
|
1012
|
-
|
1013
991
|
const readOnlyMixin = (superclass) => class ReadOnlyMixinClass extends superclass {
|
1014
992
|
get isReadOnly() {
|
1015
993
|
return this.hasAttribute('readonly') && this.getAttribute('readonly') !== 'false'
|
@@ -1029,6 +1007,76 @@ const readOnlyMixin = (superclass) => class ReadOnlyMixinClass extends superclas
|
|
1029
1007
|
}
|
1030
1008
|
};
|
1031
1009
|
|
1010
|
+
const inputEventsDispatchingMixin = (superclass) => class InputEventsDispatchingMixinClass extends superclass {
|
1011
|
+
init() {
|
1012
|
+
this.#blockNativeEvents();
|
1013
|
+
this.#handleFocusEventsDispatching();
|
1014
|
+
this.#handleInputEventDispatching();
|
1015
|
+
|
1016
|
+
super.init?.();
|
1017
|
+
}
|
1018
|
+
|
1019
|
+
// we want to block the native (trusted) events and control when these events are being dispatched
|
1020
|
+
#blockNativeEvents() {
|
1021
|
+
['blur', 'focus', 'focusin', 'focusout'].forEach(event => {
|
1022
|
+
this.addEventListener(event, (e) => {
|
1023
|
+
e.isTrusted && e.target === this && e.stopImmediatePropagation();
|
1024
|
+
});
|
1025
|
+
});
|
1026
|
+
}
|
1027
|
+
|
1028
|
+
#handleFocusEventsDispatching() {
|
1029
|
+
let timerId;
|
1030
|
+
|
1031
|
+
// in order to simulate blur & focusout on root input element
|
1032
|
+
// we are checking if focus on one of the inner elements happened immediately after blur
|
1033
|
+
// if not, the component is no longer focused and we should dispatch blur & focusout
|
1034
|
+
this.addEventListener('focusout', (e) => {
|
1035
|
+
if (e.isTrusted) {
|
1036
|
+
e.stopImmediatePropagation();
|
1037
|
+
timerId = setTimeout(() => {
|
1038
|
+
timerId = null;
|
1039
|
+
createDispatchEvent.call(this, 'blur');
|
1040
|
+
createDispatchEvent.call(this, 'focusout', { bubbles: true });
|
1041
|
+
});
|
1042
|
+
}
|
1043
|
+
});
|
1044
|
+
|
1045
|
+
// in order to simulate focus & focusin on the root input element
|
1046
|
+
// we are holding a timer id and clearing it on focusin
|
1047
|
+
// if there is a timer id, it means that the root input is still focused
|
1048
|
+
// otherwise, it was not focused before, and we should dispatch focus & focusin
|
1049
|
+
this.addEventListener('focusin', (e) => {
|
1050
|
+
if (e.isTrusted) {
|
1051
|
+
e.stopImmediatePropagation();
|
1052
|
+
clearTimeout(timerId);
|
1053
|
+
if (!timerId) {
|
1054
|
+
createDispatchEvent.call(this, 'focus');
|
1055
|
+
createDispatchEvent.call(this, 'focusin', { bubbles: true });
|
1056
|
+
}
|
1057
|
+
}
|
1058
|
+
});
|
1059
|
+
}
|
1060
|
+
|
1061
|
+
// we want to block the input events from propagating in case the value of the root input wasn't change
|
1062
|
+
// this can happen if we are sanitizing characters on the internal inputs and do not want it to affect the root input element value
|
1063
|
+
// in this case, on each input event, we are comparing the root input value to the previous one, and only if it does not match, we are allowing the input event to propagate
|
1064
|
+
#handleInputEventDispatching() {
|
1065
|
+
let previousRootComponentValue = this.value;
|
1066
|
+
|
1067
|
+
this.addEventListener('input', (e) => {
|
1068
|
+
// we are comparing the previous value to the new one,
|
1069
|
+
// and if they have the same value, we are blocking the input event
|
1070
|
+
if (previousRootComponentValue === this.value) {
|
1071
|
+
e.stopImmediatePropagation();
|
1072
|
+
} else {
|
1073
|
+
previousRootComponentValue = this.value;
|
1074
|
+
}
|
1075
|
+
});
|
1076
|
+
|
1077
|
+
}
|
1078
|
+
};
|
1079
|
+
|
1032
1080
|
const componentName$l = getComponentName('button');
|
1033
1081
|
|
1034
1082
|
const editorOverrides = `vaadin-button::part(label) { pointer-events: none; }`;
|
@@ -1754,10 +1802,11 @@ overrides$4 = `
|
|
1754
1802
|
customElements.define(componentName$a, NumberField);
|
1755
1803
|
|
1756
1804
|
const createBaseInputClass = (...args) => compose(
|
1757
|
-
focusMixin,
|
1758
1805
|
inputValidationMixin,
|
1759
1806
|
changeMixin,
|
1760
|
-
readOnlyMixin
|
1807
|
+
readOnlyMixin,
|
1808
|
+
normalizeBooleanAttributesMixin,
|
1809
|
+
inputEventsDispatchingMixin
|
1761
1810
|
)(createBaseClass(...args));
|
1762
1811
|
|
1763
1812
|
const focusElement = (ele) => {
|
@@ -1913,31 +1962,8 @@ class PasscodeInternal extends BaseInputClass$1 {
|
|
1913
1962
|
};
|
1914
1963
|
|
1915
1964
|
initInputs() {
|
1916
|
-
let prevVal = this.value;
|
1917
|
-
let blurTimerId;
|
1918
|
-
|
1919
1965
|
this.inputs.forEach((input) => {
|
1920
|
-
//
|
1921
|
-
// we are checking if focus on one of the digits happened immediately after blur on another digit
|
1922
|
-
// if not, the component is no longer focused and we should simulate blur
|
1923
|
-
input.addEventListener('blur', (e) => {
|
1924
|
-
e.stopImmediatePropagation();
|
1925
|
-
|
1926
|
-
blurTimerId = setTimeout(() => {
|
1927
|
-
blurTimerId = null;
|
1928
|
-
this.#dispatchBlur();
|
1929
|
-
});
|
1930
|
-
});
|
1931
|
-
|
1932
|
-
input.addEventListener('focus', (e) => {
|
1933
|
-
e.stopImmediatePropagation();
|
1934
|
-
|
1935
|
-
clearTimeout(blurTimerId);
|
1936
|
-
if (!blurTimerId) {
|
1937
|
-
this.#dispatchFocus();
|
1938
|
-
}
|
1939
|
-
});
|
1940
|
-
|
1966
|
+
// sanitize the input
|
1941
1967
|
input.addEventListener('input', (e) => {
|
1942
1968
|
const charArr = getSanitizedCharacters(input.value);
|
1943
1969
|
|
@@ -1946,16 +1972,10 @@ class PasscodeInternal extends BaseInputClass$1 {
|
|
1946
1972
|
input.value = '';
|
1947
1973
|
}
|
1948
1974
|
else this.fillDigits(charArr, input);
|
1949
|
-
|
1950
|
-
// we want to stop input events if the value wasn't change
|
1951
|
-
if (prevVal === this.value) {
|
1952
|
-
e.stopImmediatePropagation();
|
1953
|
-
}
|
1954
1975
|
});
|
1955
1976
|
|
1977
|
+
// we want backspace to focus on the previous digit
|
1956
1978
|
input.onkeydown = ({ key }) => {
|
1957
|
-
prevVal = this.value;
|
1958
|
-
|
1959
1979
|
// when user deletes a digit, we want to focus the previous digit
|
1960
1980
|
if (key === 'Backspace') {
|
1961
1981
|
// if the cursor is at 0, we want to move it to 1, so the value will be deleted
|
@@ -2536,8 +2556,8 @@ const ComboBoxMixin = (superclass) => class ComboBoxMixinClass extends superclas
|
|
2536
2556
|
overlay._enterModalState = function () { };
|
2537
2557
|
}
|
2538
2558
|
|
2539
|
-
|
2540
|
-
super.
|
2559
|
+
init() {
|
2560
|
+
super.init?.();
|
2541
2561
|
|
2542
2562
|
this.#overrideOverlaySettings();
|
2543
2563
|
observeChildren(this, this.#onChildrenChange.bind(this));
|
@@ -3905,9 +3925,6 @@ class PhoneFieldInternal extends BaseInputClass {
|
|
3905
3925
|
);
|
3906
3926
|
}
|
3907
3927
|
|
3908
|
-
#dispatchBlur = createDispatchEvent.bind(this, 'blur');
|
3909
|
-
#dispatchFocus = createDispatchEvent.bind(this, 'focus');
|
3910
|
-
|
3911
3928
|
constructor() {
|
3912
3929
|
super();
|
3913
3930
|
|
@@ -3972,6 +3989,13 @@ class PhoneFieldInternal extends BaseInputClass {
|
|
3972
3989
|
};
|
3973
3990
|
|
3974
3991
|
init() {
|
3992
|
+
|
3993
|
+
this.addEventListener('focus', (e) => {
|
3994
|
+
// we want to ignore focus events we are dispatching
|
3995
|
+
if (e.isTrusted)
|
3996
|
+
this.inputs[0].focus();
|
3997
|
+
});
|
3998
|
+
|
3975
3999
|
super.init();
|
3976
4000
|
this.initInputs();
|
3977
4001
|
this.setComboBoxDescriptor();
|
@@ -4022,9 +4046,6 @@ class PhoneFieldInternal extends BaseInputClass {
|
|
4022
4046
|
}
|
4023
4047
|
|
4024
4048
|
initInputs() {
|
4025
|
-
let prevVal = this.value;
|
4026
|
-
let blurTimerId;
|
4027
|
-
|
4028
4049
|
// Sanitize phone input value to filter everything but digits
|
4029
4050
|
this.phoneNumberInput.addEventListener('input', (e) => {
|
4030
4051
|
const telDigitsRegExp = /^\d$/;
|
@@ -4034,30 +4055,6 @@ class PhoneFieldInternal extends BaseInputClass {
|
|
4034
4055
|
.join('');
|
4035
4056
|
e.target.value = sanitizedInput;
|
4036
4057
|
});
|
4037
|
-
|
4038
|
-
this.inputs.forEach(input => {
|
4039
|
-
input.addEventListener('blur', (e) => {
|
4040
|
-
e.stopImmediatePropagation();
|
4041
|
-
blurTimerId = setTimeout(() => {
|
4042
|
-
blurTimerId = null;
|
4043
|
-
this.#dispatchBlur();
|
4044
|
-
});
|
4045
|
-
});
|
4046
|
-
|
4047
|
-
input.addEventListener('focus', (e) => {
|
4048
|
-
e.stopImmediatePropagation();
|
4049
|
-
clearTimeout(blurTimerId);
|
4050
|
-
if (!blurTimerId) {
|
4051
|
-
this.#dispatchFocus();
|
4052
|
-
}
|
4053
|
-
});
|
4054
|
-
|
4055
|
-
input.addEventListener('input', (e) => {
|
4056
|
-
if (prevVal === this.value) {
|
4057
|
-
e.stopImmediatePropagation();
|
4058
|
-
}
|
4059
|
-
});
|
4060
|
-
});
|
4061
4058
|
}
|
4062
4059
|
|
4063
4060
|
attributeChangedCallback(attrName, oldValue, newValue) {
|