@descope/web-components-ui 3.14.9 → 3.15.0
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/cjs/index.cjs.js +26 -0
- package/dist/cjs/index.cjs.js.map +1 -1
- package/dist/index.esm.js +68 -14
- package/dist/index.esm.js.map +1 -1
- package/dist/umd/DescopeDev.js +1 -1
- package/dist/umd/DescopeDev.js.map +1 -1
- package/dist/umd/descope-modal-index-js.js +1 -1
- package/dist/umd/descope-modal-index-js.js.map +1 -1
- package/dist/umd/descope-passcode-descope-passcode-internal-index-js.js +1 -1
- package/dist/umd/descope-passcode-descope-passcode-internal-index-js.js.map +1 -1
- package/dist/umd/descope-passcode-index-js.js +1 -1
- package/dist/umd/descope-passcode-index-js.js.map +1 -1
- package/dist/umd/index.js +1 -1
- package/package.json +40 -40
- package/src/components/descope-modal/ModalClass.js +26 -0
- package/src/components/descope-passcode/descope-passcode-internal/PasscodeInternal.js +42 -14
- package/stories/descope-modal.stories.js +13 -2
|
@@ -174,6 +174,13 @@ class PasscodeInternal extends BaseInputClass {
|
|
|
174
174
|
|
|
175
175
|
const debouncedHandleParseInput = debounce(handleParseInput, 0, { trailing: true });
|
|
176
176
|
|
|
177
|
+
// Per-input flag: set in keydown, consumed in the input event.
|
|
178
|
+
// Fallback for WebKit/Safari, where the native input event can fire
|
|
179
|
+
// non-composed; proxyInputMixin then re-dispatches it as a plain Event
|
|
180
|
+
// (no inputType), so the 'deleteContentBackward' check misses the
|
|
181
|
+
// backspace and navigation is skipped.
|
|
182
|
+
let lastKeyWasBackspace = false;
|
|
183
|
+
|
|
177
184
|
// sanitize the input
|
|
178
185
|
input.addEventListener('input', (e) => {
|
|
179
186
|
input.value = sanitizeStr(input.value);
|
|
@@ -182,29 +189,50 @@ class PasscodeInternal extends BaseInputClass {
|
|
|
182
189
|
toggleMaskVisibility(input, input.value[0]);
|
|
183
190
|
}
|
|
184
191
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
192
|
+
// inputType covers iOS (unreliable keydown); the flag covers WebKit
|
|
193
|
+
// (missing inputType). See flag declaration above.
|
|
194
|
+
const isBackspace = e?.inputType === 'deleteContentBackward' || lastKeyWasBackspace;
|
|
195
|
+
lastKeyWasBackspace = false;
|
|
196
|
+
|
|
197
|
+
if (isBackspace) {
|
|
198
|
+
// Navigate synchronously (no setTimeout) to prevent WebKit key-event
|
|
199
|
+
// leakage: with setTimeout(0), WebKit can dispatch the next key-repeat
|
|
200
|
+
// backspace event to the newly focused element, deleting a second digit.
|
|
201
|
+
// Calling focusElement here (inside the input event, not keydown) is safe
|
|
202
|
+
// because the browser has already finished processing the deletion.
|
|
203
|
+
focusElement(this.getPrevInput(input));
|
|
204
|
+
}
|
|
205
|
+
|
|
190
206
|
debouncedHandleParseInput(input.value);
|
|
191
207
|
});
|
|
192
208
|
|
|
193
209
|
// we want backspace to focus on the previous digit
|
|
194
|
-
input.onkeydown = (
|
|
195
|
-
|
|
210
|
+
input.onkeydown = (e) => {
|
|
211
|
+
const { key } = e;
|
|
196
212
|
if (key === 'Backspace') {
|
|
197
|
-
// if value is empty then the input element does not fire `input` event
|
|
198
|
-
// if this is the case, we focus the element here.
|
|
199
|
-
// otherwise, the focusElement occurs as part of the `input` event listener
|
|
200
213
|
if (!input.value) {
|
|
201
|
-
|
|
214
|
+
// Empty field: the input event will not fire (nothing to delete),
|
|
215
|
+
// so we must handle navigation here.
|
|
216
|
+
// e.preventDefault() stops WebKit from leaking this keypress to
|
|
217
|
+
// the element that receives focus (key-event leakage).
|
|
218
|
+
e.preventDefault();
|
|
219
|
+
lastKeyWasBackspace = false;
|
|
220
|
+
focusElement(this.getPrevInput(input));
|
|
202
221
|
} else {
|
|
222
|
+
// Non-empty field: let the browser delete normally so the input
|
|
223
|
+
// event fires (needed on older iOS where keydown is unreliable).
|
|
224
|
+
// Move the caret to the end first so Backspace deletes the digit
|
|
225
|
+
// even if a direct tap left the caret before it (caret at index 0).
|
|
203
226
|
input.setSelectionRange(1, 1);
|
|
227
|
+
// Fallback signal for the input handler (see flag declaration above).
|
|
228
|
+
lastKeyWasBackspace = true;
|
|
229
|
+
}
|
|
230
|
+
} else {
|
|
231
|
+
lastKeyWasBackspace = false;
|
|
232
|
+
if (key.length === 1) {
|
|
233
|
+
// we want only characters and not command keys
|
|
234
|
+
input.value = ''; // we are clearing the previous value so we can override it with the new value
|
|
204
235
|
}
|
|
205
|
-
} else if (key.length === 1) {
|
|
206
|
-
// we want only characters and not command keys
|
|
207
|
-
input.value = ''; // we are clearing the previous value so we can override it with the new value
|
|
208
236
|
}
|
|
209
237
|
};
|
|
210
238
|
|
|
@@ -13,7 +13,7 @@ const template = `
|
|
|
13
13
|
</descope-container>
|
|
14
14
|
</descope-container>`;
|
|
15
15
|
|
|
16
|
-
const Template = ({ opened }) => {
|
|
16
|
+
const Template = ({ opened, closeOnOutsideClick }) => {
|
|
17
17
|
const loader = `
|
|
18
18
|
<descope-container direction="column" st-align-items="center" st-horizontal-padding="1.25rem" st-vertical-padding="1.25rem" st-gap="0.75rem" st-background-color="transparent">
|
|
19
19
|
<descope-loader-radial size="sm" mode="primary"></descope-loader-radial>
|
|
@@ -21,7 +21,7 @@ const Template = ({ opened }) => {
|
|
|
21
21
|
`;
|
|
22
22
|
|
|
23
23
|
return `
|
|
24
|
-
<descope-modal opened="${opened}">
|
|
24
|
+
<descope-modal opened="${opened}" close-on-outside-click="${closeOnOutsideClick}">
|
|
25
25
|
${loader}
|
|
26
26
|
</descope-modal>
|
|
27
27
|
`;
|
|
@@ -30,6 +30,16 @@ const Template = ({ opened }) => {
|
|
|
30
30
|
export default {
|
|
31
31
|
component: componentName,
|
|
32
32
|
title: 'descope-modal',
|
|
33
|
+
argTypes: {
|
|
34
|
+
opened: {
|
|
35
|
+
name: 'Opened',
|
|
36
|
+
control: { type: 'boolean' },
|
|
37
|
+
},
|
|
38
|
+
closeOnOutsideClick: {
|
|
39
|
+
name: 'Close on outside click',
|
|
40
|
+
control: { type: 'boolean' },
|
|
41
|
+
},
|
|
42
|
+
},
|
|
33
43
|
decorators: [
|
|
34
44
|
(render) => {
|
|
35
45
|
setTimeout(() => {
|
|
@@ -45,4 +55,5 @@ export const Default = Template.bind({});
|
|
|
45
55
|
|
|
46
56
|
Default.args = {
|
|
47
57
|
opened: true,
|
|
58
|
+
closeOnOutsideClick: true,
|
|
48
59
|
};
|