@seriphxyz/react 0.1.8 → 0.1.11

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/dist/index.d.ts CHANGED
@@ -29,10 +29,14 @@
29
29
  * }
30
30
  * ```
31
31
  */
32
- import { type SeriphConfig, type Comment, type ControllerStatus } from "@seriphxyz/core";
33
- export type { SeriphConfig, SubscribeState, FormState, ReactionsState, CommentsState, Comment, ReactionCounts, SeriphPost, FetchPostsOptions, FetchPostOptions, ControllerStatus, } from "@seriphxyz/core";
34
- export { fetchPosts, fetchPost, DEFAULT_ENDPOINT, API_PATH, } from "@seriphxyz/core";
35
- export interface UseSubscribeOptions extends SeriphConfig {
32
+ import { type SeriphConfig, type Comment, type Announcement, type PollWithResults, type FeedbackType, type ControllerStatus } from "@seriphxyz/core";
33
+ export type { SeriphConfig, SubscribeState, FormState, ReactionsState, CommentsState, WaitlistState, ViewCountsState, FeedbackState, PollState, AnnouncementsState, Comment, Announcement, PollWithResults, FeedbackType, ReactionCounts, SeriphPost, FetchPostsOptions, FetchPostOptions, ControllerStatus, } from "@seriphxyz/core";
34
+ export { fetchPosts, fetchPost, getConfigFromMeta, resolveConfig, DEFAULT_ENDPOINT, API_PATH, } from "@seriphxyz/core";
35
+ type OptionalSiteKey<T extends SeriphConfig> = Omit<T, "siteKey"> & {
36
+ /** Site key - optional if <meta name="seriph-site-key"> is set */
37
+ siteKey?: string;
38
+ };
39
+ export interface UseSubscribeOptions extends OptionalSiteKey<SeriphConfig> {
36
40
  }
37
41
  export interface UseSubscribeReturn {
38
42
  status: ControllerStatus;
@@ -54,7 +58,7 @@ export interface UseSubscribeReturn {
54
58
  * ```
55
59
  */
56
60
  export declare function useSubscribe(options: UseSubscribeOptions): UseSubscribeReturn;
