@hobenakicoffee/libraries 1.17.1 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @hobenakicoffee/libraries
2
2
 
3
- Framework-agnostic shared constants and utilities for "হবে নাকি Coffee?" projects.
3
+ Framework-agnostic shared constants, utilities, types, UI components, and moderation tools for "হবে নাকি Coffee?" projects.
4
4
 
5
5
  ## Installation
6
6
 
@@ -16,42 +16,736 @@ bun add @hobenakicoffee/libraries
16
16
 
17
17
  ## Usage
18
18
 
19
- This package exposes three entry points:
19
+ This package exposes multiple entry points:
20
20
 
21
- - `@hobenakicoffee/libraries` (re-exports constants)
22
- - `@hobenakicoffee/libraries/constants`
23
- - `@hobenakicoffee/libraries/utils`
21
+ ```ts
22
+ // Main entry - constants and types
23
+ import { PaymentStatuses, ServiceTypes, Visibility } from "@hobenakicoffee/libraries";
24
+
25
+ // Constants only
26
+ import { SupporterPlatforms } from "@hobenakicoffee/libraries/constants";
27
+
28
+ // Utilities only
29
+ import { formatAmount, formatDate, getUserPageLink } from "@hobenakicoffee/libraries/utils";
30
+
31
+ // Types only
32
+ import type { Database, Tables } from "@hobenakicoffee/libraries/types";
33
+
34
+ // Moderation tools
35
+ import { moderateText } from "@hobenakicoffee/libraries/moderation";
36
+
37
+ // UI components
38
+ import { Button, Card, Dialog } from "@hobenakicoffee/libraries/components/ui/button";
39
+ import { ThemeProvider, useTheme } from "@hobenakicoffee/libraries/providers/theme-provider";
40
+
41
+ // Class merging utility
42
+ import { cn } from "@hobenakicoffee/libraries/lib/utils";
43
+ ```
44
+
45
+ ## Entry Points Overview
46
+
47
+ | Entrypoint | Description |
48
+ | ---------- | ----------- |
49
+ | `@hobenakicoffee/libraries` | Main entry - re-exports constants and types |
50
+ | `@hobenakicoffee/libraries/constants` | Constants and types |
51
+ | `@hobenakicoffee/libraries/utils` | Utility functions |
52
+ | `@hobenakicoffee/libraries/types` | TypeScript types (Supabase) |
53
+ | `@hobenakicoffee/libraries/moderation` | Content moderation tools |
54
+ | `@hobenakicoffee/libraries/providers/theme-provider` | Theme provider component |
55
+ | `@hobenakicoffee/libraries/lib/utils` | Class merging utility (`cn()`) |
56
+ | `@hobenakicoffee/libraries/components/ui/*` | UI components |
57
+
58
+ ---
59
+
60
+ ## Constants (`@hobenakicoffee/libraries/constants`)
24
61
 
25
- Examples:
62
+ ### Visibility
26
63
 
27
64
  ```ts
28
- import { PaymentStatuses, ServiceTypes } from "@hobenakicoffee/libraries";
65
+ import { Visibility } from "@hobenakicoffee/libraries";
29
66
 
30
- import { SupporterPlatforms } from "@hobenakicoffee/libraries/constants";
67
+ Visibility.PUBLIC // "public"
68
+ Visibility.PRIVATE // "private"
69
+ ```
70
+
71
+ ### productInfo
72
+
73
+ Product metadata for "হবে নাকি Coffee?":
31
74
 
32
- import {
33
- formatAmount,
34
- formatDate,
35
- getUserPageLink,
36
- } from "@hobenakicoffee/libraries/utils";
75
+ ```ts
76
+ import { productInfo } from "@hobenakicoffee/libraries";
77
+
78
+ productInfo.name // "হবে নাকি Coffee?"
79
+ productInfo.domain // "https://www.hobenakicoffee.com"
80
+ productInfo.twitterHandle // "@hobenakicoffee"
81
+ productInfo.title // Platform tagline
82
+ productInfo.description // Full description
83
+ productInfo.keywords // SEO keywords
84
+ productInfo.socials // Social media links object
37
85
  ```
38
86
 
39
- ## API at a glance
87
+ ### companyInfo
40
88
 
41
- ### Constants and types
89
+ Company contact and legal information:
42
90
 
43
- | Entrypoint | Runtime exports | Type exports |
44
- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- |
45
- | `@hobenakicoffee/libraries` | Re-exports all constants from `@hobenakicoffee/libraries/constants` | Re-exports all types from `@hobenakicoffee/libraries/constants` |
46
- | `@hobenakicoffee/libraries/constants` | `Visibility`, `productInfo`, `companyInfo`, `PaymentTypes`, `PaymentStatuses`, `PaymentProviders`, `PaymentDirections`, `SupporterPlatforms`, `ServiceTypes` | `Visibility`, `PaymentType`, `PaymentStatus`, `PaymentProvider`, `PaymentDirection`, `SupporterPlatform`, `ServiceType` |
91
+ ```ts
92
+ import { companyInfo } from "@hobenakicoffee/libraries";
93
+
94
+ companyInfo.name // "Shamscorner LLC"
95
+ companyInfo.contactEmail // "mail@shamscorner.com"
96
+ companyInfo.contactPhone // "+1(817) 973-7285"
97
+ companyInfo.contactLocation // Full address
98
+ companyInfo.domain // "https://www.shamscorner.com"
99
+ companyInfo.postalAddress // Postal address object
100
+ ```
47
101
 
