@xhub-short/ui 0.1.0-beta.15 → 0.1.0-beta.17

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.
@@ -216,4 +216,4 @@ declare const CommentSheet: react.NamedExoticComponent<CommentSheetHeadlessProps
216
216
  */
217
217
  declare const COMMENT_SHEET_CSS = "\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n CSS VARIABLES (Light Theme)\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n:root {\n /* Primary colors */\n --sv-comment-primary: #164d8e;\n --sv-comment-primary-light: #1354ae;\n --sv-comment-primary-dark: #003477;\n \n /* Contrast colors */\n --sv-comment-bg: #ffffff;\n --sv-comment-text: #121212;\n --sv-comment-text-secondary: #6b7271;\n --sv-comment-border: rgba(18, 18, 18, 0.08);\n \n /* Accent colors */\n --sv-comment-like-color: #ff434e;\n --sv-comment-verified-color: #1ea031;\n --sv-comment-mention-color: #164d8e;\n \n /* Component specific */\n --sv-comment-avatar-bg: #e5e6e6;\n --sv-comment-input-border: #a3a3a3;\n --sv-comment-reply-line: #e5e6e6;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n OVERRIDE BOTTOMSHEET STYLES\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-comment-sheet {\n /* Override BottomSheet theming */\n --sv-sheet-bg: var(--sv-comment-bg, #ffffff);\n --sv-sheet-border-radius: var(--sv-comment-sheet-radius, 24px);\n --sv-sheet-animation-duration: var(--sv-comment-animation-duration, 400ms);\n --sv-sheet-animation-easing: var(--sv-comment-animation-easing, cubic-bezier(0.32, 0.72, 0, 1));\n \n /* Add margin for rounded corners effect */\n margin: 16px;\n border-radius: var(--sv-comment-sheet-radius, 24px);\n}\n\n.sv-comment-sheet-backdrop {\n --sv-sheet-backdrop-bg: var(--sv-comment-backdrop-bg, rgba(0, 0, 0, 0.5));\n}\n\n/* Inner content wrapper */\n.sv-comment-sheet__inner {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n/* Content wrapper - remove BottomSheet default scroll */\n.sv-comment-sheet .sv-bottom-sheet__content {\n overflow: visible;\n display: flex;\n flex-direction: column;\n flex: 1;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n HEADER\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-comment-sheet__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px;\n border-bottom: 1px solid var(--sv-comment-border);\n flex-shrink: 0;\n position: relative;\n cursor: grab;\n touch-action: none;\n}\n\n.sv-comment-sheet__header:active {\n cursor: grabbing;\n}\n\n.sv-comment-sheet__header-handle {\n position: absolute;\n top: 8px;\n left: 50%;\n transform: translateX(-50%);\n width: 36px;\n height: 4px;\n background: var(--sv-comment-text-secondary);\n border-radius: 2px;\n opacity: 0.3;\n}\n\n.sv-comment-sheet__header-left {\n display: flex;\n align-items: center;\n gap: 2px;\n}\n\n.sv-comment-sheet__title {\n font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 18px;\n font-weight: 600;\n line-height: 1.4;\n color: var(--sv-comment-text);\n opacity: 0.9;\n margin: 0;\n}\n\n.sv-comment-sheet__sort-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n color: var(--sv-comment-text);\n}\n\n.sv-comment-sheet__sort-btn svg {\n width: 20px;\n height: 20px;\n}\n\n.sv-comment-sheet__close-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n border: none;\n border-radius: 100px;\n background: linear-gradient(180deg, var(--sv-comment-primary-light) 0%, var(--sv-comment-primary-dark) 100%);\n cursor: pointer;\n transition: opacity 0.15s ease;\n}\n\n.sv-comment-sheet__close-btn:hover {\n opacity: 0.9;\n}\n\n.sv-comment-sheet__close-btn svg {\n width: 20px;\n height: 20px;\n color: #ffffff;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n COMMENT LIST\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-comment-sheet__list {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 8px 16px 28px 16px;\n -webkit-overflow-scrolling: touch;\n overscroll-behavior: contain;\n touch-action: pan-y;\n}\n\n.sv-comment-sheet__list::-webkit-scrollbar {\n width: 0px;\n}\n\n.sv-comment-sheet__list::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.0);\n border-radius: 0px;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n COMMENT ITEM\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-comment-item {\n display: flex;\n gap: 6px;\n padding: 16px 0;\n position: relative;\n}\n\n.sv-comment-item--pending {\n opacity: 0.6;\n}\n\n.sv-comment-item--pinned {\n background: var(--sv-comment-bg);\n}\n\n.sv-comment-item__avatar {\n width: 40px;\n height: 40px;\n border-radius: 120px;\n flex-shrink: 0;\n object-fit: cover;\n background: var(--sv-comment-avatar-bg);\n}\n\n.sv-comment-item__content {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.sv-comment-item__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 4px;\n}\n\n.sv-comment-item__header-left {\n display: flex;\n align-items: center;\n gap: 4px;\n min-width: 0;\n}\n\n.sv-comment-item__pin-icon {\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n color: var(--sv-comment-primary);\n}\n\n.sv-comment-item__author {\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 14px;\n font-weight: 600;\n line-height: 1.4;\n color: var(--sv-comment-text);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.sv-comment-item__verified {\n width: 12px;\n height: 12px;\n flex-shrink: 0;\n color: var(--sv-comment-verified-color);\n}\n\n.sv-comment-item__badge {\n font-size: 10px;\n padding: 2px 6px;\n background: var(--sv-comment-primary);\n color: #ffffff;\n border-radius: 4px;\n flex-shrink: 0;\n}\n\n.sv-comment-item__menu-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n color: var(--sv-comment-text-secondary);\n}\n\n.sv-comment-item__menu-btn svg {\n width: 20px;\n height: 20px;\n}\n\n.sv-comment-item__text {\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 12px;\n font-weight: 400;\n line-height: 1.4;\n color: var(--sv-comment-text);\n word-break: break-word;\n margin: 0;\n padding-right: 16px;\n}\n\n/* Text collapse */\n.sv-comment-item__text--collapsed {\n display: -webkit-box;\n -webkit-line-clamp: var(--sv-comment-max-lines, 3);\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.sv-comment-item__expand-btn {\n background: none;\n border: none;\n padding: 0;\n font-size: 12px;\n color: var(--sv-comment-text-secondary);\n cursor: pointer;\n margin-top: 4px;\n}\n\n.sv-comment-item__expand-btn:hover {\n color: var(--sv-comment-text);\n}\n\n/* Actions row */\n.sv-comment-item__actions {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.sv-comment-item__time {\n font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 12px;\n font-weight: 500;\n line-height: 1.2;\n color: var(--sv-comment-text-secondary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.sv-comment-item__action-btn {\n display: flex;\n align-items: center;\n gap: 4px;\n background: none;\n border: none;\n padding: 0;\n font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 12px;\n font-weight: 500;\n line-height: 1.2;\n color: var(--sv-comment-text-secondary);\n cursor: pointer;\n transition: color 0.15s ease;\n}\n\n.sv-comment-item__action-btn:hover {\n color: var(--sv-comment-text);\n}\n\n.sv-comment-item__action-btn--active {\n color: var(--sv-comment-like-color);\n}\n\n.sv-comment-item__action-btn--active:hover {\n color: var(--sv-comment-like-color);\n}\n\n.sv-comment-item__action-icon {\n width: 20px;\n height: 20px;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n REPLIES\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-comment-replies {\n margin-top: 12px;\n position: relative;\n}\n\n/* Vertical connecting line */\n.sv-comment-item--has-replies::before {\n content: '';\n position: absolute;\n left: 20px;\n top: 56px;\n bottom: 0;\n width: 1px;\n background: var(--sv-comment-reply-line);\n}\n\n.sv-comment-replies__toggle {\n display: flex;\n align-items: center;\n gap: 0;\n background: none;\n border: none;\n padding: 4px 0;\n cursor: pointer;\n}\n\n.sv-comment-replies__toggle-line {\n width: 24px;\n height: 1px;\n background: #a3a3a3;\n margin-right: 0;\n}\n\n.sv-comment-replies__toggle-text {\n font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.4;\n color: var(--sv-comment-text-secondary);\n white-space: nowrap;\n}\n\n.sv-comment-replies__toggle-icon {\n width: 20px;\n height: 20px;\n color: var(--sv-comment-text-secondary);\n}\n\n.sv-comment-replies__list {\n margin-top: 12px;\n}\n\n.sv-comment-reply {\n display: flex;\n gap: 6px;\n padding: 0 0 12px 0;\n position: relative;\n}\n\n.sv-comment-reply__avatar {\n width: 24px;\n height: 24px;\n border-radius: 100px;\n flex-shrink: 0;\n object-fit: cover;\n background: var(--sv-comment-avatar-bg);\n}\n\n.sv-comment-reply__mention {\n color: var(--sv-comment-mention-color);\n font-weight: 500;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n INPUT AREA\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-comment-sheet__input-area {\n padding: 0 16px 36px 16px;\n flex-shrink: 0;\n}\n\n/* Guest mode - login prompt instead of input */\n.sv-comment-input-guest {\n padding: 16px;\n border-top: 1px solid var(--sv-comment-border);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n background: var(--sv-comment-bg);\n color: var(--sv-comment-primary);\n font-weight: 600;\n font-size: 14px;\n width: 100%;\n transition: background 0.15s ease;\n}\n\n.sv-comment-input-guest:hover {\n background: rgba(22, 77, 142, 0.05);\n}\n\n.sv-comment-input-guest:active {\n background: rgba(22, 77, 142, 0.1);\n}\n\n.sv-comment-sheet__reply-to {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 4px 0;\n margin-bottom: 8px;\n font-size: 12px;\n color: var(--sv-comment-text-secondary);\n}\n\n.sv-comment-sheet__reply-to-author-name {\n font-size: 12px;\n color: var(--sv-comment-text);\n font-weight: 500;\n}\n\n.sv-comment-sheet__reply-to-clear {\n background: none;\n border: none;\n padding: 4px;\n color: var(--sv-comment-text-secondary);\n cursor: pointer;\n font-size: 12px;\n}\n\n.sv-comment-sheet__input-wrapper {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 44px;\n padding: 16px;\n background: var(--sv-comment-bg);\n border: 1px solid var(--sv-comment-input-border);\n border-radius: 12px;\n backdrop-filter: blur(50px);\n}\n\n.sv-comment-sheet__input-left {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n min-width: 0;\n}\n\n.sv-comment-sheet__media-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n flex-shrink: 0;\n}\n\n.sv-comment-sheet__media-btn svg {\n width: 20px;\n height: 20px;\n}\n\n.sv-comment-sheet__input {\n flex: 1;\n background: none;\n border: none;\n outline: none;\n resize: none;\n font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 12px;\n font-style: italic;\n font-weight: 400;\n line-height: 1.4;\n color: var(--sv-comment-text);\n padding: 0;\n min-width: 0;\n}\n\n.sv-comment-sheet__input::placeholder {\n color: var(--sv-comment-text-secondary);\n}\n\n.sv-comment-sheet__input:not(:placeholder-shown) {\n font-style: normal;\n}\n\n.sv-comment-sheet__emoji-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n flex-shrink: 0;\n}\n\n.sv-comment-sheet__emoji-btn svg {\n width: 20px;\n height: 20px;\n color: var(--sv-comment-primary);\n}\n\n/* Hidden emoji bar (can be toggled) */\n.sv-comment-sheet__emoji-bar {\n display: none;\n gap: 8px;\n padding: 8px 0;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.sv-comment-sheet__emoji-bar--visible {\n display: flex;\n}\n\n.sv-comment-sheet__emoji-bar::-webkit-scrollbar {\n display: none;\n}\n\n.sv-comment-sheet__emoji-bar-btn {\n background: none;\n border: none;\n padding: 4px;\n font-size: 20px;\n cursor: pointer;\n border-radius: 4px;\n transition: background 0.15s ease;\n}\n\n.sv-comment-sheet__emoji-bar-btn:hover {\n background: rgba(0, 0, 0, 0.05);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n STATES\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-comment-sheet__loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px;\n color: var(--sv-comment-text-secondary);\n}\n\n.sv-comment-sheet__loading-spinner {\n width: 24px;\n height: 24px;\n border: 2px solid rgba(0, 0, 0, 0.1);\n border-top-color: var(--sv-comment-primary);\n border-radius: 50%;\n animation: sv-comment-spin 0.8s linear infinite;\n}\n\n@keyframes sv-comment-spin {\n to { transform: rotate(360deg); }\n}\n\n.sv-comment-sheet__empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px;\n text-align: center;\n}\n\n.sv-comment-sheet__empty-icon {\n font-size: 48px;\n margin-bottom: 12px;\n}\n\n.sv-comment-sheet__empty-text {\n color: var(--sv-comment-text-secondary);\n font-size: 14px;\n}\n\n.sv-comment-sheet__error {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 32px;\n text-align: center;\n color: var(--sv-comment-like-color);\n}\n\n.sv-comment-sheet__error-btn {\n margin-top: 12px;\n padding: 8px 16px;\n background: rgba(0, 0, 0, 0.05);\n border: none;\n border-radius: 8px;\n color: var(--sv-comment-text);\n cursor: pointer;\n}\n\n/* Load more */\n.sv-comment-sheet__load-more {\n display: flex;\n justify-content: center;\n padding: 12px;\n}\n\n.sv-comment-sheet__load-more-btn {\n background: none;\n border: none;\n padding: 8px 16px;\n color: var(--sv-comment-text-secondary);\n cursor: pointer;\n font-size: 13px;\n}\n\n.sv-comment-sheet__load-more-btn:hover {\n color: var(--sv-comment-text);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n COMMENT MENU (Dropdown)\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-comment-menu {\n position: relative;\n}\n\n.sv-comment-menu__trigger {\n display: flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: var(--sv-comment-text-secondary);\n border-radius: 4px;\n transition: background 0.15s ease;\n}\n\n.sv-comment-menu__trigger:hover {\n background: rgba(0, 0, 0, 0.05);\n}\n\n.sv-comment-menu__icon {\n width: 20px;\n height: 20px;\n}\n\n.sv-comment-menu__dropdown {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 4px;\n min-width: 140px;\n background: var(--sv-comment-bg);\n border: 1px solid var(--sv-comment-border);\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n z-index: 10;\n overflow: hidden;\n animation: sv-menu-fade-in 0.15s ease;\n}\n\n@keyframes sv-menu-fade-in {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.sv-comment-menu__item {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 10px 12px;\n background: none;\n border: none;\n cursor: pointer;\n font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 14px;\n font-weight: 500;\n color: var(--sv-comment-text);\n text-align: left;\n transition: background 0.15s ease;\n}\n\n.sv-comment-menu__item:hover {\n background: rgba(0, 0, 0, 0.05);\n}\n\n.sv-comment-menu__item--danger {\n color: var(--sv-comment-like-color);\n}\n\n.sv-comment-menu__item--danger:hover {\n background: rgba(255, 67, 78, 0.08);\n}\n\n.sv-comment-menu__item-icon {\n width: 18px;\n height: 18px;\n flex-shrink: 0;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n DELETE CONFIRMATION DIALOG\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-comment-dialog-overlay {\n position: fixed;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.5);\n z-index: var(--sv-comment-modal-z-index, 1100);\n animation: sv-dialog-overlay-fade-in 0.2s ease;\n}\n\n@keyframes sv-dialog-overlay-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.sv-comment-dialog {\n background: var(--sv-comment-bg);\n border-radius: 16px;\n padding: 24px;\n max-width: 300px;\n width: calc(100% - 48px);\n text-align: center;\n animation: sv-dialog-scale-in 0.2s ease;\n}\n\n@keyframes sv-dialog-scale-in {\n from { opacity: 0; transform: scale(0.95); }\n to { opacity: 1; transform: scale(1); }\n}\n\n.sv-comment-dialog__title {\n font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 17px;\n font-weight: 600;\n color: var(--sv-comment-text);\n margin: 0 0 8px 0;\n}\n\n.sv-comment-dialog__message {\n font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 14px;\n color: var(--sv-comment-text-secondary);\n margin: 0 0 20px 0;\n line-height: 1.4;\n}\n\n.sv-comment-dialog__actions {\n display: flex;\n gap: 12px;\n}\n\n.sv-comment-dialog__btn {\n flex: 1;\n padding: 12px 16px;\n border: none;\n border-radius: 10px;\n font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 15px;\n font-weight: 600;\n cursor: pointer;\n transition: opacity 0.15s ease;\n}\n\n.sv-comment-dialog__btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.sv-comment-dialog__btn--cancel {\n background: rgba(0, 0, 0, 0.06);\n color: var(--sv-comment-text);\n}\n\n.sv-comment-dialog__btn--cancel:hover:not(:disabled) {\n background: rgba(0, 0, 0, 0.1);\n}\n\n.sv-comment-dialog__btn--danger {\n background: var(--sv-comment-like-color);\n color: #ffffff;\n}\n\n.sv-comment-dialog__btn--danger:hover:not(:disabled) {\n opacity: 0.9;\n}\n\n/* Legacy classes (keep for backwards compatibility) */\n.sv-comment-delete-confirm {\n position: fixed;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.5);\n z-index: var(--sv-comment-modal-z-index, 1100);\n}\n\n.sv-comment-delete-confirm__dialog {\n background: var(--sv-comment-bg);\n border-radius: 12px;\n padding: 16px;\n max-width: 280px;\n text-align: center;\n}\n\n.sv-comment-delete-confirm__title {\n font-size: 16px;\n font-weight: 600;\n color: var(--sv-comment-text);\n margin-bottom: 8px;\n}\n\n.sv-comment-delete-confirm__text {\n font-size: 14px;\n color: var(--sv-comment-text-secondary);\n margin-bottom: 16px;\n}\n\n.sv-comment-delete-confirm__actions {\n display: flex;\n gap: 8px;\n}\n\n.sv-comment-delete-confirm__btn {\n flex: 1;\n padding: 8px 12px;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n}\n\n.sv-comment-delete-confirm__btn--cancel {\n background: rgba(0, 0, 0, 0.05);\n color: var(--sv-comment-text);\n}\n\n.sv-comment-delete-confirm__btn--delete {\n background: var(--sv-comment-like-color);\n color: #ffffff;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n SKELETON LOADING\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n@keyframes sv-skeleton-shimmer {\n 0% { background-position: -200% 0; }\n 100% { background-position: 200% 0; }\n}\n\n.sv-comment-skeleton-list {\n display: flex;\n flex-direction: column;\n}\n\n.sv-comment-skeleton {\n animation: sv-skeleton-fade-in 0.3s ease;\n}\n\n@keyframes sv-skeleton-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.sv-comment-skeleton__avatar {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: linear-gradient(\n 90deg,\n rgba(0, 0, 0, 0.04) 25%,\n rgba(0, 0, 0, 0.08) 50%,\n rgba(0, 0, 0, 0.04) 75%\n );\n background-size: 200% 100%;\n animation: sv-skeleton-shimmer 1.5s ease-in-out infinite;\n}\n\n.sv-comment-skeleton__content {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.sv-comment-skeleton__header {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.sv-comment-skeleton__author {\n width: 80px;\n height: 14px;\n border-radius: 4px;\n background: linear-gradient(\n 90deg,\n rgba(0, 0, 0, 0.04) 25%,\n rgba(0, 0, 0, 0.08) 50%,\n rgba(0, 0, 0, 0.04) 75%\n );\n background-size: 200% 100%;\n animation: sv-skeleton-shimmer 1.5s ease-in-out infinite;\n animation-delay: 0.1s;\n}\n\n.sv-comment-skeleton__time {\n width: 40px;\n height: 12px;\n border-radius: 4px;\n background: linear-gradient(\n 90deg,\n rgba(0, 0, 0, 0.04) 25%,\n rgba(0, 0, 0, 0.08) 50%,\n rgba(0, 0, 0, 0.04) 75%\n );\n background-size: 200% 100%;\n animation: sv-skeleton-shimmer 1.5s ease-in-out infinite;\n animation-delay: 0.15s;\n}\n\n.sv-comment-skeleton__text {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.sv-comment-skeleton__line {\n height: 14px;\n border-radius: 4px;\n background: linear-gradient(\n 90deg,\n rgba(0, 0, 0, 0.04) 25%,\n rgba(0, 0, 0, 0.08) 50%,\n rgba(0, 0, 0, 0.04) 75%\n );\n background-size: 200% 100%;\n animation: sv-skeleton-shimmer 1.5s ease-in-out infinite;\n}\n\n.sv-comment-skeleton__line--full {\n width: 100%;\n animation-delay: 0.2s;\n}\n\n.sv-comment-skeleton__line--medium {\n width: 65%;\n animation-delay: 0.25s;\n}\n\n.sv-comment-skeleton__actions {\n display: flex;\n align-items: center;\n gap: 16px;\n margin-top: 4px;\n}\n\n.sv-comment-skeleton__action {\n width: 50px;\n height: 12px;\n border-radius: 4px;\n background: linear-gradient(\n 90deg,\n rgba(0, 0, 0, 0.04) 25%,\n rgba(0, 0, 0, 0.08) 50%,\n rgba(0, 0, 0, 0.04) 75%\n );\n background-size: 200% 100%;\n animation: sv-skeleton-shimmer 1.5s ease-in-out infinite;\n animation-delay: 0.3s;\n}\n";
