Skip to content

mrashed21/bd-number-validator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

11 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“± bd-number-validator

Bangladesh Phone Number Validator + React Input Component

A lightweight, production-ready validator for Bangladesh mobile numbers with normalization, operator detection, React components, hook support, and full React Hook Form integration.

npm version License: MIT

Author: Muhammad Rashed
Version: 1.0.8


⭐ Features

  • βœ… Multiple Format Support - Accepts +8801781131905, 8801781131905, 01781131905, 1781131905
  • βœ… Auto Normalization - Returns standardized +8801781131905 format
  • βœ… Operator Detection - Identifies Grameenphone, Banglalink, Robi, Airtel, Teletalk
  • βœ… Live Validation - Real-time validation that starts after sufficient digits
  • βœ… Smart Error Handling - No errors on empty input
  • βœ… Smart Cursor Positioning - Maintains cursor position during formatting
  • βœ… Auto-formatting UI - Displays as 1XX XXXX XXXX while typing
  • βœ… Bangladesh Flag Icon - Built-in SVG flag component
  • βœ… React Hook + Component - Ready-to-use hooks and components
  • βœ… Tailwind-Friendly - Fully customizable with Tailwind classes
  • βœ… React Hook Form Integration - Seamless integration with form libraries
  • βœ… TypeScript Support - Full type safety
  • βœ… Zero Config CSS - Styles load automatically

πŸ“¦ Installation

npm i bd-number-validator

Or using Yarn:

yarn add bd-number-validator

🧠 1. Core Validator Usage

Basic Validation

import { validatePhoneNumber } from "bd-number-validator";

const result = validatePhoneNumber("01781131905");

console.log(result);
/*
{
  isValid: true,
  normalized: "+8801781131905",
  operator: "Grameenphone"
}
*/

Pre-Submit Validation

const result = validatePhoneNumber(phone);

if (!result.isValid) {
  console.error(result.error);
  return;
}

// Submit using normalized number
api.post("/signup", { phone: result.normalized });

Auto-Clean During Typing

validatePhoneNumber(" 017 8113-1905 ");
// Automatically removes spaces and special characters

Shorthand Format Support

Input Auto-Fixed Output
1781131905 01781131905
8801781131905 01781131905
+8801781131905 normalized format

βš›οΈ 2. React Hook Usage (useBDPhone)

import "bd-number-validator/react/style.css";
import { useBDPhone } from "bd-number-validator";

export default function App() {
  const { raw, onChange, error, normalized, operator, isValid } =
    useBDPhone("");

  return (
    <div>
      <input
        value={raw}
        placeholder="Enter phone number"
        onChange={(e) => onChange(e.target.value)}
      />

      {error && <p style={{ color: "red" }}>{error}</p>}

      {isValid && normalized && (
        <>
          <p>Normalized: {normalized}</p>
          <p>Operator: {operator}</p>
        </>
      )}
    </div>
  );
}

🎨 3. React Component β€” <BDPhoneInput />

Basic Example

import "bd-number-validator/react/style.css";
import { BDPhoneInput } from "bd-number-validator";

export default function Demo() {
  return <BDPhoneInput onValueChange={(val) => console.log(val)} />;
}

Features

  • Bangladesh Flag: Built-in SVG flag icon
  • Auto-formatting: Displays as 1XX XXXX XXXX format
  • Smart Cursor: Maintains cursor position during typing
  • Validation: Shows errors after 3+ digits entered
  • Customizable: All parts can be styled or replaced

With Label

<BDPhoneInput
  label="Phone Number"
  showLabel={true}
  onValueChange={(val) => console.log(val)}
/>

Custom Error UI

<BDPhoneInput
  renderError={(msg) => <div className="text-red-600 font-bold">⚠ {msg}</div>}
/>

Custom Flag

<BDPhoneInput
  renderFlag={() => <img src="/bd-flag.png" alt="BD" className="w-6 h-4" />}
/>

Full Tailwind Customization

<BDPhoneInput
  label="Mobile Number"
  showLabel={true}
  containerClass="mb-4"
  labelClass="block text-sm font-medium text-gray-700 mb-2"
  wrapperClass="flex items-center gap-2 border border-gray-300 rounded-lg px-3 py-2 focus-within:ring-2 focus-within:ring-blue-500"
  flagClass="w-6 h-4"
  prefixClass="text-gray-600 font-medium"
  inputClass="flex-1 outline-none text-gray-900"
  errorClass="text-sm text-red-600 mt-1"
  showError={true}
  onValueChange={(v) => console.log(v)}
