@bagelink/vue 0.0.789 → 0.0.791
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/components/form/inputs/OTP.vue.d.ts +17 -0
- package/dist/components/form/inputs/OTP.vue.d.ts.map +1 -0
- package/dist/components/form/inputs/index.d.ts +1 -0
- package/dist/components/form/inputs/index.d.ts.map +1 -1
- package/dist/index.cjs +209 -102
- package/dist/index.mjs +209 -102
- package/dist/style.css +53 -16
- package/package.json +1 -1
- package/src/components/form/inputs/OTP.vue +145 -0
- package/src/components/form/inputs/TextInput.vue +2 -2
- package/src/components/form/inputs/index.ts +1 -0
package/dist/style.css
CHANGED
|
@@ -914,6 +914,43 @@ data[data-v-5f91f598] {
|
|
|
914
914
|
direction: ltr;
|
|
915
915
|
}
|
|
916
916
|
|
|
917
|
+
.otp_wrap[data-v-539a9fdb] {
|
|
918
|
+
display: flex;
|
|
919
|
+
flex-direction: row;
|
|
920
|
+
justify-content: center;
|
|
921
|
+
align-items: center;
|
|
922
|
+
}
|
|
923
|
+
.digit-box[data-v-539a9fdb] {
|
|
924
|
+
height: 3rem;
|
|
925
|
+
flex-grow: 1;
|
|
926
|
+
border: 1px solid var(--bgl-primary-tint);
|
|
927
|
+
display: inline-block;
|
|
928
|
+
background: var(--bgl-gray-light);
|
|
929
|
+
border-radius: 5px;
|
|
930
|
+
margin: 5px;
|
|
931
|
+
text-align: center;
|
|
932
|
+
font-size: 2.4rem;
|
|
933
|
+
-moz-appearance: textfield; /* Firefox */
|
|
934
|
+
caret-color: transparent;
|
|
935
|
+
}
|
|
936
|
+
.digit-box[data-v-539a9fdb]::-webkit-outer-spin-button,
|
|
937
|
+
.digit-box[data-v-539a9fdb]::-webkit-inner-spin-button {
|
|
938
|
+
-webkit-appearance: none; /* Chrome, Safari, Edge, Opera */
|
|
939
|
+
margin: 0;
|
|
940
|
+
}
|
|
941
|
+
.digit-box[data-v-539a9fdb]:focus {
|
|
942
|
+
outline: 1px solid var(--bgl-primary);
|
|
943
|
+
filter: drop-shadow(0 0 0.25rem var(--bgl-primary));
|
|
944
|
+
}
|
|
945
|
+
.digit-box[type="number"][data-v-539a9fdb] {
|
|
946
|
+
-moz-appearance: textfield; /* Firefox */
|
|
947
|
+
}
|
|
948
|
+
@media screen and (max-width: 910px) {
|
|
949
|
+
.digit-box[data-v-539a9fdb] {
|
|
950
|
+
padding: 0.25rem;
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
|
|
917
954
|
.m-password {
|
|
918
955
|
margin-block: calc(var(--input-height) / 2 - 15px);
|
|
919
956
|
}
|
|
@@ -1563,61 +1600,61 @@ p {
|
|
|
1563
1600
|
font-size: var(--label-font-size);
|
|
1564
1601
|
}
|
|
1565
1602
|
|
|
1566
|
-
.bagel-input textarea[data-v-
|
|
1603
|
+
.bagel-input textarea[data-v-194260fc] {
|
|
1567
1604
|
min-height: unset;
|
|
1568
1605
|
font-size: var(--input-font-size);
|
|
1569
1606
|
}
|
|
1570
|
-
.bagel-input.text-input textarea[data-v-
|
|
1607
|
+
.bagel-input.text-input textarea[data-v-194260fc] {
|
|
1571
1608
|
resize: none;
|
|
1572
1609
|
}
|
|
1573
|
-
.code textarea[data-v-
|
|
1610
|
+
.code textarea[data-v-194260fc] {
|
|
1574
1611
|
font-family: 'Inconsolata', monospace;
|
|
1575
1612
|
background: var(--bgl-code-bg) !important;
|
|
1576
1613
|
color: var(--bgl-light-text) !important;
|
|
1577
1614
|
}
|
|
1578
|
-
.code textarea[data-v-
|
|
1615
|
+
.code textarea[data-v-194260fc]::placeholder {
|
|
1579
1616
|
color: var(--bgl-light-text) !important;
|
|
1580
1617
|
opacity: 0.3;
|
|
1581
1618
|
}
|
|
1582
|
-
.bagel-input.small[data-v-
|
|
1619
|
+
.bagel-input.small[data-v-194260fc] {
|
|
1583
1620
|
margin-bottom: 0;
|
|
1584
1621
|
height: 30px;
|
|
1585
1622
|
}
|
|
1586
|
-
.bagel-input.dense label[data-v-
|
|
1623
|
+
.bagel-input.dense label[data-v-194260fc] {
|
|
1587
1624
|
display: flex;
|
|
1588
1625
|
align-items: center;
|
|
1589
1626
|
gap: 0.5rem;
|
|
1590
1627
|
}
|
|
1591
|
-
.bagel-input input[data-v-
|
|
1628
|
+
.bagel-input input[data-v-194260fc]:disabled {
|
|
1592
1629
|
background: #f5f5f5;
|
|
1593
1630
|
}
|
|
1594
|
-
.bagel-input label[data-v-
|
|
1631
|
+
.bagel-input label[data-v-194260fc] {
|
|
1595
1632
|
font-size: var(--label-font-size);
|
|
1596
1633
|
}
|
|
1597
|
-
.textInputIconWrap .bgl_icon-font[data-v-
|
|
1634
|
+
.textInputIconWrap .bgl_icon-font[data-v-194260fc] {
|
|
1598
1635
|
color: var(--bgl-gray);
|
|
1599
1636
|
position: absolute;
|
|
1600
1637
|
bottom: 0px;
|
|
1601
1638
|
inset-inline-end: 0.25rem;
|
|
1602
|
-
margin-block: calc(var(--input-height) / 2 -
|
|
1639
|
+
margin-block: calc(var(--input-height) / 2 - 13px);
|
|
1603
1640
|
}
|
|
1604
|
-
.textInputIconWrap input[data-v-
|
|
1641
|
+
.textInputIconWrap input[data-v-194260fc]{
|
|
1605
1642
|
padding-inline-end: 2rem;
|
|
1606
1643
|
}
|
|
1607
|
-
.txtInputIconStart .iconStart[data-v-
|
|
1644
|
+
.txtInputIconStart .iconStart[data-v-194260fc] {
|
|
1608
1645
|
color: var(--bgl-gray);
|
|
1609
1646
|
position: absolute;
|
|
1610
1647
|
bottom: 0px;
|
|
1611
1648
|
inset-inline-start: 0.25rem;
|
|
1612
|
-
margin-block: calc(var(--input-height) / 2 -
|
|
1649
|
+
margin-block: calc(var(--input-height) / 2 - 13px);
|
|
1613
1650
|
}
|
|
1614
|
-
.txtInputIconStart input[data-v-
|
|
1651
|
+
.txtInputIconStart input[data-v-194260fc]{
|
|
1615
1652
|
padding-inline-start: 2rem;
|
|
1616
1653
|
}
|
|
1617
|
-
.txtInputIconStart textarea[data-v-
|
|
1654
|
+
.txtInputIconStart textarea[data-v-194260fc] {
|
|
1618
1655
|
padding-inline-start: 2rem;
|
|
1619
1656
|
}
|
|
1620
|
-
.bagel-input.small textarea[data-v-
|
|
1657
|
+
.bagel-input.small textarea[data-v-194260fc] {
|
|
1621
1658
|
height: 30px;
|
|
1622
1659
|
}
|
|
1623
1660
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { reactive } from 'vue'
|
|
3
|
+
|
|
4
|
+
const props = defineProps<{ digitCount: number, default?: string, modelValue?: string }>()
|
|
5
|
+
|
|
6
|
+
const emit = defineEmits(['update:modelValue', 'complete'])
|
|
7
|
+
const digits = reactive<(number | string | null)[]>([])
|
|
8
|
+
const otpCont = $ref<HTMLElement>()
|
|
9
|
+
|
|
10
|
+
function handlePaste(event: ClipboardEvent, index: number) {
|
|
11
|
+
event.preventDefault()
|
|
12
|
+
const { clipboardData } = event
|
|
13
|
+
const pastedText = clipboardData?.getData('text').replace(/\D/g, '') // Ensure only numeric digits are pasted
|
|
14
|
+
const pastedDigits = pastedText?.split('')
|
|
15
|
+
if (!pastedDigits) return
|
|
16
|
+
for (let i = 0; i < pastedDigits.length; i++) {
|
|
17
|
+
const digit = pastedDigits[i]
|
|
18
|
+
if (index + i < digits.length) {
|
|
19
|
+
digits[index + i] = digit
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
emitUpdate()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function emitUpdate() {
|
|
26
|
+
if (isDigitsFull()) {
|
|
27
|
+
emit('complete', digits.join(''))
|
|
28
|
+
} else {
|
|
29
|
+
emit('update:modelValue', digits.join(''))
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function handleKeyDown(event: KeyboardEvent, index: number) {
|
|
34
|
+
const noPreventKeys = ['Tab', 'ArrowRight', 'ArrowLeft', 'Control', 'Shift', 'Alt', 'Meta']
|
|
35
|
+
if (noPreventKeys.includes(event.key)) {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (event.key === 'Backspace') {
|
|
40
|
+
digits[index] = null
|
|
41
|
+
|
|
42
|
+
if (index !== 0) {
|
|
43
|
+
const prevDigit = otpCont?.children[index - 1] as any
|
|
44
|
+
prevDigit.focus()
|
|
45
|
+
}
|
|
46
|
+
emitUpdate()
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const numberRegex = /^\d$/
|
|
51
|
+
if (numberRegex.test(event.key)) {
|
|
52
|
+
digits[index] = event.key
|
|
53
|
+
|
|
54
|
+
if (index !== props.digitCount - 1) {
|
|
55
|
+
setTimeout(() => {
|
|
56
|
+
const nextDigit = otpCont?.children[index + 1] as any
|
|
57
|
+
nextDigit.focus()
|
|
58
|
+
}, 10)
|
|
59
|
+
}
|
|
60
|
+
emitUpdate()
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (props.default && props.default.length === props.digitCount) {
|
|
65
|
+
for (let i = 0; i < props.digitCount; i++) {
|
|
66
|
+
digits[i] = props.default.charAt(i)
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
for (let i = 0; i < props.digitCount; i++) {
|
|
70
|
+
digits[i] = null
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function isDigitsFull() {
|
|
75
|
+
for (const elem of digits) {
|
|
76
|
+
if (elem == null || elem == undefined) {
|
|
77
|
+
return false
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return true
|
|
81
|
+
}
|
|
82
|
+
</script>
|
|
83
|
+
|
|
84
|
+
<template>
|
|
85
|
+
<div ref="otpCont" class="otp_wrap">
|
|
86
|
+
<input
|
|
87
|
+
v-for="(el, ind) in digits"
|
|
88
|
+
:key="ind"
|
|
89
|
+
:value="digits[ind] || ''"
|
|
90
|
+
type="number"
|
|
91
|
+
inputmode="numeric"
|
|
92
|
+
class="digit-box"
|
|
93
|
+
:autofocus="ind === 0"
|
|
94
|
+
maxlength="1"
|
|
95
|
+
pattern="[0-9]*"
|
|
96
|
+
oninput="this.value = this.value.slice(0, 1);"
|
|
97
|
+
@keydown="handleKeyDown($event, ind)"
|
|
98
|
+
@paste="handlePaste($event, ind)"
|
|
99
|
+
>
|
|
100
|
+
</div>
|
|
101
|
+
</template>
|
|
102
|
+
|
|
103
|
+
<style scoped>
|
|
104
|
+
.otp_wrap {
|
|
105
|
+
display: flex;
|
|
106
|
+
flex-direction: row;
|
|
107
|
+
justify-content: center;
|
|
108
|
+
align-items: center;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.digit-box {
|
|
112
|
+
height: 3rem;
|
|
113
|
+
flex-grow: 1;
|
|
114
|
+
border: 1px solid var(--bgl-primary-tint);
|
|
115
|
+
display: inline-block;
|
|
116
|
+
background: var(--bgl-gray-light);
|
|
117
|
+
border-radius: 5px;
|
|
118
|
+
margin: 5px;
|
|
119
|
+
text-align: center;
|
|
120
|
+
font-size: 2.4rem;
|
|
121
|
+
-moz-appearance: textfield; /* Firefox */
|
|
122
|
+
caret-color: transparent;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.digit-box::-webkit-outer-spin-button,
|
|
126
|
+
.digit-box::-webkit-inner-spin-button {
|
|
127
|
+
-webkit-appearance: none; /* Chrome, Safari, Edge, Opera */
|
|
128
|
+
margin: 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.digit-box:focus {
|
|
132
|
+
outline: 1px solid var(--bgl-primary);
|
|
133
|
+
filter: drop-shadow(0 0 0.25rem var(--bgl-primary));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.digit-box[type="number"] {
|
|
137
|
+
-moz-appearance: textfield; /* Firefox */
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
@media screen and (max-width: 910px) {
|
|
141
|
+
.digit-box {
|
|
142
|
+
padding: 0.25rem;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
</style>
|
|
@@ -194,7 +194,7 @@ onMounted(() => {
|
|
|
194
194
|
position: absolute;
|
|
195
195
|
bottom: 0px;
|
|
196
196
|
inset-inline-end: 0.25rem;
|
|
197
|
-
margin-block: calc(var(--input-height) / 2 -
|
|
197
|
+
margin-block: calc(var(--input-height) / 2 - 13px);
|
|
198
198
|
}
|
|
199
199
|
.textInputIconWrap input{
|
|
200
200
|
padding-inline-end: 2rem;
|
|
@@ -205,7 +205,7 @@ onMounted(() => {
|
|
|
205
205
|
position: absolute;
|
|
206
206
|
bottom: 0px;
|
|
207
207
|
inset-inline-start: 0.25rem;
|
|
208
|
-
margin-block: calc(var(--input-height) / 2 -
|
|
208
|
+
margin-block: calc(var(--input-height) / 2 - 13px);
|
|
209
209
|
}
|
|
210
210
|
.txtInputIconStart input{
|
|
211
211
|
padding-inline-start: 2rem;
|
|
@@ -5,6 +5,7 @@ export { default as DateInput } from './DateInput.vue'
|
|
|
5
5
|
export { default as DatePicker } from './DatePicker.vue'
|
|
6
6
|
export { default as FileUpload } from './FileUpload.vue'
|
|
7
7
|
export { default as JSONInput } from './JSONInput.vue'
|
|
8
|
+
export { default as OTP } from './OTP.vue'
|
|
8
9
|
export { default as PasswordInput } from './PasswordInput.vue'
|
|
9
10
|
export { default as RadioGroup } from './RadioGroup.vue'
|
|
10
11
|
export { default as RadioPillsInput } from './RadioPillsInput.vue'
|