57
- export interface UseFormOptions extends SeriphConfig {
61
+ export interface UseFormOptions extends OptionalSiteKey<SeriphConfig> {
58
62
  /** Form slug/identifier */
59
63
  formSlug: string;
60
64
  }
@@ -83,7 +87,7 @@ export interface UseFormReturn {
83
87
  * ```
84
88
  */
85
89
  export declare function useForm(options: UseFormOptions): UseFormReturn;
86
- export interface UseReactionsOptions extends SeriphConfig {
90
+ export interface UseReactionsOptions extends OptionalSiteKey<SeriphConfig> {
87
91
  /** Content identifier (e.g., post slug) */
88
92
  contentId: string;
89
93
  /** Auto-fetch reactions on mount (default: true) */
@@ -114,7 +118,7 @@ export interface UseReactionsReturn {
114
118
  * ```
115
119
  */
116
120
  export declare function useReactions(options: UseReactionsOptions): UseReactionsReturn;
117
- export interface UseCommentsOptions extends SeriphConfig {
121
+ export interface UseCommentsOptions extends OptionalSiteKey<SeriphConfig> {
118
122
  /** Content identifier (e.g., post slug) */
119
123
  contentId: string;
120
124
  /** Auto-fetch comments on mount (default: true) */
@@ -152,4 +156,154 @@ export interface UseCommentsReturn {
152
156
  * ```
153
157
  */
154
158
  export declare function useComments(options: UseCommentsOptions): UseCommentsReturn;
159
+ export interface UseWaitlistOptions extends OptionalSiteKey<SeriphConfig> {
160
+ }
161
+ export interface UseWaitlistReturn {
162
+ status: ControllerStatus;
163
+ message: string | null;
164
+ position: number | null;
165
+ error: Error | null;
166
+ join: (email: string, options?: {
167
+ name?: string;
168
+ source?: string;
169
+ }) => Promise<void>;
170
+ reset: () => void;
171
+ }
172
+ /**
173
+ * Hook for handling waitlist signups.
174
+ *
175
+ * @example
176
+ * ```tsx
177
+ * const { join, status, message, position } = useWaitlist({
178
+ * siteKey: 'your-site-key',
179
+ * });
180
+ *
181
+ * <button onClick={() => join('user@example.com')}>Join Waitlist</button>
182
+ * {status === 'success' && <p>You're #{position} on the list!</p>}
183
+ * ```
184
+ */
185
+ export declare function useWaitlist(options: UseWaitlistOptions): UseWaitlistReturn;
186
+ export interface UseViewsOptions extends OptionalSiteKey<SeriphConfig> {
187
+ /** Page identifier (e.g., slug or URL path) */
188
+ pageId: string;
189
+ /** Auto-record view on mount (default: true) */
190
+ autoRecord?: boolean;
191
+ }
192
+ export interface UseViewsReturn {
193
+ views: number;
194
+ uniqueVisitors: number;
195
+ status: ControllerStatus;
196
+ error: Error | null;
197
+ record: () => Promise<void>;
198
+ refresh: () => Promise<void>;
199
+ }
200
+ /**
201
+ * Hook for tracking and displaying page views.
202
+ *
203
+ * @example
204
+ * ```tsx
205
+ * const { views, uniqueVisitors } = useViews({
206
+ * siteKey: 'your-site-key',
207
+ * pageId: '/blog/my-post',
208
+ * });
209
+ *
210
+ * <span>{views} views ({uniqueVisitors} unique)</span>
211
+ * ```
212
+ */
213
+ export declare function useViews(options: UseViewsOptions): UseViewsReturn;
214
+ export interface UseFeedbackOptions extends OptionalSiteKey<SeriphConfig> {
215
+ }
216
+ export interface UseFeedbackReturn {
217
+ status: ControllerStatus;
218
+ message: string | null;
219
+ error: Error | null;
220
+ submit: (type: FeedbackType, content: string, options?: {
221
+ email?: string;
222
+ pageUrl?: string;
223
+ }) => Promise<void>;
224
+ reset: () => void;
225
+ }
226
+ /**
227
+ * Hook for handling feedback submissions.
228
+ *
229
+ * @example
230
+ * ```tsx
231
+ * const { submit, status } = useFeedback({
232
+ * siteKey: 'your-site-key',
233
+ * });
234
+ *
235
+ * <button onClick={() => submit('feature', 'Add dark mode!')}>
236
+ * Submit Feedback
237
+ * </button>
238
+ * ```
239
+ */
240
+ export declare function useFeedback(options: UseFeedbackOptions): UseFeedbackReturn;
241
+ export interface UsePollOptions extends OptionalSiteKey<SeriphConfig> {
242
+ /** Poll slug */
243
+ slug: string;
244
+ /** Auto-fetch poll on mount (default: true) */
245
+ autoFetch?: boolean;
246
+ }
247
+ export interface UsePollReturn {
248
+ poll: PollWithResults | null;
249
+ status: ControllerStatus;
250
+ error: Error | null;
251
+ vote: (selectedOptions: string[]) => Promise<void>;
252
+ hasVoted: boolean;
253
+ refresh: () => Promise<void>;
254
+ }
255
+ /**
256
+ * Hook for displaying and voting on polls.
257
+ *
258
+ * @example
259
+ * ```tsx
260
+ * const { poll, vote, hasVoted } = usePoll({
261
+ * siteKey: 'your-site-key',
262
+ * slug: 'favorite-framework',
263
+ * });
264
+ *
265
+ * {poll && (
266
+ * <div>
267
+ * <h3>{poll.question}</h3>
268
+ * {poll.options.map(opt => (
269
+ * <button key={opt.id} onClick={() => vote([opt.id])} disabled={hasVoted}>
270
+ * {opt.text} ({poll.results[opt.id] || 0} votes)
271
+ * </button>
272
+ * ))}
273
+ * </div>
274
+ * )}
275
+ * ```
276
+ */
277
+ export declare function usePoll(options: UsePollOptions): UsePollReturn;
278
+ export interface UseAnnouncementsOptions extends OptionalSiteKey<SeriphConfig> {
279
+ /** Auto-fetch announcements on mount (default: true) */
280
+ autoFetch?: boolean;
281
+ }
282
+ export interface UseAnnouncementsReturn {
283
+ announcements: Announcement[];
284
+ status: ControllerStatus;
285
+ error: Error | null;
286
+ dismiss: (announcementId: number) => Promise<void>;
287
+ refresh: () => Promise<void>;
288
+ }
289
+ /**
290
+ * Hook for displaying site announcements.
291
+ *
292
+ * @example
293
+ * ```tsx
294
+ * const { announcements, dismiss } = useAnnouncements({
295
+ * siteKey: 'your-site-key',
296
+ * });
297
+ *
298
+ * {announcements.map(ann => (
299
+ * <div key={ann.id} className={`announcement-${ann.announcementType}`}>
300
+ * {ann.content}
301
+ * {ann.isDismissible && (
302
+ * <button onClick={() => dismiss(ann.id)}>Dismiss</button>
303
+ * )}
304
+ * </div>
305
+ * ))}
306
+ * ```
307
+ */
308
+ export declare function useAnnouncements(options: UseAnnouncementsOptions): UseAnnouncementsReturn;
155
309
  //# sourceMappingURL=index.d.ts.map
@@ -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
@@ -30,9 +30,9 @@
30
30
  * ```
31
31
  */
32
32
  import { useState, useCallback, useEffect, useRef } from "react";
33
- import { SubscribeController, FormController, ReactionsController, CommentsController, } from "@seriphxyz/core";
34
- // Re-export API functions from core
35
- export { fetchPosts, fetchPost, DEFAULT_ENDPOINT, API_PATH, } from "@seriphxyz/core";
33
+ import { SubscribeController, FormController, ReactionsController, CommentsController, WaitlistController, ViewCountsController, FeedbackController, PollController, AnnouncementsController, resolveConfig, } from "@seriphxyz/core";
34
+ // Re-export API functions and helpers from core
35
+ export { fetchPosts, fetchPost, getConfigFromMeta, resolveConfig, DEFAULT_ENDPOINT, API_PATH, } from "@seriphxyz/core";
36
36
  /**
37
37
  * Hook for handling email subscriptions.
38
38
  *
@@ -53,7 +53,8 @@ export function useSubscribe(options) {
53
53
  error: null,
54
54
  });
55
55
  useEffect(() => {
56
- const controller = new SubscribeController(options);
56
+ const config = resolveConfig(options);
57
+ const controller = new SubscribeController(config);
57
58
  controllerRef.current = controller;
58
59
  const unsubscribe = controller.subscribe(setState);
59
60
  return unsubscribe;
@@ -91,7 +92,8 @@ export function useForm(options) {
91
92
  error: null,
92
93
  });
93
94
  useEffect(() => {
94
- const controller = new FormController(options, options.formSlug);
95
+ const config = resolveConfig(options);
96
+ const controller = new FormController(config, options.formSlug);
95
97
  controllerRef.current = controller;
96
98
  const unsubscribe = controller.subscribe(setState);
97
99
  return unsubscribe;
@@ -128,7 +130,8 @@ export function useReactions(options) {
128
130
  error: null,
129
131
  });
130
132
  useEffect(() => {
131
- const controller = new ReactionsController(options, options.contentId);
133
+ const config = resolveConfig(options);
134
+ const controller = new ReactionsController(config, options.contentId);
132
135
  controllerRef.current = controller;
133
136
  const unsubscribe = controller.subscribe(setState);
134
137
  // Auto-fetch on mount (default: true)
@@ -177,7 +180,8 @@ export function useComments(options) {
177
180
  error: null,
178
181
  });
179
182
  useEffect(() => {
180
- const controller = new CommentsController(options, options.contentId);
183
+ const config = resolveConfig(options);
184
+ const controller = new CommentsController(config, options.contentId);
181
185
  controllerRef.current = controller;
182
186
  const unsubscribe = controller.subscribe(setState);
183
187
  // Auto-fetch on mount (default: true)
@@ -194,3 +198,213 @@ export function useComments(options) {
194
198
  }, []);
195
199
  return { ...state, postComment, refresh };
196
200
  }
201
+ /**
202
+ * Hook for handling waitlist signups.
203
+ *
204
+ * @example
205
+ * ```tsx
206
+ * const { join, status, message, position } = useWaitlist({
207
+ * siteKey: 'your-site-key',
208
+ * });
209
+ *
210
+ * <button onClick={() => join('user@example.com')}>Join Waitlist</button>
211
+ * {status === 'success' && <p>You're #{position} on the list!</p>}
212
+ * ```
213
+ */
214
+ export function useWaitlist(options) {
215
+ const controllerRef = useRef(null);
216
+ const [state, setState] = useState({
217
+ status: "idle",
218
+ message: null,
219
+ position: null,
220
+ error: null,
221
+ });
222
+ useEffect(() => {
223
+ const config = resolveConfig(options);
224
+ const controller = new WaitlistController(config);
225
+ controllerRef.current = controller;
226
+ const unsubscribe = controller.subscribe(setState);
227
+ return unsubscribe;
228
+ }, [options.siteKey, options.endpoint]);
229
+ const join = useCallback(async (email, opts) => {
230
+ await controllerRef.current?.join(email, opts);
231
+ }, []);
232
+ const reset = useCallback(() => {
233
+ controllerRef.current?.reset();
234
+ }, []);
235
+ return { ...state, join, reset };
236
+ }
237
+ /**
238
+ * Hook for tracking and displaying page views.
239
+ *
240
+ * @example
241
+ * ```tsx
242
+ * const { views, uniqueVisitors } = useViews({
243
+ * siteKey: 'your-site-key',
244
+ * pageId: '/blog/my-post',
245
+ * });
246
+ *
247
+ * <span>{views} views ({uniqueVisitors} unique)</span>
248
+ * ```
249
+ */
250
+ export function useViews(options) {
251
+ const controllerRef = useRef(null);
252
+ const [state, setState] = useState({
253
+ pageId: options.pageId,
254
+ views: 0,
255
+ uniqueVisitors: 0,
256
+ status: "idle",
257
+ error: null,
258
+ });
259
+ useEffect(() => {
260
+ const config = resolveConfig(options);
261
+ const controller = new ViewCountsController(config, options.pageId);
262
+ controllerRef.current = controller;
263
+ const unsubscribe = controller.subscribe(setState);
264
+ // Auto-record view on mount (default: true)
265
+ if (options.autoRecord !== false) {
266
+ controller.record();
267
+ }
268
+ return unsubscribe;
269
+ }, [options.siteKey, options.endpoint, options.pageId]);
270
+ const record = useCallback(async () => {
271
+ await controllerRef.current?.record();
272
+ }, []);
273
+ const refresh = useCallback(async () => {
274
+ await controllerRef.current?.fetch();
275
+ }, []);
276
+ return { views: state.views, uniqueVisitors: state.uniqueVisitors, status: state.status, error: state.error, record, refresh };
277
+ }
278
+ /**
279
+ * Hook for handling feedback submissions.
280
+ *
281
+ * @example
282
+ * ```tsx
283
+ * const { submit, status } = useFeedback({
284
+ * siteKey: 'your-site-key',
285
+ * });
286
+ *
287
+ * <button onClick={() => submit('feature', 'Add dark mode!')}>
288
+ * Submit Feedback
289
+ * </button>
290
+ * ```
291
+ */
292
+ export function useFeedback(options) {
293
+ const controllerRef = useRef(null);
294
+ const [state, setState] = useState({
295
+ status: "idle",
296
+ message: null,
297
+ error: null,
298
+ });
299
+ useEffect(() => {
300
+ const config = resolveConfig(options);
301
+ const controller = new FeedbackController(config);
302
+ controllerRef.current = controller;
303
+ const unsubscribe = controller.subscribe(setState);
304
+ return unsubscribe;
305
+ }, [options.siteKey, options.endpoint]);
306
+ const submit = useCallback(async (type, content, opts) => {
307
+ await controllerRef.current?.submit(type, content, opts);
308
+ }, []);
309
+ const reset = useCallback(() => {
310
+ controllerRef.current?.reset();
311
+ }, []);
312
+ return { ...state, submit, reset };
313
+ }
314
+ /**
315
+ * Hook for displaying and voting on polls.
316
+ *
317
+ * @example
318
+ * ```tsx
319
+ * const { poll, vote, hasVoted } = usePoll({
320
+ * siteKey: 'your-site-key',
321
+ * slug: 'favorite-framework',
322
+ * });
323
+ *
324
+ * {poll && (
325
+ * <div>
326
+ * <h3>{poll.question}</h3>
327
+ * {poll.options.map(opt => (
328
+ * <button key={opt.id} onClick={() => vote([opt.id])} disabled={hasVoted}>
329
+ * {opt.text} ({poll.results[opt.id] || 0} votes)
330
+ * </button>
331
+ * ))}
332
+ * </div>
333
+ * )}
334
+ * ```
335
+ */
336
+ export function usePoll(options) {
337
+ const controllerRef = useRef(null);
338
+ const [state, setState] = useState({
339
+ poll: null,
340
+ status: "idle",
341
+ error: null,
342
+ });
343
+ useEffect(() => {
344
+ const config = resolveConfig(options);
345
+ const controller = new PollController(config, options.slug);
346
+ controllerRef.current = controller;
347
+ const unsubscribe = controller.subscribe(setState);
348
+ // Auto-fetch on mount (default: true)
349
+ if (options.autoFetch !== false) {
350
+ controller.fetch();
351
+ }
352
+ return unsubscribe;
353
+ }, [options.siteKey, options.endpoint, options.slug]);
354
+ const vote = useCallback(async (selectedOptions) => {
355
+ await controllerRef.current?.vote(selectedOptions);
356
+ }, []);
357
+ const refresh = useCallback(async () => {
358
+ await controllerRef.current?.fetch();
359
+ }, []);
360
+ const hasVoted = controllerRef.current?.hasVoted() ?? false;
361
+ return { ...state, vote, hasVoted, refresh };
362
+ }
363
+ /**
364
+ * Hook for displaying site announcements.
365
+ *
366
+ * @example
367
+ * ```tsx
368
+ * const { announcements, dismiss } = useAnnouncements({
369
+ * siteKey: 'your-site-key',
370
+ * });
371
+ *
372
+ * {announcements.map(ann => (
373
+ * <div key={ann.id} className={`announcement-${ann.announcementType}`}>
374
+ * {ann.content}
375
+ * {ann.isDismissible && (
376
+ * <button onClick={() => dismiss(ann.id)}>Dismiss</button>
377
+ * )}
378
+ * </div>
379
+ * ))}
380
+ * ```
381
+ */
382
+ export function useAnnouncements(options) {
383
+ const controllerRef = useRef(null);
384
+ const [state, setState] = useState({
385
+ announcements: [],
386
+ dismissed: new Set(),
387
+ status: "idle",
388
+ error: null,
389
+ });
390
+ useEffect(() => {
391
+ const config = resolveConfig(options);
392
+ const controller = new AnnouncementsController(config);
393
+ controllerRef.current = controller;
394
+ const unsubscribe = controller.subscribe(setState);
395
+ // Auto-fetch on mount (default: true)
396
+ if (options.autoFetch !== false) {
397
+ controller.fetch();
398
+ }
399
+ return unsubscribe;
400
+ }, [options.siteKey, options.endpoint]);
401
+ const dismiss = useCallback(async (announcementId) => {
402
+ await controllerRef.current?.dismiss(announcementId);
403
+ }, []);
404
+ const refresh = useCallback(async () => {
405
+ await controllerRef.current?.fetch();
406
+ }, []);
407
+ // Return only visible (non-dismissed) announcements
408
+ const visibleAnnouncements = controllerRef.current?.getVisibleAnnouncements() ?? [];
409
+ return { announcements: visibleAnnouncements, status: state.status, error: state.error, dismiss, refresh };
410
+ }
package/package.json CHANGED
@@ -1,13 +1,17 @@
1
1
  {
2
2
  "name": "@seriphxyz/react",
3
- "version": "0.1.8",
3
+ "version": "0.1.11",
4
4
  "description": "React hooks for Seriph widgets (forms, comments, reactions, subscriptions)",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/seriphxyz/react.git"
8
8
  },
9
+ "publishConfig": {
10
+ "access": "public",
11
+ "provenance": true
12
+ },
9
13
  "homepage": "https://seriph.xyz",
10
- "author": "Tim Shedor",
14
+ "author": "Tim Marks <tim@imothee.xyz>",
11
15
  "type": "module",
12
16
  "main": "./dist/index.js",
13
17
  "types": "./dist/index.d.ts",
@@ -20,6 +24,10 @@
20
24
  "files": [
21
25
  "dist"
22
26
  ],
27
+ "scripts": {
28
+ "build": "tsc",
29
+ "dev": "tsc --watch"
30
+ },
23
31
  "keywords": [
24
32
  "react",
25
33
  "seriph",
@@ -31,7 +39,7 @@
31
39
  ],
32
40
  "license": "MIT",
33
41
  "dependencies": {
34
- "@seriphxyz/core": "0.1.8"
42
+ "@seriphxyz/core": "^0.1.11"
35
43
  },
36
44
  "peerDependencies": {
37
45
  "react": "^18.0.0 || ^19.0.0"
@@ -40,9 +48,5 @@
40
48
  "@types/react": "^18.3.0",
41
49
  "react": "^18.3.0",
42
50
  "typescript": "^5.7.3"
43
- },
44
- "scripts": {
45
- "build": "tsc",
46
- "dev": "tsc --watch"
47
51
  }
48
- }
52
+ }