UNPKG

@eristack/spreadsheet-operator

Version:

Headless spreadsheet keyboard operator — active-grid scope, cell navigation, Excel-like Enter/Tab editing

1 lines • 52.6 kB
{"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":[]}