@bagelink/vue 1.6.47 → 1.6.51

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.
Files changed (170) hide show
  1. package/bin/experimentalGenTypedRoutes.ts +18 -19
  2. package/bin/utils.ts +4 -4
  3. package/dist/components/AddressSearch.vue.d.ts.map +1 -1
  4. package/dist/components/Alert.vue.d.ts.map +1 -1
  5. package/dist/components/BglVideo.vue.d.ts.map +1 -1
  6. package/dist/components/Card.vue.d.ts.map +1 -1
  7. package/dist/components/Carousel.vue.d.ts +2 -2
  8. package/dist/components/Carousel.vue.d.ts.map +1 -1
  9. package/dist/components/Dropdown.vue.d.ts.map +1 -1
  10. package/dist/components/Flag.vue.d.ts.map +1 -1
  11. package/dist/components/IframeVue.vue.d.ts.map +1 -1
  12. package/dist/components/ListItem.vue.d.ts.map +1 -1
  13. package/dist/components/Loading.vue.d.ts.map +1 -1
  14. package/dist/components/Modal.vue.d.ts.map +1 -1
  15. package/dist/components/ModalForm.vue.d.ts.map +1 -1
  16. package/dist/components/NavBar.vue.d.ts +1 -1
  17. package/dist/components/Pill.vue.d.ts.map +1 -1
  18. package/dist/components/Zoomer.vue.d.ts +0 -1
  19. package/dist/components/Zoomer.vue.d.ts.map +1 -1
  20. package/dist/components/analytics/LineChart.vue.d.ts.map +1 -1
  21. package/dist/components/analytics/PieChart.vue.d.ts +2 -1
  22. package/dist/components/analytics/PieChart.vue.d.ts.map +1 -1
  23. package/dist/components/analytics/index.d.ts +1 -1
  24. package/dist/components/analytics/index.d.ts.map +1 -1
  25. package/dist/components/calendar/CalendarPopover.vue.d.ts.map +1 -1
  26. package/dist/components/form/BglMultiStepForm.vue.d.ts.map +1 -1
  27. package/dist/components/form/inputs/ColorInput.vue.d.ts.map +1 -1
  28. package/dist/components/form/inputs/DateInput.vue.d.ts.map +1 -1
  29. package/dist/components/form/inputs/PasswordInput.vue.d.ts.map +1 -1
  30. package/dist/components/form/inputs/RadioGroup.vue.d.ts.map +1 -1
  31. package/dist/components/form/inputs/RangeInput.vue.d.ts +11 -11
  32. package/dist/components/form/inputs/RichText/components/EditorToolbar.vue.d.ts.map +1 -1
  33. package/dist/components/form/inputs/RichText/components/TableGridSelector.vue.d.ts.map +1 -1
  34. package/dist/components/form/inputs/RichText/utils/commands.d.ts.map +1 -1
  35. package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
  36. package/dist/components/form/inputs/TelInput.vue.d.ts.map +1 -1
  37. package/dist/components/layout/AppSidebar.vue.d.ts +1 -0
  38. package/dist/components/layout/AppSidebar.vue.d.ts.map +1 -1
  39. package/dist/components/layout/Layout.vue.d.ts.map +1 -1
  40. package/dist/components/layout/Tabs.vue.d.ts.map +1 -1
  41. package/dist/components/layout/index.d.ts +3 -3
  42. package/dist/components/layout/index.d.ts.map +1 -1
  43. package/dist/index.cjs +34 -25
  44. package/dist/index.d.ts +1 -0
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.mjs +6668 -5883
  47. package/dist/plugins/useToast.d.ts.map +1 -1
  48. package/dist/style.css +1 -1
  49. package/package.json +5 -10
  50. package/src/components/AccordionItem.vue +11 -11
  51. package/src/components/AddToCalendar.vue +1 -1
  52. package/src/components/AddressSearch.vue +9 -8
  53. package/src/components/Alert.vue +2 -1
  54. package/src/components/Badge.vue +5 -5
  55. package/src/components/BglVideo.vue +44 -45
  56. package/src/components/Btn.vue +15 -15
  57. package/src/components/Card.vue +10 -8
  58. package/src/components/Carousel.vue +159 -162
  59. package/src/components/DataPreview.vue +1 -1
  60. package/src/components/DragOver.vue +6 -6
  61. package/src/components/Dropdown.vue +39 -38
  62. package/src/components/Flag.vue +7 -6
  63. package/src/components/Icon/Icon.vue +22 -22
  64. package/src/components/IframeVue.vue +5 -5
  65. package/src/components/Image.vue +17 -17
  66. package/src/components/ImportData.vue +79 -79
  67. package/src/components/ListItem.vue +20 -13
  68. package/src/components/Loading.vue +10 -9
  69. package/src/components/MapEmbed/Index.vue +24 -24
  70. package/src/components/Modal.vue +11 -9
  71. package/src/components/ModalForm.vue +9 -8
  72. package/src/components/NavBar.vue +6 -6
  73. package/src/components/Pagination.vue +27 -27
  74. package/src/components/Pill.vue +11 -12
  75. package/src/components/Rating.vue +2 -2
  76. package/src/components/Slider.vue +75 -75
  77. package/src/components/Spreadsheet/Index.vue +34 -34
  78. package/src/components/Spreadsheet/SpreadsheetTable.vue +3 -3
  79. package/src/components/Zoomer.vue +165 -170
  80. package/src/components/analytics/BarChart.vue +6 -6
  81. package/src/components/analytics/KpiCard.vue +2 -2
  82. package/src/components/analytics/LineChart.vue +63 -61
  83. package/src/components/analytics/PieChart.vue +104 -90
  84. package/src/components/analytics/index.ts +2 -2
  85. package/src/components/calendar/CalendarPopover.vue +1 -1
  86. package/src/components/calendar/Index.vue +1 -1
  87. package/src/components/calendar/views/AgendaView.vue +3 -3
  88. package/src/components/calendar/views/DayView.vue +6 -6
  89. package/src/components/calendar/views/MonthView.vue +2 -2
  90. package/src/components/calendar/views/WeekView.vue +18 -18
  91. package/src/components/dataTable/DataTable.vue +4 -4
  92. package/src/components/dataTable/useSorting.ts +1 -1
  93. package/src/components/dataTable/useTableData.ts +15 -15
  94. package/src/components/dataTable/useTableSelection.ts +15 -15
  95. package/src/components/dataTable/useTableVirtualization.ts +1 -1
  96. package/src/components/draggable/useDraggable.ts +42 -42
  97. package/src/components/form/BagelForm.vue +15 -15
  98. package/src/components/form/BglFieldSet.vue +5 -3
  99. package/src/components/form/BglMultiStepForm.vue +20 -21
  100. package/src/components/form/inputs/CheckInput.vue +2 -2
  101. package/src/components/form/inputs/CodeEditor/format.ts +7 -7
  102. package/src/components/form/inputs/CodeEditor/useHighlight.ts +6 -6
  103. package/src/components/form/inputs/ColorInput.vue +5 -4
  104. package/src/components/form/inputs/DateInput.vue +8 -9
  105. package/src/components/form/inputs/DatePicker.vue +24 -24
  106. package/src/components/form/inputs/EmailInput.vue +24 -24
  107. package/src/components/form/inputs/NumberInput.vue +26 -26
  108. package/src/components/form/inputs/OTP.vue +7 -7
  109. package/src/components/form/inputs/PasswordInput.vue +3 -2
  110. package/src/components/form/inputs/RadioGroup.vue +28 -25
  111. package/src/components/form/inputs/RadioPillsInput.vue +12 -12
  112. package/src/components/form/inputs/RangeInput.vue +21 -21
  113. package/src/components/form/inputs/RichText/components/EditorToolbar.vue +107 -92
  114. package/src/components/form/inputs/RichText/components/TableGridSelector.vue +64 -64
  115. package/src/components/form/inputs/RichText/components/gridBox.vue +10 -8
  116. package/src/components/form/inputs/RichText/composables/useCommands.ts +1 -1
  117. package/src/components/form/inputs/RichText/composables/useEditor.ts +12 -12
  118. package/src/components/form/inputs/RichText/composables/useEditorKeyboard.ts +1 -1
  119. package/src/components/form/inputs/RichText/index.vue +138 -138
  120. package/src/components/form/inputs/RichText/utils/commands.ts +84 -85
  121. package/src/components/form/inputs/RichText/utils/debug.ts +1 -1
  122. package/src/components/form/inputs/RichText/utils/formatting.ts +39 -39
  123. package/src/components/form/inputs/RichText/utils/selection.ts +28 -28
  124. package/src/components/form/inputs/RichText/utils/table.ts +19 -19
  125. package/src/components/form/inputs/SelectBtn.vue +1 -1
  126. package/src/components/form/inputs/SelectInput.vue +54 -54
  127. package/src/components/form/inputs/SignaturePad.vue +40 -40
  128. package/src/components/form/inputs/TableField.vue +1 -1
  129. package/src/components/form/inputs/TelInput.vue +54 -53
  130. package/src/components/form/inputs/TextInput.vue +19 -19
  131. package/src/components/form/inputs/ToggleInput.vue +2 -2
  132. package/src/components/form/inputs/Upload/useFileUpload.ts +6 -6
  133. package/src/components/form/useBagelFormState.ts +5 -5
  134. package/src/components/layout/AppLayout.vue +2 -2
  135. package/src/components/layout/AppSidebar.vue +77 -16
  136. package/src/components/layout/Layout.vue +12 -10
  137. package/src/components/layout/SidebarMenu.vue +4 -4
  138. package/src/components/layout/TabbedLayout.vue +17 -17
  139. package/src/components/layout/Tabs.vue +4 -5
  140. package/src/components/layout/TabsNav.vue +14 -14
  141. package/src/components/layout/index.ts +3 -5
  142. package/src/components/lightbox/Lightbox.vue +22 -22
  143. package/src/components/lightbox/index.ts +8 -8
  144. package/src/composables/index.ts +8 -8
  145. package/src/composables/useAddToCalendar.ts +13 -13
  146. package/src/composables/useDevice.ts +2 -2
  147. package/src/composables/useFormField.ts +4 -4
  148. package/src/composables/usePolling.ts +8 -8
  149. package/src/composables/useSchemaField.ts +38 -38
  150. package/src/composables/useTheme.ts +9 -9
  151. package/src/composables/useValidateFieldValue.ts +2 -2
  152. package/src/directives/pattern.ts +25 -25
  153. package/src/directives/ripple.ts +4 -4
  154. package/src/directives/vResize.ts +6 -6
  155. package/src/index.ts +1 -0
  156. package/src/plugins/bagel.ts +4 -4
  157. package/src/plugins/useToast.ts +56 -51
  158. package/src/styles/layout.css +1 -1
  159. package/src/types/index.ts +1 -1
  160. package/src/utils/BagelFormUtils.ts +7 -7
  161. package/src/utils/calendar/Helpers.ts +8 -8
  162. package/src/utils/calendar/dateUtils.ts +22 -22
  163. package/src/utils/calendar/time.ts +25 -25
  164. package/src/utils/calendar/week.ts +25 -25
  165. package/src/utils/elementUtils.ts +27 -27
  166. package/src/utils/sizeParsing.ts +2 -2
  167. package/src/utils/strings.ts +5 -5
  168. package/src/utils/tapDetector.ts +11 -11
  169. package/src/utils/useSearch.ts +29 -29
  170. package/vite.config.ts +0 -2
