@backmatter/studio 0.0.1 → 0.0.3

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.
@@ -3,7 +3,7 @@ var Ze = (e, t, n) => t in e ? Qe(e, t, { enumerable: !0, configurable: !0, writ
3
3
  var D = (e, t, n) => Ze(e, typeof t != "symbol" ? t + "" : t, n);
4
4
  import { jsxs as R, jsx as o, Fragment as be } from "react/jsx-runtime";
5
5
  import { useRef as et, useCallback as tt, useSyncExternalStore as nt, useState as E, useEffect as J, Suspense as we, lazy as rt } from "react";
6
- import { _ as st, $ as Ce, a0 as it, T as O, a1 as at, p as ot, a2 as lt, a3 as Ie, a4 as qe, a5 as Fe, a6 as ct, a7 as ut, W as ze, a8 as dt, a9 as ae, e as V, b as Be, aa as ft, ab as Me, B as ht, S as se, F as Z, I as ee, a as ye, ac as pt, Z as z, ad as gt, M as ve, ae as te, P as mt, af as xt, ag as yt, o as vt, ah as bt, ai as wt, aj as St, A as kt, G as Et, ak as De, L as Rt, al as _t, am as Ot, an as Tt, N as Pt, R as Lt, O as Ut, Q as Nt, U as jt, V as q, X as At, Y as Ct } from "./WorkspaceRoutes-DgRtdie8.js";
6
+ import { _ as st, $ as Ce, a0 as it, T as O, a1 as at, p as ot, a2 as lt, a3 as Ie, a4 as qe, a5 as Fe, a6 as ct, a7 as ut, W as ze, a8 as dt, a9 as ae, e as V, b as Be, aa as ft, ab as Me, B as ht, S as se, F as Z, I as ee, a as ye, ac as pt, Z as z, ad as gt, M as ve, ae as te, P as mt, af as xt, ag as yt, o as vt, ah as bt, ai as wt, aj as St, A as kt, G as Et, ak as De, L as Rt, al as _t, am as Ot, an as Tt, N as Pt, R as Lt, O as Ut, Q as Nt, U as jt, V as q, X as At, Y as Ct } from "./WorkspaceRoutes-DyRVES9t.js";
7
7
  const ne = /* @__PURE__ */ Object.create(null), W = (e) => {
8
8
  var t, n;
9
9
  return ((t = globalThis.process) == null ? void 0 : t.env) || ((n = globalThis.Deno) == null ? void 0 : n.env.toObject()) || globalThis.__env__ || (e ? ne : globalThis);
@@ -1676,7 +1676,7 @@ function vr({
1676
1676
  /* @__PURE__ */ o(Be, { to: "/", variant: "secondary", children: "Back to the dashboard" })
1677
1677
  ] }) }) });
1678
1678
  }
