Split apart the frontend Editor type into SubscriptionsRouter and EditorHandle (#3923)

* Remove the unused Editor.raw/wasmMemory/wasmImport

* Split out Editor.subscriptions

* Replace editor.handle.* with editor.* (1 of 2)

* Replace editor.handle.* with editor.* (2 of 2)

* Replace Editor typedef with EditorHandle import

* Pluralize subscription-router and rename subscriptionsRef->subscriptionsRouter and editorRef->editorHandle

* Remove editor.ts

* Update the readme

* Fix demo art loading bug
This commit is contained in:
Keavon Chambers
2026-03-20 23:34:13 -07:00
committed by GitHub
parent 64fd12a1a0
commit ed7987c881
40 changed files with 549 additions and 584 deletions
+16 -13
View File
@@ -1,19 +1,22 @@
import type { Editor } from "@graphite/editor";
import type { EditorHandle } from "@graphite/../wasm/pkg/graphite_wasm";
import type { SubscriptionsRouter } from "/src/subscriptions-router";
type ApiResponse = { family: string; variants: string[]; files: Record<string, string> }[];
const FONT_LIST_API = "https://api.graphite.art/font-list";
let editorRef: Editor | undefined = undefined;
let subscriptionsRouter: SubscriptionsRouter | undefined = undefined;
let editorHandle: EditorHandle | undefined = undefined;
let abortController: AbortController | undefined = undefined;
export function createFontsManager(editor: Editor) {
export function createFontsManager(subscriptions: SubscriptionsRouter, editor: EditorHandle) {
destroyFontsManager();
editorRef = editor;
subscriptionsRouter = subscriptions;
editorHandle = editor;
abortController = new AbortController();
editor.subscriptions.subscribeFrontendMessage("TriggerFontCatalogLoad", async () => {
subscriptions.subscribeFrontendMessage("TriggerFontCatalogLoad", async () => {
try {
const response = await fetch(FONT_LIST_API, abortController ? { signal: abortController.signal } : undefined);
if (!response.ok) throw new Error(`Font catalog request failed with status ${response.status}`);
@@ -31,14 +34,14 @@ export function createFontsManager(editor: Editor) {
return { name: font.family, styles };
});
editor.handle.onFontCatalogLoad(catalog);
editor.onFontCatalogLoad(catalog);
} catch (error) {
if (error instanceof DOMException && error.name === "AbortError") return;
throw error;
}
});
editor.subscriptions.subscribeFrontendMessage("TriggerFontDataLoad", async (data) => {
subscriptions.subscribeFrontendMessage("TriggerFontDataLoad", async (data) => {
const { fontFamily, fontStyle } = data.font;
try {
@@ -48,7 +51,7 @@ export function createFontsManager(editor: Editor) {
const buffer = await response.arrayBuffer();
const bytes = new Uint8Array(buffer);
editor.handle.onFontLoad(fontFamily, fontStyle, bytes);
editor.onFontLoad(fontFamily, fontStyle, bytes);
} catch (error) {
if (error instanceof DOMException && error.name === "AbortError") return;
// eslint-disable-next-line no-console
@@ -58,15 +61,15 @@ export function createFontsManager(editor: Editor) {
}
export function destroyFontsManager() {
const editor = editorRef;
if (!editor) return;
const subscriptions = subscriptionsRouter;
if (!subscriptions) return;
abortController?.abort();
editor.subscriptions.unsubscribeFrontendMessage("TriggerFontCatalogLoad");
editor.subscriptions.unsubscribeFrontendMessage("TriggerFontDataLoad");
subscriptions.unsubscribeFrontendMessage("TriggerFontCatalogLoad");
subscriptions.unsubscribeFrontendMessage("TriggerFontDataLoad");
}
// Self-accepting HMR: tear down the old instance and re-create with the new module's code
import.meta.hot?.accept((newModule) => {
if (editorRef) newModule?.createFontsManager(editorRef);
if (subscriptionsRouter && editorHandle) newModule?.createFontsManager(subscriptionsRouter, editorHandle);
});