48
- ### Utilities
102
+ ### Payment Constants
103
+
104
+ ```ts
105
+ import { PaymentTypes, PaymentStatuses, PaymentProviders, PaymentDirections, PayoutProviders, WithdrawalStatuses } from "@hobenakicoffee/libraries";
106
+
107
+ // Payment Types
108
+ PaymentTypes.SUBSCRIPTION // "subscription"
109
+ PaymentTypes.ONE_TIME // "one-time"
110
+ PaymentTypes.PAYOUT // "payout"
111
+ PaymentTypes.WITHDRAW_LOCK // "withdraw_lock"
112
+ PaymentTypes.WITHDRAW_RELEASE // "withdraw_release"
113
+ PaymentTypes.WITHDRAW_COMPLETE // "withdraw_complete"
114
+ PaymentTypes.MANUAL_ADJUSTMENT // "manual_adjustment"
115
+
116
+ // Payment Statuses
117
+ PaymentStatuses.PENDING // "pending"
118
+ PaymentStatuses.PROCESSING // "processing"
119
+ PaymentStatuses.COMPLETED // "completed"
120
+ PaymentStatuses.FAILED // "failed"
121
+ PaymentStatuses.REVERSED // "reversed"
122
+ PaymentStatuses.CANCELLED // "cancelled"
123
+ PaymentStatuses.REFUNDED // "refunded"
124
+ PaymentStatuses.REVIEWING // "reviewing"
125
+
126
+ // Payment Providers
127
+ PaymentProviders.HOBENAKICOFFEE // "HobeNakiCoffee"
128
+ PaymentProviders.BKASH // "Bkash"
129
+ PaymentProviders.NAGAD // "Nagad"
130
+ PaymentProviders.ROCKET // "Rocket"
131
+ PaymentProviders.UPAY // "Upay"
132
+ PaymentProviders.SSLCOMMERZ // "SSLCommerz"
133
+ PaymentProviders.AAMARPAY // "Aamarpay"
134
+ PaymentProviders.PORTWALLET // "Portwallet"
135
+ PaymentProviders.TAP // "Tap"
136
+ PaymentProviders.OTHER // "Other"
137
+
138
+ // Payment Directions
139
+ PaymentDirections.DEBIT // "debit"
140
+ PaymentDirections.CREDIT // "credit"
141
+
142
+ // Payout Providers
143
+ PayoutProviders.BKASH // "bkash"
144
+ PayoutProviders.NAGAD // "nagad"
145
+ PayoutProviders.ROCKET // "rocket"
146
+ PayoutProviders.BANK // "bank"
147
+
148
+ // Withdrawal Statuses
149
+ WithdrawalStatuses.REQUESTED // "requested"
150
+ WithdrawalStatuses.APPROVED // "approved"
151
+ WithdrawalStatuses.PROCESSING // "processing"
152
+ WithdrawalStatuses.PAID // "paid"
153
+ WithdrawalStatuses.REJECTED // "rejected"
154
+ WithdrawalStatuses.FAILED // "failed"
155
+ ```
49
156
 
50
- | Entrypoint | Function exports |
51
- | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
52
- | `@hobenakicoffee/libraries/utils` | `checkModeration`, `formatAmount`, `formatSignedAmount`, `formatDate`, `formatNumber`, `formatToPlainText`, `getSocialHandle`, `getSocialUrl`, `getUserNameInitials`, `getUserPageLink`, `openInNewWindow`, `shareToFacebook`, `shareToInstagram`, `shareToLinkedIn`, `shareToX`, `printQrSvg`, `toHumanReadable`, `validatePhoneNumber` |
157
+ ### Supporter Platforms
53
158
 
