nostr-comments 0.1.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.
Files changed (53) hide show
  1. package/README.md +294 -0
  2. package/dist/NostrComments.d.ts +2 -0
  3. package/dist/components/Avatar.d.ts +7 -0
  4. package/dist/components/CommentEditor.d.ts +14 -0
  5. package/dist/components/CommentItem.d.ts +14 -0
  6. package/dist/components/CommentList.d.ts +18 -0
  7. package/dist/components/LoginModal/BunkerLogin.d.ts +5 -0
  8. package/dist/components/LoginModal/Nip07Login.d.ts +5 -0
  9. package/dist/components/LoginModal/index.d.ts +9 -0
  10. package/dist/components/Username.d.ts +6 -0
  11. package/dist/components/index.d.ts +6 -0
  12. package/dist/hooks/index.d.ts +4 -0
  13. package/dist/hooks/useComments.d.ts +20 -0
  14. package/dist/hooks/useProfile.d.ts +4 -0
  15. package/dist/hooks/useSigner.d.ts +18 -0
  16. package/dist/i18n/index.d.ts +35 -0
  17. package/dist/i18n/locales/ar.d.ts +2 -0
  18. package/dist/i18n/locales/de.d.ts +2 -0
  19. package/dist/i18n/locales/en.d.ts +2 -0
  20. package/dist/i18n/locales/es.d.ts +2 -0
  21. package/dist/i18n/locales/fr.d.ts +2 -0
  22. package/dist/i18n/locales/hi.d.ts +2 -0
  23. package/dist/i18n/locales/id.d.ts +2 -0
  24. package/dist/i18n/locales/it.d.ts +2 -0
  25. package/dist/i18n/locales/ja.d.ts +2 -0
  26. package/dist/i18n/locales/ko.d.ts +2 -0
  27. package/dist/i18n/locales/nl.d.ts +2 -0
  28. package/dist/i18n/locales/pl.d.ts +2 -0
  29. package/dist/i18n/locales/pt.d.ts +2 -0
  30. package/dist/i18n/locales/ru.d.ts +2 -0
  31. package/dist/i18n/locales/th.d.ts +2 -0
  32. package/dist/i18n/locales/tr.d.ts +2 -0
  33. package/dist/i18n/locales/uk.d.ts +2 -0
  34. package/dist/i18n/locales/vi.d.ts +2 -0
  35. package/dist/i18n/locales/zh-CN.d.ts +2 -0
  36. package/dist/i18n/locales/zh-TW.d.ts +2 -0
  37. package/dist/index.d.ts +14 -0
  38. package/dist/nostr-comments.cjs +96 -0
  39. package/dist/nostr-comments.js +10257 -0
  40. package/dist/nostr-comments.umd.js +96 -0
  41. package/dist/services/comment.d.ts +32 -0
  42. package/dist/services/nostr.d.ts +6 -0
  43. package/dist/services/reaction.d.ts +18 -0
  44. package/dist/signers/BunkerSigner.d.ts +13 -0
  45. package/dist/signers/Nip07Signer.d.ts +16 -0
  46. package/dist/signers/TempSigner.d.ts +19 -0
  47. package/dist/signers/index.d.ts +4 -0
  48. package/dist/signers/types.d.ts +10 -0
  49. package/dist/types/index.d.ts +80 -0
  50. package/dist/utils/avatar.d.ts +3 -0
  51. package/dist/utils/ensureStyles.d.ts +1 -0
  52. package/dist/utils/nip22.d.ts +17 -0
  53. package/package.json +64 -0
