g-comments 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -0
- package/LICENSE +21 -0
- package/README.md +389 -2
- package/dist/chunk-IBNNENCZ.cjs +3089 -0
- package/dist/chunk-IBNNENCZ.cjs.map +1 -0
- package/dist/chunk-WACVXJHD.js +3068 -0
- package/dist/chunk-WACVXJHD.js.map +1 -0
- package/dist/element.d.ts +823 -0
- package/dist/element.js +1230 -0
- package/dist/element.js.map +1 -0
- package/dist/index.cjs +68 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +37 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/messages-C9bMljl3.d.cts +699 -0
- package/dist/messages-C9bMljl3.d.ts +699 -0
- package/dist/react.cjs +2754 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +335 -0
- package/dist/react.d.ts +335 -0
- package/dist/react.js +2745 -0
- package/dist/react.js.map +1 -0
- package/package.json +90 -4
- package/styles/styles.css +1145 -0
package/dist/react.d.cts
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { g as Comment, V as Pending, o as Commenter, r as CommentsError, T as Messages, C as CreateClientOptions, a as CommentsClient, e as AuthStatus, c as AuthProvider, a1 as SignInOptions, U as OpenThreadOptions, Z as PostResult, a9 as ThreadHandle, ab as ThreadSnapshot, b as CountRef, N as ForumTheme } from './messages-C9bMljl3.cjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `auto` follows `prefers-color-scheme`, `inherit` leaves the colours to the
|
|
7
|
+
* page, and `forum` applies the forum's own palettes, fonts and theme CSS.
|
|
8
|
+
*/
|
|
9
|
+
type Theme = "auto" | "light" | "dark" | "inherit" | "forum";
|
|
10
|
+
/** Design tokens; each is set as `--gc-<kebab-case name>` on the widget root. */
|
|
11
|
+
type AppearanceVariable = "font" | "fg" | "fgMuted" | "bg" | "bgSubtle" | "border" | "accent" | "accentFg" | "danger" | "radius" | "shadow" | "space" | "avatarSize";
|
|
12
|
+
/** Elements that accept extra class names through `appearance.elements`. */
|
|
13
|
+
type AppearanceElement = "root" | "header" | "count" | "sort" | "signIn" | "composer" | "textarea" | "toolbar" | "list" | "comment" | "avatar" | "meta" | "body" | "actions" | "menu" | "button" | "primaryButton" | "loadMore" | "pill" | "notice" | "dialog";
|
|
14
|
+
interface Appearance {
|
|
15
|
+
/** Token overrides, e.g. `{ accent: "var(--brand)", radius: "0" }`. */
|
|
16
|
+
variables?: Partial<Record<AppearanceVariable, string>>;
|
|
17
|
+
/** Extra class names, e.g. `{ comment: "card", button: "btn" }`. */
|
|
18
|
+
elements?: Partial<Record<AppearanceElement, string>>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** What the widget was doing when an `error` event fired. */
|
|
22
|
+
type CommentsAction = "open" | "load" | "loadMore" | "loadReplies" | "context" | "post" | "edit" | "delete" | "like" | "flag" | "pin" | "upload" | "preview" | "signIn" | "theme";
|
|
23
|
+
/** Delivered to `<DiscourseComments onEvent>`. */
|
|
24
|
+
type CommentsEvent = {
|
|
25
|
+
type: "comment.posted";
|
|
26
|
+
threadId: string;
|
|
27
|
+
comment: Comment;
|
|
28
|
+
}
|
|
29
|
+
/** The comment went to the review queue instead of being published. */
|
|
30
|
+
| {
|
|
31
|
+
type: "comment.pending";
|
|
32
|
+
threadId: string;
|
|
33
|
+
pending: Pending;
|
|
34
|
+
} | {
|
|
35
|
+
type: "comment.liked";
|
|
36
|
+
threadId: string;
|
|
37
|
+
comment: Comment;
|
|
38
|
+
liked: boolean;
|
|
39
|
+
} | {
|
|
40
|
+
type: "auth.signedIn";
|
|
41
|
+
user: Commenter;
|
|
42
|
+
}
|
|
43
|
+
/** `expired` is true when the forum ended the session (the key was revoked or expired). */
|
|
44
|
+
| {
|
|
45
|
+
type: "auth.signedOut";
|
|
46
|
+
expired: boolean;
|
|
47
|
+
} | {
|
|
48
|
+
type: "error";
|
|
49
|
+
action: CommentsAction;
|
|
50
|
+
error: CommentsError;
|
|
51
|
+
threadId?: string;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
interface ProviderOptions {
|
|
55
|
+
children?: ReactNode;
|
|
56
|
+
/** Default appearance for every widget inside; widgets merge their own on top. */
|
|
57
|
+
appearance?: Appearance;
|
|
58
|
+
/** UI language (`en`, `pt-BR`; other `pt*` map to `pt-BR`), also sent as `Accept-Language`. */
|
|
59
|
+
locale?: string;
|
|
60
|
+
/** Overrides for individual UI strings. */
|
|
61
|
+
messages?: Partial<Messages>;
|
|
62
|
+
theme?: Theme;
|
|
63
|
+
/** Logs client activity and shows setup diagnostics outside localhost. */
|
|
64
|
+
debug?: boolean;
|
|
65
|
+
onEvent?: (event: CommentsEvent) => void;
|
|
66
|
+
}
|
|
67
|
+
/** Client options beyond `forum`; they apply when the shared client is first created. */
|
|
68
|
+
type ClientCreationOptions = Omit<CreateClientOptions, "forum" | "locale" | "debug">;
|
|
69
|
+
type DiscourseCommentsProps = ProviderOptions & (({
|
|
70
|
+
forum: string;
|
|
71
|
+
client?: undefined;
|
|
72
|
+
} & ClientCreationOptions) | {
|
|
73
|
+
client: CommentsClient;
|
|
74
|
+
forum?: undefined;
|
|
75
|
+
});
|
|
76
|
+
/**
|
|
77
|
+
* Shares one client (auth, config, counts batching, realtime) with every
|
|
78
|
+
* comments widget and hook below it.
|
|
79
|
+
*/
|
|
80
|
+
declare function DiscourseComments(props: DiscourseCommentsProps): react.JSX.Element;
|
|
81
|
+
|
|
82
|
+
/** The client the surrounding `<DiscourseComments>` provides. */
|
|
83
|
+
declare function useClient(): CommentsClient;
|
|
84
|
+
|
|
85
|
+
interface PartProps {
|
|
86
|
+
className?: string;
|
|
87
|
+
}
|
|
88
|
+
declare function Avatar({ className }: PartProps): react.JSX.Element;
|
|
89
|
+
/** Author, badges, timestamp (a `#gc-<id>` permalink) and edited mark. */
|
|
90
|
+
declare function Meta({ className }: PartProps): react.JSX.Element;
|
|
91
|
+
/** The comment's cooked HTML, or its inline editor while editing. */
|
|
92
|
+
declare function Body({ className }: PartProps): react.JSX.Element;
|
|
93
|
+
/** Like, reply and a menu with copy link, edit, delete, report and feature. */
|
|
94
|
+
declare function Actions({ className }: PartProps): react.JSX.Element | null;
|
|
95
|
+
|
|
96
|
+
interface ComposerProps {
|
|
97
|
+
/** Replies to this comment (the inline reply composer). */
|
|
98
|
+
replyTo?: Comment;
|
|
99
|
+
/** Edits this comment; its markdown is loaded from the forum. */
|
|
100
|
+
editing?: Comment;
|
|
101
|
+
placeholder?: string;
|
|
102
|
+
autoFocus?: boolean;
|
|
103
|
+
/** Called after a successful post or save, and when the reader cancels. */
|
|
104
|
+
onDone?: () => void;
|
|
105
|
+
className?: string;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* The markdown composer. Without `replyTo`/`editing` it is the thread's main
|
|
109
|
+
* composer and renders only when the reader may write (or may sign in on submit).
|
|
110
|
+
*/
|
|
111
|
+
declare function Composer(props: ComposerProps): react.JSX.Element | null;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Explains setup problems (origin not allowed, plugin disabled, basic auth
|
|
115
|
+
* blocking preflights…). Renders on localhost-like hosts or with `debug`.
|
|
116
|
+
*/
|
|
117
|
+
declare function DevPanel({ className }: {
|
|
118
|
+
className?: string;
|
|
119
|
+
}): react.JSX.Element | null;
|
|
120
|
+
|
|
121
|
+
interface HeaderProps {
|
|
122
|
+
/** Defaults to `<Comments.Count />` and `<Comments.Sort />`. */
|
|
123
|
+
children?: ReactNode;
|
|
124
|
+
className?: string;
|
|
125
|
+
}
|
|
126
|
+
declare function Header({ children, className }: HeaderProps): react.JSX.Element;
|
|
127
|
+
interface CountProps {
|
|
128
|
+
/** Heading element; `h2` by default. */
|
|
129
|
+
as?: "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span";
|
|
130
|
+
/** Custom content for the comment count, e.g. `(n) => n`. */
|
|
131
|
+
render?: (count: number) => ReactNode;
|
|
132
|
+
className?: string;
|
|
133
|
+
}
|
|
134
|
+
declare function Count({ as: Tag, render, className }: CountProps): react.JSX.Element;
|
|
135
|
+
declare function Sort({ className }: {
|
|
136
|
+
className?: string;
|
|
137
|
+
}): react.JSX.Element | null;
|
|
138
|
+
|
|
139
|
+
type RenderComment = (comment: Comment, depth: number) => ReactNode;
|
|
140
|
+
interface ListProps {
|
|
141
|
+
/** Renders one comment; defaults to `<Comments.Item comment={c} depth={depth} />`. */
|
|
142
|
+
children?: RenderComment;
|
|
143
|
+
className?: string;
|
|
144
|
+
}
|
|
145
|
+
/** The comment tree, with its loading, error and "continue this thread" states. */
|
|
146
|
+
declare function List({ children, className }: ListProps): react.JSX.Element | null;
|
|
147
|
+
interface ItemProps {
|
|
148
|
+
comment: Comment;
|
|
149
|
+
/** 0 for top-level comments. */
|
|
150
|
+
depth?: number;
|
|
151
|
+
/** Replaces the default avatar, meta, body and actions. */
|
|
152
|
+
children?: ReactNode;
|
|
153
|
+
/** Render the comment without its replies (used for ancestors in a focused branch). */
|
|
154
|
+
showReplies?: boolean;
|
|
155
|
+
className?: string;
|
|
156
|
+
}
|
|
157
|
+
/** One comment: its card, inline reply/edit/report panels and its replies. */
|
|
158
|
+
declare function Item({ comment, depth, children, showReplies, className }: ItemProps): react.JSX.Element;
|
|
159
|
+
|
|
160
|
+
interface CommenterState {
|
|
161
|
+
user: Commenter | null;
|
|
162
|
+
status: AuthStatus;
|
|
163
|
+
/** The forum's sign-in providers; empty until the forum config has loaded. */
|
|
164
|
+
providers: readonly AuthProvider[];
|
|
165
|
+
/** The forum is answering anonymously under load: treat the widget as read-only. */
|
|
166
|
+
degraded: boolean;
|
|
167
|
+
/** Why the last sign-in failed or the session ended. */
|
|
168
|
+
error: CommentsError | null;
|
|
169
|
+
/** Opens the forum's sign-in popup; call it from a click handler so it is not blocked. */
|
|
170
|
+
signIn(options?: SignInOptions): Promise<Commenter | null>;
|
|
171
|
+
cancelSignIn(): void;
|
|
172
|
+
signOut(): Promise<void>;
|
|
173
|
+
}
|
|
174
|
+
/** The signed-in reader of the provider's forum (or of `forum`). */
|
|
175
|
+
declare function useCommenter(options?: {
|
|
176
|
+
forum?: string;
|
|
177
|
+
}): CommenterState;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Where signing in happens: `inline` shows a "Join the conversation" panel,
|
|
181
|
+
* `on-submit` lets anonymous readers write and signs them in when they post,
|
|
182
|
+
* `manual` leaves it to the site (`useCommenter().signIn()`).
|
|
183
|
+
*/
|
|
184
|
+
type SignInMode = "inline" | "on-submit" | "manual";
|
|
185
|
+
interface CommentsProps extends OpenThreadOptions {
|
|
186
|
+
/** Uses the shared client for this forum instead of the provider's. */
|
|
187
|
+
forum?: string;
|
|
188
|
+
/** Visual nesting levels; deeper replies collapse into "Continue this thread". */
|
|
189
|
+
maxDepth?: number;
|
|
190
|
+
signIn?: SignInMode;
|
|
191
|
+
/**
|
|
192
|
+
* With `signIn="manual"`, called when an anonymous reader tries to like or
|
|
193
|
+
* reply, so the site can start its own sign-in. Without it those actions are
|
|
194
|
+
* unavailable to anonymous readers in manual mode.
|
|
195
|
+
*/
|
|
196
|
+
onSignInRequired?: () => void;
|
|
197
|
+
/** Hides every write action. */
|
|
198
|
+
readOnly?: boolean;
|
|
199
|
+
/** Comment id to scroll to and highlight; defaults to the `#gc-<id>` fragment. */
|
|
200
|
+
highlight?: number | null;
|
|
201
|
+
/** Shown above the composer; defaults to the forum's setting. */
|
|
202
|
+
guidelinesUrl?: string;
|
|
203
|
+
onPosted?: (result: PostResult) => void;
|
|
204
|
+
appearance?: Appearance;
|
|
205
|
+
/** Renders without the default styles; class names stay for targeting. */
|
|
206
|
+
unstyled?: boolean;
|
|
207
|
+
theme?: Theme;
|
|
208
|
+
locale?: string;
|
|
209
|
+
className?: string;
|
|
210
|
+
}
|
|
211
|
+
interface RootProps extends CommentsProps {
|
|
212
|
+
children?: ReactNode;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Opens the thread and provides it to the primitives inside. Without a
|
|
216
|
+
* provider or `forum` nothing can be opened, so it renders a quiet notice
|
|
217
|
+
* instead of throwing (a consumer's tests may mount pages without one).
|
|
218
|
+
*/
|
|
219
|
+
declare function Root(props: RootProps): react.JSX.Element;
|
|
220
|
+
|
|
221
|
+
interface SignInProps {
|
|
222
|
+
/** Custom UI; called in every sign-in mode, including `manual`. */
|
|
223
|
+
children?: (commenter: CommenterState) => ReactNode;
|
|
224
|
+
className?: string;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Inline mode: a "Join the conversation" panel with the forum's providers.
|
|
228
|
+
* Signed in: who is commenting, with a sign-out button.
|
|
229
|
+
*/
|
|
230
|
+
declare function SignIn({ children, className }: SignInProps): react.JSX.Element | null;
|
|
231
|
+
|
|
232
|
+
/** Read-only, closed and not-allowed notices that replace the composer. */
|
|
233
|
+
declare function Notice({ className }: {
|
|
234
|
+
className?: string;
|
|
235
|
+
}): react.JSX.Element | null;
|
|
236
|
+
/** The "N new comments" pill for top-level comments that arrived live. */
|
|
237
|
+
declare function NewComments({ className }: {
|
|
238
|
+
className?: string;
|
|
239
|
+
}): react.JSX.Element;
|
|
240
|
+
/** The reader's own comments that went to the review queue. */
|
|
241
|
+
declare function AwaitingApproval({ className }: {
|
|
242
|
+
className?: string;
|
|
243
|
+
}): react.JSX.Element;
|
|
244
|
+
declare function LoadMore({ className }: {
|
|
245
|
+
className?: string;
|
|
246
|
+
}): react.JSX.Element | null;
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* The drop-in comments section for the current page, assembled from the
|
|
250
|
+
* `Comments.*` primitives that are also exported for custom layouts.
|
|
251
|
+
*/
|
|
252
|
+
declare function CommentsSection(props: CommentsProps): react.JSX.Element;
|
|
253
|
+
declare const Comments: typeof CommentsSection & {
|
|
254
|
+
Root: typeof Root;
|
|
255
|
+
Header: typeof Header;
|
|
256
|
+
Count: typeof Count;
|
|
257
|
+
Sort: typeof Sort;
|
|
258
|
+
SignIn: typeof SignIn;
|
|
259
|
+
Composer: typeof Composer;
|
|
260
|
+
List: typeof List;
|
|
261
|
+
Item: typeof Item;
|
|
262
|
+
Avatar: typeof Avatar;
|
|
263
|
+
Meta: typeof Meta;
|
|
264
|
+
Body: typeof Body;
|
|
265
|
+
Actions: typeof Actions;
|
|
266
|
+
LoadMore: typeof LoadMore;
|
|
267
|
+
NewComments: typeof NewComments;
|
|
268
|
+
AwaitingApproval: typeof AwaitingApproval;
|
|
269
|
+
Notice: typeof Notice;
|
|
270
|
+
DevPanel: typeof DevPanel;
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
interface CommentCountProps {
|
|
274
|
+
identifier?: string;
|
|
275
|
+
/** Host the `identifier` belongs to; defaults to the current page's host. */
|
|
276
|
+
host?: string;
|
|
277
|
+
/** Defaults to the current page (canonical link, else the address). */
|
|
278
|
+
url?: string;
|
|
279
|
+
topicId?: number;
|
|
280
|
+
/** Uses the shared client for this forum instead of the provider's. */
|
|
281
|
+
forum?: string;
|
|
282
|
+
/** Custom content, e.g. `(n) => n` for just the number. */
|
|
283
|
+
render?: (count: number) => ReactNode;
|
|
284
|
+
className?: string;
|
|
285
|
+
}
|
|
286
|
+
/** "12 comments" for a page, fetched once on mount and batched with other counts. */
|
|
287
|
+
declare function CommentCount({ identifier, host, url, topicId, forum, render, className, }: CommentCountProps): react.JSX.Element | null;
|
|
288
|
+
|
|
289
|
+
interface UseThreadOptions extends OpenThreadOptions {
|
|
290
|
+
/** Uses the shared client for this forum instead of the provider's. */
|
|
291
|
+
forum?: string;
|
|
292
|
+
}
|
|
293
|
+
interface UseThreadResult {
|
|
294
|
+
/** `null` until the thread has been opened. */
|
|
295
|
+
thread: ThreadHandle | null;
|
|
296
|
+
/** Re-rendered on every change; `null` until the thread has been opened. */
|
|
297
|
+
snapshot: ThreadSnapshot | null;
|
|
298
|
+
/** Why the thread could not be opened; load failures live in `snapshot.error`. */
|
|
299
|
+
error: CommentsError | null;
|
|
300
|
+
/** Opens the thread again after `error`, or reloads it after a failed load. */
|
|
301
|
+
retry(): void;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Opens the page's thread and keeps a live snapshot of it. The handle is
|
|
305
|
+
* disposed on unmount and reopened when `identifier`, `url` or (without `url`)
|
|
306
|
+
* the page address changes; `sort` changes reload the same handle.
|
|
307
|
+
*/
|
|
308
|
+
declare function useThread(options?: UseThreadOptions): UseThreadResult;
|
|
309
|
+
|
|
310
|
+
interface CommentCountState {
|
|
311
|
+
/** `null` while loading or after an error. */
|
|
312
|
+
count: number | null;
|
|
313
|
+
error: CommentsError | null;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Fetches a comment count once per ref. Lookups from the same render are
|
|
317
|
+
* batched into one request by the client; the count is not live.
|
|
318
|
+
*/
|
|
319
|
+
declare function useCommentCount(ref: CountRef | null, options?: {
|
|
320
|
+
forum?: string;
|
|
321
|
+
}): CommentCountState;
|
|
322
|
+
|
|
323
|
+
interface ForumThemeState {
|
|
324
|
+
/** `null` until loaded (or when `enabled` is false). */
|
|
325
|
+
theme: ForumTheme | null;
|
|
326
|
+
error: CommentsError | null;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* The forum's palettes, fonts and theme stylesheets (`GET /comments/theme`),
|
|
330
|
+
* for sites that style their own UI after the forum. `<Comments theme="forum">`
|
|
331
|
+
* applies the same data to the widget.
|
|
332
|
+
*/
|
|
333
|
+
declare function useForumTheme(): ForumThemeState;
|
|
334
|
+
|
|
335
|
+
export { type Appearance, type AppearanceElement, type AppearanceVariable, CommentCount, type CommentCountProps, type CommentCountState, type CommenterState, Comments, type CommentsAction, type CommentsEvent, type CommentsProps, type ComposerProps, type CountProps, DiscourseComments, type DiscourseCommentsProps, type ForumThemeState, type HeaderProps, type ItemProps, type ListProps, type RenderComment, type RootProps, type SignInMode, type SignInProps, type Theme, type UseThreadOptions, type UseThreadResult, useClient, useCommentCount, useCommenter, useForumTheme, useThread };
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { g as Comment, V as Pending, o as Commenter, r as CommentsError, T as Messages, C as CreateClientOptions, a as CommentsClient, e as AuthStatus, c as AuthProvider, a1 as SignInOptions, U as OpenThreadOptions, Z as PostResult, a9 as ThreadHandle, ab as ThreadSnapshot, b as CountRef, N as ForumTheme } from './messages-C9bMljl3.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `auto` follows `prefers-color-scheme`, `inherit` leaves the colours to the
|
|
7
|
+
* page, and `forum` applies the forum's own palettes, fonts and theme CSS.
|
|
8
|
+
*/
|
|
9
|
+
type Theme = "auto" | "light" | "dark" | "inherit" | "forum";
|
|
10
|
+
/** Design tokens; each is set as `--gc-<kebab-case name>` on the widget root. */
|
|
11
|
+
type AppearanceVariable = "font" | "fg" | "fgMuted" | "bg" | "bgSubtle" | "border" | "accent" | "accentFg" | "danger" | "radius" | "shadow" | "space" | "avatarSize";
|
|
12
|
+
/** Elements that accept extra class names through `appearance.elements`. */
|
|
13
|
+
type AppearanceElement = "root" | "header" | "count" | "sort" | "signIn" | "composer" | "textarea" | "toolbar" | "list" | "comment" | "avatar" | "meta" | "body" | "actions" | "menu" | "button" | "primaryButton" | "loadMore" | "pill" | "notice" | "dialog";
|
|
14
|
+
interface Appearance {
|
|
15
|
+
/** Token overrides, e.g. `{ accent: "var(--brand)", radius: "0" }`. */
|
|
16
|
+
variables?: Partial<Record<AppearanceVariable, string>>;
|
|
17
|
+
/** Extra class names, e.g. `{ comment: "card", button: "btn" }`. */
|
|
18
|
+
elements?: Partial<Record<AppearanceElement, string>>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** What the widget was doing when an `error` event fired. */
|
|
22
|
+
type CommentsAction = "open" | "load" | "loadMore" | "loadReplies" | "context" | "post" | "edit" | "delete" | "like" | "flag" | "pin" | "upload" | "preview" | "signIn" | "theme";
|
|
23
|
+
/** Delivered to `<DiscourseComments onEvent>`. */
|
|
24
|
+
type CommentsEvent = {
|
|
25
|
+
type: "comment.posted";
|
|
26
|
+
threadId: string;
|
|
27
|
+
comment: Comment;
|
|
28
|
+
}
|
|
29
|
+
/** The comment went to the review queue instead of being published. */
|
|
30
|
+
| {
|
|
31
|
+
type: "comment.pending";
|
|
32
|
+
threadId: string;
|
|
33
|
+
pending: Pending;
|
|
34
|
+
} | {
|
|
35
|
+
type: "comment.liked";
|
|
36
|
+
threadId: string;
|
|
37
|
+
comment: Comment;
|
|
38
|
+
liked: boolean;
|
|
39
|
+
} | {
|
|
40
|
+
type: "auth.signedIn";
|
|
41
|
+
user: Commenter;
|
|
42
|
+
}
|
|
43
|
+
/** `expired` is true when the forum ended the session (the key was revoked or expired). */
|
|
44
|
+
| {
|
|
45
|
+
type: "auth.signedOut";
|
|
46
|
+
expired: boolean;
|
|
47
|
+
} | {
|
|
48
|
+
type: "error";
|
|
49
|
+
action: CommentsAction;
|
|
50
|
+
error: CommentsError;
|
|
51
|
+
threadId?: string;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
interface ProviderOptions {
|
|
55
|
+
children?: ReactNode;
|
|
56
|
+
/** Default appearance for every widget inside; widgets merge their own on top. */
|
|
57
|
+
appearance?: Appearance;
|
|
58
|
+
/** UI language (`en`, `pt-BR`; other `pt*` map to `pt-BR`), also sent as `Accept-Language`. */
|
|
59
|
+
locale?: string;
|
|
60
|
+
/** Overrides for individual UI strings. */
|
|
61
|
+
messages?: Partial<Messages>;
|
|
62
|
+
theme?: Theme;
|
|
63
|
+
/** Logs client activity and shows setup diagnostics outside localhost. */
|
|
64
|
+
debug?: boolean;
|
|
65
|
+
onEvent?: (event: CommentsEvent) => void;
|
|
66
|
+
}
|
|
67
|
+
/** Client options beyond `forum`; they apply when the shared client is first created. */
|
|
68
|
+
type ClientCreationOptions = Omit<CreateClientOptions, "forum" | "locale" | "debug">;
|
|
69
|
+
type DiscourseCommentsProps = ProviderOptions & (({
|
|
70
|
+
forum: string;
|
|
71
|
+
client?: undefined;
|
|
72
|
+
} & ClientCreationOptions) | {
|
|
73
|
+
client: CommentsClient;
|
|
74
|
+
forum?: undefined;
|
|
75
|
+
});
|
|
76
|
+
/**
|
|
77
|
+
* Shares one client (auth, config, counts batching, realtime) with every
|
|
78
|
+
* comments widget and hook below it.
|
|
79
|
+
*/
|
|
80
|
+
declare function DiscourseComments(props: DiscourseCommentsProps): react.JSX.Element;
|
|
81
|
+
|
|
82
|
+
/** The client the surrounding `<DiscourseComments>` provides. */
|
|
83
|
+
declare function useClient(): CommentsClient;
|
|
84
|
+
|
|
85
|
+
interface PartProps {
|
|
86
|
+
className?: string;
|
|
87
|
+
}
|
|
88
|
+
declare function Avatar({ className }: PartProps): react.JSX.Element;
|
|
89
|
+
/** Author, badges, timestamp (a `#gc-<id>` permalink) and edited mark. */
|
|
90
|
+
declare function Meta({ className }: PartProps): react.JSX.Element;
|
|
91
|
+
/** The comment's cooked HTML, or its inline editor while editing. */
|
|
92
|
+
declare function Body({ className }: PartProps): react.JSX.Element;
|
|
93
|
+
/** Like, reply and a menu with copy link, edit, delete, report and feature. */
|
|
94
|
+
declare function Actions({ className }: PartProps): react.JSX.Element | null;
|
|
95
|
+
|
|
96
|
+
interface ComposerProps {
|
|
97
|
+
/** Replies to this comment (the inline reply composer). */
|
|
98
|
+
replyTo?: Comment;
|
|
99
|
+
/** Edits this comment; its markdown is loaded from the forum. */
|
|
100
|
+
editing?: Comment;
|
|
101
|
+
placeholder?: string;
|
|
102
|
+
autoFocus?: boolean;
|
|
103
|
+
/** Called after a successful post or save, and when the reader cancels. */
|
|
104
|
+
onDone?: () => void;
|
|
105
|
+
className?: string;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* The markdown composer. Without `replyTo`/`editing` it is the thread's main
|
|
109
|
+
* composer and renders only when the reader may write (or may sign in on submit).
|
|
110
|
+
*/
|
|
111
|
+
declare function Composer(props: ComposerProps): react.JSX.Element | null;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Explains setup problems (origin not allowed, plugin disabled, basic auth
|
|
115
|
+
* blocking preflights…). Renders on localhost-like hosts or with `debug`.
|
|
116
|
+
*/
|
|
117
|
+
declare function DevPanel({ className }: {
|
|
118
|
+
className?: string;
|
|
119
|
+
}): react.JSX.Element | null;
|
|
120
|
+
|
|
121
|
+
interface HeaderProps {
|
|
122
|
+
/** Defaults to `<Comments.Count />` and `<Comments.Sort />`. */
|
|
123
|
+
children?: ReactNode;
|
|
124
|
+
className?: string;
|
|
125
|
+
}
|
|
126
|
+
declare function Header({ children, className }: HeaderProps): react.JSX.Element;
|
|
127
|
+
interface CountProps {
|
|
128
|
+
/** Heading element; `h2` by default. */
|
|
129
|
+
as?: "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span";
|
|
130
|
+
/** Custom content for the comment count, e.g. `(n) => n`. */
|
|
131
|
+
render?: (count: number) => ReactNode;
|
|
132
|
+
className?: string;
|
|
133
|
+
}
|
|
134
|
+
declare function Count({ as: Tag, render, className }: CountProps): react.JSX.Element;
|
|
135
|
+
declare function Sort({ className }: {
|
|
136
|
+
className?: string;
|
|
137
|
+
}): react.JSX.Element | null;
|
|
138
|
+
|
|
139
|
+
type RenderComment = (comment: Comment, depth: number) => ReactNode;
|
|
140
|
+
interface ListProps {
|
|
141
|
+
/** Renders one comment; defaults to `<Comments.Item comment={c} depth={depth} />`. */
|
|
142
|
+
children?: RenderComment;
|
|
143
|
+
className?: string;
|
|
144
|
+
}
|
|
145
|
+
/** The comment tree, with its loading, error and "continue this thread" states. */
|
|
146
|
+
declare function List({ children, className }: ListProps): react.JSX.Element | null;
|
|
147
|
+
interface ItemProps {
|
|
148
|
+
comment: Comment;
|
|
149
|
+
/** 0 for top-level comments. */
|
|
150
|
+
depth?: number;
|
|
151
|
+
/** Replaces the default avatar, meta, body and actions. */
|
|
152
|
+
children?: ReactNode;
|
|
153
|
+
/** Render the comment without its replies (used for ancestors in a focused branch). */
|
|
154
|
+
showReplies?: boolean;
|
|
155
|
+
className?: string;
|
|
156
|
+
}
|
|
157
|
+
/** One comment: its card, inline reply/edit/report panels and its replies. */
|
|
158
|
+
declare function Item({ comment, depth, children, showReplies, className }: ItemProps): react.JSX.Element;
|
|
159
|
+
|
|
160
|
+
interface CommenterState {
|
|
161
|
+
user: Commenter | null;
|
|
162
|
+
status: AuthStatus;
|
|
163
|
+
/** The forum's sign-in providers; empty until the forum config has loaded. */
|
|
164
|
+
providers: readonly AuthProvider[];
|
|
165
|
+
/** The forum is answering anonymously under load: treat the widget as read-only. */
|
|
166
|
+
degraded: boolean;
|
|
167
|
+
/** Why the last sign-in failed or the session ended. */
|
|
168
|
+
error: CommentsError | null;
|
|
169
|
+
/** Opens the forum's sign-in popup; call it from a click handler so it is not blocked. */
|
|
170
|
+
signIn(options?: SignInOptions): Promise<Commenter | null>;
|
|
171
|
+
cancelSignIn(): void;
|
|
172
|
+
signOut(): Promise<void>;
|
|
173
|
+
}
|
|
174
|
+
/** The signed-in reader of the provider's forum (or of `forum`). */
|
|
175
|
+
declare function useCommenter(options?: {
|
|
176
|
+
forum?: string;
|
|
177
|
+
}): CommenterState;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Where signing in happens: `inline` shows a "Join the conversation" panel,
|
|
181
|
+
* `on-submit` lets anonymous readers write and signs them in when they post,
|
|
182
|
+
* `manual` leaves it to the site (`useCommenter().signIn()`).
|
|
183
|
+
*/
|
|
184
|
+
type SignInMode = "inline" | "on-submit" | "manual";
|
|
185
|
+
interface CommentsProps extends OpenThreadOptions {
|
|
186
|
+
/** Uses the shared client for this forum instead of the provider's. */
|
|
187
|
+
forum?: string;
|
|
188
|
+
/** Visual nesting levels; deeper replies collapse into "Continue this thread". */
|
|
189
|
+
maxDepth?: number;
|
|
190
|
+
signIn?: SignInMode;
|
|
191
|
+
/**
|
|
192
|
+
* With `signIn="manual"`, called when an anonymous reader tries to like or
|
|
193
|
+
* reply, so the site can start its own sign-in. Without it those actions are
|
|
194
|
+
* unavailable to anonymous readers in manual mode.
|
|
195
|
+
*/
|
|
196
|
+
onSignInRequired?: () => void;
|
|
197
|
+
/** Hides every write action. */
|
|
198
|
+
readOnly?: boolean;
|
|
199
|
+
/** Comment id to scroll to and highlight; defaults to the `#gc-<id>` fragment. */
|
|
200
|
+
highlight?: number | null;
|
|
201
|
+
/** Shown above the composer; defaults to the forum's setting. */
|
|
202
|
+
guidelinesUrl?: string;
|
|
203
|
+
onPosted?: (result: PostResult) => void;
|
|
204
|
+
appearance?: Appearance;
|
|
205
|
+
/** Renders without the default styles; class names stay for targeting. */
|
|
206
|
+
unstyled?: boolean;
|
|
207
|
+
theme?: Theme;
|
|
208
|
+
locale?: string;
|
|
209
|
+
className?: string;
|
|
210
|
+
}
|
|
211
|
+
interface RootProps extends CommentsProps {
|
|
212
|
+
children?: ReactNode;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Opens the thread and provides it to the primitives inside. Without a
|
|
216
|
+
* provider or `forum` nothing can be opened, so it renders a quiet notice
|
|
217
|
+
* instead of throwing (a consumer's tests may mount pages without one).
|
|
218
|
+
*/
|
|
219
|
+
declare function Root(props: RootProps): react.JSX.Element;
|
|
220
|
+
|
|
221
|
+
interface SignInProps {
|
|
222
|
+
/** Custom UI; called in every sign-in mode, including `manual`. */
|
|
223
|
+
children?: (commenter: CommenterState) => ReactNode;
|
|
224
|
+
className?: string;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Inline mode: a "Join the conversation" panel with the forum's providers.
|
|
228
|
+
* Signed in: who is commenting, with a sign-out button.
|
|
229
|
+
*/
|
|
230
|
+
declare function SignIn({ children, className }: SignInProps): react.JSX.Element | null;
|
|
231
|
+
|
|
232
|
+
/** Read-only, closed and not-allowed notices that replace the composer. */
|
|
233
|
+
declare function Notice({ className }: {
|
|
234
|
+
className?: string;
|
|
235
|
+
}): react.JSX.Element | null;
|
|
236
|
+
/** The "N new comments" pill for top-level comments that arrived live. */
|
|
237
|
+
declare function NewComments({ className }: {
|
|
238
|
+
className?: string;
|
|
239
|
+
}): react.JSX.Element;
|
|
240
|
+
/** The reader's own comments that went to the review queue. */
|
|
241
|
+
declare function AwaitingApproval({ className }: {
|
|
242
|
+
className?: string;
|
|
243
|
+
}): react.JSX.Element;
|
|
244
|
+
declare function LoadMore({ className }: {
|
|
245
|
+
className?: string;
|
|
246
|
+
}): react.JSX.Element | null;
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* The drop-in comments section for the current page, assembled from the
|
|
250
|
+
* `Comments.*` primitives that are also exported for custom layouts.
|
|
251
|
+
*/
|
|
252
|
+
declare function CommentsSection(props: CommentsProps): react.JSX.Element;
|
|
253
|
+
declare const Comments: typeof CommentsSection & {
|
|
254
|
+
Root: typeof Root;
|
|
255
|
+
Header: typeof Header;
|
|
256
|
+
Count: typeof Count;
|
|
257
|
+
Sort: typeof Sort;
|
|
258
|
+
SignIn: typeof SignIn;
|
|
259
|
+
Composer: typeof Composer;
|
|
260
|
+
List: typeof List;
|
|
261
|
+
Item: typeof Item;
|
|
262
|
+
Avatar: typeof Avatar;
|
|
263
|
+
Meta: typeof Meta;
|
|
264
|
+
Body: typeof Body;
|
|
265
|
+
Actions: typeof Actions;
|
|
266
|
+
LoadMore: typeof LoadMore;
|
|
267
|
+
NewComments: typeof NewComments;
|
|
268
|
+
AwaitingApproval: typeof AwaitingApproval;
|
|
269
|
+
Notice: typeof Notice;
|
|
270
|
+
DevPanel: typeof DevPanel;
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
interface CommentCountProps {
|
|
274
|
+
identifier?: string;
|
|
275
|
+
/** Host the `identifier` belongs to; defaults to the current page's host. */
|
|
276
|
+
host?: string;
|
|
277
|
+
/** Defaults to the current page (canonical link, else the address). */
|
|
278
|
+
url?: string;
|
|
279
|
+
topicId?: number;
|
|
280
|
+
/** Uses the shared client for this forum instead of the provider's. */
|
|
281
|
+
forum?: string;
|
|
282
|
+
/** Custom content, e.g. `(n) => n` for just the number. */
|
|
283
|
+
render?: (count: number) => ReactNode;
|
|
284
|
+
className?: string;
|
|
285
|
+
}
|
|
286
|
+
/** "12 comments" for a page, fetched once on mount and batched with other counts. */
|
|
287
|
+
declare function CommentCount({ identifier, host, url, topicId, forum, render, className, }: CommentCountProps): react.JSX.Element | null;
|
|
288
|
+
|
|
289
|
+
interface UseThreadOptions extends OpenThreadOptions {
|
|
290
|
+
/** Uses the shared client for this forum instead of the provider's. */
|
|
291
|
+
forum?: string;
|
|
292
|
+
}
|
|
293
|
+
interface UseThreadResult {
|
|
294
|
+
/** `null` until the thread has been opened. */
|
|
295
|
+
thread: ThreadHandle | null;
|
|
296
|
+
/** Re-rendered on every change; `null` until the thread has been opened. */
|
|
297
|
+
snapshot: ThreadSnapshot | null;
|
|
298
|
+
/** Why the thread could not be opened; load failures live in `snapshot.error`. */
|
|
299
|
+
error: CommentsError | null;
|
|
300
|
+
/** Opens the thread again after `error`, or reloads it after a failed load. */
|
|
301
|
+
retry(): void;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Opens the page's thread and keeps a live snapshot of it. The handle is
|
|
305
|
+
* disposed on unmount and reopened when `identifier`, `url` or (without `url`)
|
|
306
|
+
* the page address changes; `sort` changes reload the same handle.
|
|
307
|
+
*/
|
|
308
|
+
declare function useThread(options?: UseThreadOptions): UseThreadResult;
|
|
309
|
+
|
|
310
|
+
interface CommentCountState {
|
|
311
|
+
/** `null` while loading or after an error. */
|
|
312
|
+
count: number | null;
|
|
313
|
+
error: CommentsError | null;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Fetches a comment count once per ref. Lookups from the same render are
|
|
317
|
+
* batched into one request by the client; the count is not live.
|
|
318
|
+
*/
|
|
319
|
+
declare function useCommentCount(ref: CountRef | null, options?: {
|
|
320
|
+
forum?: string;
|
|
321
|
+
}): CommentCountState;
|
|
322
|
+
|
|
323
|
+
interface ForumThemeState {
|
|
324
|
+
/** `null` until loaded (or when `enabled` is false). */
|
|
325
|
+
theme: ForumTheme | null;
|
|
326
|
+
error: CommentsError | null;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* The forum's palettes, fonts and theme stylesheets (`GET /comments/theme`),
|
|
330
|
+
* for sites that style their own UI after the forum. `<Comments theme="forum">`
|
|
331
|
+
* applies the same data to the widget.
|
|
332
|
+
*/
|
|
333
|
+
declare function useForumTheme(): ForumThemeState;
|
|
334
|
+
|
|
335
|
+
export { type Appearance, type AppearanceElement, type AppearanceVariable, CommentCount, type CommentCountProps, type CommentCountState, type CommenterState, Comments, type CommentsAction, type CommentsEvent, type CommentsProps, type ComposerProps, type CountProps, DiscourseComments, type DiscourseCommentsProps, type ForumThemeState, type HeaderProps, type ItemProps, type ListProps, type RenderComment, type RootProps, type SignInMode, type SignInProps, type Theme, type UseThreadOptions, type UseThreadResult, useClient, useCommentCount, useCommenter, useForumTheme, useThread };
|