type RecursivePartial = { [P in keyof T]?: RecursivePartial; }; export type CommentsProps = { "website-id": number; "page-id"?: number | string; "page-url"?: string; "page-title"?: string; "page-language"?: string; "page-author"?: string; "sso-user"?: string; "sso-hash"?: string; colors?: 'light' | 'dark' | 'os'; loading?: 'default' | 'lazy' | 'manual'; instance?: string; settings?: RecursivePartial; /** * @deprecated */ translations?: Partial>; } & Partial<{ [K in CommentsTranslationsKeys as `t-${K & string}`]: string; }>; export type CommentsCustomElement = HTMLElement & { load: () => void; api: { reload: () => void; page: () => CommentsApiPage; auth: { user: () => CommentsApiLoggedUser | null; logout: () => void; }; }; }; export declare const COMMENTS_EVENTS: (keyof CommentsEvents)[]; export declare class Comments { static script(instance?: string): void; static comments(props: CommentsProps, container: HTMLElement, onEvent?: (event: T, data: CommentsEvents[T]) => void): CommentsCustomElement; } export interface CommentsSettings { /** * All the following options are extendable via settings attribute * @see https://talk.hyvor.com/docs/comments#settings */ name: string; custom_css: string | null; comments_view: { default_sort: 'top' | 'newest' | 'oldest'; note: string | null; close_after_days: number; is_keyboard_navigation_on: boolean; nested_levels: number; display_replied_to_type: 'none' | 'deep' | 'all'; }; profiles: { pictures: boolean; profile: boolean; default_picture: string | null; display_name_type: 'name' | 'username'; mod_alias_name: string | null; mod_alias_picture: string | null; mod_badge_id: number | null; }; realtime: { on: boolean; count: boolean; users: boolean; typing: 'off' | 'on_without_typer' | 'on_with_typer'; }; voting: { type: 'both' | 'upvotes' | 'none'; voters: boolean; guest: boolean; }; top_widget: 'none' | 'reactions' | 'ratings'; reactions: { configs: { type: 'superb' | 'love' | 'wow' | 'sad' | 'laugh' | 'angry'; is_shown: boolean; image_url: string | null; text: string; }[]; display_type: 'image' | 'text' | 'both'; }; ratings: { star_color: string; }; /** * Texts * * If you set a string, it will be shown *regardless* of the language. * Therefore, if you have a multi-language website, keep make sure to set * strings according to the current language dynamically. * * If you keep set it to null, default strings will be used based on the language. */ text: { comment_box: string | null; reply_box: string | null; no_comments: string | null; reactions: string | null; ratings: string | null; comment_count_0: string | null; comment_count_1: string | null; comment_count_multi: string | null; }; editor: { emoji: boolean; images: boolean; gifs: boolean; embeds: boolean; mentions: boolean; code_blocks: boolean; blockquotes: boolean; inline_styles: boolean; links: boolean; math: boolean; }; ui: { width: number | null; box_shadow: string; box_radius: string; box_border_size: string; box_border_color: string; button_radius: string; color_theme: 'os' | 'light' | 'dark'; }; light_palette: Palette; dark_palette: Palette; highlight: { new: boolean; new_color: string; upvote_1_threshold: null | number; upvote_2_threshold: null | number; upvote_1_color: string; upvote_2_color: string; }; } interface Palette { text: string; accent: string; accent_text: string; box: string; box_text: string; box_text_light: string; input: string; } export type CommentsTranslationsKeys = 'reactions-text' | 'ratings-text' | 'ratings-1' | 'ratings-multi' | 'login' | 'login-to-continue' | 'page-closed' | 'login-to-comment' | 'no-comments-text' | 'comments-0' | 'comments-1' | 'comments-multi' | 'online' | 'notifications' | 'notifications-no' | 'notifications-read' | 'notifications-reply' | 'notifications-mention' | 'notifications-load-more' | 'top' | 'newest' | 'oldest' | 'just-now' | 'ago-seconds' | 'ago-day' | 'ago-days' | 'ago-hour' | 'ago-hours' | 'ago-minute' | 'ago-minutes' | 'ago-year' | 'ago-years' | 'featured' | 'pending' | 'deleted' | 'loved-by' | 'team' | 'author' | 'edited' | 'moderate' | 'spam' | 'feature' | 'unfeature' | 'love' | 'unlove' | 'show-more' | 'show-less' | 'expand-comment' | 'expand-comments' | 'load-more-comments' | 'load-more' | 'more-replies' | 'hidden-comment' | 'reply' | 'replying-with-count' | 'guest' | 'guests' | 'show-new-comment' | 'show-new-comments' | 'show-new-reply' | 'show-new-replies' | 'show-all-comments' | 'show-parent-comment' | 'guest-name' | 'guest-email' | 'guest-name-fill' | 'guest-email-required' | 'guest-email-invalid' | 'comment-char-limit' | 'comment-box-text' | 'reply-box-text' | 'guest-vote' | 'as-guest' | 'comment-button-text' | 'reply-button-text' | 'edit' | 'delete' | 'delete-confirm' | 'cancel' | 'search' | 'search-comments' | 'search-back' | 'search-type' | 'flag' | 'unflag' | 'flag-comment' | 'flag-reason' | 'optional' | 'banned' | 'comments' | 'settings' | 'settings-for-website' | 'blocked' | 'unblocked' | 'reply-emails' | 'mention-emails' | 'saved' | 'no-results' | 'powered-by' | 'upload-image' | 'or' | 'paste-url' | 'add' | 'link' | 'embed' | 'copy-link' | 'link-copied' | 'block' | 'block-button' | 'unblock' | 'account-logout' | 'account-my' | 'default-error'; export interface CommentsEvents { /** * Comments section is fully loaded * This is triggered after the initial `/init` API call is completed */ 'loaded': null; /** * A comment is published. * Spam detection and rules are run asynchronously after this event. * Therefore, the status of the comment may change in a few seconds. */ 'comment:published': CommentsApiRealComment; /** * The comment body was edited. */ 'comment:edited': Comment; /** * A comment was deleted by the user. * (Not triggered when a moderator deletes a comment in the embed) */ 'comment:deleted': Comment; /** * A user voted/unvoted to a comment * vote: null means the current vote was removed */ 'comment:voted': { comment: Comment; vote: 'up' | 'down' | null; }; /** * A user flagged a comment * The comment will be hidden from the public view until a moderator reviews it */ 'comment:flagged': { comment: Comment; }; /** * A user reacted to a comment */ 'reaction': { type: 'superb' | 'love' | 'wow' | 'sad' | 'laugh' | 'angry'; }; /** * A user rated (star ratings) the page */ 'rating': { rating: number; count: number; average: number; }; /** * The login button was clicked * You may use this */ 'auth:login:clicked': null; /** * A user clicked on the profile picture or the name of another user * This usually triggers the user profile popup * You may use this to show a custom user profile (ex: using location.href) */ 'profile:clicked': CommentsApiLoggedUser; } export interface CommentsApiPage { id: number; created_at: number; identifier: string; url: string; title: string; is_closed: boolean; is_premoderation_on: boolean; comments_count: number; reactions: Record<'superb' | 'love' | 'wow' | 'sad' | 'laugh' | 'angry', number>; ratings: { average: number; count: number; }; online_count: number; } export interface CommentsApiBaseComment { id: number; page_id: number; url: string; parent_id: number | null; depth: number; created_at: number; } export interface CommentsApiHiddenComment extends CommentsApiBaseComment { is_hidden: true; } export interface CommentsApiRealComment extends CommentsApiBaseComment { is_hidden: false; content: string; content_html: string; is_featured: boolean; is_loved: boolean; is_edited: boolean; upvotes: number; downvotes: number; user: CommentsApiUser; status: 'published' | 'spam' | 'deleted' | 'pending'; } export type Comment = CommentsApiHiddenComment | CommentsApiRealComment; export interface CommentsApiBaseUser { name: string; username: string; picture_url: string | null; bio: string | null; location: string | null; website_url: string | null; badges: number[]; } export interface CommentsApiGuestUser extends CommentsApiBaseUser { id: undefined; type: null; } export interface CommentsApiLoggedUser extends CommentsApiBaseUser { id: number; type: 'hyvor' | 'sso'; } export type CommentsApiUser = CommentsApiGuestUser | CommentsApiLoggedUser; export {};