Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/paulopariz/vue-input-phone-shadcn
🏳️ The Vue Input Phone Shadcn library is an open source project, based on Shadcn. It offers an excellent component for entering phone numbers, supporting 194 countries, with automatic formatting and advanced validation to detect invalid formats. Plus, it's highly customizable.
https://github.com/paulopariz/vue-input-phone-shadcn
componenet flag nuxt phone-number shadcn shadcn-ui tailwindcss typescript vue
Last synced: about 1 month ago
JSON representation
🏳️ The Vue Input Phone Shadcn library is an open source project, based on Shadcn. It offers an excellent component for entering phone numbers, supporting 194 countries, with automatic formatting and advanced validation to detect invalid formats. Plus, it's highly customizable.
- Host: GitHub
- URL: https://github.com/paulopariz/vue-input-phone-shadcn
- Owner: paulopariz
- Created: 2024-09-09T23:07:48.000Z (3 months ago)
- Default Branch: master
- Last Pushed: 2024-09-15T21:21:20.000Z (3 months ago)
- Last Synced: 2024-10-20T03:47:03.413Z (2 months ago)
- Topics: componenet, flag, nuxt, phone-number, shadcn, shadcn-ui, tailwindcss, typescript, vue
- Language: TypeScript
- Homepage: https://vue-input-phone-shadcn.vercel.app
- Size: 354 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Vue Input Phone Shadch - Component Documentation
[VueInputPhoneShadcn.webm](https://github.com/user-attachments/assets/2038fbcd-c0dc-4a6b-a4fe-c0a655ff1945)
## 1. Configure components
### 1.1 Install components
To get started, install the necessary Shadcn components by running the following commands in the terminal:
```bash
npx shadcn-vue@latest add button
npx shadcn-vue@latest add input
npx shadcn-vue@latest add command
npx shadcn-vue@latest add popover
```### 1.2 Install vMaska
To format the number, install the vMaska library:
```bash
npm install maska
#or
yarn add maska
#or
pnpm install maska
#or
bun add maska
```## 2. Component `PhoneInput`
In your `components` folder, create a new subfolder called `phone`. Then add a file called `PhoneInput.vue` and insert the following code:
```ts
import { Button } from "@/components/ui/button";
import {
Command,
CommandEmpty,
CommandGroup,
CommandItem,
CommandList,
CommandSeparator,
CommandInput,
} from "@/components/ui/command";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import FlagCountry from "./FlagCountry.vue";import { CaretSortIcon, CheckIcon } from "@radix-icons/vue";
import { countriesByContinent, type ICountry } from "./countries";
import { vMaska } from "maska";const props = defineProps<{
modelValue?: string;
disabled?: boolean;
placeholder?: string;
defaultCountry?: string;
}>();const emit = defineEmits<{
(e: "update:modelValue", value: string): void;
}>();const allCountries = computed(() => countriesByContinent);
const open = ref(false);
const phoneNumber = ref(props.modelValue || "");const languageToCountry: Record<string, string> = {
"pt-BR": "BR",
pt: "BR",
"fr-FR": "FR",
fr: "FR",
"it-IT": "IT",
it: "IT",
"de-DE": "DE",
de: "DE",
"es-ES": "ES",
es: "ES",
"ja-JP": "JP",
ja: "JP",
"en-US": "US",
en: "US",
};function findCountry(countryCode: string) {
const allContinents = Object.values(allCountries.value);
for (const continent of allContinents) {
const foundByCode = continent.find((country) => country.code === countryCode);
if (foundByCode) return foundByCode;
}
return null;
}const countryCode = getCountryCodeFromLanguage(navigator?.language);
const countrySelected = ref(findCountry(countryCode));function getCountryCodeFromLanguage(language: string): string {
return props.defaultCountry || languageToCountry[language] || "US";
}function selectedCountry(data: ICountry) {
if (props.disabled) return;
phoneNumber.value = "";
countrySelected.value = data;
open.value = false;
}watch(phoneNumber, (value) => {
if (props.disabled) return;
emit(
"update:modelValue",
value.length === countrySelected.value?.mask.length ? value : value + "invalid"
);
});
No country found.
{{ country.name }}
```
## 3. Component `FlagCountry`
Now, create a file called `FlagCountry.vue` in the `phone` folder and add the following content:
```ts
import { computed } from 'vue';
interface Props {
country: string;
countryName?: string;
}const props = defineProps<Props>();
const flagUrl = computed(() => {
return `https://flagcdn.com/w40/${props.country.toLowerCase()}.png`;
});
```
## 4. Countries
Now let's add the JSON that contains the country information and corresponding phone formatting. To do this, create a file called `countries.ts`:
- [`Full code available here`](https://github.com/paulopariz/vue-input-phone-shadcn/blob/master/components/ui/phone/countries.ts)```ts
type Continent = "Africa" | "Asia" | "Europe" | "Oceania" | "South America" | "North America";export interface ICountry {
code: string;
name: string;
ddd: string;
mask: string;
}const countries: Record = {
Africa: [
{ name: "Algeria", ddd: "+213", code: "DZ", mask: "+213 ### ### ###" },
{ name: "Angola", ddd: "+244", code: "AO", mask: "+244 ### ### ###" },
// Other countries...
],
// Other continents...
};function sortCountriesByName(countries: ICountry[]): ICountry[] {
return countries.slice().sort((a, b) => a.name.localeCompare(b.name));
}const countriesByContinent = Object.keys(countries).reduce(
(sorted, continent) => {
const continentKey = continent as Continent;
sorted[continentKey] = sortCountriesByName(countries[continentKey]);
return sorted;
},
{} as Record
);export { countriesByContinent };
```## 5. Export
Finally, to export the `PhoneInput.vue` component, create a file called `index.ts` inside the `phone` folder:
```ts
export { default as PhoneInput } from './PhoneInput.vue';
```