@anonfly/react 1.0.0 → 1.0.2

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.
@@ -0,0 +1,17 @@
1
+ import { AuthSession } from '@anonfly/sdk';
2
+ /**
3
+ * Headless hook for Anonfly Authentication.
4
+ * Handles login, session management, and premium status.
5
+ */
6
+ export declare function useAnonflyAuth(): {
7
+ session: AuthSession | null;
8
+ isAuthenticated: boolean;
9
+ loading: boolean;
10
+ error: Error | null;
11
+ login: (aid: string, username: string, challenge: string, signature: string, publicKey: string, exchangePublicKey: string) => Promise<AuthSession>;
12
+ logout: () => void;
13
+ getChallenge: (aid: string) => Promise<{
14
+ nonce: string;
15
+ }>;
16
+ };
17
+ //# sourceMappingURL=useAnonflyAuth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAnonflyAuth.d.ts","sourceRoot":"","sources":["../../src/hooks/useAnonflyAuth.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C;;;GAGG;AACH,wBAAgB,cAAc;;;;;iBAMY,MAAM,YAAY,MAAM,aAAa,MAAM,aAAa,MAAM,aAAa,MAAM,qBAAqB,MAAM;;wBA4BrG,MAAM;;;EAatD"}
@@ -0,0 +1,17 @@
1
+ import { Room } from '@anonfly/sdk';
2
+ /**
3
+ * Headless hook for browsing and managing Anonfly conversations (rooms).
4
+ */
5
+ export declare function useAnonflyConversations(): {
6
+ rooms: Room[];
7
+ loading: boolean;
8
+ error: Error | null;
9
+ fetchRooms: (region?: string) => Promise<void>;
10
+ createRoom: (data: {
11
+ roomname: string;
12
+ isPrivate?: boolean;
13
+ description?: string;
14
+ password?: string;
15
+ }) => Promise<Room>;
16
+ };
17
+ //# sourceMappingURL=useAnonflyConversations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAnonflyConversations.d.ts","sourceRoot":"","sources":["../../src/hooks/useAnonflyConversations.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEpC;;GAEG;AACH,wBAAgB,uBAAuB;;;;0BAMY,MAAM;uBAYT;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;EA0BjI"}
@@ -0,0 +1,16 @@
1
+ import { Message } from '@anonfly/sdk';
2
+ /**
3
+ * Headless hook for managing Anonfly messages within a specific room.
4
+ * Supports fetching history and subscribing to real-time updates.
5
+ */
6
+ export declare function useAnonflyMessages(roomId?: string): {
7
+ messages: Message[];
8
+ loading: boolean;
9
+ error: Error | null;
10
+ fetchMessages: (options?: {
11
+ limit?: number;
12
+ before?: string;
13
+ }) => Promise<void>;
14
+ sendMessage: (content: string) => Promise<Message>;
15
+ };
16
+ //# sourceMappingURL=useAnonflyMessages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAnonflyMessages.d.ts","sourceRoot":"","sources":["../../src/hooks/useAnonflyMessages.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM;;;;8BAMK;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;2BAatC,MAAM;EA4BzD"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Headless hook for tracking presence and participants in a room.
3
+ */
4
+ export declare function useAnonflyPresence(roomId?: string): {
5
+ participants: any[];
6
+ loading: boolean;
7
+ error: Error | null;
8
+ };
9
+ //# sourceMappingURL=useAnonflyPresence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAnonflyPresence.d.ts","sourceRoot":"","sources":["../../src/hooks/useAnonflyPresence.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM;;;;EAgCjD"}
package/dist/index.cjs CHANGED
@@ -21,11 +21,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  AnonflyProvider: () => AnonflyProvider,
24
- ChatInput: () => ChatInput,
25
- MessageList: () => MessageList,
26
24
  useAnonfly: () => useAnonfly,
27
- useMessages: () => useMessages,
28
- useRooms: () => useRooms
25
+ useAnonflyAuth: () => useAnonflyAuth,
26
+ useAnonflyConversations: () => useAnonflyConversations,
27
+ useAnonflyMessages: () => useAnonflyMessages,
28
+ useAnonflyPresence: () => useAnonflyPresence
29
29
  });