/>

Custom Label Renderer

<BDPhoneInput
  label="Phone Number"
  renderLabel={(label) => (
    <div className="flex items-center gap-2 mb-2">
      <span className="font-semibold">{label}</span>
      <span className="text-xs text-gray-500">(Required)</span>
    </div>
  )}
/>

Custom Prefix

<BDPhoneInput
  renderPrefix={() => <span className="text-blue-600 font-bold">+880</span>}
/>

πŸ“š 4. API Reference

validatePhoneNumber(phone: string)

Returns:

Field Type Description
isValid boolean Phone number validity
error string | undefined Error message if invalid
normalized string | undefined +8801XXXXXXXXX format
operator Operator | undefined GP, BL, Robi, Airtel, Teletalk

useBDPhone(initialValue: string)

Returns:

Field Type Description
raw string Current input value
error string | undefined Validation error
normalized string | undefined Normalized BD format
operator Operator | undefined Operator name
isValid boolean true if number is valid
onChange (value: string) => void Pass to input onChange

<BDPhoneInput /> Props

Value & Change Handling

Prop Type Default Description
value string β€” Controlled value
onValueChange (v?: string) => void β€” Returns normalized number

Label Props

Prop Type Default Description
label string "Phone Number" Input label text
showLabel boolean true Show/hide label
labelClass string "" Label CSS class
renderLabel (label: string) => ReactNode β€” Custom label renderer

Styling Props

Prop Type Default Description
containerClass string "" Outer container class
wrapperClass string "" Input wrapper class
flagClass string "" Flag icon class
prefixClass string "" +880 prefix class
inputClass string "" Input field class
errorClass string "" Error message class

Custom Renderers

Prop Type Default Description
renderFlag () => ReactNode β€” Custom flag component
renderPrefix () => ReactNode β€” Custom prefix (e.g. +880)
renderError (error: string) => ReactNode β€” Custom error renderer

Error Display

Prop Type Default Description
showError boolean true Toggle error visibility

πŸ“‘ 5. Operator Detection Table

Operator Prefix
Grameenphone 017, 013
Banglalink 019, 014
Robi 018
Airtel 016
Teletalk 015

πŸ§ͺ 6. Example Outputs

βœ… Valid Example

{
  "isValid": true,
  "normalized": "+8801781131905",
  "operator": "Grameenphone"
}

βœ… Empty Input (Valid)

{
  "isValid": true
}

βœ… Partial Input (Valid until 3 digits)

{
  "isValid": true,
  "operator": "Grameenphone"
}

❌ Invalid Operator

{
  "isValid": false,
  "error": "Invalid operator"
}

❌ Invalid Length

{
  "isValid": false,
  "error": "Invalid number"
}

🎯 7. Formatting Behavior

UI Formatting (formatBDPhoneUI)

The input automatically formats digits as you type:

Raw Input Displayed As
017 017
0178 017 8
01781 017 81
017811 017 811
0178113 017 8113
01781131 017 8113 1
017811319 017 8113 19
0178113190 017 8113 190
01781131905 017 8113 1905

Note: Formatting is only for display. The actual value stored is numeric only.


πŸ”§ 8. React Hook Form Integration

βœ… Method A: With Controller (Recommended)

import "bd-number-validator/react/style.css";
import { Controller, useForm } from "react-hook-form";
import { BDPhoneInput, validatePhoneNumber } from "bd-number-validator";

export default function Form() {
  const { control, handleSubmit } = useForm();

  const onSubmit = (values) => console.log(values);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="phone"
        control={control}
        rules={{
          validate: (v) => {
            const r = validatePhoneNumber(v || "");
            return r.isValid || r.error || "Invalid phone number";
          },
        }}
        render={({ field, fieldState }) => (
          <BDPhoneInput
            value={field.value}
            onValueChange={field.onChange}
            showError={!!fieldState.error}
            renderError={() => (
              <span className="text-red-600">{fieldState.error?.message}</span>
            )}
          />
        )}
      />

      <button type="submit">Submit</button>
    </form>
  );
}

βœ… Method B: Without Controller (Simplest)

import "bd-number-validator/react/style.css";
import { useForm } from "react-hook-form";
import { BDPhoneInput, validatePhoneNumber } from "bd-number-validator";

