@pageloop/client 0.5.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 (70) hide show
  1. package/LICENSE +94 -0
  2. package/README.md +97 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/.tsbuildinfo.preact +1 -0
  5. package/dist/.tsbuildinfo.react +1 -0
  6. package/dist/.tsbuildinfo.solid +1 -0
  7. package/dist/ApiClient.d.ts +121 -0
  8. package/dist/ApiClient.d.ts.map +1 -0
  9. package/dist/ApiClient.js +512 -0
  10. package/dist/ApiClient.js.map +1 -0
  11. package/dist/CommentEngine.d.ts +111 -0
  12. package/dist/CommentEngine.d.ts.map +1 -0
  13. package/dist/CommentEngine.js +277 -0
  14. package/dist/CommentEngine.js.map +1 -0
  15. package/dist/EventBus.d.ts +122 -0
  16. package/dist/EventBus.d.ts.map +1 -0
  17. package/dist/EventBus.js +34 -0
  18. package/dist/EventBus.js.map +1 -0
  19. package/dist/IdbCache.d.ts +22 -0
  20. package/dist/IdbCache.d.ts.map +1 -0
  21. package/dist/IdbCache.js +79 -0
  22. package/dist/IdbCache.js.map +1 -0
  23. package/dist/PageLoop.d.ts +424 -0
  24. package/dist/PageLoop.d.ts.map +1 -0
  25. package/dist/PageLoop.js +1092 -0
  26. package/dist/PageLoop.js.map +1 -0
  27. package/dist/PageTracker.d.ts +32 -0
  28. package/dist/PageTracker.d.ts.map +1 -0
  29. package/dist/PageTracker.js +105 -0
  30. package/dist/PageTracker.js.map +1 -0
  31. package/dist/UIRenderer.d.ts +218 -0
  32. package/dist/UIRenderer.d.ts.map +1 -0
  33. package/dist/UIRenderer.js +2 -0
  34. package/dist/UIRenderer.js.map +1 -0
  35. package/dist/auth/resolveInitialToken.d.ts +49 -0
  36. package/dist/auth/resolveInitialToken.d.ts.map +1 -0
  37. package/dist/auth/resolveInitialToken.js +97 -0
  38. package/dist/auth/resolveInitialToken.js.map +1 -0
  39. package/dist/errorCode.d.ts +12 -0
  40. package/dist/errorCode.d.ts.map +1 -0
  41. package/dist/errorCode.js +21 -0
  42. package/dist/errorCode.js.map +1 -0
  43. package/dist/index.d.ts +20 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +18 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/notifications/BrowserNotifications.d.ts +68 -0
  48. package/dist/notifications/BrowserNotifications.d.ts.map +1 -0
  49. package/dist/notifications/BrowserNotifications.js +147 -0
  50. package/dist/notifications/BrowserNotifications.js.map +1 -0
  51. package/dist/preact/index.d.ts +37 -0
  52. package/dist/preact/index.d.ts.map +1 -0
  53. package/dist/preact/index.js +150 -0
  54. package/dist/preact/index.js.map +1 -0
  55. package/dist/preact/style.css +12 -0
  56. package/dist/react/index.d.ts +52 -0
  57. package/dist/react/index.d.ts.map +1 -0
  58. package/dist/react/index.js +165 -0
  59. package/dist/react/index.js.map +1 -0
  60. package/dist/react/style.css +12 -0
  61. package/dist/safeStorage.d.ts +26 -0
  62. package/dist/safeStorage.d.ts.map +1 -0
  63. package/dist/safeStorage.js +78 -0
  64. package/dist/safeStorage.js.map +1 -0
  65. package/dist/solid/index.d.ts +40 -0
  66. package/dist/solid/index.d.ts.map +1 -0
  67. package/dist/solid/index.jsx +134 -0
  68. package/dist/solid/index.jsx.map +1 -0
  69. package/dist/solid/style.css +12 -0
  70. package/package.json +85 -0
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @pageloop/client
3
+ *
4
+ * Browser SDK. Framework-agnostic — UI rendering goes through the
5
+ * `UIRenderer` interface, which @pageloop/vanilla, @pageloop/react etc.
6
+ * implement.
7
+ */
8
+ export { PageLoop, type PageLoopConfig, type PageLoopDeps } from './PageLoop.js';
9
+ export { ApiClient } from './ApiClient.js';
10
+ export { CommentEngine } from './CommentEngine.js';
11
+ export { PageTracker } from './PageTracker.js';
12
+ export { IdbCache } from './IdbCache.js';
13
+ export { EventBus, type ClientEventName, type ClientEventHandler, type PageLoopErrorPayload, } from './EventBus.js';
14
+ export type { UIRenderer, UIRendererDeps, ToolbarHandle, SidebarHandle, SidebarState, CommentComposeRequest, } from './UIRenderer.js';
15
+ export { resolveInitialToken, SESSION_TOKEN_KEY, } from './auth/resolveInitialToken.js';
16
+ export { BrowserNotifications } from './notifications/BrowserNotifications.js';
17
+ export { safeStorage } from './safeStorage.js';
18
+ export { resolveAnchor, serializeRange, serializeElement } from '@pageloop/anchor';
19
+ export type { Comment, Anchor, TrackedPage, Project, Reaction, ReactionTargetKind, } from '@pageloop/shared';
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,QAAQ,EAAE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EACN,QAAQ,EACR,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,GACzB,MAAM,eAAe,CAAC;AACvB,YAAY,EACX,UAAU,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACb,YAAY,EACZ,qBAAqB,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,mBAAmB,EACnB,iBAAiB,GACjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACnF,YAAY,EACX,OAAO,EACP,MAAM,EACN,WAAW,EACX,OAAO,EACP,QAAQ,EACR,kBAAkB,GAClB,MAAM,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @pageloop/client
3
+ *
4
+ * Browser SDK. Framework-agnostic — UI rendering goes through the
5
+ * `UIRenderer` interface, which @pageloop/vanilla, @pageloop/react etc.
6
+ * implement.
7
+ */
8
+ export { PageLoop } from './PageLoop.js';
9
+ export { ApiClient } from './ApiClient.js';
10
+ export { CommentEngine } from './CommentEngine.js';
11
+ export { PageTracker } from './PageTracker.js';
12
+ export { IdbCache } from './IdbCache.js';
13
+ export { EventBus, } from './EventBus.js';
14
+ export { resolveInitialToken, SESSION_TOKEN_KEY, } from './auth/resolveInitialToken.js';
15
+ export { BrowserNotifications } from './notifications/BrowserNotifications.js';
16
+ export { safeStorage } from './safeStorage.js';
17
+ export { resolveAnchor, serializeRange, serializeElement } from '@pageloop/anchor';
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,QAAQ,EAA0C,MAAM,eAAe,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EACN,QAAQ,GAIR,MAAM,eAAe,CAAC;AASvB,OAAO,EACN,mBAAmB,EACnB,iBAAiB,GACjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Browser-tab notifications via the standard Web Notification API.
3
+ *
4
+ * The server-side BrowserNotificationChannel emits a per-recipient
5
+ * `notification.show` event over the WebSocket; the WS broadcaster's
6
+ * fast path filters by `ctxUserId` so only the recipient's connected
7
+ * sessions receive the frame. ApiClient forwards the event onto the
8
+ * client EventBus by name — this manager subscribes to that and
9
+ * surfaces a real OS-level notification when permission is granted.
10
+ *
11
+ * Permission model:
12
+ * - We never call `Notification.requestPermission()` silently. The
13
+ * user opts in via a settings toggle (admin Settings page or the
14
+ * in-widget toggle when it lands). `requestPermission()` returns
15
+ * the new state so callers can persist the user's intent.
16
+ * - If permission is already granted, we just listen + show.
17
+ * - If permission is denied, we silently no-op — the host can
18
+ * surface a one-line hint in their settings UI.
19
+ *
20
+ * Click behaviour:
21
+ * - For comment / reply / mention envelopes carrying a pageUrl,
22
+ * clicking focuses the browser tab (if available) + navigates
23
+ * the URL with `?pl-comment=<id>` so the existing deep-link
24
+ * handler in PageLoop scrolls + flashes the target.
25
+ * - For chat envelopes, clicking focuses the tab + dispatches a
26
+ * custom event the host's chat UI can listen for.
27
+ */
28
+ import type { EventBus } from './../EventBus.js';
29
+ export interface BrowserNotificationsOptions {
30
+ bus: EventBus;
31
+ /** Optional debug-tracer; defaults to a no-op. */
32
+ debug?: (...args: unknown[]) => void;
33
+ }
34
+ export declare class BrowserNotifications {
35
+ private readonly bus;
36
+ private readonly debug;
37
+ private off;
38
+ constructor(opts: BrowserNotificationsOptions);
39
+ /**
40
+ * Wire the bus subscription. Idempotent — calling twice is a no-op.
41
+ *
42
+ * Lazy by default: only subscribes when permission has already been
43
+ * granted. A permission-not-yet-granted user pays zero overhead
44
+ * until they flip the toggle in Settings (which calls
45
+ * `requestPermission()` → re-subscribes automatically on grant).
46
+ *
47
+ * The `force: true` option exists for the Settings UI to wire up
48
+ * before the user flips the toggle, in case they had previously
49
+ * denied + are about to re-grant in another tab; a stored-event
50
+ * fan-out then resurfaces normally.
51
+ */
52
+ start(opts?: {
53
+ force?: boolean;
54
+ }): void;
55
+ stop(): void;
56
+ /** Current OS-level permission state. */
57
+ permission(): NotificationPermission;
58
+ /**
59
+ * Prompt the user for permission. Settings UIs call this when the
60
+ * user flips the browser-notifications toggle on. Resolves to the
61
+ * final permission state (which may be 'denied' if the user
62
+ * declined or had previously declined).
63
+ */
64
+ requestPermission(): Promise<NotificationPermission>;
65
+ private handleEvent;
66
+ private renderTitle;
67
+ }
68
+ //# sourceMappingURL=BrowserNotifications.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BrowserNotifications.d.ts","sourceRoot":"","sources":["../../src/notifications/BrowserNotifications.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AA0BjD,MAAM,WAAW,2BAA2B;IAC3C,GAAG,EAAE,QAAQ,CAAC;IACd,kDAAkD;IAClD,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACrC;AAED,qBAAa,oBAAoB;IAChC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAW;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA+B;IACrD,OAAO,CAAC,GAAG,CAA6B;gBAE5B,IAAI,EAAE,2BAA2B;IAK7C;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,IAAI,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,IAAI;IAmB3C,IAAI,IAAI,IAAI;IAKZ,yCAAyC;IACzC,UAAU,IAAI,sBAAsB;IAKpC;;;;;OAKG;IACG,iBAAiB,IAAI,OAAO,CAAC,sBAAsB,CAAC;YAmB5C,WAAW;IAqCzB,OAAO,CAAC,WAAW;CAqCnB"}
@@ -0,0 +1,147 @@
1
+ export class BrowserNotifications {
2
+ bus;
3
+ debug;
4
+ off = null;
5
+ constructor(opts) {
6
+ this.bus = opts.bus;
7
+ this.debug = opts.debug ?? (() => undefined);
8
+ }
9
+ /**
10
+ * Wire the bus subscription. Idempotent — calling twice is a no-op.
11
+ *
12
+ * Lazy by default: only subscribes when permission has already been
13
+ * granted. A permission-not-yet-granted user pays zero overhead
14
+ * until they flip the toggle in Settings (which calls
15
+ * `requestPermission()` → re-subscribes automatically on grant).
16
+ *
17
+ * The `force: true` option exists for the Settings UI to wire up
18
+ * before the user flips the toggle, in case they had previously
19
+ * denied + are about to re-grant in another tab; a stored-event
20
+ * fan-out then resurfaces normally.
21
+ */
22
+ start(opts = {}) {
23
+ if (this.off)
24
+ return;
25
+ if (typeof window === 'undefined' || typeof Notification === 'undefined') {
26
+ this.debug('[notifications] window or Notification API unavailable');
27
+ return;
28
+ }
29
+ if (!opts.force && Notification.permission !== 'granted') {
30
+ this.debug('[notifications] permission not granted — deferring subscription until grant');
31
+ return;
32
+ }
33
+ this.off = this.bus.on('notification.show', (event) => {
34
+ void this.handleEvent(event).catch((err) => this.debug('[notifications] handleEvent failed', err));
35
+ });
36
+ }
37
+ stop() {
38
+ this.off?.();
39
+ this.off = null;
40
+ }
41
+ /** Current OS-level permission state. */
42
+ permission() {
43
+ if (typeof Notification === 'undefined')
44
+ return 'denied';
45
+ return Notification.permission;
46
+ }
47
+ /**
48
+ * Prompt the user for permission. Settings UIs call this when the
49
+ * user flips the browser-notifications toggle on. Resolves to the
50
+ * final permission state (which may be 'denied' if the user
51
+ * declined or had previously declined).
52
+ */
53
+ async requestPermission() {
54
+ if (typeof Notification === 'undefined')
55
+ return 'denied';
56
+ if (Notification.permission === 'granted') {
57
+ // Already granted — make sure the bus subscription is live.
58
+ this.start({ force: true });
59
+ return 'granted';
60
+ }
61
+ if (Notification.permission === 'denied')
62
+ return 'denied';
63
+ try {
64
+ const result = await Notification.requestPermission();
65
+ if (result === 'granted')
66
+ this.start({ force: true });
67
+ return result;
68
+ }
69
+ catch {
70
+ return 'denied';
71
+ }
72
+ }
73
+ // ────────────────────────────────────────────────────────────────
74
+ async handleEvent(event) {
75
+ if (Notification.permission !== 'granted') {
76
+ this.debug('[notifications] received but permission not granted', event);
77
+ return;
78
+ }
79
+ const env = event.envelope;
80
+ if (!env)
81
+ return;
82
+ const { title, body, url } = this.renderTitle(env);
83
+ const tag = env.commentId ?? env.replyId ?? env.messageId ?? env.sourceId ?? env.kind;
84
+ // Same-tag notifications collapse so a burst of replies on one
85
+ // comment doesn't blast the user (browsers default `renotify`
86
+ // to false; we don't need to specify it). `tag` alone is what
87
+ // drives the collapse.
88
+ const notification = new Notification(title, {
89
+ body,
90
+ tag,
91
+ });
92
+ notification.onclick = (e) => {
93
+ e.preventDefault();
94
+ notification.close();
95
+ try {
96
+ window.focus();
97
+ }
98
+ catch {
99
+ /* cross-origin */
100
+ }
101
+ if (url) {
102
+ // `?pl-comment=<id>` activates the existing deep-link
103
+ // handler in PageLoop. For chat we just navigate.
104
+ try {
105
+ window.location.assign(url);
106
+ }
107
+ catch {
108
+ /* cross-origin or sandboxed */
109
+ }
110
+ }
111
+ };
112
+ }
113
+ renderTitle(env) {
114
+ const where = env.pageTitle ?? 'a page';
115
+ switch (env.kind) {
116
+ case 'comment.created':
117
+ return {
118
+ title: `${env.authorName} commented on ${where}`,
119
+ body: env.excerpt,
120
+ url: env.pageUrl && env.commentId
121
+ ? `${env.pageUrl}#pl-comment=${env.commentId}`
122
+ : null,
123
+ };
124
+ case 'reply.created':
125
+ return {
126
+ title: `${env.authorName} replied on ${where}`,
127
+ body: env.excerpt,
128
+ url: env.pageUrl && env.parentCommentId
129
+ ? `${env.pageUrl}#pl-comment=${env.parentCommentId}`
130
+ : null,
131
+ };
132
+ case 'chat.message':
133
+ return {
134
+ title: `${env.authorName} sent a message`,
135
+ body: env.excerpt,
136
+ url: env.pageUrl ?? null,
137
+ };
138
+ case 'mention':
139
+ return {
140
+ title: `${env.authorName} mentioned you on ${where}`,
141
+ body: env.excerpt,
142
+ url: env.pageUrl ?? null,
143
+ };
144
+ }
145
+ }
146
+ }
147
+ //# sourceMappingURL=BrowserNotifications.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BrowserNotifications.js","sourceRoot":"","sources":["../../src/notifications/BrowserNotifications.ts"],"names":[],"mappings":"AA2DA,MAAM,OAAO,oBAAoB;IACf,GAAG,CAAW;IACd,KAAK,CAA+B;IAC7C,GAAG,GAAwB,IAAI,CAAC;IAExC,YAAY,IAAiC;QAC5C,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACpB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC9C,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,OAA4B,EAAE;QACnC,IAAI,IAAI,CAAC,GAAG;YAAE,OAAO;QACrB,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,YAAY,KAAK,WAAW,EAAE,CAAC;YAC1E,IAAI,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;YACrE,OAAO;QACR,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,YAAY,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAC1D,IAAI,CAAC,KAAK,CACT,6EAA6E,CAC7E,CAAC;YACF,OAAO;QACR,CAAC;QACD,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,KAAc,EAAE,EAAE;YAC9D,KAAK,IAAI,CAAC,WAAW,CAAC,KAAkC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CACvE,IAAI,CAAC,KAAK,CAAC,oCAAoC,EAAE,GAAG,CAAC,CACrD,CAAC;QACH,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,IAAI;QACH,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QACb,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;IACjB,CAAC;IAED,yCAAyC;IACzC,UAAU;QACT,IAAI,OAAO,YAAY,KAAK,WAAW;YAAE,OAAO,QAAQ,CAAC;QACzD,OAAO,YAAY,CAAC,UAAU,CAAC;IAChC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,iBAAiB;QACtB,IAAI,OAAO,YAAY,KAAK,WAAW;YAAE,OAAO,QAAQ,CAAC;QACzD,IAAI,YAAY,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAC3C,4DAA4D;YAC5D,IAAI,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5B,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,IAAI,YAAY,CAAC,UAAU,KAAK,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC1D,IAAI,CAAC;YACJ,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,iBAAiB,EAAE,CAAC;YACtD,IAAI,MAAM,KAAK,SAAS;gBAAE,IAAI,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACtD,OAAO,MAAM,CAAC;QACf,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,QAAQ,CAAC;QACjB,CAAC;IACF,CAAC;IAED,mEAAmE;IAE3D,KAAK,CAAC,WAAW,CAAC,KAAgC;QACzD,IAAI,YAAY,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAC3C,IAAI,CAAC,KAAK,CAAC,qDAAqD,EAAE,KAAK,CAAC,CAAC;YACzE,OAAO;QACR,CAAC;QACD,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC;QAC3B,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACnD,MAAM,GAAG,GAAG,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC;QACtF,+DAA+D;QAC/D,8DAA8D;QAC9D,8DAA8D;QAC9D,uBAAuB;QACvB,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC,KAAK,EAAE;YAC5C,IAAI;YACJ,GAAG;SACH,CAAC,CAAC;QACH,YAAY,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,EAAE;YAC5B,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,YAAY,CAAC,KAAK,EAAE,CAAC;YACrB,IAAI,CAAC;gBACJ,MAAM,CAAC,KAAK,EAAE,CAAC;YAChB,CAAC;YAAC,MAAM,CAAC;gBACR,kBAAkB;YACnB,CAAC;YACD,IAAI,GAAG,EAAE,CAAC;gBACT,sDAAsD;gBACtD,kDAAkD;gBAClD,IAAI,CAAC;oBACJ,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC7B,CAAC;gBAAC,MAAM,CAAC;oBACR,+BAA+B;gBAChC,CAAC;YACF,CAAC;QACF,CAAC,CAAC;IACH,CAAC;IAEO,WAAW,CAAC,GAA6B;QAKhD,MAAM,KAAK,GAAG,GAAG,CAAC,SAAS,IAAI,QAAQ,CAAC;QACxC,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;YAClB,KAAK,iBAAiB;gBACrB,OAAO;oBACN,KAAK,EAAE,GAAG,GAAG,CAAC,UAAU,iBAAiB,KAAK,EAAE;oBAChD,IAAI,EAAE,GAAG,CAAC,OAAO;oBACjB,GAAG,EAAE,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,SAAS;wBAChC,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,eAAe,GAAG,CAAC,SAAS,EAAE;wBAC9C,CAAC,CAAC,IAAI;iBACP,CAAC;YACH,KAAK,eAAe;gBACnB,OAAO;oBACN,KAAK,EAAE,GAAG,GAAG,CAAC,UAAU,eAAe,KAAK,EAAE;oBAC9C,IAAI,EAAE,GAAG,CAAC,OAAO;oBACjB,GAAG,EAAE,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,eAAe;wBACtC,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,eAAe,GAAG,CAAC,eAAe,EAAE;wBACpD,CAAC,CAAC,IAAI;iBACP,CAAC;YACH,KAAK,cAAc;gBAClB,OAAO;oBACN,KAAK,EAAE,GAAG,GAAG,CAAC,UAAU,iBAAiB;oBACzC,IAAI,EAAE,GAAG,CAAC,OAAO;oBACjB,GAAG,EAAE,GAAG,CAAC,OAAO,IAAI,IAAI;iBACxB,CAAC;YACH,KAAK,SAAS;gBACb,OAAO;oBACN,KAAK,EAAE,GAAG,GAAG,CAAC,UAAU,qBAAqB,KAAK,EAAE;oBACpD,IAAI,EAAE,GAAG,CAAC,OAAO;oBACjB,GAAG,EAAE,GAAG,CAAC,OAAO,IAAI,IAAI;iBACxB,CAAC;QACJ,CAAC;IACF,CAAC;CACD"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @pageloop/preact
3
+ *
4
+ * Preact wrapper. Mirror of @pageloop/react using `preact/hooks` —
5
+ * same provider + hook surface, same render-into-document.body model.
6
+ */
7
+ import { type ComponentChildren, type VNode } from 'preact';
8
+ import { PageLoop, type PageLoopConfig, type UIRenderer } from '@pageloop/client';
9
+ import type { Comment, Reply, Reaction, ReactionTargetKind, TrackedPage, Project, User } from '@pageloop/shared';
10
+ type Role = 'owner' | 'editor' | 'commenter' | 'viewer' | 'anonymous';
11
+ interface PageLoopContextValue {
12
+ instance: PageLoop | null;
13
+ page: TrackedPage | null;
14
+ project: Project | null;
15
+ user: User | null;
16
+ role: Role;
17
+ comments: Comment[];
18
+ connected: boolean;
19
+ }
20
+ export interface PageLoopProviderProps {
21
+ config: PageLoopConfig;
22
+ renderer?: UIRenderer;
23
+ children: ComponentChildren;
24
+ }
25
+ export declare function PageLoopProvider(props: PageLoopProviderProps): VNode;
26
+ export declare function usePageLoop(): PageLoopContextValue;
27
+ export declare function usePageLoopInstance(): PageLoop | null;
28
+ export declare function useComments(): Comment[];
29
+ export declare function usePage(): TrackedPage | null;
30
+ export declare function useProject(): Project | null;
31
+ export declare function useUser(): User | null;
32
+ export declare function useRole(): Role;
33
+ export declare function useConnected(): boolean;
34
+ export declare function useReplies(commentId: string | null): Reply[] | null;
35
+ export declare function useReactions(targetKind: ReactionTargetKind | null, targetId: string | null): Reaction[];
36
+ export {};
37
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/preact/index.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAiB,KAAK,iBAAiB,EAAE,KAAK,KAAK,EAAE,MAAM,QAAQ,CAAC;AAE3E,OAAO,EAAE,QAAQ,EAAE,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAClF,OAAO,KAAK,EACX,OAAO,EACP,KAAK,EACL,QAAQ,EACR,kBAAkB,EAClB,WAAW,EACX,OAAO,EACP,IAAI,EACJ,MAAM,kBAAkB,CAAC;AAE1B,KAAK,IAAI,GAAG,OAAO,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEtE,UAAU,oBAAoB;IAC7B,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;CACnB;AAID,MAAM,WAAW,qBAAqB;IACrC,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,QAAQ,EAAE,iBAAiB,CAAC;CAC5B;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,KAAK,CA6DpE;AAED,wBAAgB,WAAW,IAAI,oBAAoB,CAIlD;AAED,wBAAgB,mBAAmB,IAAI,QAAQ,GAAG,IAAI,CAErD;AACD,wBAAgB,WAAW,IAAI,OAAO,EAAE,CAEvC;AACD,wBAAgB,OAAO,IAAI,WAAW,GAAG,IAAI,CAE5C;AACD,wBAAgB,UAAU,IAAI,OAAO,GAAG,IAAI,CAE3C;AACD,wBAAgB,OAAO,IAAI,IAAI,GAAG,IAAI,CAErC;AACD,wBAAgB,OAAO,IAAI,IAAI,CAE9B;AACD,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,KAAK,EAAE,GAAG,IAAI,CAwBnE;AAED,wBAAgB,YAAY,CAC3B,UAAU,EAAE,kBAAkB,GAAG,IAAI,EACrC,QAAQ,EAAE,MAAM,GAAG,IAAI,GACrB,QAAQ,EAAE,CAgBZ"}
@@ -0,0 +1,150 @@
1
+ import { jsx as _jsx } from "preact/jsx-runtime";
2
+ /**
3
+ * @pageloop/preact
4
+ *
5
+ * Preact wrapper. Mirror of @pageloop/react using `preact/hooks` —
6
+ * same provider + hook surface, same render-into-document.body model.
7
+ */
8
+ import { createContext } from 'preact';
9
+ import { useContext, useEffect, useMemo, useRef, useState } from 'preact/hooks';
10
+ import { PageLoop } from '@pageloop/client';
11
+ const PageLoopContext = createContext(null);
12
+ export function PageLoopProvider(props) {
13
+ const { config, renderer, children } = props;
14
+ const [instance, setInstance] = useState(null);
15
+ const [page, setPage] = useState(null);
16
+ const [project, setProject] = useState(null);
17
+ const [user, setUser] = useState(null);
18
+ const [role, setRole] = useState('anonymous');
19
+ const [comments, setComments] = useState([]);
20
+ const [connected, setConnected] = useState(false);
21
+ const startedRef = useRef(false);
22
+ useEffect(() => {
23
+ if (startedRef.current)
24
+ return;
25
+ startedRef.current = true;
26
+ let ld = null;
27
+ let cleanup = [];
28
+ (async () => {
29
+ const r = renderer ?? (await loadVanilla());
30
+ ld = new PageLoop(config, { renderer: r });
31
+ setInstance(ld);
32
+ const refresh = () => {
33
+ if (!ld)
34
+ return;
35
+ setPage(ld.getCurrentPage());
36
+ setProject(ld.getProject());
37
+ setUser(ld.getCurrentUser());
38
+ setRole(ld.getCurrentRole());
39
+ const p = ld.getCurrentPage();
40
+ setComments(p ? ld.comments.load(p.id) : []);
41
+ };
42
+ cleanup = [
43
+ ld.bus.on('connection:open', () => setConnected(true)),
44
+ ld.bus.on('connection:closed', () => setConnected(false)),
45
+ ld.bus.on('page:change', refresh),
46
+ ld.bus.on('page:resolved', refresh),
47
+ ld.bus.on('auth:changed', refresh),
48
+ ld.bus.on('comment:created', refresh),
49
+ ld.bus.on('comment:updated', refresh),
50
+ ld.bus.on('comment:deleted', refresh),
51
+ ld.bus.on('comment:bulkDeleted', refresh),
52
+ ];
53
+ await ld.start();
54
+ refresh();
55
+ })();
56
+ return () => {
57
+ for (const fn of cleanup)
58
+ fn();
59
+ void ld?.stop();
60
+ };
61
+ // eslint-disable-next-line react-hooks/exhaustive-deps
62
+ }, []);
63
+ const value = useMemo(() => ({ instance, page, project, user, role, comments, connected }), [instance, page, project, user, role, comments, connected]);
64
+ return _jsx(PageLoopContext.Provider, { value: value, children: children });
65
+ }
66
+ export function usePageLoop() {
67
+ const ctx = useContext(PageLoopContext);
68
+ if (!ctx)
69
+ throw new Error('usePageLoop must be called inside <PageLoopProvider>');
70
+ return ctx;
71
+ }
72
+ export function usePageLoopInstance() {
73
+ return usePageLoop().instance;
74
+ }
75
+ export function useComments() {
76
+ return usePageLoop().comments;
77
+ }
78
+ export function usePage() {
79
+ return usePageLoop().page;
80
+ }
81
+ export function useProject() {
82
+ return usePageLoop().project;
83
+ }
84
+ export function useUser() {
85
+ return usePageLoop().user;
86
+ }
87
+ export function useRole() {
88
+ return usePageLoop().role;
89
+ }
90
+ export function useConnected() {
91
+ return usePageLoop().connected;
92
+ }
93
+ export function useReplies(commentId) {
94
+ const ctx = usePageLoop();
95
+ const [list, setList] = useState(null);
96
+ useEffect(() => {
97
+ if (!ctx.instance || !commentId)
98
+ return;
99
+ const ld = ctx.instance;
100
+ const sync = () => setList(ld.comments.loadedReplies(commentId));
101
+ sync();
102
+ if (ld.comments.loadedReplies(commentId) === null) {
103
+ void ld.comments
104
+ .fetchReplies(commentId)
105
+ .then(sync)
106
+ .catch(() => undefined);
107
+ }
108
+ const offs = [
109
+ ld.bus.on('reply:created', sync),
110
+ ld.bus.on('reply:updated', sync),
111
+ ld.bus.on('reply:deleted', sync),
112
+ ];
113
+ return () => {
114
+ for (const fn of offs)
115
+ fn();
116
+ };
117
+ }, [ctx.instance, commentId]);
118
+ return list;
119
+ }
120
+ export function useReactions(targetKind, targetId) {
121
+ const ctx = usePageLoop();
122
+ const [list, setList] = useState([]);
123
+ useEffect(() => {
124
+ if (!ctx.instance || !targetKind || !targetId)
125
+ return;
126
+ const ld = ctx.instance;
127
+ const sync = () => setList(ld.comments.loadedReactions(targetKind, targetId));
128
+ sync();
129
+ void ld.comments
130
+ .fetchReactions(targetKind, targetId)
131
+ .then(sync)
132
+ .catch(() => undefined);
133
+ const off = ld.bus.on('reaction:changed', sync);
134
+ return () => off();
135
+ }, [ctx.instance, targetKind, targetId]);
136
+ return list;
137
+ }
138
+ async function loadVanilla() {
139
+ // @pageloop/vanilla is an optional runtime peer (lazy-loaded), deliberately
140
+ // NOT a build dependency of @pageloop/client — declaring it would create a
141
+ // vanilla↔client build cycle (vanilla depends on the client core). The
142
+ // `as string` keeps tsc from resolving a non-dependency at build time; the
143
+ // assertion is erased in the emitted JS, so the literal survives and a
144
+ // consumer's bundler still code-splits @pageloop/vanilla. Consumers of this
145
+ // subpath install @pageloop/vanilla themselves.
146
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
147
+ const mod = await import('@pageloop/vanilla');
148
+ return new mod.VanillaRenderer();
149
+ }
150
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/preact/index.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Re-export of the vanilla renderer's stylesheet. Consumers of
3
+ * `@pageloop/preact` who use the default renderer get the styles by
4
+ * importing this file instead of reaching directly into
5
+ * `@pageloop/vanilla` — keeps the consumer's package.json to a
6
+ * single `@pageloop/preact` dep without phantom-dependency errors
7
+ * under pnpm's strict resolution.
8
+ *
9
+ * Consumers who ship a custom renderer don't import this file and
10
+ * don't pay the CSS cost.
11
+ */
12
+ @import '@pageloop/vanilla/style.css';
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @pageloop/react
3
+ *
4
+ * React wrapper. <PageLoopProvider> mounts the SDK with the vanilla DOM
5
+ * renderer (or one you pass); hooks expose the running instance + every
6
+ * piece of state the bus broadcasts. The renderer paints into
7
+ * `document.body` directly — these hooks are for app code that wants
8
+ * to read/mutate comments alongside the floating UI, not replace it.
9
+ */
10
+ import { type ReactNode, type ReactElement } from 'react';
11
+ import { PageLoop, type PageLoopConfig, type UIRenderer } from '@pageloop/client';
12
+ import type { Comment, Reply, Reaction, ReactionTargetKind, TrackedPage, Project, User } from '@pageloop/shared';
13
+ type Role = 'owner' | 'editor' | 'commenter' | 'viewer' | 'anonymous';
14
+ interface PageLoopContextValue {
15
+ instance: PageLoop | null;
16
+ page: TrackedPage | null;
17
+ project: Project | null;
18
+ user: User | null;
19
+ role: Role;
20
+ comments: Comment[];
21
+ connected: boolean;
22
+ }
23
+ export interface PageLoopProviderProps {
24
+ config: PageLoopConfig;
25
+ /** Defaults to the vanilla DOM renderer (loaded lazily). */
26
+ renderer?: UIRenderer;
27
+ children: ReactNode;
28
+ }
29
+ export declare function PageLoopProvider(props: PageLoopProviderProps): ReactElement;
30
+ /** Throws if called outside the provider. */
31
+ export declare function usePageLoop(): PageLoopContextValue;
32
+ /** Direct access to the running PageLoop instance (for imperative calls). */
33
+ export declare function usePageLoopInstance(): PageLoop | null;
34
+ export declare function useComments(): Comment[];
35
+ export declare function usePage(): TrackedPage | null;
36
+ export declare function useProject(): Project | null;
37
+ export declare function useUser(): User | null;
38
+ export declare function useRole(): Role;
39
+ export declare function useConnected(): boolean;
40
+ /**
41
+ * Reactive replies for a comment. Subscribes to reply:* events so when a
42
+ * reply is added/edited/deleted the value updates. Returns null until
43
+ * the first `fetchReplies` call resolves; re-uses the engine's cache.
44
+ */
45
+ export declare function useReplies(commentId: string | null): Reply[] | null;
46
+ /**
47
+ * Reactive reactions for a comment OR reply. Subscribes to `reaction:changed`
48
+ * and re-fetches when the targetKind/targetId pair changes.
49
+ */
50
+ export declare function useReactions(targetKind: ReactionTargetKind | null, targetId: string | null): Reaction[];
51
+ export {};
52
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAON,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,QAAQ,EAAE,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAClF,OAAO,KAAK,EACX,OAAO,EACP,KAAK,EACL,QAAQ,EACR,kBAAkB,EAClB,WAAW,EACX,OAAO,EACP,IAAI,EACJ,MAAM,kBAAkB,CAAC;AAE1B,KAAK,IAAI,GAAG,OAAO,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEtE,UAAU,oBAAoB;IAC7B,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;CACnB;AAID,MAAM,WAAW,qBAAqB;IACrC,MAAM,EAAE,cAAc,CAAC;IACvB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,QAAQ,EAAE,SAAS,CAAC;CACpB;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,YAAY,CA+D3E;AAED,6CAA6C;AAC7C,wBAAgB,WAAW,IAAI,oBAAoB,CAIlD;AAED,6EAA6E;AAC7E,wBAAgB,mBAAmB,IAAI,QAAQ,GAAG,IAAI,CAErD;AACD,wBAAgB,WAAW,IAAI,OAAO,EAAE,CAEvC;AACD,wBAAgB,OAAO,IAAI,WAAW,GAAG,IAAI,CAE5C;AACD,wBAAgB,UAAU,IAAI,OAAO,GAAG,IAAI,CAE3C;AACD,wBAAgB,OAAO,IAAI,IAAI,GAAG,IAAI,CAErC;AACD,wBAAgB,OAAO,IAAI,IAAI,CAE9B;AACD,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,KAAK,EAAE,GAAG,IAAI,CAwBnE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC3B,UAAU,EAAE,kBAAkB,GAAG,IAAI,EACrC,QAAQ,EAAE,MAAM,GAAG,IAAI,GACrB,QAAQ,EAAE,CAgBZ"}