@descope/web-components-ui 1.0.67 → 1.0.68
Sign up to get free protection for your applications and to get access to all the features.
- 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.hasAttribute('readonly') && 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
1309
|
|
1159
|
-
this.attachShadow({ mode: 'open' })
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
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
|
-
|
1216
|
-
this.attachShadow({ mode: 'open' });
|
1217
|
-
this.shadowRoot.appendChild(template.content.cloneNode(true));
|
1218
1359
|
|
1219
|
-
this.
|
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;
|