1679
- const Q = De() ? rt(() => import("./UiKitPage-CgNMOqfE.js").then((e) => ({
1679
+ const Q = De() ? rt(() => import("./UiKitPage-CTZtLwJ0.js").then((e) => ({
1680
1680
  default: e.UiKitPage
1681
1681
  }))) : null;
1682
1682
  function br(e) {
@@ -1,7 +1,7 @@
1
1
  var Rs = Object.defineProperty;
2
2
  var Es = (r, e, t) => e in r ? Rs(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t;
3
3
  var M = (r, e, t) => Es(r, typeof e != "symbol" ? e + "" : e, t);
4
- import { ao as Bt, ap as Bs, aq as a0, ar as ct, as as xt, at as ea, au as Gn, av as Is, aw as Ls, ax as Ds, ay as La, az as Ps, aA as Os, aB as Le, aC as qs } from "./WorkspaceRoutes-DgRtdie8.js";
4
+ import { ao as Bt, ap as Bs, aq as a0, ar as ct, as as xt, at as ea, au as Gn, av as Is, aw as Ls, ax as Ds, ay as La, az as Ps, aA as Os, aB as Le, aC as qs } from "./WorkspaceRoutes-DyRVES9t.js";
5
5
  function Fs() {
6
6
  return {
7
7
  enter: {
package/dist/dashboard.js CHANGED
@@ -1,5 +1,5 @@
1
- import { A as a, i as s } from "./chunks/dashboard-XKKZuJGm.js";
2
- import { J as t, K as f } from "./chunks/WorkspaceRoutes-DgRtdie8.js";
1
+ import { A as a, i as s } from "./chunks/dashboard-nvFBzpZv.js";
2
+ import { J as t, K as f } from "./chunks/WorkspaceRoutes-DyRVES9t.js";
3
3
  export {
4
4
  a as DashboardApp,
5
5
  t as configureStudio,
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { jsx as n, jsxs as g } from "react/jsx-runtime";
2
- import { useLayoutEffect as Y, useEffect as p, useRef as J, useState as v, useMemo as Q } from "react";
3
- import { i as B, h as X, E as Z, C as ee, j as te, k as ne, l as ie, D as M, m as re, n as _, o as G, q as $, r as oe, T as b, a as C, I as se, s as S, t as ae, v as ce, w as le, x as ue, y as de, z as fe, A as me, G as he, H as ge, J as j, K as P, L as pe, M as ve, N as we, R as be, O as ye, Q as xe, U as ke, V as R, W as D, X as Ee, Y as Ce, Z as Se } from "./chunks/WorkspaceRoutes-DgRtdie8.js";
4
- import { _ as We } from "./chunks/WorkspaceRoutes-DgRtdie8.js";
1
+ import { jsx as n, jsxs as p } from "react/jsx-runtime";
2
+ import { useLayoutEffect as Y, useEffect as g, useRef as J, useState as w, useMemo as Q } from "react";
3
+ import { i as B, h as X, E as Z, C as ee, j as te, k as ne, l as ie, D as M, m as oe, n as _, o as G, q as $, r as re, T as b, a as C, I as se, s as S, t as ae, v as ce, w as le, x as ue, y as de, z as fe, A as me, G as he, H as pe, J as j, K as P, L as ge, M as we, N as ve, R as be, O as ye, Q as xe, U as ke, V as R, W as D, X as Ee, Y as Ce, Z as Se } from "./chunks/WorkspaceRoutes-DyRVES9t.js";
4
+ import { _ as We } from "./chunks/WorkspaceRoutes-DyRVES9t.js";
5
5
  import { u as Re, S as ze } from "./chunks/define-studio-BYtYDGLX.js";
6
6
  import { d as Je } from "./chunks/define-studio-BYtYDGLX.js";
7
7
  const z = {
@@ -15,19 +15,19 @@ function Pe(e) {
15
15
  }
16
16
  const Ue = [z.accent, z.accentHover, z.focus];
17
17
  function Ne() {
18
- var t, o;
19
- const e = (o = (t = Re().theme) == null ? void 0 : t.accent) == null ? void 0 : o.trim();
18
+ var t, r;
19
+ const e = (r = (t = Re().theme) == null ? void 0 : t.accent) == null ? void 0 : r.trim();
20
20
  return Y(() => {
21
21
  if (!e) return;
22
- const a = document.documentElement, s = Ue.map(Pe).filter((r) => !!r);
23
- for (const r of s) a.style.setProperty(r, e);
22
+ const a = document.documentElement, s = Ue.map(Pe).filter((o) => !!o);
23
+ for (const o of s) a.style.setProperty(o, e);
24
24
  return () => {
25
- for (const r of s) a.style.removeProperty(r);
25
+ for (const o of s) a.style.removeProperty(o);
26
26
  };
27
27
  }, [e]), null;
28
28
  }
29
29
  function Le({ workspaceId: e }) {
30
- return p(() => B(), []), /* @__PURE__ */ n(X, { children: /* @__PURE__ */ n(Z, { children: /* @__PURE__ */ n(ee, { workspaceId: e, startOpen: !0, children: /* @__PURE__ */ g(te, { children: [
30
+ return g(() => B(), []), /* @__PURE__ */ n(X, { children: /* @__PURE__ */ n(Z, { children: /* @__PURE__ */ n(ee, { workspaceId: e, startOpen: !0, children: /* @__PURE__ */ p(te, { children: [
31
31
  /* @__PURE__ */ n(Te, {}),
32
32
  /* @__PURE__ */ n(Me, {}),
33
33
  /* @__PURE__ */ n(ne, { fill: !0 })
@@ -43,46 +43,46 @@ function k() {
43
43
  }
44
44
  function Te() {
45
45
  const { setFocus: e } = ie();
46
- return p(() => {
46
+ return g(() => {
47
47
  const t = k();
48
- function o(a) {
48
+ function r(a) {
49
49
  if (!t || a.origin !== t) return;
50
50
  const s = a.data;
51
51
  if ((s == null ? void 0 : s.type) !== "backmatter:focus") return;
52
- const r = s.doc;
53
- !(r != null && r.locale) || !r.type || !r.slug || e({
54
- docRef: { locale: r.locale, type: r.type, slug: r.slug },
52
+ const o = s.doc;
53
+ !(o != null && o.locale) || !o.type || !o.slug || e({
54
+ docRef: { locale: o.locale, type: o.type, slug: o.slug },
55
55
  frontmatter: {},
56
56
  body: "",
57
57
  selection: null
58
58
  });
59
59
  }
60
- return window.addEventListener("message", o), t && window.parent.postMessage({ type: "backmatter:chat-ready" }, t), () => window.removeEventListener("message", o);
61
- }, [e]), p(() => {
60
+ return window.addEventListener("message", r), t && window.parent.postMessage({ type: "backmatter:chat-ready" }, t), () => window.removeEventListener("message", r);
61
+ }, [e]), g(() => {
62
62
  const t = k();
63
- function o(a) {
63
+ function r(a) {
64
64
  const s = a.detail;
65
65
  !t || !(s != null && s.docRef) || window.parent.postMessage({ type: "backmatter:doc-changed", doc: s.docRef }, t);
66
66
  }
67
- return window.addEventListener(M, o), () => window.removeEventListener(M, o);
67
+ return window.addEventListener(M, r), () => window.removeEventListener(M, r);
68
68
  }, []), null;
69
69
  }
70
70
  function Me() {
71
- const { panel: e, dispatch: t } = re(), o = e.mode, a = J(o);
72
- return p(() => {
71
+ const { panel: e, dispatch: t } = oe(), r = e.mode, a = J(r);
72
+ return g(() => {
73
73
  const s = k();
74
74
  if (!s || window.parent === window) return;
75
- const r = _(a.current);
76
- a.current = o, r && !_(o) && window.parent.postMessage({ type: "backmatter:chat-closed" }, s);
77
- }, [o]), p(() => {
75
+ const o = _(a.current);
76
+ a.current = r, o && !_(r) && window.parent.postMessage({ type: "backmatter:chat-closed" }, s);
77
+ }, [r]), g(() => {
78
78
  const s = k();
79
- function r(d) {
79
+ function o(d) {
80
80
  var f;
81
81
  !s || d.origin !== s || ((f = d.data) == null ? void 0 : f.type) === "backmatter:chat-open" && (t({ type: "open" }), requestAnimationFrame(() => {
82
82
  window.dispatchEvent(new Event("backmatter:chat-focus"));
83
83
  }));
84
84
  }
85
- return window.addEventListener("message", r), () => window.removeEventListener("message", r);
85
+ return window.addEventListener("message", o), () => window.removeEventListener("message", o);
86
86
  }, [t]), null;
87
87
  }
88
88
  const _e = 8e3;
@@ -105,9 +105,9 @@ function q(e) {
105
105
  function De({
106
106
  workspaceId: e
107
107
  }) {
108
- p(() => B(), []);
109
- const [t, o] = v(null), [a, s] = v("viewer"), [r, d] = v(""), [f, m] = v(null), [c, y] = v(!1), [U, N] = v(null);
110
- p(() => {
108
+ g(() => B(), []);
109
+ const [t, r] = w(null), [a, s] = w("viewer"), [o, d] = w(""), [f, m] = w(null), [c, y] = w(!1), [U, N] = w(null);
110
+ g(() => {
111
111
  let i = !1;
112
112
  return G(e).then((l) => {
113
113
  i || s(l.workspace.role);
@@ -116,12 +116,12 @@ function De({
116
116
  }), () => {
117
117
  i = !0;
118
118
  };
119
- }, [e]), p(() => {
119
+ }, [e]), g(() => {
120
120
  let i = !1;
121
121
  const l = () => {
122
122
  S(e).then((u) => {
123
123
  if (i) return;
124
- o(u);
124
+ r(u);
125
125
  const T = O();
126
126
  T && window.parent.postMessage({
127
127
  type: "backmatter:git",
@@ -133,15 +133,15 @@ function De({
133
133
  });
134
134
  };
135
135
  l();
136
- const w = window.setInterval(l, _e);
136
+ const v = window.setInterval(l, _e);
137
137
  return () => {
138
- i = !0, window.clearInterval(w);
138
+ i = !0, window.clearInterval(v);
139
139
  };
140
140
  }, [e]);
141
- const h = (t == null ? void 0 : t.changes) ?? [], x = $(t), E = ae(x, fe(a)), V = Q(() => h.filter((i) => i.status === "conflict"), [h]), F = oe(h);
141
+ const h = (t == null ? void 0 : t.changes) ?? [], x = $(t), E = ae(x, fe(a)), V = Q(() => h.filter((i) => i.status === "conflict"), [h]), F = re(h);
142
142
  async function L(i, l) {
143
- const w = `${q(i)}:${l}`;
144
- N(w), m(null);
143
+ const v = `${q(i)}:${l}`;
144
+ N(v), m(null);
145
145
  try {
146
146
  await ce(e, i.locale, i.type, i.slug, l), le({
147
147
  workspaceId: e,
@@ -151,7 +151,7 @@ function De({
151
151
  status: l === "theirs" ? "clean" : "modified"
152
152
  });
153
153
  const u = await S(e);
154
- o(u);
154
+ r(u);
155
155
  } catch (u) {
156
156
  m(u instanceof Error ? u.message : "Resolve failed");
157
157
  } finally {
@@ -162,12 +162,12 @@ function De({
162
162
  if (i.preventDefault(), !(c || E !== "commit" || h.length === 0)) {
163
163
  y(!0), m(null);
164
164
  try {
165
- const l = await ue(e, r);
165
+ const l = await ue(e, o);
166
166
  d(""), de(e, l.files);
167
- const w = O();
168
- w && window.parent.postMessage({
167
+ const v = O();
168
+ v && window.parent.postMessage({
169
169
  type: "backmatter:published"
170
- }, w), o(await S(e));
170
+ }, v), r(await S(e));
171
171
  } catch (l) {
172
172
  m($e(l));
173
173
  } finally {
@@ -176,22 +176,22 @@ function De({
176
176
  }
177
177
  }
178
178
  const W = c ? "Committing…" : x > 0 ? `Resolve ${x} ${x === 1 ? "conflict" : "conflicts"}` : E === "blocked" ? "Writers cannot publish" : h.length === 0 ? "Nothing to publish" : `Deploy ${h.length} ${h.length === 1 ? "change" : "changes"}`;
179
- return /* @__PURE__ */ g("form", { className: "x78zum5 xdt5ytf x11cgr9k x1us19tq x9f619 x1t7e3gq x1hb2obb xqjzbou x1vrk1b5", onSubmit: (i) => void H(i), children: [
179
+ return /* @__PURE__ */ p("form", { className: "x78zum5 xdt5ytf x11cgr9k x1us19tq x9f619 x1t7e3gq x1hb2obb xqjzbou x1vrk1b5", onSubmit: (i) => void H(i), children: [
180
180
  /* @__PURE__ */ n(b, { as: "p", size: "sm", weight: "medium", tone: "muted", children: (t == null ? void 0 : t.currentBranch) ?? "Publish" }),
181
- h.length === 0 ? /* @__PURE__ */ n(b, { as: "p", size: "sm", tone: "muted", children: "Nothing to publish" }) : /* @__PURE__ */ n("ul", { className: "x1ghz6dp x1717udv xe8uvvx x78zum5 xdt5ytf x1ndbd79", children: h.map((i) => /* @__PURE__ */ g("li", { className: "x78zum5 xdt5ytf x3smv4v", children: [
182
- /* @__PURE__ */ g("span", { children: [
181
+ h.length === 0 ? /* @__PURE__ */ n(b, { as: "p", size: "sm", tone: "muted", children: "Nothing to publish" }) : /* @__PURE__ */ n("ul", { className: "x1ghz6dp x1717udv xe8uvvx x78zum5 xdt5ytf x1ndbd79", children: h.map((i) => /* @__PURE__ */ p("li", { className: "x78zum5 xdt5ytf x3smv4v", children: [
182
+ /* @__PURE__ */ p("span", { children: [
183
183
  i.status,
184
184
  " ",
185
185
  i.type,
186
186
  "/",
187
187
  i.slug
188
188
  ] }),
189
- i.status === "conflict" ? /* @__PURE__ */ g("span", { className: "x78zum5 x3smv4v", children: [
189
+ i.status === "conflict" ? /* @__PURE__ */ p("span", { className: "x78zum5 x3smv4v", children: [
190
190
  /* @__PURE__ */ n(C, { size: "sm", variant: "secondary", disabled: U !== null, onClick: () => void L(i, "mine"), children: "Keep mine" }),
191
191
  /* @__PURE__ */ n(C, { size: "sm", variant: "secondary", disabled: U !== null, onClick: () => void L(i, "theirs"), children: "Take theirs" })
192
192
  ] }) : null
193
193
  ] }, q(i))) }),
194
- V.length > 0 ? null : /* @__PURE__ */ n(se, { value: r, placeholder: F, "aria-label": "Commit message", onChange: (i) => d(i.target.value) }),
194
+ V.length > 0 ? null : /* @__PURE__ */ n(se, { value: o, placeholder: F, "aria-label": "Commit message", onChange: (i) => d(i.target.value) }),
195
195
  f ? /* @__PURE__ */ n(b, { as: "p", size: "sm", tone: "danger", children: f }) : null,
196
196
  /* @__PURE__ */ n(C, { type: "submit", size: "sm", disabled: c || E !== "commit" || h.length === 0, children: W })
197
197
  ] });
@@ -199,11 +199,14 @@ function De({
199
199
  const I = "backmatter:enter-at", Oe = 1e4;
200
200
  function K(e, t) {
201
201
  if (typeof window > "u") return !1;
202
- const o = Number(window.sessionStorage.getItem(I) ?? 0);
203
- return Date.now() - o < Oe ? !1 : (window.sessionStorage.setItem(I, String(Date.now())), window.location.assign(ge(t, {
202
+ const r = Number(window.sessionStorage.getItem(I) ?? 0);
203
+ if (Date.now() - r < Oe) return !1;
204
+ window.sessionStorage.setItem(I, String(Date.now()));
205
+ const a = window.top && window.top !== window ? window.top : window;
206
+ return a.location.assign(pe(t, {
204
207
  workspaceId: e,
205
- returnUrl: window.location.href
206
- })), !0);
208
+ returnUrl: a.location.href
209
+ })), !0;
207
210
  }
208
211
  function qe(e) {
209
212
  const t = e.dashboardUrl ?? "https://dash.backmatter.app";
@@ -215,22 +218,22 @@ function qe(e) {
215
218
  version: e.version,
216
219
  dashboardUrl: t,
217
220
  onUnauthorized: ({
218
- status: o
221
+ status: r
219
222
  }) => {
220
- o === 401 && K(e.workspaceId, t);
223
+ r === 401 && K(e.workspaceId, t);
221
224
  }
222
225
  }), P();
223
226
  }
224
227
  function Ve(e) {
225
- const t = e.basePath ?? "/backmatter", [o] = v(() => qe(e));
226
- return /* @__PURE__ */ n(ze, { definition: e.studio, children: /* @__PURE__ */ g(me, { children: [
228
+ const t = e.basePath ?? "/backmatter", [r] = w(() => qe(e));
229
+ return /* @__PURE__ */ n(ze, { definition: e.studio, children: /* @__PURE__ */ p(me, { children: [
227
230
  /* @__PURE__ */ n(Ne, {}),
228
231
  /* @__PURE__ */ n(he, { basename: t, children: /* @__PURE__ */ n(Ie, { ...e }) })
229
232
  ] }) });
230
233
  }
231
234
  function Ie(e) {
232
- const t = pe(), o = e.dashboardUrl ?? "https://dash.backmatter.app", [a, s] = v("loading");
233
- if (p(() => {
235
+ const t = ge(), r = e.dashboardUrl ?? "https://dash.backmatter.app", [a, s] = w("loading");
236
+ if (g(() => {
234
237
  let f = !1;
235
238
  const m = P().onUnauthorized;
236
239
  return j({
@@ -238,10 +241,10 @@ function Ie(e) {
238
241
  onUnauthorized: (c) => {
239
242
  c.status === 426 ? s("outdated") : m == null || m(c);
240
243
  }
241
- }), ve().then(async (c) => {
244
+ }), we().then(async (c) => {
242
245
  if (f) return;
243
246
  if (!(c != null && c.user)) {
244
- K(e.workspaceId, o) || s("unauthorized");
247
+ K(e.workspaceId, r) || s("unauthorized");
245
248
  return;
246
249
  }
247
250
  const {
@@ -259,9 +262,9 @@ function Ie(e) {
259
262
  }), () => {
260
263
  f = !0;
261
264
  };
262
- }, [e.workspaceId, o]), a === "loading") return /* @__PURE__ */ n(we, {});
265
+ }, [e.workspaceId, r]), a === "loading") return /* @__PURE__ */ n(ve, {});
263
266
  if (a === "outdated")
264
- return /* @__PURE__ */ g(A, { title: "This site's editor is out of date", children: [
267
+ return /* @__PURE__ */ p(A, { title: "This site's editor is out of date", children: [
265
268
  "Update ",
266
269
  /* @__PURE__ */ n("code", { children: "@backmatter/studio" }),
267
270
  " and ",
@@ -269,18 +272,18 @@ function Ie(e) {
269
272
  " on the site, then reload."
270
273
  ] });
271
274
  if (a === "unauthorized")
272
- return /* @__PURE__ */ g(A, { title: "Could not start editing", children: [
275
+ return /* @__PURE__ */ p(A, { title: "Could not start editing", children: [
273
276
  "The site did not receive a session from the dashboard. Check that this site's origin is listed in the workspace settings and that ",
274
277
  /* @__PURE__ */ n("code", { children: "/api/backmatter" }),
275
278
  " routes are deployed."
276
279
  ] });
277
- const r = t.pathname.match(/^\/embed\/chat\/([^/]+)\/?$/);
278
- if (r != null && r[1])
279
- return /* @__PURE__ */ n(Le, { workspaceId: decodeURIComponent(r[1]) });
280
+ const o = t.pathname.match(/^\/embed\/chat\/([^/]+)\/?$/);
281
+ if (o != null && o[1])
282
+ return /* @__PURE__ */ n(Le, { workspaceId: decodeURIComponent(o[1]) });
280
283
  const d = t.pathname.match(/^\/embed\/publish\/([^/]+)\/?$/);
281
284
  return d != null && d[1] ? /* @__PURE__ */ n(De, { workspaceId: decodeURIComponent(d[1]) }) : /* @__PURE__ */ n(be, { user: a.user, children: /* @__PURE__ */ n(ye, { children: /* @__PURE__ */ n(xe, { userId: a.user.id, email: a.user.email, onLogout: () => {
282
- Ae(e.previewEntryPath ?? "/api/backmatter/preview", o);
283
- }, children: /* @__PURE__ */ g(ke, { children: [
285
+ Ae(e.previewEntryPath ?? "/api/backmatter/preview", r);
286
+ }, children: /* @__PURE__ */ p(ke, { children: [
284
287
  /* @__PURE__ */ n(R, { path: "/", element: /* @__PURE__ */ n(D, { to: `/${a.slug}`, replace: !0 }) }),
285
288
  /* @__PURE__ */ n(R, { path: "/workspaces/:workspaceId/*", element: /* @__PURE__ */ n(Ee, {}) }),
286
289
  Ce(),
@@ -301,7 +304,7 @@ function A({
301
304
  title: e,
302
305
  children: t
303
306
  }) {
304
- return /* @__PURE__ */ n("div", { className: "x1ov3xa9 xrvj5dj x1ku5rj1 x1t7e3gq", children: /* @__PURE__ */ g("div", { className: "x78zum5 xdt5ytf x1ndbd79 xq2pcee x1t7e3gq x4pepcl x1d0qn7y", children: [
307
+ return /* @__PURE__ */ n("div", { className: "x1ov3xa9 xrvj5dj x1ku5rj1 x1t7e3gq", children: /* @__PURE__ */ p("div", { className: "x78zum5 xdt5ytf x1ndbd79 xq2pcee x1t7e3gq x4pepcl x1d0qn7y", children: [
305
308
  /* @__PURE__ */ n(b, { size: "lg", weight: "medium", children: e }),
306
309
  /* @__PURE__ */ n(b, { tone: "muted", children: t })
307
310
  ] }) });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backmatter/studio",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "The Backmatter editing surface: document editor, AI chat, publish. Mounted on your site or hosted on the dashboard.",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -47,7 +47,7 @@
47
47
  },
48
48
  "dependencies": {
49
49
  "@ai-sdk/react": "^4.0.100",
50
- "@backmatter/core": "^0.0.20",
50
+ "@backmatter/core": "^0.0.21",
51
51
  "@base-ui/react": "^1.6.0",
52
52
  "@dnd-kit/abstract": "^0.5.0",
53
53
  "@dnd-kit/react": "^0.5.0",
package/src/api.ts CHANGED
@@ -261,6 +261,10 @@ export function attachGithubInstallation(
261
261
  });
262
262
  }
263
263
 
264
+ export function fetchGithubRepositoryAccess(workspaceId: string) {
265
+ return api<{ url: string }>(`/workspaces/${workspaceId}/github/repository-access`);
266
+ }
267
+
264
268
  export function fetchGithubRepos(workspaceId: string) {
265
269
  return api<{
266
270
  repos: Array<{ fullName: string; defaultBranch: string }>;
@@ -55,7 +55,7 @@ export function ChatPanel({ fill = false }: { fill?: boolean } = {}) {
55
55
  // one row so toggling the open document doesn't shift the content.
56
56
  const contextRows = Math.max(
57
57
  1,
58
- (ui.focus && ui.includeFocus ? 1 : 0) + ui.mentions.length,
58
+ (ui.focus && ui.includeFocus ? 1 : 0) + ui.mentions.length + ui.pointers.length,
59
59
  );
60
60
  const contextReserve = contextRows * CONTEXT_ROW_HEIGHT + CONTEXT_BAR_PADDING + 12;
61
61
 
@@ -46,8 +46,11 @@ import {
46
46
  } from "../chrome/EditorFocusContext";
47
47
  import {
48
48
  addMention as addMentionTo,
49
+ addPointer as addPointerTo,
49
50
  buildChatContext,
50
51
  removeMention as removeMentionFrom,
52
+ removePointer as removePointerFrom,
53
+ type ChatPointer,
51
54
  type ChatRequestContext,
52
55
  } from "./chat-context";
53
56
  import {
@@ -63,6 +66,7 @@ import {
63
66
  type PanelAction,
64
67
  type PanelState,
65
68
  } from "./chat-state";
69
+ import { fetchNotifyingSessionExpiry } from "./session-expiry";
66
70
 
67
71
  // ---------------------------------------------------------------------------
68
72
  // UI-level context (panel, thread selection, model, chips)
@@ -84,6 +88,12 @@ export type ChatUIValue = {
84
88
  mentions: DocRef[];
85
89
  addMention: (ref: DocRef) => void;
86
90
  removeMention: (ref: DocRef) => void;
91
+ /** Elements pointed at on the host site. Only the dev bar chat sets `pointer`. */
92
+ pointer: boolean;
93
+ pointers: ChatPointer[];
94
+ addPointer: (pointer: ChatPointer) => void;
95
+ removePointer: (pointer: ChatPointer) => void;
96
+ clearPointers: () => void;
87
97
  includeFocus: boolean;
88
98
  setIncludeFocus: (v: boolean) => void;
89
99
  focus: EditorFocus | null;
@@ -170,10 +180,13 @@ function refFromInput(input: unknown): DocRef | null {
170
180
  export function ChatProvider({
171
181
  workspaceId,
172
182
  startOpen = false,
183
+ pointer = false,
173
184
  children,
174
185
  }: {
175
186
  workspaceId: string;
176
187
  startOpen?: boolean;
188
+ /** Dev bar chat can point at elements on the host page. */
189
+ pointer?: boolean;
177
190
  children: React.ReactNode;
178
191
  }) {
179
192
  const [panel, dispatch] = useReducer(
@@ -188,6 +201,7 @@ export function ChatProvider({
188
201
  const [freshThread, setFreshThread] = useState(false);
189
202
  const [pendingText, setPendingText] = useState<string | null>(null);
190
203
  const [mentions, setMentions] = useState<DocRef[]>([]);
204
+ const [pointers, setPointers] = useState<ChatPointer[]>([]);
191
205
  const [includeFocus, setIncludeFocus] = useState(true);
192
206
  const [threadsVersion, setThreadsVersion] = useState(0);
193
207
  const { focus } = useEditorFocus();
@@ -222,6 +236,7 @@ export function ChatProvider({
222
236
  setFreshThread(false);
223
237
  setPendingText(null);
224
238
  setMentions([]);
239
+ setPointers([]);
225
240
  setIncludeFocus(true);
226
241
  }, [workspaceId]);
227
242
 
@@ -245,6 +260,7 @@ export function ChatProvider({
245
260
  setFreshThread(false);
246
261
  setPendingText(null);
247
262
  setMentions([]);
263
+ setPointers([]);
248
264
  dispatch({ type: "showChat" });
249
265
  }, []);
250
266
 
@@ -254,6 +270,13 @@ export function ChatProvider({
254
270
  const removeMention = useCallback((ref: DocRef) => {
255
271
  setMentions((prev) => removeMentionFrom(prev, ref));
256
272
  }, []);
273
+ const addPointer = useCallback((next: ChatPointer) => {
274
+ setPointers((prev) => addPointerTo(prev, next));
275
+ }, []);
276
+ const removePointer = useCallback((next: ChatPointer) => {
277
+ setPointers((prev) => removePointerFrom(prev, next));
278
+ }, []);
279
+ const clearPointers = useCallback(() => setPointers([]), []);
257
280
  const bumpThreads = useCallback(() => setThreadsVersion((v) => v + 1), []);
258
281
 
259
282
  // Context getter kept in a ref so the session never re-renders because of it.
@@ -261,8 +284,9 @@ export function ChatProvider({
261
284
  focusDoc: null,
262
285
  selection: null,
263
286
  mentions: [],
287
+ pointers: [],
264
288
  }));
265
- contextRef.current = () => buildChatContext({ focus, includeFocus, mentions });
289
+ contextRef.current = () => buildChatContext({ focus, includeFocus, mentions, pointers });
266
290
  const modelRef = useRef<string | null>(model);
267
291
  modelRef.current = model;
268
292
 
@@ -294,6 +318,11 @@ export function ChatProvider({
294
318
  mentions,
295
319
  addMention,
296
320
  removeMention,
321
+ pointer,
322
+ pointers,
323
+ addPointer,
324
+ removePointer,
325
+ clearPointers,
297
326
  includeFocus,
298
327
  setIncludeFocus,
299
328
  focus,
@@ -314,6 +343,11 @@ export function ChatProvider({
314
343
  mentions,
315
344
  addMention,
316
345
  removeMention,
346
+ pointer,
347
+ pointers,
348
+ addPointer,
349
+ removePointer,
350
+ clearPointers,
317
351
  includeFocus,
318
352
  focus,
319
353
  threadsVersion,
@@ -513,6 +547,10 @@ function LiveSession({
513
547
  api: aiMessagesUrl(workspaceId, threadId),
514
548
  credentials: apiCredentials(),
515
549
  headers: apiHeaders(),
550
+ fetch: fetchNotifyingSessionExpiry(
551
+ typeof location === "undefined" ? "" : location.origin,
552
+ typeof window !== "undefined" && window.parent !== window ? window.parent : null,
553
+ ),
516
554
  prepareSendMessagesRequest: ({ messages, body }) => ({
517
555
  body: {
518
556
  message: messages[messages.length - 1],