@@ -2,7 +2,7 @@
2
2
  import type { IconType, Option } from '@bagelink/vue'
3
3
  import type { AlignedPlacement } from '../../Dropdown.vue'
4
4
  import { Btn, Card, Skeleton, Dropdown, Icon, TextInput, useSearch } from '@bagelink/vue'
5
- import { onMounted, watch } from 'vue'
5
+ import { computed, onMounted, ref, watch } from 'vue'
6
6
  import 'floating-vue/style.css'
7
7
 
8
8
  type OptionsSource = Option[] | ((query: string) => Promise<Option[]>)
@@ -35,71 +35,71 @@ interface PropTypes {
35
35
  searchPlaceholder?: string
36
36
  }
37
37
 
38
- const searchInput = $ref<HTMLElement | undefined>()
39
- const triggerBtn = $ref<HTMLButtonElement | undefined>()
38
+ const searchInput = ref<HTMLElement | undefined>()
39
+ const triggerBtn = ref<HTMLButtonElement | undefined>()
40
40
 
41
- let selectedItems = $ref<Option[]>([])
41
+ const selectedItems = ref<Option[]>([])
42
42
 
43
- const selectedItemCount = $computed(() => selectedItems.length ?? 0)
44
- const searchTerm = $ref<string>('')
43
+ const selectedItemCount = computed(() => selectedItems.value.length ?? 0)
44
+ const searchTerm = ref<string>('')
45
45
 
