@bagelink/vue 0.0.466 → 0.0.473

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 (180) hide show
  1. package/dist/components/Accordion.vue.d.ts.map +1 -1
  2. package/dist/components/AccordionItem.vue.d.ts.map +1 -1
  3. package/dist/components/Alert.vue.d.ts +2 -2
  4. package/dist/components/Alert.vue.d.ts.map +1 -1
  5. package/dist/components/Avatar.vue.d.ts.map +1 -1
  6. package/dist/components/Badge.vue.d.ts +2 -2
  7. package/dist/components/Badge.vue.d.ts.map +1 -1
  8. package/dist/components/BglVideo.vue.d.ts +2 -2
  9. package/dist/components/BglVideo.vue.d.ts.map +1 -1
  10. package/dist/components/Btn.vue.d.ts +2 -0
  11. package/dist/components/Btn.vue.d.ts.map +1 -1
  12. package/dist/components/Card.vue.d.ts.map +1 -1
  13. package/dist/components/Carousel.vue.d.ts +4 -2
  14. package/dist/components/Carousel.vue.d.ts.map +1 -1
  15. package/dist/components/DataPreview.vue.d.ts.map +1 -1
  16. package/dist/components/Drop.vue.d.ts +34 -0
  17. package/dist/components/Drop.vue.d.ts.map +1 -0
  18. package/dist/components/FileUploader.vue.d.ts +60 -0
  19. package/dist/components/FileUploader.vue.d.ts.map +1 -0
  20. package/dist/components/Flag.vue.d.ts +2 -2
  21. package/dist/components/Flag.vue.d.ts.map +1 -1
  22. package/dist/components/ListItem.vue.d.ts.map +1 -1
  23. package/dist/components/ListView.vue.d.ts.map +1 -1
  24. package/dist/components/MapEmbed.vue.d.ts +2 -2
  25. package/dist/components/MapEmbed.vue.d.ts.map +1 -1
  26. package/dist/components/MaterialIcon.vue.d.ts.map +1 -1
  27. package/dist/components/Modal.vue.d.ts +2 -1
  28. package/dist/components/Modal.vue.d.ts.map +1 -1
  29. package/dist/components/ModalConfirm.vue.d.ts.map +1 -1
  30. package/dist/components/ModalForm.vue.d.ts.map +1 -1
  31. package/dist/components/NavBar.vue.d.ts.map +1 -1
  32. package/dist/components/PageTitle.vue.d.ts.map +1 -1
  33. package/dist/components/TableSchema.vue.d.ts.map +1 -1
  34. package/dist/components/Title.vue.d.ts.map +1 -1
  35. package/dist/components/dashboard/Lineart.vue.d.ts.map +1 -1
  36. package/dist/components/dashboard/index.d.ts.map +1 -1
  37. package/dist/components/form/BglField.vue.d.ts.map +1 -1
  38. package/dist/components/form/BglForm.vue.d.ts +4 -2
  39. package/dist/components/form/BglForm.vue.d.ts.map +1 -1
  40. package/dist/components/form/ItemRef.vue.d.ts +1 -0
  41. package/dist/components/form/ItemRef.vue.d.ts.map +1 -1
  42. package/dist/components/form/index.d.ts.map +1 -1
  43. package/dist/components/form/inputs/CheckInput.vue.d.ts.map +1 -1
  44. package/dist/components/form/inputs/Checkbox.vue.d.ts.map +1 -1
  45. package/dist/components/form/inputs/ColorPicker.vue.d.ts.map +1 -1
  46. package/dist/components/form/inputs/DateInput.vue.d.ts.map +1 -1
  47. package/dist/components/form/inputs/DatePicker.vue.d.ts.map +1 -1
  48. package/dist/components/form/inputs/FileUpload.vue.d.ts +2 -1
  49. package/dist/components/form/inputs/FileUpload.vue.d.ts.map +1 -1
  50. package/dist/components/form/inputs/JSONInput.vue.d.ts.map +1 -1
  51. package/dist/components/form/inputs/RadioPillsInput.vue.d.ts.map +1 -1
  52. package/dist/components/form/inputs/RichText.vue.d.ts.map +1 -1
  53. package/dist/components/form/inputs/SelectField.vue.d.ts +1 -4
  54. package/dist/components/form/inputs/SelectField.vue.d.ts.map +1 -1
  55. package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
  56. package/dist/components/form/inputs/SignaturePad.vue.d.ts +56 -0
  57. package/dist/components/form/inputs/SignaturePad.vue.d.ts.map +1 -0
  58. package/dist/components/form/inputs/TableField.vue.d.ts.map +1 -1
  59. package/dist/components/form/inputs/TelInput.vue.d.ts +2 -2
  60. package/dist/components/form/inputs/TelInput.vue.d.ts.map +1 -1
  61. package/dist/components/form/inputs/TextInput.vue.d.ts.map +1 -1
  62. package/dist/components/form/inputs/ToggleInput.vue.d.ts.map +1 -1
  63. package/dist/components/form/inputs/index.d.ts +1 -0
  64. package/dist/components/form/inputs/index.d.ts.map +1 -1
  65. package/dist/components/index.d.ts.map +1 -1
  66. package/dist/components/layout/BottomMenu.vue.d.ts.map +1 -1
  67. package/dist/components/layout/Layout.vue.d.ts +2 -2
  68. package/dist/components/layout/Layout.vue.d.ts.map +1 -1
  69. package/dist/components/layout/SidebarMenu.vue.d.ts.map +1 -1
  70. package/dist/components/layout/TabbedLayout.vue.d.ts.map +1 -1
  71. package/dist/components/layout/Tabs.vue.d.ts.map +1 -1
  72. package/dist/components/layout/TabsBody.vue.d.ts.map +1 -1
  73. package/dist/components/layout/TabsNav.vue.d.ts.map +1 -1
  74. package/dist/components/layout/index.d.ts.map +1 -1
  75. package/dist/index.cjs +17617 -20818
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.mjs +17617 -20818
  78. package/dist/plugins/bagel.d.ts +1 -1
  79. package/dist/plugins/bagel.d.ts.map +1 -1
  80. package/dist/plugins/modal.d.ts +14 -14
  81. package/dist/plugins/modal.d.ts.map +1 -1
  82. package/dist/style.css +333 -309
  83. package/dist/types/BagelForm.d.ts +16 -16
  84. package/dist/types/BagelForm.d.ts.map +1 -1
  85. package/dist/types/BtnOptions.d.ts +1 -1
  86. package/dist/types/BtnOptions.d.ts.map +1 -1
  87. package/dist/types/NavLink.d.ts +2 -2
  88. package/dist/types/NavLink.d.ts.map +1 -1
  89. package/dist/types/file.d.ts +2 -2
  90. package/dist/types/file.d.ts.map +1 -1
  91. package/dist/types/index.d.ts.map +1 -1
  92. package/dist/types/materialIcons.d.ts.map +1 -1
  93. package/dist/utils/BagelFormUtils.d.ts.map +1 -1
  94. package/dist/utils/allCountries.d.ts +2 -2
  95. package/dist/utils/allCountries.d.ts.map +1 -1
  96. package/dist/utils/clickOutside.d.ts.map +1 -1
  97. package/dist/utils/index.d.ts +5 -5
  98. package/dist/utils/index.d.ts.map +1 -1
  99. package/package.json +19 -17
  100. package/src/components/Accordion.vue +10 -10
  101. package/src/components/AccordionItem.vue +47 -47
  102. package/src/components/Alert.vue +21 -21
  103. package/src/components/Avatar.vue +15 -15
  104. package/src/components/Badge.vue +17 -16
  105. package/src/components/BglVideo.vue +43 -43
  106. package/src/components/Btn.vue +67 -65
  107. package/src/components/Card.vue +26 -26
  108. package/src/components/Carousel.vue +130 -134
  109. package/src/components/DataPreview.vue +30 -30
  110. package/src/components/Flag.vue +26 -26
  111. package/src/components/ListItem.vue +13 -13
  112. package/src/components/ListView.vue +2 -2
  113. package/src/components/MapEmbed.vue +33 -33
  114. package/src/components/MaterialIcon.vue +12 -12
  115. package/src/components/Modal.vue +73 -66
  116. package/src/components/ModalConfirm.vue +18 -18
  117. package/src/components/ModalForm.vue +79 -76
  118. package/src/components/NavBar.vue +33 -30
  119. package/src/components/PageTitle.vue +10 -8
  120. package/src/components/TableSchema.vue +126 -113
  121. package/src/components/Title.vue +8 -8
  122. package/src/components/dashboard/Lineart.vue +103 -96
  123. package/src/components/dashboard/index.ts +1 -1
  124. package/src/components/form/BglField.vue +61 -61
  125. package/src/components/form/BglFieldSet.vue +9 -8
  126. package/src/components/form/BglForm.vue +71 -70
  127. package/src/components/form/index.ts +4 -4
  128. package/src/components/form/inputs/CheckInput.vue +25 -23
  129. package/src/components/form/inputs/Checkbox.vue +10 -10
  130. package/src/components/form/inputs/ColorPicker.vue +26 -24
  131. package/src/components/form/inputs/DateInput.vue +39 -39
  132. package/src/components/form/inputs/DatePicker.vue +37 -36
  133. package/src/components/form/inputs/FileUpload.vue +165 -161
  134. package/src/components/form/inputs/FileUploadURL.vue +134 -132
  135. package/src/components/form/inputs/JSONInput.vue +29 -29
  136. package/src/components/form/inputs/RadioPillsInput.vue +49 -49
  137. package/src/components/form/inputs/RichText.vue +62 -63
  138. package/src/components/form/inputs/SelectInput.vue +173 -167
  139. package/src/components/form/inputs/SignaturePad.vue +150 -0
  140. package/src/components/form/inputs/TableField.vue +77 -76
  141. package/src/components/form/inputs/TelInput.vue +280 -285
  142. package/src/components/form/inputs/TextInput.vue +81 -76
  143. package/src/components/form/inputs/ToggleInput.vue +13 -13
  144. package/src/components/form/inputs/index.ts +17 -15
  145. package/src/components/formkit/FileUploader.vue +162 -158
  146. package/src/components/formkit/MiscFields.vue +20 -20
  147. package/src/components/formkit/Toggle.vue +13 -13
  148. package/src/components/index.ts +28 -28
  149. package/src/components/layout/BottomMenu.vue +25 -21
  150. package/src/components/layout/Layout.vue +29 -29
  151. package/src/components/layout/SidebarMenu.vue +31 -27
  152. package/src/components/layout/TabbedLayout.vue +47 -45
  153. package/src/components/layout/Tabs.vue +32 -32
  154. package/src/components/layout/TabsBody.vue +10 -10
  155. package/src/components/layout/TabsNav.vue +44 -44
  156. package/src/components/layout/index.ts +7 -7
  157. package/src/components/layout/tabsManager.ts +6 -6
  158. package/src/index.ts +13 -8
  159. package/src/plugins/bagel.ts +37 -37
  160. package/src/plugins/modal.ts +66 -67
  161. package/src/styles/layout.css +5 -3
  162. package/src/styles/mobilLayout.css +7 -0
  163. package/src/types/BagelForm.ts +27 -27
  164. package/src/types/BtnOptions.ts +13 -13
  165. package/src/types/NavLink.ts +8 -8
  166. package/src/types/file.ts +11 -11
  167. package/src/types/index.ts +16 -12
  168. package/src/types/materialIcons.ts +3249 -3249
  169. package/src/utils/BagelFormUtils.ts +23 -23
  170. package/src/utils/allCountries.ts +11 -12
  171. package/src/utils/clickOutside.ts +6 -6
  172. package/src/utils/index.ts +39 -41
  173. package/src/utils/lang.ts +13 -13
  174. package/src/utils/strings.ts +9 -9
  175. package/tsconfig.json +0 -1
  176. package/vite.config.ts +8 -8
  177. package/dist/components/Popover.vue.d.ts +0 -10
  178. package/dist/components/Popover.vue.d.ts.map +0 -1
  179. package/dist/types/materialIcon.d.ts +0 -2
  180. package/dist/types/materialIcon.d.ts.map +0 -1
