Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | 1x 1x 1x 1x 1x 1x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 25x 25x 25x 25x 25x 25x 25x 25x 25x 25x 27x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 27x | import getCaretPosition from 'textarea-caret';
import { AcceptedInputType, DropdownPosition } from '../types';
import { getInputSelectionStart } from './input';
import { DROPDOWN_MARGIN, DROPDOWN_WIDTH } from '../constants';
 
export function getDropdownPosition(
    input: AcceptedInputType,
    dropdownHeight: number
): DropdownPosition {
    const { top, left } = getCaretPosition(
        input,
        getInputSelectionStart(input)
    );
 
    // Calculate base positioning
    const inputRect = input.getBoundingClientRect();
    const baseLeft = left + input.offsetLeft + DROPDOWN_MARGIN;
    
    // Check for horizontal overflow and adjust if necessary
    const adjustedLeft = baseLeft + DROPDOWN_WIDTH > window.innerWidth
        ? window.innerWidth - DROPDOWN_WIDTH - DROPDOWN_MARGIN
        : baseLeft;
 
    // Is there place for the dropdown below the caret?
    if (
        inputRect.top + top + dropdownHeight + 2 * DROPDOWN_MARGIN <=
        window.innerHeight
    ) {
        return {
            toTop: false,
            top: top + input.offsetTop + DROPDOWN_MARGIN,
            left: adjustedLeft,
            width: DROPDOWN_WIDTH,
            height: dropdownHeight,
        };
    }
 
    // If there is place for the dropdown above the caret, show it there
    if (inputRect.top + top - dropdownHeight - DROPDOWN_MARGIN > 0) {
        return {
            toTop: true,
            top: top + input.offsetTop - dropdownHeight - DROPDOWN_MARGIN,
            left: adjustedLeft,
            width: DROPDOWN_WIDTH,
            height: dropdownHeight,
        };
    }
 
    return {
        toTop: true,
        top: input.offsetTop - inputRect.top + DROPDOWN_MARGIN,
        left: adjustedLeft,
        width: DROPDOWN_WIDTH,
        height: window.innerHeight - 2 * DROPDOWN_MARGIN,
    };
}
  |