@xhub-short/ui 0.1.0-beta.1 → 0.1.0-beta.10

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.
Files changed (45) hide show
  1. package/dist/CommentSheet.css-BeCrEaUG.d.ts +221 -0
  2. package/dist/{chunk-2PTMP65P.js → chunk-2FSDVYER.js} +8 -9
  3. package/dist/{chunk-WKX2WBVO.js → chunk-3XPJHUYL.js} +1 -39
  4. package/dist/{chunk-ANGBSV7L.js → chunk-AC2IFAJR.js} +10 -5
  5. package/dist/{chunk-4YDIRPIN.js → chunk-ANCP53F3.js} +3 -3
  6. package/dist/chunk-AQHD6LPS.js +430 -0
  7. package/dist/{chunk-HW4LXTFT.js → chunk-CL6BS7GB.js} +7 -5
  8. package/dist/{chunk-YW23IBKF.js → chunk-ECR42RKK.js} +46 -5
  9. package/dist/chunk-EDWS2IPH.js +1 -0
  10. package/dist/chunk-FNXTPQ6L.js +2573 -0
  11. package/dist/{chunk-DHQJBXQW.js → chunk-KWHMZ6H5.js} +1 -1
  12. package/dist/{chunk-UXMA4KJZ.js → chunk-RMLTPW5S.js} +3 -2
  13. package/dist/{chunk-SSJDO24Q.js → chunk-SZXFH334.js} +1 -1
  14. package/dist/{chunk-4MN72OZH.js → chunk-UNV3NWN6.js} +4 -4
  15. package/dist/{chunk-ZZDQKP4R.js → chunk-WCRDTBCZ.js} +94 -155
  16. package/dist/{chunk-XAOEHLOX.js → chunk-XDIH66C4.js} +245 -52
  17. package/dist/components/ActionBar/index.js +1 -1
  18. package/dist/components/AuthorInfo/index.d.ts +5 -1
  19. package/dist/components/AuthorInfo/index.js +1 -1
  20. package/dist/components/BlurhashPlaceholder/index.d.ts +67 -0
  21. package/dist/components/BlurhashPlaceholder/index.js +150 -0
  22. package/dist/components/CommentSheet/index.d.ts +164 -0
  23. package/dist/components/CommentSheet/index.js +1 -0
  24. package/dist/components/ErrorBoundary/index.js +1 -1
  25. package/dist/components/OfflineIndicator/index.d.ts +56 -0
  26. package/dist/components/OfflineIndicator/index.js +151 -0
  27. package/dist/components/ProgressBar/index.d.ts +30 -2
  28. package/dist/components/ProgressBar/index.js +1 -1
  29. package/dist/components/Skeleton/index.js +1 -1
  30. package/dist/components/SubtitleDisplay/index.d.ts +94 -0
  31. package/dist/components/SubtitleDisplay/index.js +165 -0
  32. package/dist/components/VideoFeed/index.d.ts +11 -0
  33. package/dist/components/VideoFeed/index.js +1 -1
  34. package/dist/components/VideoInfo/index.js +1 -1
  35. package/dist/components/VideoPlayer/index.d.ts +14 -41
  36. package/dist/components/VideoPlayer/index.js +1 -1
  37. package/dist/components/VideoSlot/index.d.ts +124 -64
  38. package/dist/components/VideoSlot/index.js +1 -1
  39. package/dist/components/VirtualSlider/index.d.ts +339 -0
  40. package/dist/components/VirtualSlider/index.js +1 -0
  41. package/dist/components/icons/index.js +1 -1
  42. package/dist/index.d.ts +76 -93
  43. package/dist/index.js +75 -27
  44. package/package.json +53 -8
  45. package/dist/use-gesture-react.esm-3SV4QLEJ.js +0 -1893