@@ -1,183 +1,20 @@
1
- <template>
2
- <div
3
- class="bagel-input"
4
- :class="{ disabled: disabled }"
5
- >
6
- <label>
7
- {{ label }}
8
- <div
9
- dir="ltr"
10
- class="flex gap-05 tel-input"
11
- tabindex="-1"
12
- aria-label="Country Code Selector"
13
- aria-haspopup="listbox"
14
- :aria-expanded="open"
15
- @keydown.esc="reset"
16
- @keydown.tab="reset"
17
- >
18
- <Dropdown
19
- :placement="'bottom'"
20
- @hide="open = false"
21
- v-if="!computedDropDownOptions.hide"
22
- :disabled="computedDropDownOptions.disabled"
23
- >
24
- <span
25
- class="flex gap-05"
26
- @click="open = true"
27
- >
28
- <Icon :icon="open ? 'collapse_all' : 'expand_all'" />
29
- <Flag
30
- v-if="computedDropDownOptions.showFlags && activeCountryCode"
31
- :country="activeCountryCode"
32
- />
33
- </span>
34
- <template #popper="{ hide }">
35
- <div class="p-075 tel-countryp-dropdown">
36
- <TextInput
37
- v-if="searchable"
38
- aria-label="Search by country name or country code"
39
- placeholder="Search"
40
- icon="search"
41
- v-model="searchQuery"
42
- />
43
-
44
- <ul
45
- ref="listEl"
46
- class="overflow-y p-0"
47
- :style="{ 'max-height': '400px' }"
48
- :class="dropdownOpenDirection"
49
- role="listbox"
50
- >
51
- <li
52
- v-for="(pb, index) in sortedCountries"
53
- role="option"
54
- class="flex gap-075"
55
- :key="pb.iso2 + isPreferred(pb)"
56
- tabindex="-1"
57
- @click="
58
- chooseCountry(pb.iso2);
59
- hide();
60
- "
61
- @mousemove="selectedIndex = index"
62
- :aria-selected="activeCountryCode === pb.iso2 && !isPreferred(pb)
63
- "
64
- >
65
- <Flag
66
- v-if="computedDropDownOptions.showFlags"
67
- :country="pb.iso2"
68
- />
69
- <p class="tel-country">{{ pb.name }}</p>
70
- <span v-if="computedDropDownOptions.showDialCodeInList">
71
- +{{ pb.dialCode }}
72
- </span>
73
- </li>
74
- </ul>
75
- </div>
76
- </template>
77
- </Dropdown>
78
-
79
- <input
80
- :required="required"
81
- :placeholder="computedInputOptions.placeholder"
82
- :disabled="disabled"
83
- v-model="phone"
84
- type="tel"
85
- ref="refInput"
86
- :autocomplete="autocomplete"
87
- :class="['vti__input']"
88
- :id="id"
89
- :pattern="computedInputOptions.pattern"
90
- :minlength="computedInputOptions.minlength"
91
- :maxlength="computedInputOptions.maxlength"
92
- :name="computedInputOptions.name"
93
- :readonly="computedInputOptions.readonly"
94
- :tabindex="computedInputOptions.tabindex"
95
- :aria-describedby="computedInputOptions['aria-describedby']"
96
- @blur="onBlur"
97
- @focus="onFocus"
98
- @keyup.enter="onEnter"
99
- @keyup.space="onSpace"
100
- @keydown="handleInput"
101
- :style="computedInputOptions.style"
102
- />
103
- </div>
104
- </label>
105
- </div>
106
- </template>
107
-
108
1
  <script lang="ts" setup>
