@descope/web-components-ui 1.0.331 → 1.0.333

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/index.esm.js CHANGED
@@ -152,7 +152,7 @@ const forwardAttrs = (source, dest, options = {}) => {
152
152
  observeAttributes(source, createSyncAttrsCb(source, dest, options.mapAttrs), options);
153
153
  };
154
154
 
155
- const forwardProps = (src, target, props = []) => {
155
+ const forwardProps$1 = (src, target, props = []) => {
156
156
  if (!props.length) return;
157
157
 
158
158
  const config = props.reduce(
@@ -744,7 +744,7 @@ const createProxy = ({
744
744
  });
745
745
 
746
746
  // this is needed for components that uses props, such as combo box
747
- forwardProps(this.baseElement, this, includeForwardProps);
747
+ forwardProps$1(this.baseElement, this, includeForwardProps);
748
748
 
749
749
  syncAttrs(this.baseElement, this, {
750
750
  excludeAttrs: excludeAttrsSync,
@@ -950,13 +950,17 @@ const inputValidationMixin = (superclass) =>
950
950
 
951
951
  const errorAttrs = ['invalid', 'required'];
952
952
 
953
- const propertyObserver = (src, target, property) => {
953
+ const forwardProps = (src, targets, property) => {
954
+ const targetArr = Array.isArray(targets) ? targets : [targets];
955
+
954
956
  Object.defineProperty(src, property, {
955
957
  set(v) {
956
- target[property] = v;
958
+ targetArr.forEach((target) => {
959
+ target[property] = v;
960
+ });
957
961
  },
958
962
  get() {
959
- return target[property];
963
+ return targets[0][property];
960
964
  },
961
965
  configurable: true,
962
966
  });
@@ -980,6 +984,10 @@ const getNestedInput = (ele) => {
980
984
  const proxyInputMixin =
981
985
  ({
982
986
  proxyProps = [],
987
+ // useProxyTargets flag allows to forwardProps to other targets, other than
988
+ // `this.inputElement`. It's to be used within `external-input` components,
989
+ // if needed
990
+ useProxyTargets = false,
983
991
  // allows us to set the event that should trigger validation
984
992
  // it can be either a string or an array of strings (for multiple events)
985
993
  inputEvent = 'input',
@@ -1106,7 +1114,11 @@ const proxyInputMixin =
1106
1114
 
1107
1115
  // sync properties
1108
1116
  proxyProps.forEach((prop) => {
1109
- propertyObserver(this, this.inputElement, prop);
1117
+ const externalInput = this.querySelector('input[slot="external-input"]') || null;
1118
+ const proxyTargets = useProxyTargets
1119
+ ? [this.baseElement, externalInput].filter(Boolean)
1120
+ : [];
1121
+ forwardProps(this, [this.inputElement, ...proxyTargets], prop);
1110
1122
  });
1111
1123
 
1112
1124
  this.setSelectionRange = this.inputElement.setSelectionRange?.bind(this.inputElement);
@@ -1687,7 +1699,7 @@ const booleanFieldMixin = (superclass) =>
1687
1699
  ],
1688
1700
  });
1689
1701
 
1690
- forwardProps(this.inputElement, this, ['checked']);
1702
+ forwardProps$1(this.inputElement, this, ['checked']);
1691
1703
  syncAttrs(this, this.inputElement, { includeAttrs: ['checked'] });
1692
1704
  }
1693
1705
  };
@@ -2636,8 +2648,13 @@ const createExternalInputEle = (targetSlotName, type, autocompleteType) => {
2636
2648
  return inputEle;
2637
2649
  };
2638
2650
 
2639
- const applyExternalInputStyles = (sourceInputEle, targetInputEle, customStyle) => {
2651
+ // We apply the original input's style to the external-input.
2652
+ // Eventually, the user should interact directly with the external input.
2653
+ // We keep the original input
2654
+ const applyExternalInputStyles = (sourceInputEle, targetInputEle, labelType) => {
2640
2655
  const computedStyle = getComputedStyle(sourceInputEle);
2656
+
2657
+ // Get minimal set of computed theme properties to set on external input
2641
2658
  const height = computedStyle.getPropertyValue('height');
2642
2659
  const paddingLeft = computedStyle.getPropertyValue('padding-left');
2643
2660
  const paddingRight = computedStyle.getPropertyValue('padding-right');
@@ -2645,24 +2662,33 @@ const applyExternalInputStyles = (sourceInputEle, targetInputEle, customStyle) =
2645
2662
  const fontFamily = computedStyle.getPropertyValue('font-family');
2646
2663
  const letterSpacing = computedStyle.getPropertyValue('letter-spacing');
2647
2664
  const caretColor = computedStyle.getPropertyValue('caret-color');
2665
+
2648
2666
  const valueColor = getValueColor(sourceInputEle, computedStyle);
2649
2667
 
2650
- // set external input style (and lock it with `all: unset` and `!important` all around)
2651
- // eslint-disable-next-line no-param-reassign
2652
- targetInputEle.style = `
2653
- all: unset !important;
2654
- position: absolute !important;
2655
- background-color: transparent !important;
2656
- color: ${valueColor} !important;
2657
- height: ${height} !important;
2658
- left: ${paddingLeft} !important;
2659
- right: ${paddingRight} !important;
2660
- font-size: ${fontSize} !important;
2661
- font-family: ${fontFamily} !important;
2662
- letter-spacing: ${letterSpacing} !important;
2663
- caret-color: ${caretColor} !important;
2664
- ${customStyle || ''}
2665
- `;
2668
+ const commonThemeStyles = [
2669
+ ['all', 'unset'],
2670
+ ['position', 'absolute'],
2671
+ ['background-color', 'transparent'],
2672
+ ['height', height],
2673
+ ['left', paddingLeft],
2674
+ ['right', paddingRight],
2675
+ ['font-size', fontSize],
2676
+ ['font-family', fontFamily],
2677
+ ['letter-spacing', letterSpacing],
2678
+ ['width', `calc(100% - ${paddingLeft} - ${paddingRight}`],
2679
+ ['caret-color', caretColor], // this is for seeing caret when focusing on external input
2680
+ ['color', valueColor],
2681
+ ];
2682
+
2683
+ commonThemeStyles.forEach(([key, val]) =>
2684
+ targetInputEle.style.setProperty(key, val, 'important')
2685
+ );
2686
+
2687
+ // Handle floating label theme properties
2688
+ if (labelType === 'floating') {
2689
+ const marginBottom = computedStyle.getPropertyValue('margin-bottom');
2690
+ targetInputEle.style.setProperty('margin-bottom', marginBottom, 'important');
2691
+ }
2666
2692
  };
2667
2693
 
2668
2694
  const componentName$M = getComponentName('email-field');
@@ -2674,19 +2700,52 @@ const customMixin$a = (superclass) =>
2674
2700
 
2675
2701
  this.baseElement.setAttribute('pattern', '^[\\w\\.\\%\\+\\-]+@[\\w\\.\\-]+\\.[A-Za-z]{2,}$');
2676
2702
 
2677
- this.handleExternalInput();
2703
+ if (!this.isNoExternalInput) {
2704
+ this.externalInput = this.handleExternalInput();
2705
+
2706
+ this.addEventListener('focus', () => {
2707
+ this.externalInput.focus();
2708
+ });
2709
+ } else {
2710
+ this.setAttribute('autocomplete', this.getAutocompleteType());
2711
+ }
2678
2712
  }
2679
2713
 
2680
- handleExternalInput() {
2681
- // reset vaadin's checkValidity
2682
- this.baseElement.checkValidity = () => {};
2714
+ get isNoExternalInput() {
2715
+ return this.getAttribute('no-external-input') === 'true';
2716
+ }
2717
+
2718
+ forwardInputValue(source, target) {
2719
+ // set internal sync events
2720
+ const valueDescriptor = Object.getOwnPropertyDescriptor(
2721
+ this.inputElement.constructor.prototype,
2722
+ 'value'
2723
+ );
2724
+
2725
+ Object.defineProperty(source, 'value', {
2726
+ ...valueDescriptor,
2727
+
2728
+ set(v) {
2729
+ valueDescriptor.set.call(this, v);
2730
+ // eslint-disable-next-line no-param-reassign
2731
+ target.value = v;
2732
+ },
2733
+ configurable: true,
2734
+ });
2735
+ }
2683
2736
 
2737
+ handleExternalInput() {
2684
2738
  // set safety attribute `external-input`
2685
2739
  this.setAttribute('external-input', 'true');
2686
2740
 
2687
2741
  // use original input element as reference
2688
2742
  const origInput = this.baseElement.querySelector('input');
2689
2743
 
2744
+ // to avoid focus loop between external-input and origInput
2745
+ // we set origInput's tabindex to -1
2746
+ // otherwise, shift-tab will never leave the component focus
2747
+ origInput.setAttribute('tabindex', '-1');
2748
+
2690
2749
  // create external slot
2691
2750
  const externalInputSlot = createExternalInputSlot('external-input', 'suffix');
2692
2751
  // append external slot to base element
@@ -2700,42 +2759,41 @@ const customMixin$a = (superclass) =>
2700
2759
 
2701
2760
  // apply original input's styles to external input
2702
2761
  setTimeout(() => {
2703
- applyExternalInputStyles(origInput, externalInput);
2762
+ applyExternalInputStyles(origInput, externalInput, this.getAttribute('label-type'));
2704
2763
  });
2705
2764
 
2706
2765
  // set external input events
2707
2766
  this.handleExternalInputEvents(externalInput);
2708
2767
 
2709
- syncAttrs(origInput, externalInput, { includeAttrs: ['disabled', 'readonly', 'pattern'] });
2768
+ // 1Password catches the internal input, so we forward the value to the external input
2769
+ this.forwardInputValue(origInput, externalInput);
2710
2770
 
2711
- externalInput.addEventListener('input', (e) => {
2712
- if (!e.target.value) {
2713
- this.removeAttribute('has-value');
2714
- } else {
2715
- this.setAttribute('has-value', 'true');
2716
- }
2771
+ syncAttrs(origInput, externalInput, {
2772
+ includeAttrs: ['disabled', 'readonly', 'pattern'],
2717
2773
  });
2718
2774
 
2719
2775
  // append external input to component's DOM
2720
2776
  this.appendChild(externalInput);
2777
+
2778
+ return externalInput;
2721
2779
  }
2722
2780
 
2723
2781
  getAutocompleteType() {
2724
2782
  return this.getAttribute('autocomplete') || 'username';
2725
2783
  }
2726
2784
 
2727
- handleExternalInputEvents(inputEle) {
2785
+ handleExternalInputEvents(externalInput) {
2728
2786
  // sync value of insible input back to original input
2729
- inputEle.addEventListener('input', (e) => {
2787
+ externalInput.addEventListener('input', (e) => {
2730
2788
  this.value = e.target.value;
2731
2789
  });
2732
2790
 
2733
2791
  // sync `focused` attribute on host when focusing on external input
2734
- inputEle.addEventListener('focus', () => {
2792
+ externalInput.addEventListener('focus', () => {
2735
2793
  this.setAttribute('focused', 'true');
2736
2794
  });
2737
2795
 
2738
- inputEle.addEventListener('blur', () => {
2796
+ externalInput.addEventListener('blur', () => {
2739
2797
  this.removeAttribute('focused');
2740
2798
  });
2741
2799
  }
@@ -2746,7 +2804,7 @@ const EmailFieldClass = compose(
2746
2804
  mappings: textFieldMappings,
2747
2805
  }),
2748
2806
  draggableMixin,
2749
- composedProxyInputMixin({ proxyProps: ['value', 'selectionStart'] }),
2807
+ composedProxyInputMixin({ proxyProps: ['value', 'selectionStart'], useProxyTargets: true }),
2750
2808
  componentNameValidationMixin,
2751
2809
  customMixin$a
2752
2810
  )(
@@ -2773,6 +2831,14 @@ const EmailFieldClass = compose(
2773
2831
  vaadin-email-field[label-type="floating"]:not([focused])[disabled] > input:placeholder-shown {
2774
2832
  opacity: 0;
2775
2833
  }
2834
+
2835
+ vaadin-email-field:not([no-external-input="true"]) > input:not(:placeholder-shown) {
2836
+ opacity: 0;
2837
+ }
2838
+
2839
+ :host ::slotted(*) {
2840
+ -webkit-mask-image: none;
2841
+ }
2776
2842
  `,
2777
2843
  excludeAttrsSync: ['tabindex'],
2778
2844
  componentName: componentName$M,
@@ -3287,7 +3353,7 @@ const TextFieldClass = compose(
3287
3353
  mappings: textFieldMappings,
3288
3354
  }),
3289
3355
  draggableMixin,
3290
- composedProxyInputMixin({ proxyProps: ['value', 'selectionStart'] }),
3356
+ composedProxyInputMixin({ proxyProps: ['value', 'selectionStart'], useProxyTargets: true }),
3291
3357
  componentNameValidationMixin,
3292
3358
  customMixin$9
3293
3359
  )(
@@ -3563,6 +3629,11 @@ const customMixin$7 = (superclass) =>
3563
3629
  // use original input element as reference
3564
3630
  const origInput = this.baseElement.querySelector('input');
3565
3631
 
3632
+ // to avoid focus loop between external-input and origInput
3633
+ // we set origInput's tabindex to -1
3634
+ // otherwise, shift-tab will never leave the component focus
3635
+ origInput.setAttribute('tabindex', '-1');
3636
+
3566
3637
  // create external slot
3567
3638
  const externalInputSlot = createExternalInputSlot('external-input', 'suffix');
3568
3639
  // append external slot to base element
@@ -3579,13 +3650,7 @@ const customMixin$7 = (superclass) =>
3579
3650
 
3580
3651
  // apply original input's styles to external input
3581
3652
  setTimeout(() => {
3582
- applyExternalInputStyles(
3583
- origInput,
3584
- externalInput,
3585
- `
3586
- width: calc(100% - 3em) !important;
3587
- `
3588
- );
3653
+ applyExternalInputStyles(origInput, externalInput, this.getAttribute('label-type'));
3589
3654
  });
3590
3655
 
3591
3656
  // set external input events
@@ -3610,11 +3675,6 @@ const customMixin$7 = (superclass) =>
3610
3675
  }
3611
3676
  });
3612
3677
 
3613
- this.addEventListener('focus', (e) => {
3614
- e.preventDefault();
3615
- this.focus();
3616
- });
3617
-
3618
3678
  // append external input to component's DOM
3619
3679
  this.appendChild(externalInput);
3620
3680
  }
@@ -3686,6 +3746,10 @@ const customMixin$7 = (superclass) =>
3686
3746
  inputEle.addEventListener('focus', () => {
3687
3747
  this.setAttribute('focused', 'true');
3688
3748
  });
3749
+
3750
+ inputEle.addEventListener('blur', () => {
3751
+ this.removeAttribute('focused');
3752
+ });
3689
3753
  }
3690
3754
  };
3691
3755
 
@@ -3844,8 +3908,11 @@ const PasswordClass = compose(
3844
3908
 
3845
3909
  ::part(reveal-button) {
3846
3910
  align-self: center;
3847
- }
3848
-
3911
+ }
3912
+
3913
+ vaadin-password-field > input:not(:placeholder-shown) {
3914
+ opacity: 0;
3915
+ }
3849
3916
  `,
3850
3917
  excludeAttrsSync: ['tabindex'],
3851
3918
  componentName: componentName$D,