54
- ## Local development
159
+ ```ts
160
+ import { SupporterPlatforms } from "@hobenakicoffee/libraries";
161
+
162
+ SupporterPlatforms.FACEBOOK // "facebook"
163
+ SupporterPlatforms.X // "x"
164
+ SupporterPlatforms.INSTAGRAM // "instagram"
165
+ SupporterPlatforms.YOUTUBE // "youtube"
166
+ SupporterPlatforms.GITHUB // "github"
167
+ SupporterPlatforms.LINKEDIN // "linkedin"
168
+ SupporterPlatforms.TWITCH // "twitch"
169
+ SupporterPlatforms.TIKTOK // "tiktok"
170
+ SupporterPlatforms.THREADS // "threads"
171
+ SupporterPlatforms.WHATSAPP // "whatsapp"
172
+ SupporterPlatforms.TELEGRAM // "telegram"
173
+ SupporterPlatforms.DISCORD // "discord"
174
+ SupporterPlatforms.REDDIT // "reddit"
175
+ SupporterPlatforms.PINTEREST // "pinterest"
176
+ SupporterPlatformS.MEDIUM // "medium"
177
+ SupporterPlatforms.DEVTO // "devto"
178
+ SupporterPlatforms.BEHANCE // "behance"
179
+ SupporterPlatforms.DRIBBBLE // "dribbble"
180
+ ```
181
+
182
+ ### Service Types
183
+
184
+ ```ts
185
+ import { ServiceTypes } from "@hobenakicoffee/libraries";
186
+
187
+ ServiceTypes.GIFT // "gift"
188
+ ServiceTypes.EXCLUSIVE_CONTENT // "exclusive_content"
189
+ ServiceTypes.WITHDRAWAL // "withdrawal"
190
+ ServiceTypes.FOLLOW // "follow"
191
+ ```
192
+
193
+ ---
194
+
195
+ ## Utilities (`@hobenakicoffee/libraries/utils`)
196
+
197
+ ### formatAmount
198
+
199
+ Formats a number as Bangladeshi Taka (৳).
200
+
201
+ ```ts
202
+ import { formatAmount, formatSignedAmount } from "@hobenakicoffee/libraries/utils";
203
+
204
+ formatAmount(1000); // "৳1,000"
205
+ formatAmount(-500); // "৳500" (absolute value)
206
+
207
+ // With direction sign
208
+ formatSignedAmount(1000, "credit"); // "+ ৳1,000"
209
+ formatSignedAmount(500, "debit"); // "- ৳500"
210
+ ```
211
+
212
+ ### formatDate
213
+
214
+ Formats a date string to a readable format.
215
+
216
+ ```ts
217
+ import { formatDate } from "@hobenakicoffee/libraries/utils";
218
+
219
+ formatDate("2024-01-15T00:00:00Z"); // "Jan 15, 2024"
220
+ formatDate("invalid"); // "-"
221
+ ```
222
+
223
+ ### formatNumber
224
+
225
+ Formats a number with thousand separators.
226
+
227
+ ```ts
228
+ import { formatNumber } from "@hobenakicoffee/libraries/utils";
229
+
230
+ formatNumber(1000000); // "1,000,000"
231
+ ```
232
+
233
+ ### formatToPlainText
234
+
235
+ Converts various data types to plain text.
236
+
237
+ ```ts
238
+ import { formatToPlainText, formatMetadataKey } from "@hobenakicoffee/libraries/utils";
239
+
240
+ // Basic usage
241
+ formatToPlainText("hello"); // "hello"
242
+ formatToPlainText(123); // "123"
243
+ formatToPlainText(true); // "Yes"
244
+ formatToPlainText(false); // "No"
245
+
246
+ // With options
247
+ formatToPlainText("some long text...", { maxStringLength: 10 });
248
+ // "some lo..."
249
+
250
+ formatToPlainText({ key: "value" });
251
+ // JSON stringified
252
+
253
+ formatMetadataKey("supporterName"); // "Supporter Name"
254
+ formatMetadataKey("is_monthly"); // "Is monthly"
255
+ ```
256
+
257
+ ### getUserPageLink
258
+
259
+ Generates a user profile page URL.
260
+
261
+ ```ts
262
+ import { getUserPageLink } from "@hobenakicoffee/libraries/utils";
263
+
264
+ getUserPageLink("johndoe");
265
+ // "https://hobenakicoffee.com/@johndoe"
266
+
267
+ getUserPageLink("johndoe", "https://custom.com");
268
+ // "https://custom.com/@johndoe"
269
+ ```
270
+
271
+ ### getUserNameInitials
272
+
273
+ Extracts initials from a name.
274
+
275
+ ```ts
276
+ import { getInitials } from "@hobenakicoffee/libraries/utils";
277
+
278
+ getInitials("John Doe"); // "JD"
279
+ getInitials("John"); // "J"
280
+ getInitials("John Michael"); // "JM"
281
+ getInitials(null); // "?"
282
+ ```
283
+
284
+ ### getSocialLink
285
+
286
+ Generates social media profile URLs.
287
+
288
+ ```ts
289
+ import { getSocialLink, SupporterPlatforms } from "@hobenakicoffee/libraries";
290
+
291
+ getSocialLink("johndoe", SupporterPlatforms.FACEBOOK);
292
+ // "https://facebook.com/johndoe"
293
+
294
+ getSocialLink("johndoe", SupporterPlatforms.INSTAGRAM);
295
+ // "https://instagram.com/johndoe"
296
+
297
+ getSocialLink("johndoe", SupporterPlatforms.GITHUB);
298
+ // "https://github.com/johndoe"
299
+ ```
300
+
301
+ ### getSocialUrl
302
+
303
+ Generates social sharing URLs with support for platform usernames.
304
+
305
+ ```ts
306
+ import { getSocialUrl } from "@hobenakicoffee/libraries/utils";
307
+
308
+ // With our platform username
309
+ getSocialUrl("johndoe");
310
+ // "https://hobenakicoffee.com/@johndoe"
311
+
312
+ // With platform and supporter name
313
+ getSocialUrl(null, "instagram", "johndoe");
314
+ // "https://instagram.com/johndoe"
315
+ ```
316
+
317
+ ### openInNewWindow
318
+
319
+ Opens a URL in a new tab safely.
320
+
321
+ ```ts
322
+ import { openInNewWindow } from "@hobenakicoffee/libraries/utils";
323
+
324
+ openInNewWindow("https://example.com");
325
+ // Opens in new tab with rel="noopener noreferrer"
326
+ ```
327
+
328
+ ### Social Sharing Functions
329
+
330
+ ```ts
331
+ import { shareToFacebook, shareToInstagram, shareToLinkedIn, shareToX } from "@hobenakicoffee/libraries/utils";
332
+
333
+ // Facebook
334
+ shareToFacebook({
335
+ url: "https://example.com",
336
+ quote: "Check this out!",
337
+ hashtag: "coffee",
338
+ ref: "campaign123"
339
+ });
340
+
341
+ // Instagram (uses Web Share API or copies to clipboard)
342
+ shareToInstagram({
343
+ url: "https://example.com",
344
+ text: "Check this out!"
345
+ });
346
+
347
+ // LinkedIn
348
+ shareToLinkedIn({
349
+ url: "https://example.com",
350
+ title: "My Title",
351
+ summary: "Description here",
352
+ source: "HobeNakiCoffee"
353
+ });
354
+
355
+ // X (Twitter)
356
+ shareToX({
357
+ text: "Hello from HobeNakiCoffee!",
358
+ url: "https://example.com",
359
+ hashtags: "coffee,support",
360
+ via: "hobenakicoffee"
361
+ });
362
+ ```
363
+
364
+ ### QR Code Utilities
365
+
366
+ ```ts
367
+ import { downloadQrSvgAsPng, printQrSvg } from "@hobenakicoffee/libraries/utils";
368
+
369
+ // Download QR as PNG
370
+ await downloadQrSvgAsPng(
371
+ '<svg>...</svg>',
372
+ "qr-code.png",
373
+ () => console.log("Success"),
374
+ () => console.log("Error")
375
+ );
376
+
377
+ // Print QR
378
+ printQrSvg(
379
+ '<svg>...</svg>',
380
+ "QR Code Print",
381
+ () => console.log("Error")
382
+ );
383
+ ```
384
+
385
+ ### toHumanReadable
386
+
387
+ Converts camelCase or snake_case strings to human-readable format.
388
+
389
+ ```ts
390
+ import { toHumanReadable } from "@hobenakicoffee/libraries/utils";
391
+
392
+ toHumanReadable("camelCase"); // "Camel Case"
393
+ toHumanReadable("snake_case"); // "Snake Case"
394
+ toHumanReadable("CONSTANT_VALUE"); // "CONSTANT VALUE"
395
+ toHumanReadable("HTTPResponseCode"); // "HTTP Response Code"
396
+ ```
397
+
398
+ ### validatePhoneNumber
399
+
400
+ Validates Bangladeshi mobile phone numbers.
401
+
402
+ ```ts
403
+ import { validatePhoneNumber } from "@hobenakicoffee/libraries/utils";
404
+
405
+ validatePhoneNumber("01712345678"); // true
406
+ validatePhoneNumber("+8801712345678"); // true
407
+ validatePhoneNumber("8801712345678"); // true
408
+ validatePhoneNumber("01512345678"); // false (invalid prefix)
409
+ validatePhoneNumber("1234567890"); // false
410
+ ```
411
+
412
+ ### checkModeration
413
+
414
+ Checks text for profanity using both local Bangla word lists and OpenAI moderation API.
415
+
416
+ ```ts
417
+ import { checkModeration } from "@hobenakicoffee/libraries/utils";
418
+ import OpenAI from "openai";
419
+
420
+ const openai = new OpenAI();
421
+
422
+ const result = await checkModeration(openai, "some text to check");
423
+
424
+ result.flagged // boolean - true if content is flagged
425
+ result.categories // OpenAI categories if flagged
426
+ result.source // "profanity" | "openai" | null
427
+ result.profaneWords // Array of matched profanity words (if from profanity check)
428
+ result.error // Error if any
429
+ ```
430
+
431
+ ---
432
+
433
+ ## Moderation (`@hobenakicoffee/libraries/moderation`)
434
+
435
+ ### moderateText
436
+
437
+ Local profanity detection for English and Bangla.
438
+
439
+ ```ts
440
+ import { moderateText } from "@hobenakicoffee/libraries/moderation";
441
+
442
+ const result = moderateText("some bad word here");
443
+
444
+ result.isAllowed // boolean
445
+ result.matched // Array of matched words
446
+ ```
447
+
448
+ ### normalizeLeetspeak
449
+
450
+ Converts leetspeak to normal text (e.g., "h4x0r" -> "haxor").
451
+
452
+ ```ts
453
+ import { normalizeLeetspeak } from "@hobenakicoffee/libraries/moderation";
454
+
455
+ normalizeLeetspeak("h4x0r"); // "haxor"
456
+ normalizeLeetspeak("p@ssw0rd"); // "password"
457
+ ```
458
+
459
+ ### normalizeUnicode
460
+
461
+ Normalizes Unicode characters (removes diacritics).
462
+
463
+ ```ts
464
+ import { normalizeUnicode } from "@hobenakicoffee/libraries/moderation";
465
+
466
+ normalizeUnicode("café"); // "cafe"
467
+ ```
468
+
469
+ ### banglaBadWords
470
+
471
+ Array of Bangla profanity words (710+ words) for content moderation.
472
+
473
+ ```ts
474
+ import { banglaBadWords } from "@hobenakicoffee/libraries/moderation";
475
+
476
+ console.log(banglaBadWords.length); // 710+
477
+ ```
478
+
479
+ ---
480
+
481
+ ## Types (`@hobenakicoffee/libraries/types`)
482
+
483
+ Full Supabase database types with Row, Insert, and Update types for each table.
484
+
485
+ ```ts
486
+ import type { Database, Tables, TablesInsert, TablesUpdate, Enums } from "@hobenakicoffee/libraries/types";
487
+
488
+ // Database type
489
+ type DB = Database;
490
+
491
+ // Table row types
492
+ type Profile = Tables<"profiles">;
493
+ type Transaction = Tables<"transactions">;
494
+ type Supporter = Tables<"supporters">;
495
+
496
+ // Insert types
497
+ type NewProfile = TablesInsert<"profiles">;
498
+ type NewTransaction = TablesInsert<"transactions">;
499
+
500
+ // Update types
501
+ type ProfileUpdate = TablesUpdate<"profiles">;
502
+
503
+ // Enum types
504
+ type PaymentStatus = Enums<"payment_status_enum">;
505
+ type SupporterPlatform = Enums<"supporter_platform_enum">;
506
+ ```
507
+
508
+ ### Database Tables
509
+
510
+ - `activities` - User activity tracking
511
+ - `coffee_gifts` - Coffee gift transactions
512
+ - `conversation_participants` - Chat participants
513
+ - `conversations` - Chat conversations
514
+ - `follows` - User follow relationships
515
+ - `manager_role_permissions` - Manager role permissions
516
+ - `manager_user_roles` - Manager user role assignments
517
+ - `managers` - Manager profiles
518
+ - `messages` - Chat messages
519
+ - `messages_*` - Monthly partitioned message tables
520
+ - `payout_methods` - User payout methods
521
+ - `profiles` - User profiles
522
+ - `supporters` - Supporter records
523
+ - `transactions` - Payment transactions
524
+ - `wallets` - User wallets
525
+ - `withdrawal_requests` - Withdrawal requests
526
+
527
+ ### Database Enums
528
+
529
+ - `manager_permission` - Manager permissions
530
+ - `manager_role` - Manager roles (super_admin, content_manager, etc.)
531
+ - `manager_status` - Manager account status
532
+ - `payment_status_enum` - Payment statuses
533
+ - `payout_provider` - Payout provider types
534
+ - `provider_enum` - Payment providers
535
+ - `reference_type_enum` - Transaction reference types
536
+ - `supporter_platform_enum` - Supporter platform types
537
+ - `transaction_direction_enum` - Debit/credit
538
+ - `user_role` - User roles
539
+ - `visibility_enum` - Public/private visibility
540
+ - `withdrawal_status` - Withdrawal request statuses
541
+
542
+ ---
543
+
544
+ ## UI Components
545
+
546
+ The library includes 30+ accessible UI components built on Radix UI.
547
+
548
+ ### Importing Components
549
+
550
+ ```ts
551
+ // Individual imports (recommended for tree-shaking)
552
+ import { Button } from "@hobenakicoffee/libraries/components/ui/button";
553
+ import { Card } from "@hobenakicoffee/libraries/components/ui/card";
554
+ import { Dialog } from "@hobenakicoffee/libraries/components/ui/dialog";
555
+ import { Input } from "@hobenakicoffee/libraries/components/ui/input";
556
+
557
+ // All components available:
558
+ import { Alert } from "@hobenakicoffee/libraries/components/ui/alert";
559
+ import { AlertDialog } from "@hobenakicoffee/libraries/components/ui/alert-dialog";
560
+ import { Avatar } from "@hobenakicoffee/libraries/components/ui/avatar";
561
+ import { Badge } from "@hobenakicoffee/libraries/components/ui/badge";
562
+ import { Breadcrumb } from "@hobenakicoffee/libraries/components/ui/breadcrumb";
563
+ import { Button, ButtonGroup } from "@hobenakicoffee/libraries/components/ui/button";
564
+ import { Calendar } from "@hobenakicoffee/libraries/components/ui/calendar";
565
+ import { Card, Chart } from "@hobenakicoffee/libraries/components/ui/card";
566
+ import { Checkbox } from "@hobenakicoffee/libraries/components/ui/checkbox";
567
+ import { Dialog } from "@hobenakicoffee/libraries/components/ui/dialog";
568
+ import { Drawer } from "@hobenakicoffee/libraries/components/ui/drawer";
569
+ import { DropdownMenu } from "@hobenakicoffee/libraries/components/ui/dropdown-menu";
570
+ import { Empty, EmptyMinimal } from "@hobenakicoffee/libraries/components/ui/empty";
571
+ import { Field, Input, InputGroup, InputOtp } from "@hobenakicoffee/libraries/components/ui/input";
572
+ import { Item } from "@hobenakicoffee/libraries/components/ui/item";
573
+ import { Label } from "@hobenakicoffee/libraries/components/ui/label";
574
+ import { Popover } from "@hobenakicoffee/libraries/components/ui/popover";
575
+ import { RadioGroup } from "@hobenakicoffee/libraries/components/ui/radio-group";
576
+ import { Select } from "@hobenakicoffee/libraries/components/ui/select";
577
+ import { Separator } from "@hobenakicoffee/libraries/components/ui/separator";
578
+ import { Sheet } from "@hobenakicoffee/libraries/components/ui/sheet";
579
+ import { Sidebar } from "@hobenakicoffee/libraries/components/ui/sidebar";
580
+ import { Skeleton } from "@hobenakicoffee/libraries/components/ui/skeleton";
581
+ import { Sonner } from "@hobenakicoffee/libraries/components/ui/sonner";
582
+ import { Spinner } from "@hobenakicoffee/libraries/components/ui/spinner";
583
+ import { Table } from "@hobenakicoffee/libraries/components/ui/table";
584
+ import { Tabs } from "@hobenakicoffee/libraries/components/ui/tabs";
585
+ import { Textarea } from "@hobenakicoffee/libraries/components/ui/textarea";
586
+ import { Toggle, ToggleGroup } from "@hobenakicoffee/libraries/components/ui/toggle";
587
+ import { Tooltip } from "@hobenakicoffee/libraries/components/ui/tooltip";
588
+ ```
589
+
590
+ ### Component Variants
591
+
592
+ Components use `cva` (class-variance-authority) for variants:
593
+
594
+ ```ts
595
+ import { Button } from "@hobenakicoffee/libraries/components/ui/button";
596
+ import { Badge } from "@hobenakicoffee/libraries/components/ui/badge";
597
+
598
+ // Button variants
599
+ <Button variant="default" />
600
+ <Button variant="destructive" />
601
+ <Button variant="outline" />
602
+ <Button variant="secondary" />
603
+ <Button variant="ghost" />
604
+ <Button variant="link" />
605
+
606
+ // Button sizes
607
+ <Button size="default" />
608
+ <Button size="sm" />
609
+ <Button size="lg" />
610
+ <Button size="icon" />
611
+
612
+ // Badge variants
613
+ <Badge variant="default" />
614
+ <Badge variant="secondary" />
615
+ <Badge variant="destructive" />
616
+ <Badge variant="outline" />
617
+ ```
618
+
619
+ ### Turnstile Captcha
620
+
621
+ ```ts
622
+ import { TurnstileCaptcha } from "@hobenakicoffee/libraries/components/turnstile-captcha";
623
+
624
+ <TurnstileCaptcha
625
+ siteKey="your-site-key"
626
+ onSuccess={(token) => console.log(token)}
627
+ onError={() => console.error("Error")}
628
+ theme="auto"
629
+ />
630
+ ```
631
+
632
+ ---
633
+
634
+ ## Theme Provider (`@hobenakicoffee/libraries/providers/theme-provider`)
635
+
636
+ Dark/light mode theming with system preference support.
637
+
638
+ ```tsx
639
+ import { ThemeProvider, useTheme } from "@hobenakicoffee/libraries/providers/theme-provider";
640
+
641
+ // Wrap your app
642
+ function App({ children }) {
643
+ return (
644
+ <ThemeProvider defaultTheme="system" storageKey="my-app-theme">
645
+ {children}
646
+ </ThemeProvider>
647
+ );
648
+ }
649
+
650
+ // Use in components
651
+ function MyComponent() {
652
+ const { theme, setTheme } = useTheme();
653
+
654
+ return (
655
+ <button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>
656
+ Toggle Theme
657
+ </button>
658
+ );
659
+ }
660
+ ```
661
+
662
+ Props:
663
+ - `children` - React nodes
664
+ - `defaultTheme` - "light" | "dark" | "system" (default: "system")
665
+ - `storageKey` - localStorage key (default: "hobenakicoffee-app-ui-themes")
666
+
667
+ ---
668
+
669
+ ## Utils (`@hobenakicoffee/libraries/lib/utils`)
670
+
671
+ ### cn
672
+
673
+ Class name merging utility combining `clsx` and `tailwind-merge`.
674
+
675
+ ```ts
676
+ import { cn } from "@hobenakicoffee/libraries/lib/utils";
677
+
678
+ cn("px-2 py-1", "bg-red-500", condition && "text-white");
679
+ // Returns merged class string
680
+ ```
681
+
682
+ ---
683
+
684
+ ## API Reference
685
+
686
+ ### Constants and Types
687
+
688
+ | Export | Type | Description |
689
+ |--------|------|-------------|
690
+ | `Visibility` | `object` | PUBLIC, PRIVATE constants |
691
+ | `Visibility` | `type` | Type for visibility values |
692
+ | `productInfo` | `object` | Product metadata |
693
+ | `companyInfo` | `object` | Company information |
694
+ | `PaymentTypes` | `object` | Payment type constants |
695
+ | `PaymentType` | `type` | Type for payment types |
696
+ | `PaymentStatuses` | `object` | Payment status constants |
697
+ | `PaymentStatus` | `type` | Type for payment statuses |
698
+ | `PaymentProviders` | `object` | Payment provider constants |
699
+ | `PaymentProvider` | `type` | Type for payment providers |
700
+ | `PaymentDirections` | `object` | Payment direction constants |
701
+ | `PaymentDirection` | `type` | Type for payment directions |
702
+ | `PayoutProviders` | `object` | Payout provider constants |
703
+ | `PayoutProvider` | `type` | Type for payout providers |
704
+ | `WithdrawalStatuses` | `object` | Withdrawal status constants |
705
+ | `WithdrawalStatus` | `type` | Type for withdrawal statuses |
706
+ | `SupporterPlatforms` | `object` | Social platform constants |
707
+ | `SupporterPlatform` | `type` | Type for supporter platforms |
708
+ | `ServiceTypes` | `object` | Service type constants |
709
+ | `ServiceType` | `type` | Type for service types |
710
+
711
+ ### Utilities
712
+
713
+ | Function | Description |
714
+ |----------|-------------|
715
+ | `formatAmount` | Format number as ৳ currency |
716
+ | `formatSignedAmount` | Format with + or - sign |
717
+ | `formatDate` | Format date string |
718
+ | `formatNumber` | Format with thousand separators |
719
+ | `formatToPlainText` | Convert value to plain text |
720
+ | `formatMetadataKey` | Format metadata key to readable text |
721
+ | `getUserPageLink` | Generate user profile URL |
722
+ | `getInitials` | Get name initials |
723
+ | `getSocialLink` | Generate social profile URL |
724
+ | `getSocialUrl` | Generate social sharing URL |
725
+ | `openInNewWindow` | Open URL in new tab |
726
+ | `shareToFacebook` | Share to Facebook |
727
+ | `shareToInstagram` | Share to Instagram |
728
+ | `shareToLinkedIn` | Share to LinkedIn |
729
+ | `shareToX` | Share to X (Twitter) |
730
+ | `downloadQrSvgAsPng` | Download QR as PNG |
731
+ | `printQrSvg` | Print QR code |
732
+ | `toHumanReadable` | Convert camelCase/snake_case to readable |
733
+ | `validatePhoneNumber` | Validate Bangladeshi phone |
734
+ | `checkModeration` | Check text for profanity |
735
+
736
+ ### Moderation
737
+
738
+ | Function | Description |
739
+ |----------|-------------|
740
+ | `moderateText` | Check text for profanity |
741
+ | `checkBanglaWords` | Check for Bangla bad words |
742
+ | `normalizeLeetspeak` | Convert leetspeak to normal |
743
+ | `normalizeUnicode` | Remove Unicode diacritics |
744
+ | `banglaBadWords` | Bangla profanity word list |
745
+
746
+ ---
747
+
748
+ ## Local Development
55
749
 
