@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
    
        package/dist/index.esm.js
    CHANGED
    
    | @@ -24,6 +24,8 @@ const compose = (...fns) => | |
| 24 24 |  | 
| 25 25 | 
             
            const upperFirst = (str) => str.charAt(0).toUpperCase() + str.slice(1);
         | 
| 26 26 |  | 
| 27 | 
            +
            const isFunction = (maybeFunc) => typeof maybeFunc === 'function';
         | 
| 28 | 
            +
             | 
| 27 29 | 
             
            const DESCOPE_PREFIX = 'descope';
         | 
| 28 30 | 
             
            const CSS_SELECTOR_SPECIFIER_MULTIPLY = 3;
         | 
| 29 31 | 
             
            const BASE_THEME_SECTION = 'host';
         | 
| @@ -175,7 +177,7 @@ const createCssSelector = ( | |
| 175 177 | 
             
            	baseSelector = '',
         | 
| 176 178 | 
             
            	relativeSelectorOrSelectorFn = ''
         | 
| 177 179 | 
             
            ) =>
         | 
| 178 | 
            -
            	 | 
| 180 | 
            +
            	isFunction(relativeSelectorOrSelectorFn)
         | 
| 179 181 | 
             
            		? relativeSelectorOrSelectorFn(baseSelector)
         | 
| 180 182 | 
             
            		: `${baseSelector}${/^[A-Za-z]/.test(relativeSelectorOrSelectorFn)
         | 
| 181 183 | 
             
            			? ` ${relativeSelectorOrSelectorFn}`
         | 
| @@ -232,7 +234,7 @@ const createStyle = (componentName, baseSelector, mappings) => { | |
| 232 234 | 
             
            			({ selector: relativeSelectorOrSelectorFn, property }) => {
         | 
| 233 235 | 
             
            				style.add(
         | 
| 234 236 | 
             
            					createCssSelector(baseSelector, relativeSelectorOrSelectorFn),
         | 
| 235 | 
            -
            					property,
         | 
| 237 | 
            +
            					isFunction(property) ? property() : property,
         | 
| 236 238 | 
             
            					createCssVarFallback(cssVarName)
         | 
| 237 239 | 
             
            				);
         | 
| 238 240 | 
             
            			}
         | 
| @@ -315,7 +317,7 @@ const createStyleMixin = | |
| 315 317 | 
             
            				this.#onComponentThemeChange();
         | 
| 316 318 | 
             
            			}
         | 
| 317 319 |  | 
| 318 | 
            -
            			# | 
| 320 | 
            +
            			#createOverridesStyle() {
         | 
| 319 321 | 
             
            				this.#overrideStyleEle = document.createElement('style');
         | 
| 320 322 | 
             
            				this.#overrideStyleEle.id = 'style-mixin-overrides';
         | 
| 321 323 |  | 
| @@ -325,7 +327,7 @@ const createStyleMixin = | |
| 325 327 | 
             
            				this.#rootElement.append(this.#overrideStyleEle);
         | 
| 326 328 | 
             
            			}
         | 
| 327 329 |  | 
| 328 | 
            -
            			# | 
| 330 | 
            +
            			#setAttrOverride(attrName, value) {
         | 
| 329 331 | 
             
            				const style = this.#overrideStyleEle?.sheet?.cssRules[0].style;
         | 
| 330 332 | 
             
            				if (!style) return;
         | 
| 331 333 |  | 
| @@ -338,10 +340,10 @@ const createStyleMixin = | |
| 338 340 | 
             
            				else style?.removeProperty(varName);
         | 
| 339 341 | 
             
            			}
         | 
| 340 342 |  | 
| 341 | 
            -
            			# | 
| 343 | 
            +
            			#updateOverridesStyle(attrs = []) {
         | 
| 342 344 | 
             
            				for (const attr of attrs) {
         | 
| 343 345 | 
             
            					if (this.#styleAttributes.includes(attr)) {
         | 
| 344 | 
            -
            						this.# | 
| 346 | 
            +
            						this.#setAttrOverride(attr, this.getAttribute(attr));
         | 
| 345 347 | 
             
            					}
         | 
| 346 348 | 
             
            				}
         | 
| 347 349 |  | 
| @@ -349,7 +351,7 @@ const createStyleMixin = | |
| 349 351 | 
             
            				this.#overrideStyleEle.innerHTML = this.#overrideStyleEle?.sheet?.cssRules[0].cssText;
         | 
| 350 352 | 
             
            			}
         | 
| 351 353 |  | 
| 352 | 
            -
            			# | 
| 354 | 
            +
            			#createMappingStyle() {
         | 
| 353 355 | 
             
            				const themeStyle = document.createElement('style');
         | 
| 354 356 | 
             
            				themeStyle.id = 'style-mixin-mappings';
         | 
| 355 357 | 
             
            				themeStyle.innerHTML = createStyle(
         | 
| @@ -370,13 +372,14 @@ const createStyleMixin = | |
| 370 372 |  | 
| 371 373 | 
             
            					this.#addClassName(superclass.componentName);
         | 
| 372 374 |  | 
| 373 | 
            -
            					 | 
| 375 | 
            +
            					// TODO: we should do everything we can on the constructor
         | 
| 376 | 
            +
            					// when dragging & dropping these styles are created over & over
         | 
| 377 | 
            +
            					this.#createMappingStyle();
         | 
| 374 378 | 
             
            					this.#createComponentTheme();
         | 
| 375 | 
            -
            					this.# | 
| 379 | 
            +
            					this.#createOverridesStyle();
         | 
| 376 380 |  | 
| 377 381 | 
             
            					// this is instead attributeChangedCallback because we cannot use static methods in this case
         | 
| 378 | 
            -
            					observeAttributes(this, this.# | 
| 379 | 
            -
             | 
| 382 | 
            +
            					observeAttributes(this, this.#updateOverridesStyle.bind(this), {});
         | 
| 380 383 | 
             
            				}
         | 
| 381 384 | 
             
            			}
         | 
| 382 385 |  | 
| @@ -398,7 +401,7 @@ const draggableMixin = (superclass) => | |
| 398 401 | 
             
            			super();
         | 
| 399 402 |  | 
| 400 403 | 
             
            			this.#styleEle = document.createElement('style');
         | 
| 401 | 
            -
            			this.#styleEle.innerText =  | 
| 404 | 
            +
            			this.#styleEle.innerText = `* { cursor: inherit!important }`;
         | 
| 402 405 | 
             
            		}
         | 
| 403 406 |  | 
| 404 407 | 
             
            		#handleDraggableStyle(isDraggable) {
         | 
| @@ -417,31 +420,32 @@ const draggableMixin = (superclass) => | |
| 417 420 | 
             
            		}
         | 
| 418 421 | 
             
            	};
         | 
| 419 422 |  | 
| 420 | 
            -
             | 
| 423 | 
            +
            const createBaseClass = ({ componentName, baseSelector = '' }) => {
         | 
| 424 | 
            +
              class DescopeBaseClass extends HTMLElement {
         | 
| 425 | 
            +
                static get componentName() {
         | 
| 426 | 
            +
                  return componentName;
         | 
| 427 | 
            +
                }
         | 
| 421 428 |  | 
| 422 | 
            -
             | 
| 423 | 
            -
             | 
| 424 | 
            -
             | 
| 425 | 
            -
             | 
| 426 | 
            -
            			connectedCallback() {
         | 
| 427 | 
            -
            				super.connectedCallback?.();
         | 
| 429 | 
            +
                #baseElement;
         | 
| 430 | 
            +
                get baseSelector() {
         | 
| 431 | 
            +
                  return baseSelector
         | 
| 432 | 
            +
                }
         | 
| 428 433 |  | 
| 429 | 
            -
             | 
| 430 | 
            -
             | 
| 431 | 
            -
             | 
| 432 | 
            -
             | 
| 433 | 
            -
            						() => this.shadowRoot.host.removeAttribute('hover'),
         | 
| 434 | 
            -
            						{ once: true }
         | 
| 435 | 
            -
            					);
         | 
| 436 | 
            -
            				};
         | 
| 434 | 
            +
                get baseElement() {
         | 
| 435 | 
            +
                  this.#baseElement ??= this.baseSelector ?
         | 
| 436 | 
            +
                    this.rootElement.querySelector(this.baseSelector) :
         | 
| 437 | 
            +
                    this;
         | 
| 437 438 |  | 
| 438 | 
            -
             | 
| 439 | 
            -
             | 
| 440 | 
            -
            				);
         | 
| 439 | 
            +
                  return this.#baseElement
         | 
| 440 | 
            +
                }
         | 
| 441 441 |  | 
| 442 | 
            -
             | 
| 443 | 
            -
             | 
| 444 | 
            -
             | 
| 442 | 
            +
                get rootElement() {
         | 
| 443 | 
            +
                  return this.shadowRoot || this
         | 
| 444 | 
            +
                }
         | 
| 445 | 
            +
              }
         | 
| 446 | 
            +
             | 
| 447 | 
            +
              return compose(componentNameValidationMixin, hoverableMixin)(DescopeBaseClass)
         | 
| 448 | 
            +
            };
         | 
| 445 449 |  | 
| 446 450 | 
             
            const createProxy = ({
         | 
| 447 451 | 
             
            	componentName,
         | 
| @@ -460,38 +464,39 @@ const createProxy = ({ | |
| 460 464 | 
             
            		</${wrappedEleName}>
         | 
| 461 465 | 
             
            	`;
         | 
| 462 466 |  | 
| 463 | 
            -
            	class  | 
| 464 | 
            -
            		static get componentName() {
         | 
| 465 | 
            -
            			return componentName;
         | 
| 466 | 
            -
            		}
         | 
| 467 | 
            -
             | 
| 467 | 
            +
            	class ProxyClass extends createBaseClass({ componentName, baseSelector: wrappedEleName }) {
         | 
| 468 468 | 
             
            		constructor() {
         | 
| 469 469 | 
             
            			super().attachShadow({ mode: 'open' }).innerHTML = template;
         | 
| 470 470 | 
             
            			this.hostElement = this.shadowRoot.host;
         | 
| 471 | 
            -
            			this.baseSelector = wrappedEleName;
         | 
| 472 471 | 
             
            			this.shadowRoot.getElementById('create-proxy').innerHTML =
         | 
| 473 | 
            -
            				 | 
| 472 | 
            +
            				isFunction(style) ? style() : style;
         | 
| 474 473 | 
             
            		}
         | 
| 475 474 |  | 
| 475 | 
            +
            		#boundOnFocus = this.#onFocus.bind(this);
         | 
| 476 | 
            +
             | 
| 477 | 
            +
            		// we want to focus on the proxy element when focusing our WCP
         | 
| 478 | 
            +
            		#onFocus() {
         | 
| 479 | 
            +
            			this.proxyElement.focus();
         | 
| 480 | 
            +
            		}
         | 