30
30
  module.exports = __toCommonJS(index_exports);
31
31
 
@@ -46,158 +46,174 @@ var useAnonfly = () => {
46
46
  return context.client;
47
47
  };
48
48
 
49
- // src/hooks/useRooms.ts
49
+ // src/hooks/useAnonflyAuth.ts
50
50
  var import_react2 = require("react");
51
- var useRooms = () => {
51
+ function useAnonflyAuth() {
52
52
  const client = useAnonfly();
53
- const [rooms, setRooms] = (0, import_react2.useState)([]);
54
- const [loading, setLoading] = (0, import_react2.useState)(true);
53
+ const [session, setSession] = (0, import_react2.useState)(null);
54
+ const [loading, setLoading] = (0, import_react2.useState)(false);
55
55
  const [error, setError] = (0, import_react2.useState)(null);
56
- const fetchRooms = async () => {
56
+ const login = (0, import_react2.useCallback)(async (aid, username, challenge, signature, publicKey, exchangePublicKey) => {
57
+ setLoading(true);
58
+ setError(null);
57
59
  try {
58
- setLoading(true);
59
- const data = await client.rooms.list();
60
- setRooms(data);
60
+ const authSession = await client.auth.verify({
61
+ challenge,
62
+ signature,
63
+ identity: {
64
+ aid,
65
+ username,
66
+ publicKey,
67
+ exchangePublicKey
68
+ }
69
+ });
70
+ setSession(authSession);
71
+ return authSession;
61
72
  } catch (err) {
62
73
  setError(err);
74
+ throw err;
63
75
  } finally {
64
76
  setLoading(false);
65
77
  }
66
- };
67
- (0, import_react2.useEffect)(() => {
68
- fetchRooms();
69
78
  }, [client]);
70
- return { rooms, loading, error, refetch: fetchRooms };
71
- };
79
+ const logout = (0, import_react2.useCallback)(() => {
80
+ setSession(null);
81
+ }, []);
82
+ const getChallenge = (0, import_react2.useCallback)(async (aid) => {
83
+ return client.auth.generateChallenge(aid);
84
+ }, [client]);
85
+ return {
86
+ session,
87
+ isAuthenticated: !!session,
88
+ loading,
89
+ error,
90
+ login,
91
+ logout,
92
+ getChallenge
93
+ };
94
+ }
72
95
 
73
- // src/hooks/useMessages.ts
96
+ // src/hooks/useAnonflyMessages.ts
74
97
  var import_react3 = require("react");
75
- var useMessages = (roomId) => {
98
+ function useAnonflyMessages(roomId) {
76
99
  const client = useAnonfly();
77
100
  const [messages, setMessages] = (0, import_react3.useState)([]);
78
- const [loading, setLoading] = (0, import_react3.useState)(true);
101
+ const [loading, setLoading] = (0, import_react3.useState)(false);
79
102
  const [error, setError] = (0, import_react3.useState)(null);
103
+ const fetchMessages = (0, import_react3.useCallback)(async (options) => {
104
+ if (!roomId) return;
105
+ setLoading(true);
106
+ try {
107
+ const data = await client.messages.list(roomId, options);
108
+ setMessages(data);
109
+ } catch (err) {
110
+ setError(err);
111
+ } finally {
112
+ setLoading(false);
113
+ }
114
+ }, [client, roomId]);
115
+ const sendMessage = (0, import_react3.useCallback)(async (content) => {
116
+ if (!roomId) throw new Error("Room ID is required to send a message");
117
+ return client.messages.send(roomId, content);
118
+ }, [client, roomId]);
80
119
  (0, import_react3.useEffect)(() => {
81
- const fetchMessages = async () => {
82
- try {
83
- setLoading(true);
84
- const data = await client.messages.list(roomId);
85
- setMessages(data);
86
- } catch (err) {
87
- setError(err);
88
- } finally {
89
- setLoading(false);
120
+ if (!roomId || !client.ws) return;
121
+ const handler = (event) => {
122
+ if (event.type === "message" && event.data.roomId === roomId) {
123
+ setMessages((prev) => [...prev, event.data]);
90
124
  }
91
125
  };
92
- fetchMessages();
93
- if (client.ws) {
94
- const handleMessage = (msg) => {
95
- if (msg.roomId === roomId) {
96
- setMessages((prev) => [...prev, msg]);
97
- }
98
- };
99
- client.ws.on("message", handleMessage);
100
- return () => {
101
- client.ws?.off("message", handleMessage);
102
- };
103
- }
104
- }, [client, roomId]);
105
- const sendMessage = async (content) => {
106
- const newMessage = await client.messages.send(roomId, content);
107
- return newMessage;
126
+ client.ws.on("message", handler);
127
+ return () => {
128
+ client.ws?.removeListener("message", handler);
129
+ };
130
+ }, [client.ws, roomId]);
131
+ return {
132
+ messages,
133
+ loading,
134
+ error,
135
+ fetchMessages,
136
+ sendMessage
108
137
  };
109
- return { messages, loading, error, sendMessage };
110
- };
111
-
112
- // src/components/MessageList.tsx
113
- var import_clsx = require("clsx");
114
- var import_tailwind_merge = require("tailwind-merge");
115
- var import_jsx_runtime2 = require("react/jsx-runtime");
116
- function cn(...inputs) {
117
- return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
118
138
  }
119
- var MessageList = ({ roomId, className }) => {
120
- const { messages, loading, error } = useMessages(roomId);
121
- if (loading && messages.length === 0) {
122
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "p-4 text-center opacity-50", children: "Loading messages..." });
123
- }
124
- if (error) {
125
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "p-4 text-center text-red-500", children: [
126
- "Error: ",
127
- error.message
128
- ] });
129
- }
130
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: cn("flex flex-col gap-4 overflow-y-auto p-4", className), children: messages.map((msg) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-col gap-1", children: [
131
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
132
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-xs font-bold opacity-70", children: msg.senderId }),
133
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-[10px] opacity-40", children: new Date(msg.timestamp).toLocaleTimeString() })
134
- ] }),
135
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "rounded-lg bg-gray-100 p-3 text-sm dark:bg-zinc-800", children: msg.content })
136
- ] }, msg.id)) });
137
- };
138
139
 
