@eristack/spreadsheet-operator
Version:
Headless spreadsheet keyboard operator — active-grid scope, cell navigation, Excel-like Enter/Tab editing
1 lines • 52.6 kB
Source Map (JSON)
{"version":3,"sources":["../../src/react/index.ts","../../src/react/scope.tsx","../../src/core/types.ts","../../src/core/address.ts","../../src/core/navigation.ts","../../src/core/keymap.ts","../../src/core/reduce.ts","../../src/core/create-operator.ts"],"sourcesContent":["export {\n isKeyTargetOutsideActiveGrid,\n isPointerTargetOutsideGrids,\n SpreadsheetGridIdProvider,\n SpreadsheetNavCell,\n SpreadsheetScopeProvider,\n SpreadsheetTable,\n SpreadsheetTextCell,\n useSpreadsheetCellEditor,\n useSpreadsheetGrid,\n useSpreadsheetGridId,\n useSpreadsheetScope,\n type KeyTargetLike,\n type SpreadsheetCellEditor,\n type SpreadsheetGridIdProviderProps,\n type SpreadsheetNavCellProps,\n type SpreadsheetScopeApi,\n type SpreadsheetScopeProviderProps,\n type SpreadsheetTableProps,\n type SpreadsheetTextCellProps,\n type UseSpreadsheetCellEditorOptions,\n type UseSpreadsheetGridResult,\n} from \"./scope.js\";\n","import {\n createContext,\n createElement,\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n type KeyboardEvent as ReactKeyboardEvent,\n type MouseEvent as ReactMouseEvent,\n type ReactNode,\n} from \"react\";\nimport {\n cellKey,\n createSpreadsheetOperator,\n sameAddress,\n type CellAddress,\n type GridDescriptor,\n type GridId,\n type OperatorEffect,\n type SpreadsheetCommitEvent,\n type SpreadsheetOperator,\n type SpreadsheetOperatorConfig,\n type SpreadsheetOperatorState,\n} from \"../index.js\";\n\nexport type SpreadsheetCellEditor = {\n focus(): void;\n selectAll?(): void;\n readValue(): string;\n writeValue?(value: string): void;\n onCommit?(value: string): void;\n onCancel?(): void;\n};\n\nexport type SpreadsheetScopeApi = {\n readonly operator: SpreadsheetOperator;\n readonly state: SpreadsheetOperatorState;\n registerEditor(gridId: GridId, address: CellAddress, editor: SpreadsheetCellEditor): () => void;\n};\n\nconst ScopeContext = createContext<SpreadsheetScopeApi | null>(null);\nconst GridIdContext = createContext<GridId | null>(null);\n\nexport function useSpreadsheetScope(): SpreadsheetScopeApi {\n const ctx = useContext(ScopeContext);\n if (!ctx) {\n throw new Error(\"useSpreadsheetScope must be used within SpreadsheetScopeProvider\");\n }\n return ctx;\n}\n\nexport function useSpreadsheetGridId(): GridId {\n const id = useContext(GridIdContext);\n if (!id) {\n throw new Error(\n \"useSpreadsheetGridId must be used within SpreadsheetTable or SpreadsheetGridIdProvider\",\n );\n }\n return id;\n}\n\nexport type SpreadsheetGridIdProviderProps = {\n gridId: GridId;\n children: ReactNode;\n};\n\n/**\n * Supplies the grid id to `SpreadsheetNavCell` / `useSpreadsheetCellEditor` when you\n * render your own container with `useSpreadsheetGrid` instead of `SpreadsheetTable`.\n */\nexport function SpreadsheetGridIdProvider({ gridId, children }: SpreadsheetGridIdProviderProps) {\n return createElement(GridIdContext.Provider, { value: gridId }, children);\n}\n\nfunction applyEditorEffects(\n editors: Map<string, SpreadsheetCellEditor>,\n effects: readonly OperatorEffect[],\n onCommit: ((event: SpreadsheetCommitEvent) => void) | undefined,\n): void {\n for (const effect of effects) {\n const editor = editors.get(cellKey(effect.gridId, effect.address));\n if (effect.type === \"commit\") {\n const value = editor?.readValue() ?? \"\";\n editor?.onCommit?.(value);\n onCommit?.({\n gridId: effect.gridId,\n address: effect.address,\n fieldKey: effect.fieldKey,\n value,\n phase: \"commit\",\n });\n }\n if (effect.type === \"cancel\") {\n editor?.onCancel?.();\n }\n if (effect.type === \"startEdit\" && effect.seed !== undefined) {\n editor?.writeValue?.(effect.seed);\n }\n }\n}\n\n/** Minimal DOM shape so the guards stay testable without jsdom. */\nexport type KeyTargetLike = {\n closest(selector: string): { getAttribute(name: string): string | null } | null;\n matches?(selector: string): boolean;\n isContentEditable?: boolean;\n};\n\nconst EDITABLE_TARGET_SELECTOR = \"input, textarea, select, [contenteditable=''], [contenteditable='true']\";\n\n/**\n * True when a keydown came from a text-entry element that does not belong to the\n * active grid (a search box, a header field). The operator must not steal those keys.\n */\nexport function isKeyTargetOutsideActiveGrid(\n target: KeyTargetLike | null | undefined,\n activeGridId: GridId,\n): boolean {\n if (!target) return false;\n const editable =\n target.isContentEditable === true ||\n (typeof target.matches === \"function\" && target.matches(EDITABLE_TARGET_SELECTOR));\n if (!editable) return false;\n const grid = target.closest(\"[data-spreadsheet-grid]\");\n return grid?.getAttribute(\"data-spreadsheet-grid\") !== activeGridId;\n}\n\n/** True when a pointer-down landed outside every registered grid element. */\nexport function isPointerTargetOutsideGrids(target: KeyTargetLike | null | undefined): boolean {\n if (!target) return false;\n return target.closest(\"[data-spreadsheet-grid]\") === null;\n}\n\nexport type SpreadsheetScopeProviderProps = {\n children: ReactNode;\n config?: SpreadsheetOperatorConfig;\n onCommit?: (event: SpreadsheetCommitEvent) => void;\n /**\n * Pointer-down outside every grid commits any edit and deactivates the operator\n * (Excel behaviour). Default `true`. Set `false` when the app owns deactivation.\n */\n deactivateOnOutsidePointerDown?: boolean;\n};\n\nexport function SpreadsheetScopeProvider({\n children,\n config,\n onCommit,\n deactivateOnOutsidePointerDown = true,\n}: SpreadsheetScopeProviderProps) {\n const editorsRef = useRef(new Map<string, SpreadsheetCellEditor>());\n const onCommitRef = useRef(onCommit);\n onCommitRef.current = onCommit;\n\n const operatorRef = useRef<SpreadsheetOperator | null>(null);\n if (operatorRef.current === null) {\n const created = createSpreadsheetOperator(config);\n created.subscribe((_state, effects) => {\n applyEditorEffects(editorsRef.current, effects, onCommitRef.current);\n });\n operatorRef.current = created;\n }\n const operator = operatorRef.current;\n\n const state = useSyncExternalStore(\n (onStoreChange) => operator.subscribe(() => onStoreChange()),\n operator.getState,\n operator.getState,\n );\n\n useEffect(() => {\n function onKeyDown(event: KeyboardEvent) {\n const current = operator.getState();\n if (current.mode === \"inactive\") return;\n if (\n isKeyTargetOutsideActiveGrid(\n event.target instanceof Element ? event.target : null,\n current.gridId,\n )\n ) {\n return;\n }\n if (operator.handleKeyDown(event)) {\n event.preventDefault();\n event.stopPropagation();\n }\n }\n window.addEventListener(\"keydown\", onKeyDown);\n return () => window.removeEventListener(\"keydown\", onKeyDown);\n }, [operator]);\n\n useEffect(() => {\n if (!deactivateOnOutsidePointerDown) return;\n function onPointerDown(event: PointerEvent) {\n if (operator.getState().mode === \"inactive\") return;\n if (isPointerTargetOutsideGrids(event.target instanceof Element ? event.target : null)) {\n operator.dispatch({ type: \"deactivate\" });\n }\n }\n document.addEventListener(\"pointerdown\", onPointerDown);\n return () => document.removeEventListener(\"pointerdown\", onPointerDown);\n }, [operator, deactivateOnOutsidePointerDown]);\n\n const registerEditor = useCallback(\n (gridId: GridId, address: CellAddress, editor: SpreadsheetCellEditor) => {\n const key = cellKey(gridId, address);\n editorsRef.current.set(key, editor);\n return () => {\n editorsRef.current.delete(key);\n };\n },\n [],\n );\n\n const api = useMemo<SpreadsheetScopeApi>(\n () => ({ operator, state, registerEditor }),\n [operator, state, registerEditor],\n );\n\n return createElement(ScopeContext.Provider, { value: api }, children);\n}\n\nexport type UseSpreadsheetGridResult = {\n gridProps: {\n role: \"grid\";\n \"data-spreadsheet-grid\": string;\n \"data-spreadsheet-active\"?: \"\";\n tabIndex: number;\n onMouseDown: (event: ReactMouseEvent<HTMLElement>) => void;\n };\n activeAddress: CellAddress | null;\n editing: boolean;\n isGridActive: boolean;\n};\n\nexport function useSpreadsheetGrid(descriptor: GridDescriptor): UseSpreadsheetGridResult {\n const { operator, state } = useSpreadsheetScope();\n operator.registerGrid(descriptor);\n\n useEffect(() => {\n const id = descriptor.id;\n return () => operator.unregisterGrid(id);\n }, [operator, descriptor.id]);\n\n const isGridActive = state.mode !== \"inactive\" && state.gridId === descriptor.id;\n const activeAddress = isGridActive ? state.address : null;\n const editing = state.mode === \"editing\" && state.gridId === descriptor.id;\n\n const onMouseDown = useCallback(\n (event: ReactMouseEvent<HTMLElement>) => {\n const target = event.target;\n if (!(target instanceof Element)) return;\n const cell = target.closest(\"[data-spreadsheet-cell]\");\n if (!cell) return;\n const row = Number(cell.getAttribute(\"data-row\"));\n const col = Number(cell.getAttribute(\"data-col\"));\n if (!Number.isFinite(row) || !Number.isFinite(col)) return;\n operator.dispatch({\n type: \"activate\",\n gridId: descriptor.id,\n address: { row, col },\n });\n },\n [operator, descriptor.id],\n );\n\n return {\n gridProps: {\n role: \"grid\",\n \"data-spreadsheet-grid\": descriptor.id,\n \"data-spreadsheet-active\": isGridActive ? \"\" : undefined,\n tabIndex: -1,\n onMouseDown,\n },\n activeAddress,\n editing,\n isGridActive,\n };\n}\n\nexport type SpreadsheetTableProps = {\n descriptor: GridDescriptor;\n children: ReactNode;\n className?: string;\n};\n\nexport function SpreadsheetTable({ descriptor, children, className }: SpreadsheetTableProps) {\n const { gridProps } = useSpreadsheetGrid(descriptor);\n return createElement(\n GridIdContext.Provider,\n { value: descriptor.id },\n createElement(\"table\", { ...gridProps, className }, children),\n );\n}\n\nexport type SpreadsheetNavCellProps = {\n address: CellAddress;\n children?: ReactNode;\n className?: string;\n};\n\nexport function SpreadsheetNavCell({ address, children, className }: SpreadsheetNavCellProps) {\n const gridId = useSpreadsheetGridId();\n const { state } = useSpreadsheetScope();\n const isActive =\n state.mode !== \"inactive\" &&\n state.gridId === gridId &&\n sameAddress(state.address, address);\n const isEditing = state.mode === \"editing\" && isActive;\n\n return createElement(\n \"td\",\n {\n role: \"gridcell\",\n className,\n \"data-spreadsheet-cell\": \"\",\n \"data-row\": address.row,\n \"data-col\": address.col,\n \"data-active\": isActive ? \"\" : undefined,\n \"data-editing\": isEditing ? \"\" : undefined,\n \"aria-selected\": isActive,\n tabIndex: isActive ? 0 : -1,\n },\n children,\n );\n}\n\nexport type UseSpreadsheetCellEditorOptions = {\n address: CellAddress;\n readValue: () => string;\n writeValue?: (value: string) => void;\n onCommit?: (value: string) => void;\n onCancel?: () => void;\n focus?: () => void;\n selectAll?: () => void;\n};\n\nexport function useSpreadsheetCellEditor(options: UseSpreadsheetCellEditorOptions): {\n editing: boolean;\n seed: string | undefined;\n} {\n const gridId = useSpreadsheetGridId();\n const { state, registerEditor } = useSpreadsheetScope();\n const editing =\n state.mode === \"editing\" &&\n state.gridId === gridId &&\n sameAddress(state.address, options.address);\n const seed = editing && state.mode === \"editing\" ? state.seed : undefined;\n\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const row = options.address.row;\n const col = options.address.col;\n\n useLayoutEffect(() => {\n return registerEditor(gridId, { row, col }, {\n focus: () => optionsRef.current.focus?.(),\n selectAll: () => optionsRef.current.selectAll?.(),\n readValue: () => optionsRef.current.readValue(),\n writeValue: (value) => optionsRef.current.writeValue?.(value),\n onCommit: (value) => optionsRef.current.onCommit?.(value),\n onCancel: () => optionsRef.current.onCancel?.(),\n });\n }, [gridId, row, col, registerEditor]);\n\n return { editing, seed };\n}\n\nexport type SpreadsheetTextCellProps = {\n address: CellAddress;\n value: string;\n onCommit: (value: string) => void;\n};\n\nexport function SpreadsheetTextCell({ address, value, onCommit }: SpreadsheetTextCellProps) {\n const inputRef = useRef<HTMLInputElement>(null);\n const { operator } = useSpreadsheetScope();\n const { editing, seed } = useSpreadsheetCellEditor({\n address,\n readValue: () => inputRef.current?.value ?? value,\n onCommit,\n focus: () => inputRef.current?.focus(),\n selectAll: () => inputRef.current?.select(),\n });\n\n useLayoutEffect(() => {\n if (!editing) return;\n const el = inputRef.current;\n if (!el) return;\n el.focus();\n if (seed === undefined) el.select();\n }, [editing, seed]);\n\n if (!editing) {\n return createElement(\"span\", { \"data-spreadsheet-display\": \"\" }, value);\n }\n\n return createElement(\"input\", {\n ref: inputRef,\n defaultValue: seed ?? value,\n \"data-spreadsheet-editor\": \"\",\n onKeyDown: (event: ReactKeyboardEvent<HTMLInputElement>) => {\n if (event.key === \"Enter\" || event.key === \"Tab\" || event.key === \"Escape\") {\n return;\n }\n event.stopPropagation();\n },\n onBlur: () => {\n operator.dispatch({ type: \"commit\" });\n },\n });\n}\n","export type GridId = string;\n\nexport type CellAddress = {\n readonly row: number;\n readonly col: number;\n};\n\nexport type CellNavKind = \"editable\" | \"select\" | \"display\" | \"readonly\";\n\nexport type CellDescriptor = {\n readonly kind: CellNavKind;\n readonly id?: string;\n readonly fieldKey?: string;\n};\n\nexport type GridDescriptor = {\n readonly id: GridId;\n readonly rowCount: number;\n readonly colCount: number;\n cellAt: (address: CellAddress) => CellDescriptor;\n};\n\nexport type SpreadsheetOperatorState =\n | { readonly mode: \"inactive\" }\n | { readonly mode: \"active\"; readonly gridId: GridId; readonly address: CellAddress }\n | {\n readonly mode: \"editing\";\n readonly gridId: GridId;\n readonly address: CellAddress;\n readonly seed?: string;\n };\n\nexport type WrapPolicy = \"wrap\" | \"stop\";\nexport type EnterMove = \"down\" | \"right\" | \"none\";\nexport type ArrowInEdit = \"caret\" | \"leave\";\n\nexport type MoveDirection = \"up\" | \"down\" | \"left\" | \"right\";\nexport type TabDirection = \"next\" | \"prev\";\nexport type NavDirection = MoveDirection | TabDirection;\n\nexport type SpreadsheetOperatorConfig = {\n /** Tab wrap. Default `wrap`. */\n readonly wrap?: WrapPolicy;\n /** Arrow wrap at edges. Default `stop`. */\n readonly arrowWrap?: WrapPolicy;\n /** After Enter commit. Default `down`. */\n readonly enterMove?: EnterMove;\n /** Printable key on an active cell starts edit. Default `true`. */\n readonly typeToEdit?: boolean;\n /** Kinds arrows/Tab land on. Default `editable` + `select` (skip `readonly`/`display`). */\n readonly navigableKinds?: readonly CellNavKind[];\n /** Kinds Enter/F2/type can edit. Default `editable` + `select`. */\n readonly editableKinds?: readonly CellNavKind[];\n /** Arrows while editing. Default `caret` (leave to the input). */\n readonly arrowInEdit?: ArrowInEdit;\n};\n\nexport type ResolvedSpreadsheetOperatorConfig = {\n readonly wrap: WrapPolicy;\n readonly arrowWrap: WrapPolicy;\n readonly enterMove: EnterMove;\n readonly typeToEdit: boolean;\n readonly navigableKinds: readonly CellNavKind[];\n readonly editableKinds: readonly CellNavKind[];\n readonly arrowInEdit: ArrowInEdit;\n};\n\nexport const DEFAULT_NAVIGABLE_KINDS: readonly CellNavKind[] = [\"editable\", \"select\"];\nexport const DEFAULT_EDITABLE_KINDS: readonly CellNavKind[] = [\"editable\", \"select\"];\n\nexport type OperatorAction =\n | { readonly type: \"activate\"; readonly gridId: GridId; readonly address: CellAddress }\n | { readonly type: \"deactivate\" }\n | { readonly type: \"move\"; readonly direction: MoveDirection }\n | { readonly type: \"tab\"; readonly shift?: boolean }\n | { readonly type: \"enter\" }\n | { readonly type: \"escape\" }\n | { readonly type: \"f2\" }\n | { readonly type: \"type\"; readonly char: string }\n | { readonly type: \"commit\" }\n | { readonly type: \"cancel\" };\n\nexport type OperatorEffect =\n | {\n readonly type: \"commit\";\n readonly gridId: GridId;\n readonly address: CellAddress;\n readonly fieldKey?: string;\n readonly phase: \"commit\";\n }\n | {\n readonly type: \"cancel\";\n readonly gridId: GridId;\n readonly address: CellAddress;\n readonly phase: \"cancel\";\n }\n | {\n readonly type: \"startEdit\";\n readonly gridId: GridId;\n readonly address: CellAddress;\n readonly seed?: string;\n };\n\nexport type SpreadsheetCommitEvent = {\n readonly gridId: GridId;\n readonly address: CellAddress;\n readonly fieldKey?: string;\n readonly value: string;\n readonly phase: \"commit\";\n};\n\nexport type OperatorKeyEvent = {\n readonly key: string;\n readonly shiftKey?: boolean;\n readonly altKey?: boolean;\n readonly ctrlKey?: boolean;\n readonly metaKey?: boolean;\n readonly isComposing?: boolean;\n};\n\nexport type OperatorContext = {\n readonly grids: ReadonlyMap<GridId, GridDescriptor>;\n readonly config: ResolvedSpreadsheetOperatorConfig;\n};\n\nexport type SpreadsheetOperatorListener = (\n state: SpreadsheetOperatorState,\n effects: readonly OperatorEffect[],\n) => void;\n","import type { CellAddress, GridDescriptor } from \"./types.js\";\n\nexport function sameAddress(a: CellAddress, b: CellAddress): boolean {\n return a.row === b.row && a.col === b.col;\n}\n\nexport function addressKey(address: CellAddress): string {\n return `${address.row}:${address.col}`;\n}\n\nexport function cellKey(gridId: string, address: CellAddress): string {\n return `${gridId}:${address.row}:${address.col}`;\n}\n\nexport function inBounds(address: CellAddress, grid: GridDescriptor): boolean {\n return (\n address.row >= 0 &&\n address.col >= 0 &&\n address.row < grid.rowCount &&\n address.col < grid.colCount\n );\n}\n\nexport function clampAddress(address: CellAddress, grid: GridDescriptor): CellAddress {\n if (grid.rowCount < 1 || grid.colCount < 1) {\n return { row: 0, col: 0 };\n }\n return {\n row: Math.min(Math.max(0, address.row), grid.rowCount - 1),\n col: Math.min(Math.max(0, address.col), grid.colCount - 1),\n };\n}\n\nexport function compareRaster(a: CellAddress, b: CellAddress): number {\n if (a.row !== b.row) return a.row - b.row;\n return a.col - b.col;\n}\n","import { clampAddress, compareRaster, inBounds, sameAddress } from \"./address.js\";\nimport type {\n CellAddress,\n CellNavKind,\n GridDescriptor,\n MoveDirection,\n NavDirection,\n ResolvedSpreadsheetOperatorConfig,\n SpreadsheetOperatorConfig,\n TabDirection,\n} from \"./types.js\";\nimport {\n DEFAULT_EDITABLE_KINDS,\n DEFAULT_NAVIGABLE_KINDS,\n} from \"./types.js\";\n\nexport function resolveConfig(\n config: SpreadsheetOperatorConfig = {},\n): ResolvedSpreadsheetOperatorConfig {\n return {\n wrap: config.wrap ?? \"wrap\",\n arrowWrap: config.arrowWrap ?? \"stop\",\n enterMove: config.enterMove ?? \"down\",\n typeToEdit: config.typeToEdit ?? true,\n navigableKinds: config.navigableKinds ?? DEFAULT_NAVIGABLE_KINDS,\n editableKinds: config.editableKinds ?? DEFAULT_EDITABLE_KINDS,\n arrowInEdit: config.arrowInEdit ?? \"caret\",\n };\n}\n\nexport function kindAt(grid: GridDescriptor, address: CellAddress): CellNavKind | undefined {\n if (!inBounds(address, grid)) return undefined;\n return grid.cellAt(address).kind;\n}\n\nexport function isKind(\n kind: CellNavKind | undefined,\n allowed: readonly CellNavKind[],\n): boolean {\n return kind !== undefined && allowed.includes(kind);\n}\n\nexport function isNavigable(\n grid: GridDescriptor,\n address: CellAddress,\n config: ResolvedSpreadsheetOperatorConfig,\n): boolean {\n return isKind(kindAt(grid, address), config.navigableKinds);\n}\n\nexport function isEditable(\n grid: GridDescriptor,\n address: CellAddress,\n config: ResolvedSpreadsheetOperatorConfig,\n): boolean {\n return isKind(kindAt(grid, address), config.editableKinds);\n}\n\nexport function listNavigableAddresses(\n grid: GridDescriptor,\n config: ResolvedSpreadsheetOperatorConfig,\n): CellAddress[] {\n const out: CellAddress[] = [];\n for (let row = 0; row < grid.rowCount; row += 1) {\n for (let col = 0; col < grid.colCount; col += 1) {\n const address = { row, col };\n if (isNavigable(grid, address, config)) out.push(address);\n }\n }\n return out;\n}\n\nfunction step(address: CellAddress, direction: MoveDirection): CellAddress {\n switch (direction) {\n case \"up\":\n return { row: address.row - 1, col: address.col };\n case \"down\":\n return { row: address.row + 1, col: address.col };\n case \"left\":\n return { row: address.row, col: address.col - 1 };\n case \"right\":\n return { row: address.row, col: address.col + 1 };\n }\n}\n\nfunction wrapArrowStart(\n address: CellAddress,\n direction: MoveDirection,\n grid: GridDescriptor,\n): CellAddress {\n switch (direction) {\n case \"up\":\n return { row: grid.rowCount - 1, col: address.col };\n case \"down\":\n return { row: 0, col: address.col };\n case \"left\":\n return { row: address.row, col: grid.colCount - 1 };\n case \"right\":\n return { row: address.row, col: 0 };\n }\n}\n\nexport function moveActiveAddress(\n grid: GridDescriptor,\n from: CellAddress,\n direction: MoveDirection,\n config: ResolvedSpreadsheetOperatorConfig,\n): CellAddress {\n if (grid.rowCount < 1 || grid.colCount < 1) return from;\n const origin = clampAddress(from, grid);\n let cursor = origin;\n const limit = Math.max(grid.rowCount, grid.colCount) + 1;\n for (let i = 0; i < limit; i += 1) {\n const next = step(cursor, direction);\n if (!inBounds(next, grid)) {\n if (config.arrowWrap === \"stop\") return origin;\n cursor = wrapArrowStart(origin, direction, grid);\n } else {\n cursor = next;\n }\n if (sameAddress(cursor, origin)) return origin;\n if (isNavigable(grid, cursor, config)) return cursor;\n }\n return origin;\n}\n\nfunction nextAfterRaster(\n list: CellAddress[],\n from: CellAddress,\n direction: TabDirection,\n): CellAddress | undefined {\n if (direction === \"next\") {\n return list.find((cell) => compareRaster(cell, from) > 0);\n }\n for (let i = list.length - 1; i >= 0; i -= 1) {\n const cell = list[i];\n if (cell && compareRaster(cell, from) < 0) return cell;\n }\n return undefined;\n}\n\nexport function tabActiveAddress(\n grid: GridDescriptor,\n from: CellAddress,\n direction: TabDirection,\n config: ResolvedSpreadsheetOperatorConfig,\n): CellAddress {\n const list = listNavigableAddresses(grid, config);\n if (list.length === 0) return from;\n const idx = list.findIndex((cell) => sameAddress(cell, from));\n if (idx === -1) {\n const found = nextAfterRaster(list, from, direction);\n if (found) return found;\n if (config.wrap === \"wrap\") {\n return direction === \"next\" ? (list[0] ?? from) : (list[list.length - 1] ?? from);\n }\n return from;\n }\n const delta = direction === \"next\" ? 1 : -1;\n const nextIdx = idx + delta;\n if (nextIdx >= 0 && nextIdx < list.length) {\n return list[nextIdx] ?? from;\n }\n if (config.wrap === \"wrap\") {\n return direction === \"next\" ? (list[0] ?? from) : (list[list.length - 1] ?? from);\n }\n return from;\n}\n\nexport function getNextEditableAddress(\n grid: GridDescriptor,\n from: CellAddress,\n direction: NavDirection,\n config: SpreadsheetOperatorConfig = {},\n): CellAddress | null {\n const resolved = resolveConfig(config);\n const origin = clampAddress(from, grid);\n if (direction === \"next\" || direction === \"prev\") {\n const next = tabActiveAddress(grid, origin, direction, resolved);\n return sameAddress(next, origin) && !isNavigable(grid, origin, resolved)\n ? null\n : next;\n }\n const next = moveActiveAddress(grid, origin, direction, resolved);\n if (sameAddress(next, origin) && !isNavigable(grid, origin, resolved)) {\n return isNavigable(grid, next, resolved) ? next : null;\n }\n return next;\n}\n","import type { MoveDirection } from \"./types.js\";\nimport type {\n OperatorAction,\n OperatorKeyEvent,\n ResolvedSpreadsheetOperatorConfig,\n SpreadsheetOperatorState,\n} from \"./types.js\";\n\nconst ARROWS: Record<string, MoveDirection> = {\n ArrowUp: \"up\",\n ArrowDown: \"down\",\n ArrowLeft: \"left\",\n ArrowRight: \"right\",\n};\n\nfunction isPrintable(key: string): boolean {\n return key.length === 1;\n}\n\nexport function keyEventToAction(\n state: SpreadsheetOperatorState,\n event: OperatorKeyEvent,\n config: ResolvedSpreadsheetOperatorConfig,\n): OperatorAction | undefined {\n if (event.isComposing) return undefined;\n if (event.ctrlKey || event.metaKey || event.altKey) return undefined;\n\n const arrow = ARROWS[event.key];\n if (arrow) {\n if (state.mode === \"inactive\") return undefined;\n if (state.mode === \"editing\" && config.arrowInEdit === \"caret\") return undefined;\n return { type: \"move\", direction: arrow };\n }\n\n if (event.key === \"Tab\") {\n if (state.mode === \"inactive\") return undefined;\n return { type: \"tab\", shift: event.shiftKey === true };\n }\n\n if (event.key === \"Enter\") {\n if (state.mode === \"inactive\") return undefined;\n return { type: \"enter\" };\n }\n\n if (event.key === \"Escape\") {\n if (state.mode === \"inactive\") return undefined;\n return { type: \"escape\" };\n }\n\n if (event.key === \"F2\") {\n if (state.mode !== \"active\") return undefined;\n return { type: \"f2\" };\n }\n\n if (state.mode === \"active\" && config.typeToEdit && isPrintable(event.key)) {\n return { type: \"type\", char: event.key };\n }\n\n return undefined;\n}\n","import { clampAddress, sameAddress } from \"./address.js\";\nimport { isEditable, moveActiveAddress, tabActiveAddress } from \"./navigation.js\";\nimport type {\n CellAddress,\n GridDescriptor,\n GridId,\n OperatorAction,\n OperatorContext,\n OperatorEffect,\n SpreadsheetOperatorState,\n} from \"./types.js\";\n\nfunction fieldKeyAt(grid: GridDescriptor, address: CellAddress): string | undefined {\n const cell = grid.cellAt(address);\n return cell.fieldKey ?? cell.id;\n}\n\nfunction commitEffect(\n gridId: GridId,\n address: CellAddress,\n ctx: OperatorContext,\n): OperatorEffect {\n const grid = ctx.grids.get(gridId);\n return {\n type: \"commit\",\n gridId,\n address,\n fieldKey: grid ? fieldKeyAt(grid, address) : undefined,\n phase: \"commit\",\n };\n}\n\nfunction cancelEffect(gridId: GridId, address: CellAddress): OperatorEffect {\n return { type: \"cancel\", gridId, address, phase: \"cancel\" };\n}\n\nfunction startEditEffect(\n gridId: GridId,\n address: CellAddress,\n seed?: string,\n): OperatorEffect {\n return { type: \"startEdit\", gridId, address, seed };\n}\n\nfunction gridOf(\n ctx: OperatorContext,\n gridId: GridId,\n): GridDescriptor | undefined {\n return ctx.grids.get(gridId);\n}\n\nfunction editingOf(\n state: SpreadsheetOperatorState,\n): Extract<SpreadsheetOperatorState, { mode: \"editing\" }> | undefined {\n return state.mode === \"editing\" ? state : undefined;\n}\n\nfunction positionedOf(\n state: SpreadsheetOperatorState,\n): Extract<SpreadsheetOperatorState, { mode: \"active\" | \"editing\" }> | undefined {\n return state.mode === \"inactive\" ? undefined : state;\n}\n\nfunction commitIfEditing(\n state: SpreadsheetOperatorState,\n ctx: OperatorContext,\n): OperatorEffect[] {\n const editing = editingOf(state);\n if (!editing) return [];\n return [commitEffect(editing.gridId, editing.address, ctx)];\n}\n\nfunction enterMoveAddress(\n grid: GridDescriptor,\n from: CellAddress,\n ctx: OperatorContext,\n): CellAddress {\n if (ctx.config.enterMove === \"none\") return from;\n const direction = ctx.config.enterMove === \"right\" ? \"right\" : \"down\";\n return moveActiveAddress(grid, from, direction, ctx.config);\n}\n\nexport function reduceOperator(\n state: SpreadsheetOperatorState,\n action: OperatorAction,\n ctx: OperatorContext,\n): { state: SpreadsheetOperatorState; effects: OperatorEffect[] } {\n switch (action.type) {\n case \"activate\": {\n const grid = gridOf(ctx, action.gridId);\n if (!grid || grid.rowCount < 1 || grid.colCount < 1) {\n return { state, effects: [] };\n }\n const address = clampAddress(action.address, grid);\n const effects = commitIfEditing(state, ctx);\n const next: SpreadsheetOperatorState = {\n mode: \"active\",\n gridId: action.gridId,\n address,\n };\n if (\n state.mode === \"active\" &&\n state.gridId === next.gridId &&\n sameAddress(state.address, next.address) &&\n effects.length === 0\n ) {\n return { state, effects: [] };\n }\n return { state: next, effects };\n }\n case \"deactivate\": {\n if (state.mode === \"inactive\") return { state, effects: [] };\n return { state: { mode: \"inactive\" }, effects: commitIfEditing(state, ctx) };\n }\n case \"move\": {\n const pos = positionedOf(state);\n if (!pos) return { state, effects: [] };\n if (state.mode === \"editing\" && ctx.config.arrowInEdit === \"caret\") {\n return { state, effects: [] };\n }\n const grid = gridOf(ctx, pos.gridId);\n if (!grid) return { state, effects: [] };\n const effects = commitIfEditing(state, ctx);\n const address = moveActiveAddress(grid, pos.address, action.direction, ctx.config);\n return {\n state: { mode: \"active\", gridId: pos.gridId, address },\n effects,\n };\n }\n case \"tab\": {\n const pos = positionedOf(state);\n if (!pos) return { state, effects: [] };\n const grid = gridOf(ctx, pos.gridId);\n if (!grid) return { state, effects: [] };\n const effects = commitIfEditing(state, ctx);\n const address = tabActiveAddress(\n grid,\n pos.address,\n action.shift ? \"prev\" : \"next\",\n ctx.config,\n );\n return {\n state: { mode: \"active\", gridId: pos.gridId, address },\n effects,\n };\n }\n case \"enter\": {\n if (state.mode === \"inactive\") return { state, effects: [] };\n const grid = gridOf(ctx, state.gridId);\n if (!grid) return { state, effects: [] };\n if (state.mode === \"active\") {\n if (!isEditable(grid, state.address, ctx.config)) {\n return { state, effects: [] };\n }\n return {\n state: { mode: \"editing\", gridId: state.gridId, address: state.address },\n effects: [startEditEffect(state.gridId, state.address)],\n };\n }\n const address = enterMoveAddress(grid, state.address, ctx);\n return {\n state: { mode: \"active\", gridId: state.gridId, address },\n effects: [commitEffect(state.gridId, state.address, ctx)],\n };\n }\n case \"escape\": {\n if (state.mode === \"inactive\") return { state, effects: [] };\n if (state.mode === \"editing\") {\n return {\n state: { mode: \"active\", gridId: state.gridId, address: state.address },\n effects: [cancelEffect(state.gridId, state.address)],\n };\n }\n return { state: { mode: \"inactive\" }, effects: [] };\n }\n case \"f2\": {\n if (state.mode !== \"active\") return { state, effects: [] };\n const grid = gridOf(ctx, state.gridId);\n if (!grid || !isEditable(grid, state.address, ctx.config)) {\n return { state, effects: [] };\n }\n return {\n state: { mode: \"editing\", gridId: state.gridId, address: state.address },\n effects: [startEditEffect(state.gridId, state.address)],\n };\n }\n case \"type\": {\n if (!ctx.config.typeToEdit) return { state, effects: [] };\n if (state.mode !== \"active\") return { state, effects: [] };\n const grid = gridOf(ctx, state.gridId);\n if (!grid || !isEditable(grid, state.address, ctx.config)) {\n return { state, effects: [] };\n }\n return {\n state: {\n mode: \"editing\",\n gridId: state.gridId,\n address: state.address,\n seed: action.char,\n },\n effects: [startEditEffect(state.gridId, state.address, action.char)],\n };\n }\n case \"commit\": {\n if (state.mode !== \"editing\") return { state, effects: [] };\n return {\n state: { mode: \"active\", gridId: state.gridId, address: state.address },\n effects: [commitEffect(state.gridId, state.address, ctx)],\n };\n }\n case \"cancel\": {\n if (state.mode !== \"editing\") return { state, effects: [] };\n return {\n state: { mode: \"active\", gridId: state.gridId, address: state.address },\n effects: [cancelEffect(state.gridId, state.address)],\n };\n }\n }\n}\n","import { keyEventToAction } from \"./keymap.js\";\nimport { resolveConfig } from \"./navigation.js\";\nimport { reduceOperator } from \"./reduce.js\";\nimport type {\n GridDescriptor,\n GridId,\n OperatorAction,\n OperatorEffect,\n OperatorKeyEvent,\n SpreadsheetOperatorConfig,\n SpreadsheetOperatorListener,\n SpreadsheetOperatorState,\n} from \"./types.js\";\n\nexport type SpreadsheetOperator = {\n getState(): SpreadsheetOperatorState;\n dispatch(action: OperatorAction): {\n state: SpreadsheetOperatorState;\n effects: readonly OperatorEffect[];\n };\n handleKeyDown(event: OperatorKeyEvent): boolean;\n registerGrid(descriptor: GridDescriptor): void;\n unregisterGrid(gridId: GridId): void;\n getGrid(gridId: GridId): GridDescriptor | undefined;\n subscribe(listener: SpreadsheetOperatorListener): () => void;\n};\n\nexport function createSpreadsheetOperator(\n config: SpreadsheetOperatorConfig = {},\n): SpreadsheetOperator {\n const resolved = resolveConfig(config);\n let state: SpreadsheetOperatorState = { mode: \"inactive\" };\n const grids = new Map<GridId, GridDescriptor>();\n const listeners = new Set<SpreadsheetOperatorListener>();\n\n function notify(effects: readonly OperatorEffect[]): void {\n for (const listener of listeners) listener(state, effects);\n }\n\n function dispatch(action: OperatorAction): {\n state: SpreadsheetOperatorState;\n effects: readonly OperatorEffect[];\n } {\n const result = reduceOperator(state, action, { grids, config: resolved });\n if (result.state === state && result.effects.length === 0) {\n return result;\n }\n state = result.state;\n notify(result.effects);\n return result;\n }\n\n return {\n getState() {\n return state;\n },\n dispatch,\n handleKeyDown(event) {\n const action = keyEventToAction(state, event, resolved);\n if (!action) return false;\n const before = state;\n const result = dispatch(action);\n return result.state !== before || result.effects.length > 0;\n },\n registerGrid(descriptor) {\n grids.set(descriptor.id, descriptor);\n },\n unregisterGrid(gridId) {\n const active = state.mode !== \"inactive\" && state.gridId === gridId;\n if (active) dispatch({ type: \"deactivate\" });\n grids.delete(gridId);\n },\n getGrid(gridId) {\n return grids.get(gridId);\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n"],"mappings":"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","names":[]}