@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/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-739e3acb] {
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-739e3acb] {
1607
+ .bagel-input.text-input textarea[data-v-194260fc] {
1571
1608
  resize: none;
1572
1609
  }
1573
- .code textarea[data-v-739e3acb] {
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-739e3acb]::placeholder {
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-739e3acb] {
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-739e3acb] {
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-739e3acb]:disabled {
1628
+ .bagel-input input[data-v-194260fc]:disabled {
1592
1629
  background: #f5f5f5;
1593
1630
  }
1594
- .bagel-input label[data-v-739e3acb] {
1631
+ .bagel-input label[data-v-194260fc] {
1595
1632
  font-size: var(--label-font-size);
1596
1633
  }
1597
- .textInputIconWrap .bgl_icon-font[data-v-739e3acb] {
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 - 16px);
1639
+ margin-block: calc(var(--input-height) / 2 - 13px);
1603
1640
  }
1604
- .textInputIconWrap input[data-v-739e3acb]{
1641
+ .textInputIconWrap input[data-v-194260fc]{
1605
1642
  padding-inline-end: 2rem;
1606
1643
  }
1607
- .txtInputIconStart .iconStart[data-v-739e3acb] {
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 - 16px);
1649
+ margin-block: calc(var(--input-height) / 2 - 13px);
1613
1650
  }
1614
- .txtInputIconStart input[data-v-739e3acb]{
1651
+ .txtInputIconStart input[data-v-194260fc]{
1615
1652
  padding-inline-start: 2rem;
1616
1653
  }
1617
- .txtInputIconStart textarea[data-v-739e3acb] {
1654
+ .txtInputIconStart textarea[data-v-194260fc] {
1618
1655
  padding-inline-start: 2rem;
1619
1656
  }
1620
- .bagel-input.small textarea[data-v-739e3acb] {
1657
+ .bagel-input.small textarea[data-v-194260fc] {
1621
1658
  height: 30px;
1622
1659
  }
1623
1660
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/vue",
3
3
  "type": "module",
4
- "version": "0.0.789",
4
+ "version": "0.0.791",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Neveh Allon",
@@ -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 - 16px);
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 - 16px);
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'