@vnkr-labs/utils
v1.0.0
Published
VNKR Design System — Helper functions (formatVND, formatDate, cn, slugify, readingTime, debounce, ...)
Maintainers
Readme
@vnkr-labs/utils
Helper functions cho VNKR Design System và các dự án Việt Nam.
Zero dependencies. Hỗ trợ ESM + CJS + TypeScript.
Cài đặt
npm install @vnkr-labs/utils
# hoặc
pnpm add @vnkr-labs/utilsFunctions
cn(...classes) — classNames helper
Kết hợp class names, bỏ qua giá trị falsy. Tương tự clsx nhưng không cần cài thêm.
import { cn } from '@vnkr-labs/utils';
cn('btn', isActive && 'btn-active', undefined, 'btn-lg')
// → 'btn btn-active btn-lg'
cn('card', { 'card--featured': true, 'card--dark': false })
// → 'card card--featured'formatVND(amount, showSymbol?) — Tiền Việt Nam Đồng
import { formatVND } from '@vnkr-labs/utils';
formatVND(1500000) // → "1.500.000 ₫"
formatVND(99000, false) // → "99.000"
formatVND(0) // → "0 ₫"formatCurrency(amount, currency?, locale?) — Currency tổng quát
import { formatCurrency } from '@vnkr-labs/utils';
formatCurrency(1500000, 'VND', 'vi') // → "1.500.000 ₫"
formatCurrency(29.99, 'USD', 'en') // → "$29.99"formatDate(date, locale?, format?) — Ngày tháng
import { formatDate } from '@vnkr-labs/utils';
formatDate('2026-09-23') // → "23 tháng 9, 2026"
formatDate('2026-09-23', 'vi', 'short') // → "23/09/2026"
formatDate('2026-09-23', 'vi', 'long') // → "Thứ tư, 23 tháng 9, 2026"
formatDate('2026-09-23', 'en') // → "September 23, 2026"
formatDate('2026-09-23', 'en', 'short') // → "09/23/2026"| format | Ví dụ (vi) |
|---|---|
| 'short' | 23/09/2026 |
| 'medium' (mặc định) | 23 tháng 9, 2026 |
| 'long' | Thứ tư, 23 tháng 9, 2026 |
formatRelativeTime(date, locale?) — Thời gian tương đối
import { formatRelativeTime } from '@vnkr-labs/utils';
formatRelativeTime(new Date(Date.now() - 30000)) // → "vừa xong"
formatRelativeTime(new Date(Date.now() - 120000)) // → "2 phút trước"
formatRelativeTime(new Date(Date.now() - 86400000)) // → "hôm qua"
formatRelativeTime(someDate, 'en') // → "3 days ago"truncate(str, maxLength, ellipsis?) — Cắt chuỗi dài
import { truncate } from '@vnkr-labs/utils';
truncate('Đây là tiêu đề bài báo rất dài cần cắt bớt', 30)
// → "Đây là tiêu đề bài báo rất..."
truncate('Short', 20) // → "Short"slugify(str) — Vietnamese-aware slug
import { slugify } from '@vnkr-labs/utils';
slugify('Hà Nội đẹp') // → "ha-noi-dep"
slugify('Tin tức Việt Nam 2026') // → "tin-tuc-viet-nam-2026"
slugify('Hello World!') // → "hello-world"stripHtml(html) — Xóa HTML tags
import { stripHtml } from '@vnkr-labs/utils';
stripHtml('<p>Xin <strong>chào</strong> bạn!</p>') // → "Xin chào bạn!"readingTime(content, locale?) — Ước tính thời gian đọc
import { readingTime } from '@vnkr-labs/utils';
readingTime('<p>Nội dung bài báo...</p>') // → "1 phút đọc"
readingTime(longArticleHtml) // → "5 phút đọc"
readingTime(content, 'en') // → "3 min read"Tốc độ đọc: 200 từ/phút (tiếng Việt), 250 từ/phút (tiếng Anh).
clamp(value, min, max) — Giới hạn số
import { clamp } from '@vnkr-labs/utils';
clamp(5, 1, 10) // → 5
clamp(-3, 0, 10) // → 0
clamp(15, 0, 10) // → 10debounce(fn, wait) — Debounce
import { debounce } from '@vnkr-labs/utils';
const onSearch = debounce((query) => fetchResults(query), 300);
input.addEventListener('input', (e) => onSearch(e.target.value));isEmail(str) — Validate email
import { isEmail } from '@vnkr-labs/utils';
isEmail('[email protected]') // → true
isEmail('not-an-email') // → falseisPhone(str) — Validate số điện thoại Việt Nam
import { isPhone } from '@vnkr-labs/utils';
isPhone('0987654321') // → true
isPhone('+84987654321') // → true
isPhone('123') // → falseHỗ trợ: đầu số 03x, 05x, 07x, 08x, 09x.
tokenVar(token) — CSS var() string
import { tokenVar } from '@vnkr-labs/utils';
// Dùng trong React inline styles hoặc JS
tokenVar('brand') // → "var(--brand)"
tokenVar('sp-4') // → "var(--sp-4)"
tokenVar('--accent') // → "var(--accent)"
// Ví dụ React:
<div style={{ color: tokenVar('brand'), padding: tokenVar('sp-4') }}>TypeScript
Package đi kèm file .d.ts đầy đủ, không cần @types/ riêng.
import { cn, formatVND, slugify } from '@vnkr-labs/utils';
import type { ClassValue } from '@vnkr-labs/utils';
const myClass: string = cn('btn', isActive && 'active');
const price: string = formatVND(price);
const slug: string = slugify(title);Types từ @vnkr-labs/types được tái sử dụng tự động qua peerDependencies.
Peer Packages
@vnkr-labs/tokens— CSS design tokens@vnkr-labs/types— TypeScript types@vnkr-labs/ui— UI component library
VNKR Labs — vnkr.vn
