@descope/web-components-ui 1.0.60 → 1.0.62

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. package/dist/cjs/index.cjs.js.map +1 -1
  2. package/dist/index.esm.js +395 -185
  3. package/dist/index.esm.js.map +1 -1
  4. package/dist/umd/442.js +1 -0
  5. package/dist/umd/942.js +1 -1
  6. package/dist/umd/descope-button-index-js.js +1 -1
  7. package/dist/umd/descope-checkbox-index-js.js +1 -1
  8. package/dist/umd/descope-combo-index-js.js +1 -1
  9. package/dist/umd/descope-container-index-js.js +1 -1
  10. package/dist/umd/descope-date-picker-index-js.js +1 -1
  11. package/dist/umd/descope-divider-index-js.js +1 -1
  12. package/dist/umd/descope-email-field-index-js.js +1 -1
  13. package/dist/umd/descope-link-index-js.js +1 -1
  14. package/dist/umd/descope-loader-linear-index-js.js +1 -1
  15. package/dist/umd/descope-loader-radial-index-js.js +1 -1
  16. package/dist/umd/descope-logo-index-js.js +1 -1
  17. package/dist/umd/descope-number-field-index-js.js +1 -1
  18. package/dist/umd/descope-passcode-descope-passcode-internal-index-js.js +1 -1
  19. package/dist/umd/descope-passcode-index-js.js +1 -1
  20. package/dist/umd/descope-password-field-index-js.js +1 -1
  21. package/dist/umd/descope-switch-toggle-index-js.js +1 -1
  22. package/dist/umd/descope-text-area-index-js.js +1 -1
  23. package/dist/umd/descope-text-field-index-js.js +1 -1
  24. package/dist/umd/descope-text-index-js.js +1 -1
  25. package/dist/umd/index.js +1 -1
  26. package/package.json +1 -1
  27. package/src/baseClasses/BaseInputClass.js +3 -0
  28. package/src/components/descope-checkbox/Checkbox.js +2 -2
  29. package/src/components/descope-combo/index.js +1 -1
  30. package/src/components/descope-container/Container.js +1 -1
  31. package/src/components/descope-divider/Divider.js +1 -1
  32. package/src/components/descope-email-field/EmailField.js +2 -2
  33. package/src/components/descope-link/Link.js +1 -1
  34. package/src/components/descope-loader-linear/LoaderLinear.js +1 -1
  35. package/src/components/descope-loader-radial/LoaderRadial.js +1 -1
  36. package/src/components/descope-logo/Logo.js +1 -1
  37. package/src/components/descope-number-field/NumberField.js +2 -2
  38. package/src/components/descope-passcode/Passcode.js +2 -2
  39. package/src/components/descope-passcode/descope-passcode-internal/PasscodeInternal.js +42 -70
  40. package/src/components/descope-password-field/PasswordField.js +2 -2
  41. package/src/components/descope-switch-toggle/SwitchToggle.js +2 -2
  42. package/src/components/descope-text/Text.js +1 -1
  43. package/src/components/descope-text-area/TextArea.js +2 -2
  44. package/src/components/descope-text-field/TextField.js +2 -2
  45. package/src/componentsHelpers/compose.js +3 -0
  46. package/src/componentsHelpers/createProxy/index.js +2 -2
  47. package/src/componentsHelpers/enforceNestingElementsStylesMixin.js +67 -59
  48. package/src/componentsHelpers/index.js +2 -6
  49. package/src/componentsHelpers/inputMixin.js +173 -94
  50. package/src/componentsHelpers/proxyInputMixin.js +152 -0
  51. package/src/theme/components/textField.js +1 -1
  52. package/dist/umd/832.js +0 -1
  53. /package/src/{components → baseClasses}/DescopeBaseClass.js +0 -0
package/dist/index.esm.js CHANGED
@@ -256,6 +256,10 @@ const draggableMixin = (superclass) =>
256
256
  }
257
257
  };
258
258
 
259
+ var compose = (...fns) =>
260
+ (val) =>
261
+ fns.reduceRight((res, fn) => fn(res), val);
262
+
259
263
  class DescopeBaseClass extends HTMLElement {}
260
264
 
261
265
  const hoverableMixin =
