@descope/web-components-ui 1.0.66 → 1.0.68
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 +481 -377
- package/dist/index.esm.js.map +1 -1
- package/dist/umd/135.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-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 -2
- package/src/baseClasses/createBaseClass.js +29 -0
- package/src/components/descope-container/Container.js +17 -25
- package/src/components/descope-divider/Divider.js +32 -40
- package/src/components/descope-link/Link.js +8 -17
- package/src/components/descope-loader-linear/LoaderLinear.js +24 -29
- package/src/components/descope-loader-radial/LoaderRadial.js +18 -26
- package/src/components/descope-logo/Logo.js +4 -12
- package/src/components/descope-passcode/Passcode.js +4 -11
- package/src/components/descope-passcode/descope-passcode-internal/PasscodeInternal.js +41 -53
- package/src/components/descope-text/Text.js +4 -12
- package/src/helpers/index.js +2 -0
- package/src/helpers/mixinsHelpers.js +18 -0
- package/src/mixins/changeMixin.js +47 -0
- package/src/mixins/componentNameValidationMixin.js +1 -1
- package/src/mixins/createProxy.js +26 -28
- package/src/mixins/createStyleMixin/helpers.js +3 -3
- package/src/mixins/createStyleMixin/index.js +10 -9
- package/src/mixins/draggableMixin.js +1 -1
- package/src/mixins/focusMixin.js +130 -0
- package/src/mixins/hoverableMixin.js +14 -13
- package/src/mixins/index.js +3 -1
- package/src/mixins/{inputMixin.js → inputValidationMixin.js} +17 -58
- package/src/mixins/proxyInputMixin.js +50 -45
- package/dist/umd/860.js +0 -1
- package/src/baseClasses/DescopeBaseClass.js +0 -1
| @@ -3,47 +3,42 @@ import { | |
| 3 3 | 
             
            	draggableMixin,
         | 
| 4 4 | 
             
            	componentNameValidationMixin
         | 
| 5 5 | 
             
            } from '../../mixins';
         | 