139
- // src/components/ChatInput.tsx
140
+ // src/hooks/useAnonflyConversations.ts
140
141
  var import_react4 = require("react");
141
- var import_lucide_react = require("lucide-react");
142
- var import_clsx2 = require("clsx");
143
- var import_tailwind_merge2 = require("tailwind-merge");
144
- var import_jsx_runtime3 = require("react/jsx-runtime");
145
- function cn2(...inputs) {
146
- return (0, import_tailwind_merge2.twMerge)((0, import_clsx2.clsx)(inputs));
147
- }
148
- var ChatInput = ({ roomId, className, placeholder = "Type a message..." }) => {
149
- const { sendMessage } = useMessages(roomId);
150
- const [content, setContent] = (0, import_react4.useState)("");
151
- const [sending, setSending] = (0, import_react4.useState)(false);
152
- const handleSubmit = async (e) => {
153
- e.preventDefault();
154
- if (!content.trim() || sending) return;
142
+ function useAnonflyConversations() {
143
+ const client = useAnonfly();
144
+ const [rooms, setRooms] = (0, import_react4.useState)([]);
145
+ const [loading, setLoading] = (0, import_react4.useState)(false);
146
+ const [error, setError] = (0, import_react4.useState)(null);
147
+ const fetchRooms = (0, import_react4.useCallback)(async (region) => {
148
+ setLoading(true);
155
149
  try {
156
- setSending(true);
157
- await sendMessage(content);
158
- setContent("");
150
+ const data = await client.rooms.list(region);
151
+ setRooms(data);
159
152
  } catch (err) {
160
- console.error("Failed to send message:", err);
153
+ setError(err);
161
154
  } finally {
162
- setSending(false);
155
+ setLoading(false);
163
156
  }
157
+ }, [client]);
158
+ const createRoom = (0, import_react4.useCallback)(async (data) => {
159
+ return client.rooms.create(data);
160
+ }, [client]);
161
+ (0, import_react4.useEffect)(() => {
162
+ let unsubscribe;
163
+ client.rooms.subscribeToPublicList((updatedRooms) => {
164
+ setRooms(updatedRooms);
165
+ }).then((unsub) => {
166
+ unsubscribe = unsub;
167
+ });
168
+ return () => {
169
+ if (unsubscribe) unsubscribe();
170
+ };
171
+ }, [client]);
172
+ return {
173
+ rooms,
174
+ loading,
175
+ error,
176
+ fetchRooms,
177
+ createRoom
164
178
  };
165
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
166
- "form",
167
- {
168
- onSubmit: handleSubmit,
169
- className: cn2("flex items-center gap-2 border-t p-4 dark:border-zinc-800", className),
170
- children: [
171
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
172
- "input",
173
- {
174
- type: "text",
175
- value: content,
176
- onChange: (e) => setContent(e.target.value),
177
- placeholder,
178
- disabled: sending,
179
- className: "flex-1 rounded-full bg-gray-100 px-4 py-2 text-sm outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800"
180
- }
181
- ),
182
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
183
- "button",
184
- {
185
- type: "submit",
186
- disabled: sending || !content.trim(),
187
- className: "flex h-9 w-9 items-center justify-center rounded-full bg-blue-600 font-bold text-white transition-opacity hover:opacity-90 disabled:opacity-50",
188
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Send, { className: "h-4 w-4" })
189
- }
190
- )
191
- ]
192
- }
193
- );
194
- };
179
+ }
180
+
181
+ // src/hooks/useAnonflyPresence.ts
182
+ var import_react5 = require("react");
183
+ function useAnonflyPresence(roomId) {
184
+ const client = useAnonfly();
185
+ const [participants, setParticipants] = (0, import_react5.useState)([]);
186
+ const [loading, setLoading] = (0, import_react5.useState)(false);
187
+ const [error, setError] = (0, import_react5.useState)(null);
188
+ (0, import_react5.useEffect)(() => {
189
+ if (!roomId) return;
190
+ setLoading(true);
191
+ let unsubscribe;
192
+ client.rooms.subscribeToRoomDetails(roomId, (details) => {
193
+ setParticipants(details.participants);
194
+ setLoading(false);
195
+ }).then((unsub) => {
196
+ unsubscribe = unsub;
197
+ }).catch((err) => {
198
+ setError(err);
199
+ setLoading(false);
200
+ });
201
+ return () => {
202
+ if (unsubscribe) unsubscribe();
203
+ };
204
+ }, [client, roomId]);
205
+ return {
206
+ participants,
207
+ loading,
208
+ error
209
+ };
210
+ }
195
211
  // Annotate the CommonJS export names for ESM import in node:
