@descope/web-components-ui 1.0.156 → 1.0.158

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.
@@ -1 +1 @@
1
- "use strict";(self.webpackChunkDescopeUI=self.webpackChunkDescopeUI||[]).push([[1841],{7361:(t,e,i)=>{i.d(e,{f:()=>u,Z:()=>h});var s=i(3878),n=i(4567);const r=t=>{t?.focus(),t?.setSelectionRange(1,1)},a=t=>{const e=t.replace(/\s/g,"");return e.match(/^\d+$/)?[...e]:[]},u=(0,n.iY)("passcode-internal"),p=["digits"],l=["disabled","bordered","size","invalid","readonly"],d=(0,s.P)({componentName:u,baseSelector:"div"}),h=class extends d{static get observedAttributes(){return p.concat(d.observedAttributes||[])}static get componentName(){return u}constructor(){super(),this.innerHTML='\n\t\t<div class="wrapper"></div>\n\t\t<style>\n\t\t\t.wrapper {\n\t\t\t\tdisplay: flex;\n\t\t\t\twidth: 100%;\n\t\t\t\tjustify-content: space-between;\n\t\t\t}\n\t\t</style>\n\t\t',this.wrapperEle=this.querySelector("div")}renderInputs(){const t=[...Array(this.digits).keys()].map((t=>`\n\t\t<descope-text-field\n\t\t\tdata-id=${t}\n\t\t\ttype="tel"\n\t\t\tautocomplete="one-time-code"\n\t\t\tinputMode="numeric"\n\t\t></descope-text-field>\n\t`));this.wrapperEle.innerHTML=t.join(""),this.inputs=Array.from(this.querySelectorAll("descope-text-field")),this.initInputs()}get digits(){return Number.parseInt(this.getAttribute("digits"),10)||6}get value(){return this.inputs?.map((({value:t})=>t)).join("")||""}set value(t){if(t===this.value)return;const e=a(t);e.length&&this.fillDigits(e,this.inputs[0])}get pattern(){return`^$|^\\d{${this.digits},}$`}getValidity(){return this.isRequired&&!this.value?{valueMissing:!0}:this.pattern&&!new RegExp(this.pattern).test(this.value)?{patternMismatch:!0}:{}}init(){this.addEventListener("focus",(t=>{t.isTrusted&&this.inputs[0].focus()})),super.init?.(),this.renderInputs()}getInputIdx(t){return Number.parseInt(t.getAttribute("data-id"),10)}getNextInput(t){const e=this.getInputIdx(t),i=Math.min(e+1,this.inputs.length-1);return this.inputs[i]}getPrevInput(t){const e=this.getInputIdx(t),i=Math.max(e-1,0);return this.inputs[i]}fillDigits(t,e){for(let i=0;i<t.length;i+=1){e.value=t[i]??"";const s=this.getNextInput(e);if(s===e)break;e=s}r(e)}initInputs(){this.inputs.forEach((t=>{t.addEventListener("input",(e=>{const i=a(t.value);i.length?this.fillDigits(i,t):t.value=""})),t.onkeydown=({key:e})=>{"Backspace"===e?(t.selectionStart||t.setSelectionRange(1,1),setTimeout((()=>{r(this.getPrevInput(t))}))):1===e.length&&(t.value="")},(0,n.oP)(this,t,{includeAttrs:l})})),this.handleFocusEventsDispatching(this.inputs),this.handleInputEventDispatching()}attributeChangedCallback(t,e,i){super.attributeChangedCallback?.(t,e,i),e!==i&&p.includes(t)&&"digits"===t&&this.renderInputs()}}},4775:(t,e,i)=>{i.r(e);var s=i(7361);customElements.define(s.f,s.Z)}}]);
1
+ "use strict";(self.webpackChunkDescopeUI=self.webpackChunkDescopeUI||[]).push([[1841],{7361:(t,e,s)=>{s.d(e,{f:()=>u,Z:()=>h});var i=s(3878),n=s(4567);const r=t=>{t?.focus(),t?.setSelectionRange(1,1)},a=t=>{const e=t.replace(/\s/g,"");return e.match(/^\d+$/)?[...e]:[]},u=(0,n.iY)("passcode-internal"),p=["digits"],l=["disabled","bordered","size","invalid","readonly"],d=(0,i.P)({componentName:u,baseSelector:"div"}),h=class extends d{static get observedAttributes(){return p.concat(d.observedAttributes||[])}static get componentName(){return u}constructor(){super(),this.innerHTML='\n\t\t<div class="wrapper"></div>\n\t\t<style>\n\t\t\t.wrapper {\n\t\t\t\tdisplay: flex;\n\t\t\t\twidth: 100%;\n\t\t\t\tjustify-content: space-between;\n\t\t\t}\n\t\t</style>\n\t\t',this.wrapperEle=this.querySelector("div")}renderInputs(){const t=[...Array(this.digits).keys()].map((t=>`\n\t\t<descope-text-field\n\t\t\tdata-id=${t}\n\t\t\ttype="tel"\n\t\t\tautocomplete="one-time-code"\n\t\t\tinputMode="numeric"\n\t\t></descope-text-field>\n\t`));this.wrapperEle.innerHTML=t.join(""),this.inputs=Array.from(this.querySelectorAll("descope-text-field")),this.initInputs()}get digits(){return Number.parseInt(this.getAttribute("digits"),10)||6}get value(){return this.inputs?.map((({value:t})=>t)).join("")||""}set value(t){if(t===this.value)return;const e=a(t);e.length&&this.fillDigits(e,this.inputs[0])}getValidity(){return this.isRequired&&!this.value?{valueMissing:!0}:this.pattern&&!new RegExp(this.pattern).test(this.value)?{patternMismatch:!0}:{}}init(){this.addEventListener("focus",(t=>{t.isTrusted&&this.inputs[0].focus()})),super.init?.(),this.renderInputs()}getInputIdx(t){return Number.parseInt(t.getAttribute("data-id"),10)}getNextInput(t){const e=this.getInputIdx(t),s=Math.min(e+1,this.inputs.length-1);return this.inputs[s]}getPrevInput(t){const e=this.getInputIdx(t),s=Math.max(e-1,0);return this.inputs[s]}fillDigits(t,e){for(let s=0;s<t.length;s+=1){e.value=t[s]??"";const i=this.getNextInput(e);if(i===e)break;e=i}r(e)}parseInputValue(t){const e=a(t.value);e.length?this.fillDigits(e,t):t.value=""}initInputs(){let t;this.inputs.forEach((e=>{e.addEventListener("change",(s=>{t!==s.target&&this.parseInputValue(e)})),e.addEventListener("input",(s=>{t=s.target,setTimeout((()=>{t=null,"deleteContentBackward"===s.inputType&&r(this.getPrevInput(e))})),this.parseInputValue(e)})),e.onkeydown=({key:t})=>{"Backspace"===t?e.setSelectionRange(1,1):1===t.length&&(e.value="")},(0,n.oP)(this,e,{includeAttrs:l})})),this.handleFocusEventsDispatching(this.inputs),this.handleInputEventDispatching()}attributeChangedCallback(t,e,s){super.attributeChangedCallback?.(t,e,s),e!==s&&p.includes(t)&&"digits"===t&&this.renderInputs()}get pattern(){return`^$|^\\d{${this.digits},}$`}}},4775:(t,e,s)=>{s.r(e);var i=s(7361);customElements.define(i.f,i.Z)}}]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@descope/web-components-ui",
3
- "version": "1.0.156",
3
+ "version": "1.0.158",
4
4
  "description": "",
5
5
  "main": "dist/cjs/index.cjs.js",
6
6
  "module": "dist/index.esm.js",
@@ -74,10 +74,6 @@ class PasscodeInternal extends BaseInputClass {
74
74
  }
75
75
  }