218
218
 
219
- export { CommentSheet as C, type ReplyTarget as R, SheetHeader as S, CommentSheetHeadless as a, type CommentSheetHeadlessProps as b, type SheetHeaderProps as c, CommentList as d, type CommentListProps as e, CommentInput as f, type CommentInputProps as g, CommentItemComponent as h, type CommentItemProps as i, CommentSheetContext as j, useOptionalCommentSheetContext as k, type CommentSheetContextValue as l, type CommentSheetI18n as m, COMMENT_SHEET_CSS as n, useCommentSheetContext as u };
219
+ export { COMMENT_SHEET_CSS as C, type ReplyTarget as R, SheetHeader as S, CommentInput as a, type CommentInputProps as b, CommentItemComponent as c, type CommentItemProps as d, CommentList as e, type CommentListProps as f, CommentSheet as g, CommentSheetContext as h, type CommentSheetContextValue as i, CommentSheetHeadless as j, type CommentSheetHeadlessProps as k, type CommentSheetI18n as l, type SheetHeaderProps as m, useOptionalCommentSheetContext as n, useCommentSheetContext as u };
@@ -49,7 +49,7 @@ function formatCount(count) {
49
49
  function DetailViewHeadlessBase({
50
50
  isOpen,
51
51
  onClose,
52
- imagePost,
52
+ article,
53
53
  initialImageIndex = 0,
54
54
  animationDuration = DEFAULT_ANIMATION_DURATION,
55
55
  enableSwipeToClose = true,
@@ -187,7 +187,7 @@ function DetailViewHeadlessBase({
187
187
  }, [isVisible, handleClose]);
188
188
  const contextValue = useMemo(
189
189
  () => ({
190
- imagePost,
190
+ article,
191
191
  currentImageIndex,
192
192
  setCurrentImageIndex,
193
193
  close: handleClose,
@@ -207,7 +207,7 @@ function DetailViewHeadlessBase({
207
207
  }
208
208
  }),
209
209
  [
210
- imagePost,
210
+ article,
211
211
  currentImageIndex,
212
212
  handleClose,
213
213
  isAnimating,
@@ -239,7 +239,7 @@ function DetailViewHeadlessBase({
239
239
  className
240
240
  ),
241
241
  "aria-modal": "true",
242
- "aria-label": `Detail view for post by ${imagePost.author?.name ?? "Unknown"}`,
242
+ "aria-label": `Detail view for article by ${article.author?.name ?? "Unknown"}`,
243
243
  onClick: stopClickPropagation,
244
244
  children: [
245
245
  /* @__PURE__ */ jsx("div", { className: "sv-detail-view__backdrop", onClick: handleClose }),
@@ -270,22 +270,22 @@ function DetailViewHeadlessBase({
270
270
  }
271
271
  ),
272
272
  /* @__PURE__ */ jsxs("div", { className: "sv-detail-view__header-author", children: [
273
- imagePost.author?.avatar && /* @__PURE__ */ jsx(
273
+ article.author?.avatar && /* @__PURE__ */ jsx(
274
274
  "img",
275
275
  {
276
- src: imagePost.author.avatar,
277
- alt: imagePost.author.name,
276
+ src: article.author.avatar,
277
+ alt: article.author.name,
278
278
  className: "sv-detail-view__header-avatar"
279
279
  }
280
280
  ),
281
- /* @__PURE__ */ jsx("span", { className: "sv-detail-view__header-name", children: imagePost.author?.name ?? headerTitle })
281
+ /* @__PURE__ */ jsx("span", { className: "sv-detail-view__header-name", children: article.author?.name ?? headerTitle })
282
282
  ] })
283
283
  ] }),
284
284
  /* @__PURE__ */ jsx("div", { className: "sv-detail-view__scroll", children: /* @__PURE__ */ jsx("div", { className: "sv-detail-view__content", children }) }),
285
285
  !hideBottomBar && (renderBottomBar ? renderBottomBar() : /* @__PURE__ */ jsx(
286
286
  DetailViewDefaultBottomBar,
287
287
  {
288
- imagePost,
288
+ article,
289
289
  isLiked,
290
290
  isBookmarked,
291
291
  onLike,
@@ -307,14 +307,14 @@ function DetailViewGallery({
307
307
  enableZoom = true,
308
308
  className
309
309
  }) {
310
- const { imagePost, currentImageIndex, setCurrentImageIndex, actions } = useDetailViewContext();
310
+ const { article, currentImageIndex, setCurrentImageIndex, actions } = useDetailViewContext();
311
311
  return /* @__PURE__ */ jsx("div", { className: clsx2("sv-detail-view__gallery", className), children: /* @__PURE__ */ jsx(
312
312
  ImageCarouselHeadless,
313
313
  {
314
- images: imagePost.images,
314
+ images: article.images,
315
315
  currentIndex: currentImageIndex,
316
316
  onIndexChange: setCurrentImageIndex,
317
- showIndicators: imagePost.images.length > 1,
317
+ showIndicators: article.images.length > 1,
318
318
  indicatorStyle: "dots",
319
319
  enableZoom,
320
320
  lazyLoad: false,
@@ -335,14 +335,14 @@ function DetailViewAuthor({
335
335
  followingLabel = "Following",
336
336
  className
337
337
  }) {
338
- const { imagePost } = useDetailViewContext();
339
- const author = imagePost.author;
338
+ const { article } = useDetailViewContext();
339
+ const author = article.author;
340
340
  if (!author) return null;
341
341
  return /* @__PURE__ */ jsxs("div", { className: clsx2("sv-detail-view__author", className), children: [
342
342
  author.avatar && /* @__PURE__ */ jsx("img", { src: author.avatar, alt: author.name, className: "sv-detail-view__author-avatar" }),
343
343
  /* @__PURE__ */ jsxs("div", { className: "sv-detail-view__author-info", children: [
344
344
  /* @__PURE__ */ jsx("div", { className: "sv-detail-view__author-name", children: author.name }),
345
- imagePost.createdAt && /* @__PURE__ */ jsx("div", { className: "sv-detail-view__author-date", children: formatDate(imagePost.createdAt) })
345
+ article.createdAt && /* @__PURE__ */ jsx("div", { className: "sv-detail-view__author-date", children: formatDate(article.createdAt) })
346
346
  ] }),
347
347
  showFollowButton && /* @__PURE__ */ jsx(
348
348
  "button",
@@ -362,9 +362,9 @@ function DetailViewCaption({
362
362
  renderHashtag,
363
363
  className
364
364
  }) {
365
- const { imagePost } = useDetailViewContext();
366
- if (!imagePost.caption) return null;
367
- const parts = imagePost.caption.split(/(#\w+)/g);
365
+ const { article } = useDetailViewContext();
366
+ if (!article.caption) return null;
367
+ const parts = article.caption.split(/(#\w+)/g);
368
368
  return /* @__PURE__ */ jsx("div", { className: clsx2("sv-detail-view__caption", className), children: parts.map((part, index) => {
369
369
  if (part.startsWith("#")) {
370
370
  return renderHashtag ? renderHashtag(part) : (
@@ -380,8 +380,8 @@ function DetailViewStats({
380
380
  labels = {},
381
381
  className
382
382
  }) {
383
- const { imagePost } = useDetailViewContext();
384
- const stats = imagePost.stats;
383
+ const { article } = useDetailViewContext();
384
+ const stats = article.stats;
385
385
  const { likes = "likes", comments = "comments", shares = "shares" } = labels;
386
386
  return /* @__PURE__ */ jsxs("div", { className: clsx2("sv-detail-view__stats", className), children: [
387
387
  stats.likes !== void 0 && /* @__PURE__ */ jsxs("div", { className: "sv-detail-view__stat", children: [
@@ -427,7 +427,7 @@ function DetailViewMusic({
427
427
  ] });
428
428
  }
429
429
  function DetailViewDefaultBottomBar({
430
- imagePost,
430
+ article,
431
431
  isLiked,
432
432
  isBookmarked,
433
433
  onLike,
@@ -443,20 +443,13 @@ function DetailViewDefaultBottomBar({
443
443
  {
444
444
  type: "like",
445
445
  isActive: isLiked,
446
- count: imagePost.stats.likes,
446
+ count: article.stats.likes,
447
447
  onClick: onLike
448
448
  }
449
449
  ),
450
- /* @__PURE__ */ jsx(
451
- DetailViewActionButton,
452
- {
453
- type: "comment",
454
- count: imagePost.stats.comments,
455
- onClick: onComment
456
- }
457
- ),
450
+ /* @__PURE__ */ jsx(DetailViewActionButton, { type: "comment", count: article.stats.comments, onClick: onComment }),
458
451
  /* @__PURE__ */ jsx(DetailViewActionButton, { type: "bookmark", isActive: isBookmarked, onClick: onBookmark }),
459
- /* @__PURE__ */ jsx(DetailViewActionButton, { type: "share", count: imagePost.stats.shares, onClick: onShare })
452
+ /* @__PURE__ */ jsx(DetailViewActionButton, { type: "share", count: article.stats.shares, onClick: onShare })
460
453
  ] })
461
454
  ] });
462
455
  }
@@ -0,0 +1,191 @@
1
+ import { VirtualSlider } from './chunk-YB7AXTX7.js';
2
+ import { clsx2 } from './chunk-EDWS2IPH.js';
3
+ import { injectComponentCSS } from './chunk-CAWE42LH.js';
4
+ import { createContext, useContext, useInsertionEffect, useRef, useMemo, useCallback } from 'react';
5
+ import { jsx, jsxs } from 'react/jsx-runtime';
6
+
7
+ // src/components/Feed/Feed.css.ts
8
+ var FEED_CSS = `.sv-feed{position:relative;width:100%;height:100%;overflow:hidden;background:var(--sv-bg-primary,#000);touch-action:pan-y;user-select:none;-webkit-user-select:none}.sv-feed__container{position:relative;width:100%;height:100%;will-change:transform}.sv-feed__container--snapping{transition:transform .3s cubic-bezier(.25,.46,.45,.94)}.sv-feed__container--swiping{transition:none}.sv-feed__slot{position:absolute;top:0;left:0;width:100%;height:100%;will-change:transform,opacity;backface-visibility:hidden;-webkit-backface-visibility:hidden}.sv-feed__slot--active{z-index:2}.sv-feed__slot--adjacent{z-index:1;pointer-events:none}.sv-feed__slot--transitioning{transition:transform .175s cubic-bezier(.25,.46,.45,.94),opacity .2s ease}.sv-feed__loading{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);display:flex;flex-direction:column;align-items:center;gap:var(--sv-spacing-md,16px);color:var(--sv-text-secondary,#999)}.sv-feed__loading-spinner{width:32px;height:32px;border:3px solid rgba(255,255,255,.2);border-top-color:var(--sv-color-primary,#fe2c55);border-radius:50%;animation:sv-feed-spinner .8s linear infinite}@keyframes sv-feed-spinner{to{transform:rotate(360deg)}}.sv-feed__loading-text{font-size:var(--sv-font-size-sm,13px);font-family:var(--sv-font-family,'Urbanist',sans-serif)}.sv-feed__empty{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);text-align:center;color:var(--sv-text-secondary,#999);font-family:var(--sv-font-family,'Urbanist',sans-serif)}.sv-feed__empty-icon{font-size:48px;margin-bottom:var(--sv-spacing-md,16px)}.sv-feed__empty-text{font-size:var(--sv-font-size-md,14px)}.sv-feed__end{position:absolute;bottom:calc(var(--sv-spacing-xl,32px)+env(safe-area-inset-bottom,0));left:50%;transform:translateX(-50%);z-index:10;padding:var(--sv-spacing-sm,8px)var(--sv-spacing-md,16px);background:rgba(0,0,0,.7);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);border-radius:var(--sv-border-radius-md,8px);color:var(--sv-text-secondary,#999);font-size:var(--sv-font-size-sm,13px);font-family:var(--sv-font-family,'Urbanist',sans-serif);pointer-events:none;animation:sv-feed-end-fade-in .3s ease-out}@keyframes sv-feed-end-fade-in{from{opacity:0;transform:translateX(-50%)translateY(10px)}to{opacity:1;transform:translateX(-50%)translateY(0)}}@media(prefers-reduced-motion:reduce){.sv-feed__container--snapping{transition:none}.sv-feed__loading-spinner{animation:none}}`;
9
+ var FeedContext = createContext(null);
10
+ function useFeedContext() {
11
+ const context = useContext(FeedContext);
12
+ if (!context) {
13
+ throw new Error("useFeedContext must be used within a Feed");
14
+ }
15
+ return context;
16
+ }
17
+ function useOptionalFeedContext() {
18
+ return useContext(FeedContext);
19
+ }
20
+ function FeedLoading({ text = "Loading..." }) {
21
+ return /* @__PURE__ */ jsxs("div", { className: "sv-feed__loading", children: [
22
+ /* @__PURE__ */ jsx("div", { className: "sv-feed__loading-spinner" }),
23
+ /* @__PURE__ */ jsx("div", { className: "sv-feed__loading-text", children: text })
24
+ ] });
25
+ }
26
+ function FeedEmpty({ text = "No content" }) {
27
+ return /* @__PURE__ */ jsxs("div", { className: "sv-feed__empty", children: [
28
+ /* @__PURE__ */ jsx("div", { className: "sv-feed__empty-icon", children: "\u{1F4ED}" }),
29
+ /* @__PURE__ */ jsx("div", { className: "sv-feed__empty-text", children: text })
30
+ ] });
31
+ }
32
+ function FeedEnd({ text = "You've reached the end" }) {
33
+ return /* @__PURE__ */ jsx("div", { className: "sv-feed__end", "aria-live": "polite", children: text });
34
+ }
35
+ function FeedHeadless({
36
+ feedState,
37
+ swipeState,
38
+ height,
39
+ className,
40
+ renderSlot,
41
+ onIndexChange,
42
+ onEndReached,
43
+ endReachedThreshold = 2,
44
+ bufferSize = 1,
45
+ renderEmpty,
46
+ renderLoading,
47
+ renderEnd,
48
+ loadingText = "Loading...",
49
+ emptyText = "No content",
50
+ endText = "You've reached the end",
51
+ disableInlineTransforms = false
52
+ }) {
53
+ useInsertionEffect(() => {
54
+ return injectComponentCSS("sv-feed", FEED_CSS);
55
+ }, []);
56
+ const { items, isLoading, hasMore } = feedState;
57
+ const { activeIndex, isSwiping, dragOffset, goToIndex } = swipeState;
58
+ const containerHeightRef = useRef(
59
+ typeof window !== "undefined" ? window.innerHeight : 800
60
+ );
61
+ const contextValue = useMemo(
62
+ () => ({
63
+ items,
64
+ videos: items,
65
+ // Backward compatibility
66
+ activeIndex: Math.max(0, Math.min(items.length - 1, activeIndex)),
67
+ isSwiping,
68
+ dragOffset,
69
+ containerHeight: containerHeightRef.current,
70
+ goToIndex,
71
+ totalCount: items.length
72
+ }),
73
+ [items, activeIndex, isSwiping, dragOffset, goToIndex]
74
+ );
75
+ const keyExtractor = useCallback((item) => item.id, []);
76
+ const renderItem = useCallback(
77
+ (item, index, isActive) => {
78
+ return renderSlot(item, index, isActive);
79
+ },
80
+ [renderSlot]
81
+ );
82
+ const loadingComponent = useMemo(
83
+ () => renderLoading?.(loadingText) || /* @__PURE__ */ jsx(FeedLoading, { text: loadingText }),
84
+ [loadingText]
85
+ );
86
+ const emptyComponent = useMemo(
87
+ () => renderEmpty?.(emptyText) || /* @__PURE__ */ jsx(FeedEmpty, { text: emptyText }),
88
+ [emptyText]
89
+ );
90
+ const endComponent = useMemo(() => renderEnd?.(endText) || /* @__PURE__ */ jsx(FeedEnd, { text: endText }), [endText]);
91
+ const sliderProps = {
92
+ // Required
93
+ items,
94
+ keyExtractor,
95
+ renderItem,
96
+ // Swipe state
97
+ activeIndex,
98
+ isSwiping,
99
+ dragOffset,
100
+ goToIndex,
101
+ // Callbacks
102
+ onIndexChange,
103
+ onEndReached,
104
+ endReachedThreshold,
105
+ bufferSize,
106
+ // Loading states
107
+ isLoading,
108
+ hasMore,
109
+ // Custom UI (video-specific styling)
110
+ loadingComponent,
111
+ emptyComponent,
112
+ endComponent,
113
+ // Styling - use sv-feed classes instead of sv-slider
114
+ height,
115
+ className: clsx2("sv-feed", className),
116
+ disableInlineTransforms
117
+ };
118
+ return /* @__PURE__ */ jsx(FeedContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(VirtualSlider, { ...sliderProps }) });
119
+ }
120
+ FeedHeadless.displayName = "FeedHeadless";
121
+ function useFeedPosition(options) {
122
+ const {
123
+ totalCount,
124
+ activeIndex,
125
+ containerHeight,
126
+ dragOffset,
127
+ isSwiping,
128
+ isResizing = false,
129
+ bufferSize = 1
130
+ } = options;
131
+ return useMemo(() => {
132
+ if (totalCount === 0) {
133
+ return {
134
+ slots: [],
135
+ scrollOffset: 0,
136
+ isAtStart: true,
137
+ isAtLastIndex: true,
138
+ clampedActiveIndex: 0
139
+ };
140
+ }
141
+ const clampedActiveIndex = Math.max(0, Math.min(totalCount - 1, activeIndex));
142
+ const slots = [];
143
+ const startIndex = Math.max(0, clampedActiveIndex - bufferSize);
144
+ const endIndex = Math.min(totalCount - 1, clampedActiveIndex + bufferSize);
145
+ const baseOffset = -clampedActiveIndex * containerHeight;
146
+ const scrollOffset = baseOffset + dragOffset;
147
+ for (let i = startIndex; i <= endIndex; i++) {
148
+ const signedDistance = i - clampedActiveIndex;
149
+ const distance = Math.abs(signedDistance);
150
+ const isActive = i === clampedActiveIndex;
151
+ const top = i * containerHeight;
152
+ const transform = `translateY(${top + scrollOffset}px)`;
153
+ let opacity = 1;
154
+ if (!isActive && !isResizing) {
155
+ opacity = isSwiping ? 0.7 : 0.3;
156
+ }
157
+ slots.push({
158
+ index: i,
159
+ top,
160
+ isActive,
161
+ distance,
162
+ signedDistance,
163
+ transform,
164
+ opacity
165
+ });
166
+ }
167
+ return {
168
+ slots,
169
+ scrollOffset,
170
+ isAtStart: clampedActiveIndex === 0,
171
+ isAtLastIndex: clampedActiveIndex >= totalCount - 1,
172
+ clampedActiveIndex
173
+ };
174
+ }, [totalCount, activeIndex, containerHeight, dragOffset, isSwiping, isResizing, bufferSize]);
175
+ }
176
+ function getSlotIndexFromPosition(yPosition, containerHeight, totalCount) {
177
+ if (totalCount === 0 || containerHeight === 0) {
178
+ return 0;
179
+ }
180
+ const rawIndex = Math.round(-yPosition / containerHeight);
181
+ return Math.max(0, Math.min(totalCount - 1, rawIndex));
182
+ }
183
+
184
+ // src/components/Feed/constants.ts
185
+ var SLOT_INDEX_ATTR = "data-slot-index";
186
+ var SLOT_ACTIVE_ATTR = "data-slot-active";
187
+ var SLOT_INDEX_DATASET_KEY = "slotIndex";
188
+ var SLOT_ACTIVE_DATASET_KEY = "slotActive";
189
+ var FEED_CLASS_PREFIX = "sv-feed";
190
+
191
+ export { FEED_CLASS_PREFIX, FEED_CSS, FeedContext, FeedHeadless, SLOT_ACTIVE_ATTR, SLOT_ACTIVE_DATASET_KEY, SLOT_INDEX_ATTR, SLOT_INDEX_DATASET_KEY, getSlotIndexFromPosition, useFeedContext, useFeedPosition, useOptionalFeedContext };