PageSourceSearch

https://cdnp.sanmar.com/_ui/v/-1144430357/responsive/common/js/app/login/login-2fa-input-v-comp.js

js sanmar.com collected 2026-10-02 02:24:24 UTC 5,128 bytes, 168 lines download raw bytes

1const { onMounted, nextTick, reactive } = Vue;
2
3const Login2faInput = {
4    name: 'TwoFactorAuthInput',
5    emits: ['completeCode', 'newInteraction'],
6    props: {
7        modalErrorMessage: {
8            type: String,
9            required: true
10        },
11        modalId: {
12            type: String,
13            required: true
14        },
15        callInProgress: {
16            type: Boolean,
17            default: false
18        }
19    },
20    setup(props, { emit }) {
21        const values = reactive(['', '', '', '', '', '']);
22        const inputs = new Array(6);
23
24        onMounted(() => {
25            const modalEl = document.getElementById(props.modalId);
26            if (modalEl) {
27                modalEl.addEventListener('shown.bs.modal', () => {
28                    nextTick(() => {
29                        inputs[0]?.focus();
30                    });
31                });
32            }
33        });
34
35        const checkComplete = () => {
36            if (values.every((v) => v !== '')) {
37                const code = values.join('');
38                emit('completeCode', code);
39            }
40        };
41
42        const onInput = (event, index) => {
43            const input = event.target;
44            let value = input.value;
45
46            if (value.length > 1) {
47                value = value.slice(-1);
48            }
49
50            values[index] = value;
51            input.value = value;
52
53            if (value !== '' && index < inputs.length - 1) {
54                nextTick(() => {
55                    inputs[index + 1]?.focus();
56                });
57            }
58            emit('newInteraction');
59            checkComplete();
60        };
61
62        const onKeyDown = (event, index) => {
63            switch (event.key) {
64                case 'Backspace':
65                    event.preventDefault();
66                    if (values[index] === '') {
67                        if (index > 0) {
68                            values[index - 1] = '';
69                            nextTick(() => {
70                                inputs[index - 1]?.focus();
71                            });
72                        }
73                    } else {
74                        values[index] = '';
75                    }
76                    emit('newInteraction');
77                    break;
78
79                case 'ArrowLeft':
80                    if (index > 0) {
81                        event.preventDefault();
82                        nextTick(() => {
83                            inputs[index - 1]?.focus();
84                        });
85                    }
86                    break;
87
88                case 'ArrowRight':
89                    if (index < inputs.length - 1) {
90                        event.preventDefault();
91                        nextTick(() => {
92                            inputs[index + 1]?.focus();
93                        });
94                    }
95                    break;
96
97                default:
98                    break;
99            }
100        };
101
102        const onPaste = (event) => {
103            const pasteData = event.clipboardData.getData('Text').slice(0, 6);
104            if (pasteData.length > 0) {
105                event.preventDefault();
106                const chars = pasteData.split('');
107                for (let i = 0; i < chars.length && i < values.length; i++) {
108                    values[i] = chars[i];
109                }
110                if (chars.length < 6) {
111                    nextTick(() => {
112                        inputs[chars.length]?.focus();
113                    });
114                } else {
115                    inputs[inputs.length - 1]?.focus();
116                }
117                emit('newInteraction');
118                checkComplete();
119            }
120        };
121
122        const onFocus = (event) => {
123            event.target.select();
124        };
125
126        const setInputRef = (el, index) => {
127            inputs[index] = el;
128        };
129
130        return {
131            values,
132            onInput,
133            onKeyDown,
134            onPaste,
135            onFocus,
136            setInputRef,
137            modalInputMessage: ACC.login2faModalInputMessage,
138            props
139        };
140    },
141    template: `
142    <div class="two-factor-input-container">
143      <div class="two-factor-input"  :class="{ 'call-in-progress': props.callInProgress }">
144        <input
145          v-for="(value, index) in values"
146          :key="index"
147          :ref="(el) => setInputRef(el, index)"
148          v-model="values[index]"
149          @focus="onFocus"
150          @input="onInput($event, index)"
151          @keydown="onKeyDown($event, index)"
152          @paste="onPaste"
153          :class="props.modalErrorMessage ? 'input-box input-box-danger':'input-box'"
154          type="text"
155          inputmode="numeric"
156          autocomplete="one-time-code"
157        />
158        <div v-if="props.callInProgress" class="call-in-progress-overlay">
159            <div class="spinner"></div>
160        </div>
161      </div>
162      <p v-if="props.modalErrorMessage" class="two-factor-error-input-message">{{ props.modalErrorMessage }}</p>
163      <p class="two-factor-input-message">{{ modalInputMessage }}</p>
164    </div>
165  `
166};
167
168export { Login2faInput };

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.