| 481 | 
            +
             | 
| 482 | 
            +
            		focus = this.#onFocus
         | 
| 483 | 
            +
             | 
| 476 484 | 
             
            		connectedCallback() {
         | 
| 477 485 | 
             
            			if (this.shadowRoot.isConnected) {
         | 
| 478 486 | 
             
            				this.proxyElement = this.shadowRoot.querySelector(wrappedEleName);
         | 
| 479 487 |  | 
| 488 | 
            +
            				this.addEventListener('focus', this.#boundOnFocus);
         | 
| 489 | 
            +
             | 
| 480 490 | 
             
            				// this is needed for components that uses props, such as combo box
         | 
| 481 491 | 
             
            				forwardProps(this.hostElement, this.proxyElement, includeForwardProps);
         | 
| 482 492 |  | 
| 483 | 
            -
            				this.setAttribute('tabindex', '0');
         | 
| 484 | 
            -
             | 
| 485 | 
            -
            				// we want to focus on the proxy element when focusing our WC
         | 
| 486 | 
            -
            				this.addEventListener('focus', () => {
         | 
| 487 | 
            -
            					this.proxyElement.focus();
         | 
| 488 | 
            -
            				});
         | 
| 489 | 
            -
             | 
| 490 493 | 
             
            				// `onkeydown` is set on `proxyElement` support proper tab-index navigation
         | 
| 491 494 | 
             
            				// this support is needed since both proxy host and element catch `focus`/`blur` event
         | 
| 492 | 
            -
            				// which causes faulty  | 
| 495 | 
            +
            				// which causes faulty behavior.
         | 
| 496 | 
            +
            				// we need this to happen only when the proxy component is in the light DOM, 
         | 
| 497 | 
            +
            				// otherwise it will focus the nested proxy element
         | 
| 493 498 | 
             
            				this.proxyElement.onkeydown = (e) => {
         | 
| 494 | 
            -
            					if (e.shiftKey && e.keyCode === 9) {
         | 
| 499 | 
            +
            					if (e.shiftKey && e.keyCode === 9 && this.getRootNode() === document) {
         | 
| 495 500 | 
             
            						this.removeAttribute('tabindex');
         | 
| 496 501 | 
             
            						// We want to defer the action of setting the tab index back
         | 
| 497 502 | 
             
            						// so it will happen after focusing the previous element
         | 
| @@ -499,10 +504,6 @@ const createProxy = ({ | |
| 499 504 | 
             
            					}
         | 
| 500 505 | 
             
            				};
         | 
| 501 506 |  | 
| 502 | 
            -
            				// sync events
         | 
| 503 | 
            -
            				this.addEventListener = (...args) =>
         | 
| 504 | 
            -
            					this.proxyElement.addEventListener(...args);
         | 
| 505 | 
            -
             | 
| 506 507 | 
             
            				syncAttrs(this.proxyElement, this.hostElement, {
         | 
| 507 508 | 
             
            					excludeAttrs: excludeAttrsSync,
         | 
| 508 509 | 
             
            					includeAttrs: includeAttrsSync
         | 
| @@ -510,28 +511,30 @@ const createProxy = ({ | |
| 510 511 | 
             
            			}
         | 
| 511 512 | 
             
            		}
         | 
| 512 513 |  | 
| 513 | 
            -
            		disconnectedCallback() {
         | 
| 514 | 
            -
            			this.proxyElement.removeEventListener('mouseover', this.mouseoverCbRef);
         | 
| 515 | 
            -
            		}
         | 
| 516 | 
            -
             | 
| 517 514 | 
             
            		attributeChangedCallback() {
         | 
| 518 515 | 
             
            			if (!this.proxyElement) {
         | 
| 519 516 | 
             
            				return;
         | 
| 520 517 | 
             
            			}
         | 
| 521 518 | 
             
            		}
         | 
| 519 | 
            +
             | 
| 520 | 
            +
            		disconnectedCallback() {
         | 
| 521 | 
            +
            			super.disconnectedCallback?.();
         | 
| 522 | 
            +
             | 
| 523 | 
            +
            			this.removeEventListener('focus', this.#boundOnFocus);
         | 
| 524 | 
            +
            		}
         | 
| 522 525 | 
             
            	}
         | 
| 523 526 |  | 
| 524 | 
            -
            	return  | 
| 527 | 
            +
            	return ProxyClass;
         | 
| 525 528 | 
             
            };
         | 
| 526 529 |  | 
| 527 | 
            -
             | 
| 528 | 
            -
             | 
| 529 | 
            -
             | 
| 530 | 
            -
             | 
| 531 | 
            -
             | 
| 532 | 
            -
               | 
| 533 | 
            -
               | 
| 534 | 
            -
             | 
| 530 | 
            +
            // move create event to here
         | 
| 531 | 
            +
             | 
| 532 | 
            +
            // usage example:
         | 
| 533 | 
            +
            // #dispatchSomething = createDispatchEvent.bind(this, 'something')
         | 
| 534 | 
            +
            function createDispatchEvent(eventName) {
         | 
| 535 | 
            +
              this[`on${eventName}`]?.(); // in case we got an event callback as property
         | 
| 536 | 
            +
              this.dispatchEvent(new Event(eventName));
         | 
| 537 | 
            +
            }
         | 
| 535 538 |  | 
| 536 539 | 
             
            const observedAttributes = [
         | 
| 537 540 | 
             
              'required',
         | 
| @@ -542,7 +545,7 @@ const errorAttributes = { | |
| 542 545 | 
             
              valueMissing: 'data-errormessage-value-missing',
         | 
| 543 546 | 
             
              patternMismatch: 'data-errormessage-pattern-mismatch'
         | 
| 544 547 | 
             
            };
         | 
| 545 | 
            -
            const  | 
| 548 | 
            +
            const inputValidationMixin = (superclass) => class InputValidationMixinClass extends superclass {
         | 
| 546 549 | 
             
              static get observedAttributes() {
         | 
| 547 550 | 
             
                return [
         | 
| 548 551 | 
             
                  ...superclass.observedAttributes || [],
         | 
| @@ -554,18 +557,19 @@ const inputMixin = (superclass) => class InputMixinClass extends superclass { | |
| 554 557 | 
             
                return true;
         | 
| 555 558 | 
             
              }
         | 
| 556 559 |  | 
| 560 | 
            +
              #dispatchValid = createDispatchEvent.bind(this, 'valid')
         | 
| 561 | 
            +
              #dispatchInvalid = createDispatchEvent.bind(this, 'invalid')
         | 
| 562 | 
            +
             | 
| 557 563 | 
             
              #internals
         | 
| 558 564 |  | 
| 565 | 
            +
              #boundedHandleInput
         | 
| 566 | 
            +
             | 
| 559 567 | 
             
              constructor() {
         | 
| 560 568 | 
             
                super();
         | 
| 561 569 |  | 
| 562 570 | 
             
                this.#internals = this.attachInternals();
         | 
| 563 571 |  | 
| 564 | 
            -
                 | 
| 565 | 
            -
                  this[`dispatch${upperFirst(event)}`] = function () {
         | 
| 566 | 
            -
                    this.dispatchInputEvent(event);
         | 
| 567 | 
            -
                  };
         | 
| 568 | 
            -
                }
         | 
| 572 | 
            +
                this.#boundedHandleInput = this.#handleInput.bind(this);
         | 
| 569 573 | 
             
              }
         | 
| 570 574 |  | 
| 571 575 | 
             
              get defaultErrorMsgValueMissing() {
         | 
| @@ -591,13 +595,7 @@ const inputMixin = (superclass) => class InputMixinClass extends superclass { | |
| 591 595 | 
             
                }
         | 
| 592 596 | 
             
              }
         | 
| 593 597 |  | 
| 594 | 
            -
              get isReadOnly() {
         | 
| 595 | 
            -
                return this.getAttribute('readonly') !== 'false'
         | 
| 596 | 
            -
              }
         | 
| 597 | 
            -
             | 
| 598 598 | 
             
              setValidity() {
         | 
| 599 | 
            -
                if (this.isReadOnly) return;
         | 
| 600 | 
            -
             | 
| 601 599 | 
             
                const validity = this.getValidity();
         | 
| 602 600 | 
             
                this.#internals.setValidity(validity, this.getErrorMessage(validity));
         | 
| 603 601 | 
             
              }
         | 
| @@ -607,7 +605,7 @@ const inputMixin = (superclass) => class InputMixinClass extends superclass { | |
| 607 605 | 
             
              }
         | 
| 608 606 |  | 
| 609 607 | 
             
              getValidity() {
         | 
| 610 | 
            -
                 | 
| 608 | 
            +
                console.warn('getValidity', 'is not implemented');
         | 
| 611 609 | 
             
              }
         | 
| 612 610 |  | 
| 613 611 | 
             
              checkValidity() {
         | 
| @@ -639,36 +637,11 @@ const inputMixin = (superclass) => class InputMixinClass extends superclass { | |
| 639 637 | 
             
                return this.getAttribute('pattern')
         | 
| 640 638 | 
             
              }
         | 
| 641 639 |  | 
| 642 | 
            -
               | 
| 643 | 
            -
                throw Error('get value', 'is not implemented')
         | 
| 644 | 
            -
              }
         | 
| 645 | 
            -
             | 
| 646 | 
            -
              set value(value) {
         | 
| 647 | 
            -
                throw Error('set value', 'is not implemented')
         | 
| 648 | 
            -
              }
         | 
| 649 | 
            -
             | 
| 650 | 
            -
              handleFocus() {
         | 
| 651 | 
            -
                throw Error('handleFocus', 'is not implemented')
         | 
| 652 | 
            -
              }
         | 
| 653 | 
            -
             | 
| 654 | 
            -
              handleInput() {
         | 
| 640 | 
            +
              #handleInput() {
         | 
| 655 641 | 
             
                this.setValidity();
         | 
| 656 642 | 
             
                this.handleDispatchValidationEvents();
         | 
| 657 643 | 
             
              }
         | 
| 658 644 |  | 
| 659 | 
            -
              handleBlur() {
         | 
| 660 | 
            -
                throw Error('handleBlur', 'is not implemented')
         | 
| 661 | 
            -
              }
         | 
| 662 | 
            -
             | 
| 663 | 
            -
              handleChange() {
         | 
| 664 | 
            -
                throw Error('handleChange', 'is not implemented')
         | 
| 665 | 
            -
              }
         | 
| 666 | 
            -
             | 
| 667 | 
            -
              dispatchInputEvent(eventName) {
         | 
| 668 | 
            -
                this[`on${eventName}`]?.(); // in case we got an event callback as property
         | 
| 669 | 
            -
                this.dispatchEvent(new InputEvent(eventName));
         | 
| 670 | 
            -
              }
         | 
| 671 | 
            -
             | 
| 672 645 | 
             
              attributeChangedCallback(attrName, oldValue, newValue) {
         | 
| 673 646 | 
             
                super.attributeChangedCallback?.(attrName, oldValue, newValue);
         | 
| 674 647 |  | 
| @@ -679,25 +652,23 @@ const inputMixin = (superclass) => class InputMixinClass extends superclass { | |
| 679 652 |  | 
| 680 653 | 
             
              handleDispatchValidationEvents() {
         | 
| 681 654 | 
             
                if (this.checkValidity()) {
         | 
| 682 | 
            -
                  this | 
| 655 | 
            +
                  this.#dispatchValid();
         | 
| 683 656 | 
             
                } else {
         | 
| 684 | 
            -
                  this | 
| 657 | 
            +
                  this.#dispatchInvalid();
         | 
| 685 658 | 
             
                }
         | 
| 686 659 | 
             
              }
         | 
| 687 660 |  | 
| 688 661 | 
             
              connectedCallback() {
         | 
| 689 662 | 
             
                super.connectedCallback?.();
         | 
| 690 663 |  | 
| 664 | 
            +
                this.addEventListener('input', this.#boundedHandleInput);
         | 
| 665 | 
            +
             | 
| 691 666 | 
             
                this.setValidity();
         | 
| 692 667 | 
             
                this.handleDispatchValidationEvents();
         | 
| 668 | 
            +
              }
         | 
| 693 669 |  | 
| 694 | 
            -
             | 
| 695 | 
            -
                 | 
| 696 | 
            -
                // of this element and not the nested element's events
         | 
| 697 | 
            -
                this.onfocus = this.handleFocus.bind(this);
         | 
| 698 | 
            -
                this.addEventListener('input', this.handleInput.bind(this));
         | 
| 699 | 
            -
                this.addEventListener('blur', this.handleBlur.bind(this));
         | 
| 700 | 
            -
                this.addEventListener('change', this.handleBlur.bind(this));
         | 
| 670 | 
            +
              disconnectedCallback() {
         | 
| 671 | 
            +
                this.removeEventListener('input', this.#boundedHandleInput);
         | 
| 701 672 | 
             
              }
         | 
| 702 673 | 
             
            };
         | 
| 703 674 |  | 
| @@ -730,18 +701,28 @@ const getNestedInput = (ele) => { | |
| 730 701 | 
             
            };
         | 
| 731 702 |  | 
| 732 703 | 
             
            const proxyInputMixin = (superclass) =>
         | 
| 733 | 
            -
            	class proxyInputMixinClass extends  | 
| 704 | 
            +
            	class proxyInputMixinClass extends inputValidationMixin(superclass) {
         | 
| 734 705 | 
             
            		static get observedAttributes() {
         | 
| 735 706 | 
             
            			return [...superclass.observedAttributes || [], ...errorAttrs];
         | 
| 736 707 | 
             
            		}
         | 
| 737 708 |  | 
| 738 709 | 
             
            		#inputElement
         | 
| 739 710 |  | 
| 711 | 
            +
            		#boundHandleFocus
         | 
| 712 | 
            +
            		#boundHandleInvalid
         | 
| 713 | 
            +
            		#boundHandleValid
         | 
| 714 | 
            +
             | 
| 740 715 | 
             
            		constructor() {
         | 
| 741 716 | 
             
            			super();
         | 
| 742 717 |  | 
| 743 718 | 
             
            			this.#inputElement = super.inputElement;
         | 
| 744 719 |  | 
| 720 | 
            +
            			this.#boundHandleFocus = this.#handleFocus.bind(this);
         | 
| 721 | 
            +
            			this.#boundHandleInvalid = this.#handleInvalid.bind(this);
         | 
| 722 | 
            +
            			this.#boundHandleValid = this.#handleValid.bind(this);
         | 
| 723 | 
            +
             | 
| 724 | 
            +
            			this.baseEle = this.shadowRoot.querySelector(this.baseSelector);
         | 
| 725 | 
            +
             | 
| 745 726 | 
             
            		}
         | 
| 746 727 |  | 
| 747 728 | 
             
            		get inputElement() {
         | 
| @@ -749,7 +730,7 @@ const proxyInputMixin = (superclass) => | |
| 749 730 | 
             
            			const textAreaSlot = this.baseEle.shadowRoot.querySelector('slot[name="textarea"]');
         | 
| 750 731 |  | 
| 751 732 | 
             
            			this.#inputElement ??= getNestedInput(inputSlot) || getNestedInput(textAreaSlot);
         | 
| 752 | 
            -
             | 
| 733 | 
            +
             | 
| 753 734 | 
             
            			if (!this.#inputElement) throw Error('no input was found');
         | 
| 754 735 |  | 
| 755 736 | 
             
            			return this.#inputElement
         | 
| @@ -765,27 +746,17 @@ const proxyInputMixin = (superclass) => | |
| 765 746 |  | 
| 766 747 | 
             
            		reportValidityOnInternalInput() {
         | 
| 767 748 | 
             
            			setTimeout(() => {
         | 
| 749 | 
            +
            				this.baseEle.focus(); //TODO: check if this is needed
         | 
| 768 750 | 
             
            				this.inputElement.reportValidity();
         | 
| 769 | 
            -
            			} | 
| 770 | 
            -
            		}
         | 
| 771 | 
            -
             | 
| 772 | 
            -
            		handleBlur() { }
         | 
| 773 | 
            -
             | 
| 774 | 
            -
            		handleFocus() {
         | 
| 775 | 
            -
            			this.inputElement.focus();
         | 
| 776 | 
            -
            			if (this.hasAttribute('invalid')) {
         | 
| 777 | 
            -
            				this.reportValidityOnInternalInput();
         | 
| 778 | 
            -
            			}
         | 
| 751 | 
            +
            			});
         | 
| 779 752 | 
             
            		}
         | 
| 780 753 |  | 
| 781 754 | 
             
            		// we want reportValidity to behave like form submission
         | 
| 782 755 | 
             
            		reportValidity() {
         | 
| 783 | 
            -
            			const isValid = super.reportValidity();
         | 
| 784 756 | 
             
            			if (!isValid) {
         | 
| 785 757 | 
             
            				this.setAttribute('invalid', 'true');
         | 
| 786 | 
            -
            				this. | 
| 758 | 
            +
            				this.reportValidityOnInternalInput();
         | 
| 787 759 | 
             
            			}
         | 
| 788 | 
            -
            			this.reportValidityOnInternalInput();
         | 
| 789 760 | 
             
            		}
         | 
| 790 761 |  | 
| 791 762 | 
             
            		setInternalInputErrorMessage() {
         | 
| @@ -794,48 +765,47 @@ const proxyInputMixin = (superclass) => | |
| 794 765 | 
             
            			}
         | 
| 795 766 | 
             
            		}
         | 
| 796 767 |  | 
| 797 | 
            -
            		 | 
| 798 | 
            -
             | 
| 799 | 
            -
             | 
| 800 | 
            -
            			 | 
| 801 | 
            -
             | 
| 802 | 
            -
             | 
| 803 | 
            -
            				 | 
| 804 | 
            -
            					if (!this.checkValidity()) {
         | 
| 805 | 
            -
            						this.setAttribute('invalid', 'true');
         | 
| 806 | 
            -
            					}
         | 
| 768 | 
            +
            		// when clicking on the form submit button and the input is invalid
         | 
| 769 | 
            +
            		// we want it to appear as invalid
         | 
| 770 | 
            +
            		#handleFocus(e) {
         | 
| 771 | 
            +
            			if (e.relatedTarget?.form) {
         | 
| 772 | 
            +
            				if (!this.checkValidity()) {
         | 
| 773 | 
            +
            					this.setAttribute('invalid', 'true');
         | 
| 774 | 
            +
            				}
         | 
| 807 775 |  | 
| 808 | 
            -
             | 
| 809 | 
            -
             | 
| 810 | 
            -
            					}
         | 
| 776 | 
            +
            				if (this.hasAttribute('invalid')) {
         | 
| 777 | 
            +
            					this.reportValidityOnInternalInput();
         | 
| 811 778 | 
             
            				}
         | 
| 812 | 
            -
            			} | 
| 779 | 
            +
            			}
         | 
| 780 | 
            +
            		}
         | 
| 813 781 |  | 
| 814 | 
            -
             | 
| 815 | 
            -
             | 
| 816 | 
            -
             | 
| 817 | 
            -
             | 
| 782 | 
            +
            		#handleInvalid() {
         | 
| 783 | 
            +
            			this.setInternalInputErrorMessage();
         | 
| 784 | 
            +
            			this.setAttribute('error-message', this.validationMessage);
         | 
| 785 | 
            +
            		}
         | 
| 818 786 |  | 
| 819 | 
            -
             | 
| 820 | 
            -
             | 
| 821 | 
            -
             | 
| 787 | 
            +
            		#handleValid() {
         | 
| 788 | 
            +
            			this.removeAttribute('invalid');
         | 
| 789 | 
            +
            		}
         | 
| 822 790 |  | 
| 791 | 
            +
            		connectedCallback() {
         | 
| 823 792 | 
             
            			super.connectedCallback?.();
         | 
| 824 793 |  | 
| 825 | 
            -
            			this | 
| 794 | 
            +
            			// this is our way to identify that the form was submitted
         | 
| 795 | 
            +
            			// in this case, we want the input to be in error state if it's not valid
         | 
| 796 | 
            +
            			this.addEventListener('focus', this.#boundHandleFocus);
         | 
| 797 | 
            +
             | 
| 798 | 
            +
            			this.addEventListener('invalid', this.#boundHandleInvalid);
         | 
| 799 | 
            +
            			this.addEventListener('valid', this.#boundHandleValid);
         | 
| 800 | 
            +
             | 
| 801 | 
            +
            			this.addEventListener('input', () => {
         | 
| 826 802 | 
             
            				this.inputElement.setCustomValidity('');
         | 
| 827 803 | 
             
            				if (!this.inputElement.checkValidity())
         | 
| 828 804 | 
             
            					this.setInternalInputErrorMessage();
         | 
| 829 805 | 
             
            			});
         | 
| 830 806 |  | 
| 831 | 
            -
            			this.inputElement.addEventListener('invalid', () => {
         | 
| 832 | 
            -
            				this.setValidity();
         | 
| 833 | 
            -
            				this.setInternalInputErrorMessage();
         | 
| 834 | 
            -
            				this.setAttribute('error-message', this.validationMessage);
         | 
| 835 | 
            -
            			});
         | 
| 836 | 
            -
             | 
| 837 807 | 
             
            			// this is needed in order to make sure the form input validation is working
         | 
| 838 | 
            -
            			if (!this.hasAttribute('tabindex')) {
         | 
| 808 | 
            +
            			if (!this.hasAttribute('tabindex') && this.getRootNode() === document) {
         | 
| 839 809 | 
             
            				this.setAttribute('tabindex', 0);
         | 
| 840 810 | 
             
            			}
         | 
| 841 811 |  | 
| @@ -844,6 +814,12 @@ const proxyInputMixin = (superclass) => | |
| 844 814 | 
             
            			this.setSelectionRange = this.inputElement.setSelectionRange?.bind(this.inputElement);
         | 
| 845 815 | 
             
            		}
         | 
| 846 816 |  | 
| 817 | 
            +
            		disconnectedCallback() {
         | 
| 818 | 
            +
            			this.removeEventListener('focus', this.#boundHandleFocus);
         | 
| 819 | 
            +
            			this.removeEventListener('invalid', this.#boundHandleInvalid);
         | 
| 820 | 
            +
            			this.removeEventListener('valid', this.#boundHandleValid);
         | 
| 821 | 
            +
            		}
         | 
| 822 | 
            +
             | 
| 847 823 | 
             
            		attributeChangedCallback(attrName, oldValue, newValue) {
         | 
| 848 824 | 
             
            			super.attributeChangedCallback?.(attrName, oldValue, newValue);
         | 
| 849 825 |  | 
| @@ -854,7 +830,7 @@ const proxyInputMixin = (superclass) => | |
| 854 830 | 
             
            	};
         | 
| 855 831 |  | 
| 856 832 | 
             
            const componentNameValidationMixin = (superclass) =>
         | 
| 857 | 
            -
            	class  | 
| 833 | 
            +
            	class ComponentNameValidationMixinClass extends superclass {
         | 
| 858 834 | 
             
            		#checkComponentName() {
         | 
| 859 835 | 
             
            			const currentComponentName = this.shadowRoot.host.tagName.toLowerCase();
         | 
| 860 836 |  | 
| @@ -879,6 +855,160 @@ const componentNameValidationMixin = (superclass) => | |
| 879 855 | 
             
            		}
         | 
| 880 856 | 
             
            	};
         | 
| 881 857 |  | 
| 858 | 
            +
            const hoverableMixin =
         | 
| 859 | 
            +
            	(superclass) =>
         | 
| 860 | 
            +
            		class HoverableMixinClass extends superclass {
         | 
| 861 | 
            +
            			#boundOnMouseOver = this.#onMouseOver.bind(this)
         | 
| 862 | 
            +
             | 
| 863 | 
            +
            			#onMouseOver(e) {
         | 
| 864 | 
            +
            				this.setAttribute('hover', 'true');
         | 
| 865 | 
            +
            				e.target.addEventListener(
         | 
| 866 | 
            +
            					'mouseleave',
         | 
| 867 | 
            +
            					() => this.shadowRoot.host.removeAttribute('hover'),
         | 
| 868 | 
            +
            					{ once: true }
         | 
| 869 | 
            +
            				);
         | 
| 870 | 
            +
            			}
         | 
| 871 | 
            +
             | 
| 872 | 
            +
            			connectedCallback() {
         | 
| 873 | 
            +
            				super.connectedCallback?.();
         | 
| 874 | 
            +
             | 
| 875 | 
            +
            				const baseElement = this.shadowRoot.querySelector(
         | 
| 876 | 
            +
            					this.baseSelector
         | 
| 877 | 
            +
            				);
         | 
| 878 | 
            +
             | 
| 879 | 
            +
            				baseElement.addEventListener('mouseover', this.#boundOnMouseOver);
         | 
| 880 | 
            +
            			}
         | 
| 881 | 
            +
            		};
         | 
| 882 | 
            +
             | 
| 883 | 
            +
            const events = [
         | 
| 884 | 
            +
              'blur',
         | 
| 885 | 
            +
              'focus',
         | 
| 886 | 
            +
              'focusin',
         | 
| 887 | 
            +
              'focusout',
         | 
| 888 | 
            +
            ];
         | 
| 889 | 
            +
             | 
| 890 | 
            +
            const focusMixin = (superclass) => class FocusMixinClass extends superclass {
         | 
| 891 | 
            +
              #isFocused = false
         | 
| 892 | 
            +
              #setFocusTimer
         | 
| 893 | 
            +
             | 
| 894 | 
            +
              #boundedHandleFocus
         | 
| 895 | 
            +
              #boundedHandleBlur
         | 
| 896 | 
            +
              #boundedHandleFocusIn
         | 
| 897 | 
            +
              #boundedHandleFocusOut
         | 
| 898 | 
            +
             | 
| 899 | 
            +
              constructor() {
         | 
| 900 | 
            +
                super();
         | 
| 901 | 
            +
             | 
| 902 | 
            +
                for (const event of events) {
         | 
| 903 | 
            +
                  this[`dispatch${upperFirst(event)}`] = function () {
         | 
| 904 | 
            +
                    this.dispatchInputEvent(event);
         | 
| 905 | 
            +
                  };
         | 
| 906 | 
            +
                }
         | 
| 907 | 
            +
             | 
| 908 | 
            +
                this.#boundedHandleFocus = this.#handleFocus.bind(this);
         | 
| 909 | 
            +
                this.#boundedHandleBlur = this.#handleBlur.bind(this);
         | 
| 910 | 
            +
                this.#boundedHandleFocusIn = this.#handleFocusIn.bind(this);
         | 
| 911 | 
            +
                this.#boundedHandleFocusOut = this.#handleFocusOut.bind(this);
         | 
| 912 | 
            +
              }
         | 
| 913 | 
            +
             | 
| 914 | 
            +
              #handleFocus(e) {
         | 
| 915 | 
            +
                if (this.isReadOnly) {
         | 
| 916 | 
            +
                  e.stopPropagation();
         | 
| 917 | 
            +
                  return
         | 
| 918 | 
            +
                }
         | 
| 919 | 
            +
                // we want to listen only to browser events 
         | 
| 920 | 
            +
                // and not to events we are dispatching
         | 
| 921 | 
            +
                if (e.isTrusted) { // TODO: check if this is needed, because Vaadin is also dispatching events
         | 
| 922 | 
            +
                  // we want to control the focus events that dispatched by the component
         | 
| 923 | 
            +
                  // so we are stopping propagation and handling it in setFocus
         | 
| 924 | 
            +
                  e.stopPropagation();
         | 
| 925 | 
            +
                  this.setFocus(true);
         | 
| 926 | 
            +
             | 
| 927 | 
            +
                  // if the focus event is on the root component (and not on the inner components)
         | 
| 928 | 
            +
                  // we want to notify the component and let it decide what to do with it
         | 
| 929 | 
            +
                  if (e.target === this) {
         | 
| 930 | 
            +
                    this.onFocus(e);
         | 
| 931 | 
            +
                  }
         | 
| 932 | 
            +
                }
         | 
| 933 | 
            +
              }
         | 
| 934 | 
            +
             | 
| 935 | 
            +
              #handleFocusOut(e) {
         | 
| 936 | 
            +
                // we want to listen only to browser events 
         | 
| 937 | 
            +
                // and not to events we are dispatching
         | 
| 938 | 
            +
                if (e.isTrusted) {
         | 
| 939 | 
            +
                  // we want to control the focus events that dispatched by the component
         | 
| 940 | 
            +
                  // so we are stopping propagation and handling it in setFocus
         | 
| 941 | 
            +
                  e.stopPropagation();
         | 
| 942 | 
            +
                }
         | 
| 943 | 
            +
              }
         | 
| 944 | 
            +
             | 
| 945 | 
            +
              #handleFocusIn(e) {
         | 
| 946 | 
            +
                // we want to listen only to browser events 
         | 
| 947 | 
            +
                // and not to events we are dispatching
         | 
| 948 | 
            +
                if (e.isTrusted) {
         | 
| 949 | 
            +
                  // we want to control the focus events that dispatched by the component
         | 
| 950 | 
            +
                  // so we are stopping propagation and handling it in setFocus
         | 
| 951 | 
            +
                  e.stopPropagation();
         | 
| 952 | 
            +
                }
         | 
| 953 | 
            +
              }
         | 
| 954 | 
            +
             | 
| 955 | 
            +
              #handleBlur(e) {
         | 
| 956 | 
            +
                if (e.isTrusted) {
         | 
| 957 | 
            +
                  e.stopPropagation();
         | 
| 958 | 
            +
                  this.setFocus(false);
         | 
| 959 | 
            +
                }
         | 
| 960 | 
            +
              }
         | 
| 961 | 
            +
             | 
| 962 | 
            +
              get isReadOnly() {
         | 
| 963 | 
            +
                return this.hasAttribute('readonly') && this.getAttribute('readonly') !== 'false'
         | 
| 964 | 
            +
              }
         | 
| 965 | 
            +
             | 
| 966 | 
            +
              // we want to debounce the calls to this fn
         | 
| 967 | 
            +
              // so we can support input like components with multiple inputs inside
         | 
| 968 | 
            +
              setFocus(isFocused) {
         | 
| 969 | 
            +
                clearTimeout(this.#setFocusTimer);
         | 
| 970 | 
            +
             | 
| 971 | 
            +
                this.#setFocusTimer = setTimeout(() => {
         | 
| 972 | 
            +
                  if (this.#isFocused !== isFocused) {
         | 
| 973 | 
            +
                    this.#isFocused = isFocused;
         | 
| 974 | 
            +
                    if (isFocused) {
         | 
| 975 | 
            +
                      this.dispatchFocus();
         | 
| 976 | 
            +
                      this.dispatchFocusin();
         | 
| 977 | 
            +
                    }
         | 
| 978 | 
            +
                    else {
         | 
| 979 | 
            +
                      this.dispatchBlur();
         | 
| 980 | 
            +
                      this.dispatchFocusout();
         | 
| 981 | 
            +
                    }
         | 
| 982 | 
            +
                  }
         | 
| 983 | 
            +
                });
         | 
| 984 | 
            +
              }
         | 
| 985 | 
            +
             | 
| 986 | 
            +
              onFocus() {
         | 
| 987 | 
            +
                console.warn('onFocus', 'is not implemented');
         | 
| 988 | 
            +
              }
         | 
| 989 | 
            +
             | 
| 990 | 
            +
              dispatchInputEvent(eventName) {
         | 
| 991 | 
            +
                this[`on${eventName}`]?.(); // in case we got an event callback as property
         | 
| 992 | 
            +
                this.dispatchEvent(new InputEvent(eventName));
         | 
| 993 | 
            +
              }
         | 
| 994 | 
            +
             | 
| 995 | 
            +
              connectedCallback() {
         | 
| 996 | 
            +
                super.connectedCallback?.();
         | 
| 997 | 
            +
             | 
| 998 | 
            +
                this.addEventListener('focus', this.#boundedHandleFocus, true);
         | 
| 999 | 
            +
                this.addEventListener('blur', this.#boundedHandleBlur, true);
         | 
| 1000 | 
            +
                this.addEventListener('focusin', this.#boundedHandleFocusIn);
         | 
| 1001 | 
            +
                this.addEventListener('focusout', this.#boundedHandleFocusOut);
         | 
| 1002 | 
            +
              }
         | 
| 1003 | 
            +
             | 
| 1004 | 
            +
              disconnectedCallback() {
         | 
| 1005 | 
            +
                this.removeEventListener('focus', this.#boundedHandleFocus);
         | 
| 1006 | 
            +
                this.removeEventListener('blur', this.#boundedHandleBlur);
         | 
| 1007 | 
            +
                this.removeEventListener('focusin', this.#boundedHandleFocusIn);
         | 
| 1008 | 
            +
                this.removeEventListener('focusout', this.#boundedHandleFocusOut);
         | 
| 1009 | 
            +
              }
         | 
| 1010 | 
            +
            };
         | 
| 1011 | 
            +
             | 
| 882 1012 | 
             
            const sanitizeSelector = (selector) => selector.replace(/[^\w\s]/gi, '');
         | 
| 883 1013 |  | 
| 884 1014 | 
             
            const appendSuffixToKeys = (obj, suffix) => Object.keys(obj).reduce((acc, key) =>
         | 
| @@ -936,6 +1066,52 @@ const portalMixin = ({ name, selector, mappings = {} }) => (superclass) => { | |
| 936 1066 | 
             
              }
         | 
| 937 1067 | 
             
            };
         | 
| 938 1068 |  | 
| 1069 | 
            +
            const changeMixin = (superclass) => class ChangeMixinClass extends superclass {
         | 
| 1070 | 
            +
             | 
| 1071 | 
            +
              #boundedHandleChange
         | 
| 1072 | 
            +
              #boundedHandleBlur  
         | 
| 1073 | 
            +
              
         | 
| 1074 | 
            +
              #removeChangeListener
         | 
| 1075 | 
            +
              #removeBlurListener
         | 
| 1076 | 
            +
             | 
| 1077 | 
            +
              #dispatchChange = createDispatchEvent.bind(this, 'change')
         | 
| 1078 | 
            +
             | 
| 1079 | 
            +
              constructor() {
         | 
| 1080 | 
            +
                super();
         | 
| 1081 | 
            +
             | 
| 1082 | 
            +
                this.#boundedHandleChange = this.#handleChange.bind(this);
         | 
| 1083 | 
            +
                this.#boundedHandleBlur = this.#handleBlur.bind(this);
         | 
| 1084 | 
            +
              }
         | 
| 1085 | 
            +
             | 
| 1086 | 
            +
              #handleChange(e) {
         | 
| 1087 | 
            +
                // we want to listen only to browser events 
         | 
| 1088 | 
            +
                // and not to events we are dispatching
         | 
| 1089 | 
            +
                if (e.isTrusted) {
         | 
| 1090 | 
            +
                  // we want to control the change events that dispatched by the component
         | 
| 1091 | 
            +
                  // so we are stopping propagation and handling it in handleBlur
         | 
| 1092 | 
            +
                  e.stopPropagation();
         | 
| 1093 | 
            +
                }
         | 
| 1094 | 
            +
              }
         | 
| 1095 | 
            +
             | 
| 1096 | 
            +
              #handleBlur() {
         | 
| 1097 | 
            +
                // on blur, we want to dispatch a change event
         | 
| 1098 | 
            +
                this.#dispatchChange();
         | 
| 1099 | 
            +
              }
         | 
| 1100 | 
            +
             | 
| 1101 | 
            +
              connectedCallback() {
         | 
| 1102 | 
            +
                super.connectedCallback?.();
         | 
| 1103 | 
            +
             | 
| 1104 | 
            +
                this.#removeChangeListener = addEventListener.bind();
         | 
| 1105 | 
            +
                this.addEventListener('change', this.#boundedHandleChange, true);
         | 
| 1106 | 
            +
                this.addEventListener('blur', this.#boundedHandleBlur);
         | 
| 1107 | 
            +
              }
         | 
| 1108 | 
            +
             | 
| 1109 | 
            +
              disconnectedCallback() {
         | 
| 1110 | 
            +
                this.removeEventListener('change', this.#boundedHandleChange);
         | 
| 1111 | 
            +
                this.removeEventListener('blur', this.#boundedHandleBlur);
         | 
| 1112 | 
            +
              }
         | 
| 1113 | 
            +
            };
         | 
| 1114 | 
            +
             | 
| 939 1115 | 
             
            const componentName$i = getComponentName('button');
         | 
| 940 1116 |  | 
| 941 1117 | 
             
            const editorOverrides = `vaadin-button::part(label) { pointer-events: none; }`;
         | 
| @@ -1063,41 +1239,36 @@ customElements.define(componentName$h, Checkbox); | |
| 1063 1239 |  | 
| 1064 1240 | 
             
            const componentName$g = getComponentName('loader-linear');
         | 
| 1065 1241 |  | 
| 1066 | 
            -
            class RawLoaderLinear extends  | 
| 1242 | 
            +
            class RawLoaderLinear extends createBaseClass({ componentName: componentName$g, baseSelector: ':host > div' }) {
         | 
| 1067 1243 | 
             
            	static get componentName() {
         | 
| 1068 1244 | 
             
            		return componentName$g;
         | 
| 1069 1245 | 
             
            	}
         | 
| 1070 1246 | 
             
            	constructor() {
         | 
| 1071 1247 | 
             
            		super();
         | 
| 1072 | 
            -
            		const template = document.createElement('template');
         | 
| 1073 | 
            -
            		template.innerHTML = `
         | 
| 1074 | 
            -
            			<style>
         | 
| 1075 | 
            -
            				@keyframes tilt {
         | 
| 1076 | 
            -
            					0% { transform: translateX(0); }
         | 
| 1077 | 
            -
            					50% { transform: translateX(400%); }
         | 
| 1078 | 
            -
            				}
         | 
| 1079 | 
            -
            				:host {
         | 
| 1080 | 
            -
            					position: relative;
         | 
| 1081 | 
            -
            					display: inline-block
         | 
| 1082 | 
            -
            				}
         | 
| 1083 | 
            -
            				div::after {
         | 
| 1084 | 
            -
            					content: '';
         | 
| 1085 | 
            -
            					animation-name: tilt;
         | 
| 1086 | 
            -
            					position: absolute;
         | 
| 1087 | 
            -
            					left: 0;
         | 
| 1088 | 
            -
            				}
         | 
| 1089 1248 |  | 
| 1090 | 
            -
             | 
| 1091 | 
            -
             | 
| 1092 | 
            -
             | 
| 1093 | 
            -
             | 
| 1094 | 
            -
             | 
| 1095 | 
            -
             | 
| 1096 | 
            -
             | 
| 1097 | 
            -
             | 
| 1098 | 
            -
             | 
| 1249 | 
            +
            		this.attachShadow({ mode: 'open' }).innerHTML = `
         | 
| 1250 | 
            +
            		<style>
         | 
| 1251 | 
            +
            			@keyframes tilt {
         | 
| 1252 | 
            +
            				0% { transform: translateX(0); }
         | 
| 1253 | 
            +
            				50% { transform: translateX(400%); }
         | 
| 1254 | 
            +
            			}
         | 
| 1255 | 
            +
            			:host {
         | 
| 1256 | 
            +
            				position: relative;
         | 
| 1257 | 
            +
            				display: inline-block
         | 
| 1258 | 
            +
            			}
         | 
| 1259 | 
            +
            			div::after {
         | 
| 1260 | 
            +
            				content: '';
         | 
| 1261 | 
            +
            				animation-name: tilt;
         | 
| 1262 | 
            +
            				position: absolute;
         | 
| 1263 | 
            +
            				left: 0;
         | 
| 1264 | 
            +
            			}
         | 
| 1099 1265 |  | 
| 1100 | 
            -
             | 
| 1266 | 
            +
            			:host > div {
         | 
| 1267 | 
            +
            				width: 100%;
         | 
| 1268 | 
            +
            			}
         | 
| 1269 | 
            +
            		</style>
         | 
| 1270 | 
            +
            		<div></div>
         | 
| 1271 | 
            +
            	`;
         | 
| 1101 1272 | 
             
            	}
         | 
| 1102 1273 | 
             
            }
         | 
| 1103 1274 |  | 
| @@ -1132,34 +1303,26 @@ customElements.define(componentName$g, LoaderLinear); | |
| 1132 1303 |  | 
| 1133 1304 | 
             
            const componentName$f = getComponentName('loader-radial');
         | 
| 1134 1305 |  | 
| 1135 | 
            -
            class RawLoaderRadial extends  | 
| 1136 | 
            -
            	static get componentName() {
         | 
| 1137 | 
            -
            		return componentName$f;
         | 
| 1138 | 
            -
            	}
         | 
| 1306 | 
            +
            class RawLoaderRadial extends createBaseClass({ componentName: componentName$f, baseSelector: ':host > div' }) {
         | 
| 1139 1307 | 
             
            	constructor() {
         | 
| 1140 1308 | 
             
            		super();
         | 
| 1141 | 
            -
            		const template = document.createElement('template');
         | 
| 1142 | 
            -
            		template.innerHTML = `
         | 
| 1143 | 
            -
            			<style>
         | 
| 1144 | 
            -
            				@keyframes spin {
         | 
| 1145 | 
            -
            					0% { transform: rotate(0deg); }
         | 
| 1146 | 
            -
            					100% { transform: rotate(360deg); }
         | 
| 1147 | 
            -
            				}
         | 
| 1148 | 
            -
            				:host {
         | 
| 1149 | 
            -
            					position: relative;
         | 
| 1150 | 
            -
            					display: inline-flex;
         | 
| 1151 | 
            -
            				}
         | 
| 1152 | 
            -
            				:host > div {
         | 
| 1153 | 
            -
            					animation-name: spin;
         | 
| 1154 | 
            -
            				}
         | 
| 1155 | 
            -
            			</style>
         | 
| 1156 | 
            -
            			<div></div>
         | 
| 1157 | 
            -
            		`;
         | 
| 1158 | 
            -
             | 
| 1159 | 
            -
            		this.attachShadow({ mode: 'open' });
         | 
| 1160 | 
            -
            		this.shadowRoot.appendChild(template.content.cloneNode(true));
         | 
| 1161 1309 |  | 
| 1162 | 
            -
            		this. | 
| 1310 | 
            +
            		this.attachShadow({ mode: 'open' }).innerHTML = `
         | 
| 1311 | 
            +
            		<style>
         | 
| 1312 | 
            +
            			@keyframes spin {
         | 
| 1313 | 
            +
            				0% { transform: rotate(0deg); }
         | 
| 1314 | 
            +
            				100% { transform: rotate(360deg); }
         | 
| 1315 | 
            +
            			}
         | 
| 1316 | 
            +
            			:host {
         | 
| 1317 | 
            +
            				position: relative;
         | 
| 1318 | 
            +
            				display: inline-flex;
         | 
| 1319 | 
            +
            			}
         | 
| 1320 | 
            +
            			:host > div {
         | 
| 1321 | 
            +
            				animation-name: spin;
         | 
| 1322 | 
            +
            			}
         | 
| 1323 | 
            +
            		</style>
         | 
| 1324 | 
            +
            		<div></div>
         | 
| 1325 | 
            +
            	`;
         | 
| 1163 1326 | 
             
            	}
         | 
| 1164 1327 | 
             
            }
         | 
| 1165 1328 |  | 
| @@ -1190,33 +1353,25 @@ customElements.define(componentName$f, LoaderRadial); | |
| 1190 1353 |  | 
| 1191 1354 | 
             
            const componentName$e = getComponentName('container');
         | 
| 1192 1355 |  | 
| 1193 | 
            -
            class RawContainer extends  | 
| 1194 | 
            -
            	static get componentName() {
         | 
| 1195 | 
            -
            		return componentName$e;
         | 
| 1196 | 
            -
            	}
         | 
| 1356 | 
            +
            class RawContainer extends createBaseClass({componentName: componentName$e, baseSelector: ':host > slot'}) {
         | 
| 1197 1357 | 
             
            	constructor() {
         | 
| 1198 1358 | 
             
            		super();
         | 
| 1199 | 
            -
            		const template = document.createElement('template');
         | 
| 1200 | 
            -
            		template.innerHTML = `
         | 
| 1201 | 
            -
            			<style>
         | 
| 1202 | 
            -
            				:host > slot {
         | 
| 1203 | 
            -
            					box-sizing: border-box;
         | 
| 1204 | 
            -
            					width: 100%;
         | 
| 1205 | 
            -
            					height: 100%;
         | 
| 1206 | 
            -
            					display: flex;
         | 
| 1207 | 
            -
            					overflow: auto;
         | 
| 1208 | 
            -
            				}
         | 
| 1209 | 
            -
            				:host {
         | 
| 1210 | 
            -
            					display: inline-block;
         | 
| 1211 | 
            -
            				}
         | 
| 1212 | 
            -
            			</style>
         | 
| 1213 | 
            -
            			<slot></slot>
         | 
| 1214 | 
            -
            		`;
         | 
| 1215 1359 |  | 
| 1216 | 
            -
            		this.attachShadow({ mode: 'open' }) | 
| 1217 | 
            -
            		 | 
| 1218 | 
            -
             | 
| 1219 | 
            -
             | 
| 1360 | 
            +
            		this.attachShadow({ mode: 'open' }).innerHTML = `
         | 
| 1361 | 
            +
            		<style>
         | 
| 1362 | 
            +
            			:host > slot {
         | 
| 1363 | 
            +
            				box-sizing: border-box;
         | 
| 1364 | 
            +
            				width: 100%;
         | 
| 1365 | 
            +
            				height: 100%;
         | 
| 1366 | 
            +
            				display: flex;
         | 
| 1367 | 
            +
            				overflow: auto;
         | 
| 1368 | 
            +
            			}
         | 
| 1369 | 
            +
            			:host {
         | 
| 1370 | 
            +
            				display: inline-block;
         | 
| 1371 | 
            +
            			}
         | 
| 1372 | 
            +
            		</style>
         | 
| 1373 | 
            +
            		<slot></slot>
         | 
| 1374 | 
            +
            	`;
         | 
| 1220 1375 | 
             
            	}
         | 
| 1221 1376 | 
             
            }
         | 
| 1222 1377 |  | 
| @@ -1273,51 +1428,43 @@ const DatePicker = compose( | |
| 1273 1428 | 
             
            customElements.define(componentName$d, DatePicker);
         | 
| 1274 1429 |  | 
| 1275 1430 | 
             
            const componentName$c = getComponentName('divider');
         | 
| 1276 | 
            -
            class RawDivider extends  | 
| 1277 | 
            -
            	static get componentName() {
         | 
| 1278 | 
            -
            		return componentName$c;
         | 
| 1279 | 
            -
            	}
         | 
| 1431 | 
            +
            class RawDivider extends createBaseClass({ componentName: componentName$c, baseSelector: ':host > div' }) {
         | 
| 1280 1432 | 
             
            	constructor() {
         | 
| 1281 1433 | 
             
            		super();
         | 
| 1282 1434 |  | 
| 1283 | 
            -
            		 | 
| 1284 | 
            -
            		 | 
| 1285 | 
            -
            			 | 
| 1286 | 
            -
            				: | 
| 1287 | 
            -
             | 
| 1288 | 
            -
             | 
| 1289 | 
            -
             | 
| 1290 | 
            -
             | 
| 1291 | 
            -
             | 
| 1292 | 
            -
            				: | 
| 1293 | 
            -
             | 
| 1294 | 
            -
             | 
| 1295 | 
            -
            				}
         | 
| 1296 | 
            -
             | 
| 1297 | 
            -
            				descope-text {
         | 
| 1298 | 
            -
            					flex-grow: 0;
         | 
| 1299 | 
            -
            					flex-shrink: 0;
         | 
| 1300 | 
            -
            				}
         | 
| 1435 | 
            +
            		this.attachShadow({ mode: 'open' }).innerHTML = `
         | 
| 1436 | 
            +
            		<style>
         | 
| 1437 | 
            +
            			:host > div {
         | 
| 1438 | 
            +
            				display: flex;
         | 
| 1439 | 
            +
            				height: 100%;
         | 
| 1440 | 
            +
            				width: 100%;
         | 
| 1441 | 
            +
            			}
         | 
| 1442 | 
            +
            			:host > div::before,
         | 
| 1443 | 
            +
            			:host > div::after {
         | 
| 1444 | 
            +
            				content: '';
         | 
| 1445 | 
            +
            				flex-grow: 1;
         | 
| 1446 | 
            +
            			}
         | 
| 1301 1447 |  | 
| 1302 | 
            -
             | 
| 1303 | 
            -
             | 
| 1304 | 
            -
            				 | 
| 1448 | 
            +
            			descope-text {
         | 
| 1449 | 
            +
            				flex-grow: 0;
         | 
| 1450 | 
            +
            				flex-shrink: 0;
         | 
| 1451 | 
            +
            			}
         | 
| 1305 1452 |  | 
| 1306 | 
            -
             | 
| 1307 | 
            -
             | 
| 1308 | 
            -
             | 
| 1453 | 
            +
            			:host(:empty) descope-text {
         | 
| 1454 | 
            +
            				display: none;
         | 
| 1455 | 
            +
            			}
         | 
| 1309 1456 |  | 
| 1310 | 
            -
            			 | 
| 1311 | 
            -
             | 
| 1312 | 
            -
             | 
| 1313 | 
            -
            					<slot></slot>
         | 
| 1314 | 
            -
            				</descope-text>
         | 
| 1315 | 
            -
            			</div>
         | 
| 1316 | 
            -
            		`;
         | 
| 1317 | 
            -
            		this.attachShadow({ mode: 'open' });
         | 
| 1318 | 
            -
            		this.shadowRoot.appendChild(template.content.cloneNode(true));
         | 
| 1457 | 
            +
            			:host([vertical="true"]) div {
         | 
| 1458 | 
            +
            				width: fit-content;
         | 
| 1459 | 
            +
            			}
         | 
| 1319 1460 |  | 
| 1320 | 
            -
            		 | 
| 1461 | 
            +
            		</style>
         | 
| 1462 | 
            +
            		<div>
         | 
| 1463 | 
            +
            			<descope-text>
         | 
| 1464 | 
            +
            				<slot></slot>
         | 
| 1465 | 
            +
            			</descope-text>
         | 
| 1466 | 
            +
            		</div>
         | 
| 1467 | 
            +
            	`;
         | 
| 1321 1468 |  | 
| 1322 1469 | 
             
            		this.textComponent = this.shadowRoot.querySelector('descope-text');
         | 
| 1323 1470 |  | 
| @@ -1345,7 +1492,7 @@ const Divider = compose( | |
| 1345 1492 | 
             
            			alignItems: root,
         | 
| 1346 1493 | 
             
            			alignSelf: root,
         | 
| 1347 1494 | 
             
            			flexDirection: root,
         | 
| 1348 | 
            -
            			textPadding: {...text$2, property: 'padding'},
         | 
| 1495 | 
            +
            			textPadding: { ...text$2, property: 'padding' },
         | 
| 1349 1496 | 
             
            			width: host$1,
         | 
| 1350 1497 | 
             
            			padding: host$1,
         | 
| 1351 1498 | 
             
            			backgroundColor: [before, after],
         | 
| @@ -1361,14 +1508,11 @@ const Divider = compose( | |
| 1361 1508 |  | 
| 1362 1509 | 
             
            const componentName$b = getComponentName('text');
         | 
| 1363 1510 |  | 
| 1364 | 
            -
            class RawText extends  | 
| 1365 | 
            -
            	static get componentName() {
         | 
| 1366 | 
            -
            		return componentName$b;
         | 
| 1367 | 
            -
            	}
         | 
| 1511 | 
            +
            class RawText extends createBaseClass({ componentName: componentName$b, baseSelector: ':host > slot' }) {
         | 
| 1368 1512 | 
             
            	constructor() {
         | 
| 1369 1513 | 
             
            		super();
         | 
| 1370 | 
            -
             | 
| 1371 | 
            -
            		 | 
| 1514 | 
            +
             | 
| 1515 | 
            +
            		this.attachShadow({ mode: 'open' }).innerHTML = `
         | 
| 1372 1516 | 
             
            		<style>
         | 
| 1373 1517 | 
             
            			:host {
         | 
| 1374 1518 | 
             
            				display: inline-block;
         | 
| @@ -1380,11 +1524,6 @@ class RawText extends DescopeBaseClass { | |
| 1380 1524 | 
             
            		</style>
         | 
| 1381 1525 | 
             
            		<slot></slot>
         | 
| 1382 1526 | 
             
            		`;
         | 
| 1383 | 
            -
             | 
| 1384 | 
            -
            		this.attachShadow({ mode: 'open' });
         | 
| 1385 | 
            -
            		this.shadowRoot.appendChild(template.content.cloneNode(true));
         | 
| 1386 | 
            -
             | 
| 1387 | 
            -
            		this.baseSelector = ':host > slot';
         | 
| 1388 1527 | 
             
            	}
         | 
| 1389 1528 | 
             
            }
         | 
| 1390 1529 |  | 
| @@ -1516,15 +1655,12 @@ overrides$5 = ` | |
| 1516 1655 | 
             
            customElements.define(componentName$a, EmailField);
         | 
| 1517 1656 |  | 
| 1518 1657 | 
             
            const componentName$9 = getComponentName('link');
         | 
| 1519 | 
            -
            class RawLink extends  | 
| 1520 | 
            -
            	static get componentName() {
         | 
| 1521 | 
            -
            		return componentName$9;
         | 
| 1522 | 
            -
            	}
         | 
| 1658 | 
            +
            class RawLink extends createBaseClass({ componentName: componentName$9, baseSelector: ':host a' }) {
         | 
| 1523 1659 | 
             
            	constructor() {
         | 
| 1524 1660 | 
             
            		super();
         | 
| 1525 | 
            -
            		 | 
| 1661 | 
            +
            		document.createElement('template');
         | 
| 1526 1662 |  | 
| 1527 | 
            -
            		 | 
| 1663 | 
            +
            		this.attachShadow({ mode: 'open' }).innerHTML = `
         | 
| 1528 1664 | 
             
            		<style>
         | 
| 1529 1665 | 
             
            		:host {
         | 
| 1530 1666 | 
             
            			display: inline-block;
         | 
| @@ -1542,9 +1678,6 @@ class RawLink extends DescopeBaseClass { | |
| 1542 1678 | 
             
            		</div>
         | 
| 1543 1679 | 
             
            		`;
         | 
| 1544 1680 |  | 
| 1545 | 
            -
            		this.attachShadow({ mode: 'open' });
         | 
| 1546 | 
            -
            		this.shadowRoot.appendChild(template.content.cloneNode(true));
         | 
| 1547 | 
            -
             | 
| 1548 1681 | 
             
            		forwardAttrs(this, this.shadowRoot.querySelector('a'), {
         | 
| 1549 1682 | 
             
            			includeAttrs: ['href', 'target', 'tooltip'],
         | 
| 1550 1683 | 
             
            			mapAttrs: {
         | 
| @@ -1555,24 +1688,23 @@ class RawLink extends DescopeBaseClass { | |
| 1555 1688 | 
             
            		forwardAttrs(this, this.shadowRoot.querySelector('descope-text'), {
         | 
| 1556 1689 | 
             
            			includeAttrs: ['mode', 'variant'],
         | 
| 1557 1690 | 
             
            		});
         | 
| 1558 | 
            -
             | 
| 1559 | 
            -
            		this.baseSelector = ':host > div';
         | 
| 1560 1691 | 
             
            	}
         | 
| 1561 1692 | 
             
            }
         | 
| 1562 1693 |  | 
| 1563 1694 | 
             
            const selectors$2 = {
         | 
| 1564 1695 | 
             
            	host: { selector: () => 'host' },
         | 
| 1565 | 
            -
            	anchor: { | 
| 1566 | 
            -
            	 | 
| 1696 | 
            +
            	anchor: {},
         | 
| 1697 | 
            +
            	wrapper: {selector: () => ':host > div'},
         | 
| 1698 | 
            +
            	text: { selector: () => Text.componentName }
         | 
| 1567 1699 | 
             
            };
         | 
| 1568 1700 |  | 
| 1569 | 
            -
            const { anchor, text: text$1, host } = selectors$2;
         | 
| 1701 | 
            +
            const { anchor, text: text$1, host, wrapper } = selectors$2;
         | 
| 1570 1702 |  | 
| 1571 1703 | 
             
            const Link = compose(
         | 
| 1572 1704 | 
             
            	createStyleMixin({
         | 
| 1573 1705 | 
             
            		mappings: {
         | 
| 1574 1706 | 
             
            			width: host,
         | 
| 1575 | 
            -
            			textAlign:  | 
| 1707 | 
            +
            			textAlign: wrapper,
         | 
| 1576 1708 | 
             
            			color: [anchor, { ...text$1, property: Text.cssVarList.color }],
         | 
| 1577 1709 | 
             
            			cursor: anchor,
         | 
| 1578 1710 | 
             
            			borderBottomWidth: anchor,
         | 
| @@ -1580,7 +1712,6 @@ const Link = compose( | |
| 1580 1712 | 
             
            			borderBottomColor: anchor
         | 
| 1581 1713 | 
             
            		},
         | 
| 1582 1714 | 
             
            	}),
         | 
| 1583 | 
            -
            	hoverableMixin(anchor.selector),
         | 
| 1584 1715 | 
             
            	draggableMixin,
         | 
| 1585 1716 | 
             
            	componentNameValidationMixin
         | 
| 1586 1717 | 
             
            )(RawLink);
         | 
| @@ -1592,23 +1723,15 @@ const componentName$8 = getComponentName('logo'); | |
| 1592 1723 | 
             
            let style;
         | 
| 1593 1724 | 
             
            const getStyle = () => style;
         | 
| 1594 1725 |  | 
| 1595 | 
            -
            class RawLogo extends  | 
| 1596 | 
            -
            	static get componentName() {
         | 
| 1597 | 
            -
            		return componentName$8;
         | 
| 1598 | 
            -
            	}
         | 
| 1726 | 
            +
            class RawLogo extends createBaseClass({ componentName: componentName$8, baseSelector: ':host > div' }) {
         | 
| 1599 1727 | 
             
            	constructor() {
         | 
| 1600 1728 | 
             
            		super();
         | 
| 1601 | 
            -
             | 
| 1602 | 
            -
            		 | 
| 1729 | 
            +
             | 
| 1730 | 
            +
            		this.attachShadow({ mode: 'open' }).innerHTML = `
         | 
| 1603 1731 | 
             
            		<style>
         | 
| 1604 1732 | 
             
            			${getStyle()}
         | 
| 1605 1733 | 
             
            		</style>
         | 
| 1606 1734 | 
             
            		<div></div>`;
         | 
| 1607 | 
            -
             | 
| 1608 | 
            -
            		this.attachShadow({ mode: 'open' });
         | 
| 1609 | 
            -
            		this.shadowRoot.appendChild(template.content.cloneNode(true));
         | 
| 1610 | 
            -
             | 
| 1611 | 
            -
            		this.baseSelector = ':host > div';
         | 
| 1612 1735 | 
             
            	}
         | 
| 1613 1736 | 
             
            }
         | 
| 1614 1737 |  | 
| @@ -1702,7 +1825,7 @@ overrides$4 = ` | |
| 1702 1825 |  | 
| 1703 1826 | 
             
            customElements.define(componentName$7, NumberField);
         | 
| 1704 1827 |  | 
| 1705 | 
            -
            var BaseInputClass =  | 
| 1828 | 
            +
            var BaseInputClass = compose(focusMixin, inputValidationMixin, changeMixin)(HTMLElement); //todo: maybe we should use base class?
         | 
| 1706 1829 |  | 
| 1707 1830 | 
             
            const focusElement = (ele) => {
         | 
| 1708 1831 | 
             
            	ele?.focus();
         | 
| @@ -1723,11 +1846,10 @@ const componentName$6 = getComponentName('passcode-internal'); | |
| 1723 1846 | 
             
            class PasscodeInternal extends BaseInputClass {
         | 
| 1724 1847 | 
             
            	static get observedAttributes() {
         | 
| 1725 1848 | 
             
            		return [
         | 
| 1726 | 
            -
            			...BaseInputClass.observedAttributes,
         | 
| 1849 | 
            +
            			...(BaseInputClass.observedAttributes || []),
         | 
| 1727 1850 | 
             
            			'disabled',
         | 
| 1728 1851 | 
             
            			'bordered',
         | 
| 1729 1852 | 
             
            			'size',
         | 
| 1730 | 
            -
            			'readonly'
         | 
| 1731 1853 | 
             
            		];
         | 
| 1732 1854 | 
             
            	}
         | 
| 1733 1855 |  | 
| @@ -1735,10 +1857,12 @@ class PasscodeInternal extends BaseInputClass { | |
| 1735 1857 | 
             
            		return componentName$6;
         | 
| 1736 1858 | 
             
            	}
         | 
| 1737 1859 |  | 
| 1860 | 
            +
            	#boundHandleInvalid = this.#handleInvalid.bind(this)
         | 
| 1861 | 
            +
            	#boundHandleValid = this.#handleValid.bind(this)
         | 
| 1862 | 
            +
            	#boundHandleBlur = this.#handleBlur.bind(this)
         | 
| 1863 | 
            +
             | 
| 1738 1864 | 
             
            	constructor() {
         | 
| 1739 1865 | 
             
            		super();
         | 
| 1740 | 
            -
            		const template = document.createElement('template');
         | 
| 1741 | 
            -
             | 
| 1742 1866 | 
             
            		const inputs = [...Array(this.digits).keys()].map((idx) => `
         | 
| 1743 1867 | 
             
            		<descope-text-field
         | 
| 1744 1868 | 
             
            			st-width="35px"
         | 
| @@ -1748,14 +1872,12 @@ class PasscodeInternal extends BaseInputClass { | |
| 1748 1872 | 
             
            		></descope-text-field>
         | 
| 1749 1873 | 
             
            	`);
         | 
| 1750 1874 |  | 
| 1751 | 
            -
            		 | 
| 1875 | 
            +
            		this.innerHTML = `
         | 
| 1752 1876 | 
             
            		<div>
         | 
| 1753 1877 | 
             
            			${inputs.join('')}
         | 
| 1754 1878 | 
             
            		</div>
         | 
| 1755 1879 | 
             
            		`;
         | 
| 1756 1880 |  | 
| 1757 | 
            -
            		this.appendChild(template.content.cloneNode(true));
         | 
| 1758 | 
            -
             | 
| 1759 1881 | 
             
            		this.baseSelector = ':host > div';
         | 
| 1760 1882 |  | 
| 1761 1883 | 
             
            		this.inputs = Array.from(this.querySelectorAll('descope-text-field'));
         | 
| @@ -1783,15 +1905,13 @@ class PasscodeInternal extends BaseInputClass { | |
| 1783 1905 | 
             
            		return `^$|^\\d{${this.digits},}$`
         | 
| 1784 1906 | 
             
            	}
         | 
| 1785 1907 |  | 
| 1786 | 
            -
            	 | 
| 1787 | 
            -
            		 | 
| 1788 | 
            -
            			 | 
| 1789 | 
            -
             | 
| 1790 | 
            -
            			}
         | 
| 1791 | 
            -
            		});
         | 
| 1908 | 
            +
            	#handleInvalid() {
         | 
| 1909 | 
            +
            		if (this.hasAttribute('invalid')) {
         | 
| 1910 | 
            +
            			this.inputs.forEach(input => input.setAttribute('invalid', 'true'));
         | 
| 1911 | 
            +
            		}
         | 
| 1792 1912 | 
             
            	}
         | 
| 1793 1913 |  | 
| 1794 | 
            -
            	 | 
| 1914 | 
            +
            	#handleValid() {
         | 
| 1795 1915 | 
             
            		this.inputs.forEach(input => input.removeAttribute('invalid'));
         | 
| 1796 1916 | 
             
            	}
         | 
| 1797 1917 |  | 
| @@ -1807,17 +1927,25 @@ class PasscodeInternal extends BaseInputClass { | |
| 1807 1927 | 
             
            		}
         | 
| 1808 1928 | 
             
            	};
         | 
| 1809 1929 |  | 
| 1810 | 
            -
            	 | 
| 1930 | 
            +
            	onFocus(){
         | 
| 1811 1931 | 
             
            		this.inputs[0].focus();
         | 
| 1812 1932 | 
             
            	}
         | 
| 1813 1933 |  | 
| 1814 | 
            -
            	 | 
| 1815 | 
            -
            		super.connectedCallback();
         | 
| 1934 | 
            +
            	connectedCallback() {
         | 
| 1935 | 
            +
            		super.connectedCallback?.();
         | 
| 1816 1936 |  | 
| 1817 1937 | 
             
            		this.initInputs();
         | 
| 1818 1938 |  | 
| 1819 | 
            -
            		this.addEventListener('invalid', this | 
| 1820 | 
            -
            		this.addEventListener('valid', this | 
| 1939 | 
            +
            		this.addEventListener('invalid', this.#boundHandleInvalid);
         | 
| 1940 | 
            +
            		this.addEventListener('valid', this.#boundHandleValid);
         | 
| 1941 | 
            +
            		this.addEventListener('blur', this.#boundHandleBlur);
         | 
| 1942 | 
            +
            	}
         | 
| 1943 | 
            +
             | 
| 1944 | 
            +
            	disconnectedCallback() {
         | 
| 1945 | 
            +
            		super.connectedCallback?.();
         | 
| 1946 | 
            +
            		this.removeEventListener('invalid', this.#boundHandleInvalid);
         | 
| 1947 | 
            +
            		this.removeEventListener('valid', this.#boundHandleValid);
         | 
| 1948 | 
            +
            		this.removeEventListener('blur', this.#boundHandleBlur);
         | 
| 1821 1949 | 
             
            	}
         | 
| 1822 1950 |  | 
| 1823 1951 | 
             
            	getInputIdx(inputEle) {
         | 
| @@ -1841,66 +1969,49 @@ class PasscodeInternal extends BaseInputClass { | |
| 1841 1969 | 
             
            			currentInput.value = charArr[i] ?? '';
         | 
| 1842 1970 |  | 
| 1843 1971 | 
             
            			const nextInput = this.getNextInput(currentInput);
         | 
| 1972 | 
            +
             | 
| 1844 1973 | 
             
            			if (nextInput === currentInput) break;
         | 
| 1845 1974 | 
             
            			currentInput = nextInput;
         | 
| 1846 1975 | 
             
            		}
         | 
| 1847 1976 |  | 
| 1848 | 
            -
            		 | 
| 1977 | 
            +
            		focusElement(currentInput);
         | 
| 1849 1978 | 
             
            	};
         | 
| 1850 1979 |  | 
| 1851 | 
            -
            	handleBlur() {
         | 
| 1852 | 
            -
            		this | 
| 1980 | 
            +
            	#handleBlur() {
         | 
| 1981 | 
            +
            		this.#handleInvalid();
         | 
| 1853 1982 | 
             
            	}
         | 
| 1854 1983 |  | 
| 1855 1984 | 
             
            	initInputs() {
         | 
| 1856 1985 | 
             
            		this.inputs.forEach((input) => {
         | 
| 1857 | 
            -
             | 
| 1858 | 
            -
            			// in order to simulate blur on the input
         | 
| 1859 | 
            -
            			// we are checking if focus on one of the digits happened immediately after blur on another digit
         | 
| 1860 | 
            -
            			// if not, the component is no longer focused and we should simulate blur
         | 
| 1861 | 
            -
            			input.addEventListener('blur', (e) => {
         | 
| 1862 | 
            -
            				e.stopPropagation();
         | 
| 1863 | 
            -
            				const timerId = setTimeout(() => {
         | 
| 1864 | 
            -
            					this.dispatchBlur();
         | 
| 1865 | 
            -
            				});
         | 
| 1866 | 
            -
             | 
| 1867 | 
            -
            				this.inputs.forEach((ele) =>
         | 
| 1868 | 
            -
            					ele.addEventListener('focus', () => clearTimeout(timerId), { once: true })
         | 
| 1869 | 
            -
            				);
         | 
| 1870 | 
            -
            			});
         | 
| 1871 | 
            -
             | 
| 1872 1986 | 
             
            			input.oninput = (e) => {
         | 
| 1873 | 
            -
            				e.stopPropagation();
         | 
| 1874 1987 | 
             
            				const charArr = getSanitizedCharacters(input.value);
         | 
| 1875 1988 |  | 
| 1876 | 
            -
            				if (!charArr.length)  | 
| 1989 | 
            +
            				if (!charArr.length) {
         | 
| 1990 | 
            +
            					// if we got an invalid value we want to clear the input
         | 
| 1991 | 
            +
            					input.value = '';
         | 
| 1992 | 
            +
            					if (e.data === null) {
         | 
| 1993 | 
            +
            						// if the user deleted the char, we want to focus the prev digit
         | 
| 1994 | 
            +
            						focusElement(this.getPrevInput(input));
         | 
| 1995 | 
            +
            					}
         | 
| 1996 | 
            +
            				}
         | 
| 1877 1997 | 
             
            				else this.fillDigits(charArr, input);
         | 
| 1878 | 
            -
             | 
| 1879 | 
            -
            				this.dispatchInput();
         | 
| 1880 1998 | 
             
            			};
         | 
| 1881 1999 |  | 
| 1882 2000 | 
             
            			input.onkeydown = ({ key }) => {
         | 
| 2001 | 
            +
            				// when user deletes a digit, we want to focus the previous digit
         | 
| 1883 2002 | 
             
            				if (key === 'Backspace') {
         | 
| 1884 | 
            -
            					 | 
| 1885 | 
            -
             | 
| 1886 | 
            -
            					// if the user deleted the digit we want to focus the previous digit
         | 
| 1887 | 
            -
            					const prevInput = this.getPrevInput(input);
         | 
| 1888 | 
            -
             | 
| 1889 | 
            -
            					!prevInput.hasAttribute('focused') && setTimeout(() => {
         | 
| 1890 | 
            -
            						focusElement(prevInput);
         | 
| 2003 | 
            +
            					setTimeout(() => {
         | 
| 2004 | 
            +
            						focusElement(this.getPrevInput(input));
         | 
| 1891 2005 | 
             
            					});
         | 
| 1892 | 
            -
             | 
| 1893 | 
            -
            					this.dispatchInput();
         | 
| 1894 2006 | 
             
            				} else if (key.match(/^(\d)$/g)) { // if input is a digit
         | 
| 1895 2007 | 
             
            					input.value = ''; // we are clearing the previous value so we can override it with the new value
         | 
| 1896 2008 | 
             
            				}
         | 
| 1897 | 
            -
             | 
| 1898 2009 | 
             
            			};
         | 
| 1899 2010 | 
             
            		});
         | 
| 1900 2011 | 
             
            	}
         | 
| 1901 2012 |  | 
| 1902 2013 | 
             
            	attributeChangedCallback(attrName, oldValue, newValue) {
         | 
| 1903 | 
            -
            		super.attributeChangedCallback(attrName, oldValue, newValue);
         | 
| 2014 | 
            +
            		super.attributeChangedCallback?.(attrName, oldValue, newValue);
         | 
| 1904 2015 |  | 
| 1905 2016 | 
             
            		if (oldValue !== newValue) {
         | 
| 1906 2017 | 
             
            			if (PasscodeInternal.observedAttributes.includes(attrName) && !BaseInputClass.observedAttributes.includes(attrName)) {
         | 
| @@ -1999,21 +2110,10 @@ const customMixin = (superclass) => | |
| 1999 2110 |  | 
| 2000 2111 | 
             
            			this.proxyElement.appendChild(template.content.cloneNode(true));
         | 
| 2001 2112 |  | 
| 2002 | 
            -
            			// we want to control when the element is out of focus
         | 
| 2003 | 
            -
            			// so the validations will be triggered blur event is dispatched from descope-passcode internal (and not every time focusing a digit)
         | 
| 2004 | 
            -
            			this.proxyElement._setFocused = () => { };
         | 
| 2005 | 
            -
             | 
| 2006 2113 | 
             
            			this.inputElement = this.shadowRoot.querySelector(componentName$6);
         | 
| 2007 2114 |  | 
| 2008 2115 | 
             
            			forwardAttrs(this.shadowRoot.host, this.inputElement, { includeAttrs: ['required', 'pattern'] });
         | 
| 2009 2116 |  | 
| 2010 | 
            -
            			// we want to trigger validation only when dispatching a blur event from the descope-passcode-internal
         | 
| 2011 | 
            -
            			this.inputElement.addEventListener('blur', (e) => {
         | 
| 2012 | 
            -
            				// we do not want native blur events, only the ones that we are sending
         | 
| 2013 | 
            -
            				if (!e.isTrusted){
         | 
| 2014 | 
            -
            					this.proxyElement.validate();
         | 
| 2015 | 
            -
            				}
         | 
| 2016 | 
            -
            			});
         | 
| 2017 2117 | 
             
            		}
         | 
| 2018 2118 | 
             
            	};
         | 
| 2019 2119 |  | 
| @@ -2050,6 +2150,10 @@ const Passcode = compose( | |
| 2050 2150 | 
             
            			display: inline-block;
         | 
| 2051 2151 | 
             
                }
         | 
| 2052 2152 |  | 
| 2153 | 
            +
            		:host([readonly]) descope-passcode-internal > div {
         | 
| 2154 | 
            +
            			pointer-events: none;
         | 
| 2155 | 
            +
            		}
         | 
| 2156 | 
            +
             | 
| 2053 2157 | 
             
                descope-passcode-internal {
         | 
| 2054 2158 | 
             
                  -webkit-mask-image: none;
         | 
| 2055 2159 | 
             
                  display: flex;
         |