@bagelink/vue 1.6.43 → 1.6.49
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/bin/experimentalGenTypedRoutes.ts +18 -19
- package/bin/utils.ts +4 -4
- package/dist/components/AddressSearch.vue.d.ts.map +1 -1
- package/dist/components/Alert.vue.d.ts.map +1 -1
- package/dist/components/BglVideo.vue.d.ts.map +1 -1
- package/dist/components/Card.vue.d.ts.map +1 -1
- package/dist/components/Carousel.vue.d.ts +2 -2
- package/dist/components/Carousel.vue.d.ts.map +1 -1
- package/dist/components/Dropdown.vue.d.ts.map +1 -1
- package/dist/components/Flag.vue.d.ts.map +1 -1
- package/dist/components/IframeVue.vue.d.ts.map +1 -1
- package/dist/components/ListItem.vue.d.ts.map +1 -1
- package/dist/components/Loading.vue.d.ts.map +1 -1
- package/dist/components/Modal.vue.d.ts.map +1 -1
- package/dist/components/ModalForm.vue.d.ts.map +1 -1
- package/dist/components/NavBar.vue.d.ts +1 -1
- package/dist/components/Pill.vue.d.ts.map +1 -1
- package/dist/components/Swiper.vue.d.ts +12 -4
- package/dist/components/Swiper.vue.d.ts.map +1 -1
- package/dist/components/Zoomer.vue.d.ts.map +1 -1
- package/dist/components/analytics/LineChart.vue.d.ts.map +1 -1
- package/dist/components/analytics/PieChart.vue.d.ts +2 -1
- package/dist/components/analytics/PieChart.vue.d.ts.map +1 -1
- package/dist/components/analytics/index.d.ts +1 -1
- package/dist/components/analytics/index.d.ts.map +1 -1
- package/dist/components/calendar/CalendarPopover.vue.d.ts.map +1 -1
- package/dist/components/form/BglMultiStepForm.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/ColorInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/DateInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/PasswordInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RadioGroup.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RangeInput.vue.d.ts +11 -11
- package/dist/components/form/inputs/RichText/components/EditorToolbar.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RichText/components/TableGridSelector.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RichText/utils/commands.d.ts.map +1 -1
- package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/TelInput.vue.d.ts.map +1 -1
- package/dist/components/layout/AppContent.vue.d.ts.map +1 -1
- package/dist/components/layout/AppSidebar.vue.d.ts +1 -0
- package/dist/components/layout/AppSidebar.vue.d.ts.map +1 -1
- package/dist/components/layout/Layout.vue.d.ts.map +1 -1
- package/dist/components/layout/Tabs.vue.d.ts.map +1 -1
- package/dist/components/layout/index.d.ts +3 -3
- package/dist/components/layout/index.d.ts.map +1 -1
- package/dist/components/lightbox/Lightbox.vue.d.ts.map +1 -1
- package/dist/index.cjs +24 -15
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +1530 -1404
- package/dist/plugins/modalTypes.d.ts +1 -8
- package/dist/plugins/modalTypes.d.ts.map +1 -1
- package/dist/plugins/useModal.d.ts.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -2
- package/src/components/AccordionItem.vue +13 -13
- package/src/components/AddToCalendar.vue +1 -1
- package/src/components/AddressSearch.vue +9 -8
- package/src/components/Alert.vue +2 -1
- package/src/components/Badge.vue +5 -5
- package/src/components/BglVideo.vue +44 -45
- package/src/components/Btn.vue +15 -15
- package/src/components/Card.vue +10 -8
- package/src/components/Carousel.vue +159 -162
- package/src/components/DataPreview.vue +1 -1
- package/src/components/DragOver.vue +6 -6
- package/src/components/Dropdown.vue +39 -38
- package/src/components/Flag.vue +7 -6
- package/src/components/Icon/Icon.vue +22 -22
- package/src/components/IframeVue.vue +5 -5
- package/src/components/Image.vue +17 -17
- package/src/components/ImportData.vue +79 -79
- package/src/components/ListItem.vue +12 -11
- package/src/components/Loading.vue +10 -9
- package/src/components/MapEmbed/Index.vue +24 -24
- package/src/components/Modal.vue +11 -9
- package/src/components/ModalForm.vue +15 -11
- package/src/components/NavBar.vue +6 -6
- package/src/components/Pagination.vue +27 -27
- package/src/components/Pill.vue +11 -12
- package/src/components/Rating.vue +2 -2
- package/src/components/Slider.vue +75 -75
- package/src/components/Spreadsheet/Index.vue +34 -34
- package/src/components/Spreadsheet/SpreadsheetTable.vue +3 -3
- package/src/components/Swiper.vue +4 -4
- package/src/components/Zoomer.vue +282 -182
- package/src/components/analytics/BarChart.vue +6 -6
- package/src/components/analytics/KpiCard.vue +2 -2
- package/src/components/analytics/LineChart.vue +63 -61
- package/src/components/analytics/PieChart.vue +104 -90
- package/src/components/analytics/index.ts +2 -2
- package/src/components/calendar/CalendarPopover.vue +1 -1
- package/src/components/calendar/Index.vue +1 -1
- package/src/components/calendar/views/AgendaView.vue +3 -3
- package/src/components/calendar/views/DayView.vue +6 -6
- package/src/components/calendar/views/MonthView.vue +2 -2
- package/src/components/calendar/views/WeekView.vue +18 -18
- package/src/components/dataTable/DataTable.vue +4 -4
- package/src/components/dataTable/useSorting.ts +1 -1
- package/src/components/dataTable/useTableData.ts +15 -15
- package/src/components/dataTable/useTableSelection.ts +15 -15
- package/src/components/dataTable/useTableVirtualization.ts +1 -1
- package/src/components/draggable/useDraggable.ts +42 -42
- package/src/components/form/BagelForm.vue +15 -15
- package/src/components/form/BglFieldSet.vue +5 -3
- package/src/components/form/BglMultiStepForm.vue +20 -21
- package/src/components/form/inputs/CheckInput.vue +2 -2
- package/src/components/form/inputs/CodeEditor/format.ts +7 -7
- package/src/components/form/inputs/CodeEditor/useHighlight.ts +6 -6
- package/src/components/form/inputs/ColorInput.vue +5 -4
- package/src/components/form/inputs/DateInput.vue +8 -9
- package/src/components/form/inputs/DatePicker.vue +24 -24
- package/src/components/form/inputs/EmailInput.vue +24 -24
- package/src/components/form/inputs/NumberInput.vue +26 -26
- package/src/components/form/inputs/OTP.vue +7 -7
- package/src/components/form/inputs/PasswordInput.vue +3 -2
- package/src/components/form/inputs/RadioGroup.vue +28 -25
- package/src/components/form/inputs/RadioPillsInput.vue +12 -12
- package/src/components/form/inputs/RangeInput.vue +21 -21
- package/src/components/form/inputs/RichText/components/EditorToolbar.vue +107 -92
- package/src/components/form/inputs/RichText/components/TableGridSelector.vue +64 -64
- package/src/components/form/inputs/RichText/components/gridBox.vue +10 -8
- package/src/components/form/inputs/RichText/composables/useCommands.ts +1 -1
- package/src/components/form/inputs/RichText/composables/useEditor.ts +12 -12
- package/src/components/form/inputs/RichText/composables/useEditorKeyboard.ts +1 -1
- package/src/components/form/inputs/RichText/index.vue +138 -138
- package/src/components/form/inputs/RichText/utils/commands.ts +84 -85
- package/src/components/form/inputs/RichText/utils/debug.ts +1 -1
- package/src/components/form/inputs/RichText/utils/formatting.ts +39 -39
- package/src/components/form/inputs/RichText/utils/media.ts +7 -7
- package/src/components/form/inputs/RichText/utils/selection.ts +28 -28
- package/src/components/form/inputs/RichText/utils/table.ts +19 -19
- package/src/components/form/inputs/SelectBtn.vue +1 -1
- package/src/components/form/inputs/SelectInput.vue +54 -54
- package/src/components/form/inputs/SignaturePad.vue +40 -40
- package/src/components/form/inputs/TableField.vue +1 -1
- package/src/components/form/inputs/TelInput.vue +54 -53
- package/src/components/form/inputs/TextInput.vue +19 -19
- package/src/components/form/inputs/ToggleInput.vue +2 -2
- package/src/components/form/inputs/Upload/useFileUpload.ts +6 -6
- package/src/components/form/useBagelFormState.ts +5 -5
- package/src/components/layout/AppContent.vue +6 -3
- package/src/components/layout/AppLayout.vue +2 -2
- package/src/components/layout/AppSidebar.vue +83 -16
- package/src/components/layout/Layout.vue +12 -10
- package/src/components/layout/SidebarMenu.vue +4 -4
- package/src/components/layout/TabbedLayout.vue +17 -17
- package/src/components/layout/Tabs.vue +4 -5
- package/src/components/layout/TabsNav.vue +14 -14
- package/src/components/layout/index.ts +3 -5
- package/src/components/lightbox/Lightbox.vue +276 -126
- package/src/components/lightbox/index.ts +8 -8
- package/src/composables/index.ts +8 -8
- package/src/composables/useAddToCalendar.ts +13 -13
- package/src/composables/useDevice.ts +2 -2
- package/src/composables/useFormField.ts +4 -4
- package/src/composables/usePolling.ts +8 -8
- package/src/composables/useSchemaField.ts +38 -38
- package/src/composables/useTheme.ts +9 -9
- package/src/composables/useValidateFieldValue.ts +2 -2
- package/src/directives/pattern.ts +25 -25
- package/src/directives/ripple.ts +4 -4
- package/src/directives/vResize.ts +6 -6
- package/src/index.ts +1 -0
- package/src/plugins/bagel.ts +4 -4
- package/src/plugins/modalTypes.ts +1 -8
- package/src/plugins/useModal.ts +43 -18
- package/src/styles/layout.css +1 -1
- package/src/types/index.ts +1 -1
- package/src/utils/BagelFormUtils.ts +7 -7
- package/src/utils/calendar/Helpers.ts +8 -8
- package/src/utils/calendar/dateUtils.ts +22 -22
- package/src/utils/calendar/time.ts +25 -25
- package/src/utils/calendar/week.ts +25 -25
- package/src/utils/elementUtils.ts +27 -27
- package/src/utils/sizeParsing.ts +2 -2
- package/src/utils/strings.ts +5 -5
- package/src/utils/tapDetector.ts +11 -11
- package/src/utils/useSearch.ts +29 -29
- package/vite.config.ts +0 -2
|
@@ -45,7 +45,7 @@ const isOpen = ref(false)
|
|
|
45
45
|
// Date formatting composable
|
|
46
46
|
function useFormatting() {
|
|
47
47
|
const formatDisplayDate = (date: Date | string | undefined): string => {
|
|
48
|
-
if (!date) {return ''}
|
|
48
|
+
if (!date) { return '' }
|
|
49
49
|
return formatDate(date, { fmt: props.enableTime ? 'DD.MM.YY HH:mm' : 'DD.MM.YY' })
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -58,7 +58,7 @@ function useFormatting() {
|
|
|
58
58
|
|
|
59
59
|
// Try DD/MM/YYYY format
|
|
60
60
|
const parts = input.split(/[/.-]/)
|
|
61
|
-
if (
|
|
61
|
+
if (parts.length === 3) {
|
|
62
62
|
const [day, month, year] = parts.map(p => Number.parseInt(p, 10))
|
|
63
63
|
if (!Number.isNaN(day) && !Number.isNaN(month) && !Number.isNaN(year)) {
|
|
64
64
|
const parsedDate = new Date(year, month - 1, day)
|
|
@@ -80,11 +80,10 @@ function useFormatting() {
|
|
|
80
80
|
// Keep the time when time is enabled
|
|
81
81
|
return date.toISOString()
|
|
82
82
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
// Normalize to midnight to emit exact date without time for server compatibility
|
|
84
|
+
const normalizedDate = new Date(date)
|
|
85
|
+
normalizedDate.setHours(0, 0, 0, 0)
|
|
86
|
+
return normalizedDate.toISOString().split('T')[0]
|
|
88
87
|
}
|
|
89
88
|
|
|
90
89
|
return {
|
|
@@ -123,9 +122,9 @@ function useInputHandling() {
|
|
|
123
122
|
}
|
|
124
123
|
|
|
125
124
|
const handleKeydown = (event: KeyboardEvent) => {
|
|
126
|
-
if ('Escape'
|
|
125
|
+
if (event.key === 'Escape') {
|
|
127
126
|
isOpen.value = false
|
|
128
|
-
} else if ('Enter'
|
|
127
|
+
} else if (event.key === 'Enter' && inputValue.value) {
|
|
129
128
|
const date = parseUserInput(inputValue.value)
|
|
130
129
|
if (date) {
|
|
131
130
|
selectedDate.value = normalizeDate(date)
|
|
@@ -28,8 +28,8 @@ const props = withDefaults(
|
|
|
28
28
|
|
|
29
29
|
const emit = defineEmits(['update:modelValue'])
|
|
30
30
|
|
|
31
|
-
const computedHighlightedDates =
|
|
32
|
-
const computedDisabledDates =
|
|
31
|
+
const computedHighlightedDates = computed(() => toValue(props.highlightedDates))
|
|
32
|
+
const computedDisabledDates = computed(() => toValue(props.disabledDates))
|
|
33
33
|
|
|
34
34
|
// State
|
|
35
35
|
const currentMonth = ref(new Date())
|
|
@@ -40,34 +40,34 @@ const time = new Time(props.firstDayOfWeek, props.locale)
|
|
|
40
40
|
|
|
41
41
|
// Parse a date string or object into a Date object
|
|
42
42
|
function parseDate(value: string | Date | undefined): Date | null {
|
|
43
|
-
if (!value) {return null}
|
|
44
|
-
const date = 'string'
|
|
43
|
+
if (!value) { return null }
|
|
44
|
+
const date = typeof value === 'string' ? new Date(value) : value
|
|
45
45
|
return Number.isNaN(date.getTime()) ? null : date
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
// Date validation composable
|
|
49
49
|
function useDateValidation() {
|
|
50
50
|
const isDateDisabled = (date: Date | null) => {
|
|
51
|
-
if (!date) {return true}
|
|
51
|
+
if (!date) { return true }
|
|
52
52
|
const minDate = parseDate(props.min)
|
|
53
53
|
const maxDate = parseDate(props.max)
|
|
54
54
|
|
|
55
55
|
// Check if date is in min/max range
|
|
56
|
-
if (minDate && date < minDate) {return true}
|
|
57
|
-
if (maxDate && date > maxDate) {return true}
|
|
56
|
+
if (minDate && date < minDate) { return true }
|
|
57
|
+
if (maxDate && date > maxDate) { return true }
|
|
58
58
|
|
|
59
59
|
// Check if date is in the disabled dates array
|
|
60
|
-
if (Array.isArray(computedDisabledDates) &&
|
|
61
|
-
const isInDisabledDates = computedDisabledDates.some((disabledDate) => {
|
|
60
|
+
if (Array.isArray(computedDisabledDates.value) && computedDisabledDates.value.length > 0) {
|
|
61
|
+
const isInDisabledDates = computedDisabledDates.value.some((disabledDate) => {
|
|
62
62
|
const parsedDisabledDate = parseDate(disabledDate)
|
|
63
|
-
if (!parsedDisabledDate) {return false}
|
|
63
|
+
if (!parsedDisabledDate) { return false }
|
|
64
64
|
|
|
65
65
|
// Compare year, month, and day
|
|
66
66
|
return date.getFullYear() === parsedDisabledDate.getFullYear()
|
|
67
67
|
&& date.getMonth() === parsedDisabledDate.getMonth()
|
|
68
68
|
&& date.getDate() === parsedDisabledDate.getDate()
|
|
69
69
|
})
|
|
70
|
-
if (isInDisabledDates) {return true}
|
|
70
|
+
if (isInDisabledDates) { return true }
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
return false
|
|
@@ -77,8 +77,8 @@ function useDateValidation() {
|
|
|
77
77
|
const minDate = parseDate(props.min)
|
|
78
78
|
const maxDate = parseDate(props.max)
|
|
79
79
|
|
|
80
|
-
if (minDate && year < minDate.getFullYear()) {return true}
|
|
81
|
-
if (maxDate && year > maxDate.getFullYear()) {return true}
|
|
80
|
+
if (minDate && year < minDate.getFullYear()) { return true }
|
|
81
|
+
if (maxDate && year > maxDate.getFullYear()) { return true }
|
|
82
82
|
return false
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -114,7 +114,7 @@ function useCalendarView() {
|
|
|
114
114
|
|
|
115
115
|
// Always ensure we have 6 rows (42 days) in our calendar
|
|
116
116
|
// If we have less than 6 weeks, add extra week(s) from the next month
|
|
117
|
-
while (
|
|
117
|
+
while (weeksInMonth.length < 6) {
|
|
118
118
|
const lastWeek = weeksInMonth[weeksInMonth.length - 1]
|
|
119
119
|
const lastDay = lastWeek[lastWeek.length - 1]
|
|
120
120
|
const nextDay = new Date(lastDay.getFullYear(), lastDay.getMonth(), lastDay.getDate() + 1)
|
|
@@ -163,14 +163,14 @@ function useCalendarView() {
|
|
|
163
163
|
})
|
|
164
164
|
|
|
165
165
|
const isSelected = (date: Date | null) => {
|
|
166
|
-
if (!date || !selectedDate.value) {return false}
|
|
166
|
+
if (!date || !selectedDate.value) { return false }
|
|
167
167
|
return date.getFullYear() === selectedDate.value.getFullYear()
|
|
168
168
|
&& date.getMonth() === selectedDate.value.getMonth()
|
|
169
169
|
&& date.getDate() === selectedDate.value.getDate()
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
const isToday = (date: Date | null) => {
|
|
173
|
-
if (!date) {return false}
|
|
173
|
+
if (!date) { return false }
|
|
174
174
|
return time.dateIsToday(date)
|
|
175
175
|
}
|
|
176
176
|
|
|
@@ -184,13 +184,13 @@ function useCalendarView() {
|
|
|
184
184
|
* @returns True if the date should be highlighted
|
|
185
185
|
*/
|
|
186
186
|
const isHighlighted = computed(() => (date?: Date): boolean => {
|
|
187
|
-
if (!date || !Array.isArray(computedHighlightedDates) || !computedHighlightedDates.length) {
|
|
187
|
+
if (!date || !Array.isArray(computedHighlightedDates.value) || !computedHighlightedDates.value.length) {
|
|
188
188
|
return false
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
return computedHighlightedDates.some((highlightedDate) => {
|
|
191
|
+
return computedHighlightedDates.value.some((highlightedDate) => {
|
|
192
192
|
const parsedDate = parseDate(highlightedDate)
|
|
193
|
-
if (!parsedDate) {return false}
|
|
193
|
+
if (!parsedDate) { return false }
|
|
194
194
|
|
|
195
195
|
// Compare year, month, and day
|
|
196
196
|
return date.getFullYear() === parsedDate.getFullYear()
|
|
@@ -233,12 +233,12 @@ function useNavigation() {
|
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
const previousYear = () => {
|
|
236
|
-
const offset = 'months'
|
|
236
|
+
const offset = currentView.value === 'months' ? 1 : 21
|
|
237
237
|
currentMonth.value = new Date(currentMonth.value.getFullYear() - offset, currentMonth.value.getMonth(), 1)
|
|
238
238
|
}
|
|
239
239
|
|
|
240
240
|
const nextYear = () => {
|
|
241
|
-
const offset = 'months'
|
|
241
|
+
const offset = currentView.value === 'months' ? 1 : 21
|
|
242
242
|
currentMonth.value = new Date(currentMonth.value.getFullYear() + offset, currentMonth.value.getMonth(), 1)
|
|
243
243
|
}
|
|
244
244
|
|
|
@@ -258,14 +258,14 @@ function useTimeHandling() {
|
|
|
258
258
|
const minutes = computed(() => selectedDate.value?.getMinutes() ?? 0)
|
|
259
259
|
|
|
260
260
|
const handleHourInput = (value: number) => {
|
|
261
|
-
if (!selectedDate.value) {return}
|
|
261
|
+
if (!selectedDate.value) { return }
|
|
262
262
|
const newDate = new Date(selectedDate.value)
|
|
263
263
|
newDate.setHours(value)
|
|
264
264
|
emitDateValue(newDate)
|
|
265
265
|
}
|
|
266
266
|
|
|
267
267
|
const handleMinuteInput = (value: number) => {
|
|
268
|
-
if (!selectedDate.value) {return}
|
|
268
|
+
if (!selectedDate.value) { return }
|
|
269
269
|
const newDate = new Date(selectedDate.value)
|
|
270
270
|
newDate.setMinutes(value)
|
|
271
271
|
emitDateValue(newDate)
|
|
@@ -308,7 +308,7 @@ const { hours, minutes, handleHourInput, handleMinuteInput } = useTimeHandling()
|
|
|
308
308
|
|
|
309
309
|
// Date selection handler
|
|
310
310
|
function selectDate(date: Date | null) {
|
|
311
|
-
if (!date) {return}
|
|
311
|
+
if (!date) { return }
|
|
312
312
|
|
|
313
313
|
if (props.enableTime) {
|
|
314
314
|
// Create date with current time values
|
|
@@ -92,14 +92,14 @@ const FAKE_EMAIL_DOMAINS = [
|
|
|
92
92
|
'poplk.com'
|
|
93
93
|
]
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
const inputVal = ref<string>('')
|
|
96
96
|
const suggestedCorrection = ref<string | null>(null)
|
|
97
97
|
const validationMessage = ref('')
|
|
98
98
|
const isValidating = ref(false)
|
|
99
99
|
const isValidEmail = ref(true)
|
|
100
100
|
const validatedEmails = new Map<string, boolean>()
|
|
101
101
|
|
|
102
|
-
const input =
|
|
102
|
+
const input = ref<HTMLInputElement>()
|
|
103
103
|
|
|
104
104
|
// Use custom validation function
|
|
105
105
|
function validateEmail(value: string) {
|
|
@@ -129,17 +129,17 @@ function validateEmail(value: string) {
|
|
|
129
129
|
return undefined
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
const debouncedEmit = useDebounceFn(() => { emit('debounce', inputVal) }, 700)
|
|
132
|
+
const debouncedEmit = useDebounceFn(() => { emit('debounce', inputVal.value) }, 700)
|
|
133
133
|
|
|
134
134
|
// Validate input directly when value changes
|
|
135
135
|
function validateInput() {
|
|
136
|
-
if (!input) { return }
|
|
136
|
+
if (!input.value) { return }
|
|
137
137
|
|
|
138
|
-
input.setCustomValidity('')
|
|
139
|
-
if (!inputVal) { return }
|
|
140
|
-
const validationResult = validateEmail(inputVal)
|
|
138
|
+
input.value.setCustomValidity('')
|
|
139
|
+
if (!inputVal.value) { return }
|
|
140
|
+
const validationResult = validateEmail(inputVal.value)
|
|
141
141
|
if (typeof validationResult === 'string') {
|
|
142
|
-
input.setCustomValidity(validationResult)
|
|
142
|
+
input.value.setCustomValidity(validationResult)
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
|
|
@@ -173,9 +173,9 @@ async function validateEmailWithServer(email: string) {
|
|
|
173
173
|
|
|
174
174
|
if (!isValid) {
|
|
175
175
|
validationMessage.value = 'This email domain appears to be invalid'
|
|
176
|
-
input?.setCustomValidity(validationMessage.value)
|
|
176
|
+
input.value?.setCustomValidity(validationMessage.value)
|
|
177
177
|
} else {
|
|
178
|
-
input?.setCustomValidity('')
|
|
178
|
+
input.value?.setCustomValidity('')
|
|
179
179
|
}
|
|
180
180
|
} catch (error) {
|
|
181
181
|
console.error('Email validation error:', error)
|
|
@@ -228,9 +228,9 @@ function checkForTypos(email: string) {
|
|
|
228
228
|
// Apply the suggested correction
|
|
229
229
|
function applyCorrection() {
|
|
230
230
|
if (suggestedCorrection.value) {
|
|
231
|
-
inputVal = suggestedCorrection.value
|
|
231
|
+
inputVal.value = suggestedCorrection.value
|
|
232
232
|
suggestedCorrection.value = null
|
|
233
|
-
emit('update:modelValue', inputVal)
|
|
233
|
+
emit('update:modelValue', inputVal.value)
|
|
234
234
|
debouncedEmit()
|
|
235
235
|
}
|
|
236
236
|
}
|
|
@@ -262,13 +262,13 @@ function calculateLevenshteinDistance(a: string, b: string): number {
|
|
|
262
262
|
return matrix[a.length][b.length]
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
-
const debouncedServerValidate = useDebounceFn(() => validateEmailWithServer(inputVal), 1000)
|
|
265
|
+
const debouncedServerValidate = useDebounceFn(() => validateEmailWithServer(inputVal.value), 1000)
|
|
266
266
|
|
|
267
267
|
function updateInputVal() {
|
|
268
268
|
if (props.disabled) { return }
|
|
269
269
|
|
|
270
270
|
// Remove typo checking while typing - only do this on focusout now
|
|
271
|
-
// checkForTypos(inputVal)
|
|
271
|
+
// checkForTypos(inputVal.value)
|
|
272
272
|
|
|
273
273
|
// Clear any previous suggestions
|
|
274
274
|
suggestedCorrection.value = null
|
|
@@ -280,17 +280,17 @@ function updateInputVal() {
|
|
|
280
280
|
debouncedServerValidate()
|
|
281
281
|
}
|
|
282
282
|
|
|
283
|
-
emit('update:modelValue', inputVal)
|
|
283
|
+
emit('update:modelValue', inputVal.value)
|
|
284
284
|
debouncedEmit()
|
|
285
285
|
}
|
|
286
286
|
|
|
287
287
|
function handleFocusout(e: FocusEvent) {
|
|
288
288
|
// Check for typos when the user leaves the field
|
|
289
|
-
checkForTypos(inputVal)
|
|
289
|
+
checkForTypos(inputVal.value)
|
|
290
290
|
|
|
291
291
|
// Immediately validate on blur
|
|
292
|
-
if (props.serverValidate && EMAIL_REGEX.test(inputVal)) {
|
|
293
|
-
validateEmailWithServer(inputVal)
|
|
292
|
+
if (props.serverValidate && EMAIL_REGEX.test(inputVal.value)) {
|
|
293
|
+
validateEmailWithServer(inputVal.value)
|
|
294
294
|
}
|
|
295
295
|
|
|
296
296
|
if (props.onFocusout) { props.onFocusout(e) }
|
|
@@ -299,8 +299,8 @@ function handleFocusout(e: FocusEvent) {
|
|
|
299
299
|
watch(
|
|
300
300
|
() => props.modelValue,
|
|
301
301
|
(newVal) => {
|
|
302
|
-
if (newVal !== inputVal) {
|
|
303
|
-
inputVal = newVal || ''
|
|
302
|
+
if (newVal !== inputVal.value) {
|
|
303
|
+
inputVal.value = newVal || ''
|
|
304
304
|
nextTick(() => { validateInput() })
|
|
305
305
|
}
|
|
306
306
|
},
|
|
@@ -308,17 +308,17 @@ watch(
|
|
|
308
308
|
)
|
|
309
309
|
|
|
310
310
|
watch(
|
|
311
|
-
() => inputVal,
|
|
311
|
+
() => inputVal.value,
|
|
312
312
|
() => { validateInput() },
|
|
313
313
|
{ immediate: true }
|
|
314
314
|
)
|
|
315
315
|
|
|
316
|
-
const hasFocus = () => document.activeElement === input
|
|
317
|
-
const focus = () => input?.focus()
|
|
316
|
+
const hasFocus = () => document.activeElement === input.value
|
|
317
|
+
const focus = () => input.value?.focus()
|
|
318
318
|
defineExpose({ focus, hasFocus })
|
|
319
319
|
|
|
320
320
|
onMounted(() => {
|
|
321
|
-
if (props.autofocus) { setTimeout(() => input?.focus(), 10) }
|
|
321
|
+
if (props.autofocus) { setTimeout(() => input.value?.focus(), 10) }
|
|
322
322
|
// Don't auto-restore defaultValue - let user control their own content
|
|
323
323
|
})
|
|
324
324
|
</script>
|
|
@@ -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 { nextTick, onMounted, watch } from 'vue'
|
|
4
|
+
import { computed, nextTick, onMounted, ref, watch } from 'vue'
|
|
5
5
|
|
|
6
6
|
type NumberLayout = 'default' | 'vertical' | 'horizontal'
|
|
7
7
|
|
|
@@ -48,12 +48,12 @@ const {
|
|
|
48
48
|
|
|
49
49
|
const emit = defineEmits(['update:modelValue'])
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
const numberValue = ref<number>()
|
|
52
52
|
|
|
53
53
|
onMounted(() => {
|
|
54
54
|
const num = modelValue !== undefined ? Number.parseFloat(`${modelValue}`) : undefined
|
|
55
55
|
const defaultNum = defaultValue !== undefined ? Number.parseFloat(`${defaultValue}`) : undefined
|
|
56
|
-
numberValue = num ?? defaultNum
|
|
56
|
+
numberValue.value = num ?? defaultNum
|
|
57
57
|
})
|
|
58
58
|
|
|
59
59
|
const btnLayouts: NumberLayout[] = ['horizontal', 'vertical']
|
|
@@ -71,24 +71,24 @@ function subtract(...numbers: (number | undefined)[]) {
|
|
|
71
71
|
return Number.parseFloat(numArr.reduce((acc, curr) => acc - curr, firstNum).toFixed(precision))
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
const canAdd =
|
|
75
|
-
const canDecrement =
|
|
74
|
+
const canAdd = computed(() => max === undefined || add(numberValue.value, step) <= max)
|
|
75
|
+
const canDecrement = computed(() => min === undefined || subtract(numberValue.value, step) >= min)
|
|
76
76
|
|
|
77
77
|
// Methods
|
|
78
78
|
function increment() {
|
|
79
|
-
if (!canAdd) {return}
|
|
80
|
-
numberValue = add(numberValue ?? 0, step)
|
|
81
|
-
emit('update:modelValue', numberValue)
|
|
79
|
+
if (!canAdd.value) { return }
|
|
80
|
+
numberValue.value = add(numberValue.value ?? 0, step)
|
|
81
|
+
emit('update:modelValue', numberValue.value)
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
function decrement() {
|
|
85
|
-
if (!canDecrement) {return}
|
|
86
|
-
numberValue = subtract(numberValue || 0, step)
|
|
87
|
-
emit('update:modelValue', numberValue)
|
|
85
|
+
if (!canDecrement.value) { return }
|
|
86
|
+
numberValue.value = subtract(numberValue.value || 0, step)
|
|
87
|
+
emit('update:modelValue', numberValue.value)
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
function formatNumber(num: number) {
|
|
91
|
-
if (Number.isNaN(num)) {return ''}
|
|
91
|
+
if (Number.isNaN(num)) { return '' }
|
|
92
92
|
const formatter = new Intl.NumberFormat('en-US', {
|
|
93
93
|
minimumFractionDigits: 0,
|
|
94
94
|
maximumFractionDigits: 20,
|
|
@@ -108,38 +108,38 @@ function formatNumber(num: number) {
|
|
|
108
108
|
: `${padding}${integerPart}`
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
const formattedValue = ref('')
|
|
112
112
|
function inputHandler() {
|
|
113
|
-
const numeric = formattedValue.replace(/[^\d.-]/g, '')
|
|
113
|
+
const numeric = formattedValue.value.replace(/[^\d.-]/g, '')
|
|
114
114
|
const emptyValue = ['', '-', '.', '-.'].includes(numeric)
|
|
115
|
-
const isTypingDecimal = formattedValue.endsWith('.')
|
|
115
|
+
const isTypingDecimal = formattedValue.value.endsWith('.')
|
|
116
116
|
const isTypingTrailingZeros = /\.\d*0$/.test(numeric) // Check if ending with decimal followed by digits ending in 0
|
|
117
117
|
|
|
118
118
|
if (emptyValue || isTypingDecimal || isTypingTrailingZeros) {
|
|
119
|
-
emit('update:modelValue', '-'
|
|
119
|
+
emit('update:modelValue', numeric === '-' ? '-' : numeric)
|
|
120
120
|
return
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
numberValue = Number.parseFloat(numeric)
|
|
124
|
-
formattedValue = emptyValue ? '' : formatNumber(numberValue)
|
|
125
|
-
emit('update:modelValue', numberValue)
|
|
123
|
+
numberValue.value = Number.parseFloat(numeric)
|
|
124
|
+
formattedValue.value = emptyValue ? '' : formatNumber(numberValue.value)
|
|
125
|
+
emit('update:modelValue', numberValue.value)
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
watch(() => numberValue, () => {
|
|
128
|
+
watch(() => numberValue.value, () => {
|
|
129
129
|
nextTick(() => {
|
|
130
130
|
// Don't reformat if user is currently typing a decimal or trailing zeros
|
|
131
|
-
if (formattedValue.endsWith('.') || /\.\d*0$/.test(formattedValue)) {return}
|
|
132
|
-
formattedValue = numberValue !== undefined ? formatNumber(numberValue) : ''
|
|
131
|
+
if (formattedValue.value.endsWith('.') || /\.\d*0$/.test(formattedValue.value)) { return }
|
|
132
|
+
formattedValue.value = numberValue.value !== undefined ? formatNumber(numberValue.value) : ''
|
|
133
133
|
})
|
|
134
134
|
})
|
|
135
135
|
|
|
136
136
|
watch(() => modelValue, (newVal) => {
|
|
137
|
-
if (newVal !== numberValue) {
|
|
138
|
-
if ('string'
|
|
139
|
-
formattedValue = newVal
|
|
137
|
+
if (newVal !== numberValue.value) {
|
|
138
|
+
if (typeof newVal === 'string' && (newVal === '-' || newVal.endsWith('.'))) {
|
|
139
|
+
formattedValue.value = newVal
|
|
140
140
|
return
|
|
141
141
|
}
|
|
142
|
-
numberValue = Number.parseFloat(`${newVal}`) || 0
|
|
142
|
+
numberValue.value = Number.parseFloat(`${newVal}`) || 0
|
|
143
143
|
}
|
|
144
144
|
}, { immediate: true })
|
|
145
145
|
</script>
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { reactive } from 'vue'
|
|
2
|
+
import { reactive, ref } from 'vue'
|
|
3
3
|
|
|
4
4
|
const props = defineProps<{ digitCount: number, default?: string, modelValue?: string }>()
|
|
5
5
|
|
|
6
6
|
const emit = defineEmits(['update:modelValue', 'complete'])
|
|
7
7
|
const digits = reactive<(number | string | undefined)[]>([])
|
|
8
|
-
const otpCont =
|
|
8
|
+
const otpCont = ref<HTMLElement>()
|
|
9
9
|
|
|
10
10
|
function handlePaste(event: ClipboardEvent, index: number) {
|
|
11
11
|
event.preventDefault()
|
|
12
12
|
const { clipboardData } = event
|
|
13
13
|
const pastedText = clipboardData?.getData('text').replaceAll(/\D/g, '') // Ensure only numeric digits are pasted
|
|
14
14
|
const pastedDigits = [...(pastedText ?? '')]
|
|
15
|
-
if (!pastedDigits) {return}
|
|
15
|
+
if (!pastedDigits) { return }
|
|
16
16
|
for (let i = 0; i < pastedDigits.length; i++) {
|
|
17
17
|
const digit = pastedDigits[i]
|
|
18
18
|
if (index + i < digits.length) {
|
|
@@ -41,11 +41,11 @@ function handleKeyDown(event: KeyboardEvent, index: number) {
|
|
|
41
41
|
return
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
if ('Backspace'
|
|
44
|
+
if (event.key === 'Backspace') {
|
|
45
45
|
digits[index] = undefined
|
|
46
46
|
|
|
47
|
-
if (
|
|
48
|
-
const prevDigit = otpCont?.children[index - 1] as any
|
|
47
|
+
if (index !== 0) {
|
|
48
|
+
const prevDigit = otpCont.value?.children[index - 1] as any
|
|
49
49
|
prevDigit.focus()
|
|
50
50
|
}
|
|
51
51
|
emitUpdate()
|
|
@@ -58,7 +58,7 @@ function handleKeyDown(event: KeyboardEvent, index: number) {
|
|
|
58
58
|
|
|
59
59
|
if (index !== props.digitCount - 1) {
|
|
60
60
|
setTimeout(() => {
|
|
61
|
-
const nextDigit = otpCont?.children[index + 1] as any
|
|
61
|
+
const nextDigit = otpCont.value?.children[index + 1] as any
|
|
62
62
|
nextDigit.focus()
|
|
63
63
|
}, 10)
|
|
64
64
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { IconType } from '@bagelink/vue'
|
|
3
3
|
import { Btn, TextInput } from '@bagelink/vue'
|
|
4
|
+
import { computed } from 'vue'
|
|
4
5
|
|
|
5
6
|
export interface TextInputProps {
|
|
6
7
|
id?: string
|
|
@@ -38,8 +39,8 @@ const props = withDefaults(
|
|
|
38
39
|
const password = defineModel<string>('modelValue')
|
|
39
40
|
const showPwd = defineModel<boolean>('showPwd', { default: false })
|
|
40
41
|
|
|
41
|
-
const toggleShowPwdIcon =
|
|
42
|
-
const inputType =
|
|
42
|
+
const toggleShowPwdIcon = computed(() => showPwd.value ? 'visibility_off' : 'visibility')
|
|
43
|
+
const inputType = computed(() => (showPwd.value ? 'text' : 'password'))
|
|
43
44
|
</script>
|
|
44
45
|
|
|
45
46
|
<template>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts" generic="ContextObjType extends { [key: string]: any }">
|
|
2
2
|
import { Btn } from '@bagelink/vue'
|
|
3
|
-
import { watch } from 'vue'
|
|
3
|
+
import { computed, ref, watch } from 'vue'
|
|
4
4
|
|
|
5
5
|
export interface RadioOption<T> {
|
|
6
6
|
imgAlt?: string
|
|
@@ -41,7 +41,7 @@ const props = withDefaults(
|
|
|
41
41
|
|
|
42
42
|
const emit = defineEmits(['delete', 'focus', 'blur', 'change'])
|
|
43
43
|
|
|
44
|
-
const name =
|
|
44
|
+
const name = computed(
|
|
45
45
|
() => (
|
|
46
46
|
props.groupName
|
|
47
47
|
|| props.id
|
|
@@ -49,38 +49,38 @@ const name = $computed(
|
|
|
49
49
|
)
|
|
50
50
|
)
|
|
51
51
|
const selectedOption = defineModel('modelValue')
|
|
52
|
-
|
|
53
|
-
const visibleOptions =
|
|
52
|
+
const loadedOptions = ref<any[]>([])
|
|
53
|
+
const visibleOptions = computed(() => Array.isArray(props.options) ? (props.options as any[]) : (loadedOptions.value as any[]))
|
|
54
54
|
|
|
55
55
|
async function loadOptionsIfNeeded() {
|
|
56
|
-
if (
|
|
56
|
+
if (typeof props.options === 'function') {
|
|
57
57
|
try {
|
|
58
|
-
loadedOptions = await props.options()
|
|
58
|
+
loadedOptions.value = await props.options()
|
|
59
59
|
} catch {
|
|
60
|
-
loadedOptions = []
|
|
60
|
+
loadedOptions.value = []
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
watch(() => props.options, () => {
|
|
66
|
-
loadedOptions = []
|
|
66
|
+
loadedOptions.value = []
|
|
67
67
|
loadOptionsIfNeeded()
|
|
68
68
|
}, { immediate: true, deep: true })
|
|
69
|
-
|
|
69
|
+
const isFocused = ref(false)
|
|
70
70
|
|
|
71
|
-
const containerClasses =
|
|
71
|
+
const containerClasses = computed(() => ({
|
|
72
72
|
'has-error': !!props.error,
|
|
73
73
|
'is-disabled': props.disabled,
|
|
74
|
-
'is-focused': isFocused
|
|
74
|
+
'is-focused': isFocused.value
|
|
75
75
|
}))
|
|
76
76
|
|
|
77
77
|
function handleFocus() {
|
|
78
|
-
isFocused = true
|
|
78
|
+
isFocused.value = true
|
|
79
79
|
emit('focus')
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
function handleBlur() {
|
|
83
|
-
isFocused = false
|
|
83
|
+
isFocused.value = false
|
|
84
84
|
emit('blur')
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -96,27 +96,29 @@ function handleChange() {
|
|
|
96
96
|
class="border rounded flex active-list-item hover"
|
|
97
97
|
:for="opt.id || `${name}-${index}`"
|
|
98
98
|
:class="{ 'p-05 gap-025': thin, 'py-1 gap-075': !thin, 'ps-05': !hideRadio, 'bg-gray-light': !bgColor && !flat, 'align-items-start': align === 'start' || align === 'top', 'align-items-center': align === 'center', 'align-items-end': align === 'end' || align === 'bottom', invertedActive }"
|
|
99
|
-
:style="{ backgroundColor: bgColor, borderColor
|
|
99
|
+
:style="{ backgroundColor: bgColor, borderColor }"
|
|
100
100
|
>
|
|
101
101
|
<input
|
|
102
102
|
:id="opt.id || `${name}-${index}`" v-model="selectedOption" :disabled class="radio-input-list"
|
|
103
|
-
type="radio" :name :value="opt.value" :required="required"
|
|
103
|
+
type="radio" :name :value="opt.value" :required="required" :class="{
|
|
104
|
+
'mt-025': align === 'start' || align === 'top',
|
|
105
|
+
'mb-025': align === 'end' || align === 'bottom',
|
|
106
|
+
'hideRadio': hideRadio,
|
|
107
|
+
}" @focus="handleFocus"
|
|
108
|
+
@blur="handleBlur"
|
|
104
109
|
@change="handleChange"
|
|
105
|
-
:class="{
|
|
106
|
-
'mt-025': align === 'start' || align === 'top',
|
|
107
|
-
'mb-025': align === 'end' || align === 'bottom',
|
|
108
|
-
'hideRadio': hideRadio
|
|
109
|
-
}"
|
|
110
110
|
>
|
|
111
|
-
<div
|
|
111
|
+
<div
|
|
112
|
+
class="flex w-100 gap-1 flex-wrap m_gap-05 m_gap-row-025"
|
|
112
113
|
:class="{ 'txt-center justify-content-center': textAlign === 'center', 'txt-end justify-content-end': textAlign === 'right', 'txt-start justify-content-start': textAlign === 'left' }"
|
|
113
|
-
:style="{ color: textColor }"
|
|
114
|
+
:style="{ color: textColor }"
|
|
115
|
+
>
|
|
114
116
|
<img
|
|
115
117
|
v-if="opt.imgSrc" class="bg-popup shadow-light py-025 radius-05 m_w40" height="40" :src="opt.imgSrc"
|
|
116
118
|
:alt="opt.imgAlt"
|
|
117
119
|
>
|
|
118
120
|
<div class="">
|
|
119
|
-
<div v-if="opt.label" class="m-0 m_txt-14 line-height-14" v-html="opt.label"
|
|
121
|
+
<div v-if="opt.label" class="m-0 m_txt-14 line-height-14" v-html="opt.label" />
|
|
120
122
|
<p v-if="opt.subLabel" class="txt-gray txt-12 m-0 pt-025">{{ opt.subLabel }}</p>
|
|
121
123
|
</div>
|
|
122
124
|
<slot name="radioItem" v-bind="opt" />
|
|
@@ -132,8 +134,9 @@ function handleChange() {
|
|
|
132
134
|
}
|
|
133
135
|
.radio-input-list {
|
|
134
136
|
width: auto;
|
|
135
|
-
transform: scale(1.
|
|
136
|
-
|
|
137
|
+
transform: scale(1.2);
|
|
138
|
+
margin-inline-end: 0.5rem;
|
|
139
|
+
margin-top: 0;
|
|
137
140
|
}
|
|
138
141
|
|
|
139
142
|
.radio-input-list.hidden {
|