export default function Form() {
  const {
    register,
    handleSubmit,
    setValue,
    getValues,
    formState: { errors },
  } = useForm();

  const submit = (data) => {
    const result = validatePhoneNumber(data.phone);
    console.log("Final normalized:", result.normalized);
  };

  return (
    <form onSubmit={handleSubmit(submit)}>
      <BDPhoneInput
        value={getValues("phone")}
        onValueChange={(v) => setValue("phone", v ?? "")}
        showError={!!errors.phone}
        renderError={() => (
          <span className="text-red-600">{errors.phone?.message}</span>
        )}
      />

      <input
        type="hidden"
        {...register("phone", {
          validate: (v) => {
            const r = validatePhoneNumber(v || "");
            return r.isValid || r.error || "Invalid phone number";
          },
        })}
      />

      <button type="submit">Submit</button>
    </form>
  );
}

🎨 9. Styling Examples

Example 1: Modern Card Style

<BDPhoneInput
  containerClass="max-w-md"
  labelClass="block text-sm font-semibold text-gray-800 mb-2"
  wrapperClass="flex items-center gap-3 bg-white border-2 border-gray-200 rounded-xl px-4 py-3 shadow-sm hover:border-blue-400 focus-within:border-blue-500 focus-within:ring-4 focus-within:ring-blue-100 transition-all"
  flagClass="w-7 h-5 rounded"
  prefixClass="text-gray-700 font-semibold text-base"
  inputClass="flex-1 outline-none text-gray-900 text-base placeholder-gray-400"
  errorClass="text-sm text-red-500 mt-2 ml-1"
/>

Example 2: Minimal Style

<BDPhoneInput
  showLabel={false}
  wrapperClass="flex items-center gap-2 border-b-2 border-gray-300 pb-2 focus-within:border-blue-500 transition-colors"
  flagClass="w-6 h-4"
  prefixClass="text-gray-500"
  inputClass="flex-1 outline-none bg-transparent"
  errorClass="text-xs text-red-500 mt-1"
/>

Example 3: Dark Mode

<BDPhoneInput
  containerClass="bg-gray-900 p-6 rounded-lg"
  labelClass="text-gray-300 text-sm mb-2 block"
  wrapperClass="flex items-center gap-3 bg-gray-800 border border-gray-700 rounded-lg px-4 py-3 focus-within:border-blue-500 focus-within:ring-2 focus-within:ring-blue-500/50"
  flagClass="w-6 h-4"
  prefixClass="text-gray-400 font-medium"
  inputClass="flex-1 outline-none bg-transparent text-white placeholder-gray-500"
  errorClass="text-sm text-red-400 mt-2"
/>

πŸ’‘ 10. Advanced Usage

Controlled Component with External State

import "bd-number-validator/react/style.css";
import { useState } from "react";
import { BDPhoneInput } from "bd-number-validator";

export default function App() {
  const [phone, setPhone] = useState("");

  return (
    <div>
      <BDPhoneInput value={phone} onValueChange={setPhone} />

      <button onClick={() => console.log(phone)}>Submit: {phone}</button>
    </div>
  );
}

Multiple Phone Inputs

export default function App() {
  const [primary, setPrimary] = useState("");
  const [secondary, setSecondary] = useState("");

  return (
    <div>
      <BDPhoneInput
        label="Primary Phone"
        value={primary}
        onValueChange={setPrimary}
      />

      <BDPhoneInput
        label="Secondary Phone"
        value={secondary}
        onValueChange={setSecondary}
      />
    </div>
  );
}

πŸš€ 11. TypeScript Support

All components and functions are fully typed:

import "bd-number-validator/react/style.css";
import {
  BDPhoneInput,
  useBDPhone,
  validatePhoneNumber,
  PhoneValidationResult,
} from "bd-number-validator";

const result: PhoneValidationResult = validatePhoneNumber("01781131905");

const MyComponent = () => {
  const { raw, isValid, normalized } = useBDPhone("");

  return <BDPhoneInput onValueChange={(v?: string) => console.log(v)} />;
};

πŸ“„ License

MIT Β© Muhammad Rashed


🀝 Contributing

Pull requests, issues, and feedback are welcome!

GitHub Repository: https://github.com/mrashed21/bd-number-validator


πŸ“§ Support

For support and inquiries, contact: rashedjaman768@gmail.com


🌟 Show Your Support

If you find this package helpful, please consider giving it a ⭐ on GitHub!

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published