Integrating with Glide Data Grid
While Titan Engine is UI-agnostic, it was architected from the ground up to pair flawlessly with Glide Data Grid. Together, they provide Excel-level performance in a standard web browser.
The Architecture Match
Glide Data Grid expects you to provide a `getCellContent` callback that fires rapidly (often at 60fps while scrolling). If this callback triggers heavy JS calculations, the scroll frame drops.
Titan solves this through Zero-Copy Memory Access. When Glide calls `getCellContent`, Titan immediately reads the cached computed state directly from WebAssembly linear memory without executing any formula logic.
Tutorial: The Integration Loop
Here is the standard pattern for marrying the two tools using React:
import React, { useState, useEffect, useCallback, useRef } from 'react';
import { DataEditor, GridCellKind } from '@glideapps/glide-data-grid';
import { initTitan } from 'titan-engine';
export default function Spreadsheet() {
const [engine, setEngine] = useState(null);
const [sheet, setSheet] = useState(null);
// We use a trigger to force React to re-render Glide when WASM recalculates
const [updateTrigger, setUpdateTrigger] = useState(0);
// 1. Initialize Titan on Mount
useEffect(() => {
initTitan().then(Titan => {
const e = new Titan();
const s = e.addSheet("Sheet1");
// Listen for calculation cycle completions
e.onCellsChanged((changes) => {
setUpdateTrigger(prev => prev + 1);
});
setEngine(e);
setSheet(s);
});
}, []);
// 2. Feed Data to Glide
const getCellContent = useCallback(([col, row]) => {
if (!sheet) return { kind: GridCellKind.Text, displayData: "", data: "" };
// Fast O(1) read from WASM memory boundary (supports {row, col} format)
const cell = sheet.get({ row, col });
return {
kind: GridCellKind.Text,
allowOverlay: true,
displayData: cell.display.toString(),
data: cell.display.toString(),
};
}, [sheet, updateTrigger]);
// 3. Send Edits to Titan via Debounced Batching
const editQueue = useRef([]);
const editTimeout = useRef(null);
const onCellEdited = useCallback((cell, newValue) => {
const [col, row] = cell;
// Queue the edit
editQueue.current.push({
sheet: sheet.id,
cell: {row, col},
value: newValue.data
});
// Debounce to batch multiple rapid edits (e.g. Pasting)
if (editTimeout.current) clearTimeout(editTimeout.current);
editTimeout.current = setTimeout(() => {
engine.setCells(editQueue.current);
editQueue.current = [];
}, 10);
}, [engine, sheet]);
if (!sheet) return Loading Engine...;
return (
<DataEditor
columns={[{ title: "A" }, { title: "B" }, { title: "C" }]}
rows={100}
getCellContent={getCellContent}
onCellEdited={onCellEdited}
/>
);
}