@hobenakicoffee/libraries
v1.24.0
Published
Framework-agnostic shared constants, utilities, types, UI components, and moderation tools for "হবে নাকি Coffee?" projects.
Downloads
2,847
Readme
@hobenakicoffee/libraries
Framework-agnostic shared constants, utilities, types, UI components, and moderation tools for "হবে নাকি Coffee?" projects.
Installation
npm install @hobenakicoffee/libraries
# or
pnpm add @hobenakicoffee/libraries
# or
yarn add @hobenakicoffee/libraries
# or
bun add @hobenakicoffee/librariesUsage
This package exposes multiple entry points:
// Main entry - constants and types
import { PaymentStatuses, ServiceTypes, Visibility } from "@hobenakicoffee/libraries";
// Constants only
import { SupporterPlatforms } from "@hobenakicoffee/libraries/constants";
// Utilities only
import { formatAmount, formatDate, getUserPageLink } from "@hobenakicoffee/libraries/utils";
// Types only
import type { Database, Tables } from "@hobenakicoffee/libraries/types";
// Moderation tools
import { moderateText } from "@hobenakicoffee/libraries/moderation";
// UI components
import { Button, Card, Dialog } from "@hobenakicoffee/libraries/components/ui/button";
import { ThemeProvider, useTheme } from "@hobenakicoffee/libraries/providers/theme-provider";
// Class merging utility
import { cn } from "@hobenakicoffee/libraries/lib/utils";Entry Points Overview
| Entrypoint | Description |
| ---------- | ----------- |
| @hobenakicoffee/libraries | Main entry - re-exports constants and types |
| @hobenakicoffee/libraries/constants | Constants and types |
| @hobenakicoffee/libraries/utils | Utility functions |
| @hobenakicoffee/libraries/types | TypeScript types (Supabase) |
| @hobenakicoffee/libraries/moderation | Content moderation tools |
| @hobenakicoffee/libraries/providers/theme-provider | Theme provider component |
| @hobenakicoffee/libraries/lib/utils | Class merging utility (cn()) |
| @hobenakicoffee/libraries/components/ui/* | UI components |
Constants (@hobenakicoffee/libraries/constants)
Visibility
import { Visibility } from "@hobenakicoffee/libraries";
Visibility.PUBLIC // "public"
Visibility.PRIVATE // "private"productInfo
Product metadata for "হবে নাকি Coffee?":
import { productInfo } from "@hobenakicoffee/libraries";
productInfo.name // "হবে নাকি Coffee?"
productInfo.domain // "https://www.hobenakicoffee.com"
productInfo.twitterHandle // "@hobenakicoffee"
productInfo.title // Platform tagline
productInfo.description // Full description
productInfo.keywords // SEO keywords
productInfo.socials // Social media links objectcompanyInfo
Company contact and legal information:
import { companyInfo } from "@hobenakicoffee/libraries";
companyInfo.name // "Shamscorner LLC"
companyInfo.contactEmail // "[email protected]"
companyInfo.contactPhone // "+1(817) 973-7285"
companyInfo.contactLocation // Full address
companyInfo.domain // "https://www.shamscorner.com"
companyInfo.postalAddress // Postal address objectPayment Constants
import { PaymentTypes, PaymentStatuses, PaymentProviders, PaymentDirections, PayoutProviders, WithdrawalStatuses } from "@hobenakicoffee/libraries";
// Payment Types
PaymentTypes.SUBSCRIPTION // "subscription"
PaymentTypes.ONE_TIME // "one-time"
PaymentTypes.PAYOUT // "payout"
PaymentTypes.WITHDRAW_LOCK // "withdraw_lock"
PaymentTypes.WITHDRAW_RELEASE // "withdraw_release"
PaymentTypes.WITHDRAW_COMPLETE // "withdraw_complete"
PaymentTypes.MANUAL_ADJUSTMENT // "manual_adjustment"
// Payment Statuses
PaymentStatuses.PENDING // "pending"
PaymentStatuses.PROCESSING // "processing"
PaymentStatuses.COMPLETED // "completed"
PaymentStatuses.FAILED // "failed"
PaymentStatuses.REVERSED // "reversed"
PaymentStatuses.CANCELLED // "cancelled"
PaymentStatuses.REFUNDED // "refunded"
PaymentStatuses.REVIEWING // "reviewing"
// Payment Providers
PaymentProviders.HOBENAKICOFFEE // "HobeNakiCoffee"
PaymentProviders.BKASH // "Bkash"
PaymentProviders.NAGAD // "Nagad"
PaymentProviders.ROCKET // "Rocket"
PaymentProviders.UPAY // "Upay"
PaymentProviders.SSLCOMMERZ // "SSLCommerz"
PaymentProviders.AAMARPAY // "Aamarpay"
PaymentProviders.PORTWALLET // "Portwallet"
PaymentProviders.TAP // "Tap"
PaymentProviders.OTHER // "Other"
// Payment Directions
PaymentDirections.DEBIT // "debit"
PaymentDirections.CREDIT // "credit"
// Payout Providers
PayoutProviders.BKASH // "bkash"
PayoutProviders.NAGAD // "nagad"
PayoutProviders.ROCKET // "rocket"
PayoutProviders.BANK // "bank"
// Withdrawal Statuses
WithdrawalStatuses.REQUESTED // "requested"
WithdrawalStatuses.APPROVED // "approved"
WithdrawalStatuses.PROCESSING // "processing"
WithdrawalStatuses.PAID // "paid"
WithdrawalStatuses.REJECTED // "rejected"
WithdrawalStatuses.FAILED // "failed"Supporter Platforms
import { SupporterPlatforms } from "@hobenakicoffee/libraries";
SupporterPlatforms.FACEBOOK // "facebook"
SupporterPlatforms.X // "x"
SupporterPlatforms.INSTAGRAM // "instagram"
SupporterPlatforms.YOUTUBE // "youtube"
SupporterPlatforms.GITHUB // "github"
SupporterPlatforms.LINKEDIN // "linkedin"
SupporterPlatforms.TWITCH // "twitch"
SupporterPlatforms.TIKTOK // "tiktok"
SupporterPlatforms.THREADS // "threads"
SupporterPlatforms.WHATSAPP // "whatsapp"
SupporterPlatforms.TELEGRAM // "telegram"
SupporterPlatforms.DISCORD // "discord"
SupporterPlatforms.REDDIT // "reddit"
SupporterPlatforms.PINTEREST // "pinterest"
SupporterPlatformS.MEDIUM // "medium"
SupporterPlatforms.DEVTO // "devto"
SupporterPlatforms.BEHANCE // "behance"
SupporterPlatforms.DRIBBBLE // "dribbble"Service Types
import { ServiceTypes } from "@hobenakicoffee/libraries";
ServiceTypes.GIFT // "gift"
ServiceTypes.EXCLUSIVE_CONTENT // "exclusive_content"
ServiceTypes.WITHDRAWAL // "withdrawal"
ServiceTypes.FOLLOW // "follow"Utilities (@hobenakicoffee/libraries/utils)
formatAmount
Formats a number as Bangladeshi Taka (৳).
import { formatAmount, formatSignedAmount } from "@hobenakicoffee/libraries/utils";
formatAmount(1000); // "৳1,000"
formatAmount(-500); // "৳500" (absolute value)
// With direction sign
formatSignedAmount(1000, "credit"); // "+ ৳1,000"
formatSignedAmount(500, "debit"); // "- ৳500"formatDate
Formats a date string to a readable format.
import { formatDate } from "@hobenakicoffee/libraries/utils";
formatDate("2024-01-15T00:00:00Z"); // "Jan 15, 2024"
formatDate("invalid"); // "-"formatNumber
Formats a number with thousand separators.
import { formatNumber } from "@hobenakicoffee/libraries/utils";
formatNumber(1000000); // "1,000,000"formatToPlainText
Converts various data types to plain text.
import { formatToPlainText, formatMetadataKey } from "@hobenakicoffee/libraries/utils";
// Basic usage
formatToPlainText("hello"); // "hello"
formatToPlainText(123); // "123"
formatToPlainText(true); // "Yes"
formatToPlainText(false); // "No"
// With options
formatToPlainText("some long text...", { maxStringLength: 10 });
// "some lo..."
formatToPlainText({ key: "value" });
// JSON stringified
formatMetadataKey("supporterName"); // "Supporter Name"
formatMetadataKey("is_monthly"); // "Is monthly"getUserPageLink
Generates a user profile page URL.
import { getUserPageLink } from "@hobenakicoffee/libraries/utils";
getUserPageLink("johndoe");
// "https://hobenakicoffee.com/@johndoe"
getUserPageLink("johndoe", "https://custom.com");
// "https://custom.com/@johndoe"getUserNameInitials
Extracts initials from a name.
import { getInitials } from "@hobenakicoffee/libraries/utils";
getInitials("John Doe"); // "JD"
getInitials("John"); // "J"
getInitials("John Michael"); // "JM"
getInitials(null); // "?"getSocialLink
Generates social media profile URLs.
import { getSocialLink, SupporterPlatforms } from "@hobenakicoffee/libraries";
getSocialLink("johndoe", SupporterPlatforms.FACEBOOK);
// "https://facebook.com/johndoe"
getSocialLink("johndoe", SupporterPlatforms.INSTAGRAM);
// "https://instagram.com/johndoe"
getSocialLink("johndoe", SupporterPlatforms.GITHUB);
// "https://github.com/johndoe"getSocialUrl
Generates social sharing URLs with support for platform usernames.
import { getSocialUrl } from "@hobenakicoffee/libraries/utils";
// With our platform username
getSocialUrl("johndoe");
// "https://hobenakicoffee.com/@johndoe"
// With platform and supporter name
getSocialUrl(null, "instagram", "johndoe");
// "https://instagram.com/johndoe"openInNewWindow
Opens a URL in a new tab safely.
import { openInNewWindow } from "@hobenakicoffee/libraries/utils";
openInNewWindow("https://example.com");
// Opens in new tab with rel="noopener noreferrer"Social Sharing Functions
import { shareToFacebook, shareToInstagram, shareToLinkedIn, shareToX } from "@hobenakicoffee/libraries/utils";
// Facebook
shareToFacebook({
url: "https://example.com",
quote: "Check this out!",
hashtag: "coffee",
ref: "campaign123"
});
// Instagram (uses Web Share API or copies to clipboard)
shareToInstagram({
url: "https://example.com",
text: "Check this out!"
});
// LinkedIn
shareToLinkedIn({
url: "https://example.com",
title: "My Title",
summary: "Description here",
source: "HobeNakiCoffee"
});
// X (Twitter)
shareToX({
text: "Hello from HobeNakiCoffee!",
url: "https://example.com",
hashtags: "coffee,support",
via: "hobenakicoffee"
});QR Code Utilities
import { downloadQrSvgAsPng, printQrSvg } from "@hobenakicoffee/libraries/utils";
// Download QR as PNG
await downloadQrSvgAsPng(
'<svg>...</svg>',
"qr-code.png",
() => console.log("Success"),
() => console.log("Error")
);
// Print QR
printQrSvg(
'<svg>...</svg>',
"QR Code Print",
() => console.log("Error")
);toHumanReadable
Converts camelCase or snake_case strings to human-readable format.
import { toHumanReadable } from "@hobenakicoffee/libraries/utils";
toHumanReadable("camelCase"); // "Camel Case"
toHumanReadable("snake_case"); // "Snake Case"
toHumanReadable("CONSTANT_VALUE"); // "CONSTANT VALUE"
toHumanReadable("HTTPResponseCode"); // "HTTP Response Code"validatePhoneNumber
Validates Bangladeshi mobile phone numbers.
import { validatePhoneNumber } from "@hobenakicoffee/libraries/utils";
validatePhoneNumber("01712345678"); // true
validatePhoneNumber("+8801712345678"); // true
validatePhoneNumber("8801712345678"); // true
validatePhoneNumber("01512345678"); // false (invalid prefix)
validatePhoneNumber("1234567890"); // falsecheckModeration
Checks text for profanity using both local Bangla word lists and OpenAI moderation API.
import { checkModeration } from "@hobenakicoffee/libraries/utils";
import OpenAI from "openai";
const openai = new OpenAI();
const result = await checkModeration(openai, "some text to check");
result.flagged // boolean - true if content is flagged
result.categories // OpenAI categories if flagged
result.source // "profanity" | "openai" | null
result.profaneWords // Array of matched profanity words (if from profanity check)
result.error // Error if anyModeration (@hobenakicoffee/libraries/moderation)
moderateText
Local profanity detection for English and Bangla.
import { moderateText } from "@hobenakicoffee/libraries/moderation";
const result = moderateText("some bad word here");
result.isAllowed // boolean
result.matched // Array of matched wordsnormalizeLeetspeak
Converts leetspeak to normal text (e.g., "h4x0r" -> "haxor").
import { normalizeLeetspeak } from "@hobenakicoffee/libraries/moderation";
normalizeLeetspeak("h4x0r"); // "haxor"
normalizeLeetspeak("p@ssw0rd"); // "password"normalizeUnicode
Normalizes Unicode characters (removes diacritics).
import { normalizeUnicode } from "@hobenakicoffee/libraries/moderation";
normalizeUnicode("café"); // "cafe"banglaBadWords
Array of Bangla profanity words (710+ words) for content moderation.
import { banglaBadWords } from "@hobenakicoffee/libraries/moderation";
console.log(banglaBadWords.length); // 710+Types (@hobenakicoffee/libraries/types)
Full Supabase database types with Row, Insert, and Update types for each table.
import type { Database, Tables, TablesInsert, TablesUpdate, Enums } from "@hobenakicoffee/libraries/types";
// Database type
type DB = Database;
// Table row types
type Profile = Tables<"profiles">;
type Transaction = Tables<"transactions">;
type Supporter = Tables<"supporters">;
// Insert types
type NewProfile = TablesInsert<"profiles">;
type NewTransaction = TablesInsert<"transactions">;
// Update types
type ProfileUpdate = TablesUpdate<"profiles">;
// Enum types
type PaymentStatus = Enums<"payment_status_enum">;
type SupporterPlatform = Enums<"supporter_platform_enum">;Database Tables
activities- User activity trackingcoffee_gifts- Coffee gift transactionsconversation_participants- Chat participantsconversations- Chat conversationsfollows- User follow relationshipsmanager_role_permissions- Manager role permissionsmanager_user_roles- Manager user role assignmentsmanagers- Manager profilesmessages- Chat messagesmessages_*- Monthly partitioned message tablespayout_methods- User payout methodsprofiles- User profilessupporters- Supporter recordstransactions- Payment transactionswallets- User walletswithdrawal_requests- Withdrawal requests
Database Enums
manager_permission- Manager permissionsmanager_role- Manager roles (super_admin, content_manager, etc.)manager_status- Manager account statuspayment_status_enum- Payment statusespayout_provider- Payout provider typesprovider_enum- Payment providersreference_type_enum- Transaction reference typessupporter_platform_enum- Supporter platform typestransaction_direction_enum- Debit/credituser_role- User rolesvisibility_enum- Public/private visibilitywithdrawal_status- Withdrawal request statuses
UI Components
The library includes 30+ accessible UI components built on Radix UI.
Importing Components
// Individual imports (recommended for tree-shaking)
import { Button } from "@hobenakicoffee/libraries/components/ui/button";
import { Card } from "@hobenakicoffee/libraries/components/ui/card";
import { Dialog } from "@hobenakicoffee/libraries/components/ui/dialog";
import { Input } from "@hobenakicoffee/libraries/components/ui/input";
// All components available:
import { Alert } from "@hobenakicoffee/libraries/components/ui/alert";
import { AlertDialog } from "@hobenakicoffee/libraries/components/ui/alert-dialog";
import { Avatar } from "@hobenakicoffee/libraries/components/ui/avatar";
import { Badge } from "@hobenakicoffee/libraries/components/ui/badge";
import { Breadcrumb } from "@hobenakicoffee/libraries/components/ui/breadcrumb";
import { Button, ButtonGroup } from "@hobenakicoffee/libraries/components/ui/button";
import { Calendar } from "@hobenakicoffee/libraries/components/ui/calendar";
import { Card, Chart } from "@hobenakicoffee/libraries/components/ui/card";
import { Checkbox } from "@hobenakicoffee/libraries/components/ui/checkbox";
import { Dialog } from "@hobenakicoffee/libraries/components/ui/dialog";
import { Drawer } from "@hobenakicoffee/libraries/components/ui/drawer";
import { DropdownMenu } from "@hobenakicoffee/libraries/components/ui/dropdown-menu";
import { Empty, EmptyMinimal } from "@hobenakicoffee/libraries/components/ui/empty";
import { Field, Input, InputGroup, InputOtp } from "@hobenakicoffee/libraries/components/ui/input";
import { Item } from "@hobenakicoffee/libraries/components/ui/item";
import { Label } from "@hobenakicoffee/libraries/components/ui/label";
import { Popover } from "@hobenakicoffee/libraries/components/ui/popover";
import { RadioGroup } from "@hobenakicoffee/libraries/components/ui/radio-group";
import { Select } from "@hobenakicoffee/libraries/components/ui/select";
import { Separator } from "@hobenakicoffee/libraries/components/ui/separator";
import { Sheet } from "@hobenakicoffee/libraries/components/ui/sheet";
import { Sidebar } from "@hobenakicoffee/libraries/components/ui/sidebar";
import { Skeleton } from "@hobenakicoffee/libraries/components/ui/skeleton";
import { Sonner } from "@hobenakicoffee/libraries/components/ui/sonner";
import { Spinner } from "@hobenakicoffee/libraries/components/ui/spinner";
import { Table } from "@hobenakicoffee/libraries/components/ui/table";
import { Tabs } from "@hobenakicoffee/libraries/components/ui/tabs";
import { Textarea } from "@hobenakicoffee/libraries/components/ui/textarea";
import { Toggle, ToggleGroup } from "@hobenakicoffee/libraries/components/ui/toggle";
import { Tooltip } from "@hobenakicoffee/libraries/components/ui/tooltip";Component Variants
Components use cva (class-variance-authority) for variants:
import { Button } from "@hobenakicoffee/libraries/components/ui/button";
import { Badge } from "@hobenakicoffee/libraries/components/ui/badge";
// Button variants
<Button variant="default" />
<Button variant="destructive" />
<Button variant="outline" />
<Button variant="secondary" />
<Button variant="ghost" />
<Button variant="link" />
// Button sizes
<Button size="default" />
<Button size="sm" />
<Button size="lg" />
<Button size="icon" />
// Badge variants
<Badge variant="default" />
<Badge variant="secondary" />
<Badge variant="destructive" />
<Badge variant="outline" />Turnstile Captcha
import { TurnstileCaptcha } from "@hobenakicoffee/libraries/components/turnstile-captcha";
<TurnstileCaptcha
siteKey="your-site-key"
onSuccess={(token) => console.log(token)}
onError={() => console.error("Error")}
theme="auto"
/>Theme Provider (@hobenakicoffee/libraries/providers/theme-provider)
Dark/light mode theming with system preference support.
import { ThemeProvider, useTheme } from "@hobenakicoffee/libraries/providers/theme-provider";
// Wrap your app
function App({ children }) {
return (
<ThemeProvider defaultTheme="system" storageKey="my-app-theme">
{children}
</ThemeProvider>
);
}
// Use in components
function MyComponent() {
const { theme, setTheme } = useTheme();
return (
<button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>
Toggle Theme
</button>
);
}Props:
children- React nodesdefaultTheme- "light" | "dark" | "system" (default: "system")storageKey- localStorage key (default: "hobenakicoffee-app-ui-themes")
Utils (@hobenakicoffee/libraries/lib/utils)
cn
Class name merging utility combining clsx and tailwind-merge.
import { cn } from "@hobenakicoffee/libraries/lib/utils";
cn("px-2 py-1", "bg-red-500", condition && "text-white");
// Returns merged class stringAPI Reference
Constants and Types
| Export | Type | Description |
|--------|------|-------------|
| Visibility | object | PUBLIC, PRIVATE constants |
| Visibility | type | Type for visibility values |
| productInfo | object | Product metadata |
| companyInfo | object | Company information |
| PaymentTypes | object | Payment type constants |
| PaymentType | type | Type for payment types |
| PaymentStatuses | object | Payment status constants |
| PaymentStatus | type | Type for payment statuses |
| PaymentProviders | object | Payment provider constants |
| PaymentProvider | type | Type for payment providers |
| PaymentDirections | object | Payment direction constants |
| PaymentDirection | type | Type for payment directions |
| PayoutProviders | object | Payout provider constants |
| PayoutProvider | type | Type for payout providers |
| WithdrawalStatuses | object | Withdrawal status constants |
| WithdrawalStatus | type | Type for withdrawal statuses |
| SupporterPlatforms | object | Social platform constants |
| SupporterPlatform | type | Type for supporter platforms |
| ServiceTypes | object | Service type constants |
| ServiceType | type | Type for service types |
Utilities
| Function | Description |
|----------|-------------|
| formatAmount | Format number as ৳ currency |
| formatSignedAmount | Format with + or - sign |
| formatDate | Format date string |
| formatNumber | Format with thousand separators |
| formatToPlainText | Convert value to plain text |
| formatMetadataKey | Format metadata key to readable text |
| getUserPageLink | Generate user profile URL |
| getInitials | Get name initials |
| getSocialLink | Generate social profile URL |
| getSocialUrl | Generate social sharing URL |
| openInNewWindow | Open URL in new tab |
| shareToFacebook | Share to Facebook |
| shareToInstagram | Share to Instagram |
| shareToLinkedIn | Share to LinkedIn |
| shareToX | Share to X (Twitter) |
| downloadQrSvgAsPng | Download QR as PNG |
| printQrSvg | Print QR code |
| toHumanReadable | Convert camelCase/snake_case to readable |
| validatePhoneNumber | Validate Bangladeshi phone |
| checkModeration | Check text for profanity |
Moderation
| Function | Description |
|----------|-------------|
| moderateText | Check text for profanity |
| checkBanglaWords | Check for Bangla bad words |
| normalizeLeetspeak | Convert leetspeak to normal |
| normalizeUnicode | Remove Unicode diacritics |
| banglaBadWords | Bangla profanity word list |
Local Development
Install dependencies:
bun installAvailable scripts:
# Build the library
bun run build
# Run in watch mode during development
bun run dev
# Run tests
bun run test
# Run tests in watch mode
bun run test:watch
# Run type checking
bun run typecheck
# Alias for typecheck
bun run lint
# Format code
bun run format
# Check formatting
bun run format:check
# Clean build artifacts
bun run cleanProject Structure
src/
├── index.ts # Main entry
├── constants/
│ ├── common.ts # Visibility
│ ├── legal.ts # productInfo, companyInfo
│ ├── payment.ts # Payment constants
│ ├── platforms.ts # SupporterPlatforms
│ ├── services.ts # ServiceTypes
│ └── index.ts # Exports
├── utils/
│ ├── check-moderation.ts
│ ├── format-amount.ts
│ ├── format-date.ts
│ ├── format-number.ts
│ ├── format-plain-text.ts
│ ├── get-social-handle.ts
│ ├── get-social-link.ts
│ ├── get-user-name-initials.ts
│ ├── get-user-page-link.ts
│ ├── open-to-new-window.ts
│ ├── post-to-facebook.ts
│ ├── post-to-instagram.ts
│ ├── post-to-linkedin.ts
│ ├── post-to-x.ts
│ ├── qr-svg-utils.ts
│ ├── to-human-readable.ts
│ ├── validate-phone-number.ts
│ └── index.ts # Exports
├── moderation/
│ ├── datasets/
│ │ ├── bn.ts # Bangla bad words (710+)
│ │ └── index.ts
│ ├── normalizer.ts
│ ├── profanity-service.ts
│ └── index.ts # Exports
├── types/
│ ├── supabase.ts # Full Supabase types
│ └── index.ts
├── lib/
│ └── utils.ts # cn() utility
├── providers/
│ └── theme-provider.tsx # Theme provider
└── components/
├── turnstile-captcha.tsx
└── ui/ # 30+ UI components
├── alert.tsx
├── alert-dialog.tsx
├── avatar.tsx
├── badge.tsx
├── breadcrumb.tsx
├── button.tsx
├── button-group.tsx
├── calendar.tsx
├── card.tsx
├── chart.tsx
├── checkbox.tsx
├── dialog.tsx
├── drawer.tsx
├── dropdown-menu.tsx
├── empty.tsx
├── empty-minimal.tsx
├── field.tsx
├── input.tsx
├── input-group.tsx
├── input-otp.tsx
├── item.tsx
├── label.tsx
├── popover.tsx
├── radio-group.tsx
├── select.tsx
├── separator.tsx
├── sheet.tsx
├── sidebar.tsx
├── skeleton.tsx
├── sonner.tsx
├── spinner.tsx
├── table.tsx
├── tabs.tsx
├── textarea.tsx
├── toggle.tsx
├── toggle-group.tsx
└── tooltip.tsxDependencies
Runtime
@fontsource-variable/noto-sans-bengali- Bengali font@hugeicons/core-free-icons- Hugeicons@hugeicons/react- React icons@marsidev/react-turnstile- Turnstile captcha@tailwindcss/vite- Tailwind CSSclass-variance-authority- Component variantsglin-profanity- Profanity detectioninput-otp- OTP inputnext-themes- Theme provideropenai- OpenAI APIradix-ui- UI primitivesreact/react-dom- Reactreact-day-picker- Calendarrecharts- Chartsshadcn- UI componentssonner- Toast notificationstailwind-merge- Tailwind mergetailwindcss- Stylingtw-animate-css- Animationsvaul- Drawer
Dev
@biomejs/biome- Linting/formattingultracite- Ultracite CLIvite- Build tool
Release & Publish
Publishing is automated on push to the main branch via GitHub Actions. Ensure:
package.jsonversion is updated.NPM_TOKENsecret is configured with publish permissions.
For local publish (if needed):
npm publish --access public