@@ -0,0 +1,2573 @@
1
+ import { clsx } from 'clsx';
2
+ import { createContext, memo, useState, useRef, useEffect, useCallback, useMemo, useContext } from 'react';
3
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
+
5
+ // src/components/CommentSheet/CommentSheetHeadless.tsx
6
+ var CommentSheetContext = createContext(void 0);
7
+ function useCommentSheetContext() {
8
+ const context = useContext(CommentSheetContext);
9
+ if (!context) {
10
+ throw new Error("useCommentSheetContext must be used within <CommentSheetHeadless>");
11
+ }
12
+ return context;
13
+ }
14
+ function useOptionalCommentSheetContext() {
15
+ return useContext(CommentSheetContext);
16
+ }
17
+ function ImageIcon({ className }) {
18
+ return /* @__PURE__ */ jsxs("svg", { "aria-hidden": "true", className, viewBox: "0 0 20 20", fill: "none", children: [
19
+ /* @__PURE__ */ jsx(
20
+ "rect",
21
+ {
22
+ x: "2",
23
+ y: "4",
24
+ width: "16",
25
+ height: "12",
26
+ rx: "2",
27
+ stroke: "#164d8e",
28
+ strokeWidth: "1.5",
29
+ fill: "none"
30
+ }
31
+ ),
32
+ /* @__PURE__ */ jsx(
33
+ "path",
34
+ {
35
+ d: "M2 13l4-4 3 3 5-5 4 4",
36
+ stroke: "#164d8e",
37
+ strokeWidth: "1.5",
38
+ strokeLinecap: "round",
39
+ strokeLinejoin: "round",
40
+ fill: "none"
41
+ }
42
+ ),
43
+ /* @__PURE__ */ jsx("circle", { cx: "14", cy: "8", r: "1.5", fill: "#9fc6e9" })
44
+ ] });
45
+ }
46
+ function EmojiIcon({ className }) {
47
+ return /* @__PURE__ */ jsxs(
48
+ "svg",
49
+ {
50
+ "aria-hidden": "true",
51
+ className,
52
+ viewBox: "0 0 24 24",
53
+ fill: "none",
54
+ stroke: "currentColor",
55
+ strokeWidth: "1.5",
56
+ children: [
57
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
58
+ /* @__PURE__ */ jsx("path", { d: "M8 14s1.5 2 4 2 4-2 4-2", strokeLinecap: "round" }),
59
+ /* @__PURE__ */ jsx("line", { x1: "9", y1: "9", x2: "9.01", y2: "9", strokeWidth: "2", strokeLinecap: "round" }),
60
+ /* @__PURE__ */ jsx("line", { x1: "15", y1: "9", x2: "15.01", y2: "9", strokeWidth: "2", strokeLinecap: "round" })
61
+ ]
62
+ }
63
+ );
64
+ }
65
+ function CloseIcon({ className }) {
66
+ return /* @__PURE__ */ jsxs(
67
+ "svg",
68
+ {
69
+ className,
70
+ viewBox: "0 0 24 24",
71
+ fill: "none",
72
+ stroke: "currentColor",
73
+ strokeWidth: "2",
74
+ "aria-hidden": "true",
75
+ focusable: "false",
76
+ children: [
77
+ /* @__PURE__ */ jsx("title", { children: "Close" }),
78
+ /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
79
+ /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
80
+ ]
81
+ }
82
+ );
83
+ }
84
+ var DEFAULT_EMOJIS = ["\u{1F600}", "\u{1F602}", "\u{1F60D}", "\u{1F525}", "\u{1F44D}", "\u{1F4AF}", "\u2764\uFE0F", "\u{1F622}"];
85
+ var CommentInput = memo(function CommentInput2({
86
+ placeholder = "Add a comment...",
87
+ emojis = DEFAULT_EMOJIS,
88
+ maxLength = 500,
89
+ className,
90
+ onSubmitSuccess,
91
+ onMediaClick,
92
+ replyingToText = "Replying to",
93
+ replyPlaceholderTemplate = "Reply to @{name}...",
94
+ cancelReplyAriaLabel = "Cancel reply",
95
+ addMediaAriaLabel = "Add media",
96
+ submitAriaLabel = "Submit comment",
97
+ emojiAriaLabel = "Open emoji",
98
+ addEmojiAriaLabel = "Add {emoji}"
99
+ }) {
100
+ const { actions, state, replyTarget, setReplyTarget } = useCommentSheetContext();
101
+ const [text, setText] = useState("");
102
+ const [showEmojis, setShowEmojis] = useState(false);
103
+ const inputRef = useRef(null);
104
+ useEffect(() => {
105
+ if (replyTarget && inputRef.current) {
106
+ inputRef.current.focus();
107
+ }
108
+ }, [replyTarget]);
109
+ const handleTextChange = useCallback(
110
+ (e) => {
111
+ const value = e.target.value;
112
+ if (value.length <= maxLength) {
113
+ setText(value);
114
+ }
115
+ },
116
+ [maxLength]
117
+ );
118
+ const handleSubmit = useCallback(async () => {
119
+ const trimmed = text.trim();
120
+ if (!trimmed || state.isPosting) return;
121
+ try {
122
+ if (replyTarget) {
123
+ await actions.postReply(replyTarget.commentId, trimmed, {
124
+ id: replyTarget.authorId,
125
+ name: replyTarget.authorName
126
+ });
127
+ setReplyTarget(null);
128
+ } else {
129
+ await actions.postComment(trimmed);
130
+ }
131
+ setText("");
132
+ setShowEmojis(false);
133
+ onSubmitSuccess?.();
134
+ } catch {
135
+ }
136
+ }, [text, state.isPosting, replyTarget, actions, setReplyTarget, onSubmitSuccess]);
137
+ const handleKeyDown = useCallback(
138
+ (e) => {
139
+ if (e.key === "Enter") {
140
+ e.preventDefault();
141
+ handleSubmit();
142
+ }
143
+ },
144
+ [handleSubmit]
145
+ );
146
+ const handleEmojiClick = useCallback((emoji) => {
147
+ setText((prev) => prev + emoji);
148
+ inputRef.current?.focus();
149
+ }, []);
150
+ const handleClearReply = useCallback(() => {
151
+ setReplyTarget(null);
152
+ inputRef.current?.focus();
153
+ }, [setReplyTarget]);
154
+ const toggleEmojis = useCallback(() => {
155
+ setShowEmojis((prev) => !prev);
156
+ }, []);
157
+ const canSubmit = text.trim().length > 0 && !state.isPosting;
158
+ return /* @__PURE__ */ jsxs("div", { className: clsx("sv-comment-sheet__input-area", className), children: [
159
+ replyTarget && /* @__PURE__ */ jsxs("div", { className: "sv-comment-sheet__reply-to", children: [
160
+ /* @__PURE__ */ jsxs("span", { children: [
161
+ replyingToText,
162
+ " \u2022 ",
163
+ /* @__PURE__ */ jsx("span", { className: "sv-comment-sheet__reply-to-author-name", children: replyTarget.authorName })
164
+ ] }),
165
+ /* @__PURE__ */ jsx(
166
+ "button",
167
+ {
168
+ type: "button",
169
+ className: "sv-comment-sheet__reply-to-clear",
170
+ onClick: handleClearReply,
171
+ "aria-label": cancelReplyAriaLabel,
172
+ children: /* @__PURE__ */ jsx(CloseIcon, { className: "sv-comment-item__action-icon" })
173
+ }
174
+ )
175
+ ] }),
176
+ /* @__PURE__ */ jsx(
177
+ "div",
178
+ {
179
+ className: clsx(
180
+ "sv-comment-sheet__emoji-bar",
181
+ showEmojis && "sv-comment-sheet__emoji-bar--visible"
182
+ ),
183
+ children: emojis.map((emoji) => /* @__PURE__ */ jsx(
184
+ "button",
185
+ {
186
+ type: "button",
187
+ className: "sv-comment-sheet__emoji-bar-btn",
188
+ onClick: () => handleEmojiClick(emoji),
189
+ "aria-label": addEmojiAriaLabel.replace("{emoji}", emoji),
190
+ children: emoji
191
+ },
192
+ emoji
193
+ ))
194
+ }
195
+ ),
196
+ /* @__PURE__ */ jsxs("div", { className: "sv-comment-sheet__input-wrapper", children: [
197
+ /* @__PURE__ */ jsxs("div", { className: "sv-comment-sheet__input-left", children: [
198
+ /* @__PURE__ */ jsx(
199
+ "button",
200
+ {
201
+ type: "button",
202
+ className: "sv-comment-sheet__media-btn",
203
+ onClick: onMediaClick,
204
+ "aria-label": addMediaAriaLabel,
205
+ children: /* @__PURE__ */ jsx(ImageIcon, {})
206
+ }
207
+ ),
208
+ /* @__PURE__ */ jsx(
209
+ "input",
210
+ {
211
+ ref: inputRef,
212
+ type: "text",
213
+ className: "sv-comment-sheet__input",
214
+ value: text,
215
+ onChange: handleTextChange,
216
+ onKeyDown: handleKeyDown,
217
+ placeholder: replyTarget ? replyPlaceholderTemplate.replace("{name}", replyTarget.authorName) : placeholder,
218
+ disabled: state.isPosting,
219
+ maxLength
220
+ }
221
+ )
222
+ ] }),
223
+ canSubmit ? /* @__PURE__ */ jsx(
224
+ "button",
225
+ {
226
+ type: "button",
227
+ className: "sv-comment-sheet__emoji-btn",
228
+ onClick: handleSubmit,
229
+ "aria-label": submitAriaLabel,
230
+ children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ jsx("path", { d: "M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" }) })
231
+ }
232
+ ) : /* @__PURE__ */ jsx(
233
+ "button",
234
+ {
235
+ type: "button",
236
+ className: "sv-comment-sheet__emoji-btn",
237
+ onClick: toggleEmojis,
238
+ "aria-label": emojiAriaLabel,
239
+ children: /* @__PURE__ */ jsx(EmojiIcon, {})
240
+ }
241
+ )
242
+ ] })
243
+ ] });
244
+ });
245
+ CommentInput.displayName = "CommentInput";
246
+ function MoreIcon({ className }) {
247
+ return /* @__PURE__ */ jsxs("svg", { "aria-hidden": "true", className, viewBox: "0 0 24 24", fill: "currentColor", children: [
248
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "1.5" }),
249
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "6", r: "1.5" }),
250
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "18", r: "1.5" })
251
+ ] });
252
+ }
253
+ function TrashIcon({ className }) {
254
+ return /* @__PURE__ */ jsx(
255
+ "svg",
256
+ {
257
+ "aria-hidden": "true",
258
+ className,
259
+ viewBox: "0 0 24 24",
260
+ fill: "none",
261
+ stroke: "currentColor",
262
+ strokeWidth: "1.5",
263
+ children: /* @__PURE__ */ jsx(
264
+ "path",
265
+ {
266
+ strokeLinecap: "round",
267
+ strokeLinejoin: "round",
268
+ d: "M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"
269
+ }
270
+ )
271
+ }
272
+ );
273
+ }
274
+ function EditIcon({ className }) {
275
+ return /* @__PURE__ */ jsx(
276
+ "svg",
277
+ {
278
+ "aria-hidden": "true",
279
+ className,
280
+ viewBox: "0 0 24 24",
281
+ fill: "none",
282
+ stroke: "currentColor",
283
+ strokeWidth: "1.5",
284
+ children: /* @__PURE__ */ jsx(
285
+ "path",
286
+ {
287
+ strokeLinecap: "round",
288
+ strokeLinejoin: "round",
289
+ d: "M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10"
290
+ }
291
+ )
292
+ }
293
+ );
294
+ }
295
+ function FlagIcon({ className }) {
296
+ return /* @__PURE__ */ jsx(
297
+ "svg",
298
+ {
299
+ "aria-hidden": "true",
300
+ className,
301
+ viewBox: "0 0 24 24",
302
+ fill: "none",
303
+ stroke: "currentColor",
304
+ strokeWidth: "1.5",
305
+ children: /* @__PURE__ */ jsx(
306
+ "path",
307
+ {
308
+ strokeLinecap: "round",
309
+ strokeLinejoin: "round",
310
+ d: "M3 3v1.5M3 21v-6m0 0l2.77-.693a9 9 0 016.208.682l.108.054a9 9 0 006.086.71l3.114-.732a48.524 48.524 0 01-.005-10.499l-3.11.732a9 9 0 01-6.085-.711l-.108-.054a9 9 0 00-6.208-.682L3 4.5M3 15V4.5"
311
+ }
312
+ )
313
+ }
314
+ );
315
+ }
316
+ var CommentMenuContext = createContext(null);
317
+ function useCommentMenuContext() {
318
+ const context = useContext(CommentMenuContext);
319
+ if (!context) {
320
+ throw new Error("CommentMenu compound components must be used within <CommentMenu>");
321
+ }
322
+ return context;
323
+ }
324
+ var DeleteConfirmDialog = memo(function DeleteConfirmDialog2({
325
+ isOpen,
326
+ onClose,
327
+ onConfirm,
328
+ isDeleting = false,
329
+ title = "Delete comment?",
330
+ message = "This action cannot be undone.",
331
+ confirmText = "Delete",
332
+ cancelText = "Cancel",
333
+ danger = true
334
+ }) {
335
+ const dialogRef = useRef(null);
336
+ useEffect(() => {
337
+ if (!isOpen) return;
338
+ const handleEscape = (e) => {
339
+ if (e.key === "Escape") onClose();
340
+ };
341
+ document.addEventListener("keydown", handleEscape);
342
+ return () => document.removeEventListener("keydown", handleEscape);
343
+ }, [isOpen, onClose]);
344
+ useEffect(() => {
345
+ if (!isOpen || !dialogRef.current) return;
346
+ const firstButton = dialogRef.current.querySelector("button");
347
+ firstButton?.focus();
348
+ }, [isOpen]);
349
+ if (!isOpen) return null;
350
+ return /* @__PURE__ */ jsx(
351
+ "div",
352
+ {
353
+ onKeyDown: (e) => e.stopPropagation(),
354
+ className: "sv-comment-dialog-overlay",
355
+ onClick: onClose,
356
+ children: /* @__PURE__ */ jsxs(
357
+ "div",
358
+ {
359
+ onKeyDown: (e) => e.stopPropagation(),
360
+ ref: dialogRef,
361
+ className: "sv-comment-dialog",
362
+ onClick: (e) => e.stopPropagation(),
363
+ role: "alertdialog",
364
+ "aria-modal": "true",
365
+ "aria-labelledby": "delete-dialog-title",
366
+ "aria-describedby": "delete-dialog-message",
367
+ children: [
368
+ /* @__PURE__ */ jsx("h3", { id: "delete-dialog-title", className: "sv-comment-dialog__title", children: title }),
369
+ /* @__PURE__ */ jsx("p", { id: "delete-dialog-message", className: "sv-comment-dialog__message", children: message }),
370
+ /* @__PURE__ */ jsxs("div", { className: "sv-comment-dialog__actions", children: [
371
+ /* @__PURE__ */ jsx(
372
+ "button",
373
+ {
374
+ type: "button",
375
+ className: "sv-comment-dialog__btn sv-comment-dialog__btn--cancel",
376
+ onClick: onClose,
377
+ disabled: isDeleting,
378
+ children: cancelText
379
+ }
380
+ ),
381
+ /* @__PURE__ */ jsx(
382
+ "button",
383
+ {
384
+ type: "button",
385
+ className: clsx(
386
+ "sv-comment-dialog__btn",
387
+ danger ? "sv-comment-dialog__btn--danger" : "sv-comment-dialog__btn--primary"
388
+ ),
389
+ onClick: onConfirm,
390
+ disabled: isDeleting,
391
+ children: isDeleting ? "..." : confirmText
392
+ }
393
+ )
394
+ ] })
395
+ ]
396
+ }
397
+ )
398
+ }
399
+ );
400
+ });
401
+ function CommentMenuRoot({
402
+ comment,
403
+ isReply = false,
404
+ parentId,
405
+ className,
406
+ children
407
+ }) {
408
+ const { i18n: sheetI18n } = useCommentSheetContext();
409
+ const [isOpen, setIsOpen] = useState(false);
410
+ const [confirmDialog, setConfirmDialog] = useState({
411
+ isOpen: false,
412
+ isLoading: false,
413
+ title: "",
414
+ message: "",
415
+ confirmText: "",
416
+ cancelText: "",
417
+ onConfirm: async () => {
418
+ }
419
+ });
420
+ const triggerRef = useRef(null);
421
+ const menuRef = useRef(null);
422
+ const i18n = useMemo(
423
+ () => ({
424
+ deleteText: sheetI18n.deleteText ?? "Delete",
425
+ editText: sheetI18n.editText ?? "Edit",
426
+ reportText: sheetI18n.reportText ?? "Report",
427
+ deleteConfirmTitle: sheetI18n.deleteConfirmTitle ?? "Delete comment?",
428
+ deleteConfirmMessage: sheetI18n.deleteConfirmMessage ?? "This action cannot be undone.",
429
+ deleteConfirmButton: sheetI18n.deleteConfirmButton ?? "Delete",
430
+ cancelButton: sheetI18n.cancelButton ?? "Cancel"
431
+ }),
432
+ [sheetI18n]
433
+ );
434
+ useEffect(() => {
435
+ if (!isOpen) return;
436
+ const handleClickOutside = (e) => {
437
+ if (menuRef.current && !menuRef.current.contains(e.target)) {
438
+ setIsOpen(false);
439
+ }
440
+ };
441
+ document.addEventListener("mousedown", handleClickOutside);
442
+ return () => document.removeEventListener("mousedown", handleClickOutside);
443
+ }, [isOpen]);
444
+ useEffect(() => {
445
+ if (!isOpen) return;
446
+ const handleEscape = (e) => {
447
+ if (e.key === "Escape") {
448
+ setIsOpen(false);
449
+ triggerRef.current?.focus();
450
+ }
451
+ };
452
+ document.addEventListener("keydown", handleEscape);
453
+ return () => document.removeEventListener("keydown", handleEscape);
454
+ }, [isOpen]);
455
+ const open = useCallback(() => setIsOpen(true), []);
456
+ const close = useCallback(() => setIsOpen(false), []);
457
+ const toggle = useCallback(() => setIsOpen((prev) => !prev), []);
458
+ const showConfirm = useCallback((config) => {
459
+ setConfirmDialog({
460
+ ...config,
461
+ isOpen: true,
462
+ isLoading: false
463
+ });
464
+ }, []);
465
+ const handleConfirm = useCallback(async () => {
466
+ setConfirmDialog((prev) => ({ ...prev, isLoading: true }));
467
+ try {
468
+ await confirmDialog.onConfirm();
469
+ setConfirmDialog((prev) => ({ ...prev, isOpen: false, isLoading: false }));
470
+ } catch {
471
+ setConfirmDialog((prev) => ({ ...prev, isLoading: false }));
472
+ }
473
+ }, [confirmDialog.onConfirm]);
474
+ const handleCloseConfirm = useCallback(() => {
475
+ setConfirmDialog((prev) => ({ ...prev, isOpen: false }));
476
+ }, []);
477
+ const contextValue = useMemo(
478
+ () => ({
479
+ comment,
480
+ isReply,
481
+ parentId,
482
+ isOpen,
483
+ open,
484
+ close,
485
+ toggle,
486
+ triggerRef,
487
+ menuRef,
488
+ showConfirm,
489
+ i18n
490
+ }),
491
+ [comment, isReply, parentId, isOpen, open, close, toggle, showConfirm, i18n]
492
+ );
493
+ return /* @__PURE__ */ jsxs(CommentMenuContext.Provider, { value: contextValue, children: [
494
+ /* @__PURE__ */ jsx("div", { ref: menuRef, className: clsx("sv-comment-menu", className), children }),
495
+ /* @__PURE__ */ jsx(
496
+ DeleteConfirmDialog,
497
+ {
498
+ isOpen: confirmDialog.isOpen,
499
+ onClose: handleCloseConfirm,
500
+ onConfirm: handleConfirm,
501
+ isDeleting: confirmDialog.isLoading,
502
+ title: confirmDialog.title,
503
+ message: confirmDialog.message,
504
+ confirmText: confirmDialog.confirmText,
505
+ cancelText: confirmDialog.cancelText,
506
+ danger: confirmDialog.danger
507
+ }
508
+ )
509
+ ] });
510
+ }
511
+ function Trigger({
512
+ className,
513
+ icon,
514
+ "aria-label": ariaLabel = "More options"
515
+ }) {
516
+ const { isOpen, toggle, triggerRef } = useCommentMenuContext();
517
+ return /* @__PURE__ */ jsx(
518
+ "button",
519
+ {
520
+ ref: triggerRef,
521
+ type: "button",
522
+ className: clsx("sv-comment-menu__trigger", className),
523
+ onClick: toggle,
524
+ "aria-label": ariaLabel,
525
+ "aria-expanded": isOpen,
526
+ "aria-haspopup": "menu",
527
+ children: icon ?? /* @__PURE__ */ jsx(MoreIcon, { className: "sv-comment-menu__icon" })
528
+ }
529
+ );
530
+ }
531
+ function Dropdown({ className, children }) {
532
+ const { isOpen } = useCommentMenuContext();
533
+ if (!isOpen) return null;
534
+ return /* @__PURE__ */ jsx("div", { className: clsx("sv-comment-menu__dropdown", className), role: "menu", children });
535
+ }
536
+ function Item({
537
+ icon,
538
+ danger = false,
539
+ disabled = false,
540
+ className,
541
+ onClick,
542
+ children
543
+ }) {
544
+ const { close } = useCommentMenuContext();
545
+ const handleClick = useCallback(() => {
546
+ if (disabled) return;
547
+ onClick?.();
548
+ close();
549
+ }, [disabled, onClick, close]);
550
+ return /* @__PURE__ */ jsxs(
551
+ "button",
552
+ {
553
+ type: "button",
554
+ className: clsx(
555
+ "sv-comment-menu__item",
556
+ danger && "sv-comment-menu__item--danger",
557
+ disabled && "sv-comment-menu__item--disabled",
558
+ className
559
+ ),
560
+ onClick: handleClick,
561
+ disabled,
562
+ role: "menuitem",
563
+ children: [
564
+ icon && /* @__PURE__ */ jsx("span", { className: "sv-comment-menu__item-icon", children: icon }),
565
+ /* @__PURE__ */ jsx("span", { children })
566
+ ]
567
+ }
568
+ );
569
+ }
570
+ function DeleteItem({ requireConfirm, onDelete, label, className }) {
571
+ const { comment, isReply, parentId, close, showConfirm, i18n } = useCommentMenuContext();
572
+ const { actions, config } = useCommentSheetContext();
573
+ const shouldConfirm = requireConfirm ?? config.requireDeleteConfirm;
574
+ const displayLabel = label ?? i18n.deleteText;
575
+ const performDelete = useCallback(async () => {
576
+ if (onDelete) {
577
+ await onDelete(comment.id, isReply, parentId);
578
+ } else {
579
+ await actions.deleteComment(comment.id, isReply, parentId);
580
+ }
581
+ }, [onDelete, actions, comment.id, isReply, parentId]);
582
+ const handleClick = useCallback(() => {
583
+ close();
584
+ if (shouldConfirm) {
585
+ showConfirm({
586
+ title: i18n.deleteConfirmTitle,
587
+ message: i18n.deleteConfirmMessage,
588
+ confirmText: i18n.deleteConfirmButton,
589
+ cancelText: i18n.cancelButton,
590
+ danger: true,
591
+ onConfirm: performDelete
592
+ });
593
+ } else {
594
+ performDelete();
595
+ }
596
+ }, [shouldConfirm, showConfirm, performDelete, i18n, close]);
597
+ return /* @__PURE__ */ jsxs(
598
+ "button",
599
+ {
600
+ type: "button",
601
+ className: clsx("sv-comment-menu__item sv-comment-menu__item--danger", className),
602
+ onClick: handleClick,
603
+ role: "menuitem",
604
+ children: [
605
+ /* @__PURE__ */ jsx(TrashIcon, { className: "sv-comment-menu__item-icon" }),
606
+ /* @__PURE__ */ jsx("span", { children: displayLabel })
607
+ ]
608
+ }
609
+ );
610
+ }
611
+ function EditItem({ onEdit, label, className }) {
612
+ const { comment, close, i18n } = useCommentMenuContext();
613
+ const displayLabel = label ?? i18n.editText;
614
+ const isDisabled = !onEdit;
615
+ const handleClick = useCallback(() => {
616
+ if (!onEdit) return;
617
+ close();
618
+ onEdit(comment.id, comment.content);
619
+ }, [close, onEdit, comment.id, comment.content]);
620
+ return /* @__PURE__ */ jsxs(
621
+ "button",
622
+ {
623
+ type: "button",
624
+ className: clsx(
625
+ "sv-comment-menu__item",
626
+ isDisabled && "sv-comment-menu__item--disabled",
627
+ className
628
+ ),
629
+ onClick: handleClick,
630
+ disabled: isDisabled,
631
+ role: "menuitem",
632
+ children: [
633
+ /* @__PURE__ */ jsx(EditIcon, { className: "sv-comment-menu__item-icon" }),
634
+ /* @__PURE__ */ jsx("span", { children: displayLabel })
635
+ ]
636
+ }
637
+ );
638
+ }
639
+ function ReportItem({
640
+ onReport,
641
+ reason = "inappropriate",
642
+ label,
643
+ className
644
+ }) {
645
+ const { comment, close, i18n } = useCommentMenuContext();
646
+ const { actions } = useCommentSheetContext();
647
+ const displayLabel = label ?? i18n.reportText;
648
+ const handleClick = useCallback(() => {
649
+ close();
650
+ if (onReport) {
651
+ onReport(comment.id);
652
+ } else {
653
+ actions.reportComment(comment.id, reason);
654
+ }
655
+ }, [close, onReport, comment.id, actions, reason]);
656
+ return /* @__PURE__ */ jsxs(
657
+ "button",
658
+ {
659
+ type: "button",
660
+ className: clsx("sv-comment-menu__item", className),
661
+ onClick: handleClick,
662
+ role: "menuitem",
663
+ children: [
664
+ /* @__PURE__ */ jsx(FlagIcon, { className: "sv-comment-menu__item-icon" }),
665
+ /* @__PURE__ */ jsx("span", { children: displayLabel })
666
+ ]
667
+ }
668
+ );
669
+ }
670
+ var CommentMenu = Object.assign(memo(CommentMenuRoot), {
671
+ Trigger: memo(Trigger),
672
+ Dropdown: memo(Dropdown),
673
+ Item: memo(Item),
674
+ DeleteItem: memo(DeleteItem),
675
+ EditItem: memo(EditItem),
676
+ ReportItem: memo(ReportItem)
677
+ });
678
+ CommentMenu.displayName = "CommentMenu";
679
+ function PinIcon({ className }) {
680
+ return /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", className, viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M9.828.722a.5.5 0 0 1 .354.146l4.95 4.95a.5.5 0 0 1 0 .707c-.48.48-1.072.588-1.503.588-.177 0-.335-.018-.46-.039l-3.134 3.134a5.927 5.927 0 0 1 .16 1.013c.046.702-.032 1.687-.72 2.375a.5.5 0 0 1-.707 0l-2.829-2.828-3.182 3.182c-.195.195-1.219.902-1.414.707-.195-.195.512-1.22.707-1.414l3.182-3.182-2.828-2.829a.5.5 0 0 1 0-.707c.688-.688 1.673-.767 2.375-.72a5.922 5.922 0 0 1 1.013.16l3.134-3.133a2.772 2.772 0 0 1-.04-.461c0-.43.108-1.022.589-1.503a.5.5 0 0 1 .353-.146z" }) });
681
+ }
682
+ function ReplyIcon({ className }) {
683
+ return /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", className, viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsx(
684
+ "path",
685
+ {
686
+ fillRule: "evenodd",
687
+ d: "M7.793 2.232a.75.75 0 01-.025 1.06L3.622 7.25h10.003a5.375 5.375 0 010 10.75H10.75a.75.75 0 010-1.5h2.875a3.875 3.875 0 000-7.75H3.622l4.146 3.957a.75.75 0 01-1.036 1.085l-5.5-5.25a.75.75 0 010-1.085l5.5-5.25a.75.75 0 011.06.025z",
688
+ clipRule: "evenodd"
689
+ }
690
+ ) });
691
+ }
692
+ function VerifiedIcon({ className }) {
693
+ return /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", className, viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" }) });
694
+ }
695
+ function ChevronIcon({ direction, className }) {
696
+ return /* @__PURE__ */ jsx(
697
+ "svg",
698
+ {
699
+ "aria-hidden": "true",
700
+ className,
701
+ viewBox: "0 0 20 20",
702
+ fill: "currentColor",
703
+ style: { transform: direction === "up" ? "rotate(180deg)" : void 0 },
704
+ children: /* @__PURE__ */ jsx(
705
+ "path",
706
+ {
707
+ fillRule: "evenodd",
708
+ d: "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
709
+ clipRule: "evenodd"
710
+ }
711
+ )
712
+ }
713
+ );
714
+ }
715
+ function CommentAvatar({
716
+ src,
717
+ name,
718
+ size = "normal",
719
+ className
720
+ }) {
721
+ const [error, setError] = useState(false);
722
+ const sizeClass = size === "small" ? "sv-comment-reply__avatar" : "sv-comment-item__avatar";
723
+ const initial = name.charAt(0).toUpperCase();
724
+ if (!src || error) {
725
+ return /* @__PURE__ */ jsx(
726
+ "div",
727
+ {
728
+ className: clsx(sizeClass, className),
729
+ style: {
730
+ display: "flex",
731
+ alignItems: "center",
732
+ justifyContent: "center",
733
+ fontSize: size === "small" ? 10 : 14,
734
+ fontWeight: 600,
735
+ color: "#6b7271"
736
+ },
737
+ children: initial
738
+ }
739
+ );
740
+ }
741
+ return /* @__PURE__ */ jsx(
742
+ "img",
743
+ {
744
+ src,
745
+ alt: name,
746
+ className: clsx(sizeClass, className),
747
+ onError: () => setError(true)
748
+ }
749
+ );
750
+ }
751
+ function CommentText({
752
+ text,
753
+ maxLines,
754
+ className,
755
+ expandText = "See more",
756
+ collapseText = "See less"
757
+ }) {
758
+ const [expanded, setExpanded] = useState(false);
759
+ const needsCollapse = text.length > maxLines * 60 || text.split("\n").length > maxLines;
760
+ return /* @__PURE__ */ jsxs("div", { className, children: [
761
+ /* @__PURE__ */ jsx(
762
+ "p",
763
+ {
764
+ className: clsx(
765
+ "sv-comment-item__text",
766
+ !expanded && needsCollapse && "sv-comment-item__text--collapsed"
767
+ ),
768
+ style: { "--sv-comment-max-lines": maxLines },
769
+ children: text
770
+ }
771
+ ),
772
+ needsCollapse && /* @__PURE__ */ jsx(
773
+ "button",
774
+ {
775
+ type: "button",
776
+ className: "sv-comment-item__expand-btn",
777
+ onClick: () => setExpanded(!expanded),
778
+ children: expanded ? collapseText : expandText
779
+ }
780
+ )
781
+ ] });
782
+ }
783
+ function defaultFormatTimeAgo(dateStr) {
784
+ const date = new Date(dateStr);
785
+ const now = /* @__PURE__ */ new Date();
786
+ const diff = Math.floor((now.getTime() - date.getTime()) / 1e3);
787
+ if (diff < 60) return "just now";
788
+ if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
789
+ if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`;
790
+ if (diff < 604800) return `${Math.floor(diff / 86400)}d ago`;
791
+ if (diff < 2592e3) return `${Math.floor(diff / 604800)}w ago`;
792
+ return `${Math.floor(diff / 2592e3)}mo ago`;
793
+ }
794
+ function formatCount(count) {
795
+ if (count >= 1e6) {
796
+ return `${(count / 1e6).toFixed(1)}M`;
797
+ }
798
+ if (count >= 1e3) {
799
+ return `${(count / 1e3).toFixed(1)}K`;
800
+ }
801
+ return String(count);
802
+ }
803
+ var ReplyItemComponent = memo(function ReplyItemComponent2({
804
+ reply,
805
+ parentComment
806
+ }) {
807
+ const { setReplyTarget, i18n } = useCommentSheetContext();
808
+ const formatTimeAgo = i18n.formatRelativeTime ?? defaultFormatTimeAgo;
809
+ const handleReply = useCallback(() => {
810
+ setReplyTarget({
811
+ commentId: parentComment.id,
812
+ authorName: reply.author.name,
813
+ authorId: reply.author.id
814
+ });
815
+ }, [setReplyTarget, parentComment.id, reply.author]);
816
+ return /* @__PURE__ */ jsxs("div", { className: clsx("sv-comment-reply", reply.isPending && "sv-comment-item--pending"), children: [
817
+ /* @__PURE__ */ jsx(CommentAvatar, { src: reply.author.avatar, name: reply.author.name, size: "small" }),
818
+ /* @__PURE__ */ jsxs("div", { className: "sv-comment-item__content", children: [
819
+ /* @__PURE__ */ jsxs("div", { className: "sv-comment-item__header", children: [
820
+ /* @__PURE__ */ jsxs("div", { className: "sv-comment-item__header-left", children: [
821
+ /* @__PURE__ */ jsx("span", { className: "sv-comment-item__author", children: reply.author.name }),
822
+ reply.author.isVerified && /* @__PURE__ */ jsx(VerifiedIcon, { className: "sv-comment-item__verified" })
823
+ ] }),
824
+ reply.isOwner && /* @__PURE__ */ jsxs(CommentMenu, { comment: reply, isReply: true, parentId: parentComment.id, children: [
825
+ /* @__PURE__ */ jsx(CommentMenu.Trigger, {}),
826
+ /* @__PURE__ */ jsx(CommentMenu.Dropdown, { children: /* @__PURE__ */ jsx(CommentMenu.DeleteItem, {}) })
827
+ ] })
828
+ ] }),
829
+ /* @__PURE__ */ jsxs("p", { className: "sv-comment-item__text", children: [
830
+ reply.replyTo && reply.replyTo.id !== parentComment.author.id && /* @__PURE__ */ jsxs("span", { className: "sv-comment-reply__mention", children: [
831
+ "@",
832
+ reply.replyTo.name,
833
+ " "
834
+ ] }),
835
+ reply.content
836
+ ] }),
837
+ /* @__PURE__ */ jsxs("div", { className: "sv-comment-item__actions", children: [
838
+ /* @__PURE__ */ jsx("span", { className: "sv-comment-item__time", children: formatTimeAgo(reply.createdAt) }),
839
+ /* @__PURE__ */ jsx("button", { type: "button", className: "sv-comment-item__action-btn", onClick: handleReply, children: /* @__PURE__ */ jsx(ReplyIcon, { className: "sv-comment-item__action-icon" }) })
840
+ ] })
841
+ ] })
842
+ ] });
843
+ });
844
+ function RepliesList({ comment }) {
845
+ const { actions, config, i18n } = useCommentSheetContext();
846
+ const [expanded, setExpanded] = useState(false);
847
+ const { replyCount, replies = [], repliesLoaded } = comment;
848
+ const shouldAutoExpand = replyCount <= config.repliesAutoExpandThreshold;
849
+ const showReplies = shouldAutoExpand || expanded;
850
+ const visibleReplies = showReplies ? replies : [];
851
+ const hasMoreReplies = !repliesLoaded && replyCount > replies.length;
852
+ const remainingReplies = replyCount - visibleReplies.length;
853
+ const hideRepliesText = i18n.hideRepliesText ?? "Hide replies";
854
+ const viewRepliesText = (i18n.viewRepliesText ?? "View {count} more replies").replace(
855
+ "{count}",
856
+ String(remainingReplies)
857
+ );
858
+ const viewMoreRepliesText = i18n.viewMoreRepliesText ?? "View more replies";
859
+ const loadRepliesText = i18n.loadRepliesText ?? "Load replies";
860
+ const handleToggle = useCallback(() => {
861
+ if (!expanded && replies.length === 0) {
862
+ actions.loadReplies(comment.id);
863
+ }
864
+ setExpanded(!expanded);
865
+ }, [expanded, replies.length, actions, comment.id]);
866
+ const handleLoadMore = useCallback(() => {
867
+ actions.loadReplies(comment.id);
868
+ }, [actions, comment.id]);
869
+ if (replyCount === 0) return null;
870
+ return /* @__PURE__ */ jsxs("div", { className: "sv-comment-replies", children: [
871
+ showReplies && visibleReplies.length > 0 && /* @__PURE__ */ jsx("div", { className: "sv-comment-replies__list", children: visibleReplies.map((reply) => /* @__PURE__ */ jsx(ReplyItemComponent, { reply, parentComment: comment }, reply.id)) }),
872
+ !shouldAutoExpand && /* @__PURE__ */ jsxs("button", { type: "button", className: "sv-comment-replies__toggle", onClick: handleToggle, children: [
873
+ /* @__PURE__ */ jsx("span", { className: "sv-comment-replies__toggle-line" }),
874
+ /* @__PURE__ */ jsx("span", { className: "sv-comment-replies__toggle-text", children: expanded ? hideRepliesText : viewRepliesText }),
875
+ /* @__PURE__ */ jsx(
876
+ ChevronIcon,
877
+ {
878
+ direction: expanded ? "up" : "down",
879
+ className: "sv-comment-replies__toggle-icon"
880
+ }
881
+ )
882
+ ] }),
883
+ expanded && hasMoreReplies && /* @__PURE__ */ jsxs("button", { type: "button", className: "sv-comment-replies__toggle", onClick: handleLoadMore, children: [
884
+ /* @__PURE__ */ jsx("span", { className: "sv-comment-replies__toggle-line" }),
885
+ /* @__PURE__ */ jsx("span", { className: "sv-comment-replies__toggle-text", children: viewMoreRepliesText }),
886
+ /* @__PURE__ */ jsx(ChevronIcon, { direction: "down", className: "sv-comment-replies__toggle-icon" })
887
+ ] }),
888
+ shouldAutoExpand && replies.length === 0 && replyCount > 0 && /* @__PURE__ */ jsxs(
889
+ "button",
890
+ {
891
+ type: "button",
892
+ className: "sv-comment-replies__toggle",
893
+ onClick: () => actions.loadReplies(comment.id),
894
+ children: [
895
+ /* @__PURE__ */ jsx("span", { className: "sv-comment-replies__toggle-line" }),
896
+ /* @__PURE__ */ jsx("span", { className: "sv-comment-replies__toggle-text", children: loadRepliesText }),
897
+ /* @__PURE__ */ jsx(ChevronIcon, { direction: "down", className: "sv-comment-replies__toggle-icon" })
898
+ ]
899
+ }
900
+ )
901
+ ] });
902
+ }
903
+ var CommentItemComponent = memo(function CommentItemComponent2({
904
+ comment,
905
+ className
906
+ }) {
907
+ const { config, setReplyTarget, i18n } = useCommentSheetContext();
908
+ const expandText = i18n.expandText ?? "See more";
909
+ const collapseText = i18n.collapseText ?? "See less";
910
+ const formatTimeAgo = i18n.formatRelativeTime ?? defaultFormatTimeAgo;
911
+ const handleReply = useCallback(() => {
912
+ setReplyTarget({
913
+ commentId: comment.id,
914
+ authorName: comment.author.name,
915
+ authorId: comment.author.id
916
+ });
917
+ }, [setReplyTarget, comment.id, comment.author]);
918
+ const hasReplies = comment.replyCount > 0;
919
+ return /* @__PURE__ */ jsxs(
920
+ "div",
921
+ {
922
+ className: clsx(
923
+ "sv-comment-item",
924
+ comment.isPending && "sv-comment-item--pending",
925
+ comment.isPinned && "sv-comment-item--pinned",
926
+ hasReplies && "sv-comment-item--has-replies",
927
+ className
928
+ ),
929
+ children: [
930
+ /* @__PURE__ */ jsx(CommentAvatar, { src: comment.author.avatar, name: comment.author.name }),
931
+ /* @__PURE__ */ jsxs("div", { className: "sv-comment-item__content", children: [
932
+ /* @__PURE__ */ jsxs("div", { className: "sv-comment-item__header", children: [
933
+ /* @__PURE__ */ jsxs("div", { className: "sv-comment-item__header-left", children: [
934
+ comment.isPinned && /* @__PURE__ */ jsx(PinIcon, { className: "sv-comment-item__pin-icon" }),
935
+ /* @__PURE__ */ jsx("span", { className: "sv-comment-item__author", children: comment.author.name }),
936
+ comment.author.isVerified && /* @__PURE__ */ jsx(VerifiedIcon, { className: "sv-comment-item__verified" }),
937
+ comment.author.badge && /* @__PURE__ */ jsx("span", { className: "sv-comment-item__badge", children: comment.author.badge })
938
+ ] }),
939
+ comment.isOwner && /* @__PURE__ */ jsxs(CommentMenu, { comment, children: [
940
+ /* @__PURE__ */ jsx(CommentMenu.Trigger, {}),
941
+ /* @__PURE__ */ jsx(CommentMenu.Dropdown, { children: /* @__PURE__ */ jsx(CommentMenu.DeleteItem, {}) })
942
+ ] })
943
+ ] }),
944
+ /* @__PURE__ */ jsx(
945
+ CommentText,
946
+ {
947
+ text: comment.content,
948
+ maxLines: config.textMaxLines,
949
+ expandText,
950
+ collapseText
951
+ }
952
+ ),
953
+ /* @__PURE__ */ jsxs("div", { className: "sv-comment-item__actions", children: [
954
+ /* @__PURE__ */ jsx("span", { className: "sv-comment-item__time", children: formatTimeAgo(comment.createdAt) }),
955
+ /* @__PURE__ */ jsxs("button", { type: "button", className: "sv-comment-item__action-btn", onClick: handleReply, children: [
956
+ /* @__PURE__ */ jsx(ReplyIcon, { className: "sv-comment-item__action-icon" }),
957
+ comment.replyCount > 0 && /* @__PURE__ */ jsx("span", { children: formatCount(comment.replyCount) })
958
+ ] })
959
+ ] }),
960
+ /* @__PURE__ */ jsx(RepliesList, { comment })
961
+ ] })
962
+ ]
963
+ }
964
+ );
965
+ });
966
+ CommentItemComponent.displayName = "CommentItem";
967
+ var CommentItemSkeleton = memo(function CommentItemSkeleton2() {
968
+ return /* @__PURE__ */ jsxs("div", { className: "sv-comment-item sv-comment-skeleton", children: [
969
+ /* @__PURE__ */ jsx("div", { className: "sv-comment-skeleton__avatar" }),
970
+ /* @__PURE__ */ jsxs("div", { className: "sv-comment-skeleton__content", children: [
971
+ /* @__PURE__ */ jsxs("div", { className: "sv-comment-skeleton__header", children: [
972
+ /* @__PURE__ */ jsx("div", { className: "sv-comment-skeleton__author" }),
973
+ /* @__PURE__ */ jsx("div", { className: "sv-comment-skeleton__time" })
974
+ ] }),
975
+ /* @__PURE__ */ jsxs("div", { className: "sv-comment-skeleton__text", children: [
976
+ /* @__PURE__ */ jsx("div", { className: "sv-comment-skeleton__line sv-comment-skeleton__line--full" }),
977
+ /* @__PURE__ */ jsx("div", { className: "sv-comment-skeleton__line sv-comment-skeleton__line--medium" })
978
+ ] }),
979
+ /* @__PURE__ */ jsxs("div", { className: "sv-comment-skeleton__actions", children: [
980
+ /* @__PURE__ */ jsx("div", { className: "sv-comment-skeleton__action" }),
981
+ /* @__PURE__ */ jsx("div", { className: "sv-comment-skeleton__action" })
982
+ ] })
983
+ ] })
984
+ ] });
985
+ });
986
+ CommentItemSkeleton.displayName = "CommentItemSkeleton";
987
+ var CommentListSkeleton = memo(function CommentListSkeleton2({
988
+ count = 5
989
+ }) {
990
+ return /* @__PURE__ */ jsx("div", { className: "sv-comment-skeleton-list", children: Array.from({ length: count }).map((_, index) => /* @__PURE__ */ jsx(
991
+ CommentItemSkeleton,
992
+ {},
993
+ `skeleton-${// biome-ignore lint/suspicious/noArrayIndexKey: <explanation>
994
+ index}`
995
+ )) });
996
+ });
997
+ CommentListSkeleton.displayName = "CommentListSkeleton";
998
+ var CommentList = memo(function CommentList2({
999
+ emptyState,
1000
+ loadingState,
1001
+ errorState,
1002
+ className,
1003
+ errorText = "Failed to load comments",
1004
+ retryText = "Try again",
1005
+ emptyText = "No comments yet. Be the first!",
1006
+ loadMoreText = "Load more comments"
1007
+ }) {
1008
+ const { state, actions, videoId } = useCommentSheetContext();
1009
+ const listRef = useRef(null);
1010
+ const loadMoreRef = useRef(null);
1011
+ const { comments, isLoading, error, hasMore, isLoadingMore } = state;
1012
+ useEffect(() => {
1013
+ if (!hasMore || isLoadingMore) return;
1014
+ const observer = new IntersectionObserver(
1015
+ (entries) => {
1016
+ if (entries[0]?.isIntersecting) {
1017
+ actions.loadMore();
1018
+ }
1019
+ },
1020
+ { threshold: 0.1 }
1021
+ );
1022
+ const target = loadMoreRef.current;
1023
+ if (target) {
1024
+ observer.observe(target);
1025
+ }
1026
+ return () => {
1027
+ if (target) {
1028
+ observer.unobserve(target);
1029
+ }
1030
+ };
1031
+ }, [hasMore, isLoadingMore, actions]);
1032
+ const handleRetry = useCallback(() => {
1033
+ if (videoId) {
1034
+ actions.loadComments(videoId);
1035
+ }
1036
+ }, [actions, videoId]);
1037
+ if (isLoading && comments.length === 0) {
1038
+ return /* @__PURE__ */ jsx("div", { className: clsx("sv-comment-sheet__list", className), children: loadingState ?? /* @__PURE__ */ jsx(CommentListSkeleton, { count: 5 }) });
1039
+ }
1040
+ if (error && comments.length === 0) {
1041
+ return /* @__PURE__ */ jsx("div", { className: clsx("sv-comment-sheet__list", className), children: errorState?.(error, handleRetry) ?? /* @__PURE__ */ jsxs("div", { className: "sv-comment-sheet__error", children: [
1042
+ /* @__PURE__ */ jsx("span", { children: errorText }),
1043
+ /* @__PURE__ */ jsx("button", { type: "button", className: "sv-comment-sheet__error-btn", onClick: handleRetry, children: retryText })
1044
+ ] }) });
1045
+ }
1046
+ if (comments.length === 0) {
1047
+ return /* @__PURE__ */ jsx("div", { className: clsx("sv-comment-sheet__list", className), children: emptyState ?? /* @__PURE__ */ jsxs("div", { className: "sv-comment-sheet__empty", children: [
1048
+ /* @__PURE__ */ jsx("span", { className: "sv-comment-sheet__empty-icon", children: "\u{1F4AC}" }),
1049
+ /* @__PURE__ */ jsx("span", { className: "sv-comment-sheet__empty-text", children: emptyText })
1050
+ ] }) });
1051
+ }
1052
+ return /* @__PURE__ */ jsxs("div", { ref: listRef, className: clsx("sv-comment-sheet__list", className), children: [
1053
+ comments.map((comment) => /* @__PURE__ */ jsx(CommentItemComponent, { comment }, comment.id)),
1054
+ hasMore && /* @__PURE__ */ jsx("div", { ref: loadMoreRef, className: "sv-comment-sheet__load-more", children: isLoadingMore ? /* @__PURE__ */ jsx(CommentItemSkeleton, {}) : /* @__PURE__ */ jsx(
1055
+ "button",
1056
+ {
1057
+ type: "button",
1058
+ className: "sv-comment-sheet__load-more-btn",
1059
+ onClick: () => actions.loadMore(),
1060
+ children: loadMoreText
1061
+ }
1062
+ ) })
1063
+ ] });
1064
+ });
1065
+ CommentList.displayName = "CommentList";
1066
+
1067
+ // src/components/CommentSheet/CommentSheet.css.ts
1068
+ var COMMENT_SHEET_CSS = `
1069
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
1070
+ CSS VARIABLES (Light Theme)
1071
+ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
1072
+
1073
+ :root {
1074
+ /* Primary colors */
1075
+ --sv-comment-primary: #164d8e;
1076
+ --sv-comment-primary-light: #1354ae;
1077
+ --sv-comment-primary-dark: #003477;
1078
+
1079
+ /* Contrast colors */
1080
+ --sv-comment-bg: #ffffff;
1081
+ --sv-comment-text: #121212;
1082
+ --sv-comment-text-secondary: #6b7271;
1083
+ --sv-comment-border: rgba(18, 18, 18, 0.08);
1084
+
1085
+ /* Accent colors */
1086
+ --sv-comment-like-color: #ff434e;
1087
+ --sv-comment-verified-color: #1ea031;
1088
+ --sv-comment-mention-color: #164d8e;
1089
+
1090
+ /* Component specific */
1091
+ --sv-comment-avatar-bg: #e5e6e6;
1092
+ --sv-comment-input-border: #a3a3a3;
1093
+ --sv-comment-reply-line: #e5e6e6;
1094
+ }
1095
+
1096
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
1097
+ BACKDROP & CONTAINER
1098
+ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
1099
+
1100
+ .sv-comment-sheet-backdrop {
1101
+ position: fixed;
1102
+ inset: 0;
1103
+ background: var(--sv-comment-backdrop-bg, rgba(0, 0, 0, 0.5));
1104
+ z-index: var(--sv-comment-sheet-z-index, 1000);
1105
+ opacity: 0;
1106
+ visibility: hidden;
1107
+ pointer-events: none;
1108
+ transition: opacity var(--sv-comment-animation-duration, 400ms) ease,
1109
+ visibility 0s linear var(--sv-comment-animation-duration, 400ms);
1110
+ }
1111
+
1112
+ .sv-comment-sheet-backdrop--open {
1113
+ opacity: 1;
1114
+ visibility: visible;
1115
+ pointer-events: auto;
1116
+ transition: opacity var(--sv-comment-animation-duration, 400ms) ease,
1117
+ visibility 0s linear 0s;
1118
+ }
1119
+
1120
+ /* Keyframes for slide animations */
1121
+ @keyframes sv-sheet-slide-up {
1122
+ from { transform: translateY(100%); }
1123
+ to { transform: translateY(0); }
1124
+ }
1125
+
1126
+ @keyframes sv-sheet-slide-down {
1127
+ from { transform: translateY(0); }
1128
+ to { transform: translateY(100%); }
1129
+ }
1130
+
1131
+ .sv-comment-sheet {
1132
+ position: fixed;
1133
+ margin: 16px;
1134
+ left: 0;
1135
+ right: 0;
1136
+ bottom: 0;
1137
+ background: var(--sv-comment-bg, #ffffff);
1138
+ border-radius: var(--sv-comment-sheet-radius, 24px);
1139
+ z-index: var(--sv-comment-sheet-z-index, 1001);
1140
+ display: flex;
1141
+ flex-direction: column;
1142
+ max-height: var(--sv-comment-sheet-height, 55vh);
1143
+ transform: translateY(100%);
1144
+ overflow: hidden;
1145
+ touch-action: pan-y;
1146
+ isolation: isolate;
1147
+ pointer-events: none;
1148
+ will-change: transform;
1149
+ }
1150
+
1151
+ .sv-comment-sheet--open {
1152
+ transform: translateY(0);
1153
+ pointer-events: auto;
1154
+ animation: sv-sheet-slide-up var(--sv-comment-animation-duration, 400ms)
1155
+ var(--sv-comment-animation-easing, cubic-bezier(0.32, 0.72, 0, 1)) forwards;
1156
+ }
1157
+
1158
+ .sv-comment-sheet--open.sv-comment-sheet--closing {
1159
+ pointer-events: none;
1160
+ animation: sv-sheet-slide-down var(--sv-comment-animation-duration, 400ms)
1161
+ var(--sv-comment-animation-easing, cubic-bezier(0.32, 0.72, 0, 1)) forwards !important;
1162
+ }
1163
+
1164
+ /* CRITICAL: Disable VirtualSlider/VideoFeed swipe when CommentSheet is open */
1165
+ body.sv-comment-sheet-open .sv-slider,
1166
+ body.sv-comment-sheet-open .sv-video-feed {
1167
+ pointer-events: none !important;
1168
+ touch-action: none !important;
1169
+ }
1170
+
1171
+ body.sv-comment-sheet-open .sv-comment-sheet,
1172
+ body.sv-comment-sheet-open .sv-comment-sheet-backdrop {
1173
+ touch-action: auto !important;
1174
+ }
1175
+
1176
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
1177
+ HEADER
1178
+ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
1179
+
1180
+ .sv-comment-sheet__header {
1181
+ display: flex;
1182
+ align-items: center;
1183
+ justify-content: space-between;
1184
+ padding: 16px;
1185
+ border-bottom: 1px solid var(--sv-comment-border);
1186
+ flex-shrink: 0;
1187
+ position: relative;
1188
+ cursor: grab;
1189
+ touch-action: none;
1190
+ }
1191
+
1192
+ .sv-comment-sheet__header:active {
1193
+ cursor: grabbing;
1194
+ }
1195
+
1196
+ .sv-comment-sheet__header-handle {
1197
+ position: absolute;
1198
+ top: 8px;
1199
+ left: 50%;
1200
+ transform: translateX(-50%);
1201
+ width: 36px;
1202
+ height: 4px;
1203
+ background: var(--sv-comment-text-secondary);
1204
+ border-radius: 2px;
1205
+ opacity: 0.3;
1206
+ }
1207
+
1208
+ .sv-comment-sheet__header-left {
1209
+ display: flex;
1210
+ align-items: center;
1211
+ gap: 2px;
1212
+ }
1213
+
1214
+ .sv-comment-sheet__title {
1215
+ font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;
1216
+ font-size: 18px;
1217
+ font-weight: 600;
1218
+ line-height: 1.4;
1219
+ color: var(--sv-comment-text);
1220
+ opacity: 0.9;
1221
+ margin: 0;
1222
+ }
1223
+
1224
+ .sv-comment-sheet__sort-btn {
1225
+ display: flex;
1226
+ align-items: center;
1227
+ justify-content: center;
1228
+ background: none;
1229
+ border: none;
1230
+ padding: 0;
1231
+ cursor: pointer;
1232
+ color: var(--sv-comment-text);
1233
+ }
1234
+
1235
+ .sv-comment-sheet__sort-btn svg {
1236
+ width: 20px;
1237
+ height: 20px;
1238
+ }
1239
+
1240
+ .sv-comment-sheet__close-btn {
1241
+ display: flex;
1242
+ align-items: center;
1243
+ justify-content: center;
1244
+ width: 36px;
1245
+ height: 36px;
1246
+ border: none;
1247
+ border-radius: 100px;
1248
+ background: linear-gradient(180deg, var(--sv-comment-primary-light) 0%, var(--sv-comment-primary-dark) 100%);
1249
+ cursor: pointer;
1250
+ transition: opacity 0.15s ease;
1251
+ }
1252
+
1253
+ .sv-comment-sheet__close-btn:hover {
1254
+ opacity: 0.9;
1255
+ }
1256
+
1257
+ .sv-comment-sheet__close-btn svg {
1258
+ width: 20px;
1259
+ height: 20px;
1260
+ color: #ffffff;
1261
+ }
1262
+
1263
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
1264
+ COMMENT LIST
1265
+ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
1266
+
1267
+ .sv-comment-sheet__list {
1268
+ flex: 1;
1269
+ overflow-y: auto;
1270
+ overflow-x: hidden;
1271
+ padding: 8px 16px 28px 16px;
1272
+ -webkit-overflow-scrolling: touch;
1273
+ overscroll-behavior: contain;
1274
+ touch-action: pan-y;
1275
+ }
1276
+
1277
+ .sv-comment-sheet__list::-webkit-scrollbar {
1278
+ width: 0px;
1279
+ }
1280
+
1281
+ .sv-comment-sheet__list::-webkit-scrollbar-thumb {
1282
+ background: rgba(0, 0, 0, 0.0);
1283
+ border-radius: 0px;
1284
+ }
1285
+
1286
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
1287
+ COMMENT ITEM
1288
+ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
1289
+
1290
+ .sv-comment-item {
1291
+ display: flex;
1292
+ gap: 6px;
1293
+ padding: 16px 0;
1294
+ position: relative;
1295
+ }
1296
+
1297
+ .sv-comment-item--pending {
1298
+ opacity: 0.6;
1299
+ }
1300
+
1301
+ .sv-comment-item--pinned {
1302
+ background: var(--sv-comment-bg);
1303
+ }
1304
+
1305
+ .sv-comment-item__avatar {
1306
+ width: 40px;
1307
+ height: 40px;
1308
+ border-radius: 120px;
1309
+ flex-shrink: 0;
1310
+ object-fit: cover;
1311
+ background: var(--sv-comment-avatar-bg);
1312
+ }
1313
+
1314
+ .sv-comment-item__content {
1315
+ flex: 1;
1316
+ min-width: 0;
1317
+ display: flex;
1318
+ flex-direction: column;
1319
+ gap: 6px;
1320
+ }
1321
+
1322
+ .sv-comment-item__header {
1323
+ display: flex;
1324
+ align-items: center;
1325
+ justify-content: space-between;
1326
+ gap: 4px;
1327
+ }
1328
+
1329
+ .sv-comment-item__header-left {
1330
+ display: flex;
1331
+ align-items: center;
1332
+ gap: 4px;
1333
+ min-width: 0;
1334
+ }
1335
+
1336
+ .sv-comment-item__pin-icon {
1337
+ width: 16px;
1338
+ height: 16px;
1339
+ flex-shrink: 0;
1340
+ color: var(--sv-comment-primary);
1341
+ }
1342
+
1343
+ .sv-comment-item__author {
1344
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
1345
+ font-size: 14px;
1346
+ font-weight: 600;
1347
+ line-height: 1.4;
1348
+ color: var(--sv-comment-text);
1349
+ overflow: hidden;
1350
+ text-overflow: ellipsis;
1351
+ white-space: nowrap;
1352
+ }
1353
+
1354
+ .sv-comment-item__verified {
1355
+ width: 12px;
1356
+ height: 12px;
1357
+ flex-shrink: 0;
1358
+ color: var(--sv-comment-verified-color);
1359
+ }
1360
+
1361
+ .sv-comment-item__badge {
1362
+ font-size: 10px;
1363
+ padding: 2px 6px;
1364
+ background: var(--sv-comment-primary);
1365
+ color: #ffffff;
1366
+ border-radius: 4px;
1367
+ flex-shrink: 0;
1368
+ }
1369
+
1370
+ .sv-comment-item__menu-btn {
1371
+ display: flex;
1372
+ align-items: center;
1373
+ justify-content: center;
1374
+ background: none;
1375
+ border: none;
1376
+ padding: 0;
1377
+ cursor: pointer;
1378
+ color: var(--sv-comment-text-secondary);
1379
+ }
1380
+
1381
+ .sv-comment-item__menu-btn svg {
1382
+ width: 20px;
1383
+ height: 20px;
1384
+ }
1385
+
1386
+ .sv-comment-item__text {
1387
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
1388
+ font-size: 12px;
1389
+ font-weight: 400;
1390
+ line-height: 1.4;
1391
+ color: var(--sv-comment-text);
1392
+ word-break: break-word;
1393
+ margin: 0;
1394
+ padding-right: 16px;
1395
+ }
1396
+
1397
+ /* Text collapse */
1398
+ .sv-comment-item__text--collapsed {
1399
+ display: -webkit-box;
1400
+ -webkit-line-clamp: var(--sv-comment-max-lines, 3);
1401
+ -webkit-box-orient: vertical;
1402
+ overflow: hidden;
1403
+ }
1404
+
1405
+ .sv-comment-item__expand-btn {
1406
+ background: none;
1407
+ border: none;
1408
+ padding: 0;
1409
+ font-size: 12px;
1410
+ color: var(--sv-comment-text-secondary);
1411
+ cursor: pointer;
1412
+ margin-top: 4px;
1413
+ }
1414
+
1415
+ .sv-comment-item__expand-btn:hover {
1416
+ color: var(--sv-comment-text);
1417
+ }
1418
+
1419
+ /* Actions row */
1420
+ .sv-comment-item__actions {
1421
+ display: flex;
1422
+ align-items: center;
1423
+ gap: 16px;
1424
+ }
1425
+
1426
+ .sv-comment-item__time {
1427
+ font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;
1428
+ font-size: 12px;
1429
+ font-weight: 500;
1430
+ line-height: 1.2;
1431
+ color: var(--sv-comment-text-secondary);
1432
+ overflow: hidden;
1433
+ text-overflow: ellipsis;
1434
+ white-space: nowrap;
1435
+ }
1436
+
1437
+ .sv-comment-item__action-btn {
1438
+ display: flex;
1439
+ align-items: center;
1440
+ gap: 4px;
1441
+ background: none;
1442
+ border: none;
1443
+ padding: 0;
1444
+ font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;
1445
+ font-size: 12px;
1446
+ font-weight: 500;
1447
+ line-height: 1.2;
1448
+ color: var(--sv-comment-text-secondary);
1449
+ cursor: pointer;
1450
+ transition: color 0.15s ease;
1451
+ }
1452
+
1453
+ .sv-comment-item__action-btn:hover {
1454
+ color: var(--sv-comment-text);
1455
+ }
1456
+
1457
+ .sv-comment-item__action-btn--active {
1458
+ color: var(--sv-comment-like-color);
1459
+ }
1460
+
1461
+ .sv-comment-item__action-btn--active:hover {
1462
+ color: var(--sv-comment-like-color);
1463
+ }
1464
+
1465
+ .sv-comment-item__action-icon {
1466
+ width: 20px;
1467
+ height: 20px;
1468
+ }
1469
+
1470
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
1471
+ REPLIES
1472
+ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
1473
+
1474
+ .sv-comment-replies {
1475
+ margin-top: 12px;
1476
+ position: relative;
1477
+ }
1478
+
1479
+ /* Vertical connecting line */
1480
+ .sv-comment-item--has-replies::before {
1481
+ content: '';
1482
+ position: absolute;
1483
+ left: 20px;
1484
+ top: 56px;
1485
+ bottom: 0;
1486
+ width: 1px;
1487
+ background: var(--sv-comment-reply-line);
1488
+ }
1489
+
1490
+ .sv-comment-replies__toggle {
1491
+ display: flex;
1492
+ align-items: center;
1493
+ gap: 0;
1494
+ background: none;
1495
+ border: none;
1496
+ padding: 4px 0;
1497
+ cursor: pointer;
1498
+ }
1499
+
1500
+ .sv-comment-replies__toggle-line {
1501
+ width: 24px;
1502
+ height: 1px;
1503
+ background: #a3a3a3;
1504
+ margin-right: 0;
1505
+ }
1506
+
1507
+ .sv-comment-replies__toggle-text {
1508
+ font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;
1509
+ font-size: 13px;
1510
+ font-weight: 600;
1511
+ line-height: 1.4;
1512
+ color: var(--sv-comment-text-secondary);
1513
+ white-space: nowrap;
1514
+ }
1515
+
1516
+ .sv-comment-replies__toggle-icon {
1517
+ width: 20px;
1518
+ height: 20px;
1519
+ color: var(--sv-comment-text-secondary);
1520
+ }
1521
+
1522
+ .sv-comment-replies__list {
1523
+ margin-top: 12px;
1524
+ }
1525
+
1526
+ .sv-comment-reply {
1527
+ display: flex;
1528
+ gap: 6px;
1529
+ padding: 0 0 12px 0;
1530
+ position: relative;
1531
+ }
1532
+
1533
+ .sv-comment-reply__avatar {
1534
+ width: 24px;
1535
+ height: 24px;
1536
+ border-radius: 100px;
1537
+ flex-shrink: 0;
1538
+ object-fit: cover;
1539
+ background: var(--sv-comment-avatar-bg);
1540
+ }
1541
+
1542
+ .sv-comment-reply__mention {
1543
+ color: var(--sv-comment-mention-color);
1544
+ font-weight: 500;
1545
+ }
1546
+
1547
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
1548
+ INPUT AREA
1549
+ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
1550
+
1551
+ .sv-comment-sheet__input-area {
1552
+ padding: 0 16px 36px 16px;
1553
+ flex-shrink: 0;
1554
+ }
1555
+
1556
+ /* Guest mode - login prompt instead of input */
1557
+ .sv-comment-input-guest {
1558
+ padding: 16px;
1559
+ border-top: 1px solid var(--sv-comment-border);
1560
+ display: flex;
1561
+ align-items: center;
1562
+ justify-content: center;
1563
+ cursor: pointer;
1564
+ background: var(--sv-comment-bg);
1565
+ color: var(--sv-comment-primary);
1566
+ font-weight: 600;
1567
+ font-size: 14px;
1568
+ width: 100%;
1569
+ transition: background 0.15s ease;
1570
+ }
1571
+
1572
+ .sv-comment-input-guest:hover {
1573
+ background: rgba(22, 77, 142, 0.05);
1574
+ }
1575
+
1576
+ .sv-comment-input-guest:active {
1577
+ background: rgba(22, 77, 142, 0.1);
1578
+ }
1579
+
1580
+ .sv-comment-sheet__reply-to {
1581
+ display: flex;
1582
+ align-items: center;
1583
+ justify-content: space-between;
1584
+ padding: 4px 0;
1585
+ margin-bottom: 8px;
1586
+ font-size: 12px;
1587
+ color: var(--sv-comment-text-secondary);
1588
+ }
1589
+
1590
+ .sv-comment-sheet__reply-to-author-name {
1591
+ font-size: 12px;
1592
+ color: var(--sv-comment-text);
1593
+ font-weight: 500;
1594
+ }
1595
+
1596
+ .sv-comment-sheet__reply-to-clear {
1597
+ background: none;
1598
+ border: none;
1599
+ padding: 4px;
1600
+ color: var(--sv-comment-text-secondary);
1601
+ cursor: pointer;
1602
+ font-size: 12px;
1603
+ }
1604
+
1605
+ .sv-comment-sheet__input-wrapper {
1606
+ display: flex;
1607
+ align-items: center;
1608
+ gap: 8px;
1609
+ height: 44px;
1610
+ padding: 16px;
1611
+ background: var(--sv-comment-bg);
1612
+ border: 1px solid var(--sv-comment-input-border);
1613
+ border-radius: 12px;
1614
+ backdrop-filter: blur(50px);
1615
+ }
1616
+
1617
+ .sv-comment-sheet__input-left {
1618
+ display: flex;
1619
+ align-items: center;
1620
+ gap: 8px;
1621
+ flex: 1;
1622
+ min-width: 0;
1623
+ }
1624
+
1625
+ .sv-comment-sheet__media-btn {
1626
+ display: flex;
1627
+ align-items: center;
1628
+ justify-content: center;
1629
+ background: none;
1630
+ border: none;
1631
+ padding: 0;
1632
+ cursor: pointer;
1633
+ flex-shrink: 0;
1634
+ }
1635
+
1636
+ .sv-comment-sheet__media-btn svg {
1637
+ width: 20px;
1638
+ height: 20px;
1639
+ }
1640
+
1641
+ .sv-comment-sheet__input {
1642
+ flex: 1;
1643
+ background: none;
1644
+ border: none;
1645
+ outline: none;
1646
+ resize: none;
1647
+ font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;
1648
+ font-size: 12px;
1649
+ font-style: italic;
1650
+ font-weight: 400;
1651
+ line-height: 1.4;
1652
+ color: var(--sv-comment-text);
1653
+ padding: 0;
1654
+ min-width: 0;
1655
+ }
1656
+
1657
+ .sv-comment-sheet__input::placeholder {
1658
+ color: var(--sv-comment-text-secondary);
1659
+ }
1660
+
1661
+ .sv-comment-sheet__input:not(:placeholder-shown) {
1662
+ font-style: normal;
1663
+ }
1664
+
1665
+ .sv-comment-sheet__emoji-btn {
1666
+ display: flex;
1667
+ align-items: center;
1668
+ justify-content: center;
1669
+ background: none;
1670
+ border: none;
1671
+ padding: 0;
1672
+ cursor: pointer;
1673
+ flex-shrink: 0;
1674
+ }
1675
+
1676
+ .sv-comment-sheet__emoji-btn svg {
1677
+ width: 20px;
1678
+ height: 20px;
1679
+ color: var(--sv-comment-primary);
1680
+ }
1681
+
1682
+ /* Hidden emoji bar (can be toggled) */
1683
+ .sv-comment-sheet__emoji-bar {
1684
+ display: none;
1685
+ gap: 8px;
1686
+ padding: 8px 0;
1687
+ overflow-x: auto;
1688
+ -webkit-overflow-scrolling: touch;
1689
+ }
1690
+
1691
+ .sv-comment-sheet__emoji-bar--visible {
1692
+ display: flex;
1693
+ }
1694
+
1695
+ .sv-comment-sheet__emoji-bar::-webkit-scrollbar {
1696
+ display: none;
1697
+ }
1698
+
1699
+ .sv-comment-sheet__emoji-bar-btn {
1700
+ background: none;
1701
+ border: none;
1702
+ padding: 4px;
1703
+ font-size: 20px;
1704
+ cursor: pointer;
1705
+ border-radius: 4px;
1706
+ transition: background 0.15s ease;
1707
+ }
1708
+
1709
+ .sv-comment-sheet__emoji-bar-btn:hover {
1710
+ background: rgba(0, 0, 0, 0.05);
1711
+ }
1712
+
1713
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
1714
+ STATES
1715
+ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
1716
+
1717
+ .sv-comment-sheet__loading {
1718
+ display: flex;
1719
+ flex-direction: column;
1720
+ align-items: center;
1721
+ justify-content: center;
1722
+ padding: 32px;
1723
+ color: var(--sv-comment-text-secondary);
1724
+ }
1725
+
1726
+ .sv-comment-sheet__loading-spinner {
1727
+ width: 24px;
1728
+ height: 24px;
1729
+ border: 2px solid rgba(0, 0, 0, 0.1);
1730
+ border-top-color: var(--sv-comment-primary);
1731
+ border-radius: 50%;
1732
+ animation: sv-comment-spin 0.8s linear infinite;
1733
+ }
1734
+
1735
+ @keyframes sv-comment-spin {
1736
+ to { transform: rotate(360deg); }
1737
+ }
1738
+
1739
+ .sv-comment-sheet__empty {
1740
+ display: flex;
1741
+ flex-direction: column;
1742
+ align-items: center;
1743
+ justify-content: center;
1744
+ padding: 32px;
1745
+ text-align: center;
1746
+ }
1747
+
1748
+ .sv-comment-sheet__empty-icon {
1749
+ font-size: 48px;
1750
+ margin-bottom: 12px;
1751
+ }
1752
+
1753
+ .sv-comment-sheet__empty-text {
1754
+ color: var(--sv-comment-text-secondary);
1755
+ font-size: 14px;
1756
+ }
1757
+
1758
+ .sv-comment-sheet__error {
1759
+ display: flex;
1760
+ flex-direction: column;
1761
+ align-items: center;
1762
+ padding: 32px;
1763
+ text-align: center;
1764
+ color: var(--sv-comment-like-color);
1765
+ }
1766
+
1767
+ .sv-comment-sheet__error-btn {
1768
+ margin-top: 12px;
1769
+ padding: 8px 16px;
1770
+ background: rgba(0, 0, 0, 0.05);
1771
+ border: none;
1772
+ border-radius: 8px;
1773
+ color: var(--sv-comment-text);
1774
+ cursor: pointer;
1775
+ }
1776
+
1777
+ /* Load more */
1778
+ .sv-comment-sheet__load-more {
1779
+ display: flex;
1780
+ justify-content: center;
1781
+ padding: 12px;
1782
+ }
1783
+
1784
+ .sv-comment-sheet__load-more-btn {
1785
+ background: none;
1786
+ border: none;
1787
+ padding: 8px 16px;
1788
+ color: var(--sv-comment-text-secondary);
1789
+ cursor: pointer;
1790
+ font-size: 13px;
1791
+ }
1792
+
1793
+ .sv-comment-sheet__load-more-btn:hover {
1794
+ color: var(--sv-comment-text);
1795
+ }
1796
+
1797
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
1798
+ COMMENT MENU (Dropdown)
1799
+ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
1800
+
1801
+ .sv-comment-menu {
1802
+ position: relative;
1803
+ }
1804
+
1805
+ .sv-comment-menu__trigger {
1806
+ display: flex;
1807
+ align-items: center;
1808
+ justify-content: center;
1809
+ background: none;
1810
+ border: none;
1811
+ padding: 4px;
1812
+ cursor: pointer;
1813
+ color: var(--sv-comment-text-secondary);
1814
+ border-radius: 4px;
1815
+ transition: background 0.15s ease;
1816
+ }
1817
+
1818
+ .sv-comment-menu__trigger:hover {
1819
+ background: rgba(0, 0, 0, 0.05);
1820
+ }
1821
+
1822
+ .sv-comment-menu__icon {
1823
+ width: 20px;
1824
+ height: 20px;
1825
+ }
1826
+
1827
+ .sv-comment-menu__dropdown {
1828
+ position: absolute;
1829
+ top: 100%;
1830
+ right: 0;
1831
+ margin-top: 4px;
1832
+ min-width: 140px;
1833
+ background: var(--sv-comment-bg);
1834
+ border: 1px solid var(--sv-comment-border);
1835
+ border-radius: 8px;
1836
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1837
+ z-index: 10;
1838
+ overflow: hidden;
1839
+ animation: sv-menu-fade-in 0.15s ease;
1840
+ }
1841
+
1842
+ @keyframes sv-menu-fade-in {
1843
+ from { opacity: 0; transform: translateY(-4px); }
1844
+ to { opacity: 1; transform: translateY(0); }
1845
+ }
1846
+
1847
+ .sv-comment-menu__item {
1848
+ display: flex;
1849
+ align-items: center;
1850
+ gap: 8px;
1851
+ width: 100%;
1852
+ padding: 10px 12px;
1853
+ background: none;
1854
+ border: none;
1855
+ cursor: pointer;
1856
+ font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;
1857
+ font-size: 14px;
1858
+ font-weight: 500;
1859
+ color: var(--sv-comment-text);
1860
+ text-align: left;
1861
+ transition: background 0.15s ease;
1862
+ }
1863
+
1864
+ .sv-comment-menu__item:hover {
1865
+ background: rgba(0, 0, 0, 0.05);
1866
+ }
1867
+
1868
+ .sv-comment-menu__item--danger {
1869
+ color: var(--sv-comment-like-color);
1870
+ }
1871
+
1872
+ .sv-comment-menu__item--danger:hover {
1873
+ background: rgba(255, 67, 78, 0.08);
1874
+ }
1875
+
1876
+ .sv-comment-menu__item-icon {
1877
+ width: 18px;
1878
+ height: 18px;
1879
+ flex-shrink: 0;
1880
+ }
1881
+
1882
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
1883
+ DELETE CONFIRMATION DIALOG
1884
+ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
1885
+
1886
+ .sv-comment-dialog-overlay {
1887
+ position: fixed;
1888
+ inset: 0;
1889
+ display: flex;
1890
+ align-items: center;
1891
+ justify-content: center;
1892
+ background: rgba(0, 0, 0, 0.5);
1893
+ z-index: var(--sv-comment-modal-z-index, 1100);
1894
+ animation: sv-dialog-overlay-fade-in 0.2s ease;
1895
+ }
1896
+
1897
+ @keyframes sv-dialog-overlay-fade-in {
1898
+ from { opacity: 0; }
1899
+ to { opacity: 1; }
1900
+ }
1901
+
1902
+ .sv-comment-dialog {
1903
+ background: var(--sv-comment-bg);
1904
+ border-radius: 16px;
1905
+ padding: 24px;
1906
+ max-width: 300px;
1907
+ width: calc(100% - 48px);
1908
+ text-align: center;
1909
+ animation: sv-dialog-scale-in 0.2s ease;
1910
+ }
1911
+
1912
+ @keyframes sv-dialog-scale-in {
1913
+ from { opacity: 0; transform: scale(0.95); }
1914
+ to { opacity: 1; transform: scale(1); }
1915
+ }
1916
+
1917
+ .sv-comment-dialog__title {
1918
+ font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;
1919
+ font-size: 17px;
1920
+ font-weight: 600;
1921
+ color: var(--sv-comment-text);
1922
+ margin: 0 0 8px 0;
1923
+ }
1924
+
1925
+ .sv-comment-dialog__message {
1926
+ font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;
1927
+ font-size: 14px;
1928
+ color: var(--sv-comment-text-secondary);
1929
+ margin: 0 0 20px 0;
1930
+ line-height: 1.4;
1931
+ }
1932
+
1933
+ .sv-comment-dialog__actions {
1934
+ display: flex;
1935
+ gap: 12px;
1936
+ }
1937
+
1938
+ .sv-comment-dialog__btn {
1939
+ flex: 1;
1940
+ padding: 12px 16px;
1941
+ border: none;
1942
+ border-radius: 10px;
1943
+ font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;
1944
+ font-size: 15px;
1945
+ font-weight: 600;
1946
+ cursor: pointer;
1947
+ transition: opacity 0.15s ease;
1948
+ }
1949
+
1950
+ .sv-comment-dialog__btn:disabled {
1951
+ opacity: 0.6;
1952
+ cursor: not-allowed;
1953
+ }
1954
+
1955
+ .sv-comment-dialog__btn--cancel {
1956
+ background: rgba(0, 0, 0, 0.06);
1957
+ color: var(--sv-comment-text);
1958
+ }
1959
+
1960
+ .sv-comment-dialog__btn--cancel:hover:not(:disabled) {
1961
+ background: rgba(0, 0, 0, 0.1);
1962
+ }
1963
+
1964
+ .sv-comment-dialog__btn--danger {
1965
+ background: var(--sv-comment-like-color);
1966
+ color: #ffffff;
1967
+ }
1968
+
1969
+ .sv-comment-dialog__btn--danger:hover:not(:disabled) {
1970
+ opacity: 0.9;
1971
+ }
1972
+
1973
+ /* Legacy classes (keep for backwards compatibility) */
1974
+ .sv-comment-delete-confirm {
1975
+ position: fixed;
1976
+ inset: 0;
1977
+ display: flex;
1978
+ align-items: center;
1979
+ justify-content: center;
1980
+ background: rgba(0, 0, 0, 0.5);
1981
+ z-index: var(--sv-comment-modal-z-index, 1100);
1982
+ }
1983
+
1984
+ .sv-comment-delete-confirm__dialog {
1985
+ background: var(--sv-comment-bg);
1986
+ border-radius: 12px;
1987
+ padding: 16px;
1988
+ max-width: 280px;
1989
+ text-align: center;
1990
+ }
1991
+
1992
+ .sv-comment-delete-confirm__title {
1993
+ font-size: 16px;
1994
+ font-weight: 600;
1995
+ color: var(--sv-comment-text);
1996
+ margin-bottom: 8px;
1997
+ }
1998
+
1999
+ .sv-comment-delete-confirm__text {
2000
+ font-size: 14px;
2001
+ color: var(--sv-comment-text-secondary);
2002
+ margin-bottom: 16px;
2003
+ }
2004
+
2005
+ .sv-comment-delete-confirm__actions {
2006
+ display: flex;
2007
+ gap: 8px;
2008
+ }
2009
+
2010
+ .sv-comment-delete-confirm__btn {
2011
+ flex: 1;
2012
+ padding: 8px 12px;
2013
+ border: none;
2014
+ border-radius: 8px;
2015
+ font-size: 14px;
2016
+ font-weight: 600;
2017
+ cursor: pointer;
2018
+ }
2019
+
2020
+ .sv-comment-delete-confirm__btn--cancel {
2021
+ background: rgba(0, 0, 0, 0.05);
2022
+ color: var(--sv-comment-text);
2023
+ }
2024
+
2025
+ .sv-comment-delete-confirm__btn--delete {
2026
+ background: var(--sv-comment-like-color);
2027
+ color: #ffffff;
2028
+ }
2029
+
2030
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
2031
+ SKELETON LOADING
2032
+ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
2033
+
2034
+ @keyframes sv-skeleton-shimmer {
2035
+ 0% { background-position: -200% 0; }
2036
+ 100% { background-position: 200% 0; }
2037
+ }
2038
+
2039
+ .sv-comment-skeleton-list {
2040
+ display: flex;
2041
+ flex-direction: column;
2042
+ }
2043
+
2044
+ .sv-comment-skeleton {
2045
+ animation: sv-skeleton-fade-in 0.3s ease;
2046
+ }
2047
+
2048
+ @keyframes sv-skeleton-fade-in {
2049
+ from { opacity: 0; }
2050
+ to { opacity: 1; }
2051
+ }
2052
+
2053
+ .sv-comment-skeleton__avatar {
2054
+ width: 40px;
2055
+ height: 40px;
2056
+ border-radius: 50%;
2057
+ background: linear-gradient(
2058
+ 90deg,
2059
+ rgba(0, 0, 0, 0.04) 25%,
2060
+ rgba(0, 0, 0, 0.08) 50%,
2061
+ rgba(0, 0, 0, 0.04) 75%
2062
+ );
2063
+ background-size: 200% 100%;
2064
+ animation: sv-skeleton-shimmer 1.5s ease-in-out infinite;
2065
+ }
2066
+
2067
+ .sv-comment-skeleton__content {
2068
+ flex: 1;
2069
+ min-width: 0;
2070
+ display: flex;
2071
+ flex-direction: column;
2072
+ gap: 8px;
2073
+ }
2074
+
2075
+ .sv-comment-skeleton__header {
2076
+ display: flex;
2077
+ align-items: center;
2078
+ gap: 12px;
2079
+ }
2080
+
2081
+ .sv-comment-skeleton__author {
2082
+ width: 80px;
2083
+ height: 14px;
2084
+ border-radius: 4px;
2085
+ background: linear-gradient(
2086
+ 90deg,
2087
+ rgba(0, 0, 0, 0.04) 25%,
2088
+ rgba(0, 0, 0, 0.08) 50%,
2089
+ rgba(0, 0, 0, 0.04) 75%
2090
+ );
2091
+ background-size: 200% 100%;
2092
+ animation: sv-skeleton-shimmer 1.5s ease-in-out infinite;
2093
+ animation-delay: 0.1s;
2094
+ }
2095
+
2096
+ .sv-comment-skeleton__time {
2097
+ width: 40px;
2098
+ height: 12px;
2099
+ border-radius: 4px;
2100
+ background: linear-gradient(
2101
+ 90deg,
2102
+ rgba(0, 0, 0, 0.04) 25%,
2103
+ rgba(0, 0, 0, 0.08) 50%,
2104
+ rgba(0, 0, 0, 0.04) 75%
2105
+ );
2106
+ background-size: 200% 100%;
2107
+ animation: sv-skeleton-shimmer 1.5s ease-in-out infinite;
2108
+ animation-delay: 0.15s;
2109
+ }
2110
+
2111
+ .sv-comment-skeleton__text {
2112
+ display: flex;
2113
+ flex-direction: column;
2114
+ gap: 4px;
2115
+ }
2116
+
2117
+ .sv-comment-skeleton__line {
2118
+ height: 14px;
2119
+ border-radius: 4px;
2120
+ background: linear-gradient(
2121
+ 90deg,
2122
+ rgba(0, 0, 0, 0.04) 25%,
2123
+ rgba(0, 0, 0, 0.08) 50%,
2124
+ rgba(0, 0, 0, 0.04) 75%
2125
+ );
2126
+ background-size: 200% 100%;
2127
+ animation: sv-skeleton-shimmer 1.5s ease-in-out infinite;
2128
+ }
2129
+
2130
+ .sv-comment-skeleton__line--full {
2131
+ width: 100%;
2132
+ animation-delay: 0.2s;
2133
+ }
2134
+
2135
+ .sv-comment-skeleton__line--medium {
2136
+ width: 65%;
2137
+ animation-delay: 0.25s;
2138
+ }
2139
+
2140
+ .sv-comment-skeleton__actions {
2141
+ display: flex;
2142
+ align-items: center;
2143
+ gap: 16px;
2144
+ margin-top: 4px;
2145
+ }
2146
+
2147
+ .sv-comment-skeleton__action {
2148
+ width: 50px;
2149
+ height: 12px;
2150
+ border-radius: 4px;
2151
+ background: linear-gradient(
2152
+ 90deg,
2153
+ rgba(0, 0, 0, 0.04) 25%,
2154
+ rgba(0, 0, 0, 0.08) 50%,
2155
+ rgba(0, 0, 0, 0.04) 75%
2156
+ );
2157
+ background-size: 200% 100%;
2158
+ animation: sv-skeleton-shimmer 1.5s ease-in-out infinite;
2159
+ animation-delay: 0.3s;
2160
+ }
2161
+ `;
2162
+ function AngleDownIcon({ className }) {
2163
+ return /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", className, viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsx(
2164
+ "path",
2165
+ {
2166
+ fillRule: "evenodd",
2167
+ d: "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
2168
+ clipRule: "evenodd"
2169
+ }
2170
+ ) });
2171
+ }
2172
+ function CloseIcon2({ className, style }) {
2173
+ return /* @__PURE__ */ jsxs(
2174
+ "svg",
2175
+ {
2176
+ "aria-hidden": "true",
2177
+ className,
2178
+ style,
2179
+ viewBox: "0 0 24 24",
2180
+ fill: "none",
2181
+ stroke: "currentColor",
2182
+ strokeWidth: "2",
2183
+ strokeLinecap: "round",
2184
+ strokeLinejoin: "round",
2185
+ children: [
2186
+ /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
2187
+ /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
2188
+ ]
2189
+ }
2190
+ );
2191
+ }
2192
+ function formatCount2(count) {
2193
+ if (count >= 1e6) {
2194
+ return `${(count / 1e6).toFixed(1)}M`;
2195
+ }
2196
+ if (count >= 1e3) {
2197
+ return `${(count / 1e3).toFixed(1)}K`;
2198
+ }
2199
+ return String(count);
2200
+ }
2201
+ var SheetHeader = memo(function SheetHeader2({
2202
+ titleLabel = "Comments",
2203
+ showHandle = false,
2204
+ showSort = true,
2205
+ onSortClick,
2206
+ closeIcon,
2207
+ className,
2208
+ sortAriaLabel = "Sort comments",
2209
+ closeAriaLabel = "Close comments"
2210
+ }) {
2211
+ const { state, onClose, initialCount } = useCommentSheetContext();
2212
+ const totalCount = state.totalCount > 0 ? state.totalCount : initialCount ?? 0;
2213
+ return /* @__PURE__ */ jsxs("div", { className: clsx("sv-comment-sheet__header", className), children: [
2214
+ showHandle && /* @__PURE__ */ jsx("div", { className: "sv-comment-sheet__header-handle" }),
2215
+ /* @__PURE__ */ jsxs("div", { className: "sv-comment-sheet__header-left", children: [
2216
+ /* @__PURE__ */ jsxs("h2", { className: "sv-comment-sheet__title", children: [
2217
+ formatCount2(totalCount),
2218
+ " ",
2219
+ titleLabel
2220
+ ] }),
2221
+ showSort && /* @__PURE__ */ jsx(
2222
+ "button",
2223
+ {
2224
+ type: "button",
2225
+ className: "sv-comment-sheet__sort-btn",
2226
+ onClick: onSortClick,
2227
+ "aria-label": sortAriaLabel,
2228
+ children: /* @__PURE__ */ jsx(AngleDownIcon, {})
2229
+ }
2230
+ )
2231
+ ] }),
2232
+ /* @__PURE__ */ jsx(
2233
+ "button",
2234
+ {
2235
+ type: "button",
2236
+ className: "sv-comment-sheet__close-btn",
2237
+ onClick: onClose,
2238
+ "aria-label": closeAriaLabel,
2239
+ children: closeIcon ?? /* @__PURE__ */ jsx(CloseIcon2, {})
2240
+ }
2241
+ )
2242
+ ] });
2243
+ });
2244
+ SheetHeader.displayName = "SheetHeader";
2245
+ var cssInjected = false;
2246
+ function injectCSS() {
2247
+ if (cssInjected || typeof document === "undefined") return;
2248
+ const styleId = "sv-comment-sheet-styles";
2249
+ if (!document.getElementById(styleId)) {
2250
+ const style = document.createElement("style");
2251
+ style.id = styleId;
2252
+ style.textContent = COMMENT_SHEET_CSS;
2253
+ document.head.appendChild(style);
2254
+ }
2255
+ cssInjected = true;
2256
+ }
2257
+ var DEFAULT_CONFIG = {
2258
+ pageSize: 20,
2259
+ replyPageSize: 10,
2260
+ cacheTTL: 5 * 60 * 1e3,
2261
+ // 5 minutes
2262
+ repliesAutoExpandThreshold: 1,
2263
+ repliesCollapseLimit: 3,
2264
+ textMaxLines: 3,
2265
+ inputMaxLength: 500,
2266
+ enableOptimisticUI: true,
2267
+ requireDeleteConfirm: true
2268
+ };
2269
+ var ANIMATION_DURATION = 400;
2270
+ var DEFAULT_I18N = {
2271
+ expandText: "See more",
2272
+ collapseText: "See less",
2273
+ viewRepliesText: "View {count} more replies",
2274
+ hideRepliesText: "Hide replies",
2275
+ loadRepliesText: "Load replies",
2276
+ viewMoreRepliesText: "View more replies"
2277
+ };
2278
+ var CommentSheetHeadless = memo(function CommentSheetHeadless2({
2279
+ isOpen,
2280
+ onClose,
2281
+ videoId,
2282
+ state,
2283
+ actions,
2284
+ config: configOverride,
2285
+ initialCount,
2286
+ children,
2287
+ className,
2288
+ backdropClassName,
2289
+ closeOnBackdropClick = true,
2290
+ closeOnEscape = true,
2291
+ enableDragToDismiss = true,
2292
+ dragCloseThreshold = 150,
2293
+ i18n: i18nOverride
2294
+ }) {
2295
+ useEffect(() => {
2296
+ injectCSS();
2297
+ }, []);
2298
+ const sheetRef = useRef(null);
2299
+ const dragStartY = useRef(0);
2300
+ const currentTranslateY = useRef(0);
2301
+ const isDragging = useRef(false);
2302
+ const [isClosing, setIsClosing] = useState(false);
2303
+ const isDragClosingRef = useRef(false);
2304
+ const closeTimeoutRef = useRef(null);
2305
+ const openedAtRef = useRef(0);
2306
+ const config = useMemo(() => ({ ...DEFAULT_CONFIG, ...configOverride }), [configOverride]);
2307
+ const i18n = useMemo(() => ({ ...DEFAULT_I18N, ...i18nOverride }), [i18nOverride]);
2308
+ const handleClose = useCallback(() => {
2309
+ if (isClosing) return;
2310
+ const timeSinceOpen = Date.now() - openedAtRef.current;
2311
+ if (timeSinceOpen < 100) return;
2312
+ setIsClosing(true);
2313
+ closeTimeoutRef.current = setTimeout(() => {
2314
+ setIsClosing(false);
2315
+ onClose();
2316
+ }, ANIMATION_DURATION);
2317
+ }, [isClosing, onClose]);
2318
+ useEffect(() => {
2319
+ return () => {
2320
+ if (closeTimeoutRef.current) {
2321
+ clearTimeout(closeTimeoutRef.current);
2322
+ }
2323
+ };
2324
+ }, []);
2325
+ useEffect(() => {
2326
+ if (isOpen) {
2327
+ openedAtRef.current = Date.now();
2328
+ setIsClosing(false);
2329
+ if (closeTimeoutRef.current) {
2330
+ clearTimeout(closeTimeoutRef.current);
2331
+ closeTimeoutRef.current = null;
2332
+ }
2333
+ }
2334
+ }, [isOpen]);
2335
+ const [replyTarget, setReplyTarget] = useState(null);
2336
+ useEffect(() => {
2337
+ if (!isOpen) {
2338
+ setReplyTarget(null);
2339
+ }
2340
+ }, [isOpen]);
2341
+ useEffect(() => {
2342
+ if (!closeOnEscape || !isOpen) return;
2343
+ const handleEscapeKey = (e) => {
2344
+ if (e.key === "Escape") {
2345
+ handleClose();
2346
+ }
2347
+ };
2348
+ document.addEventListener("keydown", handleEscapeKey);
2349
+ return () => document.removeEventListener("keydown", handleEscapeKey);
2350
+ }, [closeOnEscape, isOpen, handleClose]);
2351
+ const handleBackdropClick = useCallback(
2352
+ (e) => {
2353
+ e.stopPropagation();
2354
+ if (closeOnBackdropClick && e.target === e.currentTarget) {
2355
+ handleClose();
2356
+ }
2357
+ },
2358
+ [closeOnBackdropClick, handleClose]
2359
+ );
2360
+ useEffect(() => {
2361
+ if (!isOpen) return;
2362
+ const originalOverflow = document.body.style.overflow;
2363
+ document.body.style.overflow = "hidden";
2364
+ document.body.classList.add("sv-comment-sheet-open");
2365
+ const blockTouchMove = (e) => {
2366
+ const target = e.target;
2367
+ const isInsideSheet = target.closest(".sv-comment-sheet");
2368
+ if (!isInsideSheet) {
2369
+ e.preventDefault();
2370
+ e.stopPropagation();
2371
+ }
2372
+ };
2373
+ document.addEventListener("touchmove", blockTouchMove, { passive: false, capture: true });
2374
+ return () => {
2375
+ document.body.style.overflow = originalOverflow;
2376
+ document.body.classList.remove("sv-comment-sheet-open");
2377
+ document.removeEventListener("touchmove", blockTouchMove, { capture: true });
2378
+ };
2379
+ }, [isOpen]);
2380
+ const dragSourceRef = useRef(null);
2381
+ const isListAtTop = useCallback(() => {
2382
+ const list = sheetRef.current?.querySelector(".sv-comment-sheet__list");
2383
+ if (!list) return true;
2384
+ return list.scrollTop <= 0;
2385
+ }, []);
2386
+ useEffect(() => {
2387
+ if (!isOpen || !sheetRef.current) return;
2388
+ sheetRef.current.style.transform = "";
2389
+ sheetRef.current.style.transition = "";
2390
+ sheetRef.current.style.animation = "";
2391
+ currentTranslateY.current = 0;
2392
+ isDragging.current = false;
2393
+ dragSourceRef.current = null;
2394
+ isDragClosingRef.current = false;
2395
+ }, [isOpen]);
2396
+ const getDragSource = useCallback(
2397
+ (target) => {
2398
+ const isInput = target.closest(".sv-comment-sheet__input-container");
2399
+ if (isInput) return null;
2400
+ const isHeader = target.closest(".sv-comment-sheet__header");
2401
+ if (isHeader) return "header";
2402
+ const isList = target.closest(".sv-comment-sheet__list");
2403
+ if (isList && isListAtTop()) return "overscroll";
2404
+ return null;
2405
+ },
2406
+ [isListAtTop]
2407
+ );
2408
+ const animateClose = useCallback(
2409
+ (sheet) => {
2410
+ isDragClosingRef.current = true;
2411
+ setIsClosing(true);
2412
+ sheet.style.transition = `transform ${ANIMATION_DURATION}ms cubic-bezier(0.32, 0.72, 0, 1)`;
2413
+ sheet.style.transform = "translateY(100%)";
2414
+ closeTimeoutRef.current = setTimeout(() => {
2415
+ sheet.style.transition = "";
2416
+ sheet.style.transform = "";
2417
+ sheet.style.animation = "";
2418
+ isDragClosingRef.current = false;
2419
+ setIsClosing(false);
2420
+ onClose();
2421
+ }, ANIMATION_DURATION);
2422
+ },
2423
+ [onClose]
2424
+ );
2425
+ const animateSnapBack = useCallback((sheet) => {
2426
+ sheet.style.transition = `transform ${ANIMATION_DURATION}ms cubic-bezier(0.32, 0.72, 0, 1)`;
2427
+ sheet.style.transform = "translateY(0)";
2428
+ setTimeout(() => {
2429
+ sheet.style.transition = "";
2430
+ sheet.style.transform = "";
2431
+ }, ANIMATION_DURATION);
2432
+ }, []);
2433
+ useEffect(() => {
2434
+ const sheet = sheetRef.current;
2435
+ if (!sheet || !isOpen || !enableDragToDismiss) return;
2436
+ const onTouchStart = (e) => {
2437
+ e.stopPropagation();
2438
+ const source = getDragSource(e.target);
2439
+ if (!source) return;
2440
+ dragSourceRef.current = source;
2441
+ isDragging.current = true;
2442
+ dragStartY.current = e.touches[0]?.clientY ?? 0;
2443
+ currentTranslateY.current = 0;
2444
+ sheet.style.animation = "none";
2445
+ sheet.style.transition = "none";
2446
+ void sheet.offsetHeight;
2447
+ };
2448
+ const onTouchMove = (e) => {
2449
+ e.stopPropagation();
2450
+ const clientY = e.touches[0]?.clientY ?? 0;
2451
+ const deltaY = clientY - dragStartY.current;
2452
+ if (dragSourceRef.current === "overscroll" && (deltaY <= 0 || !isListAtTop())) {
2453
+ isDragging.current = false;
2454
+ return;
2455
+ }
2456
+ if (!isDragging.current) return;
2457
+ currentTranslateY.current = Math.max(0, deltaY);
2458
+ if (currentTranslateY.current > 0) {
2459
+ e.preventDefault();
2460
+ }
2461
+ sheet.style.transform = `translateY(${currentTranslateY.current}px)`;
2462
+ };
2463
+ const onTouchEnd = (e) => {
2464
+ e.stopPropagation();
2465
+ dragSourceRef.current = null;
2466
+ if (!isDragging.current) return;
2467
+ isDragging.current = false;
2468
+ const dragDistance = currentTranslateY.current;
2469
+ currentTranslateY.current = 0;
2470
+ if (dragDistance > dragCloseThreshold) {
2471
+ animateClose(sheet);
2472
+ } else if (dragDistance > 0) {
2473
+ animateSnapBack(sheet);
2474
+ }
2475
+ };
2476
+ sheet.addEventListener("touchstart", onTouchStart, { passive: false });
2477
+ sheet.addEventListener("touchmove", onTouchMove, { passive: false });
2478
+ sheet.addEventListener("touchend", onTouchEnd, { passive: false });
2479
+ return () => {
2480
+ sheet.removeEventListener("touchstart", onTouchStart);
2481
+ sheet.removeEventListener("touchmove", onTouchMove);
2482
+ sheet.removeEventListener("touchend", onTouchEnd);
2483
+ };
2484
+ }, [
2485
+ isOpen,
2486
+ enableDragToDismiss,
2487
+ dragCloseThreshold,
2488
+ isListAtTop,
2489
+ getDragSource,
2490
+ animateClose,
2491
+ animateSnapBack
2492
+ ]);
2493
+ const contextValue = useMemo(
2494
+ () => ({
2495
+ state,
2496
+ actions,
2497
+ videoId,
2498
+ config,
2499
+ isOpen,
2500
+ onClose: handleClose,
2501
+ // Use animated close handler
2502
+ replyTarget,
2503
+ setReplyTarget,
2504
+ initialCount,
2505
+ i18n
2506
+ }),
2507
+ [state, actions, videoId, config, isOpen, handleClose, replyTarget, initialCount, i18n]
2508
+ );
2509
+ const defaultChildren = /* @__PURE__ */ jsxs(Fragment, { children: [
2510
+ /* @__PURE__ */ jsx(SheetHeader, {}),
2511
+ /* @__PURE__ */ jsx(CommentList, {}),
2512
+ /* @__PURE__ */ jsx(CommentInput, {})
2513
+ ] });
2514
+ const handleKeyDown = useCallback(
2515
+ (e) => {
2516
+ if (e.key === "Escape") {
2517
+ handleClose();
2518
+ }
2519
+ },
2520
+ [handleClose]
2521
+ );
2522
+ return /* @__PURE__ */ jsxs(CommentSheetContext.Provider, { value: contextValue, children: [
2523
+ /* @__PURE__ */ jsx(
2524
+ "div",
2525
+ {
2526
+ className: clsx(
2527
+ "sv-comment-sheet-backdrop",
2528
+ isOpen && !isClosing && "sv-comment-sheet-backdrop--open",
2529
+ backdropClassName
2530
+ ),
2531
+ onClick: handleBackdropClick,
2532
+ onKeyDown: handleKeyDown,
2533
+ onPointerDown: (e) => e.stopPropagation(),
2534
+ onPointerUp: (e) => e.stopPropagation(),
2535
+ onTouchStart: (e) => e.stopPropagation(),
2536
+ onTouchMove: (e) => e.stopPropagation(),
2537
+ onTouchEnd: (e) => e.stopPropagation(),
2538
+ role: "presentation"
2539
+ }
2540
+ ),
2541
+ /* @__PURE__ */ jsx(
2542
+ "div",
2543
+ {
2544
+ ref: sheetRef,
2545
+ className: clsx(
2546
+ "sv-comment-sheet",
2547
+ isOpen && "sv-comment-sheet--open",
2548
+ // Keep --open while closing for proper animation
2549
+ isClosing && !isDragClosingRef.current && "sv-comment-sheet--closing",
2550
+ // Skip CSS animation for drag close
2551
+ className
2552
+ ),
2553
+ "aria-label": "Comments",
2554
+ "aria-hidden": !isOpen,
2555
+ onKeyDown: handleKeyDown,
2556
+ tabIndex: isOpen ? 0 : -1,
2557
+ onClick: (e) => e.stopPropagation(),
2558
+ onPointerDown: (e) => e.stopPropagation(),
2559
+ onPointerUp: (e) => e.stopPropagation(),
2560
+ children: children ?? defaultChildren
2561
+ }
2562
+ )
2563
+ ] });
2564
+ });
2565
+ CommentSheetHeadless.displayName = "CommentSheetHeadless";
2566
+ var CommentSheet = Object.assign(CommentSheetHeadless, {
2567
+ Header: SheetHeader,
2568
+ List: CommentList,
2569
+ Input: CommentInput,
2570
+ Item: CommentItemComponent
2571
+ });
2572
+
2573
+ export { COMMENT_SHEET_CSS, CommentInput, CommentItemComponent, CommentItemSkeleton, CommentList, CommentListSkeleton, CommentMenu, CommentSheet, CommentSheetContext, CommentSheetHeadless, DeleteConfirmDialog, SheetHeader, useCommentMenuContext, useCommentSheetContext, useOptionalCommentSheetContext };