76
76
 
77
- get pattern() {
78
- return `^$|^\\d{${this.digits},}$`;
79
- }
80
-
81
77
  getValidity() {
82
78
  if (this.isRequired && !this.value) {
83
79
  return { valueMissing: true };
@@ -131,29 +127,50 @@ class PasscodeInternal extends BaseInputClass {
131
127
  focusElement(currentInput);
132
128
  }
133
129
 
130
+ parseInputValue(input) {
131
+ const charArr = getSanitizedCharacters(input.value);
132
+
133
+ if (!charArr.length) {
134
+ // if we got an invalid value we want to clear the input
135
+ input.value = '';
136
+ } else this.fillDigits(charArr, input);
137
+ }
138
+
134
139
  initInputs() {
140
+ let currentInput;
141
+
135
142
  this.inputs.forEach((input) => {
143
+ input.addEventListener('change', (e) => {
144
+ if (currentInput !== e.target) {
145
+ this.parseInputValue(input);
146
+ }
147
+ });
148
+
136
149
  // sanitize the input
137
- input.addEventListener('input', (_) => {
138
- const charArr = getSanitizedCharacters(input.value);
150
+ input.addEventListener('input', (e) => {
151
+ // when using iPhone's code autofill we get only `change` events.
152
+ // In other scenarios we get `input` AND `change` events.
153
+ // In order to be parse the digits properly in iPhone, we need to listen to `change` event
154
+ // and validate it was not preceeded by an `input` event.
155
+ // To do so, we're keeping a reference to the input element in `input` events,
156
+ // and only if there the reference is null, then we're assuming no `input` event was preceeding,
157
+ // and we're parsing the digits.
158
+ currentInput = e.target;
159
+ setTimeout(() => {
160
+ currentInput = null;
161
+ if (e.inputType === 'deleteContentBackward') {
162
+ focusElement(this.getPrevInput(input));
163
+ }
164
+ });
139
165
 
140
- if (!charArr.length) {
141
- // if we got an invalid value we want to clear the input
142
- input.value = '';
143
- } else this.fillDigits(charArr, input);
166
+ this.parseInputValue(input);
144
167
  });
145
168
 
146
169
  // we want backspace to focus on the previous digit
147
170
  input.onkeydown = ({ key }) => {
148
171
  // when user deletes a digit, we want to focus the previous digit
149
172
  if (key === 'Backspace') {
150
- // if the cursor is at 0, we want to move it to 1, so the value will be deleted
151
- if (!input.selectionStart) {
152
- input.setSelectionRange(1, 1);
153
- }
154
- setTimeout(() => {
155
- focusElement(this.getPrevInput(input));
156
- });
173
+ input.setSelectionRange(1, 1);
157
174
  } else if (key.length === 1) {
158
175
  // we want only characters and not command keys
159
176
  input.value = ''; // we are clearing the previous value so we can override it with the new value
@@ -179,6 +196,10 @@ class PasscodeInternal extends BaseInputClass {
179
196
  }
180
197
  }
181
198
  }
199
+
200
+ get pattern() {
201
+ return `^$|^\\d{${this.digits},}$`;
202
+ }
182
203
  }
183
204
 
184
205
  export default PasscodeInternal;