@descope/web-components-ui 1.0.135 → 1.0.148
Sign up to get free protection for your applications and to get access to all the features.
- package/package.json +77 -56
- package/src/baseClasses/createBaseClass.js +18 -16
- package/src/baseClasses/createBaseInputClass.js +14 -8
- package/src/baseClasses/createCssVarImageClass.js +27 -23
- package/src/components/boolean-fields/booleanFieldMixin.js +18 -29
- package/src/components/boolean-fields/commonStyles.js +1 -1
- package/src/components/boolean-fields/descope-boolean-field-internal/BooleanFieldInternal.js +46 -51
- package/src/components/boolean-fields/descope-boolean-field-internal/index.js +1 -1
- package/src/components/boolean-fields/descope-checkbox/CheckboxClass.js +80 -85
- package/src/components/boolean-fields/descope-checkbox/index.js +2 -2
- package/src/components/boolean-fields/descope-switch-toggle/SwitchToggleClass.js +88 -95
- package/src/components/boolean-fields/descope-switch-toggle/index.js +2 -2
- package/src/components/descope-button/ButtonClass.js +57 -47
- package/src/components/descope-button/clickableMixin.js +10 -0
- package/src/components/descope-combo-box/ComboBoxClass.js +156 -160
- package/src/components/descope-container/ContainerClass.js +32 -42
- package/src/components/descope-date-picker/index.js +9 -14
- package/src/components/descope-divider/DividerClass.js +52 -62
- package/src/components/descope-email-field/EmailFieldClass.js +25 -20
- package/src/components/descope-image/ImageClass.js +21 -24
- package/src/components/descope-link/LinkClass.js +31 -35
- package/src/components/descope-loader-linear/LoaderLinearClass.js +31 -36
- package/src/components/descope-loader-radial/LoaderRadialClass.js +23 -30
- package/src/components/descope-logo/LogoClass.js +5 -1
- package/src/components/descope-new-password/NewPasswordClass.js +63 -81
- package/src/components/descope-new-password/descope-new-password-internal/NewPasswordInternal.js +157 -162
- package/src/components/descope-new-password/descope-new-password-internal/componentName.js +1 -1
- package/src/components/descope-new-password/descope-new-password-internal/index.js +3 -3
- package/src/components/descope-new-password/index.js +3 -3
- package/src/components/descope-number-field/NumberFieldClass.js +25 -20
- package/src/components/descope-passcode/PasscodeClass.js +95 -95
- package/src/components/descope-passcode/descope-passcode-internal/PasscodeInternal.js +151 -157
- package/src/components/descope-passcode/descope-passcode-internal/helpers.js +7 -8
- package/src/components/descope-passcode/descope-passcode-internal/index.js +2 -2
- package/src/components/descope-passcode/index.js +2 -2
- package/src/components/descope-password/PasswordClass.js +75 -83
- package/src/components/descope-password/passwordDraggableMixin.js +28 -27
- package/src/components/descope-phone-field/CountryCodes.js +1210 -1210
- package/src/components/descope-phone-field/PhoneFieldClass.js +139 -141
- package/src/components/descope-phone-field/descope-phone-field-internal/PhoneFieldInternal.js +157 -173
- package/src/components/descope-phone-field/helpers.js +3 -3
- package/src/components/descope-text/TextClass.js +25 -29
- package/src/components/descope-text-area/TextAreaClass.js +68 -67
- package/src/components/descope-text-field/TextFieldClass.js +42 -37
- package/src/components/descope-text-field/textFieldMappings.js +40 -55
- package/src/components/descope-totp-image/TotpImageClass.js +5 -1
- package/src/components/descope-upload-file/UploadFileClass.js +202 -0
- package/src/components/descope-upload-file/helpers.js +11 -0
- package/src/components/descope-upload-file/index.js +6 -0
- package/src/constants.js +3 -3
- package/src/helpers/componentHelpers.js +68 -74
- package/src/helpers/index.js +17 -16
- package/src/helpers/mixinsHelpers.js +21 -10
- package/src/helpers/themeHelpers/colorsHelpers.js +18 -18
- package/src/helpers/themeHelpers/componentsThemeManager.js +7 -6
- package/src/helpers/themeHelpers/index.js +114 -124
- package/src/helpers/themeHelpers/resetHelpers.js +16 -16
- package/src/index.cjs.js +3 -3
- package/src/index.d.ts +22 -21
- package/src/index.js +5 -4
- package/src/index.umd.js +14 -13
- package/src/mixins/changeMixin.js +18 -17
- package/src/mixins/componentNameValidationMixin.js +19 -19
- package/src/mixins/createProxy.js +33 -33
- package/src/mixins/createStyleMixin/helpers.js +54 -64
- package/src/mixins/createStyleMixin/index.js +155 -141
- package/src/mixins/draggableMixin.js +61 -61
- package/src/mixins/hoverableMixin.js +11 -13
- package/src/mixins/index.js +6 -6
- package/src/mixins/inputEventsDispatchingMixin.js +61 -60
- package/src/mixins/inputValidationMixin.js +153 -148
- package/src/mixins/lifecycleEventsMixin.js +17 -15
- package/src/mixins/normalizeBooleanAttributesMixin.js +31 -23
- package/src/mixins/portalMixin.js +58 -52
- package/src/mixins/proxyInputMixin.js +138 -132
- package/src/theme/components/button.js +86 -81
- package/src/theme/components/checkbox.js +26 -28
- package/src/theme/components/comboBox.js +32 -31
- package/src/theme/components/container.js +99 -89
- package/src/theme/components/divider.js +30 -31
- package/src/theme/components/emailField.js +20 -19
- package/src/theme/components/image.js +3 -3
- package/src/theme/components/index.js +33 -25
- package/src/theme/components/inputWrapper.js +28 -25
- package/src/theme/components/link.js +29 -36
- package/src/theme/components/loader/index.js +3 -3
- package/src/theme/components/loader/loaderLinear.js +34 -34
- package/src/theme/components/loader/loaderRadial.js +40 -34
- package/src/theme/components/logo.js +4 -4
- package/src/theme/components/newPassword.js +14 -13
- package/src/theme/components/numberField.js +20 -19
- package/src/theme/components/passcode.js +20 -22
- package/src/theme/components/password.js +22 -21
- package/src/theme/components/phoneField.js +23 -23
- package/src/theme/components/switchToggle.js +47 -46
- package/src/theme/components/text.js +72 -72
- package/src/theme/components/textArea.js +27 -25
- package/src/theme/components/textField.js +23 -22
- package/src/theme/components/totpImage.js +4 -4
- package/src/theme/components/uploadFile.js +60 -0
- package/src/theme/globals.js +123 -124
- package/src/theme/index.js +1 -1
- package/dist/cjs/index.cjs.js +0 -5924
- package/dist/cjs/index.cjs.js.map +0 -1
- package/dist/cjs/package.json +0 -1
- package/dist/index.d.ts +0 -51
- package/dist/index.esm.js +0 -6606
- package/dist/index.esm.js.map +0 -1
- package/dist/umd/1018.js +0 -577
- package/dist/umd/1018.js.LICENSE.txt +0 -23
- package/dist/umd/2481.js +0 -1
- package/dist/umd/3208.js +0 -2
- package/dist/umd/3208.js.LICENSE.txt +0 -5
- package/dist/umd/3585.js +0 -1
- package/dist/umd/3878.js +0 -1
- package/dist/umd/4201.js +0 -1
- package/dist/umd/422.js +0 -2
- package/dist/umd/422.js.LICENSE.txt +0 -5
- package/dist/umd/4447.js +0 -1
- package/dist/umd/4513.js +0 -1
- package/dist/umd/4803.js +0 -1
- package/dist/umd/541.js +0 -744
- package/dist/umd/541.js.LICENSE.txt +0 -21
- package/dist/umd/5767.js +0 -2
- package/dist/umd/5767.js.LICENSE.txt +0 -15
- package/dist/umd/5806.js +0 -109
- package/dist/umd/5806.js.LICENSE.txt +0 -5
- package/dist/umd/7056.js +0 -48
- package/dist/umd/7056.js.LICENSE.txt +0 -5
- package/dist/umd/7101.js +0 -148
- package/dist/umd/7101.js.LICENSE.txt +0 -11
- package/dist/umd/729.js +0 -1
- package/dist/umd/7824.js +0 -229
- package/dist/umd/7824.js.LICENSE.txt +0 -27
- package/dist/umd/7840.js +0 -356
- package/dist/umd/7840.js.LICENSE.txt +0 -61
- package/dist/umd/8725.js +0 -37
- package/dist/umd/8725.js.LICENSE.txt +0 -11
- package/dist/umd/9211.js +0 -312
- package/dist/umd/9211.js.LICENSE.txt +0 -5
- package/dist/umd/9241.js +0 -1
- package/dist/umd/9314.js +0 -283
- package/dist/umd/9314.js.LICENSE.txt +0 -27
- package/dist/umd/9437.js +0 -19
- package/dist/umd/9437.js.LICENSE.txt +0 -5
- package/dist/umd/9515.js +0 -202
- package/dist/umd/9515.js.LICENSE.txt +0 -11
- package/dist/umd/9789.js +0 -1
- package/dist/umd/boolean-fields-descope-boolean-field-internal-index-js.js +0 -1
- package/dist/umd/boolean-fields-descope-checkbox-index-js.js +0 -1
- package/dist/umd/boolean-fields-descope-switch-toggle-index-js.js +0 -1
- package/dist/umd/descope-button-index-js.js +0 -1
- package/dist/umd/descope-combo-box-index-js.js +0 -1
- package/dist/umd/descope-container-index-js.js +0 -1
- package/dist/umd/descope-date-picker-index-js.js +0 -1
- package/dist/umd/descope-divider-index-js.js +0 -1
- package/dist/umd/descope-email-field-index-js.js +0 -1
- package/dist/umd/descope-image-index-js.js +0 -1
- package/dist/umd/descope-link-index-js.js +0 -1
- package/dist/umd/descope-loader-linear-index-js.js +0 -1
- package/dist/umd/descope-loader-radial-index-js.js +0 -1
- package/dist/umd/descope-logo-index-js.js +0 -1
- package/dist/umd/descope-new-password-descope-new-password-internal-index-js.js +0 -1
- package/dist/umd/descope-new-password-index-js.js +0 -1
- package/dist/umd/descope-number-field-index-js.js +0 -1
- package/dist/umd/descope-passcode-descope-passcode-internal-index-js.js +0 -1
- package/dist/umd/descope-passcode-index-js.js +0 -1
- package/dist/umd/descope-password-index-js.js +0 -1
- package/dist/umd/descope-phone-field-descope-phone-field-internal-index-js.js +0 -1
- package/dist/umd/descope-phone-field-index-js.js +0 -1
- package/dist/umd/descope-text-area-index-js.js +0 -1
- package/dist/umd/descope-text-field-index-js.js +0 -1
- package/dist/umd/descope-text-index-js.js +0 -1
- package/dist/umd/descope-totp-image-index-js.js +0 -1
- package/dist/umd/index.js +0 -1
@@ -1,62 +1,62 @@
|
|
1
1
|
export const draggableMixin = (superclass) =>
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
2
|
+
class DraggableMixinClass extends superclass {
|
3
|
+
#styleEle = null;
|
4
|
+
|
5
|
+
static get observedAttributes() {
|
6
|
+
const superAttrs = superclass.observedAttributes || [];
|
7
|
+
return [...superAttrs, 'draggable'];
|
8
|
+
}
|
9
|
+
|
10
|
+
constructor() {
|
11
|
+
super();
|
12
|
+
|
13
|
+
this.#styleEle = document.createElement('style');
|
14
|
+
this.#styleEle.innerText = `* { cursor: inherit!important }`;
|
15
|
+
}
|
16
|
+
|
17
|
+
#handleDraggableStyle(isDraggable) {
|
18
|
+
if (isDraggable) {
|
19
|
+
this.shadowRoot.appendChild(this.#styleEle);
|
20
|
+
} else {
|
21
|
+
this.#styleEle.remove();
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
get isDraggable() {
|
26
|
+
return this.hasAttribute('draggable') && this.getAttribute('draggable') !== 'false';
|
27
|
+
}
|
28
|
+
|
29
|
+
init() {
|
30
|
+
// because we are delegating the focus from the outer component,
|
31
|
+
// the D&D is not working well in the page editor
|
32
|
+
// in order to solve it we are making the inner component focusable on mouse down
|
33
|
+
// and removing it on complete
|
34
|
+
this.addEventListener('mousedown', (e) => {
|
35
|
+
if (this.isDraggable) {
|
36
|
+
const prevTabIndex = this.baseElement.getAttribute('tabindex');
|
37
|
+
this.baseElement.setAttribute('tabindex', '-1');
|
38
|
+
|
39
|
+
const onComplete = () => {
|
40
|
+
prevTabIndex
|
41
|
+
? this.baseElement.setAttribute('tabindex', prevTabIndex)
|
42
|
+
: this.baseElement.removeAttribute('tabindex');
|
43
|
+
|
44
|
+
e.target.removeEventListener('mouseup', onComplete);
|
45
|
+
e.target.removeEventListener('dragend', onComplete);
|
46
|
+
};
|
47
|
+
|
48
|
+
e.target.addEventListener('mouseup', onComplete, { once: true });
|
49
|
+
e.target.addEventListener('dragend', onComplete, { once: true });
|
50
|
+
}
|
51
|
+
});
|
52
|
+
|
53
|
+
super.init?.();
|
54
|
+
}
|
55
|
+
|
56
|
+
attributeChangedCallback(attrName, oldValue, newValue) {
|
57
|
+
super.attributeChangedCallback?.(attrName, oldValue, newValue);
|
58
|
+
if (attrName === 'draggable') {
|
59
|
+
this.#handleDraggableStyle(newValue === 'true');
|
60
|
+
}
|
61
|
+
}
|
62
|
+
};
|
@@ -1,15 +1,13 @@
|
|
1
1
|
export const hoverableMixin = (superclass) =>
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
class HoverableMixinClass extends superclass {
|
3
|
+
init() {
|
4
|
+
super.init?.();
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
}
|
15
|
-
};
|
6
|
+
this.baseElement.addEventListener('mouseover', (e) => {
|
7
|
+
this.setAttribute('hover', 'true');
|
8
|
+
e.target.addEventListener('mouseleave', () => this.removeAttribute('hover'), {
|
9
|
+
once: true,
|
10
|
+
});
|
11
|
+
});
|
12
|
+
}
|
13
|
+
};
|
package/src/mixins/index.js
CHANGED
@@ -4,9 +4,9 @@ export { createProxy } from './createProxy';
|
|
4
4
|
export { proxyInputMixin } from './proxyInputMixin';
|
5
5
|
export { componentNameValidationMixin } from './componentNameValidationMixin';
|
6
6
|
export { hoverableMixin } from './hoverableMixin';
|
7
|
-
export { inputValidationMixin } from './inputValidationMixin'
|
8
|
-
export { portalMixin } from './portalMixin'
|
9
|
-
export { changeMixin } from './changeMixin'
|
10
|
-
export { normalizeBooleanAttributesMixin } from './normalizeBooleanAttributesMixin'
|
11
|
-
export { lifecycleEventsMixin } from './lifecycleEventsMixin'
|
12
|
-
export { inputEventsDispatchingMixin } from './inputEventsDispatchingMixin'
|
7
|
+
export { inputValidationMixin } from './inputValidationMixin';
|
8
|
+
export { portalMixin } from './portalMixin';
|
9
|
+
export { changeMixin } from './changeMixin';
|
10
|
+
export { normalizeBooleanAttributesMixin } from './normalizeBooleanAttributesMixin';
|
11
|
+
export { lifecycleEventsMixin } from './lifecycleEventsMixin';
|
12
|
+
export { inputEventsDispatchingMixin } from './inputEventsDispatchingMixin';
|
@@ -1,71 +1,72 @@
|
|
1
|
-
import { createDispatchEvent } from
|
1
|
+
import { createDispatchEvent } from '../helpers/mixinsHelpers';
|
2
2
|
|
3
|
-
export const inputEventsDispatchingMixin = (superclass) =>
|
4
|
-
|
5
|
-
|
3
|
+
export const inputEventsDispatchingMixin = (superclass) =>
|
4
|
+
class InputEventsDispatchingMixinClass extends superclass {
|
5
|
+
init() {
|
6
|
+
this.#blockNativeEvents();
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
super.init?.();
|
9
|
+
}
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
// we want to block the native (trusted) events and control when these events are being dispatched
|
12
|
+
#blockNativeEvents() {
|
13
|
+
['blur', 'focus', 'focusin', 'focusout'].forEach((event) => {
|
14
|
+
this.addEventListener(event, (e) => {
|
15
|
+
e.isTrusted && e.target === this && e.stopImmediatePropagation();
|
16
|
+
});
|
17
|
+
});
|
18
|
+
}
|
18
19
|
|
19
|
-
|
20
|
-
|
20
|
+
handleFocusEventsDispatching(inputs) {
|
21
|
+
let timerId;
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
23
|
+
// in order to simulate blur & focusout on root input element
|
24
|
+
// we are checking if focus on one of the inner elements happened immediately after blur
|
25
|
+
// if not, the component is no longer focused and we should dispatch blur & focusout
|
26
|
+
inputs?.forEach((input) => {
|
27
|
+
input?.addEventListener('focusout', (e) => {
|
28
|
+
e.stopImmediatePropagation();
|
29
|
+
timerId = setTimeout(() => {
|
30
|
+
timerId = null;
|
30
31
|
|
31
|
-
|
32
|
-
|
32
|
+
createDispatchEvent.call(this, 'blur');
|
33
|
+
createDispatchEvent.call(this, 'focusout', { bubbles: true });
|
34
|
+
});
|
33
35
|
});
|
34
|
-
})
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
37
|
+
// in order to simulate focus & focusin on the root input element
|
38
|
+
// we are holding a timer id and clearing it on focusin
|
39
|
+
// if there is a timer id, it means that the root input is still focused
|
40
|
+
// otherwise, it was not focused before, and we should dispatch focus & focusin
|
41
|
+
const onFocus = (e) => {
|
42
|
+
e.stopImmediatePropagation();
|
43
|
+
clearTimeout(timerId);
|
44
|
+
if (!timerId) {
|
45
|
+
createDispatchEvent.call(this, 'focus');
|
46
|
+
createDispatchEvent.call(this, 'focusin', { bubbles: true });
|
47
|
+
}
|
48
|
+
};
|
48
49
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
50
|
+
// some components are not dispatching focusin but only focus
|
51
|
+
input?.addEventListener('focusin', onFocus);
|
52
|
+
input?.addEventListener('focus', onFocus);
|
53
|
+
});
|
54
|
+
}
|
54
55
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
56
|
+
// we want to block the input events from propagating in case the value of the root input wasn't change
|
57
|
+
// this can happen if we are sanitizing characters on the internal inputs and do not want it to affect the root input element value
|
58
|
+
// 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
|
59
|
+
handleInputEventDispatching() {
|
60
|
+
let previousRootComponentValue = this.value;
|
60
61
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
}
|
62
|
+
this.addEventListener('input', (e) => {
|
63
|
+
// we are comparing the previous value to the new one,
|
64
|
+
// and if they have the same value, we are blocking the input event
|
65
|
+
if (previousRootComponentValue === this.value) {
|
66
|
+
e.stopImmediatePropagation();
|
67
|
+
} else {
|
68
|
+
previousRootComponentValue = this.value;
|
69
|
+
}
|
70
|
+
});
|
71
|
+
}
|
72
|
+
};
|
@@ -1,154 +1,159 @@
|
|
1
|
-
const observedAttributes = [
|
2
|
-
'required',
|
3
|
-
'pattern',
|
4
|
-
]
|
1
|
+
const observedAttributes = ['required', 'pattern'];
|
5
2
|
|
6
3
|
const errorAttributes = {
|
7
4
|
valueMissing: 'data-errormessage-value-missing',
|
8
5
|
patternMismatch: 'data-errormessage-pattern-mismatch',
|
9
6
|
tooShort: 'data-errormessage-pattern-mismatch-too-short',
|
10
7
|
tooLong: 'data-errormessage-pattern-mismatch-too-long',
|
11
|
-
}
|
12
|
-
export const inputValidationMixin = (superclass) =>
|
13
|
-
|
14
|
-
|
15
|
-
...superclass.observedAttributes || [],
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
this
|
116
|
-
}
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
8
|
+
};
|
9
|
+
export const inputValidationMixin = (superclass) =>
|
10
|
+
class InputValidationMixinClass extends superclass {
|
11
|
+
static get observedAttributes() {
|
12
|
+
return [...(superclass.observedAttributes || []), ...observedAttributes];
|
13
|
+
}
|
14
|
+
|
15
|
+
static get formAssociated() {
|
16
|
+
return true;
|
17
|
+
}
|
18
|
+
|
19
|
+
#internals;
|
20
|
+
|
21
|
+
constructor() {
|
22
|
+
super();
|
23
|
+
|
24
|
+
this.#internals = this.attachInternals();
|
25
|
+
}
|
26
|
+
|
27
|
+
// eslint-disable-next-line class-methods-use-this
|
28
|
+
get defaultErrorMsgValueMissing() {
|
29
|
+
return 'Please fill out this field.';
|
30
|
+
}
|
31
|
+
|
32
|
+
// eslint-disable-next-line class-methods-use-this
|
33
|
+
get defaultErrorMsgPatternMismatch() {
|
34
|
+
return 'Please match the requested format.';
|
35
|
+
}
|
36
|
+
|
37
|
+
get defaultErrorMsgTooShort() {
|
38
|
+
return `Minimum length is ${this.getAttribute('minlength')}.`;
|
39
|
+
}
|
40
|
+
|
41
|
+
get defaultErrorMsgTooLong() {
|
42
|
+
return `Maximum length is ${this.getAttribute('maxlength')}. `;
|
43
|
+
}
|
44
|
+
|
45
|
+
getErrorMessage(flags) {
|
46
|
+
const {
|
47
|
+
valueMissing,
|
48
|
+
patternMismatch,
|
49
|
+
typeMismatch,
|
50
|
+
stepMismatch,
|
51
|
+
tooShort,
|
52
|
+
tooLong,
|
53
|
+
rangeOverflow,
|
54
|
+
rangeUnderflow,
|
55
|
+
badInput,
|
56
|
+
customError,
|
57
|
+
} = flags;
|
58
|
+
switch (true) {
|
59
|
+
case valueMissing:
|
60
|
+
return (
|
61
|
+
this.getAttribute(errorAttributes.valueMissing) || this.defaultErrorMsgValueMissing
|
62
|
+
);
|
63
|
+
case patternMismatch ||
|
64
|
+
typeMismatch ||
|
65
|
+
stepMismatch ||
|
66
|
+
rangeOverflow ||
|
67
|
+
rangeUnderflow ||
|
68
|
+
badInput:
|
69
|
+
return (
|
70
|
+
this.getAttribute(errorAttributes.patternMismatch) ||
|
71
|
+
this.defaultErrorMsgPatternMismatch
|
72
|
+
);
|
73
|
+
case tooShort:
|
74
|
+
return this.getAttribute(errorAttributes.tooShort) || this.defaultErrorMsgTooShort;
|
75
|
+
case tooLong:
|
76
|
+
return this.getAttribute(errorAttributes.tooLong) || this.defaultErrorMsgTooLong;
|
77
|
+
case customError:
|
78
|
+
return this.validationMessage;
|
79
|
+
default:
|
80
|
+
return '';
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
#setValidity() {
|
85
|
+
const validity = this.isReadOnly ? {} : this.getValidity();
|
86
|
+
this.#internals.setValidity(validity, this.getErrorMessage(validity), this.validationTarget);
|
87
|
+
}
|
88
|
+
|
89
|
+
get validationMessage() {
|
90
|
+
return this.#internals.validationMessage;
|
91
|
+
}
|
92
|
+
|
93
|
+
// eslint-disable-next-line class-methods-use-this
|
94
|
+
getValidity() {
|
95
|
+
// eslint-disable-next-line no-console
|
96
|
+
console.warn('getValidity', 'is not implemented');
|
97
|
+
}
|
98
|
+
|
99
|
+
checkValidity() {
|
100
|
+
return this.#internals.validity.valid;
|
101
|
+
}
|
102
|
+
|
103
|
+
reportValidity() {
|
104
|
+
return this.#internals.reportValidity();
|
105
|
+
}
|
106
|
+
|
107
|
+
get validity() {
|
108
|
+
return this.#internals.validity;
|
109
|
+
}
|
110
|
+
|
111
|
+
get validationTarget() {
|
112
|
+
return this.inputElement;
|
113
|
+
}
|
114
|
+
|
115
|
+
setCustomValidity(errorMessage) {
|
116
|
+
if (errorMessage) {
|
117
|
+
this.#internals.setValidity({ customError: true }, errorMessage, this.validationTarget);
|
118
|
+
} else {
|
119
|
+
this.#internals.setValidity({});
|
120
|
+
this.#setValidity();
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
get isRequired() {
|
125
|
+
return this.hasAttribute('required') && this.getAttribute('required') !== 'false';
|
126
|
+
}
|
127
|
+
|
128
|
+
get isReadOnly() {
|
129
|
+
return this.hasAttribute('readonly') && this.getAttribute('readonly') !== 'false';
|
130
|
+
}
|
131
|
+
|
132
|
+
get pattern() {
|
133
|
+
return this.getAttribute('pattern');
|
134
|
+
}
|
135
|
+
|
136
|
+
get form() {
|
137
|
+
return this.#internals.form;
|
138
|
+
}
|
139
|
+
|
140
|
+
attributeChangedCallback(attrName, oldValue, newValue) {
|
141
|
+
super.attributeChangedCallback?.(attrName, oldValue, newValue);
|
142
|
+
|
143
|
+
if (observedAttributes.includes(attrName)) {
|
144
|
+
this.#setValidity();
|
145
|
+
}
|
146
|
+
}
|
147
|
+
|
148
|
+
init() {
|
149
|
+
super.init?.();
|
150
|
+
this.addEventListener('change', this.#setValidity);
|
151
|
+
this.addEventListener('invalid', (e) => e.stopPropagation());
|
152
|
+
this.addEventListener('input', this.#setValidity);
|
153
|
+
|
154
|
+
// The attribute sync takes time, so getValidity returns valid,
|
155
|
+
// even when it shouldn't. This way allows all attributes to sync
|
156
|
+
// after render, before checking the validity.
|
157
|
+
setTimeout(() => this.#setValidity());
|
158
|
+
}
|
159
|
+
};
|
@@ -1,21 +1,23 @@
|
|
1
|
-
import { createDispatchEvent } from
|
1
|
+
import { createDispatchEvent } from '../helpers/mixinsHelpers';
|
2
2
|
|
3
|
-
export const lifecycleEventsMixin = (superclass) =>
|
4
|
-
|
5
|
-
|
3
|
+
export const lifecycleEventsMixin = (superclass) =>
|
4
|
+
class LifecycleEventsMixinClass extends superclass {
|
5
|
+
#dispatchConnected = createDispatchEvent.bind(this, 'connected');
|
6
6
|
|
7
|
-
|
8
|
-
if (this.rootElement.isConnected) {
|
9
|
-
super.connectedCallback?.();
|
7
|
+
#dispatchDisconnected = createDispatchEvent.bind(this, 'disconnected');
|
10
8
|
|
11
|
-
|
12
|
-
|
9
|
+
connectedCallback() {
|
10
|
+
if (this.rootElement.isConnected) {
|
11
|
+
super.connectedCallback?.();
|
12
|
+
|
13
|
+
// we are waiting for all components to listen before dispatching
|
14
|
+
setTimeout(this.#dispatchConnected);
|
15
|
+
}
|
13
16
|
}
|
14
|
-
}
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
+
disconnectedCallback() {
|
19
|
+
super.disconnectedCallback?.();
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
}
|
21
|
+
this.#dispatchDisconnected();
|
22
|
+
}
|
23
|
+
};
|