Skip to content

Custom Reference Integration

Many deployments need to display a local catalog of references, highlight citations as authors select them, and sync back to an external service. This guide distills the moving parts so you can recreate the pattern in your own UI.

Data Flow

  1. Host app owns the reference list (from your API, CSL store, etc.).
  2. Editor emits events (editor-change, editor-selection-change) whenever the document or selection changes.
  3. Sidebar components render references, highlight matches, and dispatch drag/drop or click events back to the editor.

Step-by-Step

1. Render Your Reference Panel

Create a list component (plain DOM or framework) that exposes two methods:

  • render(references: Array<{ id: string; rawCitation: string; mimeType?: string }>)
  • highlight(ids: string[])

Start with static markup and evolve it as needed; no special helpers are required from the package.

2. Listen for Document Updates

editor.addEventListener('editor-change', (event) => {
  const { doc } = event.detail;
  latestDoc = doc;
  panel.render(resolveReferences(doc));
});

resolveReferences is your hook to fetch or derive metadata (CSL JSON, raw citations, etc.).

3. Highlight References Based on Selection

Selection-aware highlighting will be exposed through a supported API in a future release. Avoid reaching into the ProseMirror view; for now, trigger panel.highlight(ids) from your own UI interactions (e.g., when a user clicks a reference in your panel) or keep it disabled.

4. Support Drag-and-Drop Insertion

Use a consistent drag payload so the citation feature can consume it automatically:

transfer.setData('application/x-sciflow-reference', 'sidebar');
transfer.setData('application/json', JSON.stringify({
  type: 'reference',
  id: reference.id,
  text: reference.rawCitation,
}));

The citation feature automatically consumes this payload via the drop handler in packages/editor/core/src/lib/features/citation/index.ts, calling runInsertCitation. Reuse the same MIME types so no extra work is required in the editor.

Optional: Programmatic Insertion

If you prefer buttons or menus to drag-and-drop:

const insertCitation = editor.commands?.commands?.insertCitation;
if (insertCitation) {
  insertCitation({
    items: [{ id: 'reference-1' }],
    text: '[1]',
    style: 'apa',
  });
}

Async lookups

Resolve metadata (authors, titles) before calling the command. The editor only stores what you send in text plus whatever you include in the node attributes.