@pixerate/editor-react 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/spreadsheet/useSpreadsheetEditor.ts","../src/spreadsheet/SpreadsheetEditor.tsx","../src/spreadsheet/SpreadsheetContextMenu.tsx","../src/spreadsheet/SpreadsheetGroupRow.tsx","../src/spreadsheet/useSpreadsheetTableInteractions.ts","../src/spreadsheet/FormulaHints.tsx"],"sourcesContent":["import { useState, useRef, useCallback, useMemo } from 'react';\nimport {\n SpreadsheetController,\n bindSpreadsheetTableActions,\n type SpreadsheetControllerOptions,\n type SpreadsheetDocument,\n type CellCoordinate,\n type CellRange,\n type SpreadsheetColumn,\n type SpreadsheetRow,\n type SpreadsheetDataSource\n} from '@pixerate/editor/spreadsheet';\n\nexport function useSpreadsheetEditor(options: SpreadsheetControllerOptions = {}) {\n // Callbacks are read through a ref so they are never stale.\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const settersRef = useRef<{\n setDoc?: (doc: SpreadsheetDocument) => void;\n setActiveCell?: (cell: CellCoordinate | null) => void;\n setSelectedRange?: (range: CellRange | null) => void;\n }>({});\n\n // Create the controller first so the initial state reflects its document\n // (including default rows and columns when no document is passed).\n const [controller] = useState(\n () =>\n new SpreadsheetController({\n ...options,\n onDocumentChange: (updated) => {\n settersRef.current.setDoc?.({ ...updated });\n optionsRef.current.onDocumentChange?.(updated);\n },\n onSelectionChange: (active, range) => {\n settersRef.current.setActiveCell?.(active);\n settersRef.current.setSelectedRange?.(range);\n optionsRef.current.onSelectionChange?.(active, range);\n },\n onCellCommit: (rowId, colId, raw, value) => {\n optionsRef.current.onCellCommit?.(rowId, colId, raw, value);\n },\n }),\n );\n\n const [doc, setDoc] = useState<SpreadsheetDocument>(() => ({ ...controller.document }));\n const [activeCell, setActiveCell] = useState<CellCoordinate | null>(controller.activeCell);\n const [selectedRange, setSelectedRange] = useState<CellRange | null>(controller.selectedRange);\n const [editingCell, setEditingCell] = useState<CellCoordinate | null>(null);\n const [draftValue, setDraftValue] = useState<string>('');\n settersRef.current = { setDoc, setActiveCell, setSelectedRange };\n\n const setCellValue = useCallback((rowId: string, colId: string, raw: string) => {\n controller.setCellValue(rowId, colId, raw);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const selectCell = useCallback((row: number, col: number, extendSelection = false) => {\n controller.selectCell(row, col, extendSelection);\n setActiveCell(controller.activeCell);\n setSelectedRange(controller.selectedRange);\n }, [controller]);\n\n const selectRange = useCallback((range: CellRange) => {\n controller.selectRange(range);\n setSelectedRange(controller.selectedRange);\n }, [controller]);\n\n const startEditing = useCallback((row?: number, col?: number, initialVal?: string) => {\n controller.startEditing(row, col, initialVal);\n setActiveCell(controller.activeCell);\n setEditingCell(controller.editingCell);\n setDraftValue(controller.draftValue);\n }, [controller]);\n\n const commitEditing = useCallback((val?: string) => {\n controller.commitEditing(val);\n setEditingCell(null);\n setDraftValue('');\n setDoc({ ...controller.document });\n }, [controller]);\n\n const cancelEditing = useCallback(() => {\n controller.cancelEditing();\n setEditingCell(null);\n setDraftValue('');\n }, [controller]);\n\n const moveCursor = useCallback((dir: 'up' | 'down' | 'left' | 'right', extend = false) => {\n controller.moveCursor(dir, extend);\n setActiveCell(controller.activeCell);\n setSelectedRange(controller.selectedRange);\n }, [controller]);\n\n const insertColumn = useCallback((index: number, config?: Partial<SpreadsheetColumn>) => {\n controller.insertColumn(index, config);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const deleteColumn = useCallback((colId: string) => {\n controller.deleteColumn(colId);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const insertRow = useCallback((index: number, config?: Partial<SpreadsheetRow>) => {\n controller.insertRow(index, config);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const deleteRow = useCallback((rowId: string) => {\n controller.deleteRow(rowId);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const setColumnWidth = useCallback((colId: string, width: number) => {\n controller.setColumnWidth(colId, width);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const autoFitColumnWidth = useCallback((colId: string, customWidth?: number) => {\n controller.autoFitColumnWidth(colId, customWidth);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const registerDataSource = useCallback((ds: SpreadsheetDataSource) => {\n controller.registerDataSource(ds);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const setPrimaryDataSource = useCallback((id: string | undefined) => {\n controller.setPrimaryDataSource(id);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const recalculateAll = useCallback(() => {\n controller.recalculateAll();\n setDoc({ ...controller.document });\n }, [controller]);\n\n const undo = useCallback(() => {\n controller.undo();\n setDoc({ ...controller.document });\n }, [controller]);\n\n const redo = useCallback(() => {\n controller.redo();\n setDoc({ ...controller.document });\n }, [controller]);\n\n // Table operations (sort, filters, freeze, hide, merge, autofill, categories,\n // transpose, CSV, clipboard). The controller reports their changes through\n // onDocumentChange / onSelectionChange, which update the state above.\n const tableActions = useMemo(() => bindSpreadsheetTableActions(controller), [controller]);\n // What to render: visible rows (with group headers) and columns, frozen\n // offsets and merged-cell spans. Recomputed whenever the document changes.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const viewModel = useMemo(() => controller.getViewModel(), [controller, doc]);\n\n return {\n document: doc,\n activeCell,\n selectedRange,\n editingCell,\n draftValue,\n setDraftValue,\n controller,\n getCell: (rowId: string, colId: string) => controller.getCell(rowId, colId),\n setCellValue,\n selectCell,\n selectRange,\n startEditing,\n commitEditing,\n cancelEditing,\n moveCursor,\n insertColumn,\n deleteColumn,\n insertRow,\n deleteRow,\n setColumnWidth,\n autoFitColumnWidth,\n loadDocument: (document: SpreadsheetDocument) => {\n controller.loadDocument(document);\n setDoc({ ...controller.document });\n setActiveCell(null);\n setSelectedRange(null);\n setEditingCell(null);\n setDraftValue('');\n },\n syncWithDataSource: () => {\n controller.syncWithDataSource();\n controller.recalculateAll();\n setDoc({ ...controller.document });\n },\n registerDataSource,\n setPrimaryDataSource,\n recalculateAll,\n exportToTsv: (range?: CellRange | null) => controller.exportToTsv(range),\n importFromTsv: (data: string) => {\n controller.importFromTsv(data);\n setDoc({ ...controller.document });\n },\n ...tableActions,\n viewModel,\n undo,\n redo\n };\n}\n","import React, { useRef, useState, useMemo, useEffect, useCallback } from 'react';\nimport {\n indexToColName,\n getSpreadsheetMenuItems,\n normalizeRange,\n rangeContains,\n type SpreadsheetColumn,\n type SpreadsheetRow,\n type CellData,\n type SpreadsheetMenuItem,\n type SpreadsheetViewColumn,\n type SpreadsheetViewRow\n} from '@pixerate/editor/spreadsheet';\nimport { useSpreadsheetEditor } from './useSpreadsheetEditor';\nimport { SpreadsheetContextMenu } from './SpreadsheetContextMenu';\nimport { SpreadsheetGroupRow } from './SpreadsheetGroupRow';\nimport { useFillHandle, useSpreadsheetClipboard } from './useSpreadsheetTableInteractions';\n\n// Sizes of the sticky header row and row-number column, for frozen-pane offsets.\nconst COLUMN_HEADER_HEIGHT = 28;\nconst ROW_HEADER_WIDTH = 48;\n\n/** Sticky positioning for cells in frozen rows and/or columns. */\nfunction frozenCellStyle(\n viewRow: Extract<SpreadsheetViewRow, { kind: 'row' }>,\n viewCol: SpreadsheetViewColumn\n): React.CSSProperties | undefined {\n if (!viewRow.frozen && !viewCol.frozen) return undefined;\n return {\n position: 'sticky',\n ...(viewRow.frozen ? { top: COLUMN_HEADER_HEIGHT + viewRow.stickyTop } : {}),\n ...(viewCol.frozen ? { left: ROW_HEADER_WIDTH + viewCol.stickyLeft } : {}),\n zIndex: viewRow.frozen && viewCol.frozen ? 14 : viewRow.frozen ? 12 : 11,\n background: 'var(--background, #fff)'\n };\n}\nimport { FormulaHints } from './FormulaHints';\n\nexport interface SpreadsheetEditorProps {\n state?: ReturnType<typeof useSpreadsheetEditor>;\n readOnly?: boolean;\n customCellRenderer?: (props: { row: SpreadsheetRow; col: SpreadsheetColumn; cell: CellData }) => React.ReactNode;\n onAddColumnClick?: () => void;\n onColumnHeaderClick?: (col: SpreadsheetColumn) => void;\n onColumnResize?: (colId: string, width: number) => void;\n}\n\nexport const SpreadsheetEditor: React.FC<SpreadsheetEditorProps> = ({\n state: externalState,\n readOnly = false,\n customCellRenderer,\n onAddColumnClick,\n onColumnHeaderClick,\n onColumnResize\n}) => {\n const defaultState = useSpreadsheetEditor();\n const state = externalState || defaultState;\n const gridRef = useRef<HTMLDivElement>(null);\n const formulaBarRef = useRef<HTMLInputElement>(null);\n const cellInputRef = useRef<HTMLInputElement>(null);\n\n const [resizingColId, setResizingColId] = useState<string | null>(null);\n const [hoveredColId, setHoveredColId] = useState<string | null>(null);\n const [resizeStartX, setResizeStartX] = useState(0);\n const [resizeStartWidth, setResizeStartWidth] = useState(0);\n\n // Table operations: render model, clipboard, fill handle and context menu.\n const view = state.viewModel;\n const { copyShortcutFallback } = useSpreadsheetClipboard(gridRef, state, readOnly);\n const { fillTarget, startFill, extendFill } = useFillHandle(state);\n const [menu, setMenu] = useState<{ x: number; y: number; items: SpreadsheetMenuItem[] } | null>(null);\n const filter = state.document.table?.filter;\n const filteredColIds = useMemo(\n () => new Set(filter?.enabled ? filter.rules.map((r) => r.colId) : []),\n [filter]\n );\n\n const handleCellContextMenu = useCallback((rIdx: number, cIdx: number, e: React.MouseEvent) => {\n if (readOnly) return;\n e.preventDefault();\n if (state.editingCell) state.commitEditing();\n if (!state.selectedRange || !rangeContains(state.selectedRange, rIdx, cIdx)) {\n state.selectCell(rIdx, cIdx);\n }\n setMenu({ x: e.clientX, y: e.clientY, items: getSpreadsheetMenuItems(state.controller, { row: rIdx, col: cIdx }) });\n }, [readOnly, state]);\n\n const activeRawValue = useMemo(() => {\n if (!state.activeCell) return '';\n const row = state.document.rows[state.activeCell.row];\n const col = state.document.columns[state.activeCell.col];\n if (!row || !col) return '';\n return state.getCell(row.id, col.id).raw;\n }, [state.activeCell, state.document]);\n\n const coordLabel = useMemo(() => {\n if (!state.activeCell) return '--';\n const colName = indexToColName(state.activeCell.col);\n return `${colName}${state.activeCell.row + 1}`;\n }, [state.activeCell]);\n\n // Text typed in the formula bar while no cell editor is open.\n const [formulaDraft, setFormulaDraft] = useState<string | null>(null);\n const activeColumn = state.activeCell ? state.document.columns[state.activeCell.col] : undefined;\n const formulaBarReadOnly = readOnly || !state.activeCell || !!activeColumn?.readOnly;\n\n useEffect(() => {\n setFormulaDraft(null);\n }, [state.activeCell?.row, state.activeCell?.col]);\n\n const commitFormulaBar = () => {\n if (state.editingCell) {\n state.commitEditing();\n return;\n }\n if (formulaDraft === null || !state.activeCell) return;\n const row = state.document.rows[state.activeCell.row];\n const col = state.document.columns[state.activeCell.col];\n if (row && col && !formulaBarReadOnly && formulaDraft !== activeRawValue) {\n state.setCellValue(row.id, col.id, formulaDraft);\n }\n setFormulaDraft(null);\n };\n\n const handleCellClick = useCallback((rIdx: number, cIdx: number, e: React.MouseEvent) => {\n if (state.editingCell && (state.editingCell.row !== rIdx || state.editingCell.col !== cIdx)) {\n state.commitEditing();\n }\n state.selectCell(rIdx, cIdx, e.shiftKey);\n }, [state]);\n\n const handleCellDblClick = useCallback((rIdx: number, cIdx: number) => {\n if (readOnly) return;\n const col = state.document.columns[cIdx];\n if (col?.readOnly) return;\n state.startEditing(rIdx, cIdx);\n }, [readOnly, state]);\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent) => {\n if (state.editingCell) {\n if (e.key === 'Enter') {\n e.preventDefault();\n state.commitEditing();\n state.moveCursor('down');\n } else if (e.key === 'Escape') {\n e.preventDefault();\n state.cancelEditing();\n } else if (e.key === 'Tab') {\n e.preventDefault();\n state.commitEditing();\n state.moveCursor(e.shiftKey ? 'left' : 'right');\n }\n return;\n }\n\n if (!state.activeCell) return;\n\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n state.moveCursor('up', e.shiftKey);\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n state.moveCursor('down', e.shiftKey);\n } else if (e.key === 'ArrowLeft') {\n e.preventDefault();\n state.moveCursor('left', e.shiftKey);\n } else if (e.key === 'ArrowRight') {\n e.preventDefault();\n state.moveCursor('right', e.shiftKey);\n } else if (e.key === 'Tab') {\n e.preventDefault();\n state.moveCursor(e.shiftKey ? 'left' : 'right');\n } else if (e.key === 'Enter') {\n e.preventDefault();\n const col = state.document.columns[state.activeCell.col];\n if (!readOnly && !col?.readOnly) {\n state.startEditing();\n }\n } else if (e.key === 'Backspace' || e.key === 'Delete') {\n if (readOnly) return;\n const row = state.document.rows[state.activeCell.row];\n const col = state.document.columns[state.activeCell.col];\n if (row && col && !col.readOnly) {\n e.preventDefault();\n state.setCellValue(row.id, col.id, '');\n }\n } else if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'z') {\n // With Shift held, e.key is 'Z'.\n e.preventDefault();\n if (e.shiftKey) {\n state.redo();\n } else {\n state.undo();\n }\n } else if (e.ctrlKey && !e.metaKey && e.key.toLowerCase() === 'y') {\n e.preventDefault();\n state.redo();\n } else if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'c') {\n // Copy the selection, not the whole sheet. The browser's copy event\n // writes TSV, HTML and the internal format; the fallback writes TSV.\n copyShortcutFallback();\n } else if (!readOnly && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {\n const col = state.document.columns[state.activeCell.col];\n if (!col?.readOnly) {\n state.startEditing(state.activeCell.row, state.activeCell.col, e.key);\n }\n }\n }, [readOnly, state, copyShortcutFallback]);\n // The resize effect reads these through refs: re-running it on every width\n // update would reset the in-progress drag (and skip onColumnResize).\n const stateRef = useRef(state);\n stateRef.current = state;\n const onColumnResizeRef = useRef(onColumnResize);\n onColumnResizeRef.current = onColumnResize;\n\n useEffect(() => {\n if (!resizingColId) return;\n\n if (typeof document !== 'undefined') {\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n }\n\n let rafId: number | null = null;\n let pendingWidth = resizeStartWidth;\n let hasDragged = false;\n\n const handleMouseMove = (e: MouseEvent) => {\n const delta = e.clientX - resizeStartX;\n if (Math.abs(delta) > 2) {\n hasDragged = true;\n }\n pendingWidth = Math.max(30, resizeStartWidth + delta);\n\n if (rafId === null) {\n rafId = requestAnimationFrame(() => {\n rafId = null;\n stateRef.current.setColumnWidth(resizingColId, pendingWidth);\n });\n }\n };\n\n const handleMouseUp = () => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n if (hasDragged) {\n stateRef.current.setColumnWidth(resizingColId, pendingWidth);\n onColumnResizeRef.current?.(resizingColId, pendingWidth);\n }\n setResizingColId(null);\n if (typeof document !== 'undefined') {\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n }\n };\n\n window.addEventListener('mousemove', handleMouseMove);\n window.addEventListener('mouseup', handleMouseUp);\n return () => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n }\n if (typeof document !== 'undefined') {\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n }\n window.removeEventListener('mousemove', handleMouseMove);\n window.removeEventListener('mouseup', handleMouseUp);\n };\n }, [resizingColId, resizeStartX, resizeStartWidth]);\n\n const measureElementContentWidth = useCallback((el: HTMLElement, container: HTMLElement): number => {\n if (typeof document === 'undefined') return 0;\n\n let maxW = el.scrollWidth || 0;\n const firstChild = el.firstElementChild as HTMLElement | null;\n if (firstChild && firstChild.scrollWidth > maxW) {\n maxW = firstChild.scrollWidth;\n }\n\n const truncated = el.querySelectorAll<HTMLElement>('.truncate, [title], span, div');\n truncated.forEach((node) => {\n if (node.scrollWidth > maxW) {\n maxW = node.scrollWidth;\n }\n });\n\n try {\n const clone = (firstChild ? firstChild.cloneNode(true) : el.cloneNode(true)) as HTMLElement;\n clone.style.cssText = `\n position: absolute !important;\n visibility: hidden !important;\n width: max-content !important;\n min-width: max-content !important;\n max-width: none !important;\n overflow: visible !important;\n white-space: nowrap !important;\n pointer-events: none !important;\n top: -9999px !important;\n left: -9999px !important;\n `;\n\n const allNodes = clone.querySelectorAll<HTMLElement>('*');\n allNodes.forEach((node) => {\n node.style.maxWidth = 'none';\n node.style.overflow = 'visible';\n node.style.textOverflow = 'clip';\n node.style.whiteSpace = 'nowrap';\n if (\n node.classList.contains('truncate') ||\n node.classList.contains('min-w-0') ||\n node.classList.contains('w-full') ||\n node.classList.contains('max-w-0') ||\n node.classList.contains('flex-1')\n ) {\n node.style.width = 'max-content';\n node.style.minWidth = 'max-content';\n }\n });\n\n container.appendChild(clone);\n const rect = clone.getBoundingClientRect();\n container.removeChild(clone);\n\n if (rect.width > maxW) {\n maxW = rect.width;\n }\n } catch {\n // Ignore cloning/measuring errors\n }\n\n return maxW;\n }, []);\n\n const autoFitColumn = useCallback((colId: string, colIndex: number) => {\n const col = state.document.columns.find((c) => c.id === colId);\n if (!col) return;\n\n let calculatedWidth = 0;\n\n if (gridRef.current && typeof document !== 'undefined') {\n const table = gridRef.current.querySelector('table');\n if (table) {\n // Look cells up by column index: hidden columns and merges shift DOM positions.\n const th = table.querySelector(`thead th[data-col=\"${colIndex}\"]`) as HTMLElement | null;\n if (th) {\n const headerInner = (th.firstElementChild as HTMLElement) || th;\n const headerW = measureElementContentWidth(headerInner, gridRef.current);\n calculatedWidth = Math.max(calculatedWidth, headerW + 28);\n }\n\n const rows = table.querySelectorAll('tbody tr');\n const sampleLimit = Math.min(rows.length, 150);\n for (let r = 0; r < sampleLimit; r++) {\n const tr = rows[r];\n const td = tr.querySelector(`td[data-col=\"${colIndex}\"][colspan=\"1\"]`) as HTMLElement | null;\n if (td) {\n const cellW = measureElementContentWidth(td, gridRef.current);\n calculatedWidth = Math.max(calculatedWidth, cellW + 20);\n }\n }\n }\n }\n\n if (calculatedWidth > 0) {\n const finalWidth = Math.min(600, Math.max(50, Math.ceil(calculatedWidth)));\n state.setColumnWidth(colId, finalWidth);\n } else {\n state.autoFitColumnWidth?.(colId);\n }\n\n const updatedCol = state.document.columns.find((c) => c.id === colId);\n if (updatedCol && onColumnResize) {\n onColumnResize(updatedCol.id, updatedCol.width || 130);\n }\n }, [state, measureElementContentWidth, onColumnResize]);\n\n const handleResizeDblClick = useCallback((colId: string, colIndex: number, e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n autoFitColumn(colId, colIndex);\n }, [autoFitColumn]);\n\n const handleHeaderDblClick = useCallback((colId: string, colIndex: number, e: React.MouseEvent) => {\n const target = e.currentTarget as HTMLElement | null;\n if (target) {\n const rect = target.getBoundingClientRect();\n if (rect.right - e.clientX <= 12) {\n e.preventDefault();\n e.stopPropagation();\n autoFitColumn(colId, colIndex);\n }\n }\n }, [autoFitColumn]);\n\n const isCellSelected = (rIdx: number, cIdx: number) => {\n if (!state.selectedRange) return false;\n const minR = Math.min(state.selectedRange.startRow, state.selectedRange.endRow);\n const maxR = Math.max(state.selectedRange.startRow, state.selectedRange.endRow);\n const minC = Math.min(state.selectedRange.startCol, state.selectedRange.endCol);\n const maxC = Math.max(state.selectedRange.startCol, state.selectedRange.endCol);\n return rIdx >= minR && rIdx <= maxR && cIdx >= minC && cIdx <= maxC;\n };\n\n const isActiveCell = (rIdx: number, cIdx: number) => {\n return state.activeCell?.row === rIdx && state.activeCell?.col === cIdx;\n };\n\n return (\n <div\n ref={gridRef}\n className=\"flex flex-col h-full w-full overflow-hidden border border-border bg-background select-none outline-none text-foreground font-sans text-xs\"\n tabIndex={0}\n onKeyDown={handleKeyDown}\n role=\"grid\"\n aria-label=\"Spreadsheet\"\n >\n {/* Formula Bar */}\n <div className=\"flex items-center gap-2 border-b border-border bg-muted/20 px-3 py-1.5 text-xs font-mono\">\n <div className=\"flex h-6 min-w-[3rem] items-center justify-center rounded border border-border bg-background px-1.5 font-semibold text-foreground\">\n {coordLabel}\n </div>\n <div className=\"flex items-center text-muted-foreground select-none\">\n <span className=\"italic font-serif font-bold text-sm text-primary\">fx</span>\n </div>\n <input\n ref={formulaBarRef}\n type=\"text\"\n className=\"flex-1 bg-transparent px-2 py-0.5 outline-none font-sans text-xs text-foreground placeholder:text-muted-foreground/60 focus:bg-background focus:ring-1 focus:ring-primary rounded\"\n placeholder=\"Enter a value or formula (e.g. =SUM(A1:A5))\"\n aria-label=\"Formula bar\"\n readOnly={formulaBarReadOnly}\n value={state.editingCell ? state.draftValue : formulaDraft ?? activeRawValue}\n onFocus={() => {\n if (!state.editingCell) setFormulaDraft(activeRawValue);\n }}\n onChange={(e) => {\n if (state.editingCell) {\n state.setDraftValue(e.target.value);\n } else if (state.activeCell) {\n setFormulaDraft(e.target.value);\n }\n }}\n onBlur={() => commitFormulaBar()}\n onKeyDown={(e) => {\n // Keys typed here must not reach the grid's navigation handler.\n e.stopPropagation();\n if (e.key === 'Enter') {\n e.preventDefault();\n commitFormulaBar();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n setFormulaDraft(null);\n if (state.editingCell) state.cancelEditing();\n }\n }}\n />\n {!formulaBarReadOnly && (\n <FormulaHints\n inputRef={formulaBarRef}\n value={state.editingCell ? state.draftValue : formulaDraft ?? activeRawValue}\n onAccept={(next) => (state.editingCell ? state.setDraftValue(next) : setFormulaDraft(next))}\n />\n )}\n </div>\n\n {/* Main Grid */}\n <div className=\"relative flex-1 overflow-auto\">\n <table className=\"border-collapse table-fixed w-max min-w-full\">\n <thead>\n <tr className=\"h-7 bg-muted/60 sticky top-0 z-20 border-b border-border shadow-xs\">\n <th className=\"w-12 min-w-[3rem] sticky left-0 z-30 bg-muted/90 border-r border-border text-center text-[10px] text-muted-foreground font-medium\">\n #\n </th>\n {view.columns.map(({ column: col, index: cIdx, frozen, stickyLeft }) => (\n <th\n key={col.id}\n data-col={cIdx}\n className={`relative border-r border-border px-2 text-left font-medium text-muted-foreground hover:bg-muted/90 transition-colors group overflow-hidden max-w-0 ${\n onColumnHeaderClick ? 'cursor-pointer' : 'cursor-default'\n }`}\n style={{\n width: col.width || 130,\n minWidth: col.width || 130,\n maxWidth: col.width || 130,\n overflow: 'hidden',\n ...(frozen ? { position: 'sticky', left: ROW_HEADER_WIDTH + stickyLeft, zIndex: 25, background: 'var(--muted, #f4f4f5)' } : {})\n }}\n onClick={() => onColumnHeaderClick?.(col)}\n onDoubleClick={(e) => handleHeaderDblClick(col.id, cIdx, e)}\n >\n <div className=\"flex items-center justify-between gap-1 min-w-0 overflow-hidden truncate\">\n <span className=\"truncate font-semibold text-foreground text-xs min-w-0\">{col.title}</span>\n {filteredColIds.has(col.id) && (\n <span className=\"text-[10px] text-primary shrink-0\" title=\"Filtered\" data-filtered=\"true\">⏷</span>\n )}\n <span className=\"text-[10px] text-muted-foreground/70 font-mono font-normal shrink-0\">({col.key})</span>\n </div>\n {/* Column Resize Handle */}\n <div\n className=\"col-resize-handle\"\n style={{ position: 'absolute', top: 0, bottom: 0, width: 12, right: -6, cursor: 'col-resize', zIndex: 20, display: 'flex', justifyContent: 'center', touchAction: 'none' }}\n onMouseEnter={() => setHoveredColId(col.id)}\n onMouseLeave={() => setHoveredColId((cur) => cur === col.id ? null : cur)}\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setResizingColId(col.id);\n setResizeStartX(e.clientX);\n setResizeStartWidth(col.width || 130);\n }}\n onDoubleClick={(e) => handleResizeDblClick(col.id, cIdx, e)}\n role=\"separator\"\n aria-orientation=\"vertical\"\n >\n <div\n className=\"col-resize-handle-line\"\n style={{\n width: 2,\n height: '100%',\n pointerEvents: 'none',\n transition: 'background-color 150ms ease',\n backgroundColor: resizingColId === col.id ? 'var(--primary, #6366f1)' : hoveredColId === col.id ? 'color-mix(in srgb, var(--primary, #6366f1) 75%, transparent)' : 'transparent'\n }}\n />\n </div>\n </th>\n ))}\n {onAddColumnClick && (\n <th\n className=\"w-10 min-w-[2.5rem] px-1 text-center bg-muted/40 hover:bg-muted cursor-pointer transition-colors\"\n onClick={onAddColumnClick}\n title=\"Add Column\"\n >\n <span className=\"text-xs font-bold text-muted-foreground\">+</span>\n </th>\n )}\n </tr>\n </thead>\n <tbody>\n {view.rows.map((viewRow) => {\n if (viewRow.kind === 'group') {\n return (\n <SpreadsheetGroupRow\n key={`group:${viewRow.group.key}`}\n group={viewRow.group}\n columns={view.columns}\n groupColId={state.document.table?.grouping?.colId ?? ''}\n onToggle={state.toggleGroupCollapsed}\n trailingCell={!!onAddColumnClick}\n />\n );\n }\n const displayRowIndex = viewRow.index;\n const selection = state.selectedRange ? normalizeRange(state.selectedRange) : null;\n return (\n <tr\n key={viewRow.row.id}\n data-row={displayRowIndex}\n className={`border-b border-border hover:bg-muted/10 transition-colors ${viewRow.section !== 'body' ? 'bg-muted/30 font-semibold' : ''}`}\n style={{ height: viewRow.row.height || 32 }}\n >\n <td\n className=\"w-12 min-w-[3rem] sticky left-0 z-10 bg-muted/50 border-r border-border text-center text-[10px] text-muted-foreground font-mono select-none\"\n style={viewRow.frozen ? { top: COLUMN_HEADER_HEIGHT + viewRow.stickyTop, zIndex: 15 } : undefined}\n >\n {displayRowIndex + 1}\n </td>\n {view.columns.map((viewCol) => {\n // A merged cell renders its top-left cell, spanning the merge.\n const span = view.getCellSpan(displayRowIndex, viewCol.index);\n if (!span) return null;\n const rIdx = span.source.row;\n const cIdx = span.source.col;\n const row = state.document.rows[rIdx];\n const col = state.document.columns[cIdx];\n const cell = state.getCell(row.id, col.id);\n const selected = isCellSelected(rIdx, cIdx);\n const active = isActiveCell(rIdx, cIdx);\n const isEditing = state.editingCell?.row === rIdx && state.editingCell?.col === cIdx;\n\n const inFillPreview = !!fillTarget && !selected && rangeContains(fillTarget, displayRowIndex, viewCol.index);\n const showFillHandle =\n !readOnly &&\n !isEditing &&\n !!selection &&\n (span.merge\n ? rangeContains(span.merge, selection.endRow, selection.endCol)\n : selection.endRow === rIdx && selection.endCol === cIdx);\n\n return (\n <td\n key={viewCol.column.id}\n data-row={rIdx}\n data-col={cIdx}\n rowSpan={span.rowSpan}\n colSpan={span.colSpan}\n className={`relative border-r border-border px-2 py-1 truncate max-w-0 text-foreground transition-colors ${\n selected ? 'bg-primary/10' : ''\n } ${active ? 'ring-2 ring-primary ring-inset z-10' : ''} ${viewCol.header ? 'font-semibold' : ''}`}\n style={{\n maxWidth: 0,\n overflow: 'hidden',\n ...frozenCellStyle(viewRow, viewCol),\n ...(inFillPreview ? { outline: '1px dashed var(--primary, #6366f1)', outlineOffset: -1 } : {})\n }}\n onClick={(e) => handleCellClick(rIdx, cIdx, e)}\n onDoubleClick={() => handleCellDblClick(rIdx, cIdx)}\n onContextMenu={(e) => handleCellContextMenu(rIdx, cIdx, e)}\n onMouseOver={() => extendFill(displayRowIndex, viewCol.index)}\n >\n {isEditing ? (\n <>\n <input\n ref={cellInputRef}\n type=\"text\"\n className=\"absolute inset-0 w-full h-full px-2 py-1 bg-background text-foreground outline-none font-sans text-xs border-2 border-primary z-20\"\n value={state.draftValue}\n onChange={(e) => state.setDraftValue(e.target.value)}\n onBlur={() => state.commitEditing()}\n autoFocus\n />\n <FormulaHints inputRef={cellInputRef} value={state.draftValue} onAccept={state.setDraftValue} />\n </>\n ) : customCellRenderer ? (\n customCellRenderer({ row, col, cell })\n ) : (\n <span\n className={`truncate block max-w-full ${cell.error ? 'text-destructive font-semibold' : ''}`}\n title={cell.error ? cell.errorMessage ?? cell.error : undefined}\n >\n {cell.error || (cell.value ?? '')}\n </span>\n )}\n {showFillHandle && (\n <div\n className=\"spreadsheet-fill-handle\"\n aria-label=\"Fill handle\"\n onMouseDown={startFill}\n onClick={(e) => e.stopPropagation()}\n style={{ position: 'absolute', right: 0, bottom: 0, width: 7, height: 7, background: 'var(--primary, #6366f1)', cursor: 'crosshair', zIndex: 25 }}\n />\n )}\n </td>\n );\n })}\n {onAddColumnClick && <td className=\"w-10 min-w-[2.5rem] bg-muted/10 border-r border-border\" />}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n {menu && (\n <SpreadsheetContextMenu\n items={menu.items}\n x={menu.x}\n y={menu.y}\n onClose={() => {\n setMenu(null);\n gridRef.current?.focus();\n }}\n />\n )}\n <style>{`\n .col-resize-handle:hover .col-resize-handle-line {\n background-color: var(--primary, #6366f1);\n opacity: 0.75;\n }\n .col-resize-handle.active .col-resize-handle-line {\n background-color: var(--primary, #6366f1);\n opacity: 1;\n }\n table.table-fixed th {\n overflow: hidden;\n }\n table.table-fixed td {\n max-width: 0;\n overflow: hidden;\n }\n `}</style>\n </div>\n );\n};\n","import React, { useEffect, useRef } from 'react';\nimport type { SpreadsheetMenuItem } from '@pixerate/editor/spreadsheet';\n\nexport interface SpreadsheetContextMenuProps {\n items: SpreadsheetMenuItem[];\n x: number;\n y: number;\n onClose: () => void;\n}\n\n/** The table context menu (sort, filter, freeze, hide, merge, categories, transpose). */\nexport const SpreadsheetContextMenu: React.FC<SpreadsheetContextMenuProps> = ({ items, x, y, onClose }) => {\n const menuRef = useRef<HTMLDivElement>(null);\n const onCloseRef = useRef(onClose);\n onCloseRef.current = onClose;\n\n useEffect(() => {\n const handlePointer = (e: MouseEvent) => {\n if (!menuRef.current?.contains(e.target as Node)) onCloseRef.current();\n };\n const handleKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onCloseRef.current();\n };\n window.addEventListener('mousedown', handlePointer);\n window.addEventListener('keydown', handleKey);\n return () => {\n window.removeEventListener('mousedown', handlePointer);\n window.removeEventListener('keydown', handleKey);\n };\n }, []);\n\n return (\n <div\n ref={menuRef}\n role=\"menu\"\n aria-label=\"Table actions\"\n className=\"fixed z-50 min-w-[14rem] rounded-md border border-border bg-popover py-1 text-xs text-popover-foreground shadow-lg\"\n style={{ left: x, top: y, background: 'var(--popover, var(--background, #fff))' }}\n onContextMenu={(e) => e.preventDefault()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n {items.map((item) => (\n <React.Fragment key={item.id}>\n {item.separatorBefore && <div role=\"separator\" className=\"my-1 h-px bg-border\" />}\n <button\n type=\"button\"\n role=\"menuitem\"\n data-action={item.id}\n disabled={item.disabled}\n className=\"block w-full px-3 py-1 text-left hover:bg-muted disabled:cursor-default disabled:opacity-40 disabled:hover:bg-transparent\"\n onClick={() => {\n onClose();\n item.run();\n }}\n >\n {item.label}\n </button>\n </React.Fragment>\n ))}\n </div>\n );\n};\n","import React from 'react';\nimport type { SpreadsheetRowGroup, SpreadsheetViewColumn } from '@pixerate/editor/spreadsheet';\n\nexport interface SpreadsheetGroupRowProps {\n group: SpreadsheetRowGroup;\n columns: SpreadsheetViewColumn[];\n /** Column the rows are grouped by: shows the group label and toggle. */\n groupColId: string;\n onToggle: (key: string) => void;\n /** Render a trailing cell for the \"add column\" column. */\n trailingCell?: boolean;\n}\n\nconst formatSummary = (value: number | null) => (value === null ? '–' : String(value));\n\n/** A category header row: collapse toggle, label, row count and per-column summaries. */\nexport const SpreadsheetGroupRow: React.FC<SpreadsheetGroupRowProps> = ({\n group,\n columns,\n groupColId,\n onToggle,\n trailingCell\n}) => {\n // The label goes in the grouping column, or the first column when that one is hidden.\n const labelColId = columns.some((c) => c.column.id === groupColId) ? groupColId : columns[0]?.column.id;\n return (\n <tr className=\"border-b border-border bg-muted/40 font-semibold\" data-group-key={group.key} style={{ height: 28 }}>\n <td className=\"w-12 min-w-[3rem] sticky left-0 z-10 bg-muted/60 border-r border-border text-center\">\n <button\n type=\"button\"\n aria-label={`${group.collapsed ? 'Expand' : 'Collapse'} group ${group.label}`}\n aria-expanded={!group.collapsed}\n className=\"h-5 w-5 rounded text-[10px] text-muted-foreground hover:bg-muted\"\n onClick={(e) => {\n e.stopPropagation();\n onToggle(group.key);\n }}\n >\n {group.collapsed ? '▸' : '▾'}\n </button>\n </td>\n {columns.map(({ column }) => {\n const summary = group.summaries[column.id];\n return (\n <td key={column.id} className=\"border-r border-border px-2 py-1 truncate max-w-0 text-foreground\" style={{ maxWidth: 0, overflow: 'hidden' }}>\n {column.id === labelColId ? (\n <span className=\"truncate\">\n {group.label} <span className=\"font-normal text-muted-foreground\">({group.rowIndices.length})</span>\n </span>\n ) : summary !== undefined ? (\n <span className=\"truncate\" data-summary={column.id}>{formatSummary(summary)}</span>\n ) : null}\n </td>\n );\n })}\n {trailingCell && <td className=\"w-10 min-w-[2.5rem] bg-muted/10 border-r border-border\" />}\n </tr>\n );\n};\n","import { useCallback, useEffect, useRef, useState, type RefObject } from 'react';\nimport {\n computeFillTarget,\n normalizeRange,\n type CellRange\n} from '@pixerate/editor/spreadsheet';\nimport type { useSpreadsheetEditor } from './useSpreadsheetEditor';\n\ntype SpreadsheetState = ReturnType<typeof useSpreadsheetEditor>;\n\n/** True when focus is in the grid itself, not in a text input (cell editor, formula bar). */\nfunction gridHasFocus(grid: HTMLElement | null): boolean {\n if (!grid || typeof document === 'undefined') return false;\n const active = document.activeElement;\n if (!active || !grid.contains(active)) return false;\n return !(active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement);\n}\n\n/**\n * Copy and paste for the grid. Copy writes TSV, an HTML table and the\n * lossless `application/x.pixerate.spreadsheet+json` format; paste prefers\n * that format, then HTML, then TSV.\n *\n * The listeners are on `document`: with no text selection the browser fires\n * `copy`/`paste` at `<body>`, not at the focused grid. Text inputs inside the\n * grid keep native copy/paste.\n */\nexport function useSpreadsheetClipboard(\n gridRef: RefObject<HTMLElement | null>,\n state: SpreadsheetState,\n readOnly: boolean\n) {\n const stateRef = useRef(state);\n stateRef.current = state;\n const readOnlyRef = useRef(readOnly);\n readOnlyRef.current = readOnly;\n // Set when a copy event wrote the selection, so the keyboard fallback is skipped.\n const copiedRef = useRef(false);\n\n useEffect(() => {\n if (typeof document === 'undefined') return;\n const handleCopy = (e: ClipboardEvent) => {\n const s = stateRef.current;\n if (!gridHasFocus(gridRef.current) || s.editingCell || !e.clipboardData || !s.selectedRange) return;\n for (const [type, data] of Object.entries(s.copyToClipboardData(s.selectedRange))) {\n e.clipboardData.setData(type, data);\n }\n copiedRef.current = true;\n e.preventDefault();\n };\n const handlePaste = (e: ClipboardEvent) => {\n const s = stateRef.current;\n if (readOnlyRef.current || !gridHasFocus(gridRef.current) || s.editingCell || !e.clipboardData) return;\n if (s.pasteClipboardData(e.clipboardData)) e.preventDefault();\n };\n document.addEventListener('copy', handleCopy);\n document.addEventListener('paste', handlePaste);\n return () => {\n document.removeEventListener('copy', handleCopy);\n document.removeEventListener('paste', handlePaste);\n };\n }, [gridRef]);\n\n /**\n * Call on Mod+C (without preventing default). The browser normally follows\n * with a `copy` event; where it doesn't (no selection in some browsers),\n * the selection is written as plain TSV instead.\n */\n const copyShortcutFallback = useCallback(() => {\n copiedRef.current = false;\n setTimeout(() => {\n if (copiedRef.current) return;\n const s = stateRef.current;\n navigator.clipboard?.writeText(s.exportToTsv(s.selectedRange));\n }, 0);\n }, []);\n\n return { copyShortcutFallback };\n}\n\n/**\n * Fill handle dragging: press on the handle, move over cells, release to\n * autofill from the selection into the dragged range (one undo step).\n */\nexport function useFillHandle(state: SpreadsheetState) {\n const [drag, setDrag] = useState<{ source: CellRange; target: CellRange | null } | null>(null);\n const dragRef = useRef(drag);\n dragRef.current = drag;\n const stateRef = useRef(state);\n stateRef.current = state;\n const dragging = drag !== null;\n\n useEffect(() => {\n if (!dragging) return;\n const handleMouseUp = () => {\n const current = dragRef.current;\n setDrag(null);\n if (current?.target) stateRef.current.autofill(current.source, current.target);\n };\n window.addEventListener('mouseup', handleMouseUp);\n return () => window.removeEventListener('mouseup', handleMouseUp);\n }, [dragging]);\n\n const startFill = useCallback((e: { preventDefault(): void; stopPropagation(): void }) => {\n e.preventDefault();\n e.stopPropagation();\n const range = stateRef.current.selectedRange;\n if (range) setDrag({ source: normalizeRange(range), target: null });\n }, []);\n\n const extendFill = useCallback((row: number, col: number) => {\n const current = dragRef.current;\n if (!current) return;\n setDrag({ source: current.source, target: computeFillTarget(current.source, { row, col }) });\n }, []);\n\n return { fillTarget: drag?.target ?? null, isFilling: dragging, startFill, extendFill };\n}\n","import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport { applyFormulaSuggestion, getFormulaHints } from '@pixerate/editor/spreadsheet';\n\nexport interface FormulaHintsProps {\n /** The input being edited (a cell editor or the formula bar). */\n inputRef: React.RefObject<HTMLInputElement | null>;\n /** The input's current value. */\n value: string;\n /** Called with the new value when a suggestion is accepted. */\n onAccept: (value: string) => void;\n /** Maximum number of function suggestions (default 8). */\n limit?: number;\n}\n\n/**\n * Formula autocomplete for an input: while the value starts with `=`, lists\n * functions matching the name at the caret (name, signature, description) and,\n * inside a call, shows the signature with the current argument highlighted.\n *\n * Keys are handled on the input itself, before the grid sees them: ArrowUp /\n * ArrowDown move the selection, Tab accepts it, Escape closes the list.\n * Enter is left alone so it still commits the cell.\n */\nexport const FormulaHints: React.FC<FormulaHintsProps> = ({ inputRef, value, onAccept, limit = 8 }) => {\n const [caret, setCaret] = useState<number | null>(null);\n const [focused, setFocused] = useState(false);\n const [selected, setSelected] = useState(0);\n const [dismissed, setDismissed] = useState(false);\n const [position, setPosition] = useState<{ top: number; left: number; width: number } | null>(null);\n const pendingCaret = useRef<number | null>(null);\n\n const hints = useMemo(\n () => getFormulaHints(value, caret ?? value.length, { limit }),\n [value, caret, limit],\n );\n const suggestions = dismissed ? [] : hints.suggestions;\n const selectedIndex = Math.max(0, Math.min(selected, suggestions.length - 1));\n const visible = focused && value.trimStart().startsWith('=') && (suggestions.length > 0 || !!hints.activeCall);\n\n // The key listener reads the latest state through a ref.\n const latest = useRef({ suggestions, selected: selectedIndex, value, caret, onAccept });\n latest.current = { suggestions, selected: selectedIndex, value, caret, onAccept };\n\n const accept = (index: number) => {\n const { suggestions: list, value: current, caret: at, onAccept: commit } = latest.current;\n const suggestion = list[index];\n if (!suggestion) return;\n const next = applyFormulaSuggestion(current, at ?? current.length, suggestion.name);\n pendingCaret.current = next.caret;\n commit(next.value);\n };\n\n useEffect(() => {\n const input = inputRef.current;\n if (!input) return;\n const syncCaret = () => setCaret(input.selectionStart ?? input.value.length);\n const onInput = () => {\n setDismissed(false);\n setSelected(0);\n syncCaret();\n };\n const onFocus = () => {\n setFocused(true);\n syncCaret();\n };\n const onBlur = () => setFocused(false);\n // A native listener on the input runs before React's delegated handlers,\n // so stopping propagation keeps these keys away from the grid.\n const onKeyDown = (e: KeyboardEvent) => {\n const { suggestions: list } = latest.current;\n if (list.length === 0) return;\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {\n e.preventDefault();\n e.stopPropagation();\n const step = e.key === 'ArrowDown' ? 1 : -1;\n setSelected((i) => (i + step + list.length) % list.length);\n } else if (e.key === 'Tab' && !e.shiftKey) {\n e.preventDefault();\n e.stopPropagation();\n accept(latest.current.selected);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n setDismissed(true);\n }\n };\n\n input.addEventListener('input', onInput);\n input.addEventListener('keyup', syncCaret);\n input.addEventListener('click', syncCaret);\n input.addEventListener('select', syncCaret);\n input.addEventListener('focus', onFocus);\n input.addEventListener('blur', onBlur);\n input.addEventListener('keydown', onKeyDown);\n // Inputs focused on mount (autoFocus) fired `focus` before this effect ran.\n if (typeof document !== 'undefined' && document.activeElement === input) onFocus();\n return () => {\n input.removeEventListener('input', onInput);\n input.removeEventListener('keyup', syncCaret);\n input.removeEventListener('click', syncCaret);\n input.removeEventListener('select', syncCaret);\n input.removeEventListener('focus', onFocus);\n input.removeEventListener('blur', onBlur);\n input.removeEventListener('keydown', onKeyDown);\n };\n }, [inputRef]);\n\n // After accepting, put the caret inside the inserted parenthesis.\n useLayoutEffect(() => {\n const input = inputRef.current;\n const at = pendingCaret.current;\n if (!input || at === null || input.value !== value) return;\n pendingCaret.current = null;\n input.setSelectionRange(at, at);\n setCaret(at);\n setSelected(0);\n }, [value, inputRef]);\n\n useLayoutEffect(() => {\n const input = inputRef.current;\n if (!visible || !input) return;\n const rect = input.getBoundingClientRect();\n setPosition({ top: rect.bottom + 2, left: rect.left, width: rect.width });\n }, [visible, value, inputRef]);\n\n if (!visible) return null;\n\n const { activeCall } = hints;\n return (\n <div\n data-formula-hints=\"\"\n className=\"rounded-md border border-border bg-popover text-popover-foreground shadow-md text-xs font-sans overflow-hidden\"\n style={{\n position: 'fixed',\n top: position?.top ?? 0,\n left: position?.left ?? 0,\n minWidth: Math.max(260, position?.width ?? 0),\n maxWidth: 440,\n zIndex: 50,\n visibility: position ? 'visible' : 'hidden'\n }}\n onMouseDown={(e) => e.preventDefault()}\n >\n {activeCall && (\n <div data-formula-signature=\"\" className=\"px-2 py-1.5 border-b border-border bg-muted/30\">\n <div className=\"font-mono\">\n {activeCall.parts.map((part, i) => (\n <span\n key={i}\n data-active={part.active ? '' : undefined}\n className={part.active ? 'font-bold text-primary underline' : ''}\n >\n {part.text}\n </span>\n ))}\n </div>\n <div className=\"mt-0.5 text-muted-foreground\">\n {activeCall.argument ? (\n <>\n <span className=\"font-semibold\">{activeCall.argument.name}</span>: {activeCall.argument.description}\n </>\n ) : (\n activeCall.description\n )}\n </div>\n </div>\n )}\n {suggestions.length > 0 && (\n <ul role=\"listbox\" aria-label=\"Formula suggestions\" className=\"max-h-64 overflow-auto py-1 m-0 list-none p-0\">\n {suggestions.map((s, i) => (\n <li\n key={s.name}\n role=\"option\"\n aria-selected={i === selectedIndex}\n className={`cursor-pointer px-2 py-1 ${i === selectedIndex ? 'bg-primary/10' : 'hover:bg-muted/50'}`}\n onMouseEnter={() => setSelected(i)}\n onMouseDown={(e) => {\n // Keep focus in the input so the edit isn't committed by blur.\n e.preventDefault();\n accept(i);\n }}\n >\n <div className=\"font-mono font-semibold text-foreground\">{s.signature}</div>\n <div className=\"text-muted-foreground truncate\">{s.description}</div>\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n};\n"],"mappings":"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","names":["document","useRef","useState","useMemo","useEffect","useCallback","normalizeRange","useRef","jsx","jsxs","useCallback","useEffect","useRef","useState","useEffect","useMemo","useRef","useState","jsx","jsxs","Fragment","jsx","jsxs","useRef","useState","useMemo","useCallback","useEffect","normalizeRange"]}
package/dist/index.cjs CHANGED
@@ -33,11 +33,11 @@ __export(src_exports, {
33
33
  BubbleMenu: () => BubbleMenu,
34
34
  CommentButton: () => CommentButton,
35
35
  CommentsPanel: () => CommentsPanel,
36
- DirtyTracker: () => import_editor15.DirtyTracker,
36
+ DirtyTracker: () => import_editor11.DirtyTracker,
37
37
  EditorContent: () => EditorContent,
38
38
  EditorSlotsProvider: () => EditorSlotsProvider,
39
39
  FormulaHints: () => FormulaHints,
40
- HistoryManager: () => import_editor15.HistoryManager,
40
+ HistoryManager: () => import_editor11.HistoryManager,
41
41
  ImageEditor: () => ImageEditor,
42
42
  OutlinePanel: () => OutlinePanel,
43
43
  ReviewToolbar: () => ReviewToolbar,
@@ -46,9 +46,9 @@ __export(src_exports, {
46
46
  SpreadsheetGroupRow: () => SpreadsheetGroupRow,
47
47
  TemplateRenderer: () => TemplateRenderer,
48
48
  VariableForm: () => VariableForm,
49
- createDirtyTracker: () => import_editor15.createDirtyTracker,
50
- createHistoryManager: () => import_editor15.createHistoryManager,
51
- defaultIsEqual: () => import_editor15.defaultIsEqual,
49
+ createDirtyTracker: () => import_editor11.createDirtyTracker,
50
+ createHistoryManager: () => import_editor11.createHistoryManager,
51
+ defaultIsEqual: () => import_editor11.defaultIsEqual,
52
52
  useAgentToolProvider: () => useAgentToolProvider,
53
53
  useComments: () => useComments,
54
54
  useDismissGuard: () => useDismissGuard,
@@ -884,17 +884,17 @@ var OutlinePanel = ({
884
884
  };
885
885
 
886
886
  // src/index.ts
887
- var import_editor15 = require("@pixerate/editor");
887
+ var import_editor11 = require("@pixerate/editor");
888
888
 
889
889
  // src/spreadsheet/useSpreadsheetEditor.ts
890
890
  var import_react15 = require("react");
891
- var import_editor9 = require("@pixerate/editor");
891
+ var import_spreadsheet = require("@pixerate/editor/spreadsheet");
892
892
  function useSpreadsheetEditor(options = {}) {
893
893
  const optionsRef = (0, import_react15.useRef)(options);
894
894
  optionsRef.current = options;
895
895
  const settersRef = (0, import_react15.useRef)({});
896
896
  const [controller] = (0, import_react15.useState)(
897
- () => new import_editor9.SpreadsheetController({
897
+ () => new import_spreadsheet.SpreadsheetController({
898
898
  ...options,
899
899
  onDocumentChange: (updated) => {
900
900
  settersRef.current.setDoc?.({ ...updated });
@@ -995,7 +995,7 @@ function useSpreadsheetEditor(options = {}) {
995
995
  controller.redo();
996
996
  setDoc({ ...controller.document });
997
997
  }, [controller]);
998
- const tableActions = (0, import_react15.useMemo)(() => (0, import_editor9.bindSpreadsheetTableActions)(controller), [controller]);
998
+ const tableActions = (0, import_react15.useMemo)(() => (0, import_spreadsheet.bindSpreadsheetTableActions)(controller), [controller]);
999
999
  const viewModel = (0, import_react15.useMemo)(() => controller.getViewModel(), [controller, doc]);
1000
1000
  return {
1001
1001
  document: doc,
@@ -1049,7 +1049,7 @@ function useSpreadsheetEditor(options = {}) {
1049
1049
 
1050
1050
  // src/spreadsheet/SpreadsheetEditor.tsx
1051
1051
  var import_react19 = require("react");
1052
- var import_editor12 = require("@pixerate/editor");
1052
+ var import_spreadsheet4 = require("@pixerate/editor/spreadsheet");
1053
1053
 
1054
1054
  // src/spreadsheet/SpreadsheetContextMenu.tsx
1055
1055
  var import_react16 = __toESM(require("react"), 1);
@@ -1148,7 +1148,7 @@ var SpreadsheetGroupRow = ({
1148
1148
 
1149
1149
  // src/spreadsheet/useSpreadsheetTableInteractions.ts
1150
1150
  var import_react17 = require("react");
1151
- var import_editor10 = require("@pixerate/editor");
1151
+ var import_spreadsheet2 = require("@pixerate/editor/spreadsheet");
1152
1152
  function gridHasFocus(grid) {
1153
1153
  if (!grid || typeof document === "undefined") return false;
1154
1154
  const active = document.activeElement;
@@ -1215,19 +1215,19 @@ function useFillHandle(state) {
1215
1215
  e.preventDefault();
1216
1216
  e.stopPropagation();
1217
1217
  const range = stateRef.current.selectedRange;
1218
- if (range) setDrag({ source: (0, import_editor10.normalizeRange)(range), target: null });
1218
+ if (range) setDrag({ source: (0, import_spreadsheet2.normalizeRange)(range), target: null });
1219
1219
  }, []);
1220
1220
  const extendFill = (0, import_react17.useCallback)((row, col) => {
1221
1221
  const current = dragRef.current;
1222
1222
  if (!current) return;
1223
- setDrag({ source: current.source, target: (0, import_editor10.computeFillTarget)(current.source, { row, col }) });
1223
+ setDrag({ source: current.source, target: (0, import_spreadsheet2.computeFillTarget)(current.source, { row, col }) });
1224
1224
  }, []);
1225
1225
  return { fillTarget: drag?.target ?? null, isFilling: dragging, startFill, extendFill };
1226
1226
  }
1227
1227
 
1228
1228
  // src/spreadsheet/FormulaHints.tsx
1229
1229
  var import_react18 = require("react");
1230
- var import_editor11 = require("@pixerate/editor");
1230
+ var import_spreadsheet3 = require("@pixerate/editor/spreadsheet");
1231
1231
  var import_jsx_runtime7 = require("react/jsx-runtime");
1232
1232
  var FormulaHints = ({ inputRef, value, onAccept, limit = 8 }) => {
1233
1233
  const [caret, setCaret] = (0, import_react18.useState)(null);
@@ -1237,7 +1237,7 @@ var FormulaHints = ({ inputRef, value, onAccept, limit = 8 }) => {
1237
1237
  const [position, setPosition] = (0, import_react18.useState)(null);
1238
1238
  const pendingCaret = (0, import_react18.useRef)(null);
1239
1239
  const hints = (0, import_react18.useMemo)(
1240
- () => (0, import_editor11.getFormulaHints)(value, caret ?? value.length, { limit }),
1240
+ () => (0, import_spreadsheet3.getFormulaHints)(value, caret ?? value.length, { limit }),
1241
1241
  [value, caret, limit]
1242
1242
  );
1243
1243
  const suggestions = dismissed ? [] : hints.suggestions;
@@ -1249,7 +1249,7 @@ var FormulaHints = ({ inputRef, value, onAccept, limit = 8 }) => {
1249
1249
  const { suggestions: list, value: current, caret: at, onAccept: commit } = latest.current;
1250
1250
  const suggestion = list[index];
1251
1251
  if (!suggestion) return;
1252
- const next = (0, import_editor11.applyFormulaSuggestion)(current, at ?? current.length, suggestion.name);
1252
+ const next = (0, import_spreadsheet3.applyFormulaSuggestion)(current, at ?? current.length, suggestion.name);
1253
1253
  pendingCaret.current = next.caret;
1254
1254
  commit(next.value);
1255
1255
  };
@@ -1419,10 +1419,10 @@ var SpreadsheetEditor = ({
1419
1419
  if (readOnly) return;
1420
1420
  e.preventDefault();
1421
1421
  if (state.editingCell) state.commitEditing();
1422
- if (!state.selectedRange || !(0, import_editor12.rangeContains)(state.selectedRange, rIdx, cIdx)) {
1422
+ if (!state.selectedRange || !(0, import_spreadsheet4.rangeContains)(state.selectedRange, rIdx, cIdx)) {
1423
1423
  state.selectCell(rIdx, cIdx);
1424
1424
  }
1425
- setMenu({ x: e.clientX, y: e.clientY, items: (0, import_editor12.getSpreadsheetMenuItems)(state.controller, { row: rIdx, col: cIdx }) });
1425
+ setMenu({ x: e.clientX, y: e.clientY, items: (0, import_spreadsheet4.getSpreadsheetMenuItems)(state.controller, { row: rIdx, col: cIdx }) });
1426
1426
  }, [readOnly, state]);
1427
1427
  const activeRawValue = (0, import_react19.useMemo)(() => {
1428
1428
  if (!state.activeCell) return "";
@@ -1433,7 +1433,7 @@ var SpreadsheetEditor = ({
1433
1433
  }, [state.activeCell, state.document]);
1434
1434
  const coordLabel = (0, import_react19.useMemo)(() => {
1435
1435
  if (!state.activeCell) return "--";
1436
- const colName = (0, import_editor12.indexToColName)(state.activeCell.col);
1436
+ const colName = (0, import_spreadsheet4.indexToColName)(state.activeCell.col);
1437
1437
  return `${colName}${state.activeCell.row + 1}`;
1438
1438
  }, [state.activeCell]);
1439
1439
  const [formulaDraft, setFormulaDraft] = (0, import_react19.useState)(null);
@@ -1842,7 +1842,7 @@ var SpreadsheetEditor = ({
1842
1842
  );
1843
1843
  }
1844
1844
  const displayRowIndex = viewRow.index;
1845
- const selection = state.selectedRange ? (0, import_editor12.normalizeRange)(state.selectedRange) : null;
1845
+ const selection = state.selectedRange ? (0, import_spreadsheet4.normalizeRange)(state.selectedRange) : null;
1846
1846
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1847
1847
  "tr",
1848
1848
  {
@@ -1869,8 +1869,8 @@ var SpreadsheetEditor = ({
1869
1869
  const selected = isCellSelected(rIdx, cIdx);
1870
1870
  const active = isActiveCell(rIdx, cIdx);
1871
1871
  const isEditing = state.editingCell?.row === rIdx && state.editingCell?.col === cIdx;
1872
- const inFillPreview = !!fillTarget && !selected && (0, import_editor12.rangeContains)(fillTarget, displayRowIndex, viewCol.index);
1873
- const showFillHandle = !readOnly && !isEditing && !!selection && (span.merge ? (0, import_editor12.rangeContains)(span.merge, selection.endRow, selection.endCol) : selection.endRow === rIdx && selection.endCol === cIdx);
1872
+ const inFillPreview = !!fillTarget && !selected && (0, import_spreadsheet4.rangeContains)(fillTarget, displayRowIndex, viewCol.index);
1873
+ const showFillHandle = !readOnly && !isEditing && !!selection && (span.merge ? (0, import_spreadsheet4.rangeContains)(span.merge, selection.endRow, selection.endCol) : selection.endRow === rIdx && selection.endCol === cIdx);
1874
1874
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1875
1875
  "td",
1876
1876
  {
@@ -3407,7 +3407,7 @@ var ImageEditor = ({
3407
3407
 
3408
3408
  // src/review/useReview.ts
3409
3409
  var import_react23 = require("react");
3410
- var import_editor13 = require("@pixerate/editor");
3410
+ var import_editor9 = require("@pixerate/editor");
3411
3411
  var EMPTY_COMMENTS = Object.freeze({
3412
3412
  threads: [],
3413
3413
  activeThreadId: null
@@ -3424,7 +3424,7 @@ function isCommentStore(value) {
3424
3424
  return !!value && typeof value.getSnapshot === "function" && typeof value.createThread === "function";
3425
3425
  }
3426
3426
  function useComments(source) {
3427
- const store = isCommentStore(source) ? source : (0, import_editor13.getCommentStore)(source);
3427
+ const store = isCommentStore(source) ? source : (0, import_editor9.getCommentStore)(source);
3428
3428
  const subscribe = (0, import_react23.useCallback)(
3429
3429
  (onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
3430
3430
  [store]
@@ -3434,7 +3434,7 @@ function useComments(source) {
3434
3434
  return (0, import_react23.useMemo)(() => ({ ...snapshot, store }), [snapshot, store]);
3435
3435
  }
3436
3436
  function useTrackChanges(editor) {
3437
- const store = (0, import_editor13.getTrackChangesStore)(editor ?? null);
3437
+ const store = (0, import_editor9.getTrackChangesStore)(editor ?? null);
3438
3438
  const subscribe = (0, import_react23.useCallback)(
3439
3439
  (onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
3440
3440
  [store]
@@ -3462,7 +3462,7 @@ function useTrackChanges(editor) {
3462
3462
 
3463
3463
  // src/review/CommentsPanel.tsx
3464
3464
  var import_react24 = require("react");
3465
- var import_editor14 = require("@pixerate/editor");
3465
+ var import_editor10 = require("@pixerate/editor");
3466
3466
  var import_jsx_runtime11 = require("react/jsx-runtime");
3467
3467
  var buttonClass = "rounded px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-50";
3468
3468
  var primaryButtonClass = "rounded px-2 py-1 text-xs bg-primary/10 text-primary hover:bg-primary/20 disabled:opacity-50";
@@ -3473,12 +3473,12 @@ var CommentsPanel = ({
3473
3473
  author: authorProp,
3474
3474
  showResolved: showResolvedInitial = false,
3475
3475
  className = "flex flex-col gap-2 text-sm text-foreground",
3476
- formatTime = (t) => (0, import_editor14.formatReviewTime)(t),
3476
+ formatTime = (t) => (0, import_editor10.formatReviewTime)(t),
3477
3477
  emptyMessage = "No comments yet. Select text and add a comment."
3478
3478
  }) => {
3479
3479
  const { threads, activeThreadId, store } = useComments(storeProp ?? editor);
3480
3480
  const [showResolved, setShowResolved] = (0, import_react24.useState)(showResolvedInitial);
3481
- const author = authorProp ?? (0, import_editor14.getCommentAuthor)(editor) ?? { id: "anonymous", name: "Anonymous" };
3481
+ const author = authorProp ?? (0, import_editor10.getCommentAuthor)(editor) ?? { id: "anonymous", name: "Anonymous" };
3482
3482
  const visible = threads.filter((t) => showResolved || !t.resolved);
3483
3483
  const resolvedCount = threads.filter((t) => t.resolved).length;
3484
3484
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("aside", { className, "aria-label": "Comments", children: [