@@ -438,9 +442,177 @@ const createProxy = ({
438
442
  return compose(hoverableMixin())(ProxyElement);
439
443
  };
440
444
 
441
- const attrs = {
442
- valueMissing: 'data-errormessage-value-missing',
443
- patternMismatch: 'data-errormessage-pattern-mismatch'
445
+ const upperFirst = (str) => str.charAt(0).toUpperCase() + str.slice(1);
446
+
447
+ const events = [
448
+ 'change',
449
+ 'input',
450
+ 'blur',
451
+ 'focus',
452
+ 'invalid',
453
+ 'valid',
454
+ ];
455
+
456
+ const observedAttributes = [
457
+ 'required',
458
+ 'pattern',
459
+ ];
460
+
461
+ const errorAttributes = {
462
+ valueMissing: 'data-errormessage-value-missing',
463
+ patternMismatch: 'data-errormessage-pattern-mismatch'
464
+ };
465
+ const inputMixin = (superclass) => class InputMixinClass extends superclass {
466
+ static get observedAttributes() {
467
+ return [
468
+ ...superclass.observedAttributes || [],
469
+ ...observedAttributes
470
+ ];
471
+ }
472
+
473
+ static get formAssociated() {
474
+ return true;
475
+ }
476
+
477
+ #internals
478
+
479
+ constructor() {
480
+ super();
481
+
482
+ this.#internals = this.attachInternals();
483
+
484
+ for (const event of events) {
485
+ this[`dispatch${upperFirst(event)}`] = function () {
486
+ this.dispatchInputEvent(event);
487
+ };
488
+ }
489
+ }
490
+
491
+ get defaultErrorMsgValueMissing() {
492
+ return 'Please fill out this field.'
493
+ }
494
+
495
+ get defaultErrorMsgPatternMismatch() {
496
+ return 'Please match the requested format.'
497
+ }
498
+
499
+ getErrorMessage(flags) {
500
+ switch (true) {
501
+ case flags.valueMissing:
502
+ return this.getAttribute(errorAttributes.valueMissing) ||
503
+ this.defaultErrorMsgValueMissing
504
+ case flags.patternMismatch || flags.typeMismatch:
505
+ return this.getAttribute(errorAttributes.patternMismatch) ||
506
+ this.defaultErrorMsgPatternMismatch
507
+ case flags.customError:
508
+ return this.validationMessage
509
+ default:
510
+ return ''
511
+ }
512
+ }
513
+
514
+ setValidity() {
515
+ const validity = this.getValidity();
516
+ this.#internals.setValidity(validity, this.getErrorMessage(validity));
517
+ }
518
+
519
+ get validationMessage() {
520
+ return this.#internals.validationMessage;
521
+ }
522
+
523
+ getValidity() {
524
+ throw Error('getValidity', 'is not implemented')
525
+ }
526
+
527
+ checkValidity() {
528
+ return this.#internals.validity.valid
529
+ }
530
+
531
+ reportValidity() {
532
+ return this.#internals.reportValidity()
533
+ }
534
+
535
+ get validity() {
536
+ return this.#internals.validity
537
+ }
538
+
539
+ setCustomValidity(errorMessage) {
540
+ if(errorMessage){
541
+ this.#internals.setValidity({customError: true}, errorMessage);
542
+ } else {
543
+ this.#internals.setValidity({});
544
+ this.setValidity();
545
+ }
546
+ }
547
+
548
+ get isRequired() {
549
+ return this.hasAttribute('required') && this.getAttribute('required') !== 'false'
550
+ }
551
+
552
+ get pattern() {
553
+ return this.getAttribute('pattern')
554
+ }
555
+
556
+ get value() {
557
+ throw Error('get value', 'is not implemented')
558
+ }
559
+
560
+ set value(value) {
561
+ throw Error('set value', 'is not implemented')
562
+ }
563
+
564
+ handleFocus() {
565
+ throw Error('handleFocus', 'is not implemented')
566
+ }
567
+
568
+ handleInput() {
569
+ this.setValidity();
570
+ this.handleDispatchValidationEvents();
571
+ }
572
+
573
+ handleBlur() {
574
+ throw Error('handleBlur', 'is not implemented')
575
+ }
576
+
577
+ handleChange() {
578
+ throw Error('handleChange', 'is not implemented')
579
+ }
580
+
581
+ dispatchInputEvent(eventName) {
582
+ this[`on${eventName}`]?.(); // in case we got an event callback as property
583
+ this.dispatchEvent(new InputEvent(eventName));
584
+ }
585
+
586
+ attributeChangedCallback(attrName, oldValue, newValue) {
587
+ super.attributeChangedCallback?.(attrName, oldValue, newValue);
588
+
589
+ if (observedAttributes.includes(attrName)) {
590
+ this.setValidity();
591
+ }
592
+ }
593
+
594
+ handleDispatchValidationEvents(){
595
+ if(this.checkValidity()) {
596
+ this.dispatchValid();
597
+ } else {
598
+ this.dispatchInvalid();
599
+ }
600
+ }
601
+
602
+ connectedCallback() {
603
+ super.connectedCallback?.();
604
+
605
+ this.setValidity();
606
+ this.handleDispatchValidationEvents();
607
+
608
+ // create proxy replace the addEventListener fn
609
+ // and we want to be able to access the focus events
610
+ // of this element and not the nested element's events
611
+ this.onfocus = this.handleFocus.bind(this);
612
+ this.addEventListener('input', this.handleInput.bind(this));
613
+ this.addEventListener('blur', this.handleBlur.bind(this));
614
+ this.addEventListener('change', this.handleBlur.bind(this));
615
+ }
444
616
  };
445
617
 
446
618
  const errorAttrs = ['invalid', 'has-error-message'];
@@ -457,79 +629,140 @@ const propertyObserver = (src, target, property) => {
457
629
  });
458
630
  };
