MaskedInput
Yozish paytida formatlanadigan maydonlar: telefon, summa, karta raqami va o'z niqobingiz.
Qiymat: ""
Qiymat: 1250000
Qiymat: ""
Qiymat: ""
'use client';
import { CardInput, Field, MaskedInput, MoneyInput, PhoneInput } from '@akhatmirzo/ui';
import { useState } from 'react';
export default function MaskedInputOverview() {
const [phone, setPhone] = useState('');
const [sum, setSum] = useState<number | null>(1250000);
const [card, setCard] = useState('');
const [passport, setPassport] = useState('');
return (
<div className="grid w-full max-w-2xl gap-4 sm:grid-cols-2">
<Field label="Telefon" description={`Qiymat: "${phone}"`}>
<PhoneInput value={phone} onValueChange={setPhone} />
</Field>
<Field label="Summa" description={`Qiymat: ${sum ?? 'null'}`}>
<MoneyInput value={sum} onValueChange={setSum} />
</Field>
<Field label="Karta raqami" description={`Qiymat: "${card}"`}>
<CardInput value={card} onValueChange={setCard} />
</Field>
<Field label="Pasport" description={`Qiymat: "${passport}"`}>
<MaskedInput
mask="AA 9999999"
uppercase
placeholder="AB 1234567"
value={passport}
onValueChange={setPassport}
/>
</Field>
</div>
);
}
Import
import { CardInput, MaskedInput, MoneyInput, PhoneInput } from '@akhatmirzo/ui';To'rt komponentning umumiy qoidasi: ichki qiymat — toza, ko'rinish — formatlangan. Ekranda
"(90) 123-45-67", onValueChange da esa "901234567". Serverga yuborish, saqlash va tekshirish
uchun ortiqcha belgilarni tozalash shart emas.
| Komponent | Ko'rinish | Qiymat (value) |
|---|---|---|
PhoneInput | +998 (90) 123-45-67 | "901234567" |
MoneyInput | 1 250 000 so'm | 1250000 (number) |
CardInput | 8600 1234 1234 1234 UZCARD | "8600123412341234" |
MaskedInput | AB 1234567 ("AA 9999999") | "AB1234567" |
Qachon ishlatish
- Format qat'iy bo'lgan ma'lumot uchun — telefon, karta, pasport, avtomobil raqami. Foydalanuvchi ajratuvchilarni o'zi yozmaydi, xato qilish imkoni kamayadi.
- Pul summasi uchun —
MoneyInput: minglik ajratuvchi o'qishni osonlashtiradi, qiymat esa tayyornumber. - Erkin matn uchun ishlatmang — ism, manzil, izoh oddiy Input bilan qoladi. Uzunligi o'zgaruvchan ma'lumotga niqob halal beradi.
- Har doim label bering — Field ichida. Placeholder ("(90) 123-45-67") faqat namuna, label o'rnini bosmaydi.
- Hamma narsa
Inputdan meros:size,invalid,clearable,leftIcon,disabled,readOnly— barchasi xuddi Input dagidek ishlaydi.
Kursor sakramaydi
Formatlash paytida kursor joyida qoladi: raqamni o'rtadan o'chirsangiz yoki qo'shsangiz ham u
"oxiriga qochmaydi". Backspace doimiy belgini (-, bo'sh joy, nuqta) emas, undan oldingi
raqamni o'chiradi — Delete ham xuddi shunday, oldinga qarab.
PhoneInput
O'zbekiston raqami: +998 — o'chirib bo'lmaydigan prefiks, foydalanuvchi faqat 9 raqam yozadi.
"+998 90 123 45 67" ni nusxalab joylasangiz ham to'g'ri tushadi. Operator kodi tekshiriladi (33,
50, 55, 77, 88, 90, 91, 93, 94, 95, 97, 98, 99) — noto'g'ri kodda maydon avtomatik invalid
bo'ladi.
+998 90 123 45 67 ni joylang
'use client';
import { Field, PhoneInput, type PhoneInputDetails } from '@akhatmirzo/ui';
import { useState } from 'react';
export default function PhoneInputDemo() {
const [phone, setPhone] = useState('');
const [details, setDetails] = useState<PhoneInputDetails | null>(null);
const badOperator = phone.length >= 2 && !details?.operator;
return (
<div className="flex w-full max-w-xs flex-col gap-4">
<Field
label="Telefon raqami"
required
error={badOperator ? `"${phone.slice(0, 2)}" — bunday operator kodi yo'q` : undefined}
description={
details?.valid ? `Operator: ${details.operator}` : '+998 90 123 45 67 ni joylang'
}
>
<PhoneInput
value={phone}
onValueChange={(value, info) => {
setPhone(value);
setDetails(info);
}}
/>
</Field>
<PhoneInput aria-label="Kichik" size="sm" defaultValue="991234567" />
<PhoneInput aria-label="Faqat o'qish" readOnly defaultValue="935554433" />
</div>
);
}
onValueChange ikkinchi argumentda tafsilotlarni beradi: { valid, operator, complete }. Xuddi
shu ma'lumotni komponentdan tashqarida getPhoneDetails(value) bilan olasiz — masalan forma
tekshiruvida.
import { getPhoneDetails } from '@akhatmirzo/ui';
getPhoneDetails('901234567'); // { valid: true, operator: '90', complete: true }
getPhoneDetails('121234567'); // { valid: false, operator: null, complete: true }MoneyInput
Minglik ajratuvchi — bo'sh joy, o'ngda valyuta (standart — "so'm"). Qiymat — number | null.
Mobilda raqamli klaviatura ochiladi (decimals bo'lsa — kasr nuqtasi bilan).
Qiymat: null
decimals={2}, currency="$"
100 000 dan 50 000 000 gacha
currency={null}
'use client';
import { Field, MoneyInput } from '@akhatmirzo/ui';
import { useState } from 'react';
export default function MoneyInputDemo() {
const [price, setPrice] = useState<number | null>(null);
return (
<div className="grid w-full max-w-2xl gap-4 sm:grid-cols-2">
<Field label="Narx" description={`Qiymat: ${price ?? 'null'}`}>
<MoneyInput value={price} onValueChange={setPrice} clearable />
</Field>
<Field label="Kurs" description='decimals={2}, currency="$"'>
<MoneyInput decimals={2} currency="$" defaultValue={12.5} />
</Field>
<Field label="Oylik to'lov" description="100 000 dan 50 000 000 gacha">
<MoneyInput min={100000} max={50000000} />
</Field>
<Field label="Valyutasiz" description="currency={null}">
<MoneyInput currency={null} defaultValue={980000} />
</Field>
</div>
);
}
decimals— kasr raqamlari soni (standart0). Vergul bilan yozilsa ham nuqtaga aylanadi.max— undan katta qiymatni yozib bo'lmaydi (belgi qabul qilinmaydi).min— kichik qiymat maydondan chiqqanda (blur)minga tenglashtiriladi.currency={null}— valyuta ko'rsatilmaydi;currency="$"yoki istalganReactNode.
Summa so'zlar bilan
showWords — summa maydon ostida so'z bilan yoziladi: "Bir million ikki yuz ellik ming soʻm".
Shartnoma, hisob-faktura va to'lov formalarida raqamni tekshirishga yordam beradi. Matn
@akhatmirzo/core dagi moneyToWords bilan yasaladi va yozish bilan birga yangilanadi.
Bir million ikki yuz ellik ming soʻm
Бир миллион икки юз эллик минг сўм
'use client';
import { Field, MoneyInput } from '@akhatmirzo/ui';
import { useState } from 'react';
export default function MoneyWords() {
const [amount, setAmount] = useState<number | null>(1250000);
return (
<div className="grid w-full max-w-2xl gap-4 sm:grid-cols-2">
<Field label="Shartnoma summasi">
<MoneyInput value={amount} onValueChange={setAmount} showWords />
</Field>
<Field label="Кирилл, расмий">
<MoneyInput
value={amount}
onValueChange={setAmount}
showWords={{ script: 'cyrillic', formal: true }}
/>
</Field>
</div>
);
}
showWords={{ script: 'cyrillic' }}— kirillda.scriptberilmasa, ScriptProvider dagi alifbo olinadi (provider bo'lmasa — lotin).showWords={{ formal: true }}— rasmiy uslub: "bir yuz", "bir ming".- Field ichida so'zlar
descriptiondan keyin, maydon ostida chiqadi vaaria-describedbyga qo'shiladi. Matnaria-live="polite"hududida — ekran o'quvchi yangi summani o'qiydi.
CardInput
Bank kartasi: 4 tadan guruh, o'ngda brend belgisi — UZCARD (8600), HUMO (9860), VISA
(4) va Mastercard (51–55, 2221–2720). 16 raqam kiritilganda Luhn tekshiruvi o'tkaziladi; o'tmasa —
maydon invalid.
Sinab ko'ring: 4111 1111 1111 1111
'use client';
import { CardInput, Field, getCardDetails } from '@akhatmirzo/ui';
import { useState } from 'react';
export default function CardInputDemo() {
const [card, setCard] = useState('');
const { complete, valid, brand } = getCardDetails(card);
return (
<div className="grid w-full max-w-2xl gap-4 sm:grid-cols-2">
<Field
label="Karta raqami"
error={complete && !valid ? "Karta raqami noto'g'ri" : undefined}
description={
valid ? `Karta to'g'ri · ${brand ?? 'boshqa'}` : "Sinab ko'ring: 4111 1111 1111 1111"
}
>
<CardInput value={card} onValueChange={setCard} />
</Field>
<div className="flex flex-col gap-3">
<CardInput aria-label="Uzcard" defaultValue="8600123412341234" />
<CardInput aria-label="Humo" defaultValue="9860010203040506" />
<CardInput aria-label="Luhn xato" defaultValue="4111111111111112" />
</div>
</div>
);
}
Brend belgisi rasmiy logo emas — semantik tokenlardagi neytral matnli belgi (dark mode'da ham
o'qiladi). Rasmiy logo kerak bo'lsa, renderBrand bilan o'zingiz chizing:
import { CardInput } from '@akhatmirzo/ui';
<CardInput renderBrand={(brand) => <img src={`/cards/${brand}.svg`} alt="" className="h-5" />} />;getCardDetails(value) — { brand, complete, valid }; CardBrandMark komponenti ham eksport
qilinadi (<CardBrandMark brand="humo" />).
O'z niqobingiz
MaskedInput — umumiy niqob. Belgilar: 9 — raqam, A — harf, * — istalgan belgi (bo'sh
joydan tashqari). Qolgan har qanday belgi — doimiy, foydalanuvchi uni yozmaydi. uppercase —
harflarni avtomatik katta qiladi.
mask="99 A 999 AA"
14 ta raqam
mask="99:99"
mask="****-****"
'use client';
import { Field, MaskedInput } from '@akhatmirzo/ui';
export default function MaskedInputCustom() {
return (
<div className="grid w-full max-w-2xl gap-4 sm:grid-cols-2">
<Field label="Avtomobil raqami" description='mask="99 A 999 AA"'>
<MaskedInput mask="99 A 999 AA" uppercase placeholder="01 A 123 BC" />
</Field>
<Field label="JShShIR" description="14 ta raqam">
<MaskedInput mask="99999999999999" inputMode="numeric" placeholder="14 raqam" />
</Field>
<Field label="Vaqt" description='mask="99:99"'>
<MaskedInput mask="99:99" inputMode="numeric" placeholder="09:30" />
</Field>
<Field label="Promo-kod" description='mask="****-****"'>
<MaskedInput mask="****-****" uppercase placeholder="XXXX-XXXX" />
</Field>
</div>
);
}
onValueChange(value, { formatted, complete }) — complete barcha o'rinlar to'lganini bildiradi.
Ildiz elementda data-mask atributi bor.
Formada
name bersangiz, formaga toza qiymatli yashirin <input> qo'shiladi — FormData da
"901234567", "1250000" kabi qiymat keladi, formatlangan matn emas.
<form action="/api/order">
<PhoneInput name="phone" required />
<MoneyInput name="amount" />
</form>Props
Barcha komponentlar Input props'larini (size, invalid, clearable,
leftIcon, disabled, readOnly, name, aria-* ...) va ref ni qabul qiladi. type va
defaultValue / value — o'zlariniki.
MaskedInput
| Prop | Tip | Standart | Tavsif |
|---|---|---|---|
maskmajburiy | string | — | 9 — raqam, A — harf, * — istalgan; qolgani doimiy belgi |
value | string | — | Toza qiymat, doimiy belgilarsiz: "AB1234567" |
defaultValue | string | — | |
onValueChange | (value: string, details: MaskedInputDetails) => void | — | details: { formatted, complete } |
uppercase | boolean | false | Harflarni katta harfga o'tkazish |
PhoneInput
prefix qabul qilinmaydi — u doim +998.
| Prop | Tip | Standart | Tavsif |
|---|---|---|---|
value | string | — | 9 raqam, +998 siz: "901234567" |
defaultValue | string | — | |
onValueChange | (value: string, details: PhoneInputDetails) => void | — | details: { valid, operator, complete } |
validateOperator | boolean | true | Operator kodi noto'g'ri bo'lsa avtomatik invalid |
placeholder | string | '(90) 123-45-67' |
MoneyInput
| Prop | Tip | Standart | Tavsif |
|---|---|---|---|
value | number | null | — | |
defaultValue | number | null | — | |
onValueChange | (value: number | null) => void | — | |
currency | ReactNode | "so'm" | O'ngdagi valyuta; null — ko'rsatilmaydi |
decimals | number | 0 | Kasr raqamlari soni |
min | number | — | Kichik qiymat blur paytida min ga tenglashtiriladi |
max | number | — | Undan katta qiymatni yozib bo'lmaydi |
showWords | boolean | { formal?: boolean; script?: 'latin' | 'cyrillic' } | false | Summani maydon ostida so'z bilan ko'rsatish |
placeholder | string | '0' |
CardInput
| Prop | Tip | Standart | Tavsif |
|---|---|---|---|
value | string | — | 16 raqam: "8600123412341234" |
defaultValue | string | — | |
onValueChange | (value: string, details: CardInputDetails) => void | — | details: { brand, complete, valid } |
validateLuhn | boolean | true | To'liq kiritilganda Luhn xato bo'lsa avtomatik invalid |
renderBrand | (brand: CardBrand) => ReactNode | — | Brend belgisini o'zingiz chizish |
leftIcon | ReactNode | — | Standart — karta ikonkasi |
placeholder | string | '0000 0000 0000 0000' |
CardBrand — 'uzcard' | 'humo' | 'visa' | 'mastercard' (@akhatmirzo/core dan).
Data atributlari
| Atribut | Komponent | Qiymat |
|---|---|---|
data-mask | MaskedInput | mask qiymati |
data-brand | CardInput | uzcard · humo · visa · mastercard |
Accessibility
- Native
<input type="text">— ekran o'quvchi formatlangan matnni o'qiydi, tahrirlash odatdagidek ishlaydi. - Mobil klaviatura turiga mos:
PhoneInput—inputMode="tel",CardInputvaMoneyInput—numeric(decimalsbilan —decimal). - Avtoto'ldirish:
PhoneInput—autoComplete="tel-national",CardInput—autoComplete="cc-number".MaskedInputda avtoto'ldirish o'chiq (off), imlo tekshiruvi ham. - Xato holati (
validateOperator,validateLuhn)aria-invalidsifatida beriladi. Xato sababini matn bilanFieldningerrorprop'ida ko'rsating — rang yetarli emas. - Valyuta va karta brendi dekorativ (
aria-hidden) — summa uchun label'ga valyutani yozing ("Summa, so'm"), agar u muhim bo'lsa.