109
2
  import {
110
- Icon,
3
+ type Country,
111
4
  Dropdown,
112
- TextInput,
113
5
  Flag,
6
+ Icon,
7
+ TextInput,
114
8
  allCountries,
115
- type Country,
116
9
  debounce,
117
- } from '@bagelink/vue';
118
- import { type Raw, type StyleValue, onMounted, watch } from 'vue';
10
+ } from '@bagelink/vue'
11
+ import { type Raw, type StyleValue, onMounted, watch } from 'vue'
119
12
  import {
120
- parsePhoneNumberFromString,
121
- type NumberFormat,
122
13
  type CountryCode,
123
- } from 'libphonenumber-js';
124
- import axios from 'axios';
125
-
126
- async function getIp() {
127
- const apiData = sessionStorage?.getItem('ipapi');
128
- if (apiData) return JSON.parse(apiData);
129
- const { data } = await axios.get('https://ipapi.co/json/');
130
- sessionStorage.setItem('ipapi', JSON.stringify(data));
131
- return data;
132
- }
133
-
134
- const defaultDropdownOptions = {
135
- hide: false,
136
- disabled: false,
137
- showFlags: true,
138
- showDialCodeInSelection: true,
139
- showDialCodeInList: true,
140
- searchable: true,
141
- };
142
-
143
- const defaultInputOptions = {
144
- showDialCode: true,
145
- autofocus: false,
146
- 'aria-describedby': '',
147
- id: '',
148
- maxlength: 25,
149
- minlength: 9,
150
- pattern: '',
151
- name: '',
152
- readonly: false,
153
- tabindex: 0,
154
- style: '' as Raw<StyleValue>,
155
- placeholder: 'Enter a phone number',
156
- };
157
-
158
- type Props = {
159
- label?: string;
160
- id?: string;
161
- autocomplete?: 'on' | 'off' | 'tel';
162
- placeholder?: string;
163
- required?: boolean;
164
- modelValue: string;
165
- allCountries?: Country[];
166
- autoFormat?: boolean;
167
- customValidate?: boolean | RegExp;
168
- defaultCountry?: string | number;
169
- disabled?: boolean;
170
- searchable?: boolean;
171
- autoDefaultCountry?: boolean;
172
- inputOptions?: Partial<typeof defaultInputOptions>;
173
- dropdownOptions?: Partial<typeof defaultDropdownOptions>;
174
- excludeCountries?: string[];
175
- mode?: NumberFormat;
176
- onlyCountries?: string[];
177
- preferredCountries?: string[];
178
- parseArg?: { extract?: boolean };
179
- debounceDelay?: number;
180
- };
14
+ type NumberFormat,
15
+ parsePhoneNumberFromString,
16
+ } from 'libphonenumber-js'
17
+ import axios from 'axios'
181
18
 
