@bagelink/vue 0.0.1256 → 0.0.1258

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.
@@ -3,7 +3,7 @@ interface InputOptions {
3
3
  required?: boolean;
4
4
  placeholder?: string;
5
5
  class?: string;
6
- defaultValue?: string;
6
+ defaultValue?: string | number;
7
7
  disabled?: boolean;
8
8
  helptext?: string;
9
9
  vIf?: boolean | ((item: any, row: any) => boolean);
@@ -69,7 +69,7 @@ export declare function uploadField(id: string, label?: string, options?: Upload
69
69
  required?: boolean;
70
70
  placeholder?: string;
71
71
  class?: string;
72
- defaultValue?: string;
72
+ defaultValue?: string | number;
73
73
  disabled?: boolean;
74
74
  helptext?: string;
75
75
  vIf?: boolean | ((item: any, row: any) => boolean);
@@ -1 +1 @@
1
- {"version":3,"file":"BagelFormUtils.d.ts","sourceRoot":"","sources":["../../src/utils/BagelFormUtils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"BagelFormUtils.d.ts","sourceRoot":"","sources":["../../src/utils/BagelFormUtils.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/vue",
3
3
  "type": "module",
4
- "version": "0.0.1256",
4
+ "version": "0.0.1258",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Neveh Allon",
@@ -29,9 +29,9 @@ const isFaBrand = $computed(() => FONT_AWESOME_BRANDS_ICONS.includes(iconRender)
29
29
  >
30
30
  {{ iconRender }}
31
31
  </span>
32
- <i
32
+ <span
33
33
  v-else-if="iconRenderType === 'font-awesome'"
34
- class="fa far" :class="[`fa-${iconRender}`, { 'fa-brands': isFaBrand }]"
34
+ class="fa far bgl_icon-font" :class="[`fa-${iconRender}`, { 'fa-brands': isFaBrand }]"
35
35
  :style="{ 'fontSize': `${size}rem`, color, 'font-variation-settings': `'wght' ${weight || 400}` }"
36
36
  />
37
37
  </template>
@@ -16,6 +16,7 @@ import {
16
16
  import '../styles/modal.css'
17
17
 
18
18
  const props = defineProps<{
19
+ thin?: boolean
19
20
  side?: boolean
20
21
  title?: string
21
22
  width?: string
@@ -74,7 +75,7 @@ onUnmounted(() => {
74
75
  @click="() => (dismissable ? closeModal() : '')"
75
76
  @keydown.esc="closeModal"
76
77
  >
77
- <Card class="modal" :style="{ ...maxWidth }" @click.stop>
78
+ <Card class="modal" :style="{ ...maxWidth }" :thin="thin" @click.stop>
78
79
  <header v-if="slots.toolbar || title" class="tool-bar">
79
80
  <slot name="toolbar" />
80
81
  <Btn
@@ -36,7 +36,6 @@ const formData = ref<T>(safeClone(props.modelValue ?? {}) as T)
36
36
  const initialFormData = ref<T>(safeClone(props.modelValue ?? {}) as T)
37
37
 
38
38
  onMounted(() => {
39
- console.log('formData.value')
40
39
  if (props.modelValue) {
41
40
  initialFormData.value = safeClone(props.modelValue)
42
41
  }
@@ -1,9 +1,7 @@
1
1
  <script setup lang="ts">
2
- import type { VueDatePickerProps, DatePickerInstance } from '@vuepic/vue-datepicker'
3
- import VDatepicker from '@vuepic/vue-datepicker'
4
- import { onMounted } from 'vue'
5
-
6
- import '@vuepic/vue-datepicker/dist/main.css'
2
+ import type { modeType } from '../../Calendar/typings/types'
3
+ import { Btn, NumberInput, Dropdown, TextInput } from '@bagelink/vue'
4
+ import Time, { WEEK_START_DAY } from '../../Calendar/helpers/Time'
7
5
 
8
6
  const props = withDefaults(
9
7
  defineProps<{
@@ -13,84 +11,465 @@ const props = withDefaults(
13
11
  small?: boolean
14
12
  enableTime?: boolean
15
13
  modelValue?: string | Date
16
- defaultValue?: string | Date
17
- extraProps?: Omit<VueDatePickerProps, 'Slots' | 'InternalTime'>
18
- allowedDates?: string[] | Date[]
19
- timePickerInline?: boolean
20
- minutesIncrement?: string | number
21
- minutesGridIncrement?: string | number
14
+ min?: string | Date
15
+ max?: string | Date
16
+ timezone?: string
17
+ mode?: modeType
18
+ firstDayOfWeek?: WEEK_START_DAY
19
+ locale?: string
20
+ center?: boolean
21
+
22
22
  }>(),
23
23
  {
24
24
  enableTime: false,
25
25
  editMode: true,
26
26
  small: false,
27
+ timezone: 'UTC',
28
+ mode: 'day',
29
+ firstDayOfWeek: WEEK_START_DAY.MONDAY,
30
+ locale: ''
27
31
  },
28
32
  )
29
33
 
30
34
  const emit = defineEmits(['update:modelValue'])
35
+ let isOpen = $ref(false)
36
+ let currentMonth = $ref(new Date())
37
+ type ViewMode = 'days' | 'months' | 'years'
38
+ let currentView = $ref<ViewMode>('days')
31
39
 
32
- const datePicker = $ref<DatePickerInstance>()
33
-
34
- const date = $computed<string | Date>({
35
- get: () => props.modelValue || '',
36
- set: (val) => {
37
- const d = typeof val === 'string' ? new Date(val) : val
38
- if (props.enableTime) {
39
- emit('update:modelValue', d.toISOString())
40
- } else {
41
- emit('update:modelValue', d.toISOString().split('T')[0])
42
- }
43
- },
40
+ const time = new Time(props.firstDayOfWeek, props.locale)
41
+
42
+ function formatDisplayDate(date: Date | string | undefined): string {
43
+ if (!date) return ''
44
+ const dateObj = typeof date === 'string' ? new Date(date) : date
45
+
46
+ if (props.enableTime) {
47
+ return dateObj.toLocaleString(props.locale || undefined, {
48
+ year: 'numeric',
49
+ month: 'short',
50
+ day: 'numeric',
51
+ hour: '2-digit',
52
+ minute: '2-digit',
53
+ timeZone: props.timezone
54
+ })
55
+ }
56
+
57
+ return dateObj.toLocaleString(props.locale || undefined, {
58
+ year: 'numeric',
59
+ month: 'short',
60
+ day: 'numeric',
61
+ timeZone: props.timezone
62
+ })
63
+ }
64
+
65
+ function formatDate(date: Date | string | undefined): string {
66
+ if (!date) return ''
67
+ const dateObj = typeof date === 'string' ? new Date(date) : date
68
+ return props.enableTime ? dateObj.toISOString().slice(0, 16) : dateObj.toISOString().split('T')[0]
69
+ }
70
+
71
+ const formattedDisplayValue = $computed(() => formatDisplayDate(props.modelValue))
72
+ const formattedMin = $computed(() => formatDate(props.min))
73
+ const formattedMax = $computed(() => formatDate(props.max))
74
+
75
+ const selectedDate = $computed(() => {
76
+ if (!props.modelValue) return null
77
+ return typeof props.modelValue === 'string' ? new Date(props.modelValue) : props.modelValue
44
78
  })
45
79
 
46
- onMounted(() => {
47
- if (
48
- props.defaultValue && date === ''
49
- ) {
50
- Object.assign(date, { date: props.defaultValue })
80
+ const currentMonthDays = $computed(() => {
81
+ const year = currentMonth.getFullYear()
82
+ const month = currentMonth.getMonth()
83
+ return time.getCalendarMonthSplitInWeeks(year, month).flat()
84
+ })
85
+
86
+ const currentMonthValue = $computed(() => ({
87
+ month: currentMonth.getMonth(),
88
+ year: currentMonth.getFullYear(),
89
+ formatted: {
90
+ month: time.getLocalizedNameOfMonth(currentMonth, 'long'),
91
+ year: time.getLocalizedDateString(currentMonth).split('/').pop() // Get just the year part
92
+ }
93
+ }))
94
+
95
+ const months = $computed(() => Array.from({ length: 12 }, (_, i) => {
96
+ const date = new Date(currentMonthValue.year, i, 1)
97
+ return {
98
+ name: time.getLocalizedNameOfMonth(date, 'short'),
99
+ value: i,
100
+ disabled: isDateDisabled(date)
51
101
  }
102
+ }))
103
+
104
+ const years = $computed(() => {
105
+ const startYear = currentMonthValue.year - 10
106
+ return Array.from({ length: 21 }, (_, i) => ({
107
+ value: startYear + i,
108
+ disabled: isYearDisabled(startYear + i)
109
+ }))
52
110
  })
111
+
112
+ const weekDays = $computed(() => {
113
+ const weekStart = new Date()
114
+ weekStart.setDate(weekStart.getDate() - weekStart.getDay() + (props.firstDayOfWeek === WEEK_START_DAY.MONDAY ? 1 : 0))
115
+ return Array.from({ length: 7 }, (_, i) => {
116
+ const day = new Date(weekStart)
117
+ day.setDate(weekStart.getDate() + i)
118
+ return time.getLocalizedNameOfWeekday(day, 'short')
119
+ })
120
+ })
121
+
122
+ function isDateDisabled(date: Date | null) {
123
+ if (!date) return true
124
+ const minDate = props.min ? new Date(props.min) : null
125
+ const maxDate = props.max ? new Date(props.max) : null
126
+
127
+ if (minDate && date < minDate) return true
128
+ if (maxDate && date > maxDate) return true
129
+ return false
130
+ }
131
+
132
+ function isYearDisabled(year: number) {
133
+ const minDate = props.min ? new Date(props.min) : null
134
+ const maxDate = props.max ? new Date(props.max) : null
135
+
136
+ if (minDate && year < minDate.getFullYear()) return true
137
+ if (maxDate && year > maxDate.getFullYear()) return true
138
+ return false
139
+ }
140
+
141
+ function selectMonth(monthIndex: number) {
142
+ currentMonth = new Date(currentMonth.getFullYear(), monthIndex, 1)
143
+ currentView = 'days'
144
+ }
145
+
146
+ function selectYear(year: number) {
147
+ currentMonth = new Date(year, currentMonth.getMonth(), 1)
148
+ currentView = 'months'
149
+ }
150
+
151
+ function previousMonth() {
152
+ currentMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1, 1)
153
+ }
154
+
155
+ function nextMonth() {
156
+ currentMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, 1)
157
+ }
158
+
159
+ function previousYear() {
160
+ const offset = currentView === 'months' ? 1 : 21
161
+ currentMonth = new Date(currentMonth.getFullYear() - offset, currentMonth.getMonth(), 1)
162
+ }
163
+
164
+ function nextYear() {
165
+ const offset = currentView === 'months' ? 1 : 21
166
+ currentMonth = new Date(currentMonth.getFullYear() + offset, currentMonth.getMonth(), 1)
167
+ }
168
+
169
+ function selectDate(date: Date | null) {
170
+ if (!date || !props.editMode) return
171
+
172
+ // Create date at start of day in the target timezone
173
+ const newDate = new Date(date.getFullYear(), date.getMonth(), date.getDate())
174
+
175
+ // If time is enabled, preserve existing time or set to current time
176
+ if (props.enableTime) {
177
+ const currentHours = selectedDate?.getHours() ?? new Date().getHours()
178
+ const currentMinutes = selectedDate?.getMinutes() ?? new Date().getMinutes()
179
+ newDate.setHours(currentHours)
180
+ newDate.setMinutes(currentMinutes)
181
+ emit('update:modelValue', newDate.toISOString())
182
+ } else {
183
+ // For dates without time, ensure time is set to midnight UTC
184
+ newDate.setUTCHours(0, 0, 0, 0)
185
+ emit('update:modelValue', newDate.toISOString().split('T')[0])
186
+ isOpen = false
187
+ }
188
+ }
189
+
190
+ function handleInput(event: Event) {
191
+ const input = event.target as HTMLInputElement
192
+ if (!input.value) {
193
+ emit('update:modelValue', '')
194
+ return
195
+ }
196
+
197
+ const date = new Date(input.value)
198
+ emit('update:modelValue', props.enableTime ? date.toISOString() : date.toISOString().split('T')[0])
199
+ }
200
+
201
+ const hours = $computed(() => selectedDate?.getHours() ?? 0)
202
+ const minutes = $computed(() => selectedDate?.getMinutes() ?? 0)
203
+
204
+ function handleHourInput(value: number) {
205
+ if (!selectedDate) return
206
+ const newDate = new Date(selectedDate)
207
+ newDate.setHours(value)
208
+ emit('update:modelValue', newDate.toISOString())
209
+ }
210
+
211
+ function handleMinuteInput(value: number) {
212
+ if (!selectedDate) return
213
+ const newDate = new Date(selectedDate)
214
+ newDate.setMinutes(value)
215
+ emit('update:modelValue', newDate.toISOString())
216
+ }
217
+
218
+ function isSelected(date: Date | null) {
219
+ if (!date || !selectedDate) return false
220
+ return date.toISOString().split('T')[0] === selectedDate.toISOString().split('T')[0]
221
+ }
222
+
223
+ function isToday(date: Date | null) {
224
+ if (!date) return false
225
+ return time.dateIsToday(date)
226
+ }
227
+
228
+ const timezoneDisplay = $computed(() => {
229
+ if (!props.enableTime) return ''
230
+ try {
231
+ return new Date().toLocaleString('en-US', {
232
+ timeZoneName: 'short',
233
+ timeZone: props.timezone
234
+ }).split(' ').pop()
235
+ } catch {
236
+ return 'UTC'
237
+ }
238
+ })
239
+
240
+ function isNotInMonth(date: Date) {
241
+ return time.isTrailingOrLeadingDate(date, currentMonth.getMonth())
242
+ }
53
243
  </script>
54
244
 
55
245
  <template>
56
- <div
57
- class="bagel-input"
58
- :title="label"
59
- :class="{ small }"
60
- >
246
+ <div class="bagel-input" :class="{ small }" :title="label">
61
247
  <label v-if="label">
62
248
  {{ label }}
249
+ <span v-if="required" class="required">*</span>
63
250
  </label>
64
- <VDatepicker
65
- ref="datePicker"
66
- v-model="date"
67
- :required="required"
68
- :auto-apply="true"
69
- :enable-time-picker="enableTime"
70
- :allowed-dates="allowedDates"
71
- v-bind="extraProps"
72
- :time-picker-inline="timePickerInline"
73
- :minutes-increment="minutesIncrement"
74
- :minutes-grid-increment="minutesGridIncrement"
75
- :start-time="{ hours: 8, minutes: 0 }"
76
- />
251
+
252
+ <Dropdown
253
+ :shown="isOpen"
254
+ placement="bottom-start"
255
+ @apply-show="isOpen = true"
256
+ @apply-hide="isOpen = false"
257
+ >
258
+ <template #trigger>
259
+ <div class="date-picker-container">
260
+ <TextInput
261
+ :modelValue="formattedDisplayValue"
262
+ icon="calendar"
263
+ :min="formattedMin"
264
+ :max="formattedMax"
265
+ :required="required"
266
+ :disabled="!editMode"
267
+ class="date-input"
268
+ :class="{
269
+ 'txt-center': center }"
270
+ readonly
271
+ @click="isOpen = true"
272
+ />
273
+ </div>
274
+ </template>
275
+
276
+ <div class="flex gap-075 p-05 m_flex-wrap calendar-container justify-content-center h-100p">
277
+ <div class="calendar-section m_border-none pe-05 m_p-0">
278
+ <div class="flex space-between pb-1">
279
+ <template v-if="currentView === 'days'">
280
+ <Btn flat icon="chevron_left" @click="previousMonth" />
281
+ <div class="flex gap-05">
282
+ <Btn flat class="month-btn" @click="currentView = 'months'">
283
+ {{ currentMonthValue.formatted.month }}
284
+ </Btn>
285
+ <Btn flat class="year-btn" @click="currentView = 'years'">
286
+ {{ currentMonthValue.formatted.year }}
287
+ </Btn>
288
+ </div>
289
+ <Btn flat icon="chevron_right" @click="nextMonth" />
290
+ </template>
291
+ <template v-else>
292
+ <Btn flat icon="chevron_left" @click="previousYear" />
293
+ <span class="month-year">{{ currentMonthValue.formatted.year }}</span>
294
+ <Btn flat icon="chevron_right" @click="nextYear" />
295
+ </template>
296
+ </div>
297
+
298
+ <div v-if="currentView === 'days'" class="calendar-grid grid gap-025">
299
+ <div
300
+ v-for="day in weekDays"
301
+ :key="day"
302
+ class="txt-center txt-12 opacity-6"
303
+ >
304
+ {{ day }}
305
+ </div>
306
+
307
+ <button
308
+ v-for="date in currentMonthDays"
309
+ :key="date?.toISOString()"
310
+ type="button"
311
+ class="day aspect-ratio-1 flex align-items-center justify-content-center pointer round txt14 p-0"
312
+ :class="{
313
+ 'selected': isSelected(date),
314
+ 'today': isToday(date),
315
+ 'disabled': isDateDisabled(date),
316
+ 'not-in-month': isNotInMonth(date),
317
+ }"
318
+ :disabled="isDateDisabled(date)"
319
+ @click="selectDate(date)"
320
+ >
321
+ {{ date?.getDate() }}
322
+ </button>
323
+ </div>
324
+
325
+ <div v-else-if="currentView === 'months'" class="month-grid grid gap-05 p-05">
326
+ <button
327
+ v-for="month in months"
328
+ :key="month.value"
329
+ class="month-item flex align-items-center justify-content-center pointer rounded p-05 txt14 border-none"
330
+ :class="{
331
+ selected: month.value === currentMonthValue.month,
332
+ disabled: month.disabled,
333
+ }"
334
+ :disabled="month.disabled"
335
+ @click="selectMonth(month.value)"
336
+ >
337
+ {{ month.name }}
338
+ </button>
339
+ </div>
340
+
341
+ <div v-else class="year-grid grid gap-05 p-0">
342
+ <button
343
+ v-for="year in years"
344
+ :key="year.value"
345
+ class="year-item flex align-items-center justify-content-center pointer rounded p-05 txt14 border-none"
346
+ :class="{
347
+ selected: year.value === currentMonthValue.year,
348
+ disabled: year.disabled,
349
+ }"
350
+ :disabled="year.disabled"
351
+ @click="selectYear(year.value)"
352
+ >
353
+ {{ year.value }}
354
+ </button>
355
+ </div>
356
+ </div>
357
+
358
+ <div v-if="enableTime && currentView === 'days'" class="time-picker border-start flex column gap-1 w-120px">
359
+ <div class="flex gap-025">
360
+ <NumberInput
361
+ center
362
+ :model-value="hours"
363
+ :disabled="!selectedDate"
364
+ :min="0"
365
+ :max="23"
366
+ layout="vertical"
367
+ :padZero="2"
368
+ @update:model-value="handleHourInput"
369
+ />
370
+ <p class="pb-075">
371
+ :
372
+ </p>
373
+ <NumberInput
374
+ center
375
+ :model-value="minutes"
376
+ :disabled="!selectedDate"
377
+ :min="0"
378
+ :max="59"
379
+ :padZero="2"
380
+ layout="vertical"
381
+ @update:model-value="handleMinuteInput"
382
+ />
383
+ </div>
384
+ <span class="txt-center opacity-6 txt14">{{ timezoneDisplay }}</span>
385
+ <Btn v-if="selectedDate" flat @click="isOpen = false">
386
+ Done
387
+ </Btn>
388
+ </div>
389
+ </div>
390
+ </Dropdown>
77
391
  </div>
78
392
  </template>
79
393
 
80
- <style>
81
- .dp__input_wrap input {
82
- padding-inline-start: 2rem !important;
394
+ <style scoped>
395
+ .calendar-container {
396
+ max-width: 90vw;
397
+ }
398
+
399
+ .calendar-section {
400
+ min-width: 280px;
401
+ }
402
+
403
+ .calendar-grid {
404
+ grid-template-columns: repeat(7, 1fr);
405
+ }
406
+
407
+ .month-grid {
408
+ grid-template-columns: repeat(3, 1fr);
409
+ grid-template-rows: repeat(4, 1fr);
410
+ }
411
+
412
+ .year-grid {
413
+ grid-template-columns: repeat(3, 1fr);
414
+ grid-template-rows: repeat(7, 1fr);
415
+ }
416
+
417
+ .month-item,
418
+ .year-item {
419
+ background: none;
420
+ color: var(--bgl-text-color);
421
+ }
422
+
423
+ .month-item:hover:not(.disabled),
424
+ .year-item:hover:not(.disabled) {
425
+ background: var(--bgl-box-bg);
426
+ filter: var(--bgl-hover-filter);
427
+ }
428
+
429
+ .month-item:active:not(.disabled),
430
+ .year-item:active:not(.disabled) {
431
+ background: var(--bgl-box-bg);
432
+ filter: var(--bgl-active-filter);
433
+ }
434
+
435
+ .month-item.selected,
436
+ .year-item.selected {
437
+ background-color: var(--bgl-primary);
438
+ color: white;
439
+ }
440
+
441
+ .month-item.disabled,
442
+ .year-item.disabled {
443
+ opacity: 0.6;
444
+ filter: grayscale(0.3);
445
+ }
446
+
447
+ .day {
448
+ border: none;
449
+ background: none;
450
+ color: var(--bgl-text-color);
451
+ }
452
+
453
+ .day:hover:not(.disabled) {
454
+ background-color: var(--input-bg);
455
+ }
456
+
457
+ .day.selected {
458
+ background-color: var(--bgl-primary);
459
+ color: var(--bgl-white);
83
460
  }
84
461
 
85
- .dp__calendar_row>div:last-child {
86
- pointer-events: auto !important;
462
+ .day.today:not(.selected) {
463
+ border: 1px solid var(--bgl-primary);
87
464
  }
88
465
 
89
- .dp__time_input {
90
- direction: ltr;
466
+ .day.disabled {
467
+ opacity: 0.6;
468
+ filter: grayscale(0.3);
469
+ cursor: not-allowed;
91
470
  }
92
471
 
93
- .ltrDateInput input {
94
- direction: ltr;
472
+ .day.not-in-month {
473
+ opacity: 0.4;
95
474
  }
96
475
  </style>
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import type { IconType } from '@bagelink/vue'
3
3
  import { Icon, Btn } from '@bagelink/vue'
4
- import { watch } from 'vue'
4
+ import { onMounted, watch } from 'vue'
5
5
 
6
6
  type NumberLayout = 'default' | 'vertical' | 'horizontal'
7
7
 
@@ -14,6 +14,7 @@ interface NumberInputProps {
14
14
  iconStart?: IconType
15
15
  icon?: IconType
16
16
  label?: string
17
+ defaultValue?: number
17
18
  placeholder?: string
18
19
  disabled?: boolean
19
20
  required?: boolean
@@ -40,11 +41,18 @@ const {
40
41
  layout,
41
42
  id,
42
43
  padZero = 1,
44
+ defaultValue
43
45
  } = defineProps<NumberInputProps>()
44
46
 
45
47
  const emit = defineEmits(['update:modelValue'])
46
48
 
47
- let numberValue = $ref(Number.parseFloat(`${modelValue}`) || undefined)
49
+ let numberValue = $ref<number>()
50
+
51
+ onMounted(() => {
52
+ const num = modelValue !== undefined ? Number.parseFloat(`${modelValue}`) : undefined
53
+ const defaultNum = defaultValue !== undefined ? Number.parseFloat(`${defaultValue}`) : undefined
54
+ numberValue = num || defaultNum
55
+ })
48
56
 
49
57
  const btnLayouts: NumberLayout[] = ['horizontal', 'vertical']
50
58
 
@@ -23,10 +23,9 @@ function handlePaste(event: ClipboardEvent, index: number) {
23
23
  }
24
24
 
25
25
  function emitUpdate() {
26
+ emit('update:modelValue', digits.join(''))
26
27
  if (isDigitsFull()) {
27
28
  emit('complete', digits.join(''))
28
- } else {
29
- emit('update:modelValue', digits.join(''))
30
29
  }
31
30
  }
32
31
 
@@ -93,7 +92,7 @@ function isDigitsFull() {
93
92
  :autofocus="ind === 0"
94
93
  maxlength="1"
95
94
  pattern="[0-9]*"
96
- oninput="this.value = this.value.slice(0, 1);"
95
+ oninput="this.value = this.value.slice(0, 1)"
97
96
  @keydown="handleKeyDown($event, ind)"
98
97
  @paste="handlePaste($event, ind)"
99
98
  >