196
212
  0 && (module.exports = {
197
213
  AnonflyProvider,
198
- ChatInput,
199
- MessageList,
200
214
  useAnonfly,
201
- useMessages,
202
- useRooms
215
+ useAnonflyAuth,
216
+ useAnonflyConversations,
217
+ useAnonflyMessages,
218
+ useAnonflyPresence
203
219
  });
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export * from './context/AnonflyContext.js';
2
- export * from './hooks/useRooms.js';
3
- export * from './hooks/useMessages.js';
4
- export * from './components/MessageList.js';
5
- export * from './components/ChatInput.js';
1
+ export * from './context/AnonflyContext';
2
+ export * from './hooks/useAnonflyAuth';
3
+ export * from './hooks/useAnonflyMessages';
4
+ export * from './hooks/useAnonflyConversations';
5
+ export * from './hooks/useAnonflyPresence';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iCAAiC,CAAC;AAChD,cAAc,4BAA4B,CAAC"}
package/dist/index.js CHANGED
@@ -15,157 +15,173 @@ var useAnonfly = () => {
15
15
  return context.client;
16
16
  };
17
17
 
18
- // src/hooks/useRooms.ts
19
- import { useEffect, useState } from "react";
20
- var useRooms = () => {
18
+ // src/hooks/useAnonflyAuth.ts
19
+ import { useState, useCallback } from "react";
20
+ function useAnonflyAuth() {
21
21
  const client = useAnonfly();
22
- const [rooms, setRooms] = useState([]);
23
- const [loading, setLoading] = useState(true);
22
+ const [session, setSession] = useState(null);
23
+ const [loading, setLoading] = useState(false);
24
24
  const [error, setError] = useState(null);
25
- const fetchRooms = async () => {
25
+ const login = useCallback(async (aid, username, challenge, signature, publicKey, exchangePublicKey) => {
26
+ setLoading(true);
27
+ setError(null);
26
28
  try {
27
- setLoading(true);
28
- const data = await client.rooms.list();
29
- setRooms(data);
29
+ const authSession = await client.auth.verify({
30
+ challenge,
31
+ signature,
32
+ identity: {
33
+ aid,
34
+ username,
35
+ publicKey,
36
+ exchangePublicKey
37
+ }
38
+ });
39
+ setSession(authSession);
40
+ return authSession;
30
41
  } catch (err) {
31
42
  setError(err);
43
+ throw err;
32
44
  } finally {
33
45
  setLoading(false);
34
46
  }
35
- };
36
- useEffect(() => {
37
- fetchRooms();
38
47
  }, [client]);
39
- return { rooms, loading, error, refetch: fetchRooms };
40
- };
48
+ const logout = useCallback(() => {
49
+ setSession(null);
50
+ }, []);
51
+ const getChallenge = useCallback(async (aid) => {
52
+ return client.auth.generateChallenge(aid);
53
+ }, [client]);
54
+ return {
55
+ session,
56
+ isAuthenticated: !!session,
57
+ loading,
58
+ error,
59
+ login,
60
+ logout,
61
+ getChallenge
62
+ };
63
+ }
41
64
 
42
- // src/hooks/useMessages.ts
43
- import { useEffect as useEffect2, useState as useState2 } from "react";
44
- var useMessages = (roomId) => {
65
+ // src/hooks/useAnonflyMessages.ts
66
+ import { useState as useState2, useCallback as useCallback2, useEffect } from "react";
67
+ function useAnonflyMessages(roomId) {
45
68
  const client = useAnonfly();
46
69
  const [messages, setMessages] = useState2([]);
47
- const [loading, setLoading] = useState2(true);
70
+ const [loading, setLoading] = useState2(false);
48
71
  const [error, setError] = useState2(null);
49
- useEffect2(() => {
50
- const fetchMessages = async () => {
51
- try {
52
- setLoading(true);
53
- const data = await client.messages.list(roomId);
54
- setMessages(data);
55
- } catch (err) {
56
- setError(err);
57
- } finally {
58
- setLoading(false);
59
- }
60
- };
61
- fetchMessages();
62
- if (client.ws) {
63
- const handleMessage = (msg) => {
64
- if (msg.roomId === roomId) {
65
- setMessages((prev) => [...prev, msg]);
66
- }
67
- };
68
- client.ws.on("message", handleMessage);
69
- return () => {
70
- client.ws?.off("message", handleMessage);
71
- };
72
+ const fetchMessages = useCallback2(async (options) => {
73
+ if (!roomId) return;
74
+ setLoading(true);
75
+ try {
76
+ const data = await client.messages.list(roomId, options);
77
+ setMessages(data);
78
+ } catch (err) {
79
+ setError(err);
80
+ } finally {
81
+ setLoading(false);
72
82
  }
73
83
  }, [client, roomId]);
74
- const sendMessage = async (content) => {
75
- const newMessage = await client.messages.send(roomId, content);
76
- return newMessage;
84
+ const sendMessage = useCallback2(async (content) => {
85
+ if (!roomId) throw new Error("Room ID is required to send a message");
86
+ return client.messages.send(roomId, content);
87
+ }, [client, roomId]);
88
+ useEffect(() => {
89
+ if (!roomId || !client.ws) return;
90
+ const handler = (event) => {
91
+ if (event.type === "message" && event.data.roomId === roomId) {
92
+ setMessages((prev) => [...prev, event.data]);
93
+ }
94
+ };
95
+ client.ws.on("message", handler);
96
+ return () => {
97
+ client.ws?.removeListener("message", handler);
98
+ };
99
+ }, [client.ws, roomId]);
100
+ return {
101
+ messages,
102
+ loading,
103
+ error,
104
+ fetchMessages,
105
+ sendMessage
77
106
  };
78
- return { messages, loading, error, sendMessage };
79
- };
80
-
81
- // src/components/MessageList.tsx
82
- import { clsx } from "clsx";
83
- import { twMerge } from "tailwind-merge";
84
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
85
- function cn(...inputs) {
86
- return twMerge(clsx(inputs));
87
107
  }
88
- var MessageList = ({ roomId, className }) => {
89
- const { messages, loading, error } = useMessages(roomId);
90
- if (loading && messages.length === 0) {
91
- return /* @__PURE__ */ jsx2("div", { className: "p-4 text-center opacity-50", children: "Loading messages..." });
92
- }
93
- if (error) {
94
- return /* @__PURE__ */ jsxs("div", { className: "p-4 text-center text-red-500", children: [
95
- "Error: ",
96
- error.message
97
- ] });
98
- }
99
- return /* @__PURE__ */ jsx2("div", { className: cn("flex flex-col gap-4 overflow-y-auto p-4", className), children: messages.map((msg) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
100
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
101
- /* @__PURE__ */ jsx2("span", { className: "text-xs font-bold opacity-70", children: msg.senderId }),
102
- /* @__PURE__ */ jsx2("span", { className: "text-[10px] opacity-40", children: new Date(msg.timestamp).toLocaleTimeString() })
103
- ] }),
104
- /* @__PURE__ */ jsx2("div", { className: "rounded-lg bg-gray-100 p-3 text-sm dark:bg-zinc-800", children: msg.content })
105
- ] }, msg.id)) });
106
- };
107
108
 
108
- // src/components/ChatInput.tsx
109
- import { useState as useState3 } from "react";
110
- import { Send } from "lucide-react";
111
- import { clsx as clsx2 } from "clsx";
112
- import { twMerge as twMerge2 } from "tailwind-merge";
113
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
114
- function cn2(...inputs) {
115
- return twMerge2(clsx2(inputs));
116
- }
117
- var ChatInput = ({ roomId, className, placeholder = "Type a message..." }) => {
118
- const { sendMessage } = useMessages(roomId);
119
- const [content, setContent] = useState3("");
120
- const [sending, setSending] = useState3(false);
121
- const handleSubmit = async (e) => {
122
- e.preventDefault();
123
- if (!content.trim() || sending) return;
109
+ // src/hooks/useAnonflyConversations.ts
110
+ import { useState as useState3, useCallback as useCallback3, useEffect as useEffect2 } from "react";
111
+ function useAnonflyConversations() {
112
+ const client = useAnonfly();
113
+ const [rooms, setRooms] = useState3([]);
114
+ const [loading, setLoading] = useState3(false);
115
+ const [error, setError] = useState3(null);
116
+ const fetchRooms = useCallback3(async (region) => {
117
+ setLoading(true);
124
118
  try {
125
- setSending(true);
126
- await sendMessage(content);
127
- setContent("");
119
+ const data = await client.rooms.list(region);
120
+ setRooms(data);
128
121
  } catch (err) {
129
- console.error("Failed to send message:", err);
122
+ setError(err);
130
123
  } finally {
131
- setSending(false);
124
+ setLoading(false);
132
125
  }
126
+ }, [client]);
127
+ const createRoom = useCallback3(async (data) => {
128
+ return client.rooms.create(data);
129
+ }, [client]);
130
+ useEffect2(() => {
131
+ let unsubscribe;
132
+ client.rooms.subscribeToPublicList((updatedRooms) => {
133
+ setRooms(updatedRooms);
134
+ }).then((unsub) => {
135
+ unsubscribe = unsub;
136
+ });
137
+ return () => {
138
+ if (unsubscribe) unsubscribe();
139
+ };
140
+ }, [client]);
141
+ return {
142
+ rooms,
143
+ loading,
144
+ error,
145
+ fetchRooms,
146
+ createRoom
133
147
  };
134
- return /* @__PURE__ */ jsxs2(
135
- "form",
136
- {
137
- onSubmit: handleSubmit,
138
- className: cn2("flex items-center gap-2 border-t p-4 dark:border-zinc-800", className),
139
- children: [
140
- /* @__PURE__ */ jsx3(
141
- "input",
142
- {
143
- type: "text",
144
- value: content,
145
- onChange: (e) => setContent(e.target.value),
146
- placeholder,
147
- disabled: sending,
148
- className: "flex-1 rounded-full bg-gray-100 px-4 py-2 text-sm outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800"
149
- }
150
- ),
151
- /* @__PURE__ */ jsx3(
152
- "button",
153
- {
154
- type: "submit",
155
- disabled: sending || !content.trim(),
156
- className: "flex h-9 w-9 items-center justify-center rounded-full bg-blue-600 font-bold text-white transition-opacity hover:opacity-90 disabled:opacity-50",
157
- children: /* @__PURE__ */ jsx3(Send, { className: "h-4 w-4" })
158
- }
159
- )
160
- ]
161
- }
162
- );
163
- };
148
+ }
149
+
150
+ // src/hooks/useAnonflyPresence.ts
151
+ import { useState as useState4, useEffect as useEffect3 } from "react";
152
+ function useAnonflyPresence(roomId) {
153
+ const client = useAnonfly();
154
+ const [participants, setParticipants] = useState4([]);
155
+ const [loading, setLoading] = useState4(false);
156
+ const [error, setError] = useState4(null);
157
+ useEffect3(() => {
158
+ if (!roomId) return;
159
+ setLoading(true);
160
+ let unsubscribe;
161
+ client.rooms.subscribeToRoomDetails(roomId, (details) => {
162
+ setParticipants(details.participants);
163
+ setLoading(false);
164
+ }).then((unsub) => {
165
+ unsubscribe = unsub;
166
+ }).catch((err) => {
167
+ setError(err);
168
+ setLoading(false);
169
+ });
170
+ return () => {
171
+ if (unsubscribe) unsubscribe();
172
+ };
173
+ }, [client, roomId]);
174
+ return {
175
+ participants,
176
+ loading,
177
+ error
178
+ };
179
+ }
164
180
  export {
165
181
  AnonflyProvider,
166
- ChatInput,
167
- MessageList,
168
182
  useAnonfly,
169
- useMessages,
170
- useRooms
183
+ useAnonflyAuth,
184
+ useAnonflyConversations,
185
+ useAnonflyMessages,
186
+ useAnonflyPresence
171
187
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anonfly/react",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "type": "module",
5
5
  "description": "React UI components for Anonfly SDK",
6
6
  "main": "./dist/index.cjs",
@@ -17,22 +17,22 @@
17
17
  "dev": "tsup src/index.ts --format cjs,esm --watch --dts --external react"
18
18
  },
19
19
  "dependencies": {
20
- "@anonfly/sdk": "0.0.0",
21
- "lucide-react": "^0.300.0",
22
- "clsx": "^2.1.0",
23
- "tailwind-merge": "^2.2.0"
20
+ "@anonfly/sdk": "^1.0.1",
21
+ "lucide-react": "^0.473.0",
22
+ "clsx": "^2.1.1",
23
+ "tailwind-merge": "^3.0.1"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "react": ">=18",
27
27
  "react-dom": ">=18"
28
28
  },
29
29
  "devDependencies": {
30
- "@types/react": "^18.0.0",
31
- "@types/react-dom": "^18.0.0",
32
- "react": "^18.0.0",
33
- "react-dom": "^18.0.0",
34
- "tsup": "^8.0.0",
35
- "typescript": "^5.0.0"
30
+ "@types/react": "^19.0.0",
31
+ "@types/react-dom": "^19.0.0",
32
+ "react": "^19.0.0",
33
+ "react-dom": "^19.0.0",
34
+ "tsup": "^8.3.5",
35
+ "typescript": "^5.7.2"
36
36
  },
37
37
  "publishConfig": {
38
38
  "access": "public"