182
19
  const props = withDefaults(defineProps<Props>(), {
183
20
  modelValue: '',
@@ -197,25 +34,7 @@ const props = withDefaults(defineProps<Props>(), {
197
34
  preferredCountries: () => [],
198
35
  showDropdown: true,
199
36
  debounceDelay: 300,
200
- });
201
-
202
- const computedDropDownOptions = $computed(() => ({
203
- ...defaultDropdownOptions,
204
- ...props.dropdownOptions,
205
- }));
206
-
207
- const computedInputOptions = $computed(() => ({
208
- ...defaultInputOptions,
209
- ...props.inputOptions,
210
- }));
211
-
212
- let activeCountryCode = $ref<CountryCode>();
213
- let open = $ref(false);
214
- let selectedIndex = $ref<number>();
215
- const dropdownOpenDirection = $ref('below');
216
- const searchQuery = $ref('');
217
-
218
- const refInput = $ref<HTMLInputElement | null>(null);
37
+ })
219
38
 
220
39
  const emit = defineEmits([
221
40
  'update:modelValue',
@@ -227,78 +46,147 @@ const emit = defineEmits([
227
46
  'enter',
228
47
  'space',
229
48
  'debounce',
230
- ]);
49
+ ])
50
+
51
+ async function getIp() {
52
+ const apiData = sessionStorage.getItem('ipapi')
53
+ if (apiData) return JSON.parse(apiData)
54
+ const { data } = await axios.get('https://ipapi.co/json/')
55
+ sessionStorage.setItem('ipapi', JSON.stringify(data))
56
+ return data
57
+ }
58
+
59
+ const defaultDropdownOptions = {
60
+ hide: false,
61
+ disabled: false,
62
+ showFlags: true,
63
+ showDialCodeInSelection: true,
64
+ showDialCodeInList: true,
65
+ searchable: true,
66
+ }
67
+
68
+ const defaultInputOptions = {
69
+ 'showDialCode': true,
70
+ 'autofocus': false,
71
+ 'aria-describedby': '',
72
+ 'id': '',
73
+ 'maxlength': 25,
74
+ 'minlength': 9,
75
+ 'pattern': '',
76
+ 'name': '',
77
+ 'readonly': false,
78
+ 'tabindex': 0,
79
+ 'style': '' as Raw<StyleValue>,
80
+ 'placeholder': 'Enter a phone number',
81
+ }
82
+
83
+ interface Props {
84
+ label?: string
85
+ id?: string
86
+ autocomplete?: 'on' | 'off' | 'tel'
87
+ placeholder?: string
88
+ required?: boolean
89
+ modelValue: string
90
+ allCountries?: Country[]
91
+ autoFormat?: boolean
92
+ customValidate?: boolean | RegExp
93
+ defaultCountry?: string | number
94
+ disabled?: boolean
95
+ searchable?: boolean
96
+ autoDefaultCountry?: boolean
97
+ inputOptions?: Partial<typeof defaultInputOptions>
98
+ dropdownOptions?: Partial<typeof defaultDropdownOptions>
99
+ excludeCountries?: string[]
100
+ mode?: NumberFormat
101
+ onlyCountries?: string[]
102
+ preferredCountries?: string[]
103
+ parseArg?: { extract?: boolean }
104
+ debounceDelay?: number
105
+ }
106
+
107
+ const computedDropDownOptions = $computed(() => ({
108
+ ...defaultDropdownOptions,
109
+ ...props.dropdownOptions,
110
+ }))
111
+
112
+ const computedInputOptions = $computed(() => ({
113
+ ...defaultInputOptions,
114
+ ...props.inputOptions,
115
+ }))
116
+
117
+ let activeCountryCode = $ref<CountryCode>()
118
+ let open = $ref(false)
119
+ let selectedIndex = $ref<number>()
120
+ const dropdownOpenDirection = $ref('below')
121
+ const searchQuery = $ref('')
122
+
123
+ const refInput = $ref<HTMLInputElement | null>(null)
231
124
 
