@seriphxyz/react 0.1.2 → 0.1.7

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/README.md ADDED
@@ -0,0 +1,288 @@
1
+ # @seriphxyz/react
2
+
3
+ > **Note:** This repo is a read-only mirror. Source lives in a private monorepo.
4
+ > For issues/PRs, please open them here and we'll sync changes back.
5
+
6
+ React hooks for [Seriph](https://seriph.xyz) widgets - comments, reactions, forms, subscriptions, and more.
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install @seriphxyz/react
12
+ ```
13
+
14
+ Works with React 18+ and React 19. Compatible with Next.js, Remix, Vite, and more.
15
+
16
+ ## Hooks
17
+
18
+ ### useSubscribe
19
+
20
+ Email subscription form:
21
+
22
+ ```tsx
23
+ import { useSubscribe } from "@seriphxyz/react";
24
+
25
+ function SubscribeForm() {
26
+ const [email, setEmail] = useState("");
27
+ const { submit, status, message, error } = useSubscribe({
28
+ siteKey: "your-key",
29
+ });
30
+
31
+ const handleSubmit = async (e) => {
32
+ e.preventDefault();
33
+ await submit(email);
34
+ };
35
+
36
+ return (
37
+ <form onSubmit={handleSubmit}>
38
+ <input
39
+ type="email"
40
+ value={email}
41
+ onChange={(e) => setEmail(e.target.value)}
42
+ placeholder="your@email.com"
43
+ />
44
+ <button disabled={status === "loading"}>
45
+ {status === "loading" ? "Subscribing..." : "Subscribe"}
46
+ </button>
47
+ {status === "success" && <p>{message}</p>}
48
+ {status === "error" && <p>{error?.message}</p>}
49
+ </form>
50
+ );
51
+ }
52
+ ```
53
+
54
+ ### useReactions
55
+
56
+ Reaction buttons (like, love, clap, etc.):
57
+
58
+ ```tsx
59
+ import { useReactions } from "@seriphxyz/react";
60
+
61
+ function LikeButton() {
62
+ const { counts, userReactions, add, remove, status } = useReactions({
63
+ siteKey: "your-key",
64
+ pageId: "my-page",
65
+ });
66
+
67
+ const hasLiked = userReactions.includes("like");
68
+
69
+ return (
70
+ <button onClick={() => (hasLiked ? remove("like") : add("like"))}>
71
+ {hasLiked ? "Unlike" : "Like"} ({counts.like || 0})
72
+ </button>
73
+ );
74
+ }
75
+ ```
76
+
77
+ ### useComments
78
+
79
+ Threaded comments:
80
+
81
+ ```tsx
82
+ import { useComments } from "@seriphxyz/react";
83
+
84
+ function Comments() {
85
+ const { comments, post, status, error } = useComments({
86
+ siteKey: "your-key",
87
+ pageId: "my-page",
88
+ });
89
+
90
+ const handleSubmit = async (name, content) => {
91
+ await post(name, content);
92
+ };
93
+
94
+ return (
95
+ <div>
96
+ {comments.map((comment) => (
97
+ <div key={comment.id}>
98
+ <strong>{comment.authorName}</strong>
99
+ <p>{comment.content}</p>
100
+ </div>
101
+ ))}
102
+ </div>
103
+ );
104
+ }
105
+ ```
106
+
107
+ ### useForm
108
+
109
+ Contact forms with spam protection:
110
+
111
+ ```tsx
112
+ import { useForm } from "@seriphxyz/react";
113
+
114
+ function ContactForm() {
115
+ const { submit, status, message } = useForm({
116
+ siteKey: "your-key",
117
+ formSlug: "contact",
118
+ });
119
+
120
+ const handleSubmit = async (e) => {
121
+ e.preventDefault();
122
+ const data = Object.fromEntries(new FormData(e.target));
123
+ await submit(data);
124
+ };
125
+
126
+ return (
127
+ <form onSubmit={handleSubmit}>
128
+ <input name="email" type="email" required />
129
+ <textarea name="message" required />
130
+ <button type="submit">Send</button>
131
+ {status === "success" && <p>{message}</p>}
132
+ </form>
133
+ );
134
+ }
135
+ ```
136
+
137
+ ### useWaitlist
138
+
139
+ Waitlist signups:
140
+
141
+ ```tsx
142
+ import { useWaitlist } from "@seriphxyz/react";
143
+
144
+ function WaitlistForm() {
145
+ const { join, status, message, position } = useWaitlist({
146
+ siteKey: "your-key",
147
+ });
148
+
149
+ const handleSubmit = async (e) => {
150
+ e.preventDefault();
151
+ await join(email, { name, source: "homepage" });
152
+ };
153
+
154
+ return (
155
+ <form onSubmit={handleSubmit}>
156
+ <input name="email" type="email" required />
157
+ <button type="submit">Join Waitlist</button>
158
+ {status === "success" && <p>{message}</p>}
159
+ </form>
160
+ );
161
+ }
162
+ ```
163
+
164
+ ### useFeedback
165
+
166
+ Feedback forms:
167
+
168
+ ```tsx
169
+ import { useFeedback } from "@seriphxyz/react";
170
+
171
+ function FeedbackWidget() {
172
+ const { submit, status, message } = useFeedback({
173
+ siteKey: "your-key",
174
+ });
175
+
176
+ const handleSubmit = async (type, content) => {
177
+ await submit(type, content, { email, pageUrl: window.location.href });
178
+ };
179
+
180
+ // ...
181
+ }
182
+ ```
183
+
184
+ ### usePoll
185
+
186
+ Polls and voting:
187
+
188
+ ```tsx
189
+ import { usePoll } from "@seriphxyz/react";
190
+
191
+ function Poll() {
192
+ const { poll, vote, hasVoted, status } = usePoll({
193
+ siteKey: "your-key",
194
+ pollId: 123,
195
+ });
196
+
197
+ if (!poll) return <div>Loading...</div>;
198
+
199
+ return (
200
+ <div>
201
+ <h3>{poll.question}</h3>
202
+ {poll.options.map((option) => (
203
+ <button
204
+ key={option.id}
205
+ onClick={() => vote([option.id])}
206
+ disabled={hasVoted}
207
+ >
208
+ {option.text} ({poll.results?.[option.id] || 0})
209
+ </button>
210
+ ))}
211
+ </div>
212
+ );
213
+ }
214
+ ```
215
+
216
+ ### useAnnouncements
217
+
218
+ Site announcements:
219
+
220
+ ```tsx
221
+ import { useAnnouncements } from "@seriphxyz/react";
222
+
223
+ function AnnouncementBanner() {
224
+ const { announcements, dismiss, status } = useAnnouncements({
225
+ siteKey: "your-key",
226
+ });
227
+
228
+ const visible = announcements.filter((a) => !a.dismissed);
229
+
230
+ return (
231
+ <>
232
+ {visible.map((announcement) => (
233
+ <div key={announcement.id}>
234
+ <p>{announcement.content}</p>
235
+ {announcement.isDismissible && (
236
+ <button onClick={() => dismiss(announcement.id)}>Dismiss</button>
237
+ )}
238
+ </div>
239
+ ))}
240
+ </>
241
+ );
242
+ }
243
+ ```
244
+
245
+ ### useViewCounts
246
+
247
+ Page view tracking:
248
+
249
+ ```tsx
250
+ import { useViewCounts } from "@seriphxyz/react";
251
+ import { useEffect } from "react";
252
+
253
+ function PageViews() {
254
+ const { views, uniqueVisitors, record, status } = useViewCounts({
255
+ siteKey: "your-key",
256
+ pageId: "my-page",
257
+ });
258
+
259
+ // Record view on mount
260
+ useEffect(() => {
261
+ record();
262
+ }, []);
263
+
264
+ return (
265
+ <span>
266
+ {views} views ({uniqueVisitors} unique)
267
+ </span>
268
+ );
269
+ }
270
+ ```
271
+
272
+ ## All Hooks
273
+
274
+ | Hook | Purpose |
275
+ |------|---------|
276
+ | `useSubscribe` | Email subscriptions |
277
+ | `useReactions` | Page reactions |
278
+ | `useComments` | Threaded comments |
279
+ | `useForm` | Form submissions |
280
+ | `useWaitlist` | Waitlist signups |
281
+ | `useFeedback` | Feedback forms |
282
+ | `usePoll` | Polls and voting |
283
+ | `useAnnouncements` | Site announcements |
284
+ | `useViewCounts` | Page view tracking |
285
+
286
+ ## License
287
+
288
+ MIT
package/dist/index.d.ts CHANGED
@@ -124,7 +124,10 @@ export interface UseCommentsReturn {
124
124
  comments: Comment[];
125
125
  status: ControllerStatus;
126
126
  error: Error | null;
127
- postComment: (author: string, content: string) => Promise<void>;
127
+ postComment: (author: string, content: string, options?: {
128
+ authorEmail?: string;
129
+ parentId?: string;
130
+ }) => Promise<void>;
128
131
  refresh: () => Promise<void>;
129
132
  }
130
133
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -186,8 +186,8 @@ export function useComments(options) {
186
186
  }
187
187
  return unsubscribe;
188
188
  }, [options.siteKey, options.endpoint, options.contentId]);
189
- const postComment = useCallback(async (author, content) => {
190
- await controllerRef.current?.post(author, content);
189
+ const postComment = useCallback(async (author, content, options) => {
190
+ await controllerRef.current?.post(author, content, options);
191
191
  }, []);
192
192
  const refresh = useCallback(async () => {
193
193
  await controllerRef.current?.fetch();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seriphxyz/react",
3
- "version": "0.1.2",
3
+ "version": "0.1.7",
4
4
  "description": "React hooks for Seriph widgets (forms, comments, reactions, subscriptions)",
5
5
  "repository": {
6
6
  "type": "git",
@@ -31,7 +31,7 @@
31
31
  ],
32
32
  "license": "MIT",
33
33
  "dependencies": {
34
- "@seriphxyz/core": "0.1.2"
34
+ "@seriphxyz/core": "0.1.7"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "react": "^18.0.0 || ^19.0.0"