56
750
  Install dependencies:
57
751
 
@@ -80,59 +774,141 @@ bun run typecheck
80
774
  # Alias for typecheck
81
775
  bun run lint
82
776
 
777
+ # Format code
778
+ bun run format
779
+
780
+ # Check formatting
781
+ bun run format:check
782
+
83
783
  # Clean build artifacts
84
784
  bun run clean
85
785
  ```
86
786
 
87
- ## Project structure
787
+ ---
788
+
789
+ ## Project Structure
88
790
 
89
- ```text
791
+ ```
90
792
  src/
91
- index.ts
92
- constants/
93
- common.ts
94
- legal.ts
95
- payment.ts
96
- platforms.ts
97
- services.ts
98
- index.ts
99
- utils/
100
- check-moderation.ts
101
- format-amount.ts
102
- format-date.ts
103
- format-number.ts
104
- format-plain-text.ts
105
- get-social-handle.ts
106
- get-social-link.ts
107
- get-user-name-initials.ts
108
- get-user-page-link.ts
109
- open-to-new-window.ts
110
- post-to-facebook.ts
111
- post-to-instagram.ts
112
- post-to-linkedin.ts
113
- post-to-x.ts
114
- qr-svg-utils.ts
115
- to-human-readable.ts
116
- validate-phone-number.ts
117
- index.ts
118
- moderation/
119
- normalizer.ts
120
- profanity-service.ts
121
- index.ts
122
- types/
123
- supabase.ts
124
- index.ts
125
- lib/
126
- utils.ts
127
- providers/
128
- theme-provider.tsx
129
- components/
130
- ui/
131
- ... (Radix UI based components)
132
- turnstile-captcha.tsx
133
- ```
134
-
135
- ## Release & publish
793
+ ├── index.ts # Main entry
794
+ ├── constants/
795
+ │ ├── common.ts # Visibility
796
+ │ ├── legal.ts # productInfo, companyInfo
797
+ │ ├── payment.ts # Payment constants
798
+ │ ├── platforms.ts # SupporterPlatforms
799
+ │ ├── services.ts # ServiceTypes
800
+ │ └── index.ts # Exports
801
+ ├── utils/
802
+ │ ├── check-moderation.ts
803
+ │ ├── format-amount.ts
804
+ │ ├── format-date.ts
805
+ │ ├── format-number.ts
806
+ │ ├── format-plain-text.ts
807
+ │ ├── get-social-handle.ts
808
+ │ ├── get-social-link.ts
809
+ │ ├── get-user-name-initials.ts
810
+ │ ├── get-user-page-link.ts
811
+ │ ├── open-to-new-window.ts
812
+ │ ├── post-to-facebook.ts
813
+ │ ├── post-to-instagram.ts
814
+ │ ├── post-to-linkedin.ts
815
+ │ ├── post-to-x.ts
816
+ │ ├── qr-svg-utils.ts
817
+ │ ├── to-human-readable.ts
818
+ │ ├── validate-phone-number.ts
819
+ │ └── index.ts # Exports
820
+ ├── moderation/
821
+ │ ├── datasets/
822
+ │ │ ├── bn.ts # Bangla bad words (710+)
823
+ │ │ └── index.ts
824
+ │ ├── normalizer.ts
825
+ │ ├── profanity-service.ts
826
+ │ └── index.ts # Exports
827
+ ├── types/
828
+ │ ├── supabase.ts # Full Supabase types
829
+ │ └── index.ts
830
+ ├── lib/
831
+ │ └── utils.ts # cn() utility
832
+ ├── providers/
833
+ │ └── theme-provider.tsx # Theme provider
834
+ └── components/
835
+ ├── turnstile-captcha.tsx
836
+ └── ui/ # 30+ UI components
837
+ ├── alert.tsx
838
+ ├── alert-dialog.tsx
839
+ ├── avatar.tsx
840
+ ├── badge.tsx
841
+ ├── breadcrumb.tsx
842
+ ├── button.tsx
843
+ ├── button-group.tsx
844
+ ├── calendar.tsx
845
+ ├── card.tsx
846
+ ├── chart.tsx
847
+ ├── checkbox.tsx
848
+ ├── dialog.tsx
849
+ ├── drawer.tsx
850
+ ├── dropdown-menu.tsx
851
+ ├── empty.tsx
852
+ ├── empty-minimal.tsx
853
+ ├── field.tsx
854
+ ├── input.tsx
855
+ ├── input-group.tsx
856
+ ├── input-otp.tsx
857
+ ├── item.tsx
858
+ ├── label.tsx
859
+ ├── popover.tsx
860
+ ├── radio-group.tsx
861
+ ├── select.tsx
862
+ ├── separator.tsx
863
+ ├── sheet.tsx
864
+ ├── sidebar.tsx
865
+ ├── skeleton.tsx
866
+ ├── sonner.tsx
867
+ ├── spinner.tsx
868
+ ├── table.tsx
869
+ ├── tabs.tsx
870
+ ├── textarea.tsx
871
+ ├── toggle.tsx
872
+ ├── toggle-group.tsx
873
+ └── tooltip.tsx
874
+ ```
875
+
876
+ ---
877
+
878
+ ## Dependencies
879
+
880
+ ### Runtime
881
+
882
+ - `@fontsource-variable/noto-sans-bengali` - Bengali font
883
+ - `@hugeicons/core-free-icons` - Hugeicons
884
+ - `@hugeicons/react` - React icons
885
+ - `@marsidev/react-turnstile` - Turnstile captcha
886
+ - `@tailwindcss/vite` - Tailwind CSS
887
+ - `class-variance-authority` - Component variants
888
+ - `glin-profanity` - Profanity detection
889
+ - `input-otp` - OTP input
890
+ - `next-themes` - Theme provider
891
+ - `openai` - OpenAI API
892
+ - `radix-ui` - UI primitives
893
+ - `react` / `react-dom` - React
894
+ - `react-day-picker` - Calendar
895
+ - `recharts` - Charts
896
+ - `shadcn` - UI components
897
+ - `sonner` - Toast notifications
898
+ - `tailwind-merge` - Tailwind merge
899
+ - `tailwindcss` - Styling
900
+ - `tw-animate-css` - Animations
901
+ - `vaul` - Drawer
902
+
903
+ ### Dev
904
+
905
+ - `@biomejs/biome` - Linting/formatting
906
+ - `ultracite` - Ultracite CLI
907
+ - `vite` - Build tool
908
+
909
+ ---
910
+
911
+ ## Release & Publish
136
912
 
137
913
  Publishing is automated on push to the `main` branch via GitHub Actions. Ensure:
138
914
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hobenakicoffee/libraries",
3
- "version": "1.17.1",
3
+ "version": "1.18.0",
4
4
  "type": "module",
5
5
  "types": "src/index.ts",
6
6
  "exports": {
@@ -784,6 +784,44 @@ export type Database = {
784
784
  },
785
785
  ];
786
786
  };
787
+ user_services: {
788
+ Row: {
789
+ config: Json | null;
790
+ created_at: string | null;
791
+ id: string;
792
+ is_enabled: boolean | null;
793
+ profile_id: string;
794
+ service: string;
795
+ updated_at: string | null;
796
+ };
797
+ Insert: {
798
+ config?: Json | null;
799
+ created_at?: string | null;
800
+ id?: string;
801
+ is_enabled?: boolean | null;
802
+ profile_id: string;
803
+ service: string;
804
+ updated_at?: string | null;
805
+ };
806
+ Update: {
807
+ config?: Json | null;
808
+ created_at?: string | null;
809
+ id?: string;
810
+ is_enabled?: boolean | null;
811
+ profile_id?: string;
812
+ service?: string;
813
+ updated_at?: string | null;
814
+ };
815
+ Relationships: [
816
+ {
817
+ foreignKeyName: "user_services_profile_id_fkey";
818
+ columns: ["profile_id"];
819
+ isOneToOne: false;
820
+ referencedRelation: "profiles";
821
+ referencedColumns: ["id"];
822
+ },
823
+ ];
824
+ };
787
825
  wallets: {
788
826
  Row: {
789
827
  balance: number;