232
125
  // Computed: activeCountry
233
- const activeCountry = $computed(() =>
234
- props.allCountries.find(
235
- (country) => country.iso2 === activeCountryCode?.toUpperCase(),
236
- ),
237
- );
126
+ const activeCountry = $computed(() => props.allCountries.find(
127
+ country => country.iso2 === activeCountryCode?.toUpperCase(),
128
+ ),
129
+ )
238
130
 
239
- const isPreferred = (country?: Country) =>
240
- props.preferredCountries.includes(country?.iso2 as CountryCode);
131
+ const isPreferred = (country?: Country) => props.preferredCountries.includes(country?.iso2 as CountryCode)
241
132
 
242
133
  const filteredCountries = $computed(() => {
243
134
  if (props.onlyCountries.length) {
244
- return props.allCountries.filter(({ iso2 }) =>
245
- props.onlyCountries.some((c) => c.toUpperCase() === iso2),
246
- );
135
+ return props.allCountries.filter(({ iso2 }) => props.onlyCountries.some(c => c.toUpperCase() === iso2),
136
+ )
247
137
  }
248
138
  if (props.excludeCountries.length) {
249
139
  return props.allCountries.filter(
250
- ({ iso2 }) =>
251
- !props.excludeCountries.includes(iso2.toUpperCase()) &&
252
- !props.excludeCountries.includes(iso2.toLowerCase()),
253
- );
140
+ ({ iso2 }) => !props.excludeCountries.includes(iso2.toUpperCase())
141
+ && !props.excludeCountries.includes(iso2.toLowerCase()),
142
+ )
254
143
  }
255
- return props.allCountries;
256
- });
144
+ return props.allCountries
145
+ })
257
146
 