| 6 | 
            -
            import {  | 
| 6 | 
            +
            import { createBaseClass } from '../../baseClasses/createBaseClass';
         | 
| 7 7 | 
             
            import { compose } from '../../helpers';
         | 
| 8 8 | 
             
            import { getComponentName } from '../../helpers/componentHelpers';
         | 
| 9 9 |  | 
| 10 10 | 
             
            export const componentName = getComponentName('loader-linear');
         | 
| 11 11 |  | 
| 12 | 
            -
            class RawLoaderLinear extends  | 
| 12 | 
            +
            class RawLoaderLinear extends createBaseClass({ componentName, baseSelector: ':host > div' }) {
         | 
| 13 13 | 
             
            	static get componentName() {
         | 
| 14 14 | 
             
            		return componentName;
         | 
| 15 15 | 
             
            	}
         | 
| 16 16 | 
             
            	constructor() {
         | 
| 17 17 | 
             
            		super();
         | 
| 18 | 
            -
            		const template = document.createElement('template');
         | 
| 19 | 
            -
            		template.innerHTML = `
         | 
| 20 | 
            -
            			<style>
         | 
| 21 | 
            -
            				@keyframes tilt {
         | 
| 22 | 
            -
            					0% { transform: translateX(0); }
         | 
| 23 | 
            -
            					50% { transform: translateX(400%); }
         | 
| 24 | 
            -
            				}
         | 
| 25 | 
            -
            				:host {
         | 
| 26 | 
            -
            					position: relative;
         | 
| 27 | 
            -
            					display: inline-block
         | 
| 28 | 
            -
            				}
         | 
| 29 | 
            -
            				div::after {
         | 
| 30 | 
            -
            					content: '';
         | 
| 31 | 
            -
            					animation-name: tilt;
         | 
| 32 | 
            -
            					position: absolute;
         | 
| 33 | 
            -
            					left: 0;
         | 
| 34 | 
            -
            				}
         | 
| 35 18 |  | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 19 | 
            +
            		this.attachShadow({ mode: 'open' }).innerHTML = `
         | 
| 20 | 
            +
            		<style>
         | 
| 21 | 
            +
            			@keyframes tilt {
         | 
| 22 | 
            +
            				0% { transform: translateX(0); }
         | 
| 23 | 
            +
            				50% { transform: translateX(400%); }
         | 
| 24 | 
            +
            			}
         | 
| 25 | 
            +
            			:host {
         | 
| 26 | 
            +
            				position: relative;
         | 
| 27 | 
            +
            				display: inline-block
         | 
| 28 | 
            +
            			}
         | 
| 29 | 
            +
            			div::after {
         | 
| 30 | 
            +
            				content: '';
         | 
| 31 | 
            +
            				animation-name: tilt;
         | 
| 32 | 
            +
            				position: absolute;
         | 
| 33 | 
            +
            				left: 0;
         | 
| 34 | 
            +
            			}
         | 
| 42 35 |  | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
            		 | 
| 36 | 
            +
            			:host > div {
         | 
| 37 | 
            +
            				width: 100%;
         | 
| 38 | 
            +
            			}
         | 
| 39 | 
            +
            		</style>
         | 
| 40 | 
            +
            		<div></div>
         | 
| 41 | 
            +
            	`;
         | 
| 47 42 | 
             
            	}
         | 
| 48 43 | 
             
            }
         | 
| 49 44 |  | 
| @@ -3,40 +3,32 @@ import { | |
| 3 3 | 
             
            	draggableMixin,
         | 
| 4 4 | 
             
            	componentNameValidationMixin
         | 
| 5 5 | 
             
            } from '../../mixins';
         | 
| 6 | 
            -
            import {  | 
| 6 | 
            +
            import { createBaseClass } from '../../baseClasses/createBaseClass';
         | 
| 7 7 | 
             
            import { compose } from '../../helpers';
         | 
| 8 8 | 
             
            import { getComponentName } from '../../helpers/componentHelpers';
         | 
| 9 9 |  | 
| 10 10 | 
             
            export const componentName = getComponentName('loader-radial');
         | 
| 11 11 |  | 
| 12 | 
            -
            class RawLoaderRadial extends  | 
| 13 | 
            -
            	static get componentName() {
         | 
| 14 | 
            -
            		return componentName;
         | 
| 15 | 
            -
            	}
         | 
| 12 | 
            +
            class RawLoaderRadial extends createBaseClass({ componentName, baseSelector: ':host > div' }) {
         | 
| 16 13 | 
             
            	constructor() {
         | 
| 17 14 | 
             
            		super();
         | 
| 18 | 
            -
            		const template = document.createElement('template');
         | 
| 19 | 
            -
            		template.innerHTML = `
         | 
| 20 | 
            -
            			<style>
         | 
| 21 | 
            -
            				@keyframes spin {
         | 
| 22 | 
            -
            					0% { transform: rotate(0deg); }
         | 
| 23 | 
            -
            					100% { transform: rotate(360deg); }
         | 
| 24 | 
            -
            				}
         | 
| 25 | 
            -
            				:host {
         | 
| 26 | 
            -
            					position: relative;
         | 
| 27 | 
            -
            					display: inline-flex;
         | 
| 28 | 
            -
            				}
         | 
| 29 | 
            -
            				:host > div {
         | 
| 30 | 
            -
            					animation-name: spin;
         | 
| 31 | 
            -
            				}
         | 
| 32 | 
            -
            			</style>
         | 
| 33 | 
            -
            			<div></div>
         | 
| 34 | 
            -
            		`;
         | 
| 35 | 
            -
             | 
| 36 | 
            -
            		this.attachShadow({ mode: 'open' });
         | 
| 37 | 
            -
            		this.shadowRoot.appendChild(template.content.cloneNode(true));
         | 
| 38 15 |  | 
| 39 | 
            -
            		this. | 
| 16 | 
            +
            		this.attachShadow({ mode: 'open' }).innerHTML = `
         | 
| 17 | 
            +
            		<style>
         | 
| 18 | 
            +
            			@keyframes spin {
         | 
| 19 | 
            +
            				0% { transform: rotate(0deg); }
         | 
| 20 | 
            +
            				100% { transform: rotate(360deg); }
         | 
| 21 | 
            +
            			}
         | 
| 22 | 
            +
            			:host {
         | 
| 23 | 
            +
            				position: relative;
         | 
| 24 | 
            +
            				display: inline-flex;
         | 
| 25 | 
            +
            			}
         | 
| 26 | 
            +
            			:host > div {
         | 
| 27 | 
            +
            				animation-name: spin;
         | 
| 28 | 
            +
            			}
         | 
| 29 | 
            +
            		</style>
         | 
| 30 | 
            +
            		<div></div>
         | 
| 31 | 
            +
            	`;
         | 
| 40 32 | 
             
            	}
         | 
| 41 33 | 
             
            }
         | 
| 42 34 |  | 
| @@ -3,7 +3,7 @@ import { | |
| 3 3 | 
             
            	draggableMixin,
         | 
| 4 4 | 
             
            	componentNameValidationMixin
         | 
| 5 5 | 
             
            } from '../../mixins';
         | 
| 6 | 
            -
            import {  | 
| 6 | 
            +
            import { createBaseClass } from '../../baseClasses/createBaseClass';
         | 
| 7 7 | 
             
            import { compose } from '../../helpers';
         | 
| 8 8 | 
             
            import { getComponentName } from '../../helpers/componentHelpers';
         | 
| 9 9 |  | 
| @@ -12,23 +12,15 @@ export const componentName = getComponentName('logo'); | |
| 12 12 | 
             
            let style;
         | 
| 13 13 | 
             
            const getStyle = () => style;
         | 
| 14 14 |  | 
| 15 | 
            -
            class RawLogo extends  | 
| 16 | 
            -
            	static get componentName() {
         | 
| 17 | 
            -
            		return componentName;
         | 
| 18 | 
            -
            	}
         | 
| 15 | 
            +
            class RawLogo extends createBaseClass({ componentName, baseSelector: ':host > div' }) {
         | 
| 19 16 | 
             
            	constructor() {
         | 
| 20 17 | 
             
            		super();
         | 
| 21 | 
            -
             | 
| 22 | 
            -
            		 | 
| 18 | 
            +
             | 
| 19 | 
            +
            		this.attachShadow({ mode: 'open' }).innerHTML = `
         | 
| 23 20 | 
             
            		<style>
         | 
| 24 21 | 
             
            			${getStyle()}
         | 
| 25 22 | 
             
            		</style>
         | 
| 26 23 | 
             
            		<div></div>`;
         | 
| 27 | 
            -
             | 
| 28 | 
            -
            		this.attachShadow({ mode: 'open' });
         | 
| 29 | 
            -
            		this.shadowRoot.appendChild(template.content.cloneNode(true));
         | 
| 30 | 
            -
             | 
| 31 | 
            -
            		this.baseSelector = ':host > div';
         | 
| 32 24 | 
             
            	}
         | 
| 33 25 | 
             
            }
         | 
| 34 26 |  | 
| @@ -38,21 +38,10 @@ const customMixin = (superclass) => | |
| 38 38 |  | 
| 39 39 | 
             
            			this.proxyElement.appendChild(template.content.cloneNode(true));
         | 
| 40 40 |  | 
| 41 | 
            -
            			// we want to control when the element is out of focus
         | 
| 42 | 
            -
            			// so the validations will be triggered blur event is dispatched from descope-passcode internal (and not every time focusing a digit)
         | 
| 43 | 
            -
            			this.proxyElement._setFocused = () => { };
         | 
| 44 | 
            -
             | 
| 45 41 | 
             
            			this.inputElement = this.shadowRoot.querySelector(descopeInternalComponentName);
         | 
| 46 42 |  | 
| 47 43 | 
             
            			forwardAttrs(this.shadowRoot.host, this.inputElement, { includeAttrs: ['required', 'pattern'] })
         | 
| 48 44 |  | 
| 49 | 
            -
            			// we want to trigger validation only when dispatching a blur event from the descope-passcode-internal
         | 
| 50 | 
            -
            			this.inputElement.addEventListener('blur', (e) => {
         | 
| 51 | 
            -
            				// we do not want native blur events, only the ones that we are sending
         | 
| 52 | 
            -
            				if (!e.isTrusted){
         | 
| 53 | 
            -
            					this.proxyElement.validate();
         | 
| 54 | 
            -
            				}
         | 
| 55 | 
            -
            			});
         | 
| 56 45 | 
             
            		}
         | 
| 57 46 | 
             
            	};
         | 
| 58 47 |  | 
| @@ -89,6 +78,10 @@ const Passcode = compose( | |
| 89 78 | 
             
            			display: inline-block;
         | 
| 90 79 | 
             
                }
         | 
| 91 80 |  | 
| 81 | 
            +
            		:host([readonly]) descope-passcode-internal > div {
         | 
| 82 | 
            +
            			pointer-events: none;
         | 
| 83 | 
            +
            		}
         | 
| 84 | 
            +
             | 
| 92 85 | 
             
                descope-passcode-internal {
         | 
| 93 86 | 
             
                  -webkit-mask-image: none;
         | 
| 94 87 | 
             
                  display: flex;
         | 
| @@ -7,11 +7,10 @@ export const componentName = getComponentName('passcode-internal'); | |
| 7 7 | 
             
            class PasscodeInternal extends BaseInputClass {
         | 
| 8 8 | 
             
            	static get observedAttributes() {
         | 
| 9 9 | 
             
            		return [
         | 
| 10 | 
            -
            			...BaseInputClass.observedAttributes,
         | 
| 10 | 
            +
            			...(BaseInputClass.observedAttributes || []),
         | 
| 11 11 | 
             
            			'disabled',
         | 
| 12 12 | 
             
            			'bordered',
         | 
| 13 13 | 
             
            			'size',
         | 
| 14 | 
            -
            			'readonly'
         | 
| 15 14 | 
             
            		];
         | 
| 16 15 | 
             
            	}
         | 
| 17 16 |  | 
| @@ -19,10 +18,12 @@ class PasscodeInternal extends BaseInputClass { | |
| 19 18 | 
             
            		return componentName;
         | 
| 20 19 | 
             
            	}
         | 
| 21 20 |  | 
| 21 | 
            +
            	#boundHandleInvalid = this.#handleInvalid.bind(this)
         | 
| 22 | 
            +
            	#boundHandleValid = this.#handleValid.bind(this)
         | 
| 23 | 
            +
            	#boundHandleBlur = this.#handleBlur.bind(this)
         | 
| 24 | 
            +
             | 
| 22 25 | 
             
            	constructor() {
         | 
| 23 26 | 
             
            		super();
         | 
| 24 | 
            -
            		const template = document.createElement('template');
         | 
| 25 | 
            -
             | 
| 26 27 | 
             
            		const inputs = [...Array(this.digits).keys()].map((idx) => `
         | 
| 27 28 | 
             
            		<descope-text-field
         | 
| 28 29 | 
             
            			st-width="35px"
         | 
| @@ -32,14 +33,12 @@ class PasscodeInternal extends BaseInputClass { | |
| 32 33 | 
             
            		></descope-text-field>
         | 
| 33 34 | 
             
            	`)
         | 
| 34 35 |  | 
| 35 | 
            -
            		 | 
| 36 | 
            +
            		this.innerHTML = `
         | 
| 36 37 | 
             
            		<div>
         | 
| 37 38 | 
             
            			${inputs.join('')}
         | 
| 38 39 | 
             
            		</div>
         | 
| 39 40 | 
             
            		`;
         | 
| 40 41 |  | 
| 41 | 
            -
            		this.appendChild(template.content.cloneNode(true));
         | 
| 42 | 
            -
             | 
| 43 42 | 
             
            		this.baseSelector = ':host > div';
         | 
| 44 43 |  | 
| 45 44 | 
             
            		this.inputs = Array.from(this.querySelectorAll('descope-text-field'))
         | 
| @@ -67,15 +66,13 @@ class PasscodeInternal extends BaseInputClass { | |
| 67 66 | 
             
            		return `^$|^\\d{${this.digits},}$`
         | 
| 68 67 | 
             
            	}
         | 
| 69 68 |  | 
| 70 | 
            -
            	 | 
| 71 | 
            -
            		 | 
| 72 | 
            -
            			 | 
| 73 | 
            -
             | 
| 74 | 
            -
            			}
         | 
| 75 | 
            -
            		})
         | 
| 69 | 
            +
            	#handleInvalid() {
         | 
| 70 | 
            +
            		if (this.hasAttribute('invalid')) {
         | 
| 71 | 
            +
            			this.inputs.forEach(input => input.setAttribute('invalid', 'true'))
         | 
| 72 | 
            +
            		}
         | 
| 76 73 | 
             
            	}
         | 
| 77 74 |  | 
| 78 | 
            -
            	 | 
| 75 | 
            +
            	#handleValid() {
         | 
| 79 76 | 
             
            		this.inputs.forEach(input => input.removeAttribute('invalid'))
         | 
| 80 77 | 
             
            	}
         | 
| 81 78 |  | 
| @@ -91,17 +88,25 @@ class PasscodeInternal extends BaseInputClass { | |
| 91 88 | 
             
            		}
         | 
| 92 89 | 
             
            	};
         | 
| 93 90 |  | 
| 94 | 
            -
            	 | 
| 95 | 
            -
            		this.inputs[0].focus() | 
| 91 | 
            +
            	onFocus(){
         | 
| 92 | 
            +
            		this.inputs[0].focus()
         | 
| 96 93 | 
             
            	}
         | 
| 97 94 |  | 
| 98 | 
            -
            	 | 
| 99 | 
            -
            		super.connectedCallback();
         | 
| 95 | 
            +
            	connectedCallback() {
         | 
| 96 | 
            +
            		super.connectedCallback?.();
         | 
| 100 97 |  | 
| 101 98 | 
             
            		this.initInputs()
         | 
| 102 99 |  | 
| 103 | 
            -
            		this.addEventListener('invalid', this | 
| 104 | 
            -
            		this.addEventListener('valid', this | 
| 100 | 
            +
            		this.addEventListener('invalid', this.#boundHandleInvalid)
         | 
| 101 | 
            +
            		this.addEventListener('valid', this.#boundHandleValid)
         | 
| 102 | 
            +
            		this.addEventListener('blur', this.#boundHandleBlur)
         | 
| 103 | 
            +
            	}
         | 
| 104 | 
            +
             | 
| 105 | 
            +
            	disconnectedCallback() {
         | 
| 106 | 
            +
            		super.connectedCallback?.();
         | 
| 107 | 
            +
            		this.removeEventListener('invalid', this.#boundHandleInvalid)
         | 
| 108 | 
            +
            		this.removeEventListener('valid', this.#boundHandleValid)
         | 
| 109 | 
            +
            		this.removeEventListener('blur', this.#boundHandleBlur)
         | 
| 105 110 | 
             
            	}
         | 
| 106 111 |  | 
| 107 112 | 
             
            	getInputIdx(inputEle) {
         | 
| @@ -125,66 +130,49 @@ class PasscodeInternal extends BaseInputClass { | |
| 125 130 | 
             
            			currentInput.value = charArr[i] ?? '';
         | 
| 126 131 |  | 
| 127 132 | 
             
            			const nextInput = this.getNextInput(currentInput);
         | 
| 133 | 
            +
             | 
| 128 134 | 
             
            			if (nextInput === currentInput) break;
         | 
| 129 135 | 
             
            			currentInput = nextInput;
         | 
| 130 136 | 
             
            		}
         | 
| 131 137 |  | 
| 132 | 
            -
            		 | 
| 138 | 
            +
            		focusElement(currentInput);
         | 
| 133 139 | 
             
            	};
         | 
| 134 140 |  | 
| 135 | 
            -
            	handleBlur() {
         | 
| 136 | 
            -
            		this | 
| 141 | 
            +
            	#handleBlur() {
         | 
| 142 | 
            +
            		this.#handleInvalid()
         | 
| 137 143 | 
             
            	}
         | 
| 138 144 |  | 
| 139 145 | 
             
            	initInputs() {
         | 
| 140 146 | 
             
            		this.inputs.forEach((input) => {
         | 
| 141 | 
            -
             | 
| 142 | 
            -
            			// in order to simulate blur on the input
         | 
| 143 | 
            -
            			// we are checking if focus on one of the digits happened immediately after blur on another digit
         | 
| 144 | 
            -
            			// if not, the component is no longer focused and we should simulate blur
         | 
| 145 | 
            -
            			input.addEventListener('blur', (e) => {
         | 
| 146 | 
            -
            				e.stopPropagation()
         | 
| 147 | 
            -
            				const timerId = setTimeout(() => {
         | 
| 148 | 
            -
            					this.dispatchBlur()
         | 
| 149 | 
            -
            				});
         | 
| 150 | 
            -
             | 
| 151 | 
            -
            				this.inputs.forEach((ele) =>
         | 
| 152 | 
            -
            					ele.addEventListener('focus', () => clearTimeout(timerId), { once: true })
         | 
| 153 | 
            -
            				);
         | 
| 154 | 
            -
            			})
         | 
| 155 | 
            -
             | 
| 156 147 | 
             
            			input.oninput = (e) => {
         | 
| 157 | 
            -
            				e.stopPropagation()
         | 
| 158 148 | 
             
            				const charArr = getSanitizedCharacters(input.value);
         | 
| 159 149 |  | 
| 160 | 
            -
            				if (!charArr.length)  | 
| 150 | 
            +
            				if (!charArr.length) {
         | 
| 151 | 
            +
            					// if we got an invalid value we want to clear the input
         | 
| 152 | 
            +
            					input.value = '';
         | 
| 153 | 
            +
            					if (e.data === null) {
         | 
| 154 | 
            +
            						// if the user deleted the char, we want to focus the prev digit
         | 
| 155 | 
            +
            						focusElement(this.getPrevInput(input));
         | 
| 156 | 
            +
            					}
         | 
| 157 | 
            +
            				}
         | 
| 161 158 | 
             
            				else this.fillDigits(charArr, input);
         | 
| 162 | 
            -
             | 
| 163 | 
            -
            				this.dispatchInput()
         | 
| 164 159 | 
             
            			};
         | 
| 165 160 |  | 
| 166 161 | 
             
            			input.onkeydown = ({ key }) => {
         | 
| 162 | 
            +
            				// when user deletes a digit, we want to focus the previous digit
         | 
| 167 163 | 
             
            				if (key === 'Backspace') {
         | 
| 168 | 
            -
            					 | 
| 169 | 
            -
             | 
| 170 | 
            -
            					// if the user deleted the digit we want to focus the previous digit
         | 
| 171 | 
            -
            					const prevInput = this.getPrevInput(input)
         | 
| 172 | 
            -
             | 
| 173 | 
            -
            					!prevInput.hasAttribute('focused') && setTimeout(() => {
         | 
| 174 | 
            -
            						focusElement(prevInput);
         | 
| 164 | 
            +
            					setTimeout(() => {
         | 
| 165 | 
            +
            						focusElement(this.getPrevInput(input));
         | 
| 175 166 | 
             
            					});
         | 
| 176 | 
            -
             | 
| 177 | 
            -
            					this.dispatchInput()
         | 
| 178 167 | 
             
            				} else if (key.match(/^(\d)$/g)) { // if input is a digit
         | 
| 179 168 | 
             
            					input.value = ''; // we are clearing the previous value so we can override it with the new value
         | 
| 180 169 | 
             
            				}
         | 
| 181 | 
            -
             | 
| 182 170 | 
             
            			};
         | 
| 183 171 | 
             
            		})
         | 
| 184 172 | 
             
            	}
         | 
| 185 173 |  | 
| 186 174 | 
             
            	attributeChangedCallback(attrName, oldValue, newValue) {
         | 
| 187 | 
            -
            		super.attributeChangedCallback(attrName, oldValue, newValue)
         | 
| 175 | 
            +
            		super.attributeChangedCallback?.(attrName, oldValue, newValue)
         | 
| 188 176 |  | 
| 189 177 | 
             
            		if (oldValue !== newValue) {
         | 
| 190 178 | 
             
            			if (PasscodeInternal.observedAttributes.includes(attrName) && !BaseInputClass.observedAttributes.includes(attrName)) {
         | 
| @@ -3,20 +3,17 @@ import { | |
| 3 3 | 
             
            	draggableMixin,
         | 
| 4 4 | 
             
            	componentNameValidationMixin
         | 
| 5 5 | 
             
            } from '../../mixins';
         | 
| 6 | 
            -
            import {  | 
| 6 | 
            +
            import { createBaseClass } from '../../baseClasses/createBaseClass';
         | 
| 7 7 | 
             
            import { compose } from '../../helpers';
         | 
| 8 8 | 
             
            import { getComponentName } from '../../helpers/componentHelpers';
         | 
| 9 9 |  | 
| 10 10 | 
             
            export const componentName = getComponentName('text');
         | 
| 11 11 |  | 
| 12 | 
            -
            class RawText extends  | 
| 13 | 
            -
            	static get componentName() {
         | 
| 14 | 
            -
            		return componentName;
         | 
| 15 | 
            -
            	}
         | 
| 12 | 
            +
            class RawText extends createBaseClass({ componentName, baseSelector: ':host > slot' }) {
         | 
| 16 13 | 
             
            	constructor() {
         | 
| 17 14 | 
             
            		super();
         | 
| 18 | 
            -
             | 
| 19 | 
            -
            		 | 
| 15 | 
            +
             | 
| 16 | 
            +
            		this.attachShadow({ mode: 'open' }).innerHTML = `
         | 
| 20 17 | 
             
            		<style>
         | 
| 21 18 | 
             
            			:host {
         | 
| 22 19 | 
             
            				display: inline-block;
         | 
| @@ -28,11 +25,6 @@ class RawText extends DescopeBaseClass { | |
| 28 25 | 
             
            		</style>
         | 
| 29 26 | 
             
            		<slot></slot>
         | 
| 30 27 | 
             
            		`;
         | 
| 31 | 
            -
             | 
| 32 | 
            -
            		this.attachShadow({ mode: 'open' });
         | 
| 33 | 
            -
            		this.shadowRoot.appendChild(template.content.cloneNode(true));
         | 
| 34 | 
            -
             | 
| 35 | 
            -
            		this.baseSelector = ':host > slot';
         | 
| 36 28 | 
             
            	}
         | 
| 37 29 | 
             
            }
         | 
| 38 30 |  | 
    
        package/src/helpers/index.js
    CHANGED
    
    
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            // move create event to here
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            // usage example:
         | 
| 4 | 
            +
            // #dispatchSomething = createDispatchEvent.bind(this, 'something')
         | 
| 5 | 
            +
            export function createDispatchEvent(eventName) {
         | 
| 6 | 
            +
              this[`on${eventName}`]?.(); // in case we got an event callback as property
         | 
| 7 | 
            +
              this.dispatchEvent(new Event(eventName));
         | 
| 8 | 
            +
            }
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            // usage example:
         | 
| 11 | 
            +
            // #removeChangeListener = createEventListener.call(this,'change', this.onChange)
         | 
| 12 | 
            +
            export function createEventListener(event, callback) {
         | 
| 13 | 
            +
              const boundCallback = callback.bind(this);
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              this.addEventListener(event, boundCallback);
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              return () => this.removeEventListener(event, boundCallback)
         | 
| 18 | 
            +
            }
         | 
| @@ -0,0 +1,47 @@ | |
| 1 | 
            +
            import { createDispatchEvent } from "../helpers/mixinsHelpers";
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            export const changeMixin = (superclass) => class ChangeMixinClass extends superclass {
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              #boundedHandleChange
         | 
| 6 | 
            +
              #boundedHandleBlur  
         | 
| 7 | 
            +
              
         | 
| 8 | 
            +
              #removeChangeListener
         | 
| 9 | 
            +
              #removeBlurListener
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              #dispatchChange = createDispatchEvent.bind(this, 'change')
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              constructor() {
         | 
| 14 | 
            +
                super();
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                this.#boundedHandleChange = this.#handleChange.bind(this);
         | 
| 17 | 
            +
                this.#boundedHandleBlur = this.#handleBlur.bind(this);
         | 
| 18 | 
            +
              }
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              #handleChange(e) {
         | 
| 21 | 
            +
                // we want to listen only to browser events 
         | 
| 22 | 
            +
                // and not to events we are dispatching
         | 
| 23 | 
            +
                if (e.isTrusted) {
         | 
| 24 | 
            +
                  // we want to control the change events that dispatched by the component
         | 
| 25 | 
            +
                  // so we are stopping propagation and handling it in handleBlur
         | 
| 26 | 
            +
                  e.stopPropagation()
         | 
| 27 | 
            +
                }
         | 
| 28 | 
            +
              }
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              #handleBlur() {
         | 
| 31 | 
            +
                // on blur, we want to dispatch a change event
         | 
| 32 | 
            +
                this.#dispatchChange()
         | 
| 33 | 
            +
              }
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              connectedCallback() {
         | 
| 36 | 
            +
                super.connectedCallback?.();
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                this.#removeChangeListener = addEventListener.bind()
         | 
| 39 | 
            +
                this.addEventListener('change', this.#boundedHandleChange, true)
         | 
| 40 | 
            +
                this.addEventListener('blur', this.#boundedHandleBlur)
         | 
| 41 | 
            +
              }
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              disconnectedCallback() {
         | 
| 44 | 
            +
                this.removeEventListener('change', this.#boundedHandleChange)
         | 
| 45 | 
            +
                this.removeEventListener('blur', this.#boundedHandleBlur)
         | 
| 46 | 
            +
              }
         | 
| 47 | 
            +
            }
         | 
| @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            export const componentNameValidationMixin = (superclass) =>
         | 
| 2 | 
            -
            	class  | 
| 2 | 
            +
            	class ComponentNameValidationMixinClass extends superclass {
         | 
| 3 3 | 
             
            		#checkComponentName() {
         | 
| 4 4 | 
             
            			const currentComponentName = this.shadowRoot.host.tagName.toLowerCase();
         | 
| 5 5 |  | 
| @@ -1,7 +1,6 @@ | |
| 1 | 
            -
            import {  | 
| 2 | 
            -
            import {  | 
| 1 | 
            +
            import { createBaseClass } from '../baseClasses/createBaseClass';
         | 
| 2 | 
            +
            import { isFunction } from '../helpers';
         | 
| 3 3 | 
             
            import { forwardProps, syncAttrs } from '../helpers/componentHelpers';
         | 
| 4 | 
            -
            import { hoverableMixin } from './hoverableMixin';
         | 
| 5 4 |  | 
| 6 5 | 
             
            export const createProxy = ({
         | 
| 7 6 | 
             
            	componentName,
         | 
| @@ -20,38 +19,39 @@ export const createProxy = ({ | |
| 20 19 | 
             
            		</${wrappedEleName}>
         | 
| 21 20 | 
             
            	`;
         | 
| 22 21 |  | 
| 23 | 
            -
            	class  | 
| 24 | 
            -
            		static get componentName() {
         | 
| 25 | 
            -
            			return componentName;
         | 
| 26 | 
            -
            		}
         | 
| 27 | 
            -
             | 
| 22 | 
            +
            	class ProxyClass extends createBaseClass({ componentName, baseSelector: wrappedEleName }) {
         | 
| 28 23 | 
             
            		constructor() {
         | 
| 29 24 | 
             
            			super().attachShadow({ mode: 'open' }).innerHTML = template;
         | 
| 30 25 | 
             
            			this.hostElement = this.shadowRoot.host;
         | 
| 31 | 
            -
            			this.baseSelector = wrappedEleName;
         | 
| 32 26 | 
             
            			this.shadowRoot.getElementById('create-proxy').innerHTML =
         | 
| 33 | 
            -
            				 | 
| 27 | 
            +
            				isFunction(style) ? style() : style;
         | 
| 28 | 
            +
            		}
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            		#boundOnFocus = this.#onFocus.bind(this);
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            		// we want to focus on the proxy element when focusing our WCP
         | 
| 33 | 
            +
            		#onFocus() {
         | 
| 34 | 
            +
            			this.proxyElement.focus();
         | 
| 34 35 | 
             
            		}
         | 
| 35 36 |  | 
| 37 | 
            +
            		focus = this.#onFocus
         | 
| 38 | 
            +
             | 
| 36 39 | 
             
            		connectedCallback() {
         | 
| 37 40 | 
             
            			if (this.shadowRoot.isConnected) {
         | 
| 38 41 | 
             
            				this.proxyElement = this.shadowRoot.querySelector(wrappedEleName);
         | 
| 39 42 |  | 
| 43 | 
            +
            				this.addEventListener('focus', this.#boundOnFocus);
         | 
| 44 | 
            +
             | 
| 40 45 | 
             
            				// this is needed for components that uses props, such as combo box
         | 
| 41 46 | 
             
            				forwardProps(this.hostElement, this.proxyElement, includeForwardProps)
         | 
| 42 47 |  | 
| 43 | 
            -
            				this.setAttribute('tabindex', '0');
         | 
| 44 | 
            -
             | 
| 45 | 
            -
            				// we want to focus on the proxy element when focusing our WC
         | 
| 46 | 
            -
            				this.addEventListener('focus', () => {
         | 
| 47 | 
            -
            					this.proxyElement.focus();
         | 
| 48 | 
            -
            				});
         | 
| 49 | 
            -
             | 
| 50 48 | 
             
            				// `onkeydown` is set on `proxyElement` support proper tab-index navigation
         | 
| 51 49 | 
             
            				// this support is needed since both proxy host and element catch `focus`/`blur` event
         | 
| 52 | 
            -
            				// which causes faulty  | 
| 50 | 
            +
            				// which causes faulty behavior.
         | 
| 51 | 
            +
            				// we need this to happen only when the proxy component is in the light DOM, 
         | 
| 52 | 
            +
            				// otherwise it will focus the nested proxy element
         | 
| 53 53 | 
             
            				this.proxyElement.onkeydown = (e) => {
         | 
| 54 | 
            -
            					if (e.shiftKey && e.keyCode === 9) {
         | 
| 54 | 
            +
            					if (e.shiftKey && e.keyCode === 9 && this.getRootNode() === document) {
         | 
| 55 55 | 
             
            						this.removeAttribute('tabindex');
         | 
| 56 56 | 
             
            						// We want to defer the action of setting the tab index back
         | 
| 57 57 | 
             
            						// so it will happen after focusing the previous element
         | 
| @@ -59,10 +59,6 @@ export const createProxy = ({ | |
| 59 59 | 
             
            					}
         | 
| 60 60 | 
             
            				};
         | 
| 61 61 |  | 
| 62 | 
            -
            				// sync events
         | 
| 63 | 
            -
            				this.addEventListener = (...args) =>
         | 
| 64 | 
            -
            					this.proxyElement.addEventListener(...args);
         | 
| 65 | 
            -
             | 
| 66 62 | 
             
            				syncAttrs(this.proxyElement, this.hostElement, {
         | 
| 67 63 | 
             
            					excludeAttrs: excludeAttrsSync,
         | 
| 68 64 | 
             
            					includeAttrs: includeAttrsSync
         | 
| @@ -70,16 +66,18 @@ export const createProxy = ({ | |
| 70 66 | 
             
            			}
         | 
| 71 67 | 
             
            		}
         | 
| 72 68 |  | 
| 73 | 
            -
            		disconnectedCallback() {
         | 
| 74 | 
            -
            			this.proxyElement.removeEventListener('mouseover', this.mouseoverCbRef);
         | 
| 75 | 
            -
            		}
         | 
| 76 | 
            -
             | 
| 77 69 | 
             
            		attributeChangedCallback() {
         | 
| 78 70 | 
             
            			if (!this.proxyElement) {
         | 
| 79 71 | 
             
            				return;
         | 
| 80 72 | 
             
            			}
         | 
| 81 73 | 
             
            		}
         | 
| 74 | 
            +
             | 
| 75 | 
            +
            		disconnectedCallback() {
         | 
| 76 | 
            +
            			super.disconnectedCallback?.()
         | 
| 77 | 
            +
             | 
| 78 | 
            +
            			this.removeEventListener('focus', this.#boundOnFocus);
         | 
| 79 | 
            +
            		}
         | 
| 82 80 | 
             
            	}
         | 
| 83 81 |  | 
| 84 | 
            -
            	return  | 
| 82 | 
            +
            	return ProxyClass;
         | 
| 85 83 | 
             
            };
         | 
| @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            import { kebabCase } from '../../helpers';
         | 
| 1 | 
            +
            import { isFunction, kebabCase } from '../../helpers';
         | 
| 2 2 | 
             
            import { getCssVarName } from '../../helpers/componentHelpers';
         | 
| 3 3 |  | 
| 4 4 | 
             
            const createCssVarFallback = (first, ...rest) =>
         | 
| @@ -8,7 +8,7 @@ const createCssSelector = ( | |
| 8 8 | 
             
            	baseSelector = '',
         | 
| 9 9 | 
             
            	relativeSelectorOrSelectorFn = ''
         | 
| 10 10 | 
             
            ) =>
         | 
| 11 | 
            -
            	 | 
| 11 | 
            +
            	isFunction(relativeSelectorOrSelectorFn)
         | 
| 12 12 | 
             
            		? relativeSelectorOrSelectorFn(baseSelector)
         | 
| 13 13 | 
             
            		: `${baseSelector}${/^[A-Za-z]/.test(relativeSelectorOrSelectorFn)
         | 
| 14 14 | 
             
            			? ` ${relativeSelectorOrSelectorFn}`
         | 
| @@ -65,7 +65,7 @@ export const createStyle = (componentName, baseSelector, mappings) => { | |
| 65 65 | 
             
            			({ selector: relativeSelectorOrSelectorFn, property }) => {
         | 
| 66 66 | 
             
            				style.add(
         | 
| 67 67 | 
             
            					createCssSelector(baseSelector, relativeSelectorOrSelectorFn),
         | 
| 68 | 
            -
            					property,
         | 
| 68 | 
            +
            					isFunction(property) ? property() : property,
         | 
| 69 69 | 
             
            					createCssVarFallback(cssVarName)
         | 
| 70 70 | 
             
            				);
         | 
| 71 71 | 
             
            			}
         | 
| @@ -64,7 +64,7 @@ export const createStyleMixin = | |
| 64 64 | 
             
            				this.#onComponentThemeChange()
         | 
| 65 65 | 
             
            			}
         | 
| 66 66 |  | 
| 67 | 
            -
            			# | 
| 67 | 
            +
            			#createOverridesStyle() {
         | 
| 68 68 | 
             
            				this.#overrideStyleEle = document.createElement('style');
         | 
| 69 69 | 
             
            				this.#overrideStyleEle.id = 'style-mixin-overrides';
         | 
| 70 70 |  | 
| @@ -74,7 +74,7 @@ export const createStyleMixin = | |
| 74 74 | 
             
            				this.#rootElement.append(this.#overrideStyleEle);
         | 
| 75 75 | 
             
            			}
         | 
| 76 76 |  | 
| 77 | 
            -
            			# | 
| 77 | 
            +
            			#setAttrOverride(attrName, value) {
         | 
| 78 78 | 
             
            				const style = this.#overrideStyleEle?.sheet?.cssRules[0].style;
         | 
| 79 79 | 
             
            				if (!style) return;
         | 
| 80 80 |  | 
| @@ -87,10 +87,10 @@ export const createStyleMixin = | |
| 87 87 | 
             
            				else style?.removeProperty(varName);
         | 
| 88 88 | 
             
            			}
         | 
| 89 89 |  | 
| 90 | 
            -
            			# | 
| 90 | 
            +
            			#updateOverridesStyle(attrs = []) {
         | 
| 91 91 | 
             
            				for (const attr of attrs) {
         | 
| 92 92 | 
             
            					if (this.#styleAttributes.includes(attr)) {
         | 
| 93 | 
            -
            						this.# | 
| 93 | 
            +
            						this.#setAttrOverride(attr, this.getAttribute(attr));
         | 
| 94 94 | 
             
            					}
         | 
| 95 95 | 
             
            				}
         | 
| 96 96 |  | 
| @@ -98,7 +98,7 @@ export const createStyleMixin = | |
| 98 98 | 
             
            				this.#overrideStyleEle.innerHTML = this.#overrideStyleEle?.sheet?.cssRules[0].cssText
         | 
| 99 99 | 
             
            			}
         | 
| 100 100 |  | 
| 101 | 
            -
            			# | 
| 101 | 
            +
            			#createMappingStyle() {
         | 
| 102 102 | 
             
            				const themeStyle = document.createElement('style');
         | 
| 103 103 | 
             
            				themeStyle.id = 'style-mixin-mappings'
         | 
| 104 104 | 
             
            				themeStyle.innerHTML = createStyle(
         | 
| @@ -119,13 +119,14 @@ export const createStyleMixin = | |
| 119 119 |  | 
| 120 120 | 
             
            					this.#addClassName(superclass.componentName)
         | 
| 121 121 |  | 
| 122 | 
            -
            					 | 
| 122 | 
            +
            					// TODO: we should do everything we can on the constructor
         | 
| 123 | 
            +
            					// when dragging & dropping these styles are created over & over
         | 
| 124 | 
            +
            					this.#createMappingStyle();
         | 
| 123 125 | 
             
            					this.#createComponentTheme();
         | 
| 124 | 
            -
            					this.# | 
| 126 | 
            +
            					this.#createOverridesStyle();
         | 
| 125 127 |  | 
| 126 128 | 
             
            					// this is instead attributeChangedCallback because we cannot use static methods in this case
         | 
| 127 | 
            -
            					observeAttributes(this, this.# | 
| 128 | 
            -
             | 
| 129 | 
            +
            					observeAttributes(this, this.#updateOverridesStyle.bind(this), {})
         | 
| 129 130 | 
             
            				}
         | 
| 130 131 | 
             
            			}
         | 
| 131 132 |  |