459
631
 
460
- const inputMixin = (superclass) =>
461
- class InputMixinClass extends superclass {
462
- static get formAssociated() {
463
- return true;
632
+ // recursively take the first slot child until it finds an element which is not a slot
633
+ // stops after "nestingLevel" times
634
+ const getNestedInput = (ele) => {
635
+ if (!ele) return;
636
+
637
+ const nestingLevel = 10;
638
+
639
+ let nonSlotEle = ele;
640
+ for (let i = 0; i < nestingLevel; i++) {
641
+ nonSlotEle = nonSlotEle.assignedElements()[0];
642
+ if (nonSlotEle.localName !== 'slot') return nonSlotEle
643
+ }
644
+ };
645
+
646
+ const proxyInputMixin = (superclass) =>
647
+ class proxyInputMixinClass extends inputMixin(superclass) {
648
+ static get observedAttributes() {
649
+ return [...superclass.observedAttributes || [], ...errorAttrs];
464
650
  }
465
651
 
466
- #internals;
652
+ #inputElement
467
653
 
468
654
  constructor() {
469
655
  super();
470
656
 
471
- this.#internals = this.attachInternals();
657
+ this.#inputElement = super.inputElement;
658
+
659
+ // this is our way to identify that the form was submitted
660
+ // in this case, we want the input to be in error state if it's not valid
661
+ this.addEventListener('focus', (e) => {
662
+ if (e.relatedTarget?.form) {
663
+ if (!this.checkValidity()) {
664
+ this.setAttribute('invalid', 'true');
665
+ }
666
+
667
+ if (this.hasAttribute('invalid')) {
668
+ this.reportValidityOnInternalInput();
669
+ }
670
+ }
671
+ });
672
+
673
+ this.addEventListener('invalid', () => {
674
+ this.setInternalInputErrorMessage();
675
+ this.setAttribute('error-message', this.validationMessage);
676
+ });
677
+
678
+ this.addEventListener('valid', () => {
679
+ this.removeAttribute('invalid');
680
+ });
681
+ }
682
+
683
+ get inputElement() {
684
+ const inputSlot = this.baseEle.shadowRoot.querySelector('slot[name="input"]');
685
+ const textAreaSlot = this.baseEle.shadowRoot.querySelector('slot[name="textarea"]');
686
+
687
+ this.#inputElement ??= getNestedInput(inputSlot) || getNestedInput(textAreaSlot);
688
+
689
+ if (!this.#inputElement) throw Error('no input was found');
690
+
691
+ return this.#inputElement
692
+ }
693
+
694
+ set inputElement(ele) {
695
+ this.#inputElement = ele;
696
+ }
697
+
698
+ getValidity() {
699
+ return this.inputElement.validity
472
700
  }
473
701
 
474
- formAssociatedCallback() {
475
- this.setValidity?.();
702
+ reportValidityOnInternalInput() {
703
+ setTimeout(() => {
704
+ this.inputElement.reportValidity();
705
+ }, 0);
476
706
  }
477
707
 
478
- setValidationAttribute(attr) {
479
- const validationAttr = this.getAttribute(attr);
480
- if (validationAttr) {
481
- this.proxyElement.setAttribute('error-message', validationAttr);
708
+ handleBlur() { }
709
+
710
+ handleFocus() {
711
+ this.inputElement.focus();
712
+ if (this.hasAttribute('invalid')) {
713
+ this.reportValidityOnInternalInput();
482
714
  }
483
- // normalize vaadin error attributes to have a boolean value
484
- errorAttrs.forEach((att) => this.proxyElement.setAttribute(att, 'true'));
485
715
  }
486
716
 
487
- validate() {
488
- const { valueMissing, patternMismatch, typeMismatch } = this.validity;
489
- if (valueMissing) {
490
- this.setValidationAttribute(attrs.valueMissing);
491
- } else if (typeMismatch || patternMismatch) {
492
- this.setValidationAttribute(attrs.patternMismatch);
717
+ // we want reportValidity to behave like form submission
718
+ reportValidity() {
719
+ const isValid = super.reportValidity();
720
+ if (!isValid) {
721
+ this.setAttribute('invalid', 'true');
722
+ this.inputElement.focus();
723
+ }
724
+ this.reportValidityOnInternalInput();
725
+ }
726
+
727
+ setInternalInputErrorMessage() {
728
+ if (!this.checkValidity()) {
729
+ this.inputElement.setCustomValidity(this.validationMessage);
493
730
  }
494
731
  }
495
732
 
496
733
  connectedCallback() {
734
+ this.baseEle = this.shadowRoot.querySelector(this.baseSelector);
735
+
497
736
  super.connectedCallback?.();
498
737
 
499
- this.baseEle = this.shadowRoot.querySelector(this.baseSelector);
738
+ this.inputElement.addEventListener('input', () => {
739
+ this.inputElement.setCustomValidity('');
740
+ if (!this.inputElement.checkValidity())
741
+ this.setInternalInputErrorMessage();
742
+ });
743
+
744
+ this.inputElement.addEventListener('invalid', () => {
745
+ this.setValidity();
746
+ this.setInternalInputErrorMessage();
747
+ this.setAttribute('error-message', this.validationMessage);
748
+ });
500
749
 
501
750
  // this is needed in order to make sure the form input validation is working
502
751
  if (!this.hasAttribute('tabindex')) {
503
752
  this.setAttribute('tabindex', 0);
504
753
  }
505
754
 
506
- this.inputElement ??= this.baseEle.shadowRoot.querySelector('slot[name="input"]')?.assignedElements()[0] ||
507
- this.baseEle.shadowRoot.querySelector('slot[name="textarea"]')?.assignedElements()[0];
508
- if (!this.inputElement) throw Error('no input was found');
509
-
510
755
  // sync properties
511
756
  propertyObserver(this, this.inputElement, 'value');
512
757
  this.setSelectionRange = this.inputElement.setSelectionRange?.bind(this.inputElement);
758
+ }
513
759
 
514
- this.validity = this.inputElement.validity;
515
-
516
- this.setValidity = () => {
517
- this.#internals.setValidity(this.inputElement.validity, this.inputElement.validationMessage);
518
- };
519
-
520
- this.inputElement.oninput = () => {
521
- this.value = this.inputElement.value;
522
- this.setValidity();
523
- };
524
-
525
- this.onfocus = () => {
526
- setTimeout(() => this.inputElement.reportValidity(), 0);
527
- this.validate();
528
- };
760
+ attributeChangedCallback(attrName, oldValue, newValue) {
761
+ super.attributeChangedCallback?.(attrName, oldValue, newValue);
529
762
 
530
- this.inputElement.oninvalid = () => {
531
- this.validate();
532
- };
763
+ if (attrName === 'invalid' && newValue === '') {
764
+ this.setAttribute('invalid', 'true');
765
+ }
533
766
  }
534
767
  };
535
768
 
@@ -561,11 +794,6 @@ const componentNameValidationMixin = (superclass) =>
561
794
 
562
795
  const getComponentName = (name) => kebabCaseJoin(DESCOPE_PREFIX, name);
563
796
 
564
- const compose =
565
- (...fns) =>
566
- (val) =>
567
- fns.reduceRight((res, fn) => fn(res), val);
568
-
569
797
  const componentName$i = getComponentName('button');
570
798
 
571
799
  const editorOverrides = `vaadin-button::part(label) { pointer-events: none; }`;
@@ -664,7 +892,7 @@ const Checkbox = compose(
664
892
  }
665
893
  }),
666
894
  draggableMixin,
667
- inputMixin,
895
+ proxyInputMixin,
668
896
  componentNameValidationMixin
669
897
  )(
670
898
  createProxy({
@@ -846,7 +1074,7 @@ const TextField = compose(
846
1074
  mappings: textFieldMappings
847
1075
  }),
848
1076
  draggableMixin,
849
- inputMixin,
1077
+ proxyInputMixin,
850
1078
  componentNameValidationMixin
851
1079
  )(
852
1080
  createProxy({
@@ -1019,65 +1247,65 @@ const insertNestingLevel = (srcEle, nestingEle) => {
1019
1247
  // to be under the nesting element
1020
1248
  const enforceNestingElementsStylesMixin =
1021
1249
  ({ nestingElementTagName, nestingElementDestSlotName, forwardAttrOptions }) =>
1022
- (superclass) => {
1023
- const getChildNodeEle = () =>
1024
- Object.assign(document.createElement(nestingElementTagName), {
1025
- slot: nestingElementDestSlotName
1026
- });
1250
+ (superclass) => {
1251
+ const getChildNodeEle = () =>
1252
+ document.createElement(nestingElementTagName, {
1253
+ slot: nestingElementDestSlotName
1254
+ });
1027
1255
 
1028
- let childObserver;
1029
-
1030
- const getObserver = () => childObserver;
1256
+ let childObserver;
1031
1257
 
1032
- return class EnforceNestingElementsStylesMixinClass extends superclass {
1033
- constructor() {
1034
- super();
1258
+ const getObserver = () => childObserver;
1035
1259
 
1036
- const childObserverCallback = () => {
1037
- // we are going to change the DOM, so we need to disconnect the observer before
1038
- // and reconnect it after the child component is added
1039
- getObserver().disconnect(this.shadowRoot.host);
1040
-
1041
- const isNestingElementExist = this.shadowRoot.host.querySelector(nestingElementTagName);
1042
- const hasNewChildren = this.shadowRoot.host.childNodes.length > 0;
1043
-
1044
- if (!isNestingElementExist && hasNewChildren) {
1045
- // if before there were no children and now there are children - insert
1046
- insertNestingLevel(this.shadowRoot.host, getChildNodeEle());
1047
- } else if (isNestingElementExist && hasNewChildren) {
1048
- // if children existed, and they changed -
1049
- // we need to update (move) the new children into
1050
- // descope-text and remove previous children
1051
- this.shadowRoot.host.querySelector(child).remove();
1052
- insertNestingLevel(this.shadowRoot.host, getChildNodeEle());
1053
- }
1054
- else if (isNestingElementExist && !hasNewChildren) {
1055
- // if children existed and now there are none -
1056
- // we need to remove descope-text completely
1057
- this.shadowRoot.host.querySelector(child).remove();
1058
- }
1260
+ let isMutating = false;
1059
1261
 
1060
- // we need a new observer, because we remove the nesting element
1061
- this.shadowRoot.host.querySelector(nestingElementTagName) &&
1062
- forwardAttrs(
1063
- this.shadowRoot.host,
1064
- this.shadowRoot.host.querySelector(nestingElementTagName),
1065
- forwardAttrOptions
1066
- );
1262
+ const filterNestingElement = (node) => node.localName !== nestingElementTagName;
1263
+ return class EnforceNestingElementsStylesMixinClass extends superclass {
1264
+ constructor() {
1265
+ super();
1067
1266
 
1068
- getObserver().observe(this.shadowRoot.host, {
1069
- childList: true
1070
- });
1071
- };
1267
+ const childObserverCallback = (mutation, observer) => {
1072
1268
 
1073
- childObserver = getChildObserver(childObserverCallback);
1074
- }
1269
+ // we are going to change the DOM, so we need to skip the upcoming mutations
1270
+ if (isMutating) return;
1075
1271
 
1076
- connectedCallback() {
1077
- super.connectedCallback?.();
1272
+ isMutating = true;
1273
+
1274
+ const { addedNodes, removedNodes } = mutation;
1275
+
1276
+ const nestingElement = this.shadowRoot.host.querySelector(nestingElementTagName);
1277
+ const hasNewChildren = Array.from(addedNodes)
1278
+ .filter(filterNestingElement)
1279
+ .length > 0;
1280
+ const hasRemovedChildren = Array.from(removedNodes)
1281
+ .filter(filterNestingElement)
1282
+ .length > 0;
1283
+
1284
+ if (!nestingElement && hasNewChildren) {
1285
+ // if before there were no children and now there are children - insert
1286
+ this.handleNestingLevelInsertion();
1287
+
1288
+ } else if (nestingElement && hasNewChildren) {
1289
+ // if children existed, and they changed -
1290
+ // we need to update (move) the new children into
1291
+ // descope-text and remove previous children
1292
+ nestingElement.replaceChildren(...addedNodes);
1293
+ }
1294
+ else if (nestingElement && !hasNewChildren && hasRemovedChildren) {
1295
+ // // if children existed and now there are none -
1296
+ // // we need to remove descope-text completely
1297
+ nestingElement.remove();
1298
+ }
1078
1299
 
1079
- if (this.shadowRoot.host.childNodes.length > 0) {
1080
- // on the first render - we want to move all component's children to be under descope-text
1300
+ setTimeout(() => {
1301
+ isMutating = false;
1302
+ });
1303
+ };
1304
+
1305
+ childObserver = getChildObserver(childObserverCallback);
1306
+ }
1307
+
1308
+ handleNestingLevelInsertion() {
1081
1309
  insertNestingLevel(this.shadowRoot.host, getChildNodeEle());
1082
1310
 
1083
1311
  forwardAttrs(
@@ -1087,12 +1315,20 @@ const enforceNestingElementsStylesMixin =
1087
1315
  );
1088
1316
  }
1089
1317
 
1090
- getObserver().observe(this.shadowRoot.host, {
1091
- childList: true
1092
- });
1093
- }
1318
+ connectedCallback() {
1319
+ super.connectedCallback?.();
1320
+
1321
+ if (this.shadowRoot.host.childNodes.length > 0) {
1322
+ // on the first render - we want to move all component's children to be under descope-text
1323
+ this.handleNestingLevelInsertion();
1324
+ }
1325
+
1326
+ getObserver().observe(this.shadowRoot.host, {
1327
+ childList: true
1328
+ });
1329
+ }
1330
+ };
1094
1331
  };
1095
- };
1096
1332
 
1097
1333
  const componentName$a = getComponentName('text');
1098
1334
 
@@ -1230,7 +1466,7 @@ const EmailField = compose(
1230
1466
  }
1231
1467
  }),
1232
1468
  draggableMixin,
1233
- inputMixin,
1469
+ proxyInputMixin,
1234
1470
  componentNameValidationMixin
1235
1471
  )(
1236
1472
  createProxy({
@@ -1422,7 +1658,7 @@ const NumberField = compose(
1422
1658
  }
1423
1659
  }),
1424
1660
  draggableMixin,
1425
- inputMixin,
1661
+ proxyInputMixin,
1426
1662
  componentNameValidationMixin
1427
1663
  )(
1428
1664
  createProxy({
@@ -1476,6 +1712,8 @@ overrides$4 = `
1476
1712
 
1477
1713
  customElements.define(componentName$5, NumberField);
1478
1714
 
1715
+ var BaseInputClass = inputMixin(HTMLElement); //todo: maybe we should use base class?
1716
+
1479
1717
  const focusElement = (ele) => {
1480
1718
  ele?.focus();
1481
1719
  ele?.setSelectionRange(1, 1);
@@ -1492,14 +1730,13 @@ const getSanitizedCharacters = (str) => {
1492
1730
 
1493
1731
  const componentName$4 = getComponentName('passcode-internal');
1494
1732
 
1495
- class PasscodeInternal extends HTMLElement {
1733
+ class PasscodeInternal extends BaseInputClass {
1496
1734
  static get observedAttributes() {
1497
1735
  return [
1736
+ ...BaseInputClass.observedAttributes,
1498
1737
  'disabled',
1499
1738
  'bordered',
1500
- 'size',
1501
- 'required',
1502
- 'pattern'
1739
+ 'size'
1503
1740
  ];
1504
1741
  }
1505
1742
 
@@ -1507,12 +1744,6 @@ class PasscodeInternal extends HTMLElement {
1507
1744
  return componentName$4;
1508
1745
  }
1509
1746
 
1510
- static get formAssociated() {
1511
- return true;
1512
- }
1513
-
1514
- #internals
1515
-
1516
1747
  constructor() {
1517
1748
  super();
1518
1749
  const template = document.createElement('template');
@@ -1536,23 +1767,9 @@ class PasscodeInternal extends HTMLElement {
1536
1767
 
1537
1768
  this.baseSelector = ':host > div';
1538
1769
 
1539
- this.#internals = this.attachInternals();
1540
-
1541
1770
  this.inputs = Array.from(this.querySelectorAll('descope-text-field'));
1542
1771
  }
1543
1772
 
1544
- checkValidity() {
1545
- // we need to toggle the has-error-message so the text inside the digits will become red when there is an error
1546
- if (this.#internals.validity.valid) {
1547
- this.inputs.forEach(input => input.removeAttribute('has-error-message'));
1548
- } else {
1549
- this.inputs.forEach(input => input.setAttribute('has-error-message', 'true'));
1550
- // we need to call it so the has-error-message with have the correct format (="true")
1551
- this.oninvalid?.();
1552
- }
1553
- return this.#internals.validity.valid
1554
- }
1555
-
1556
1773
  get digits() {
1557
1774
  return Number.parseInt(this.getAttribute('digits')) || 6
1558
1775
  }
@@ -1561,59 +1778,54 @@ class PasscodeInternal extends HTMLElement {
1561
1778
  return this.inputs.map(({ value }) => value).join('')
1562
1779
  }
1563
1780
 
1564
- set value(val) { }
1781
+ set value(val) {
1782
+ if(val === this.value) return;
1783
+
1784
+ const charArr = getSanitizedCharacters(val);
1565
1785
 
1566
- get isRequired() {
1567
- return this.hasAttribute('required') && this.getAttribute('required') !== 'false'
1786
+ if (charArr.length) {
1787
+ this.fillDigits(charArr, this.inputs[0]);
1788
+ }
1568
1789
  }
1569
1790
 
1570
1791
  get pattern() {
1571
1792
  return `^$|^\\d{${this.digits},}$`
1572
1793
  }
1573
1794
 
1574
- get valueMissingErrMsg() {
1575
- return 'Please fill out this field.'
1576
- }
1577
-
1578
- get patternMismatchErrMsg() {
1579
- return `Must be a ${this.digits} digits number.`
1580
- }
1581
-
1582
- get validity() {
1583
- return this.#internals.validity;
1584
- }
1585
-
1586
- get validationMessage() {
1587
- return this.#internals.validationMessage;
1588
- }
1589
-
1590
- reportValidity() {
1591
- this.#internals.reportValidity();
1795
+ handleInputsInvalid() {
1796
+ setTimeout(() => {
1797
+ if (this.hasAttribute('invalid')) {
1798
+ this.inputs.forEach(input => input.setAttribute('invalid', 'true'));
1799
+ }
1800
+ });
1592
1801
  }
1593
1802
 
1594
- formAssociatedCallback() {
1595
- this.setValidity?.();
1803
+ handleInputsValid() {
1804
+ this.inputs.forEach(input => input.removeAttribute('invalid'));
1596
1805
  }
1597
1806
 
1598
- setValidity = () => {
1807
+ getValidity() {
1599
1808
  if (this.isRequired && !this.value) {
1600
- this.#internals.setValidity({ valueMissing: true }, this.valueMissingErrMsg);
1809
+ return { valueMissing: true };
1601
1810
  }
1602
1811
  else if (this.pattern && !new RegExp(this.pattern).test(this.value)) {
1603
- this.#internals.setValidity({ patternMismatch: true }, this.patternMismatchErrMsg);
1812
+ return { patternMismatch: true };
1604
1813
  }
1605
1814
  else {
1606
- this.#internals.setValidity({});
1815
+ return {}
1607
1816
  }
1608
1817
  };
1609
1818
 
1819
+ handleFocus() {
1820
+ this.inputs[0].focus();
1821
+ }
1822
+
1610
1823
  async connectedCallback() {
1611
- this.setValidity();
1824
+ super.connectedCallback();
1612
1825
  this.initInputs();
1613
1826
 
1614
- this.onfocus = () => {
1615
- this.inputs[0].focus();
1616
- };
1827
+ this.addEventListener('invalid', this.handleInputsInvalid);
1828
+ this.addEventListener('valid', this.handleInputsValid);
1617
1829
  }
1618
1830
 
1619
1831
  getInputIdx(inputEle) {
@@ -1644,6 +1856,10 @@ class PasscodeInternal extends HTMLElement {
1644
1856
  !currentInput.hasAttribute('focused') && focusElement(currentInput);
1645
1857
  };
1646
1858
 
1859
+ handleBlur() {
1860
+ this.handleInputsInvalid();
1861
+ }
1862
+
1647
1863
  initInputs() {
1648
1864
  this.inputs.forEach((input) => {
1649
1865
 
@@ -1652,7 +1868,7 @@ class PasscodeInternal extends HTMLElement {
1652
1868
  // if not, the component is no longer focused and we should simulate blur
1653
1869
  input.addEventListener('blur', () => {
1654
1870
  const timerId = setTimeout(() => {
1655
- this.dispatchEvent(new Event('blur'));
1871
+ this.dispatchBlur();
1656
1872
  });
1657
1873
 
1658
1874
  this.inputs.forEach((ele) =>
@@ -1660,13 +1876,13 @@ class PasscodeInternal extends HTMLElement {
1660
1876
  );
1661
1877
  });
1662
1878
 
1663
- input.oninput = (e) => {
1879
+ input.oninput = () => {
1664
1880
  const charArr = getSanitizedCharacters(input.value);
1665
1881
 
1666
1882
  if (!charArr.length) input.value = ''; // if we got an invalid value we want to clear the input
1667
1883
  else this.fillDigits(charArr, input);
1668
1884
 
1669
- this.setValidity();
1885
+ this.dispatchInput();
1670
1886
  };
1671
1887
 
1672
1888
  input.onkeydown = ({ key }) => {
@@ -1679,27 +1895,21 @@ class PasscodeInternal extends HTMLElement {
1679
1895
  !prevInput.hasAttribute('focused') && setTimeout(() => {
1680
1896
  focusElement(prevInput);
1681
1897
  });
1898
+
1899
+ this.dispatchInput();
1682
1900
  } else if (key.match(/^(\d)$/g)) { // if input is a digit
1683
1901
  input.value = ''; // we are clearing the previous value so we can override it with the new value
1684
1902
  }
1685
1903
 
1686
- this.setValidity();
1687
1904
  };
1688
1905
  });
1689
1906
  }
1690
1907
 
1691
- attributeChangedCallback(
1692
- attrName,
1693
- oldValue,
1694
- newValue
1695
- ) {
1696
- const validationRelatedAttributes = ['required', 'pattern'];
1908
+ attributeChangedCallback(attrName, oldValue, newValue) {
1909
+ super.attributeChangedCallback(attrName, oldValue, newValue);
1697
1910
 
1698
1911
  if (oldValue !== newValue) {
1699
- if (validationRelatedAttributes.includes(attrName)) {
1700
- this.setValidity();
1701
- }
1702
- else if (PasscodeInternal.observedAttributes.includes(attrName)) {
1912
+ if (PasscodeInternal.observedAttributes.includes(attrName) && !BaseInputClass.observedAttributes.includes(attrName)) {
1703
1913
  this.inputs.forEach((input) => input.setAttribute(attrName, newValue));
1704
1914
  }
1705
1915
  }
@@ -1771,7 +1981,7 @@ const Passcode = compose(
1771
1981
  }
1772
1982
  }),
1773
1983
  draggableMixin,
1774
- inputMixin,
1984
+ proxyInputMixin,
1775
1985
  componentNameValidationMixin,
1776
1986
  customMixin
1777
1987
  )(
@@ -1858,7 +2068,7 @@ const PasswordField = compose(
1858
2068
  }
1859
2069
  }),
1860
2070
  draggableMixin,
1861
- inputMixin,
2071
+ proxyInputMixin,
1862
2072
  componentNameValidationMixin
1863
2073
  )(
1864
2074
  createProxy({
@@ -1924,7 +2134,7 @@ const SwitchToggle = compose(
1924
2134
  }
1925
2135
  }),
1926
2136
  draggableMixin,
1927
- inputMixin,
2137
+ proxyInputMixin,
1928
2138
  componentNameValidationMixin
1929
2139
  )(
1930
2140
  createProxy({
@@ -2015,7 +2225,7 @@ const TextArea = compose(
2015
2225
  }
2016
2226
  }),
2017
2227
  draggableMixin,
2018
- inputMixin,
2228
+ proxyInputMixin,
2019
2229
  componentNameValidationMixin
2020
2230
  )(
2021
2231
  createProxy({
@@ -2442,7 +2652,7 @@ const textField = (vars) => ({
2442
2652
  [vars.borderColor]: globalRefs$6.colors.surface.main
2443
2653
  },
2444
2654
 
2445
- _hasErrorMessage: {
2655
+ _invalid: {
2446
2656
  [vars.borderColor]: globalRefs$6.colors.error.main,
2447
2657
  [vars.color]: globalRefs$6.colors.error.main,
2448
2658
  [vars.placeholderColor]: globalRefs$6.colors.error.light