258
147
  const sortedCountries = $computed(() => {
259
- const preferredCountries = getCountries(props.preferredCountries);
148
+ const preferredCountries = getCountries(props.preferredCountries)
260
149
 
261
- const countriesList = [...preferredCountries, ...filteredCountries];
150
+ const countriesList = [...preferredCountries, ...filteredCountries]
262
151
  const cleanInput = searchQuery.replace(
263
- /[~`!@#$%^&*()+={}[\];:'"<>.,/\\?-_]/g,
152
+ /[~`!#$%&*()+={};:'"<>.,/?-_]/g,
264
153
  '',
265
- );
154
+ )
266
155
  return countriesList
267
156
  .filter(
268
- (c) =>
269
- new RegExp(cleanInput, 'i').test(c?.name || '') ||
270
- new RegExp(cleanInput, 'i').test(c?.iso2 || '') ||
271
- new RegExp(cleanInput, 'i').test(c?.dialCode || ''),
157
+ c => new RegExp(cleanInput, 'i').test(c.name || '')
158
+ || new RegExp(cleanInput, 'i').test(c.iso2 || '')
159
+ || new RegExp(cleanInput, 'i').test(c.dialCode || ''),
272
160
  )
273
- .filter(Boolean);
274
- });
161
+ .filter(Boolean)
162
+ })
275
163
 
276
164
  const parseArgs = $computed(() => ({
277
- ...props?.parseArg,
165
+ ...props.parseArg,
278
166
  defaultCountry: activeCountryCode,
279
- }));
167
+ }))
280
168
 
281
169
  const phone = defineModel<string>('modelValue', {
282
170
  default: '',
283
171
  set: (value) => {
284
- const formatted = formatPhone(`${value}`);
285
- if (!formatted) return '';
172
+ const formatted = formatPhone(`${value}`)
173
+ if (!formatted) return ''
286
174
 
287
- emit('update:modelValue', formatted);
288
- debounce(() => emit('debounce', formatted), props.debounceDelay);
289
- return formatted;
175
+ emit('update:modelValue', formatted)
176
+ debounce(() => { emit('debounce', formatted) }, props.debounceDelay)
177
+ return formatted
290
178
  },
291
- });
179
+ })
292
180
 
293
181
  function formatPhone(val: string): string {
294
- const phoneNumber = parsePhoneNumberFromString(val, parseArgs);
182
+ const phoneNumber = parsePhoneNumberFromString(val, parseArgs)
295
183
  if (!phoneNumber) {
296
- const dialCode =
297
- sortedCountries.find((c) => c.iso2 === activeCountryCode)?.dialCode || '';
298
- if (props.mode === 'INTERNATIONAL') return `+${dialCode}`;
299
- return dialCode;
184
+ const dialCode
185
+ = sortedCountries.find(c => c.iso2 === activeCountryCode)?.dialCode || ''
186
+ if (props.mode === 'INTERNATIONAL') return `+${dialCode}`
187
+ return dialCode
300
188
  }
301
- return phoneNumber.format(props.mode)?.replaceAll(' ', '') || '';
189
+ return phoneNumber.format(props.mode).replaceAll(' ', '') || ''
302
190
  }
303
191
 
304
192
  // Watchers
@@ -306,109 +194,216 @@ watch(
306
194
  () => activeCountry,
307
195
  (value, oldValue) => {
308
196
  if (!value && oldValue?.iso2) {
309
- activeCountryCode = oldValue.iso2;
310
- return;
197
+ activeCountryCode = oldValue.iso2
198
+ return
311
199
  }
312
- if (value?.iso2) emit('country-changed', value);
200
+ if (value?.iso2) emit('country-changed', value)
313
201
  },
314
- );
202
+ )
315
203
 
