import { type ReactNode } from 'react'; import { editableValue, isComputed, type ColumnMeta, type Row } from '@wellformed/shared'; import { useRows } from '../api/hooks'; import { useI18n } from '../i18n'; import { useWorkspace } from '../state/workspace'; import { useCurrency } from '../state/session'; import { typeMark } from './Icons'; /** * The address-and-value strip above the grid. It reads; it does not write. * * It used to offer a text field for every column, which is a promise this * product cannot keep: a select, a date, a checkbox and a link each have a * shape, and a bare text box can only send something the server then has to * refuse — after a round trip, with the typing thrown away. Matching the cell * editor's controls here would mean building that editor a second time, so * writing stays in the cell, where every type already has the right control. * * What is left is what only this strip can say: which cell you are in, the * whole of a value too long for its column, and — for a computed column — the * expression the database is actually evaluating. */ export function FormulaBar(): ReactNode { const ws = useWorkspace(); const currency = useCurrency(); const { t } = useI18n(); const { rows } = useRows({ table: ws.tableName, viewId: ws.viewId, filters: ws.adHocFilters, sort: ws.sortOverride, hidden: ws.hiddenOverride, search: ws.search, enabled: Boolean(ws.tableName), }); const selection = ws.selection; const column = ws.table?.columns.find((c) => c.name === selection?.col); const row = rows.find((r) => r.id === selection?.rowId); const computed = column ? isComputed(column.type) : false; // A link's stored value is a row id. Showing it here would contradict the // grid, which names the row, so this strip names it too. const isLink = column?.type === 'link'; const stored = column && row ? editableValue(row.values[column.name] ?? null) : ''; const shown = computed && column ? `= ${column.expr ?? ''}` : isLink ? linkLabel(row, column) : stored; const rowLabel = describeRow(row, ws.table?.display); const address = selection ? `${ws.tableName}!${selection.col} · ${rowLabel}` : t('grid.noSelection'); // With nothing selected the strip has nothing to address, but it keeps its // row: collapsing it moved the grid up under the pointer, so the click that // selected the first cell dropped the header onto the row you were aiming // at — and a double-click to edit sorted the table instead. return (