package/README.md ADDED
@@ -0,0 +1,294 @@
1
+ # Nostr Comments
2
+
3
+ A web comment component based on the Nostr network, implementing the [NIP-22](https://github.com/nostr-protocol/nips/blob/master/22.md) protocol (Web part), using the `I` tag to identify URLs.
4
+
5
+ ## Features
6
+
7
+ - **NIP-22 Protocol**: Uses kind:1111 events, supports comments and replies
8
+ - **Multiple Login Methods**:
9
+ - NIP-07 browser extensions (Alby, nos2x, etc.)
10
+ - NIP-46 Bunker remote signing
11
+ - Temporary account (locally generated key pair)
12
+ - **Multilingual**: 20 languages built-in (en, zh-CN, zh-TW, ja, ko, es, fr, de, pt, ru, ar, it, nl, pl, tr, vi, th, id, hi, uk), supports custom translations
13
+ - **Profile Links**: Click avatar or username to view profile on [Jumble](https://jumble.social)
14
+ - **Themes**: Light, dark, auto (follows system), easy customization with a few CSS variables
15
+ - **Transparent Background**: No default background, blends into any host page
16
+ - **Headless Mode**: Disable default styles for fully custom UI
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install nostr-comments
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ### React/Preact Usage
27
+
28
+ ```tsx
29
+ import { NostrComments } from "nostr-comments";
30
+ import "nostr-comments/style.css";
31
+
32
+ function App() {
33
+ return <NostrComments url="https://example.com/blog/my-post" locale="en" />;
34
+ }
35
+ ```
36
+
37
+ ### CDN Usage
38
+
39
+ ```html
40
+ <link
41
+ rel="stylesheet"
42
+ href="https://cdn.jsdelivr.net/npm/nostr-comments/dist/nostr-comments.css"
43
+ />
44
+ <script src="https://cdn.jsdelivr.net/npm/nostr-comments/dist/nostr-comments.umd.js"></script>
45
+
46
+ <div id="comments"></div>
47
+
48
+ <script>
49
+ NostrComments.render("#comments", {
50
+ url: "https://example.com/blog/my-post",
51
+ locale: "en",
52
+ });
53
+ </script>
54
+ ```
55
+
56
+ ## API
57
+
58
+ ### NostrComments Component Props
59
+
60
+ | Prop | Type | Default | Description |
61
+ | -------------------- | ----------------------------------- | ------------------ | ---------------------------------------------------- |
62
+ | `url` | `string` | **Required** | Web page URL, used to identify comment scope |
63
+ | `authorPubkeys` | `string[]` | - | List of article author public keys for notifications |
64
+ | `relays` | `string[]` | Default relay list | List of Nostr relay addresses |
65
+ | `pageSize` | `number` | `50` | Number of comments per page |
66
+ | `locale` | `string` | Auto-detect | Interface language (20 languages supported) |
67
+ | `translations` | `Partial<Translations>` | - | Custom translation text |
68
+ | `theme` | `'light' \| 'dark' \| 'auto'` | `'auto'` | Theme mode |
69
+ | `headless` | `boolean` | `false` | Enable Headless mode |
70
+ | `classNames` | `object` | - | Custom CSS class names |
71
+ | `enabledSigners` | `('nip07' \| 'bunker' \| 'temp')[]` | All enabled | Enabled login methods |
72
+ | `onCommentPublished` | `(event: NostrEvent) => void` | - | Callback when comment is published |
73
+ | `onError` | `(error: Error) => void` | - | Error callback |
74
+
75
+ ### classNames Object
76
+
77
+ ```ts
78
+ {
79
+ root?: string // Root container
80
+ list?: string // Comment list
81
+ item?: string // Comment item
82
+ editor?: string // Editor
83
+ loginModal?: string // Login modal
84
+ }
85
+ ```
86
+
87
+ ## Examples
88
+
89
+ ### Custom Relays
90
+
91
+ ```tsx
92
+ <NostrComments
93
+ url="https://example.com/post/123"
94
+ relays={["wss://relay.damus.io", "wss://relay.nostr.band", "wss://nos.lol"]}
95
+ />
96
+ ```
97
+
98
+ ### Dark Theme
99
+
100
+ ```tsx
101
+ <NostrComments url="https://example.com/post/123" theme="dark" />
102
+ ```
103
+
104
+ ### Custom Translations
105
+
106
+ ```tsx
107
+ <NostrComments
108
+ url="https://example.com/post/123"
109
+ locale="en"
110
+ translations={{
111
+ comments: "Discussion",
112
+ writeComment: "Share your thoughts...",
113
+ publish: "Post",
114
+ noComments: "Start the conversation!",
115
+ keyCompatibility: "This key works with any Nostr app!",
116
+ }}
117
+ />
118
+ ```
119
+
120
+ ### Extension Login Only
121
+
122
+ ```tsx
123
+ <NostrComments url="https://example.com/post/123" enabledSigners={["nip07"]} />
124
+ ```
125
+
126
+ ### Headless Mode
127
+
128
+ ```tsx
129
+ <NostrComments
130
+ url="https://example.com/post/123"
131
+ headless={true}
132
+ classNames={{
133
+ root: "my-comments",
134
+ list: "my-comments-list",
135
+ editor: "my-editor",
136
+ }}
137
+ />
138
+ ```
139
+
140
+ ## CSS Variables
141
+
142
+ The component uses CSS variables for theme customization. Only a few base colors need to be set — all secondary, hover, border, and muted colors are **automatically derived** via `color-mix()`.
143
+
144
+ ### Base Colors (override these to customize)
145
+
146
+ ```css
147
+ .nostr-comments {
148
+ --nc-bg: #ffffff; /* Background for inputs, modals */
149
+ --nc-text: #1f2937; /* Primary text color */
150
+ --nc-primary: #2563eb; /* Accent/brand color */
151
+ --nc-error: #dc2626; /* Error states */
152
+ --nc-success: #16a34a; /* Success states */
153
+ }
154
+ ```
155
+
156
+ All other color variables (`--nc-bg-secondary`, `--nc-bg-hover`, `--nc-border`, `--nc-text-secondary`, `--nc-text-muted`, `--nc-primary-hover`, `--nc-primary-light`, `--nc-error-light`, `--nc-success-light`) are derived automatically from the base colors.
157
+
158
+ ### Custom Theme Example
159
+
160
+ ```css
161
+ /* A custom purple theme — works for both light and dark */
162
+ .nostr-comments {
163
+ --nc-bg: #1a1a2e;
164
+ --nc-text: #eaeaea;
165
+ --nc-primary: #e94560;
166
+ }
167
+ ```
168
+
169
+ For dark mode, override the base colors under `[data-theme="dark"]` or `[data-theme="auto"]` with `prefers-color-scheme: dark`. The derived colors will adjust automatically.
170
+
171
+ ### Other Variables
172
+
173
+ ```css
174
+ .nostr-comments {
175
+ /* Spacing */
176
+ --nc-space-xs: 4px;
177
+ --nc-space-sm: 8px;
178
+ --nc-space-md: 12px;
179
+ --nc-space-lg: 16px;
180
+ --nc-space-xl: 24px;
181
+
182
+ /* Border Radius */
183
+ --nc-radius-sm: 8px;
184
+ --nc-radius-md: 12px;
185
+ --nc-radius-lg: 16px;
186
+ --nc-radius-xl: 24px;
187
+
188
+ /* Avatar Border Radius */
189
+ --nc-avatar-radius: 50%;
190
+ }
191
+ ```
192
+
193
+ ## Advanced Usage
194
+
195
+ ### Using Standalone Hooks
196
+
197
+ ```tsx
198
+ import { useComments, useSigner } from "nostr-comments";
199
+
200
+ function CustomComments({ url }) {
201
+ const { comments, loading, addEvent } = useComments({ url });
202
+ const { signer, loginWithNip07 } = useSigner();
203
+
204
+ // Custom UI...
205
+ }
206
+ ```
207
+
208
+ ### Using Service Functions
209
+
210
+ ```tsx
211
+ import { publishComment, subscribeComments } from "nostr-comments";
212
+
213
+ // Publish a comment
214
+ const event = await publishComment(signer, relays, {
215
+ url: "https://example.com/post",
216
+ content: "Great post!",
217
+ });
218
+
219
+ // Subscribe to comments
220
+ const unsubscribe = subscribeComments({
221
+ url: "https://example.com/post",
222
+ relays,
223
+ onEvent: (event) => console.log("New comment:", event),
224
+ });
225
+ ```
226
+
227
+ ### Custom Signers
228
+
229
+ ```tsx
230
+ import { Nip07Signer, TempSigner, BunkerSigner } from "nostr-comments";
231
+
232
+ // NIP-07 extension
233
+ const nip07 = new Nip07Signer();
234
+ const pubkey = await nip07.getPublicKey();
235
+
236
+ // Temporary account
237
+ const temp = new TempSigner();
238
+ const nsec = temp.getNsec(); // Export private key
239
+ temp.downloadKeyFile(); // Download key file
240
+
241
+ // Bunker
242
+ const bunker = BunkerSigner.create("bunker://pubkey?relay=wss://...");
243
+ await bunker.connect();
244
+ ```
245
+
246
+ ## NIP-22 Event Format
247
+
248
+ ### Top-level Comment
249
+
250
+ ```json
251
+ {
252
+ "kind": 1111,
253
+ "content": "Nice article!",
254
+ "tags": [
255
+ ["I", "https://example.com/post/123"],
256
+ ["K", "web"],
257
+ ["i", "https://example.com/post/123"],
258
+ ["k", "web"]
259
+ ]
260
+ }
261
+ ```
262
+
263
+ ### Reply Comment
264
+
265
+ ```json
266
+ {
267
+ "kind": 1111,
268
+ "content": "I agree!",
269
+ "tags": [
270
+ ["I", "https://example.com/post/123"],
271
+ ["K", "web"],
272
+ ["e", "<parent_event_id>", "<relay_hint>", "<parent_pubkey>"],
273
+ ["k", "1111"],
274
+ ["p", "<parent_pubkey>"]
275
+ ]
276
+ }
277
+ ```
278
+
279
+ ## Development
280
+
281
+ ```bash
282
+ # Install dependencies
283
+ npm install
284
+
285
+ # Start development server
286
+ npm run dev
287
+
288
+ # Build
289
+ npm run build
290
+ ```
291
+
292
+ ## License
293
+
294
+ MIT
@@ -0,0 +1,2 @@
1
+ import type { NostrCommentsProps } from "./types";
2
+ export declare function NostrComments({ locale, translations, theme, headless, ...props }: NostrCommentsProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,7 @@
1
+ interface AvatarProps {
2
+ pubkey: string;
3
+ size?: number;
4
+ className?: string;
5
+ }
6
+ export declare function Avatar({ pubkey, size, className }: AvatarProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1,14 @@
1
+ import type { NostrEvent } from "nostr-tools";
2
+ interface CommentEditorProps {
3
+ url: string;
4
+ relays?: string[];
5
+ authorPubkeys?: string[];
6
+ parentEvent?: NostrEvent | null;
7
+ onClearParent?: () => void;
8
+ onPublished?: (event: NostrEvent) => void;
9
+ onLoginRequired: () => void;
10
+ onError?: (error: Error) => void;
11
+ className?: string;
12
+ }
13
+ export declare function CommentEditor({ url, relays, authorPubkeys, parentEvent, onClearParent, onPublished, onLoginRequired, onError, className, }: CommentEditorProps): import("react/jsx-runtime").JSX.Element;
14
+ export {};
@@ -0,0 +1,14 @@
1
+ import type { NostrEvent } from "nostr-tools";
2
+ import type { Comment } from "../types";
3
+ interface CommentItemProps {
4
+ comment: Comment;
5
+ relays?: string[];
6
+ onReply: (event: NostrEvent) => void;
7
+ onLoginRequired: () => void;
8
+ currentPubkey?: string;
9
+ className?: string;
10
+ /** Whether this is a child comment (second level) */
11
+ isChild?: boolean;
12
+ }
13
+ export declare function CommentItem({ comment, relays, onReply, onLoginRequired, currentPubkey, className, isChild, }: CommentItemProps): import("react/jsx-runtime").JSX.Element;
14
+ export {};
@@ -0,0 +1,18 @@
1
+ import type { NostrEvent } from "nostr-tools";
2
+ import type { Comment } from "../types";
3
+ interface CommentListProps {
4
+ comments: Comment[];
5
+ loading: boolean;
6
+ loadingMore: boolean;
7
+ hasMore: boolean;
8
+ error: string | null;
9
+ relays?: string[];
10
+ onReply: (event: NostrEvent) => void;
11
+ onLoginRequired: () => void;
12
+ onLoadMore: () => void;
13
+ onRetry: () => void;
14
+ currentPubkey?: string;
15
+ className?: string;
16
+ }
17
+ export declare function CommentList({ comments, loading, loadingMore, hasMore, error, relays, onReply, onLoginRequired, onLoadMore, onRetry, currentPubkey, className, }: CommentListProps): import("react/jsx-runtime").JSX.Element;
18
+ export {};
@@ -0,0 +1,5 @@
1
+ interface BunkerLoginProps {
2
+ onSuccess: () => void;
3
+ }
4
+ export declare function BunkerLogin({ onSuccess }: BunkerLoginProps): import("react/jsx-runtime").JSX.Element;
5
+ export {};
@@ -0,0 +1,5 @@
1
+ interface Nip07LoginProps {
2
+ onSuccess: () => void;
3
+ }
4
+ export declare function Nip07Login({ onSuccess }: Nip07LoginProps): import("react/jsx-runtime").JSX.Element;
5
+ export {};
@@ -0,0 +1,9 @@
1
+ import type { SignerType } from '../../signers/types';
2
+ interface LoginModalProps {
3
+ isOpen: boolean;
4
+ onClose: () => void;
5
+ enabledSigners?: SignerType[];
6
+ className?: string;
7
+ }
8
+ export declare function LoginModal({ isOpen, onClose, enabledSigners, className }: LoginModalProps): import("react/jsx-runtime").JSX.Element | null;
9
+ export {};
@@ -0,0 +1,6 @@
1
+ interface UsernameProps {
2
+ pubkey: string;
3
+ className?: string;
4
+ }
5
+ export declare function Username({ pubkey, className }: UsernameProps): import("react/jsx-runtime").JSX.Element;
6
+ export {};
@@ -0,0 +1,6 @@
1
+ export { Avatar } from "./Avatar";
2
+ export { Username } from "./Username";
3
+ export { CommentItem } from "./CommentItem";
4
+ export { CommentList } from "./CommentList";
5
+ export { CommentEditor } from "./CommentEditor";
6
+ export { LoginModal } from "./LoginModal";
@@ -0,0 +1,4 @@
1
+ export { useSigner, isLoggedIn } from "./useSigner";
2
+ export { useComments } from "./useComments";
3
+ export type { UseCommentsOptions } from "./useComments";
4
+ export { useProfile } from "./useProfile";
@@ -0,0 +1,20 @@
1
+ import type { NostrEvent } from "nostr-tools";
2
+ import type { Comment } from "../types";
3
+ export interface UseCommentsOptions {
4
+ url: string;
5
+ authors?: string[];
6
+ relays?: string[];
7
+ pageSize?: number;
8
+ }
9
+ export declare function useComments(options: UseCommentsOptions): {
10
+ comments: Comment[];
11
+ commentCount: number;
12
+ events: NostrEvent[];
13
+ loading: boolean;
14
+ loadingMore: boolean;
15
+ error: string | null;
16
+ hasMore: boolean;
17
+ reload: () => Promise<() => void>;
18
+ loadMore: () => Promise<void>;
19
+ addEvent: (event: NostrEvent) => void;
20
+ };
@@ -0,0 +1,4 @@
1
+ import { NostrUser } from "@nostr/gadgets/metadata";
2
+ export declare function useProfile(pubkey: string): {
3
+ profile: NostrUser;
4
+ };
@@ -0,0 +1,18 @@
1
+ import { TempSigner } from "../signers";
2
+ import type { Signer, SignerInfo } from "../signers/types";
3
+ export declare function isLoggedIn(): boolean;
4
+ export declare function useSigner(): {
5
+ signer: Signer | null;
6
+ signerInfo: SignerInfo | null;
7
+ loading: boolean;
8
+ error: string | null;
9
+ isLoggedIn: boolean;
10
+ loginWithNip07: () => Promise<void>;
11
+ loginWithTemp: () => Promise<void>;
12
+ loginWithNsec: (nsec: string) => Promise<void>;
13
+ loginWithBunker: (bunkerUrl: string) => Promise<void>;
14
+ logout: () => void;
15
+ clearError: () => void;
16
+ getTempSigner: () => TempSigner | null;
17
+ isNip07Available: boolean;
18
+ };
@@ -0,0 +1,35 @@
1
+ import { type ReactNode } from "react";
2
+ import type { Translations } from "../types";
3
+ import { en } from "./locales/en";
4
+ import { zhCN } from "./locales/zh-CN";
5
+ import { zhTW } from "./locales/zh-TW";
6
+ import { ja } from "./locales/ja";
7
+ import { ko } from "./locales/ko";
8
+ import { es } from "./locales/es";
9
+ import { fr } from "./locales/fr";
10
+ import { de } from "./locales/de";
11
+ import { pt } from "./locales/pt";
12
+ import { ru } from "./locales/ru";
13
+ import { ar } from "./locales/ar";
14
+ import { it } from "./locales/it";
15
+ import { nl } from "./locales/nl";
16
+ import { pl } from "./locales/pl";
17
+ import { tr } from "./locales/tr";
18
+ import { vi } from "./locales/vi";
19
+ import { th } from "./locales/th";
20
+ import { id } from "./locales/id";
21
+ import { hi } from "./locales/hi";
22
+ import { uk } from "./locales/uk";
23
+ interface I18nContextValue {
24
+ locale: string;
25
+ translations: Translations;
26
+ t: (key: keyof Translations) => string;
27
+ }
28
+ interface I18nProviderProps {
29
+ locale?: string;
30
+ translations?: Partial<Translations>;
31
+ children: ReactNode;
32
+ }
33
+ export declare function I18nProvider({ locale, translations: customTranslations, children, }: I18nProviderProps): import("react/jsx-runtime").JSX.Element;
34
+ export declare function useI18n(): I18nContextValue;
35
+ export { en, zhCN as zhCN, zhTW, ja, ko, es, fr, de, pt, ru, ar, it, nl, pl, tr, vi, th, id, hi, uk, };
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const ar: Translations;
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const de: Translations;
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const en: Translations;
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const es: Translations;
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const fr: Translations;
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const hi: Translations;
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const id: Translations;
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const it: Translations;
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const ja: Translations;
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const ko: Translations;
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const nl: Translations;
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const pl: Translations;
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const pt: Translations;
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const ru: Translations;
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const th: Translations;
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const tr: Translations;
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const uk: Translations;
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const vi: Translations;
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const zhCN: Translations;
@@ -0,0 +1,2 @@
1
+ import type { Translations } from "../../types";
2
+ export declare const zhTW: Translations;
@@ -0,0 +1,14 @@
1
+ export { NostrComments } from "./NostrComments";
2
+ export type { NostrCommentsProps, Comment, Profile, Translations, } from "./types";
3
+ export { Nip07Signer, TempSigner, BunkerSigner } from "./signers";
4
+ export type { Signer, SignerType, SignerInfo } from "./signers";
5
+ export { useSigner, useComments, useProfile, isLoggedIn } from "./hooks";
6
+ export type { UseCommentsOptions } from "./hooks";
7
+ export { Avatar, Username, CommentItem, CommentList, CommentEditor, LoginModal, } from "./components";
8
+ export { getDefaultRelays, queryEvents, subscribeEvents, publishEvent, } from "./services/nostr";
9
+ export { subscribeComments, fetchComments, publishComment, publishReply, buildCommentTree, } from "./services/comment";
10
+ export { subscribeReactions, fetchReactions, publishReaction, countLikes, hasLiked, buildReactionEvent, } from "./services/reaction";
11
+ export { buildWebComment, buildReplyComment, isReply, getParentId, getRootUrl, } from "./utils/nip22";
12
+ export { getColorFromPubkey, generateAvatarSvg, getAvatarDataUrl, } from "./utils/avatar";
13
+ export { I18nProvider, useI18n, en, zhCN } from "./i18n";
14
+ import "./styles/base.css";