@descope/web-components-ui 1.0.370 → 1.0.372

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. package/dist/cjs/index.cjs.js +410 -41
  2. package/dist/cjs/index.cjs.js.map +1 -1
  3. package/dist/index.esm.js +413 -42
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/umd/4392.js +1 -1
  6. package/dist/umd/4978.js +1 -1
  7. package/dist/umd/DescopeDev.js +1 -1
  8. package/dist/umd/button-selection-group-fields-descope-button-multi-selection-group-index-js.js +1 -1
  9. package/dist/umd/button-selection-group-fields-descope-button-selection-group-index-js.js +1 -1
  10. package/dist/umd/button-selection-group-fields-descope-button-selection-group-item-index-js.js +1 -1
  11. package/dist/umd/descope-button-index-js.js +2 -2
  12. package/dist/umd/descope-email-field-index-js.js +2 -2
  13. package/dist/umd/descope-icon-index-js.js +1 -1
  14. package/dist/umd/descope-new-password-descope-new-password-internal-index-js.js +1 -1
  15. package/dist/umd/descope-new-password-index-js.js +1 -1
  16. package/dist/umd/descope-number-field-index-js.js +1 -1
  17. package/dist/umd/descope-passcode-index-js.js +1 -1
  18. package/dist/umd/descope-password-index-js.js +1 -1
  19. package/dist/umd/descope-radio-group-index-js.js +1 -1
  20. package/dist/umd/descope-text-field-index-js.js +1 -1
  21. package/dist/umd/descope-upload-file-index-js.js +1 -1
  22. package/dist/umd/descope-user-attribute-index-js.js +1 -1
  23. package/dist/umd/descope-user-auth-method-index-js.js +1 -1
  24. package/dist/umd/mapping-fields-descope-mappings-field-index-js.js +1 -1
  25. package/package.json +1 -1
  26. package/src/components/descope-email-field/EmailFieldClass.js +12 -0
  27. package/src/components/descope-icon/IconClass.js +17 -30
  28. package/src/components/descope-new-password/NewPasswordClass.js +35 -0
  29. package/src/components/descope-new-password/descope-new-password-internal/NewPasswordInternal.js +3 -1
  30. package/src/components/descope-password/PasswordClass.js +59 -1
  31. package/src/components/descope-text-field/textFieldMappings.js +37 -6
  32. package/src/mixins/externalInputHelpers.js +86 -0
  33. package/src/mixins/externalInputMixin.js +165 -0
  34. package/src/mixins/index.js +1 -0
  35. package/src/mixins/proxyInputMixin.js +5 -2
  36. package/src/theme/components/button.js +0 -1
@@ -2229,7 +2229,7 @@ const proxyInputMixin =
2229
2229
  ({
2230
2230
  proxyProps = [],
2231
2231
  // useProxyTargets flag allows to forwardProps to other targets, other than
2232
- // `this.inputElement`.
2232
+ // `this.inputElement`. It's to be used within `external-input` components,
2233
2233
  // if needed
2234
2234
  useProxyTargets = false,
2235
2235
  // allows us to set the event that should trigger validation
@@ -2368,7 +2368,10 @@ const proxyInputMixin =
2368
2368
 
2369
2369
  // sync properties
2370
2370
  proxyProps.forEach((prop) => {
2371
- const proxyTargets = useProxyTargets ? [this.baseElement].filter(Boolean) : [];
2371
+ const externalInput = this.querySelector('input[slot="external-input"]') || null;
2372
+ const proxyTargets = useProxyTargets
2373
+ ? [this.baseElement, externalInput].filter(Boolean)
2374
+ : [];
2372
2375
  forwardProps(this, [this.inputElement, ...proxyTargets], prop);
2373
2376
  });
2374
2377
 
@@ -2618,6 +2621,252 @@ const inputEventsDispatchingMixin = (superclass) =>
2618
2621
  }
2619
2622
  };
2620
2623
 