46
- const dropdown = $ref<InstanceType<typeof Dropdown> | undefined>()
47
- let selected = $ref(false)
48
- let open = $ref(false)
46
+ const dropdown = ref<InstanceType<typeof Dropdown> | undefined>()
47
+ const selected = ref(false)
48
+ const open = ref(false)
49
49
 
50
- const selectedLabel = $computed((): string => {
51
- if (selectedItemCount === 0) { return props.placeholder }
52
- if (selectedItemCount > 4) {
53
- const str = selectedItems
50
+ const selectedLabel = computed((): string => {
51
+ if (selectedItemCount.value === 0) { return props.placeholder }
52
+ if (selectedItemCount.value > 4) {
53
+ const str = selectedItems.value
54
54
  .slice(0, 4)
55
55
  .map(item => getLabel(item))
56
56
  .join(', ')
57
- return `${str}... +${selectedItemCount - 4}`
57
+ return `${str}... +${selectedItemCount.value - 4}`
58
58
  }
59
- return selectedItems.map(item => getLabel(item)).join(', ')
59
+ return selectedItems.value.map(item => getLabel(item)).join(', ')
60
60
  })
61
- const searchPlaceholder = $computed(() => props.searchPlaceholder ?? selectedLabel ?? 'Search')
61
+ const searchPlaceholder = computed(() => props.searchPlaceholder ?? selectedLabel.value ?? 'Search')
62
62
 
63
63
  const { results, isLoading } = useSearch<Option>({
64
- searchTerm: () => searchTerm,
64
+ searchTerm: () => searchTerm.value,
65
65
  serverSearch: isAsyncSource(props.options) ? props.options : undefined,
66
66
  items: () => (Array.isArray(props.options) ? props.options : []),
67
67
  minChars: isAsyncSource(props.options) ? 0 : 2,
68
68
  })
69
69
 
70
- let highlightedIndex = $ref(-1)
70
+ const highlightedIndex = ref(-1)
71
71
 
72
- const selectOptions = $ref<HTMLElement | undefined>()
72
+ const selectOptions = ref<HTMLElement | undefined>()
73
73
 
74
74
  function navigate(direction: 'up' | 'down') {
75
- if (!open) {
76
- open = true
75
+ if (!open.value) {
76
+ open.value = true
77
77
  setTimeout(() => { navigate(direction) }, 210)
78
78
  return
79
79
  }
80
80
  if (direction === 'up') {
81
- highlightedIndex = highlightedIndex > 0 ? highlightedIndex - 1 : results.value.length - 1
81
+ highlightedIndex.value = highlightedIndex.value > 0 ? highlightedIndex.value - 1 : results.value.length - 1
82
82
  } else if (direction === 'down') {
83
- highlightedIndex = highlightedIndex < results.value.length - 1 ? highlightedIndex + 1 : 0
83
+ highlightedIndex.value = highlightedIndex.value < results.value.length - 1 ? highlightedIndex.value + 1 : 0
84
84
  }
85
85
  setTimeout(() => {
86
- const el = selectOptions?.children[highlightedIndex] as HTMLElement
86
+ const el = selectOptions.value?.children[highlightedIndex.value] as HTMLElement
87
87
  if (el) { el.focus() }
88
- else { highlightedIndex = -1 }
88
+ else { highlightedIndex.value = -1 }
89
89
  }, 10)
90
90
  }
91
91
 
92
- const isSelected = (option: Option) => selectedItems.find(item => getValue(option) === getValue(item)) !== undefined
92
+ const isSelected = (option: Option) => selectedItems.value.find(item => getValue(option) === getValue(item)) !== undefined
93
93
 
94
94
  function scrollToSelectedItem() {
95
- if (!selectOptions || selectedItemCount === 0) { return }
95
+ if (!selectOptions.value || selectedItemCount.value === 0) { return }
96
96
 
97
97
  // Find the first selected item in the results
98
98
  const selectedIndex = results.value.findIndex(option => isSelected(option))
99
99
  if (selectedIndex === -1) { return }
100
100
 
101
101
  // Get the selected option element
102
- const selectedElement = selectOptions.children[selectedIndex] as HTMLElement
102
+ const selectedElement = selectOptions.value.children[selectedIndex] as HTMLElement
103
103
  if (!selectedElement) { return }
104
104
 
105
105
  // Scroll the selected item into view
@@ -123,47 +123,47 @@ function getValue(option?: Option): Primitive | undefined {
123
123
  }
124
124
 
125
125
  function focusInput() {
126
- open = true
126
+ open.value = true
127
127
  setTimeout(() => {
128
- if (searchInput) { searchInput.focus() }
128
+ if (searchInput.value) { searchInput.value.focus() }
129
129
  }, 10)
130
130
  }
131
131
 
132
132
  function select(option: Option) {
133
- selected = true
134
- const existingIndex = selectedItems.findIndex(
133
+ selected.value = true
134
+ const existingIndex = selectedItems.value.findIndex(
135
135
  item => getValue(item) === getValue(option),
136
136
  )
137
137
  if (existingIndex > -1) {
138
- selectedItems.splice(existingIndex, 1)
138
+ selectedItems.value.splice(existingIndex, 1)
139
139
  }
140
140
  else if (props.multiselect) {
141
- const current = [...selectedItems]
141
+ const current = [...selectedItems.value]
142
142
  current.push(option)
143
143
 
144
- selectedItems = current
144
+ selectedItems.value = current
145
145
  } else {
146
- selectedItems.splice(0, selectedItemCount, option)
146
+ selectedItems.value.splice(0, selectedItemCount.value, option)
147
147
  }
148
148
 
149
149
  // Move focus away from popper content before it gets aria-hidden
150
150
  const active = document.activeElement as HTMLElement | null
151
- if (active && selectOptions?.contains(active)) { active.blur() }
151
+ if (active && selectOptions.value?.contains(active)) { active.blur() }
152
152
 
153
153
  if (!props.multiselect) {
154
- open = false
154
+ open.value = false
155
155
  // After closing, return focus to the trigger for accessibility
156
- setTimeout(() => { triggerBtn?.focus() }, 0)
156
+ setTimeout(() => { triggerBtn.value?.focus() }, 0)
157
157
  }
158
158
  emitUpdate()
159
159
  }
160
160
 
161
161
  function emitUpdate() {
162
162
  if (props.multiselect) {
163
- emit('update:modelValue', selectedItems.map(getValue).filter(Boolean))
163
+ emit('update:modelValue', selectedItems.value.map(getValue).filter(Boolean))
164
164
  } else {
165
- // selectedItems.splice(1, selectedItemCount - 1);
166
- const [item] = selectedItems
165
+ // selectedItems.value.splice(1, selectedItemCount.value - 1);
166
+ const [item] = selectedItems.value
167
167
  emit('update:modelValue', getValue(item))
168
168
  }
169
169
  }
@@ -182,21 +182,21 @@ watch(
182
182
  const newOption = Array.isArray(props.options)
183
183
  ? (props.options.find(o => getValue(o) === newVal) ?? newVal)
184
184
  : newVal
185
- if (newOption && !isSelected(newOption)) { selectedItems = [newOption] }
185
+ if (newOption && !isSelected(newOption)) { selectedItems.value = [newOption] }
186
186
  } else {
187
187
  const newData = [newVal].flat()
188
- const isSame = compareArrays(newData, selectedItems)
188
+ const isSame = compareArrays(newData, selectedItems.value)
189
189
  if (!isSame) {
190
- selectedItems.splice(0, selectedItemCount, ...newData)
190
+ selectedItems.value.splice(0, selectedItemCount.value, ...newData)
191
191
  }
192
192
  }
193
193
  },
194
194
  { immediate: true },
195
195
  )
196
196
 
197
- watch(() => open, (value) => {
197
+ watch(() => open.value, (value) => {
198
198
  if (value) {
199
- highlightedIndex = -1
199
+ highlightedIndex.value = -1
200
200
  // Scroll to selected item when dropdown opens
201
201
  setTimeout(() => { scrollToSelectedItem() }, 10)
202
202
  }
@@ -207,15 +207,15 @@ watch(
207
207
  () => {
208
208
  const opts = props.options
209
209
  if (!Array.isArray(opts)) { return }
210
- selectedItems.forEach((option, i) => {
210
+ selectedItems.value.forEach((option, i) => {
211
211
  const exists = opts.find(
212
212
  (o: Option) => getValue(o) === getValue(option),
213
213
  )
214
- if (exists === undefined) { selectedItems.splice(i, 1) }
215
- else { selectedItems.splice(i, 1, exists) }
214
+ if (exists === undefined) { selectedItems.value.splice(i, 1) }
215
+ else { selectedItems.value.splice(i, 1, exists) }
216
216
  })
217
217
  // const original = JSON.stringify(props.options.map(getValue));
218
- // const newSelection = JSON.stringify(selectedItems.map(getValue));
218
+ // const newSelection = JSON.stringify(selectedItems.value.map(getValue));
219
219
  // if (original !== newSelection) emitUpdate();
220
220
  },
221
221
  { deep: true, immediate: true },
@@ -226,7 +226,7 @@ watch(
226
226
  () => results.value,
227
227
  (newResults) => {
228
228
  if (isAsyncSource(props.options) && newResults.length > 0) {
229
- selectedItems.forEach((option, i) => {
229
+ selectedItems.value.forEach((option, i) => {
230
230
  const optionValue = getValue(option)
231
231
  // If the selected item is just a primitive value (no label), find the full option
232
232
  if (typeof option !== 'object' || !option.label) {
@@ -234,7 +234,7 @@ watch(
234
234
  (o: Option) => getValue(o) === optionValue,
235
235
  )
236
236
  if (fullOption) {
237
- selectedItems.splice(i, 1, fullOption)
237
+ selectedItems.value.splice(i, 1, fullOption)
238
238
  }
239
239
  }
240
240
  })
@@ -252,7 +252,7 @@ onMounted(() => {
252
252
 
253
253
  if (defaultOption === undefined) { return }
254
254
 
255
- selectedItems = [defaultOption]
255
+ selectedItems.value = [defaultOption]
256
256
  }
257
257
  })
258
258
  </script>
@@ -3,7 +3,7 @@ import type { Options as SignaturePadOptions } from 'signature_pad'
3
3
  import { Btn } from '@bagelink/vue'
4
4
  import { useEventListener, useResizeObserver } from '@vueuse/core'
5
5
  import SignaturePad from 'signature_pad'
6
- import { onMounted, watch } from 'vue'
6
+ import { computed, onMounted, ref, watch } from 'vue'
7
7
 
8
8
  export interface WaterMark {
9
9
  text: string
@@ -38,35 +38,35 @@ const props = withDefaults(defineProps<{
38
38
  const sigData = defineModel()
39
39
  const fileData = defineModel<File>('file')
40
40
 
41
- const vCanvas = $ref<HTMLCanvasElement>()
41
+ const vCanvas = ref<HTMLCanvasElement>()
42
42
 
43
- let sig = $ref<SignaturePad>()
43
+ const sig = ref<SignaturePad>()
44
44
 
45
- let _isEmpty = $ref<boolean>(true)
45
+ const _isEmpty = ref<boolean>(true)
46
46
 
47
47
  function clear() {
48
- sig?.clear()
49
- _isEmpty = true
48
+ sig.value?.clear()
49
+ _isEmpty.value = true
50
50
  sigData.value = undefined
51
51
  }
52
52
 
53
53
  function save(format?: FormatType) {
54
54
  format = format || props.format
55
- return format ? sig?.toDataURL(format) : sig?.toDataURL()
55
+ return format ? sig.value?.toDataURL(format) : sig.value?.toDataURL()
56
56
  }
57
57
 
58
58
  function saveFile() {
59
59
  const data = save()
60
- if (!data) {return}
60
+ if (!data) { return }
61
61
 
62
- if ('image/svg+xml' === props.format) {
62
+ if (props.format === 'image/svg+xml') {
63
63
  // For SVG, create file directly from the SVG string
64
64
  fileData.value = new File([data], 'signature.svg', { type: 'image/svg+xml' })
65
65
  } else {
66
66
  try {
67
67
  // For PNG/JPG, convert base64 to blob first
68
68
  const base64Data = data.split(',')[1]
69
- if (!base64Data) {throw new Error('Invalid data URL format')}
69
+ if (!base64Data) { throw new Error('Invalid data URL format') }
70
70
 
71
71
  const byteCharacters = atob(base64Data)
72
72
  // Create byte array directly with mapping function
@@ -86,41 +86,41 @@ function saveFile() {
86
86
  }
87
87
 
88
88
  function fromDataURL(url: string) {
89
- return sig?.fromDataURL(url, {
90
- height: vCanvas?.height,
91
- width: vCanvas?.width,
89
+ return sig.value?.fromDataURL(url, {
90
+ height: vCanvas.value?.height,
91
+ width: vCanvas.value?.width,
92
92
  ratio: props.ratio,
93
93
  xOffset: 0,
94
94
  yOffset: 0,
95
95
  })
96
96
  }
97
97
 
98
- const isEmpty = () => sig?.isEmpty()
98
+ const isEmpty = () => sig.value?.isEmpty()
99
99
  function undo() {
100
- const data = sig?.toData()
100
+ const data = sig.value?.toData()
101
101
  if (data) {
102
102
  data.pop()
103
- sig?.fromData(data)
103
+ sig.value?.fromData(data)
104
104
  }
105
105
  }
106
106
 
107
- const defaultOptions = $ref<SignaturePadOptions>({
107
+ const defaultOptions = ref<SignaturePadOptions>({
108
108
  penColor: 'rgb(0, 0, 0)',
109
109
  backgroundColor: 'rgb(255, 255, 255)',
110
110
  })
111
111
 
112
- const signatureOptions = $computed(() => ({ ...defaultOptions, ...props.sigOption }))
112
+ const signatureOptions = computed(() => ({ ...defaultOptions.value, ...props.sigOption }))
113
113
 
114
114
  watch(
115
115
  () => props.disabled,
116
116
  (val) => {
117
- if (val) {sig?.off()}
118
- else {sig?.on()}
117
+ if (val) { sig.value?.off() }
118
+ else { sig.value?.on() }
119
119
  },
120
120
  )
121
121
 
122
122
  function addWaterMark(data: WaterMark) {
123
- if (!('[object Object]' === Object.prototype.toString.call(data))) {
123
+ if (!(Object.prototype.toString.call(data) === '[object Object]')) {
124
124
  throw new Error(`Expected Object, got ${typeof data}.`)
125
125
  } else {
126
126
  const textData = {
@@ -131,15 +131,15 @@ function addWaterMark(data: WaterMark) {
131
131
  sy: data.sy || 40,
132
132
  }
133
133
 
134
- const ctx = vCanvas?.getContext('2d')
135
- if (!ctx) {return}
134
+ const ctx = vCanvas.value?.getContext('2d')
135
+ if (!ctx) { return }
136
136
  ctx.font = data.font || '20px sans-serif'
137
137
  ctx.fillStyle = data.fillStyle || '#333'
138
138
  ctx.strokeStyle = data.strokeStyle || '#333'
139
- if ('all' === data.style) {
139
+ if (data.style === 'all') {
140
140
  ctx.fillText(textData.text, textData.x, textData.y)
141
141
  ctx.strokeText(textData.text, textData.sx, textData.sy)
142
- } else if ('stroke' === data.style) {
142
+ } else if (data.style === 'stroke') {
143
143
  ctx.strokeText(textData.text, textData.sx, textData.sy)
144
144
  } else {
145
145
  ctx.fillText(textData.text, textData.x, textData.y)
@@ -148,20 +148,20 @@ function addWaterMark(data: WaterMark) {
148
148
  }
149
149
 
150
150
  function onEndStroke() {
151
- _isEmpty = sig?.isEmpty() ?? false
151
+ _isEmpty.value = sig.value?.isEmpty() ?? false
152
152
  const data = save()
153
153
  sigData.value = data
154
154
  saveFile()
155
155
  }
156
156
 
157
157
  function loadFile(file: File | undefined) {
158
- if (!file) {return}
158
+ if (!file) { return }
159
159
  const reader = new FileReader()
160
160
  return new Promise((resolve) => {
161
161
  reader.onload = (e) => {
162
162
  const dataUrl = String(e.target?.result)
163
163
  void fromDataURL(dataUrl)
164
- _isEmpty = false
164
+ _isEmpty.value = false
165
165
  sigData.value = dataUrl
166
166
  resolve(true)
167
167
  }
@@ -175,22 +175,22 @@ watch(fileData, (newFile) => {
175
175
 
176
176
  function resizeCanvas() {
177
177
  let url
178
- if (!isEmpty()) {url = save()}
178
+ if (!isEmpty()) { url = save() }
179
179
  const ratio = props.ratio ?? 1 / 2
180
- const { width } = vCanvas!.getBoundingClientRect()
181
- vCanvas!.width = props.width ? Number(props.width.replaceAll('px', '')) : width
182
- vCanvas!.height = props.height ? Number(props.height.replaceAll('px', '')) : width * ratio
180
+ const { width } = vCanvas.value!.getBoundingClientRect()
181
+ vCanvas.value!.width = props.width ? Number(props.width.replaceAll('px', '')) : width
182
+ vCanvas.value!.height = props.height ? Number(props.height.replaceAll('px', '')) : width * ratio
183
183
  clear()
184
- if (!props.clearOnResize && url !== undefined) {void fromDataURL(url)}
185
- if (props.waterMark) {addWaterMark(props.waterMark)}
184
+ if (!props.clearOnResize && url !== undefined) { void fromDataURL(url) }
185
+ if (props.waterMark) { addWaterMark(props.waterMark) }
186
186
  }
187
187
 
188
188
  function draw() {
189
- sig = new SignaturePad(vCanvas!, signatureOptions)
189
+ sig.value = new SignaturePad(vCanvas.value!, signatureOptions.value)
190
190
  resizeCanvas()
191
- if (props.disabled) {sig.off()}
192
- else {sig.on()}
193
- _isEmpty = sig.isEmpty()
191
+ if (props.disabled) { sig.value.off() }
192
+ else { sig.value.on() }
193
+ _isEmpty.value = sig.value.isEmpty()
194
194
 
195
195
  // Load initial file if provided
196
196
  if (fileData.value) {
@@ -199,8 +199,8 @@ function draw() {
199
199
  }
200
200
 
201
201
  onMounted(draw)
202
- useResizeObserver(() => vCanvas, resizeCanvas)
203
- useEventListener(() => sig, 'endStroke', onEndStroke)
202
+ useResizeObserver(() => vCanvas.value, resizeCanvas)
203
+ useEventListener(() => sig.value, 'endStroke', onEndStroke)
204
204
 
205
205
  defineExpose({
206
206
  save,
@@ -40,7 +40,7 @@ function addRow() {
40
40
  } as { [key: string]: any }
41
41
  entityMeta?.fields.forEach((field: any) => {
42
42
  if (field.default) {
43
- if ('Check' === field.fieldtype) {
43
+ if (field.fieldtype === 'Check') {
44
44
  entry[field.fieldname] = Number.parseInt(field.default)
45
45
  } else {
46
46
  entry[field.fieldname] = field.default
@@ -3,7 +3,7 @@ import type { Country } from '@bagelink/vue'
3
3
  import type { CountryCode } from 'libphonenumber-js'
4
4
  import { Dropdown, Flag, Icon, TextInput, allCountries, ipapi } from '@bagelink/vue'
5
5
  import { parsePhoneNumberFromString } from 'libphonenumber-js'
6
- import { onMounted, watch, ref } from 'vue'
6
+ import { computed, onMounted, ref, watch } from 'vue'
7
7
 
8
8
  const props = defineProps<{
9
9
  id?: string
@@ -18,27 +18,27 @@ const props = defineProps<{
18
18
 
19
19
  const emit = defineEmits(['update:modelValue', 'blur', 'focus', 'keydown', 'input', 'paste'])
20
20
 
21
- let phoneNumber = $ref(props.modelValue ?? '')
22
- let search = $ref('')
23
- let activeCountry = $ref<Country>()
24
- const searchInput = $ref<InstanceType<typeof TextInput>>()
25
- let open = $ref(false)
21
+ const phoneNumber = ref(props.modelValue ?? '')
22
+ const search = ref('')
23
+ const activeCountry = ref<Country>()
24
+ const searchInput = ref<InstanceType<typeof TextInput>>()
25
+ const open = ref(false)
26
26
  const inputRef = ref<HTMLInputElement | null>(null)
27
- let isValid = $ref(true)
27
+ const isValid = ref(true)
28
28
 
29
29
  // Watch for changes to phoneNumber and emit update events
30
- watch(() => phoneNumber, (newValue) => {
30
+ watch(() => phoneNumber.value, (newValue) => {
31
31
  emit('update:modelValue', newValue)
32
32
  })
33
33
 
34
34
  // Watch for changes to the modelValue prop
35
35
  watch(() => props.modelValue, (newValue) => {
36
- if (newValue !== phoneNumber) {
37
- phoneNumber = newValue ?? ''
36
+ if (newValue !== phoneNumber.value) {
37
+ phoneNumber.value = newValue ?? ''
38
38
  }
39
39
  })
40
40
 
41
- const countries = $computed(() => {
41
+ const countries = computed(() => {
42
42
  let filteredCountries = allCountries
43
43
  if (props.excludeCountries && props.excludeCountries.length) {
44
44
  const excludeCountries = props.excludeCountries.map(c => c.toLowerCase())
@@ -48,52 +48,52 @@ const countries = $computed(() => {
48
48
  const onlyCountries = props.onlyCountries.map(c => c.toLowerCase())
49
49
  filteredCountries = filteredCountries.filter(c => onlyCountries.includes(c.iso2.toLowerCase()))
50
50
  }
51
- if (search.length) {
52
- const lowerCaseSearch = search.toLowerCase()
51
+ if (search.value.length) {
52
+ const lowerCaseSearch = search.value.toLowerCase()
53
53
  filteredCountries = filteredCountries.filter(c => c.name.toLowerCase().includes(lowerCaseSearch)
54
54
  || c.iso2.toLowerCase().includes(lowerCaseSearch)
55
- || c.dialCode.includes(search.replace('+', ''))
55
+ || c.dialCode.includes(search.value.replace('+', ''))
56
56
  )
57
57
  }
58
58
  return filteredCountries
59
59
  })
60
60
 
61
- const activeCountryCode = $computed(() => activeCountry?.iso2)
61
+ const activeCountryCode = computed(() => activeCountry.value?.iso2)
62
62
 
63
63
  function selectCountry(country: Country) {
64
- activeCountry = country
65
- open = false
66
- search = ''
64
+ activeCountry.value = country
65
+ open.value = false
66
+ search.value = ''
67
67
 
68
- if (!phoneNumber) {
69
- phoneNumber = `+${activeCountry.dialCode}`
70
- } else if (phoneNumber.startsWith('+')) {
68
+ if (!phoneNumber.value) {
69
+ phoneNumber.value = `+${activeCountry.value.dialCode}`
70
+ } else if (phoneNumber.value.startsWith('+')) {
71
71
  // Replace existing country code with the new one
72
- const existingCountry = countries.find(c => phoneNumber.startsWith(`+${c.dialCode}`))
72
+ const existingCountry = countries.value.find(c => phoneNumber.value.startsWith(`+${c.dialCode}`))
73
73
  if (existingCountry && existingCountry !== country) {
74
74
  // Remove the old country code and replace with new one
75
- const nationalPart = phoneNumber.substring(`+${existingCountry.dialCode}`.length).trim()
76
- phoneNumber = `+${activeCountry.dialCode}${nationalPart ? ` ${nationalPart}` : ''}`
75
+ const nationalPart = phoneNumber.value.substring(`+${existingCountry.dialCode}`.length).trim()
76
+ phoneNumber.value = `+${activeCountry.value.dialCode}${nationalPart ? ` ${nationalPart}` : ''}`
77
77
  }
78
78
  } else {
79
79
  // Phone number doesn't start with +, prepend the country code
80
- phoneNumber = `+${activeCountry.dialCode} ${phoneNumber.replace(/^0+/, '')}`
80
+ phoneNumber.value = `+${activeCountry.value.dialCode} ${phoneNumber.value.replace(/^0+/, '')}`
81
81
  }
82
82
  }
83
83
 
84
84
  async function getIp() {
85
85
  const { country_code } = await ipapi()
86
- selectCountry(countries.find(c => c.iso2 === country_code) ?? countries[0])
86
+ selectCountry(countries.value.find(c => c.iso2 === country_code) ?? countries.value[0])
87
87
  }
88
88
 
89
89
  // Get the country code for use with libphonenumber-js
90
90
  function getCountryCode(): CountryCode | undefined {
91
- return activeCountry?.iso2 ? activeCountry.iso2.toUpperCase() as CountryCode : undefined
91
+ return activeCountry.value?.iso2 ? activeCountry.value.iso2.toUpperCase() as CountryCode : undefined
92
92
  }
93
93
 
94
94
  // Parse and format the phone number
95
95
  function parseAndFormatPhoneNumber(value: string): string {
96
- if (!value) {return value}
96
+ if (!value) { return value }
97
97
 
98
98
  try {
99
99
  const parsedNumber = parsePhoneNumberFromString(value, getCountryCode())
@@ -108,31 +108,32 @@ function parseAndFormatPhoneNumber(value: string): string {
108
108
 
109
109
  // Validate the phone number and set custom validity
110
110
  function validatePhoneNumber() {
111
- if (!inputRef.value) {return}
111
+ if (!inputRef.value) { return }
112
112
 
113
113
  try {
114
- const parsedNumber = parsePhoneNumberFromString(phoneNumber, getCountryCode())
114
+ const parsedNumber = parsePhoneNumberFromString(phoneNumber.value, getCountryCode())
115
115
  if (parsedNumber && parsedNumber.isValid()) {
116
116
  inputRef.value.setCustomValidity('')
117
- isValid = true
117
+ isValid.value = true
118
118
  } else {
119
119
  inputRef.value.setCustomValidity('Please enter a valid phone number')
120
- isValid = false
120
+ isValid.value = false
121
121
  }
122
122
  } catch (error) {
123
+ console.error('Error validating phone number:', error)
123
124
  inputRef.value.setCustomValidity('Please enter a valid phone number')
124
- isValid = false
125
+ isValid.value = false
125
126
  }
126
127
  }
127
128
 
128
129
  function detectCountryFromNumber(value: string): boolean {
129
- if (!value.startsWith('+')) {return false}
130
+ if (!value.startsWith('+')) { return false }
130
131
 
131
132
  const digits = value.replace(/\D/g, '')
132
- if (1 >= digits.length) {return false}
133
+ if (digits.length <= 1) { return false }
133
134
 
134
- for (const country of countries) {
135
- if (digits.startsWith(country.dialCode) && country !== activeCountry) {
135
+ for (const country of countries.value) {
136
+ if (digits.startsWith(country.dialCode) && country !== activeCountry.value) {
136
137
  selectCountry(country)
137
138
  return true
138
139
  }
@@ -141,15 +142,15 @@ function detectCountryFromNumber(value: string): boolean {
141
142
  }
142
143
 
143
144
  async function initializeCountry() {
144
- if (phoneNumber) {
145
- detectCountryFromNumber(phoneNumber)
145
+ if (phoneNumber.value) {
146
+ detectCountryFromNumber(phoneNumber.value)
146
147
  } else {
147
148
  await getIp()
148
149
  }
149
- const formatted = parseAndFormatPhoneNumber(phoneNumber)
150
- if (formatted !== phoneNumber) {
151
- phoneNumber = formatted
152
- emit('input', phoneNumber)
150
+ const formatted = parseAndFormatPhoneNumber(phoneNumber.value)
151
+ if (formatted !== phoneNumber.value) {
152
+ phoneNumber.value = formatted
153
+ emit('input', phoneNumber.value)
153
154
  validatePhoneNumber()
154
155
  }
155
156
  validatePhoneNumber()
@@ -163,35 +164,35 @@ function handlePhoneInput(event: Event) {
163
164
  if (value.startsWith('+')) {
164
165
  const formatted = parseAndFormatPhoneNumber(value)
165
166
  if (formatted !== value) {
166
- phoneNumber = formatted
167
+ phoneNumber.value = formatted
167
168
  emit('input', event)
168
169
  validatePhoneNumber()
169
170
  return
170
171
  }
171
172
  }
172
173
 
173
- phoneNumber = value
174
+ phoneNumber.value = value
174
175
  emit('input', event)
175
176
  validatePhoneNumber()
176
177
  }
177
178
 
178
179
  function handleBlur(event: Event) {
179
- if (phoneNumber && !phoneNumber.startsWith('+') && activeCountry) {
180
- const nationalNumber = phoneNumber.replace(/^0+/, '')
181
- phoneNumber = `+${activeCountry.dialCode} ${nationalNumber}`
182
- } else if (phoneNumber) {
183
- phoneNumber = parseAndFormatPhoneNumber(phoneNumber)
180
+ if (phoneNumber.value && !phoneNumber.value.startsWith('+') && activeCountry.value) {
181
+ const nationalNumber = phoneNumber.value.replace(/^0+/, '')
182
+ phoneNumber.value = `+${activeCountry.value.dialCode} ${nationalNumber}`
183
+ } else if (phoneNumber.value) {
184
+ phoneNumber.value = parseAndFormatPhoneNumber(phoneNumber.value)
184
185
  }
185
186
 
186
187
  validatePhoneNumber()
187
188
  emit('blur', event)
188
189
  }
189
190
 
190
- const disableDropdown = $computed(() => 1 === countries.length && !search)
191
- const searchable = $computed(() => 7 < countries.length || search)
191
+ const disableDropdown = computed(() => countries.value.length === 1 && !search.value)
192
+ const searchable = computed(() => countries.value.length > 7 || search.value)
192
193
 
193
194
  function focusSearchInput() {
194
- setTimeout(() => searchInput?.focus(), 100)
195
+ setTimeout(() => searchInput.value?.focus(), 100)
195
196
  }
196
197
 
197
198
  onMounted(initializeCountry)