316
- const initializeCountry = async () => {
204
+ async function initializeCountry() {
317
205
  // if (phone?.[0] === '+') return;
318
206
  // 2. Use default country if passed from parent
319
207
  if (props.defaultCountry) {
320
208
  if (typeof props.defaultCountry === 'string') {
321
- chooseCountry(props.defaultCountry);
322
- return;
209
+ chooseCountry(props.defaultCountry)
210
+ return
323
211
  }
324
212
  if (typeof props.defaultCountry === 'number') {
325
- const country = findCountryByDialCode(props.defaultCountry);
213
+ const country = findCountryByDialCode(props.defaultCountry)
326
214
  if (country) {
327
- chooseCountry(country.iso2);
328
- return;
215
+ chooseCountry(country.iso2)
216
+ return
329
217
  }
330
218
  }
331
219
  }
332
220
 
333
- const fallbackCountry = sortedCountries[0];
221
+ const fallbackCountry = sortedCountries[0]
334
222
 
335
223
  if (props.autoDefaultCountry) {
336
224
  try {
337
- const res = (await getIp()).country;
338
- chooseCountry(res || activeCountryCode);
225
+ const res = (await getIp()).country
226
+ chooseCountry(res || activeCountryCode)
339
227
  } catch (error) {
340
- console.warn(error);
341
- chooseCountry(fallbackCountry?.iso2);
228
+ console.warn(error)
229
+ chooseCountry(fallbackCountry.iso2)
342
230
  }
343
231
  } else {
344
232
  // 4. Use the first country from preferred list (if available) or all countries list
345
- chooseCountry(fallbackCountry?.iso2);
233
+ chooseCountry(fallbackCountry.iso2)
346
234
  }
347
- };
235
+ }
348
236
 
349
- onMounted(initializeCountry);
237
+ onMounted(initializeCountry)
350
238
 
351
- const findCountry = (iso: string) =>
352
- filteredCountries.find((country) => country.iso2 === iso?.toUpperCase());
239
+ const findCountry = (iso: string) => filteredCountries.find(country => country.iso2 === iso.toUpperCase())
353
240
 
354
- const getCountries = (list: string[]): Country[] => {
355
- const countryList: Country[] = [];
241
+ function getCountries(list: string[]): Country[] {
242
+ const countryList: Country[] = []
356
243
  list.forEach((countryCode) => {
357
- const country = findCountry(countryCode);
358
- if (country) countryList.push(country);
359
- });
360
- return countryList;
361
- };
244
+ const country = findCountry(countryCode)
245
+ if (country) countryList.push(country)
246
+ })
247
+ return countryList
248
+ }
362
249
 
363
- const findCountryByDialCode = (dialCode: number) =>
364
- filteredCountries.find((country) => Number(country.dialCode) === dialCode);
250
+ function findCountryByDialCode(dialCode: number) {
251
+ return filteredCountries.find(country => Number(country.dialCode) === dialCode)
252
+ }
365
253
 
366
- const chooseCountry = (country?: string) => {
367
- if (!country) return;
368
- const parsedCountry = findCountry(country);
369
- if (!parsedCountry) return;
370
- activeCountryCode = parsedCountry.iso2;
254
+ function chooseCountry(country?: string) {
255
+ if (!country) return
256
+ const parsedCountry = findCountry(country)
257
+ if (!parsedCountry) return
258
+ activeCountryCode = parsedCountry.iso2
371
259
 
372
260
  if (props.inputOptions?.showDialCode && parsedCountry) {
373
- phone.value = `+ ${parsedCountry.dialCode}`;
374
- activeCountryCode = parsedCountry.iso2 || '';
375
- return;
261
+ phone.value = `+ ${parsedCountry.dialCode}`
262
+ activeCountryCode = parsedCountry.iso2 || ''
263
+ return
376
264
  }
377
265
 
378
- activeCountryCode = parsedCountry.iso2 || '';
266
+ activeCountryCode = parsedCountry.iso2 || ''
379
267
  // emitInput(phone);
380
- };
268
+ }
381
269
 
382
- const onBlur = () => emit('blur');
270
+ function onBlur() { emit('blur') }
383
271
 
384
- const onFocus = () => emit('focus');
272
+ function onFocus() { emit('focus') }
385
273
 
386
- const onEnter = (e: KeyboardEvent) => emit('enter');
274
+ function onEnter(e: KeyboardEvent) { emit('enter') }
387
275
 
388
- const onSpace = () => emit('space');
276
+ function onSpace() { emit('space') }
389
277
 
390
278
  // const focus = () => refInput?.focus();
391
279
 
392
280
  // Method: reset
