import type { DisplayFile } from "./file_thumbnail"; /** Networks whose feed shape and publishing rules this module knows; API-less surfaces (a personal * Facebook profile, a group, a Zalo OA) are pasted by hand. RN-free so an app's publish gate reads it * without rendering. */ export declare const SOCIAL_NETWORKS: readonly ["facebook", "instagram", "threads", "x", "linkedin"]; export type SocialNetwork = (typeof SOCIAL_NETWORKS)[number]; /** The feed's fold (a display fact) and the API's refusals, in one table so preview and gate agree before * publishing. */ export interface SocialNetworkRules { /** In code points; X weights URLs and CJK differently, so there it is a guide. */ maxChars: number; /** `null` when the feed never folds. */ foldChars: number | null; /** `null` when the API sets no count. */ maxImages: number | null; video: "alone" | "mixed"; /** A GIF alone (X) or as an image. */ gif: "alone" | "image"; /** A card, or inert text. */ link: "card" | "text"; linkBesideMedia: boolean; requiresMedia: boolean; } export declare const SOCIAL_NETWORK_RULES: Record; /** Proper nouns, so not in the packs. */ export declare const SOCIAL_NETWORK_LABELS: Record; export interface SocialPostLink { url: string; title?: string; } /** The three things every network takes. */ export interface SocialPostDraft { text: string; media?: readonly DisplayFile[]; link?: SocialPostLink | null; } export type SocialPostIssue = { kind: "empty"; } | { kind: "over_limit"; over: number; max: number; } | { kind: "needs_media"; } | { kind: "too_many_images"; max: number; } | { kind: "video_alone"; } | { kind: "gif_alone"; } | { kind: "link_or_media"; }; /** Code points, so a toned Vietnamese vowel is one character. */ export declare function countSocialChars(text: string): number; /** Everything the network would refuse, from the draft alone, so the gate closes before upload in the * preview's words. Empty promises a well-formed request, not a landed post. */ export declare function socialPostIssues(network: SocialNetwork, draft: SocialPostDraft): SocialPostIssue[]; export interface SocialPostPreviewLabels { more: string; justNow: string; /** No words, no files, and no link the feed draws as the post. */ empty: string; overLimit: (over: number) => string; needsMedia: string; tooManyImages: (max: number) => string; videoAlone: string; gifAlone: string; linkOrMedia: string; } /** The same sentence beside the preview and on the gate. */ export declare function socialPostIssueText(issue: SocialPostIssue, labels: SocialPostPreviewLabels): string;