@descope/web-components-ui 1.0.358 → 1.0.359

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
@@ -4,6 +4,7 @@ import '@vaadin/checkbox';
4
4
  import '@vaadin/text-field';
5
5
  import '@vaadin/email-field';
6
6
  import '@vaadin/number-field';
7
+ import debounce from 'lodash.debounce';
7
8
  import '@vaadin/icons';
8
9
  import '@vaadin/icon';
9
10
  import '@vaadin/password-field';
@@ -2518,6 +2519,7 @@ const {
2518
2519
  requiredIndicator: requiredIndicator$9,
2519
2520
  inputField: inputField$6,
2520
2521
  input,
2522
+ inputMask,
2521
2523
  helperText: helperText$8,
2522
2524
  errorMessage: errorMessage$a,
2523
2525
  disabledPlaceholder,
@@ -2534,6 +2536,7 @@ const {
2534
2536
  disabledPlaceholder: { selector: '> input:disabled::placeholder' },
2535
2537
  inputField: { selector: '::part(input-field)' },
2536
2538
  input: { selector: 'input' },
2539
+ inputMask: { selector: '::part(input-field)::before' },
2537
2540
  inputDisabled: { selector: 'input:disabled' },
2538
2541
  helperText: { selector: '::part(helper-text)' },
2539
2542
  errorMessage: { selector: '::part(error-message)' },
@@ -2559,7 +2562,10 @@ var textFieldMappings = {
2559
2562
  hostMinWidth: { ...host$i, property: 'min-width' },
2560
2563
  hostDirection: { ...host$i, property: 'direction' },
2561
2564
 
2562
- inputBackgroundColor: { ...inputField$6, property: 'background-color' },
2565
+ inputBackgroundColor: [
2566
+ { ...inputField$6, property: 'background-color' },
2567
+ { ...inputMask, property: 'background-color' },
2568
+ ],
2563
2569
 
2564
2570
  errorMessageTextColor: { ...errorMessage$a, property: 'color' },
2565
2571
  helperTextColor: { ...helperText$8, property: '-webkit-text-fill-color' },
@@ -2870,18 +2876,46 @@ const NumberFieldClass = compose(
2870
2876
 
2871
2877
  customElements.define(componentName$I, NumberFieldClass);
2872
2878
 
2879
+ const INPUT_MASK_TEXT_PROP = '--descope-input-mask-content';
2880
+ const INPUT_MASK_DISPLAY_PROP = '--descope-input-mask-display';
2881
+ const INPUT_MASK_FALLBACK_PROP = '--descope-input-mask-fallback';
2882
+
2873
2883
  const focusElement = (ele) => {
2874
2884
  ele?.focus();
2875
2885
  ele?.setSelectionRange?.(1, 1);
2876
2886
  };
2877
2887
 
2878
- const getSanitizedCharacters = (str) => {
2879
- const pin = str.replace(/\s/g, ''); // sanitize string
2888
+ const sanitizeStr = (str) => {
2889
+ return str.replace(/\D/g, '') || '';
2890
+ };
2880
2891
 
2881
- // accept only numbers
2882
- if (!pin.match(/^\d+$/)) return [];
2892
+ // During debounced input we hide the value with a mask.
2893
+ // This allows us to hide the multiple population of the first input
2894
+ // in case of an automated input (e.g. Safari OTP Autofill or paste).
2895
+ const createInputMaskStyle = () => {
2896
+ const ele = document.createElement('style');
2897
+ ele.id = 'input-mask';
2898
+ ele.innerHTML = `vaadin-text-field::part(input-field)::before {
2899
+ ${INPUT_MASK_FALLBACK_PROP}: '';
2900
+ content: var(${INPUT_MASK_TEXT_PROP}, var(${INPUT_MASK_FALLBACK_PROP}));
2901
+ position: absolute;
2902
+ width: 100%;
2903
+ height: 100%;
2904
+ display: var(${INPUT_MASK_DISPLAY_PROP}, none);
2905
+ align-items: center;
2906
+ justify-content: center;
2907
+ }`;
2908
+ return ele;
2909
+ };
2883
2910
 
2884
- return [...pin]; // creating array of chars
2911
+ const toggleMaskVisibility = (input, value) => {
2912
+ if (value) {
2913
+ input.style.setProperty(INPUT_MASK_TEXT_PROP, `"${value}"`);
2914
+ input.style.setProperty(INPUT_MASK_DISPLAY_PROP, 'flex');
2915
+ } else {
2916
+ input.style.removeProperty(INPUT_MASK_TEXT_PROP);
2917
+ input.style.removeProperty(INPUT_MASK_DISPLAY_PROP);
2918
+ }
2885
2919
  };
2886
2920
 
2887
2921
  /* eslint-disable no-param-reassign */
@@ -2972,11 +3006,7 @@ class PasscodeInternal extends BaseInputClass$7 {
2972
3006
  set value(val) {
2973
3007
  if (val === this.value) return;
2974
3008
 
2975
- const charArr = getSanitizedCharacters(val);
2976
-
2977
- if (charArr.length) {
2978
- this.fillDigits(charArr, this.inputs[0]);
2979
- }
3009
+ this.parseInputValue(this.inputs[0], sanitizeStr(val));
2980
3010
  }
2981
3011
 
2982
3012
  getValidity() {
@@ -3032,8 +3062,8 @@ class PasscodeInternal extends BaseInputClass$7 {
3032
3062
  focusElement(currentInput);
3033
3063
  }
3034
3064
 
3035
- parseInputValue(input) {
3036
- const charArr = getSanitizedCharacters(input.value);
3065
+ parseInputValue(input, value = '') {
3066
+ const charArr = value.split('');
3037
3067
 
3038
3068
  if (!charArr.length) {
3039
3069
  // if we got an invalid value we want to clear the input
@@ -3045,15 +3075,30 @@ class PasscodeInternal extends BaseInputClass$7 {
3045
3075
  let currentInput;
3046
3076
 
3047
3077
  this.inputs.forEach((input) => {
3078
+ input.shadowRoot.appendChild(createInputMaskStyle());
3079
+
3048
3080
  input.addEventListener('change', (e) => {
3049
3081
  if (currentInput !== e.target) {
3050
- this.parseInputValue(input);
3082
+ this.parseInputValue(input, input.value);
3051
3083
  this.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
3052
3084
  }
3053
3085
  });
3054
3086
 
3087
+ const handleParseInput = (val) => {
3088
+ this.parseInputValue(input, val);
3089
+ toggleMaskVisibility(input);
3090
+ };
3091
+
3092
+ const debouncedHandleParseInput = debounce(handleParseInput, 20, { trailing: true });
3093
+
3055
3094
  // sanitize the input
3056
3095
  input.addEventListener('input', (e) => {
3096
+ input.value = sanitizeStr(input.value);
3097
+
3098
+ if (input.value) {
3099
+ toggleMaskVisibility(input, input.value[0]);
3100
+ }
3101
+
3057
3102
  // when using iPhone's code autofill we get only `change` events.
3058
3103
  // In other scenarios we get `input` AND `change` events.
3059
3104
  // In order to be parse the digits properly in iPhone, we need to listen to `change` event
@@ -3064,12 +3109,11 @@ class PasscodeInternal extends BaseInputClass$7 {
3064
3109
  currentInput = e.target;
3065
3110
  setTimeout(() => {
3066
3111
  currentInput = null;
3067
- if (e.inputType === 'deleteContentBackward') {
3112
+ if (e?.inputType === 'deleteContentBackward') {
3068
3113
  focusElement(this.getPrevInput(input));
3069
3114
  }
3070
3115
  });
3071
-
3072
- this.parseInputValue(input);
3116
+ debouncedHandleParseInput(input.value);
3073
3117
  });
3074
3118
 
3075
3119
  // we want backspace to focus on the previous digit
@@ -3394,10 +3438,15 @@ const PasscodeClass = compose(
3394
3438
  -webkit-mask-image: none;
3395
3439
  }
3396
3440
 
3441
+ /* safari */
3442
+ vaadin-text-field::part(input-field)::after {
3443
+ opacity: 0;
3444
+ }
3445
+
3397
3446
  vaadin-text-field {
3398
3447
  margin: 0;
3399
3448
  padding: 0;
3400
- width: 100%
3449
+ width: 100%;
3401
3450
  }
3402
3451
 
3403
3452
  vaadin-text-field::before {