@bagelink/vue 1.4.99 → 1.4.103
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/AccordionItem.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/TelInput.vue.d.ts.map +1 -1
- package/dist/index.cjs +19 -19
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +19 -19
- package/dist/style.css +1 -1
- package/dist/utils/ipapi.d.ts +2 -0
- package/dist/utils/ipapi.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/components/AccordionItem.vue +12 -16
- package/src/components/Dropdown.vue +1 -1
- package/src/components/form/inputs/TelInput.vue +21 -53
- package/src/index.ts +1 -0
- package/src/utils/ipapi.ts +11 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ipapi.d.ts","sourceRoot":"","sources":["../../src/utils/ipapi.ts"],"names":[],"mappings":"AAEA,wBAAsB,KAAK,iBAQ1B"}
|
package/package.json
CHANGED
|
@@ -65,14 +65,12 @@ function toggle() {
|
|
|
65
65
|
<template>
|
|
66
66
|
<div class="accordion-item txt-start" :class="[{ flat }]">
|
|
67
67
|
<button
|
|
68
|
-
:aria-expanded="isOpen ? 'true' : 'false'"
|
|
69
|
-
|
|
70
|
-
:aria-controls="`accordion-body-${id}`"
|
|
71
|
-
@click="toggle()"
|
|
68
|
+
:aria-expanded="isOpen ? 'true' : 'false'" class="accordion-head"
|
|
69
|
+
:aria-controls="`accordion-body-${id}`" @click="toggle()"
|
|
72
70
|
>
|
|
73
71
|
<span
|
|
74
|
-
v-if="iconPosition === 'start'"
|
|
75
|
-
|
|
72
|
+
v-if="iconPosition === 'start'" class="accordion-icon"
|
|
73
|
+
:class="[iconClass, { open: isOpen && iconType === 'expand_more' }]"
|
|
76
74
|
>
|
|
77
75
|
<Icon :icon="computedIcon" />
|
|
78
76
|
</span>
|
|
@@ -84,17 +82,15 @@ function toggle() {
|
|
|
84
82
|
</slot>
|
|
85
83
|
|
|
86
84
|
<span
|
|
87
|
-
v-if="iconPosition === 'end'"
|
|
88
|
-
|
|
85
|
+
v-if="iconPosition === 'end'" class="accordion-icon"
|
|
86
|
+
:class="[iconClass, { open: isOpen && iconType === 'expand_more' }]"
|
|
89
87
|
>
|
|
90
88
|
<Icon :icon="computedIcon" />
|
|
91
89
|
</span>
|
|
92
90
|
</button>
|
|
93
91
|
<Transition name="expand">
|
|
94
92
|
<div
|
|
95
|
-
v-if="isOpen"
|
|
96
|
-
:id="`accordion-body-${id}`"
|
|
97
|
-
class="accordion-body"
|
|
93
|
+
v-if="isOpen" :id="`accordion-body-${id}`" class="accordion-body"
|
|
98
94
|
:aria-hidden="isOpen ? 'false' : 'true'"
|
|
99
95
|
>
|
|
100
96
|
<slot />
|
|
@@ -107,9 +103,9 @@ function toggle() {
|
|
|
107
103
|
.accordion-item {
|
|
108
104
|
border-bottom: 1px solid var(--border-color);
|
|
109
105
|
transition: all 0.2s;
|
|
110
|
-
cursor: pointer;
|
|
111
106
|
overflow: hidden;
|
|
112
107
|
}
|
|
108
|
+
|
|
113
109
|
.accordion-item button {
|
|
114
110
|
cursor: pointer;
|
|
115
111
|
}
|
|
@@ -130,14 +126,14 @@ function toggle() {
|
|
|
130
126
|
display: flex;
|
|
131
127
|
align-items: center;
|
|
132
128
|
flex-shrink: 0;
|
|
133
|
-
width: calc(
|
|
134
|
-
height: calc(
|
|
129
|
+
width: calc(var(--btn-height) / 1.5);
|
|
130
|
+
height: calc(var(--btn-height) / 1.5);
|
|
135
131
|
padding-inline: calc(var(--btn-padding) / 3);
|
|
136
132
|
justify-content: center;
|
|
137
133
|
}
|
|
138
134
|
|
|
139
|
-
[aria-expanded="true"] .accordion-icon
|
|
140
|
-
|
|
135
|
+
[aria-expanded="true"] .accordion-icon {
|
|
136
|
+
transform: rotate(180deg);
|
|
141
137
|
}
|
|
142
138
|
|
|
143
139
|
.accordion-label {
|
|
@@ -161,7 +161,7 @@ const computedDelay = $computed((): number | { show: number, hide: number } | un
|
|
|
161
161
|
if (delay !== undefined) return delay
|
|
162
162
|
// For hover dropdowns, add a hide delay
|
|
163
163
|
if (triggers.includes('hover')) {
|
|
164
|
-
return { show: 0, hide:
|
|
164
|
+
return { show: 0, hide: 10 } // 50ms delay before hiding
|
|
165
165
|
}
|
|
166
166
|
// For click dropdowns, no delay
|
|
167
167
|
return 0
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { Country } from '@bagelink/vue'
|
|
3
3
|
import type { CountryCode } from 'libphonenumber-js'
|
|
4
|
-
import { Dropdown, Flag, Icon, TextInput, allCountries } from '@bagelink/vue'
|
|
5
|
-
import axios from 'axios'
|
|
4
|
+
import { Dropdown, Flag, Icon, TextInput, allCountries, ipapi } from '@bagelink/vue'
|
|
6
5
|
import { parsePhoneNumberFromString } from 'libphonenumber-js'
|
|
7
6
|
import { onMounted, watch, ref } from 'vue'
|
|
8
7
|
|
|
@@ -83,13 +82,7 @@ function selectCountry(country: Country) {
|
|
|
83
82
|
}
|
|
84
83
|
|
|
85
84
|
async function getIp() {
|
|
86
|
-
|
|
87
|
-
if (!apiData) {
|
|
88
|
-
apiData = (await axios.get('https://ipapi.co/json/')).data
|
|
89
|
-
apiData = JSON.stringify(apiData)
|
|
90
|
-
sessionStorage.setItem('ipapi', apiData)
|
|
91
|
-
}
|
|
92
|
-
const { country_code } = JSON.parse(apiData)
|
|
85
|
+
const { country_code } = await ipapi()
|
|
93
86
|
selectCountry(countries.find(c => c.iso2 === country_code) ?? countries[0])
|
|
94
87
|
}
|
|
95
88
|
|
|
@@ -209,47 +202,30 @@ onMounted(initializeCountry)
|
|
|
209
202
|
<label>
|
|
210
203
|
{{ label }} <span v-if="required && label">*</span>
|
|
211
204
|
<div
|
|
212
|
-
dir="ltr"
|
|
213
|
-
|
|
214
|
-
tabindex="-1"
|
|
215
|
-
aria-label="Country Code Selector"
|
|
216
|
-
aria-haspopup="listbox"
|
|
217
|
-
:aria-expanded="open"
|
|
205
|
+
dir="ltr" class="flex gap-05 tel-input" tabindex="-1" aria-label="Country Code Selector"
|
|
206
|
+
aria-haspopup="listbox" :aria-expanded="open"
|
|
218
207
|
>
|
|
219
208
|
<Dropdown
|
|
220
|
-
v-model:shown="open"
|
|
221
|
-
placement="bottom-start"
|
|
222
|
-
:disabled="disableDropdown"
|
|
209
|
+
v-model:shown="open" placement="bottom-start" :disabled="disableDropdown"
|
|
223
210
|
@show="focusSearchInput"
|
|
224
211
|
>
|
|
225
212
|
<template #trigger>
|
|
226
213
|
<span class="flex gap-05 country-code-display">
|
|
227
214
|
<Icon v-if="!disableDropdown" :icon="open ? 'collapse_all' : 'expand_all'" />
|
|
228
|
-
<Flag v-if="activeCountryCode"
|
|
215
|
+
<Flag v-if="activeCountryCode" :country="activeCountryCode" />
|
|
229
216
|
</span>
|
|
230
217
|
</template>
|
|
231
218
|
<div class="p-075 tel-countryp-dropdown">
|
|
232
219
|
<TextInput
|
|
233
|
-
v-if="searchable"
|
|
234
|
-
|
|
235
|
-
v-model="search"
|
|
236
|
-
aria-label="Search by country name or country code"
|
|
237
|
-
placeholder="Search"
|
|
238
|
-
icon="search"
|
|
220
|
+
v-if="searchable" ref="searchInput" v-model="search"
|
|
221
|
+
aria-label="Search by country name or country code" placeholder="Search" icon="search"
|
|
239
222
|
/>
|
|
240
223
|
|
|
241
|
-
<ul
|
|
242
|
-
class="overflow-y p-0 max-h-300px"
|
|
243
|
-
role="listbox"
|
|
244
|
-
>
|
|
224
|
+
<ul class="overflow-y p-0 max-h-300px" role="listbox">
|
|
245
225
|
<li
|
|
246
|
-
v-for="(pb) in countries"
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
class="flex gap-075 pointer hover"
|
|
250
|
-
tabindex="-1"
|
|
251
|
-
:aria-selected="activeCountryCode === pb.iso2"
|
|
252
|
-
@click="selectCountry(pb)"
|
|
226
|
+
v-for="(pb) in countries" :key="pb.iso2" role="option"
|
|
227
|
+
class="flex gap-075 pointer hover" tabindex="-1"
|
|
228
|
+
:aria-selected="activeCountryCode === pb.iso2" @click="selectCountry(pb)"
|
|
253
229
|
>
|
|
254
230
|
<Flag :country="pb.iso2" />
|
|
255
231
|
<p class="tel-country">{{ pb.name }}</p>
|
|
@@ -261,22 +237,10 @@ onMounted(initializeCountry)
|
|
|
261
237
|
</div>
|
|
262
238
|
</Dropdown>
|
|
263
239
|
<input
|
|
264
|
-
:id="id"
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
:required="required"
|
|
269
|
-
:placeholder="placeholder || label || 'Phone Number'"
|
|
270
|
-
:disabled="disabled"
|
|
271
|
-
type="tel"
|
|
272
|
-
autocomplete="tel"
|
|
273
|
-
:name="id"
|
|
274
|
-
tabindex="0"
|
|
275
|
-
class="national-number-input"
|
|
276
|
-
@blur="handleBlur($event)"
|
|
277
|
-
@focus="emit('focus', $event)"
|
|
278
|
-
@keydown="emit('keydown', $event)"
|
|
279
|
-
@input="handlePhoneInput($event)"
|
|
240
|
+
:id="id" ref="inputRef" v-model="phoneNumber" v-pattern.tel :required="required"
|
|
241
|
+
:placeholder="placeholder || label || 'Phone Number'" :disabled="disabled" type="tel"
|
|
242
|
+
autocomplete="tel" :name="id" tabindex="0" class="national-number-input" @blur="handleBlur($event)"
|
|
243
|
+
@focus="emit('focus', $event)" @keydown="emit('keydown', $event)" @input="handlePhoneInput($event)"
|
|
280
244
|
@paste="emit('paste', $event)"
|
|
281
245
|
>
|
|
282
246
|
</div>
|
|
@@ -353,12 +317,16 @@ onMounted(initializeCountry)
|
|
|
353
317
|
}
|
|
354
318
|
|
|
355
319
|
@keyframes highlight-country {
|
|
356
|
-
|
|
320
|
+
|
|
321
|
+
0%,
|
|
322
|
+
100% {
|
|
357
323
|
background-color: transparent;
|
|
358
324
|
}
|
|
325
|
+
|
|
359
326
|
30% {
|
|
360
327
|
background-color: var(--primary-color-light, rgba(0, 123, 255, 0.2));
|
|
361
328
|
}
|
|
329
|
+
|
|
362
330
|
70% {
|
|
363
331
|
background-color: var(--primary-color-light, rgba(0, 123, 255, 0.2));
|
|
364
332
|
}
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import axios from 'axios'
|
|
2
|
+
|
|
3
|
+
export async function ipapi() {
|
|
4
|
+
let apiData = sessionStorage.getItem('ipapi')
|
|
5
|
+
if (!apiData) {
|
|
6
|
+
apiData = (await axios.get('https://ipapi.co/json/')).data
|
|
7
|
+
apiData = JSON.stringify(apiData)
|
|
8
|
+
sessionStorage.setItem('ipapi', apiData)
|
|
9
|
+
}
|
|
10
|
+
return JSON.parse(apiData)
|
|
11
|
+
}
|