393
- const reset = () => {
281
+ function reset() {
394
282
  selectedIndex = sortedCountries.findIndex(
395
- (c) => c.iso2 === activeCountryCode,
396
- );
397
- open = false;
398
- };
283
+ c => c.iso2 === activeCountryCode,
284
+ )
285
+ open = false
286
+ }
399
287
 
400
288
  function handleInput(e: KeyboardEvent) {
401
- const keyVal = e.key;
402
- if (keyVal?.length > 1 || e.metaKey) return;
289
+ const keyVal = e.key
290
+ if (keyVal.length > 1 || e.metaKey) return
403
291
 
404
- const hasBadChars = RegExp(/[^+\d]/).test(keyVal);
292
+ const hasBadChars = RegExp(/[^+\d]/).test(keyVal)
405
293
 
406
- if (!hasBadChars) return;
294
+ if (!hasBadChars) return
407
295
 
408
- e.preventDefault();
296
+ e.preventDefault()
409
297
  }
410
298
  </script>
411
299
 
300
+ <template>
301
+ <div
302
+ class="bagel-input"
303
+ :class="{ disabled }"
304
+ >
305
+ <label>
306
+ {{ label }}
307
+ <div
308
+ dir="ltr"
309
+ class="flex gap-05 tel-input"
310
+ tabindex="-1"
311
+ aria-label="Country Code Selector"
312
+ aria-haspopup="listbox"
313
+ :aria-expanded="open"
314
+ @keydown.esc="reset"
315
+ @keydown.tab="reset"
316
+ >
317
+ <Dropdown
318
+ v-if="!computedDropDownOptions.hide"
319
+ placement="bottom"
320
+ :disabled="computedDropDownOptions.disabled"
321
+ @hide="open = false"
322
+ >
323
+ <span
324
+ class="flex gap-05"
325
+ @click="open = true"
326
+ >
327
+ <Icon :icon="open ? 'collapse_all' : 'expand_all'" />
328
+ <Flag
329
+ v-if="computedDropDownOptions.showFlags && activeCountryCode"
330
+ :country="activeCountryCode"
331
+ />
332
+ </span>
333
+ <template #popper="{ hide }">
334
+ <div class="p-075 tel-countryp-dropdown">
335
+ <TextInput
336
+ v-if="searchable"
337
+ v-model="searchQuery"
338
+ aria-label="Search by country name or country code"
339
+ placeholder="Search"
340
+ icon="search"
341
+ />
342
+
343
+ <ul
344
+ ref="listEl"
345
+ class="overflow-y p-0"
346
+ :style="{ 'max-height': '400px' }"
347
+ :class="dropdownOpenDirection"
348
+ role="listbox"
349
+ >
350
+ <li
351
+ v-for="(pb, index) in sortedCountries"
352
+ :key="pb.iso2 + isPreferred(pb)"
353
+ role="option"
354
+ class="flex gap-075"
355
+ tabindex="-1"
356
+ :aria-selected="activeCountryCode === pb.iso2 && !isPreferred(pb)
357
+ "
358
+ @click="
359
+ chooseCountry(pb.iso2);
360
+ hide();
361
+ "
362
+ @mousemove="selectedIndex = index"
363
+ >
364
+ <Flag
365
+ v-if="computedDropDownOptions.showFlags"
366
+ :country="pb.iso2"
367
+ />
368
+ <p class="tel-country">{{ pb.name }}</p>
369
+ <span v-if="computedDropDownOptions.showDialCodeInList">
370
+ +{{ pb.dialCode }}
371
+ </span>
372
+ </li>
373
+ </ul>
374
+ </div>
375
+ </template>
376
+ </Dropdown>
377
+
378
+ <input
379
+ :id="id"
380
+ ref="refInput"
381
+ v-model="phone"
382
+ :required="required"
383
+ :placeholder="computedInputOptions.placeholder"
384
+ :disabled="disabled"
385
+ type="tel"
386
+ :autocomplete="autocomplete"
387
+ class="vti__input"
388
+ :pattern="computedInputOptions.pattern"
389
+ :minlength="computedInputOptions.minlength"
390
+ :maxlength="computedInputOptions.maxlength"
391
+ :name="computedInputOptions.name"
392
+ :readonly="computedInputOptions.readonly"
393
+ :tabindex="computedInputOptions.tabindex"
394
+ :aria-describedby="computedInputOptions['aria-describedby']"
395
+ :style="computedInputOptions.style"
396
+ @blur="onBlur"
397
+ @focus="onFocus"
398
+ @keyup.enter="onEnter"
399
+ @keyup.space="onSpace"
400
+ @keydown="handleInput"
401
+ >
402
+ </div>
403
+ </label>
404
+ </div>
405
+ </template>
406
+
412
407
  <style scoped>
413
408
  .tel-input {
414
409
  direction: ltr;