@descope/web-components-ui 1.0.370 → 1.0.372

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.
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 {