@draftably/runtime 0.1.0 → 0.3.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.
package/dist/viewer.js CHANGED
@@ -1,5 +1,7 @@
1
- import { r as ce, F as ee } from "./render-BOAZBzVa.js";
2
- import { f as Ee, a as ke } from "./render-BOAZBzVa.js";
1
+ import { r as ce } from "./render-Dgo42PR4.js";
2
+ import { a as ke } from "./render-Dgo42PR4.js";
3
+ import { F as ee } from "./compile-Csfz4rk4.js";
4
+ import { h as Ae } from "./compile-Csfz4rk4.js";
3
5
  const de = "http://www.w3.org/2000/svg", le = new Set(
4
6
  "svg title desc metadata defs style marker g a path rect ellipse circle line polyline polygon text tspan".split(
5
7
  " "
@@ -13,25 +15,25 @@ let me = 0;
13
15
  function ue(y, c) {
14
16
  const V = new y.defaultView.DOMParser().parseFromString(c, "image/svg+xml"), s = /* @__PURE__ */ new Map();
15
17
  for (const v of Array.from(V.querySelectorAll("text[font-family]"))) {
16
- const m = (v.getAttribute("font-family") ?? "").split(",")[0].trim().replace(/^['"]|['"]$/g, ""), b = v.getAttribute("font-weight") ?? "400";
17
- if (!Object.values(ee).some((o) => o.family === m && String(o.weight) === b))
18
+ const l = (v.getAttribute("font-family") ?? "").split(",")[0].trim().replace(/^['"]|['"]$/g, ""), b = v.getAttribute("font-weight") ?? "400";
19
+ if (!Object.values(ee).some((o) => o.family === l && String(o.weight) === b))
18
20
  throw new Error("Runtime SVG requested an unknown bundled font face.");
19
- s.set(`${m}:${b}`, { family: m, weight: b });
21
+ s.set(`${l}:${b}`, { family: l, weight: b });
20
22
  }
21
23
  return [...s.values()];
22
24
  }
23
25
  function we(y, c, V) {
24
26
  const s = new y.defaultView.DOMParser().parseFromString(c, "image/svg+xml"), v = /* @__PURE__ */ new Map();
25
- for (const m of Array.from(s.querySelectorAll("style"))) {
26
- const b = m.textContent ?? "";
27
+ for (const l of Array.from(s.querySelectorAll("style"))) {
28
+ const b = l.textContent ?? "";
27
29
  for (const [, o] of b.matchAll(/@font-face\s*\{([^{}]{1,200000})\}/g)) {
28
- const l = /font-family\s*:\s*['"]([^'"]+)['"]/i.exec(o)?.[1], w = /font-weight\s*:\s*(\d{1,4})/i.exec(o)?.[1], p = /src\s*:\s*url\((data:font\/woff2;base64,[A-Za-z0-9+/=]+)\)/i.exec(o)?.[1];
29
- !l || !w || !p || Object.values(ee).some((f) => f.family === l && String(f.weight) === w) && v.set(`${l}:${w}`, { family: l, weight: w, data: p });
30
+ const f = /font-family\s*:\s*['"]([^'"]+)['"]/i.exec(o)?.[1], w = /font-weight\s*:\s*(\d{1,4})/i.exec(o)?.[1], p = /src\s*:\s*url\((data:font\/woff2;base64,[A-Za-z0-9+/=]+)\)/i.exec(o)?.[1];
31
+ !f || !w || !p || Object.values(ee).some((m) => m.family === f && String(m.weight) === w) && v.set(`${f}:${w}`, { family: f, weight: w, data: p });
30
32
  }
31
33
  }
32
- return V.map((m) => {
33
- const b = v.get(`${m.family}:${m.weight}`);
34
- if (!b) throw new Error(`Embedded font ${m.family} ${m.weight} is missing.`);
34
+ return V.map((l) => {
35
+ const b = v.get(`${l.family}:${l.weight}`);
36
+ if (!b) throw new Error(`Embedded font ${l.family} ${l.weight} is missing.`);
35
37
  return b;
36
38
  });
37
39
  }
@@ -39,37 +41,37 @@ function ge(y, c, V, s = 1e5) {
39
41
  const v = new y.defaultView.DOMParser().parseFromString(c, "image/svg+xml");
40
42
  if (v.querySelector("parsererror") || v.documentElement.localName !== "svg")
41
43
  throw new Error("Runtime returned invalid SVG.");
42
- const m = new Set(
43
- Array.from(v.querySelectorAll("[id]"), (l) => l.getAttribute("id") ?? "")
44
+ const l = new Set(
45
+ Array.from(v.querySelectorAll("[id]"), (f) => f.getAttribute("id") ?? "")
44
46
  );
45
47
  let b = 0;
46
- const o = (l) => {
47
- if (++b > s || !le.has(l.localName))
48
+ const o = (f) => {
49
+ if (++b > s || !le.has(f.localName))
48
50
  throw new Error("Runtime SVG exceeded the allowed drawing vocabulary.");
49
- const w = y.createElementNS(de, l.localName);
50
- for (const { name: p, value: f } of Array.from(l.attributes)) {
51
+ const w = y.createElementNS(de, f.localName);
52
+ for (const { name: p, value: m } of Array.from(f.attributes)) {
51
53
  if (/^on/i.test(p)) continue;
52
54
  if (p === "href") {
53
- if (l.localName !== "a") continue;
55
+ if (f.localName !== "a") continue;
54
56
  try {
55
- const a = new URL(f, y.baseURI);
57
+ const a = new URL(m, y.baseURI);
56
58
  (a.protocol === "http:" || a.protocol === "https:") && w.setAttribute("href", a.href);
57
59
  } catch {
58
60
  }
59
61
  continue;
60
62
  }
61
63
  if (!fe.has(p) && !/^data-[a-z0-9-]+$/.test(p)) continue;
62
- const x = [...f.matchAll(/url\(#([^)]*)\)/g)].map((a) => a[1]);
63
- /url\s*\(/i.test(f) && (x.length === 0 || x.some((a) => !m.has(a))) || p === "aria-labelledby" && f.split(/\s+/).some((a) => !m.has(a)) || w.setAttribute(p, f);
64
+ const x = [...m.matchAll(/url\(#([^)]*)\)/g)].map((a) => a[1]);
65
+ /url\s*\(/i.test(m) && (x.length === 0 || x.some((a) => !l.has(a))) || p === "aria-labelledby" && m.split(/\s+/).some((a) => !l.has(a)) || w.setAttribute(p, m);
64
66
  }
65
- l.localName === "a" && w.getAttribute("target") === "_blank" && w.setAttribute("rel", "noopener noreferrer");
66
- for (const p of Array.from(l.childNodes))
67
+ f.localName === "a" && w.getAttribute("target") === "_blank" && w.setAttribute("rel", "noopener noreferrer");
68
+ for (const p of Array.from(f.childNodes))
67
69
  if (p.nodeType === 1) w.append(o(p));
68
70
  else if (p.nodeType === 3) {
69
- const f = p.nodeValue ?? "";
71
+ const m = p.nodeValue ?? "";
70
72
  w.append(
71
73
  y.createTextNode(
72
- l.localName === "style" && V ? f.replace(/@font-face\s*\{[^{}]*\}/g, "") : f
74
+ f.localName === "style" && V ? m.replace(/@font-face\s*\{[^{}]*\}/g, "") : m
73
75
  )
74
76
  );
75
77
  }
@@ -84,27 +86,27 @@ function K(y, c, V) {
84
86
  diagnostics: [{ code: c, severity: "error", message: V, itemIds: [] }]
85
87
  };
86
88
  }
87
- function ve(y, c = {}) {
89
+ function be(y, c = {}) {
88
90
  const V = y?.ownerDocument?.defaultView;
89
91
  if (!V || !(y instanceof V.HTMLElement))
90
92
  throw new TypeError("host must be an HTMLElement.");
91
93
  if (y.childNodes.length) throw new Error("Viewer host must be empty and exclusively owned.");
92
94
  if ((c.execution ?? { mode: "worker" }).mode === "worker" && c.render?.links?.mode === "safe" && c.render.links.resolve)
93
95
  throw new TypeError('A link resolver requires execution: { mode: "main" }.');
94
- const s = y.ownerDocument, v = V, m = s.createElement("section");
95
- m.className = "draft-viewer", m.setAttribute("aria-label", c.label ?? "Diagram viewer");
96
+ const s = y.ownerDocument, v = V, l = s.createElement("section");
97
+ l.className = "draft-viewer", c.outline !== "visible" && l.classList.add("draft-viewer--outline-hidden"), l.setAttribute("aria-label", c.label ?? "Diagram viewer");
96
98
  const b = s.createElement("div");
97
99
  b.className = "draft-viewer__toolbar", b.setAttribute("role", "toolbar"), b.setAttribute("aria-label", "Diagram controls");
98
100
  const o = s.createElement("div");
99
101
  o.className = "draft-viewer__viewport", o.tabIndex = 0, o.setAttribute("aria-label", c.label ?? "Diagram");
100
- const l = s.createElement("p");
101
- l.className = "draft-viewer__status", l.setAttribute("role", "status"), l.setAttribute("aria-live", "polite");
102
+ const f = s.createElement("p");
103
+ f.className = "draft-viewer__status", f.setAttribute("role", "status"), f.setAttribute("aria-live", "polite");
102
104
  const w = s.createElement("ol");
103
- w.className = "draft-viewer__outline", w.setAttribute("aria-label", "Diagram outline"), m.append(b, o, l, w), y.append(m);
105
+ w.className = "draft-viewer__outline", w.setAttribute("aria-label", "Diagram outline"), l.append(b, o, f, w), y.append(l);
104
106
  const p = `draftViewer${(++me).toString(36)}${Math.random().toString(36).slice(2, 9)}`;
105
- let f = 0, x = !1, a = { centerX: 0, centerY: 0, zoom: 1 }, T = !1, u, F, B, te = 0;
106
- const M = /* @__PURE__ */ new Map(), G = /* @__PURE__ */ new Map(), q = /* @__PURE__ */ new Map(), L = (e, r) => {
107
- for (const t of G.get(e) ?? [])
107
+ let m = 0, x = !1, a = { centerX: 0, centerY: 0, zoom: 1 }, _ = !1, u, C, q, te = 0;
108
+ const N = /* @__PURE__ */ new Map(), U = /* @__PURE__ */ new Map(), B = /* @__PURE__ */ new Map(), L = (e, r) => {
109
+ for (const t of U.get(e) ?? [])
108
110
  try {
109
111
  t(r);
110
112
  } catch {
@@ -130,19 +132,19 @@ function ve(y, c = {}) {
130
132
  centerX: t + g / 2,
131
133
  centerY: S + n / 2,
132
134
  zoom: Math.min(1, re() * 0.92)
133
- }, T = !1, R(), L("camera", { camera: { ...a }, reason: e });
135
+ }, _ = !1, R(), L("camera", { camera: { ...a }, reason: e });
134
136
  }, P = (e) => {
135
- a.zoom = Math.max(0.02, Math.min(8, a.zoom * e)), T = !0, R(), L("camera", { camera: { ...a }, reason: "user" });
137
+ a.zoom = Math.max(0.02, Math.min(8, a.zoom * e)), _ = !0, R(), L("camera", { camera: { ...a }, reason: "user" });
136
138
  }, ne = () => {
137
- a.zoom = 1, T = !0, R(), L("camera", { camera: { ...a }, reason: "user" });
139
+ a.zoom = 1, _ = !0, R(), L("camera", { camera: { ...a }, reason: "user" });
138
140
  };
139
141
  c.toolbar !== !1 && (j("Zoom in", () => P(1.2)), j("Zoom out", () => P(1 / 1.2)), j("Fit diagram", () => Y()), j("Actual size", ne));
140
142
  const J = new v.ResizeObserver(() => {
141
- u && !o.getBoundingClientRect().width || (T ? R() : Y("resize"));
143
+ u && !o.getBoundingClientRect().width || (_ ? R() : Y("resize"));
142
144
  });
143
145
  J.observe(o);
144
146
  const X = (e, r) => {
145
- l.textContent = r.map((t) => t.message).join(" "), m.classList.add("draft-viewer--stale"), L("diagnostics", { revision: e, diagnostics: r, stale: !!u });
147
+ f.textContent = r.map((t) => t.message).join(" "), l.classList.add("draft-viewer--stale"), L("diagnostics", { revision: e, diagnostics: r, stale: !!u });
146
148
  }, oe = async (e, r) => {
147
149
  const t = ue(s, e);
148
150
  if (!t.length) return [];
@@ -161,9 +163,9 @@ function ve(y, c = {}) {
161
163
  if (!g) throw new Error("The browser cannot load embedded diagram fonts.");
162
164
  return Promise.all(
163
165
  S.map(async (n) => {
164
- const h = `${n.family}:${n.weight}`, C = M.get(h);
165
- if (C?.status === "loaded" && Array.from(s.fonts).includes(C))
166
- return { key: h, face: C };
166
+ const h = `${n.family}:${n.weight}`, F = N.get(h);
167
+ if (F?.status === "loaded" && Array.from(s.fonts).includes(F))
168
+ return { key: h, face: F };
167
169
  const d = new g(n.family, `url("${n.data}")`, { weight: n.weight });
168
170
  if (await d.load(), d.status !== "loaded")
169
171
  throw new Error(`Embedded font ${n.family} ${n.weight} did not load.`);
@@ -171,34 +173,34 @@ function ve(y, c = {}) {
171
173
  })
172
174
  );
173
175
  }, z = (e) => {
174
- const r = B;
175
- B = void 0, r && (v.clearTimeout(r.timer), r.cleanup(), r.finish(void 0, e ?? new Error("Viewer render was cancelled."))), F?.terminate(), F = void 0;
176
+ const r = q;
177
+ q = void 0, r && (v.clearTimeout(r.timer), r.cleanup(), r.finish(void 0, e ?? new Error("Viewer render was cancelled."))), C?.terminate(), C = void 0;
176
178
  }, ae = (e, r, t) => (c.execution ?? { mode: "worker" }).mode === "main" ? ce(e, { ...r, signal: t }) : new Promise((S, g) => {
177
179
  const n = ++te;
178
180
  let h = !1;
179
- const C = () => {
180
- F && (F.removeEventListener("message", E), F.removeEventListener("error", W), F.removeEventListener("messageerror", U), t?.removeEventListener("abort", H));
181
+ const F = () => {
182
+ C && (C.removeEventListener("message", E), C.removeEventListener("error", W), C.removeEventListener("messageerror", G), t?.removeEventListener("abort", H));
181
183
  }, d = (k, D) => {
182
184
  if (h) return;
183
185
  h = !0;
184
- const i = B;
185
- i?.id === n && (B = void 0, v.clearTimeout(i.timer), i.cleanup()), D ? g(D) : S(k);
186
+ const i = q;
187
+ i?.id === n && (q = void 0, v.clearTimeout(i.timer), i.cleanup()), D ? g(D) : S(k);
186
188
  }, E = (k) => {
187
189
  k.data?.id === n && d(k.data.result);
188
190
  }, W = (k) => {
189
191
  k.preventDefault(), z(new Error(k.message || "Viewer render worker failed."));
190
- }, U = () => z(new Error("Viewer render worker returned an unreadable result.")), H = () => z(new Error("Viewer render was aborted."));
192
+ }, G = () => z(new Error("Viewer render worker returned an unreadable result.")), H = () => z(new Error("Viewer render was aborted."));
191
193
  try {
192
- F ??= c.execution?.mode === "worker" && c.execution.createWorker ? c.execution.createWorker() : new Worker(new URL(
194
+ C ??= c.execution?.mode === "worker" && c.execution.createWorker ? c.execution.createWorker() : new Worker(new URL(
193
195
  /* @vite-ignore */
194
- "" + new URL("assets/render.worker-BpUp6NY_.js", import.meta.url).href,
196
+ "" + new URL("assets/render.worker-dvseyGmC.js", import.meta.url).href,
195
197
  import.meta.url
196
- ), { type: "module" }), F.addEventListener("message", E), F.addEventListener("error", W), F.addEventListener("messageerror", U), t?.addEventListener("abort", H, { once: !0 });
198
+ ), { type: "module" }), C.addEventListener("message", E), C.addEventListener("error", W), C.addEventListener("messageerror", G), t?.addEventListener("abort", H, { once: !0 });
197
199
  const k = c.execution?.mode === "worker" ? c.execution.timeoutMs ?? 5e3 : 5e3, D = v.setTimeout(
198
200
  () => z(new Error("Viewer render worker timed out.")),
199
201
  k
200
202
  );
201
- B = { id: n, timer: D, finish: d, cleanup: C }, F.postMessage({ id: n, source: e, options: r });
203
+ q = { id: n, timer: D, finish: d, cleanup: F }, C.postMessage({ id: n, source: e, options: r });
202
204
  } catch (k) {
203
205
  z(
204
206
  k instanceof Error ? k : new Error("Viewer render worker could not start.")
@@ -226,7 +228,7 @@ function ve(y, c = {}) {
226
228
  scale: a.zoom
227
229
  }, o.setPointerCapture(e.pointerId));
228
230
  }), o.addEventListener("pointermove", (e) => {
229
- A && (a.centerX = A.centerX - (e.clientX - A.x) / A.scale, a.centerY = A.centerY - (e.clientY - A.y) / A.scale, T = !0, R());
231
+ A && (a.centerX = A.centerX - (e.clientX - A.x) / A.scale, a.centerY = A.centerY - (e.clientY - A.y) / A.scale, _ = !0, R());
230
232
  });
231
233
  const Q = () => {
232
234
  if (A) {
@@ -250,41 +252,41 @@ function ve(y, c = {}) {
250
252
  return;
251
253
  }
252
254
  const S = r?.closest("[data-id]")?.getAttribute("data-id"), g = u?.items.find((n) => n.id === S);
253
- g && L("itemactivate", { id: g.id, kind: g.kind, input: "pointer", revision: f });
255
+ g && L("itemactivate", { id: g.id, kind: g.kind, input: "pointer", revision: m });
254
256
  }), o.addEventListener("keydown", (e) => {
255
257
  e.target !== o || e.altKey || e.ctrlKey || e.metaKey || (e.key === "+" || e.key === "=" ? P(1.2) : e.key === "-" ? P(1 / 1.2) : e.key.toLowerCase() === "f" && Y());
256
258
  });
257
259
  const se = (e, r) => {
258
- for (const [t, S] of q)
260
+ for (const [t, S] of B)
259
261
  t !== e && S.resolve({ status: r, revision: t });
260
262
  };
261
263
  return {
262
264
  update: (e, r = {}) => {
263
- const t = ++f;
265
+ const t = ++m;
264
266
  return x ? Promise.resolve({ status: "destroyed", revision: t }) : (se(t, "superseded"), z(new Error("Viewer update was superseded.")), new Promise((S) => {
265
267
  let g = !1;
266
268
  const n = (d) => {
267
269
  if (g) return;
268
- g = !0, r.signal?.removeEventListener("abort", h), q.delete(t);
269
- const E = x ? { status: "destroyed", revision: t } : t !== f ? { status: "superseded", revision: t } : r.signal?.aborted ? { status: "aborted", revision: t } : d;
270
+ g = !0, r.signal?.removeEventListener("abort", h), B.delete(t);
271
+ const E = x ? { status: "destroyed", revision: t } : t !== m ? { status: "superseded", revision: t } : r.signal?.aborted ? { status: "aborted", revision: t } : d;
270
272
  S(E);
271
273
  }, h = () => {
272
- t === f && (c.execution ?? { mode: "worker" }).mode === "worker" && z(new Error("Viewer render was aborted.")), n({ status: "aborted", revision: t });
274
+ t === m && (c.execution ?? { mode: "worker" }).mode === "worker" && z(new Error("Viewer render was aborted.")), n({ status: "aborted", revision: t });
273
275
  };
274
- if (q.set(t, { resolve: n }), r.signal?.aborted) {
276
+ if (B.set(t, { resolve: n }), r.signal?.aborted) {
275
277
  h();
276
278
  return;
277
279
  }
278
280
  r.signal?.addEventListener("abort", h, { once: !0 });
279
- const C = {
281
+ const F = {
280
282
  ...c.render ?? {},
281
283
  target: "inline",
282
284
  idPrefix: p,
283
285
  fonts: c.render?.fonts ?? "embed",
284
286
  ...r.state !== void 0 ? { state: r.state } : {}
285
287
  };
286
- ae(e, C, r.signal).then(async (d) => {
287
- if (x || t !== f || r.signal?.aborted) {
288
+ ae(e, F, r.signal).then(async (d) => {
289
+ if (x || t !== m || r.signal?.aborted) {
288
290
  n({ status: "superseded", revision: t });
289
291
  return;
290
292
  }
@@ -294,9 +296,9 @@ function ve(y, c = {}) {
294
296
  }
295
297
  let E;
296
298
  try {
297
- E = await oe(d.value.svg, C.fonts ?? "embed");
299
+ E = await oe(d.value.svg, F.fonts ?? "embed");
298
300
  } catch (i) {
299
- if (x || t !== f || r.signal?.aborted) {
301
+ if (x || t !== m || r.signal?.aborted) {
300
302
  n({
301
303
  status: r.signal?.aborted ? "aborted" : "superseded",
302
304
  revision: t
@@ -311,25 +313,25 @@ function ve(y, c = {}) {
311
313
  X(t, $.diagnostics), n({ status: "error", revision: t, error: $ });
312
314
  return;
313
315
  }
314
- if (x || t !== f || r.signal?.aborted) {
316
+ if (x || t !== m || r.signal?.aborted) {
315
317
  n({ status: "superseded", revision: t });
316
318
  return;
317
319
  }
318
320
  let W;
319
321
  try {
320
- W = ge(s, d.value.svg, C.fonts !== "host");
322
+ W = ge(s, d.value.svg, F.fonts !== "host");
321
323
  } catch (i) {
322
- const $ = i instanceof Error ? i.message : "Could not build safe SVG.", N = K("internal", "DRAFT_VIEWER_DOM", $);
323
- X(t, N.diagnostics), n({ status: "error", revision: t, error: N });
324
+ const $ = i instanceof Error ? i.message : "Could not build safe SVG.", M = K("internal", "DRAFT_VIEWER_DOM", $);
325
+ X(t, M.diagnostics), n({ status: "error", revision: t, error: M });
324
326
  return;
325
327
  }
326
- const U = [];
328
+ const G = [];
327
329
  try {
328
330
  for (const i of E)
329
- M.has(i.key) || (s.fonts.add(i.face), M.set(i.key, i.face), U.push(i));
331
+ N.has(i.key) || (s.fonts.add(i.face), N.set(i.key, i.face), G.push(i));
330
332
  } catch (i) {
331
- for (const { key: N, face: Z } of U)
332
- s.fonts.delete(Z), M.delete(N);
333
+ for (const { key: M, face: Z } of G)
334
+ s.fonts.delete(Z), N.delete(M);
333
335
  const $ = K(
334
336
  "environment",
335
337
  "DRAFT_FONT_UNAVAILABLE",
@@ -341,10 +343,10 @@ function ve(y, c = {}) {
341
343
  const H = !!u;
342
344
  u = d.value, o.replaceChildren(W), w.replaceChildren(
343
345
  ...u.items.map((i) => {
344
- const $ = s.createElement("li"), N = s.createElement("button");
345
- N.type = "button";
346
+ const $ = s.createElement("li"), M = s.createElement("button");
347
+ M.type = "button";
346
348
  const Z = i.label.trim() || (i.kind === "edge" ? `${i.from ?? "?"} to ${i.to ?? "?"}` : i.id);
347
- return N.textContent = `${i.kind}: ${Z}`, N.dataset.itemId = i.id, N.addEventListener("click", () => {
349
+ return M.textContent = `${i.kind}: ${Z}`, M.dataset.itemId = i.id, M.addEventListener("click", () => {
348
350
  L("itemactivate", {
349
351
  id: i.id,
350
352
  kind: i.kind,
@@ -352,23 +354,23 @@ function ve(y, c = {}) {
352
354
  revision: t
353
355
  });
354
356
  const O = Array.from(o.querySelectorAll("[data-id]")).find(
355
- (_) => _.getAttribute("data-id") === i.id
357
+ (T) => T.getAttribute("data-id") === i.id
356
358
  );
357
359
  if (O) {
358
- const _ = O.getBoundingClientRect(), I = o.getBoundingClientRect();
359
- (_.width || _.height) && I.width && I.height && (a = {
360
- centerX: a.centerX + (_.left + _.width / 2 - (I.left + I.width / 2)) / a.zoom,
361
- centerY: a.centerY + (_.top + _.height / 2 - (I.top + I.height / 2)) / a.zoom,
360
+ const T = O.getBoundingClientRect(), I = o.getBoundingClientRect();
361
+ (T.width || T.height) && I.width && I.height && (a = {
362
+ centerX: a.centerX + (T.left + T.width / 2 - (I.left + I.width / 2)) / a.zoom,
363
+ centerY: a.centerY + (T.top + T.height / 2 - (I.top + I.height / 2)) / a.zoom,
362
364
  zoom: Math.max(1, a.zoom)
363
- }, T = !0, R(), L("camera", { camera: { ...a }, reason: "user" }));
365
+ }, _ = !0, R(), L("camera", { camera: { ...a }, reason: "user" }));
364
366
  }
365
- }), $.append(N), $;
367
+ }), $.append(M), $;
366
368
  })
367
369
  );
368
370
  const k = new Set(E.map((i) => i.key));
369
- for (const [i, $] of M)
370
- k.has(i) || (s.fonts.delete($), M.delete(i));
371
- m.classList.remove("draft-viewer--stale"), l.textContent = d.diagnostics.map((i) => i.message).join(" "), !H || r.camera === "fit" ? Y() : R();
371
+ for (const [i, $] of N)
372
+ k.has(i) || (s.fonts.delete($), N.delete(i));
373
+ l.classList.remove("draft-viewer--stale"), f.textContent = d.diagnostics.map((i) => i.message).join(" "), !H || r.camera === "fit" ? Y() : R();
372
374
  const D = {
373
375
  status: "committed",
374
376
  revision: t,
@@ -377,7 +379,7 @@ function ve(y, c = {}) {
377
379
  };
378
380
  n(D), L("render", { revision: t, value: u }), L("diagnostics", { revision: t, diagnostics: d.diagnostics, stale: !1 });
379
381
  }).catch((d) => {
380
- if (x || t !== f || r.signal?.aborted) {
382
+ if (x || t !== m || r.signal?.aborted) {
381
383
  n({
382
384
  status: r.signal?.aborted ? "aborted" : "superseded",
383
385
  revision: t
@@ -396,12 +398,12 @@ function ve(y, c = {}) {
396
398
  on(e, r) {
397
399
  if (x) return () => {
398
400
  };
399
- const t = G.get(e) ?? /* @__PURE__ */ new Set();
400
- return t.add(r), G.set(e, t), () => t.delete(r);
401
+ const t = U.get(e) ?? /* @__PURE__ */ new Set();
402
+ return t.add(r), U.set(e, t), () => t.delete(r);
401
403
  },
402
404
  getCamera: () => ({ ...a }),
403
405
  setCamera(e) {
404
- x || !Number.isFinite(e.centerX) || !Number.isFinite(e.centerY) || !Number.isFinite(e.zoom) || e.zoom <= 0 || (a = { ...e }, T = !0, R(), L("camera", { camera: { ...a }, reason: "api" }));
406
+ x || !Number.isFinite(e.centerX) || !Number.isFinite(e.centerY) || !Number.isFinite(e.zoom) || e.zoom <= 0 || (a = { ...e }, _ = !0, R(), L("camera", { camera: { ...a }, reason: "api" }));
405
407
  },
406
408
  fit: () => {
407
409
  x || Y();
@@ -415,24 +417,24 @@ function ve(y, c = {}) {
415
417
  },
416
418
  destroy() {
417
419
  if (!x) {
418
- if (x = !0, f++, A) {
420
+ if (x = !0, m++, A) {
419
421
  try {
420
422
  o.releasePointerCapture(A.pointerId);
421
423
  } catch {
422
424
  }
423
425
  A = void 0;
424
426
  }
425
- for (const [e, r] of q)
427
+ for (const [e, r] of B)
426
428
  r.resolve({ status: "destroyed", revision: e });
427
- q.clear(), z(new Error("Viewer was destroyed."));
428
- for (const e of M.values()) s.fonts.delete(e);
429
- M.clear(), J.disconnect(), G.clear(), y.replaceChildren(), u = void 0;
429
+ B.clear(), z(new Error("Viewer was destroyed."));
430
+ for (const e of N.values()) s.fonts.delete(e);
431
+ N.clear(), J.disconnect(), U.clear(), y.replaceChildren(), u = void 0;
430
432
  }
431
433
  }
432
434
  };
433
435
  }
434
436
  export {
435
- Ee as fontMetricsVersion,
436
- ve as mountViewer,
437
+ Ae as fontMetricsVersion,
438
+ be as mountViewer,
437
439
  ke as runtimeVersion
438
440
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@draftably/runtime",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "private": false,
5
5
  "description": "Portable native Draftably SVG rendering, validation, and optional viewer.",
6
6
  "type": "module",
@@ -26,6 +26,10 @@
26
26
  "types": "./dist/types/src/runtime/element.d.ts",
27
27
  "import": "./dist/element.js"
28
28
  },
29
+ "./graph": {
30
+ "types": "./dist/types/src/graph-api/index.d.ts",
31
+ "import": "./dist/graph.js"
32
+ },
29
33
  "./viewer.css": "./dist/viewer.css",
30
34
  "./fonts.css": "./dist/fonts.css",
31
35
  "./browser": {
@@ -34,9 +38,6 @@
34
38
  },
35
39
  "./package.json": "./package.json"
36
40
  },
37
- "scripts": {
38
- "build": "node ../../scripts/build-runtime.ts"
39
- },
40
41
  "engines": {
41
42
  "node": ">=22.21.0"
42
43
  },
@@ -48,5 +49,8 @@
48
49
  "publishConfig": {
49
50
  "access": "public",
50
51
  "registry": "https://registry.npmjs.org"
52
+ },
53
+ "scripts": {
54
+ "build": "node ../../scripts/build-runtime.ts"
51
55
  }
52
- }
56
+ }