@descope/web-components-ui 1.0.76 → 1.0.78
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/index.esm.js +137 -133
- package/dist/index.esm.js.map +1 -1
- package/dist/umd/878.js +1 -1
- package/dist/umd/933.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 -2
- package/src/components/descope-combo-box/ComboBox.js +2 -2
- package/src/components/descope-passcode/descope-passcode-internal/PasscodeInternal.js +5 -31
- package/src/components/descope-phone-field/PhoneField.js +0 -7
- package/src/components/descope-phone-field/descope-phone-field-internal/PhoneFieldInternal.js +10 -31
- package/src/mixins/index.js +1 -0
- package/src/mixins/inputEventsDispatchingMixin.js +54 -0
- package/src/mixins/proxyInputMixin.js +7 -5
- package/dist/umd/744.js +0 -1
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,46 +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
905
|
const focusMixin = (superclass) => class FocusMixinClass extends superclass {
|
885
906
|
// we want to block all native events,
|
886
907
|
// so the input can control when to dispatch it based on its internal behavior
|
@@ -991,25 +1012,6 @@ const changeMixin = (superclass) => class ChangeMixinClass extends superclass {
|
|
991
1012
|
}
|
992
1013
|
};
|
993
1014
|
|
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
1015
|
const readOnlyMixin = (superclass) => class ReadOnlyMixinClass extends superclass {
|
1014
1016
|
get isReadOnly() {
|
1015
1017
|
return this.hasAttribute('readonly') && this.getAttribute('readonly') !== 'false'
|
@@ -1029,6 +1031,59 @@ const readOnlyMixin = (superclass) => class ReadOnlyMixinClass extends superclas
|
|
1029
1031
|
}
|
1030
1032
|
};
|
1031
1033
|
|
1034
|
+
const inputEventsDispatchingMixin = (superclass) => class InputEventsDispatchingMixinClass extends superclass {
|
1035
|
+
handleFocusEventsDispatching(focusableElements = []) {
|
1036
|
+
let blurTimerId;
|
1037
|
+
|
1038
|
+
// in order to simulate blur on the input
|
1039
|
+
// we are checking if focus on one of the other elements happened immediately after blur
|
1040
|
+
// if not, the component is no longer focused and we should dispatch blur
|
1041
|
+
focusableElements.forEach(ele => {
|
1042
|
+
ele?.addEventListener('blur', (e) => {
|
1043
|
+
e.stopImmediatePropagation();
|
1044
|
+
blurTimerId = setTimeout(() => {
|
1045
|
+
blurTimerId = null;
|
1046
|
+
createDispatchEvent.call(this, 'blur');
|
1047
|
+
createDispatchEvent.call(this, 'focusout', { bubbles: true });
|
1048
|
+
});
|
1049
|
+
});
|
1050
|
+
|
1051
|
+
// in order to simulate focus on the input
|
1052
|
+
// we are holding a blur timer id and clearing it on blur
|
1053
|
+
// if there is a timer id, it means that there was no blur on the input, so it's still focused
|
1054
|
+
// otherwise, it was not focused before, and we need to dispatch a focus event
|
1055
|
+
ele?.addEventListener('focus', (e) => {
|
1056
|
+
e.stopImmediatePropagation();
|
1057
|
+
clearTimeout(blurTimerId);
|
1058
|
+
if (!blurTimerId) {
|
1059
|
+
createDispatchEvent.call(this, 'focus');
|
1060
|
+
createDispatchEvent.call(this, 'focusin', { bubbles: true });
|
1061
|
+
}
|
1062
|
+
});
|
1063
|
+
});
|
1064
|
+
}
|
1065
|
+
|
1066
|
+
// we want to block the input events from propagating in case the value of the root input wasn't change
|
1067
|
+
// this can happen if we are sanitizing characters on the internal inputs and do not want it to affect the root input element value
|
1068
|
+
// 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
|
1069
|
+
handleInputEventDispatching(inputElements) {
|
1070
|
+
let previousRootComponentValue = this.value;
|
1071
|
+
|
1072
|
+
inputElements.forEach(input => {
|
1073
|
+
input.addEventListener('input', (e) => {
|
1074
|
+
// we are comparing the previous value to the new one,
|
1075
|
+
// and if they have the same value, we are blocking the input event
|
1076
|
+
if (previousRootComponentValue === this.value) {
|
1077
|
+
e.stopImmediatePropagation();
|
1078
|
+
} else {
|
1079
|
+
previousRootComponentValue = this.value;
|
1080
|
+
}
|
1081
|
+
});
|
1082
|
+
});
|
1083
|
+
|
1084
|
+
}
|
1085
|
+
};
|
1086
|
+
|
1032
1087
|
const componentName$l = getComponentName('button');
|
1033
1088
|
|
1034
1089
|
const editorOverrides = `vaadin-button::part(label) { pointer-events: none; }`;
|
@@ -1757,7 +1812,9 @@ const createBaseInputClass = (...args) => compose(
|
|
1757
1812
|
focusMixin,
|
1758
1813
|
inputValidationMixin,
|
1759
1814
|
changeMixin,
|
1760
|
-
readOnlyMixin
|
1815
|
+
readOnlyMixin,
|
1816
|
+
normalizeBooleanAttributesMixin,
|
1817
|
+
inputEventsDispatchingMixin
|
1761
1818
|
)(createBaseClass(...args));
|
1762
1819
|
|
1763
1820
|
const focusElement = (ele) => {
|
@@ -1913,31 +1970,8 @@ class PasscodeInternal extends BaseInputClass$1 {
|
|
1913
1970
|
};
|
1914
1971
|
|
1915
1972
|
initInputs() {
|
1916
|
-
let prevVal = this.value;
|
1917
|
-
let blurTimerId;
|
1918
|
-
|
1919
1973
|
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
|
-
|
1974
|
+
// sanitize the input
|
1941
1975
|
input.addEventListener('input', (e) => {
|
1942
1976
|
const charArr = getSanitizedCharacters(input.value);
|
1943
1977
|
|
@@ -1946,16 +1980,10 @@ class PasscodeInternal extends BaseInputClass$1 {
|
|
1946
1980
|
input.value = '';
|
1947
1981
|
}
|
1948
1982
|
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
1983
|
});
|
1955
1984
|
|
1985
|
+
// we want backspace to focus on the previous digit
|
1956
1986
|
input.onkeydown = ({ key }) => {
|
1957
|
-
prevVal = this.value;
|
1958
|
-
|
1959
1987
|
// when user deletes a digit, we want to focus the previous digit
|
1960
1988
|
if (key === 'Backspace') {
|
1961
1989
|
// if the cursor is at 0, we want to move it to 1, so the value will be deleted
|
@@ -1972,6 +2000,9 @@ class PasscodeInternal extends BaseInputClass$1 {
|
|
1972
2000
|
|
1973
2001
|
forwardAttrs(this, input, { includeAttrs: forwardAttributes });
|
1974
2002
|
});
|
2003
|
+
|
2004
|
+
this.handleFocusEventsDispatching(this.inputs);
|
2005
|
+
this.handleInputEventDispatching(this.inputs);
|
1975
2006
|
}
|
1976
2007
|
|
1977
2008
|
attributeChangedCallback(attrName, oldValue, newValue) {
|
@@ -2536,8 +2567,8 @@ const ComboBoxMixin = (superclass) => class ComboBoxMixinClass extends superclas
|
|
2536
2567
|
overlay._enterModalState = function () { };
|
2537
2568
|
}
|
2538
2569
|
|
2539
|
-
|
2540
|
-
super.
|
2570
|
+
init() {
|
2571
|
+
super.init?.();
|
2541
2572
|
|
2542
2573
|
this.#overrideOverlaySettings();
|
2543
2574
|
observeChildren(this, this.#onChildrenChange.bind(this));
|
@@ -3905,9 +3936,6 @@ class PhoneFieldInternal extends BaseInputClass {
|
|
3905
3936
|
);
|
3906
3937
|
}
|
3907
3938
|
|
3908
|
-
#dispatchBlur = createDispatchEvent.bind(this, 'blur');
|
3909
|
-
#dispatchFocus = createDispatchEvent.bind(this, 'focus');
|
3910
|
-
|
3911
3939
|
constructor() {
|
3912
3940
|
super();
|
3913
3941
|
|
@@ -3972,6 +4000,13 @@ class PhoneFieldInternal extends BaseInputClass {
|
|
3972
4000
|
};
|
3973
4001
|
|
3974
4002
|
init() {
|
4003
|
+
|
4004
|
+
this.addEventListener('focus', (e) => {
|
4005
|
+
// we want to ignore focus events we are dispatching
|
4006
|
+
if (e.isTrusted)
|
4007
|
+
this.inputs[0].focus();
|
4008
|
+
});
|
4009
|
+
|
3975
4010
|
super.init();
|
3976
4011
|
this.initInputs();
|
3977
4012
|
this.setComboBoxDescriptor();
|
@@ -4022,9 +4057,6 @@ class PhoneFieldInternal extends BaseInputClass {
|
|
4022
4057
|
}
|
4023
4058
|
|
4024
4059
|
initInputs() {
|
4025
|
-
let prevVal = this.value;
|
4026
|
-
let blurTimerId;
|
4027
|
-
|
4028
4060
|
// Sanitize phone input value to filter everything but digits
|
4029
4061
|
this.phoneNumberInput.addEventListener('input', (e) => {
|
4030
4062
|
const telDigitsRegExp = /^\d$/;
|
@@ -4035,29 +4067,8 @@ class PhoneFieldInternal extends BaseInputClass {
|
|
4035
4067
|
e.target.value = sanitizedInput;
|
4036
4068
|
});
|
4037
4069
|
|
4038
|
-
this.inputs
|
4039
|
-
|
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
|
-
});
|
4070
|
+
this.handleFocusEventsDispatching(this.inputs);
|
4071
|
+
this.handleInputEventDispatching(this.inputs);
|
4061
4072
|
}
|
4062
4073
|
|
4063
4074
|
attributeChangedCallback(attrName, oldValue, newValue) {
|
@@ -4251,13 +4262,6 @@ const PhoneField = compose(
|
|
4251
4262
|
})
|
4252
4263
|
);
|
4253
4264
|
|
4254
|
-
/*
|
4255
|
-
Bugs:
|
4256
|
-
- default code value, open the dropdown and click outside, the value is gone
|
4257
|
-
- make invalid by blur, enter a 6 digit number, component is valid but the divider is red
|
4258
|
-
- missing handling of outline when focused, hiding the divider when focusing the phone
|
4259
|
-
*/
|
4260
|
-
|
4261
4265
|
customElements.define(componentName, PhoneField);
|
4262
4266
|
|
4263
4267
|
const getVarName = (path) => getCssVarName(DESCOPE_PREFIX, ...path);
|