import { useState, useRef, useEffect, useLayoutEffect } from "react"; import { createPortal } from "react-dom"; export interface FkOption { value: string; // the referenced column's value (what gets committed) label: string; // fallback display text (e.g. "42 — Alice") /** Referenced row cells shown in one row (≤5 columns), FK-reference style. */ cells?: { name: string; value: string }[]; } const MAX_FK_CELLS = 4; const FK_DROPDOWN_WIDTH = 360; interface CellEditorProps { initialValue: string; dataType: string; nullable?: boolean; enumValues?: string[]; // when present → render commitRaw(e.target.value)} onKeyDown={(e) => { if (e.key === "Escape") { e.preventDefault(); onCancel(); } }} > {enumValues.map((v) => ( ))} {errorBubble} ); } if (fkOptions && fkOptions.length > 0) { const q = query.trim().toLowerCase(); const fkSearchText = (o: FkOption) => [ o.label, ...(o.cells ?? []).map((c) => `${c.name}:${c.value}`), ] .join(" ") .toLowerCase(); const filtered = q === "" ? fkOptions : fkOptions.filter((o) => fkSearchText(o).includes(q)); return (
{ setQuery(e.target.value); setError(null); }} onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); if (filtered.length > 0) commitRaw(filtered[0].value); else commitRaw(query); } else if (e.key === "Escape") { e.preventDefault(); onCancel(); } }} /> {fkDropdownPos && createPortal(
{nullable && ( )} {filtered.length === 0 && (
No matches
)} {filtered.map((o) => ( ))}
, document.body, )} {errorBubble}
); } const cls = large ? `${inputClass} h-4 resize-none overflow-y-auto whitespace-pre leading-none py-0.5` : inputClass; return (
{ setValue(e.target.value); setError(null); }} onKeyDown={(e) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); commit(); } else if (e.key === "Escape") { e.preventDefault(); onCancel(); } }} /> {errorBubble}
); }