2624
+ // since on load we can only sample the color of the placeholder,
2625
+ // we need to temporarily populate the input in order to sample the value color
2626
+ const getValueColor = (ele, computedStyle) => {
2627
+ // eslint-disable-next-line no-param-reassign
2628
+ ele.value = '_';
2629
+
2630
+ const valueColor = computedStyle.getPropertyValue('color');
2631
+
2632
+ // eslint-disable-next-line no-param-reassign
2633
+ ele.value = '';
2634
+
2635
+ return valueColor;
2636
+ };
2637
+
2638
+ const createExternalInputSlot = (slotName, targetSlotName) => {
2639
+ const slotEle = document.createElement('slot');
2640
+
2641
+ slotEle.setAttribute('name', slotName);
2642
+ slotEle.setAttribute('slot', targetSlotName);
2643
+
2644
+ return slotEle;
2645
+ };
2646
+
2647
+ const createExternalInputEle = (targetSlotName, type, autocompleteType) => {
2648
+ const inputEle = document.createElement('input');
2649
+
2650
+ inputEle.setAttribute('slot', targetSlotName);
2651
+ inputEle.setAttribute('type', type);
2652
+ inputEle.setAttribute('data-hidden-input', 'true');
2653
+ inputEle.setAttribute('autocomplete', autocompleteType);
2654
+
2655
+ return inputEle;
2656
+ };
2657
+
2658
+ // We apply the original input's style to the external-input.
2659
+ // Eventually, the user should interact directly with the external input.
2660
+ // We keep the original input
2661
+ const applyExternalInputStyles = (sourceInputEle, targetInputEle, labelType) => {
2662
+ // We set a timeout here to avoid "Double Print" cases,
2663
+ // caused by sampling the computed style before it's ready.
2664
+ setTimeout(() => {
2665
+ const computedStyle = getComputedStyle(sourceInputEle);
2666
+ // Get minimal set of computed theme properties to set on external input
2667
+ const height = computedStyle.getPropertyValue('height');
2668
+ const paddingLeft = computedStyle.getPropertyValue('padding-left');
2669
+ const paddingRight = computedStyle.getPropertyValue('padding-right');
2670
+ const fontSize = computedStyle.getPropertyValue('font-size');
2671
+ const fontFamily = computedStyle.getPropertyValue('font-family');
2672
+ const letterSpacing = computedStyle.getPropertyValue('letter-spacing');
2673
+ const caretColor = computedStyle.getPropertyValue('caret-color');
2674
+
2675
+ const valueColor = getValueColor(sourceInputEle, computedStyle);
2676
+
2677
+ const commonThemeStyles = [
2678
+ ['all', 'unset'],
2679
+ ['position', 'absolute'],
2680
+ ['background-color', 'transparent'],
2681
+ ['height', height],
2682
+ ['left', paddingLeft],
2683
+ ['right', paddingRight],
2684
+ ['font-size', fontSize],
2685
+ ['font-family', fontFamily],
2686
+ ['letter-spacing', letterSpacing],
2687
+ ['caret-color', caretColor], // this is for seeing caret when focusing on external input
2688
+ ['color', valueColor],
2689
+ ];
2690
+
2691
+ commonThemeStyles.forEach(([key, val]) =>
2692
+ targetInputEle.style.setProperty(key, val, 'important')
2693
+ );
2694
+
2695
+ // Handle floating label theme properties
2696
+ if (labelType === 'floating') {
2697
+ const marginBottom = computedStyle.getPropertyValue('margin-bottom');
2698
+ targetInputEle.style.setProperty('margin-bottom', marginBottom, 'important');
2699
+ }
2700
+
2701
+ // sample and apply width only after original input is ready and fully rendered
2702
+ const width = computedStyle.getPropertyValue('width');
2703
+ targetInputEle.style.setProperty(
2704
+ 'width',
2705
+ `calc(${width} - ${paddingLeft} - ${paddingRight}`,
2706
+ 'important'
2707
+ );
2708
+ }, 0);
2709
+ };
2710
+
2711
+ const externalInputMixin =
2712
+ ({ inputType, autocompleteType, includeAttrs = [], noBlurDispatch = false }) =>
2713
+ (superclass) =>
2714
+ class ExternalInputMixinClass extends superclass {
2715
+ #timers = [];
2716
+
2717
+ get isExternalInput() {
2718
+ return this.getAttribute('external-input') === 'true';
2719
+ }
2720
+
2721
+ createExternalInput() {
2722
+ if (!this.isExternalInput) {
2723
+ return null;
2724
+ }
2725
+
2726
+ // use original input element as reference
2727
+ const origInput = this.baseElement.querySelector('input');
2728
+
2729
+ // to avoid focus loop between external-input and origInput
2730
+ // we set origInput's tabindex to -1
2731
+ // otherwise, shift-tab will never leave the component focus
2732
+ origInput.setAttribute('tabindex', '-1');
2733
+
2734
+ // create external slot
2735
+ const externalInputSlot = createExternalInputSlot('external-input', 'suffix');
2736
+
2737
+ // append external slot to base element
2738
+ this.baseElement.appendChild(externalInputSlot);
2739
+
2740
+ this.externalInput = createExternalInputEle(
2741
+ 'external-input',
2742
+ inputType,
2743
+ this.getAutocompleteType()
2744
+ );
2745
+
2746
+ // apply original input's styles to external input
2747
+ setTimeout(() => {
2748
+ applyExternalInputStyles(origInput, this.externalInput, this.getAttribute('label-type'));
2749
+ });
2750
+
2751
+ // 1Password catches the internal input, so we forward the value to the external input
2752
+ this.forwardInputValue(origInput, this.externalInput);
2753
+
2754
+ syncAttrs(origInput, this.externalInput, {
2755
+ includeAttrs,
2756
+ });
2757
+
2758
+ // We disable Vaadin's original `_setFocused` function, and use handleFocusEvents
2759
+ // and handleBlurEvents functions
2760
+ this.baseElement
2761
+ .querySelector('input')
2762
+ .addEventListener('focusout', (e) => e.stopImmediatePropagation(), true);
2763
+
2764
+ // In order to manage focus/blur events when moving between parts of the component
2765
+ // we're managing the event dispatching by ourselves, with the following strategy:
2766
+ // - If one of the component parts is focused - it means that the component is still focused - so we stop the blur events.
2767
+ // - When none of the component parts is focused, we dispatch blur event.
2768
+ this.handleFocusEvents();
2769
+ this.handleBlurEvents();
2770
+
2771
+ // sync input value
2772
+ this.handlelInputEvents(this.externalInput);
2773
+
2774
+ // append external input to component's DOM
2775
+ this.appendChild(this.externalInput);
2776
+
2777
+ return this.externalInput;
2778
+ }
2779
+
2780
+ clearBlurTimers() {
2781
+ this.#timers.forEach((timer) => clearTimeout(timer));
2782
+ this.#timers.length = 0;
2783
+ }
2784
+
2785
+ dispatchBlur() {
2786
+ return setTimeout(() => {
2787
+ this.dispatchEvent(new Event('blur', { bubbles: true, composed: true }));
2788
+ this.removeAttribute('focused');
2789
+ });
2790
+ }
2791
+
2792
+ handleFocusEvents() {
2793
+ // on baseElement `focus` we forward the focus to the external input.
2794
+ // also, in order to avoid any blur within the component, we clear the blur timers.
2795
+ this.baseElement.addEventListener('focus', () => {
2796
+ this.externalInput.focus();
2797
+ this.clearBlurTimers();
2798
+ });
2799
+
2800
+ // on `focus` of the external input, we manually set the `focused` attribute
2801
+ this.externalInput.addEventListener('focus', () => {
2802
+ this.clearBlurTimers();
2803
+ setTimeout(() => this.baseElement.setAttribute('focused', 'true'));
2804
+ });
2805
+ }
2806
+
2807
+ handleBlurEvents() {
2808
+ this.baseElement.addEventListener(
2809
+ 'blur',
2810
+ (e) => {
2811
+ e.stopImmediatePropagation();
2812
+ // some components do not require this synthetic blur dispatch (e.g. Password)
2813
+ // so we allow them to override this dispatch
2814
+ if (noBlurDispatch) return;
2815
+ this.#timers.push(this.dispatchBlur());
2816
+ },
2817
+ true
2818
+ );
2819
+
2820
+ this.externalInput.addEventListener(
2821
+ 'blur',
2822
+ (e) => {
2823
+ e.stopImmediatePropagation();
2824
+ this.#timers.push(this.dispatchBlur());
2825
+ },
2826
+ true
2827
+ );
2828
+ }
2829
+
2830
+ handlelInputEvents(externalInput) {
2831
+ // sync value of insible input back to original input
2832
+ externalInput.addEventListener('input', (e) => {
2833
+ this.value = e.target.value;
2834
+ });
2835
+
2836
+ // handle has-value attr
2837
+ externalInput.addEventListener('input', (e) => {
2838
+ if (!e.target.value) {
2839
+ this.removeAttribute('has-value');
2840
+ } else {
2841
+ this.setAttribute('has-value', 'true');
2842
+ }
2843
+ });
2844
+ }
2845
+
2846
+ getAutocompleteType() {
2847
+ return this.getAttribute('autocomplete') || autocompleteType;
2848
+ }
2849
+
2850
+ forwardInputValue(source, target) {
2851
+ // set internal sync events
2852
+ const valueDescriptor = Object.getOwnPropertyDescriptor(
2853
+ this.inputElement.constructor.prototype,
2854
+ 'value'
2855
+ );
2856
+
2857
+ Object.defineProperty(source, 'value', {
2858
+ ...valueDescriptor,
2859
+
2860
+ set(v) {
2861
+ valueDescriptor.set.call(this, v);
2862
+ // eslint-disable-next-line no-param-reassign
2863
+ target.value = v;
2864
+ },
2865
+ configurable: true,
2866
+ });
2867
+ }
2868
+ };
2869
+
2621
2870
  const getFileExtension = (path) => {
2622
2871
  const match = path.match(/\.([0-9a-z]+)(?:[\\?#]|$)/i);
2623
2872
  return match ? match[1] : null;
@@ -2674,7 +2923,7 @@ const componentName$V = getComponentName('icon');
2674
2923
 
2675
2924
  class RawIcon extends createBaseClass({ componentName: componentName$V, baseSelector: 'slot' }) {
2676
2925
  static get observedAttributes() {
2677
- return ['src', 'fill-color'];
2926
+ return ['src'];
2678
2927
  }
2679
2928
 
2680
2929
  #icon;
@@ -2699,36 +2948,23 @@ class RawIcon extends createBaseClass({ componentName: componentName$V, baseSele
2699
2948
  `;
2700
2949
  }
2701
2950
 
2702
- get fillColor() {
2703
- return this.getAttribute('fill-color') === 'true';
2704
- }
2705
-
2706
2951
  get src() {
2707
2952
  return this.getAttribute('src');
2708
2953
  }
2709
2954
 
2710
2955
  // in order to fill an SVG with `currentColor` override all of its `fill` and `path` nodes
2711
2956
  // with the value from the `st-fill` attribute
2712
- updateFillColor() {
2713
- if (this.#icon && this.fillColor) {
2714
- const fillCssVar = (selector) => {
2715
- this.querySelectorAll(selector).forEach((ele) =>
2716
- ele.setAttribute(
2717
- 'fill',
2718
- `var(${IconClass.cssVarList.fill}, ${ele.getAttribute('fill') || "''"})`
2719
- )
2720
- );
2721
- };
2722
-
2723
- fillCssVar('*[fill]');
2724
- fillCssVar('path');
2725
- }
2726
- }
2727
-
2728
- resetIcon() {
2729
- if (!this.#icon) return;
2730
- this.innerHTML = '';
2731
- this.appendChild(this.#icon.cloneNode(true));
2957
+ // eslint-disable-next-line class-methods-use-this
2958
+ updateFillColor(node) {
2959
+ // set fill to root node and all its relevant selectors
2960
+ const elementsToReplace = [node, ...node.querySelectorAll('*[fill]')];
2961
+
2962
+ elementsToReplace.forEach((ele) => {
2963
+ ele.setAttribute(
2964
+ 'fill',
2965
+ `var(${IconClass.cssVarList.fill}, ${ele.getAttribute('fill') || "''"})`
2966
+ );
2967
+ });
2732
2968
  }
2733
2969
 
2734
2970
  attributeChangedCallback(attrName, oldValue, newValue) {
@@ -2738,13 +2974,13 @@ class RawIcon extends createBaseClass({ componentName: componentName$V, baseSele
2738
2974
 
2739
2975
  if (attrName === 'src') {
2740
2976
  createIcon(this.src).then((res) => {
2741
- this.#icon = res;
2742
- this.resetIcon();
2743
- this.updateFillColor();
2977
+ this.innerHTML = '';
2978
+ if (res) {
2979
+ const clonedNode = res.cloneNode(true);
2980
+ this.updateFillColor(clonedNode);
2981
+ this.appendChild(clonedNode);
2982
+ }
2744
2983
  });
2745
- } else if (attrName === 'fill-color') {
2746
- this.resetIcon();
2747
- this.updateFillColor();
2748
2984
  }
2749
2985
  }
2750
2986
  }
@@ -2969,7 +3205,6 @@ const button = {
2969
3205
  [compVars$6.outlineColor]: 'transparent',
2970
3206
 
2971
3207
  [compVars$6.iconSize]: '1.5em',
2972
- [compVars$6.iconColor]: 'currentColor',
2973
3208
 
2974
3209
  size: {
2975
3210
  xs: { [compVars$6.fontSize]: '12px' },
@@ -3071,6 +3306,10 @@ const {
3071
3306
  disabledPlaceholder,
3072
3307
  inputDisabled,
3073
3308
  inputIcon,
3309
+ externalInput,
3310
+ externalInputDisabled,
3311
+ externalPlaceholder,
3312
+ externalDisabledPlaceholder,
3074
3313
  } = {
3075
3314
  host: { selector: () => ':host' },
3076
3315
  label: { selector: '::part(label)' },
@@ -3087,6 +3326,10 @@ const {
3087
3326
  helperText: { selector: '::part(helper-text)' },
3088
3327
  errorMessage: { selector: '::part(error-message)' },
3089
3328
  inputIcon: { selector: 'vaadin-icon' },
3329
+ externalInput: { selector: () => '::slotted(input)' },
3330
+ externalInputDisabled: { selector: () => '::slotted(input:disabled)' },
3331
+ externalPlaceholder: { selector: () => '::slotted(input:placeholder-shown)' },
3332
+ externalDisabledPlaceholder: { selector: () => '::slotted(input:disabled::placeholder)' },
3090
3333
  };
3091
3334
 
3092
3335
  var textFieldMappings = {
@@ -3119,8 +3362,12 @@ var textFieldMappings = {
3119
3362
  inputValueTextColor: [
3120
3363
  { ...inputField$6, property: 'color' },
3121
3364
  { ...inputDisabled, property: '-webkit-text-fill-color' },
3365
+ { ...externalInputDisabled, property: '-webkit-text-fill-color' },
3366
+ ],
3367
+ inputCaretTextColor: [
3368
+ { ...input, property: 'caret-color' },
3369
+ { ...externalInput, property: 'caret-color' },
3122
3370
  ],
3123
- inputCaretTextColor: [{ ...input, property: 'color' }],
3124
3371
 
3125
3372
  labelRequiredIndicator: { ...requiredIndicator$b, property: 'content' },
3126
3373
 
@@ -3133,6 +3380,8 @@ var textFieldMappings = {
3133
3380
  inputHorizontalPadding: [
3134
3381
  { ...input, property: 'padding-left' },
3135
3382
  { ...input, property: 'padding-right' },
3383
+ { ...externalInput, property: 'padding-left' },
3384
+ { ...externalInput, property: 'padding-right' },
3136
3385
  ],
3137
3386
 
3138
3387
  inputOutlineColor: { ...inputField$6, property: 'outline-color' },
@@ -3140,12 +3389,17 @@ var textFieldMappings = {
3140
3389
  inputOutlineWidth: { ...inputField$6, property: 'outline-width' },
3141
3390
  inputOutlineOffset: { ...inputField$6, property: 'outline-offset' },
3142
3391
 
3143
- inputTextAlign: [{ ...input, property: 'text-align' }],
3392
+ inputTextAlign: [
3393
+ { ...input, property: 'text-align' },
3394
+ { ...externalInput, property: 'text-align' },
3395
+ ],
3144
3396
 
3145
3397
  inputPlaceholderColor: [
3146
3398
  { selector: () => ':host input:placeholder-shown', property: 'color' },
3399
+ { ...externalPlaceholder, property: 'color' },
3147
3400
  { ...placeholder$3, property: 'color' },
3148
3401
  { ...disabledPlaceholder, property: '-webkit-text-fill-color' },
3402
+ { ...externalDisabledPlaceholder, property: '-webkit-text-fill-color' },
3149
3403
  ],
3150
3404
 
3151
3405
  labelPosition: { ...label$9, property: 'position' },
@@ -3157,10 +3411,22 @@ var textFieldMappings = {
3157
3411
  inputTransformY: { ...label$9, property: 'transform' },
3158
3412
  inputTransition: { ...label$9, property: 'transition' },
3159
3413
  marginInlineStart: { ...label$9, property: 'margin-inline-start' },
3160
- placeholderOpacity: [{ selector: '> input:placeholder-shown', property: 'opacity' }],
3161
- inputVerticalAlignment: [{ ...inputField$6, property: 'align-items' }],
3162
- valueInputHeight: [{ ...input, property: 'height' }],
3163
- valueInputMarginBottom: [{ ...input, property: 'margin-bottom' }],
3414
+ placeholderOpacity: [
3415
+ { selector: '> input:placeholder-shown', property: 'opacity' },
3416
+ { ...externalPlaceholder, property: 'opacity' },
3417
+ ],
3418
+ inputVerticalAlignment: [
3419
+ { ...inputField$6, property: 'align-items' },
3420
+ { ...externalInput, property: 'align-items' },
3421
+ ],
3422
+ valueInputHeight: [
3423
+ { ...input, property: 'height' },
3424
+ { ...externalInput, property: 'height' },
3425
+ ],
3426
+ valueInputMarginBottom: [
3427
+ { ...input, property: 'margin-bottom' },
3428
+ { ...externalInput, property: 'margin-bottom' },
3429
+ ],
3164
3430
 
3165
3431
  inputIconOffset: [
3166
3432
  { ...inputIcon, property: 'margin-right' },
@@ -3672,6 +3938,15 @@ const customMixin$b = (superclass) =>
3672
3938
  this.origSetPasswordVisible = this.baseElement._setPasswordVisible;
3673
3939
  this.origSetFocused = this.baseElement._setFocused;
3674
3940
  this.baseElement._setFocused = this.setFocus.bind(this);
3941
+
3942
+ this.initExternalInput();
3943
+ }
3944
+
3945
+ initExternalInput() {
3946
+ const externalInput = this.createExternalInput();
3947
+ if (externalInput) {
3948
+ this.handlePasswordVisibility(externalInput);
3949
+ }
3675
3950
  }
3676
3951
 
3677
3952
  get caretPosition() {
@@ -3686,6 +3961,7 @@ const customMixin$b = (superclass) =>
3686
3961
  setTimeout(() => {
3687
3962
  origTogglePasswordVisibility();
3688
3963
  this.inputElement.setSelectionRange(this.caretPosition, this.caretPosition);
3964
+ return false;
3689
3965
  });
3690
3966
  };
3691
3967
  }
@@ -3712,6 +3988,44 @@ const customMixin$b = (superclass) =>
3712
3988
  attributeChangedCallback(attrName, oldValue, newValue) {
3713
3989
  super.attributeChangedCallback?.(attrName, oldValue, newValue);
3714
3990
  }
3991
+
3992
+ // override vaadin's password visibility toggle.
3993
+ // we need this override in order to to resolve the external input `focus` race condition,
3994
+ // which is caused due to the focus sync between the two inputs.
3995
+ handlePasswordVisibility(externalInput) {
3996
+ // disable vaadin's `__boundRevealButtonMouseDown` mouse-down event lisetener
3997
+ const origBoundRevealButtonMouseDown = this.baseElement.__boundRevealButtonMouseDown;
3998
+ this.baseElement
3999
+ .querySelector('vaadin-password-field-button')
4000
+ .removeEventListener('mousedown', origBoundRevealButtonMouseDown);
4001
+
4002
+ // disable vaadin's `_passwordVisibleChanged` observer
4003
+ this.baseElement._passwordVisibleChanged = () => {};
4004
+
4005
+ // override vaadin's `_togglePasswordVisibility`
4006
+ this.baseElement._togglePasswordVisibility = () => {
4007
+ const currVisibility = externalInput.getAttribute('type');
4008
+ if (currVisibility === 'password') {
4009
+ this.showPasswordVisibility(externalInput);
4010
+ } else {
4011
+ this.hidePasswordVisibility(externalInput);
4012
+ }
4013
+ };
4014
+ }
4015
+
4016
+ showPasswordVisibility(input) {
4017
+ // handle input element's type
4018
+ input.setAttribute('type', 'text');
4019
+ // handle vaadin's `password-visible` attribute
4020
+ this.setAttribute('password-visible', 'true');
4021
+ }
4022
+
4023
+ hidePasswordVisibility(input) {
4024
+ // handle input element's type
4025
+ input.setAttribute('type', 'password');
4026
+ // handle vaadin's `password-visible` attribute
4027
+ this.setAttribute('password-visible', 'false');
4028
+ }
3715
4029
  };
3716
4030
 
3717
4031
  const {
@@ -3806,7 +4120,12 @@ const PasswordClass = compose(
3806
4120
  },
3807
4121
  }),
3808
4122
  draggableMixin,
3809
- composedProxyInputMixin({ proxyProps: ['value', 'selectionStart'] }),
4123
+ externalInputMixin({
4124
+ inputType: 'password',
4125
+ includeAttrs: ['disabled', 'readonly', 'pattern', 'type', 'autocomplete'],
4126
+ noBlurDispatch: true,
4127
+ }),
4128
+ composedProxyInputMixin({ proxyProps: ['value', 'selectionStart'], useProxyTargets: true }),
3810
4129
  componentNameValidationMixin,
3811
4130
  passwordDraggableMixin,
3812
4131
  customMixin$b
@@ -3870,6 +4189,10 @@ const PasswordClass = compose(
3870
4189
  ::part(reveal-button) {
3871
4190
  align-self: center;
3872
4191
  }
4192
+
4193
+ vaadin-password-field[external-input="true"] > input:not(:placeholder-shown) {
4194
+ opacity: 0;
4195
+ }
3873
4196
  `,
3874
4197
  excludeAttrsSync: ['tabindex'],
3875
4198
  componentName: componentName$R,
@@ -4021,6 +4344,8 @@ const customMixin$a = (superclass) =>
4021
4344
  if (!this.getAttribute('autocomplete')) {
4022
4345
  this.setAttribute('autocomplete', defaultAutocomplete);
4023
4346
  }
4347
+
4348
+ this.createExternalInput();
4024
4349
  }
4025
4350
  };
4026
4351
 
@@ -4029,6 +4354,11 @@ const EmailFieldClass = compose(
4029
4354
  mappings: textFieldMappings,
4030
4355
  }),
4031
4356
  draggableMixin,
4357
+ externalInputMixin({
4358
+ inputType: 'text',
4359
+ autocompleteType: 'username',
4360
+ includeAttrs: ['disabled', 'readonly', 'pattern'],
4361
+ }),
4032
4362
  composedProxyInputMixin({ proxyProps: ['value', 'selectionStart'], useProxyTargets: true }),
4033
4363
  componentNameValidationMixin,
4034
4364
  customMixin$a
@@ -4060,6 +4390,10 @@ const EmailFieldClass = compose(
4060
4390
  :host ::slotted(*) {
4061
4391
  -webkit-mask-image: none;
4062
4392
  }
4393
+
4394
+ vaadin-email-field[external-input="true"] > input:not(:placeholder-shown) {
4395
+ opacity: 0;
4396
+ }
4063
4397
  `,
4064
4398
  excludeAttrsSync: ['tabindex'],
4065
4399
  componentName: componentName$P,
@@ -8622,11 +8956,14 @@ const customMixin$6 = (superclass) =>
8622
8956
 
8623
8957
  const template = document.createElement('template');
8624
8958
 
8959
+ const externalInputAttr = this.getAttribute('external-input');
8960
+
8625
8961
  template.innerHTML = `
8626
8962
  <${componentName$s}
8627
8963
  name="new-password"
8628
8964
  tabindex="-1"
8629
8965
  slot="input"
8966
+ external-input="${externalInputAttr}"
8630
8967
  >
8631
8968
  </${componentName$s}>
8632
8969
  `;
@@ -8635,6 +8972,10 @@ const customMixin$6 = (superclass) =>
8635
8972
 
8636
8973
  this.inputElement = this.shadowRoot.querySelector(componentName$s);
8637
8974
 
8975
+ if (this.getAttribute('external-input') === 'true') {
8976
+ this.initExternalInput();
8977
+ }
8978
+
8638
8979
  forwardAttrs(this, this.inputElement, {
8639
8980
  includeAttrs: [
8640
8981
  'password-label',
@@ -8659,6 +9000,34 @@ const customMixin$6 = (superclass) =>
8659
9000
  ],
8660
9001
  });
8661
9002
  }
9003
+
9004
+ createSlottedExternalInput(node, slotName) {
9005
+ const externalInput = node.querySelector('input');
9006
+ const slotEle = document.createElement('slot');
9007
+
9008
+ const targetSlot = externalInput.getAttribute('slot');
9009
+
9010
+ slotEle.setAttribute('name', slotName);
9011
+ slotEle.setAttribute('slot', targetSlot);
9012
+
9013
+ node.appendChild(slotEle);
9014
+
9015
+ // move external input
9016
+ externalInput.setAttribute('slot', slotName);
9017
+ externalInput.setAttribute('data-hidden-input', 'true');
9018
+
9019
+ this.appendChild(externalInput);
9020
+ }
9021
+
9022
+ initExternalInput() {
9023
+ // get descope input components
9024
+ this.passwordInput = this.inputElement.querySelector('[data-id="password"]');
9025
+ this.confirmInput = this.inputElement.querySelector('[data-id="confirm"]');
9026
+
9027
+ // create slots for external password input
9028
+ this.createSlottedExternalInput(this.passwordInput, 'external-password-input');
9029
+ this.createSlottedExternalInput(this.confirmInput, 'external-confirm-input');
9030
+ }
8662
9031
  };
8663
9032
 
8664
9033
  const {