@backmatter/next 0.0.32 → 0.0.34

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backmatter/next",
3
- "version": "0.0.32",
3
+ "version": "0.0.34",
4
4
  "description": "Experimental Next.js adapter for Backmatter. APIs will break. Not ready for production.",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -50,7 +50,7 @@
50
50
  "@backmatter/core": "^0.0.26",
51
51
  "@mdx-js/mdx": "^3.1.1",
52
52
  "remark-gfm": "^4.0.1",
53
- "@backmatter/studio": "^0.0.9"
53
+ "@backmatter/studio": "^0.0.12"
54
54
  },
55
55
  "peerDependencies": {
56
56
  "next": ">=16.3.0",
@@ -8,9 +8,14 @@ import {
8
8
  createPreviewPage,
9
9
  createWindowPreviewTransport,
10
10
  type PreviewChannelRef,
11
+ type PreviewPageSession,
11
12
  type PreviewRenderDoc,
12
13
  type PreviewTransport,
13
14
  } from "@backmatter/core/preview";
15
+ import { POINTER_ARM_EVENT } from "@backmatter/studio/src/chat/pointer-arm";
16
+ import { installPreviewPointer } from "@backmatter/studio/src/install-preview-pointer";
17
+ import { registerPreviewPointerHost } from "@backmatter/studio/src/preview-pointer-host";
18
+ import { findPointedElement, highlightPointedElement } from "@backmatter/studio/src/site-pointer";
14
19
  import { fanInPreviewTransports, sitePageTransport } from "./site-channel";
15
20
  import { PreviewPageReloader as PreviewStreamReloader, PreviewRemoved } from "./preview-live";
16
21
 
@@ -22,6 +27,12 @@ export function PreviewPageReloader(props: { locale: string; type: string; slug:
22
27
  router.refresh();
23
28
  });
24
29
  }, [router]);
30
+ // HEAD and other documents in this checkout. This document's own saves
31
+ // arrive on the doc stream below and must not refresh the page twice.
32
+ useEffect(
33
+ () => subscribeTreeStream({ locale: props.locale, type: props.type, slug: props.slug }, refresh),
34
+ [props.locale, props.type, props.slug, refresh],
35
+ );
25
36
  return <PreviewStreamReloader {...props} refresh={refresh} />;
26
37
  }
27
38
 
@@ -183,9 +194,27 @@ export function PreviewClient({
183
194
  startTransition(() => router.refresh());
184
195
  };
185
196
  const unsubscribeTree = subscribeTreeStream(ref, refreshOthers);
186
- const session = createPreviewPage({
197
+ let session: PreviewPageSession;
198
+ const previewPointer = installPreviewPointer(document, {
199
+ bar: () => document.querySelector("[data-backmatter-devbar]"),
200
+ ignore: (target) => {
201
+ if (!(target instanceof Element)) return true;
202
+ if (target.closest("[data-backmatter-panel]")) return true;
203
+ return target.closest("iframe") !== null;
204
+ },
205
+ onEditorGrab: (grab) => session.grab(grab),
206
+ onDevbarGrab: (grab) => {
207
+ window.dispatchEvent(new CustomEvent("backmatter:devbar-grab", { detail: grab }));
208
+ },
209
+ onEscape: (source) => {
210
+ if (source === "editor") session.point(false);
211
+ window.dispatchEvent(new CustomEvent(POINTER_ARM_EVENT, { detail: { on: false } }));
212
+ },
213
+ });
214
+ session = createPreviewPage({
187
215
  ref,
188
216
  transport,
217
+ capabilities: ["point"],
189
218
  subscribeSse: (onEvent) => subscribeDocStream(ref, onEvent),
190
219
  renderer: async (_ref, doc) => {
191
220
  const result = await renderPreview(ref, doc, checkoutToken);
@@ -206,10 +235,34 @@ export function PreviewClient({
206
235
  onNavigate: (path) => {
207
236
  startTransition(() => router.push(path));
208
237
  },
238
+ onPoint(on) {
239
+ if (on) {
240
+ previewPointer.arm("editor");
241
+ window.dispatchEvent(new CustomEvent(POINTER_ARM_EVENT, { detail: { on: false } }));
242
+ return;
243
+ }
244
+ if (previewPointer.source() === "editor") previewPointer.disarm();
245
+ },
246
+ onHighlight(blockId) {
247
+ const target = blockId ? findPointedElement(document, { blockId, quote: "" }) : null;
248
+ highlightPointedElement(document, target);
249
+ },
250
+ },
251
+ });
252
+ const stopHost = registerPreviewPointerHost({
253
+ armFromDevbar() {
254
+ previewPointer.arm("devbar");
255
+ session.point(false);
256
+ },
257
+ disarmFromDevbar() {
258
+ if (previewPointer.source() !== "devbar") return;
259
+ previewPointer.disarm();
209
260
  },
210
261
  });
211
262
  return () => {
212
263
  unsubscribeTree();
264
+ stopHost();
265
+ previewPointer.dispose();
213
266
  session.close();
214
267
  windowTransport?.close();
215
268
  };