"use strict";

exports.__esModule = true;
exports.useCellFocusAndEditing = useCellFocusAndEditing;
var _react = require("react");
var _reactDom = require("react-dom");
function useCellFocusAndEditing({
  state,
  rowKey,
  columnId,
  cellRef,
  editInputRef
}) {
  const {
    cellInteraction
  } = state;
  const column = state._columnMap.get(columnId);
  const resolved = column ? state.resolveCellTypeByColumnId(column.id) : null;
  const isFocused = cellInteraction.isCellFocused(rowKey, columnId);
  const isEditing = cellInteraction.isCellEditing(rowKey, columnId);
  const isEditable = state.isCellEditable(rowKey, columnId);

  // Register the focused cell's DOM element on the state so
  // scrollFocusedCellIntoView can use it. useLayoutEffect ensures
  // the element is set before the requestAnimationFrame in
  // scrollFocusedCellIntoView runs.
  (0, _react.useLayoutEffect)(() => {
    if (isFocused) {
      cellInteraction.focusedCellElement = cellRef.current;
    }
    return () => {
      if (cellInteraction.focusedCellElement === cellRef.current) {
        cellInteraction.focusedCellElement = null;
      }
    };
  }, [isFocused, cellRef, cellInteraction]);

  // When focused (not editing): focus the cell div so it receives keyboard events.
  // When editing starts: focus the input, then place caret at end in a setTimeout
  // so it runs after the browser's own selection (e.g. from autoSelect) settles.
  // Skip caret placement if the input already has a non-collapsed selection.
  (0, _react.useEffect)(() => {
    if (!isFocused) {
      return;
    }
    if (isEditing) {
      if (editInputRef.current && document.activeElement !== editInputRef.current) {
        editInputRef.current.focus();
      }
      setTimeout(() => {
        var _input$value;
        // Use document.activeElement rather than editInputRef.current because
        // editInputRef may point to a React component instance (e.g. InputArea)
        // rather than the underlying DOM element, which has no .value property.
        const input = document.activeElement;
        if (!input || !('selectionStart' in input)) {
          return;
        }
        if (input.selectionStart !== input.selectionEnd) {
          return;
        }
        const len = ((_input$value = input.value) == null ? void 0 : _input$value.length) ?? 0;
        input.setSelectionRange(len, len);
      }, 0);
    } else {
      var _cellRef$current;
      // Don't steal focus if a descendant already has it (e.g. image cell's
      // inner-focus buttons). The gridcell only needs focusing when it isn't
      // already within the active focus subtree.
      if (!((_cellRef$current = cellRef.current) != null && _cellRef$current.contains(document.activeElement))) {
        var _cellRef$current2;
        (_cellRef$current2 = cellRef.current) == null || _cellRef$current2.focus({
          preventScroll: true
        });
      }
    }
  }, [isFocused, isEditing, cellRef, editInputRef]);
  const handleActivate = (0, _react.useCallback)(() => {
    if (resolved != null && resolved.toggleValue) {
      state.cellValue.toggleCell(rowKey, columnId);
    } else {
      cellInteraction.startEdit();
    }
  }, [resolved, state, rowKey, columnId, cellInteraction]);

  // Handle Enter and type-to-edit at the cell level
  const onKeyDown = (0, _react.useCallback)(e => {
    if (!isFocused || !isEditable || isEditing) {
      return;
    }
    if (state.updateItemDisabled) {
      return;
    }
    if (e.key === 'Enter') {
      e.preventDefault();
      if (resolved != null && resolved.showEditWhenFocused) {
        var _editInputRef$current;
        // EditComponent is always visible. Focus into its first interactive
        // element (inner focus) rather than entering full edit mode now —
        // the cell type calls onStartEdit() itself right before any external
        // UI (media manager / modal) opens, which is the only time isEditing
        // needs to be true for useClearFocusOnBlur protection.
        (_editInputRef$current = editInputRef.current) == null || _editInputRef$current.focus();
      } else {
        handleActivate();
      }
      return;
    }

    // Type-to-edit: prevent the browser's default text insertion, start
    // edit mode, then set the value programmatically via React state.
    // startEdit() must come before setEditingValue() because it resets
    // editingValue to undefined.
    if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey && !e.nativeEvent.isComposing) {
      var _editInputRef$current3;
      // Cell-type-level gate: only cell types that define onTypeToEdit support
      // type-to-edit. Absence of onTypeToEdit is the natural opt-out (e.g. boolean).
      if (!(resolved != null && resolved.onTypeToEdit)) {
        return;
      }

      // Key-level gate: onTypeToEdit returning undefined means "block this key"
      // (e.g. number blocks non-digit keys).
      const typeResult = resolved.onTypeToEdit({
        key: e.key,
        validation: column == null ? void 0 : column.validation
      });
      if (typeResult === undefined) {
        return;
      }
      if (resolved.nativeTypeToEdit) {
        var _editInputRef$current2;
        // Synchronously enter edit mode and focus the input within the same
        // keydown event. The browser's default action then delivers the
        // character to the now-focused input — no programmatic seeding.
        // Mirrors cms-web's `focusOnTyping` pattern (table-cell-wrapper.tsx).
        (0, _reactDom.flushSync)(() => {
          cellInteraction.startEdit(undefined, undefined, {
            kind: 'type',
            key: e.key
          });
          if ('value' in typeResult) {
            cellInteraction.setEditingValue(typeResult.value);
          }
        });
        (_editInputRef$current2 = editInputRef.current) == null || _editInputRef$current2.focus();
        e.stopPropagation();
        // Intentionally no preventDefault — the browser inserts the
        // character into the now-focused input naturally.
        return;
      }
      e.preventDefault();
      cellInteraction.startEdit(undefined, undefined, {
        kind: 'type',
        key: e.key
      });
      if ('value' in typeResult) {
        // Cell type provides an explicit pre-populated value (e.g. first typed
        // char for text, or the digit for number).
        cellInteraction.setEditingValue(typeResult.value);
      }
      // onTypeToEdit returned {} (no value): enter edit mode with current value intact
      // (e.g. select/date open their picker without pre-populating).

      // Best-effort: editInputRef.current is null here because the Edit
      // component only mounts after isEditing flips. The useEffect above
      // is the reliable focus path once the component renders.
      (_editInputRef$current3 = editInputRef.current) == null || _editInputRef$current3.focus();
      e.stopPropagation();
    }
  }, [editInputRef, isFocused, isEditable, isEditing, state, cellInteraction, resolved, handleActivate]);
  return (0, _react.useMemo)(() => ({
    onKeyDown
  }), [onKeyDown]);
}
//# sourceMappingURL=useCellFocusAndEditing.js.map