tiktok-comments 0.1.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 ADDED
@@ -0,0 +1,91 @@
1
+ # tiktok-comments
2
+
3
+ TikTok-style comment section UI packaged as a React library with isolated Tailwind CSS (`tcm:` prefix) for safe use in host apps.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install tiktok-comments
9
+ ```
10
+
11
+ ## Usage (React SPA)
12
+
13
+ ```tsx
14
+ import { useState, useCallback } from "react";
15
+ import { CommentSection } from "tiktok-comments";
16
+ import type { Attachment, Comment } from "tiktok-comments";
17
+ import "tiktok-comments/styles.css";
18
+
19
+ export function VideoComments() {
20
+ const [comments, setComments] = useState<Comment[]>([]);
21
+
22
+ const handleSubmit = useCallback((text: string, attachment?: Attachment, replyTo?: string) => {
23
+ // persist to your API, then update state
24
+ }, []);
25
+
26
+ return (
27
+ <CommentSection
28
+ comments={comments}
29
+ currentUser={{ name: "You", avatar: "/avatar.png" }}
30
+ onSubmit={handleSubmit}
31
+ onLike={(id) => { /* ... */ }}
32
+ onLikeReply={(commentId, replyId) => { /* ... */ }}
33
+ theme="dark"
34
+ />
35
+ );
36
+ }
37
+ ```
38
+
39
+ ## Usage (Next.js App Router)
40
+
41
+ Import the CSS once in your root layout:
42
+
43
+ ```tsx
44
+ import "tiktok-comments/styles.css";
45
+ ```
46
+
47
+ Use the component in a client page or client component:
48
+
49
+ ```tsx
50
+ "use client";
51
+
52
+ import { CommentSection } from "tiktok-comments";
53
+
54
+ export default function CommentsPage() {
55
+ return <CommentSection comments={[]} onSubmit={() => {}} onLike={() => {}} onLikeReply={() => {}} />;
56
+ }
57
+ ```
58
+
59
+ ## API
60
+
61
+ `CommentSection` is a controlled component. You own comment state and wire it to your backend.
62
+
63
+ | Prop | Type | Description |
64
+ |------|------|-------------|
65
+ | `comments` | `Comment[]` | Comment list to render |
66
+ | `currentUser` | `{ name, avatar }` | Shown in the input bar |
67
+ | `onSubmit` | `(text, attachment?, replyTo?) => void` | New comment submitted |
68
+ | `onLike` | `(commentId) => void` | Top-level comment liked |
69
+ | `onLikeReply` | `(commentId, replyId) => void` | Reply liked |
70
+ | `onReply` | `(commentId, username) => void` | Optional reply intent callback |
71
+ | `theme` | `"dark" \| "light"` | Default `"dark"` |
72
+ | `className` | `string` | Extra classes on root |
73
+
74
+ Exported types: `Comment`, `Reply`, `Attachment`, `CommentUser`, `EarnedBadge`, `SubscriptionTier`.
75
+
76
+ ## CSS isolation
77
+
78
+ All Tailwind utilities use the `tcm:` prefix (e.g. `tcm:flex`, `tcm:hover:tcm:bg-muted`). Theme tokens are scoped under `.tcm-root`, so host app CSS variables are not overwritten.
79
+
80
+ ## Development
81
+
82
+ ```bash
83
+ npm install
84
+ npm run dev # demo playground
85
+ npm run check # typecheck + lint
86
+ npm run build # library + CSS to dist/
87
+ ```
88
+
89
+ ## License
90
+
91
+ MIT
@@ -0,0 +1,7 @@
1
+ import { EarnedBadge } from './comment-data';
2
+ interface BadgeDrawerProps {
3
+ badge: EarnedBadge;
4
+ onClose: () => void;
5
+ }
6
+ export declare function BadgeDrawer({ badge, onClose }: BadgeDrawerProps): import("react").JSX.Element;
7
+ export {};
@@ -0,0 +1,6 @@
1
+ import { LucideProps } from 'lucide-react';
2
+ interface BadgeIconProps extends LucideProps {
3
+ name: string;
4
+ }
5
+ export declare function BadgeIcon({ name, ...props }: BadgeIconProps): import("react").JSX.Element | null;
6
+ export {};
@@ -0,0 +1,43 @@
1
+ export type SubscriptionTier = "pro" | "max";
2
+ export interface CommentUser {
3
+ name: string;
4
+ avatar: string;
5
+ }
6
+ export interface EarnedBadge {
7
+ id: string;
8
+ lucideIcon: string;
9
+ color: string;
10
+ name: string;
11
+ description: string;
12
+ rarity: "common" | "rare" | "epic" | "legendary";
13
+ }
14
+ export declare const BADGE_CATALOG: EarnedBadge[];
15
+ export interface Reply {
16
+ id: string;
17
+ name: string;
18
+ avatar: string;
19
+ text: string;
20
+ likes: number;
21
+ liked: boolean;
22
+ timestamp: string;
23
+ replyingTo?: string;
24
+ image?: string;
25
+ sticker?: string;
26
+ subscription?: SubscriptionTier;
27
+ }
28
+ export interface Comment {
29
+ id: string;
30
+ name: string;
31
+ avatar: string;
32
+ text: string;
33
+ likes: number;
34
+ liked: boolean;
35
+ timestamp: string;
36
+ pinned?: boolean;
37
+ replies: Reply[];
38
+ image?: string;
39
+ sticker?: string;
40
+ subscription?: SubscriptionTier;
41
+ badges?: string[];
42
+ }
43
+ export declare function formatLikes(count: number): string;
@@ -0,0 +1,13 @@
1
+ import { CommentUser } from './comment-data';
2
+ export interface Attachment {
3
+ type: "image" | "sticker";
4
+ url: string;
5
+ }
6
+ interface CommentInputBarProps {
7
+ replyingTo: string | null;
8
+ onCancelReply: () => void;
9
+ onSubmit: (text: string, attachment?: Attachment) => void;
10
+ currentUser?: CommentUser;
11
+ }
12
+ export declare function CommentInputBar({ replyingTo, onCancelReply, onSubmit, currentUser }: CommentInputBarProps): import("react").JSX.Element;
13
+ export {};
@@ -0,0 +1,9 @@
1
+ import { Comment } from './comment-data';
2
+ interface CommentItemProps {
3
+ comment: Comment;
4
+ onLike: (id: string) => void;
5
+ onLikeReply: (commentId: string, replyId: string) => void;
6
+ onReply: (name: string) => void;
7
+ }
8
+ export declare function CommentItem({ comment, onLike, onLikeReply, onReply }: CommentItemProps): import("react").JSX.Element;
9
+ export {};
@@ -0,0 +1,13 @@
1
+ import { Comment, CommentUser } from './comment-data';
2
+ import { Attachment } from './comment-input-bar';
3
+ export interface CommentSectionProps {
4
+ comments: Comment[];
5
+ currentUser?: CommentUser;
6
+ onSubmit: (text: string, attachment?: Attachment, replyTo?: string) => void;
7
+ onLike: (commentId: string) => void;
8
+ onLikeReply: (commentId: string, replyId: string) => void;
9
+ onReply?: (commentId: string, username: string) => void;
10
+ className?: string;
11
+ theme?: "dark" | "light";
12
+ }
13
+ export declare function CommentSection({ comments, currentUser, onSubmit, onLike, onLikeReply, onReply, className, theme, }: CommentSectionProps): import("react").JSX.Element;
@@ -0,0 +1,7 @@
1
+ interface LightboxProps {
2
+ src: string;
3
+ alt?: string;
4
+ onClose: () => void;
5
+ }
6
+ export declare function Lightbox({ src, alt, onClose }: LightboxProps): import("react").JSX.Element;
7
+ export {};
@@ -0,0 +1,6 @@
1
+ interface MentionSelectorProps {
2
+ onSelect: (username: string) => void;
3
+ onClose: () => void;
4
+ }
5
+ export declare function MentionSelector({ onSelect, onClose }: MentionSelectorProps): import("react").JSX.Element;
6
+ export {};
@@ -0,0 +1,10 @@
1
+ import { SubscriptionTier } from './comment-data';
2
+ interface ProfileDrawerProps {
3
+ name: string;
4
+ avatar: string;
5
+ subscription?: SubscriptionTier;
6
+ badges?: string[];
7
+ onClose: () => void;
8
+ }
9
+ export declare function ProfileDrawer({ name, avatar, subscription, badges, onClose }: ProfileDrawerProps): import("react").JSX.Element;
10
+ export {};
@@ -0,0 +1,8 @@
1
+ import { Reply } from './comment-data';
2
+ interface ReplyListProps {
3
+ replies: Reply[];
4
+ onLikeReply: (replyId: string) => void;
5
+ onReply: (username: string) => void;
6
+ }
7
+ export declare function ReplyList({ replies, onLikeReply, onReply }: ReplyListProps): import("react").JSX.Element | null;
8
+ export {};
@@ -0,0 +1,6 @@
1
+ interface StickerDrawerProps {
2
+ src: string;
3
+ onClose: () => void;
4
+ }
5
+ export declare function StickerDrawer({ src, onClose }: StickerDrawerProps): import("react").JSX.Element;
6
+ export {};
@@ -0,0 +1,6 @@
1
+ interface StickerSelectorProps {
2
+ onSelect: (stickerUrl: string) => void;
3
+ onClose: () => void;
4
+ }
5
+ export declare function StickerSelector({ onSelect, onClose }: StickerSelectorProps): import("react").JSX.Element;
6
+ export {};