import { selectParentNode } from 'prosemirror-commands';
import { keydownHandler } from 'prosemirror-keymap';
import { AllSelection, NodeSelection, Plugin, TextSelection, } from 'prosemirror-state';
import { Decoration, DecorationSet } from 'prosemirror-view';
import { isSelectableNode } from "../../../utils/nodes.js";
import { isNodeSelection } from "../../../utils/selection.js";
import { arrowDown, arrowLeft, arrowRight, arrowUp, backspace } from "./commands.js";
import "./selection.css";
export const selection = () => new Plugin({
    props: {
        handleKeyDown: keydownHandler({
            ArrowLeft: arrowLeft,
            ArrowRight: arrowRight,
            ArrowUp: arrowUp,
            ArrowDown: arrowDown,
            Backspace: backspace,
        }),
        decorations(state) {
            return getDecorations(state.tr);
        },
        handleClickOn(view, _pos, node, nodePos, _event, direct) {
            if (direct && node.type.spec.allowSelection) {
                return selectNode(nodePos)(view.state, view.dispatch);
            }
            return false;
        },
    },
    view(view) {
        reselect(view);
        return {
            update(view) {
                reselect(view);
            },
        };
    },
});
const reselect = (view) => {
    const { selection: sel } = view.state;
    if (!sel.empty && isNodeSelection(sel) && !isSelectableNode(sel.node)) {
        return selectParentNode(view.state, view.dispatch);
    }
    return false;
};
const selectNode = (pos) => (state, dispatch) => {
    if (dispatch) {
        dispatch(state.tr.setSelection(new NodeSelection(state.doc.resolve(pos))));
    }
    return true;
};
const getDecorations = (tr) => {
    if (tr.selection instanceof NodeSelection) {
        return DecorationSet.create(tr.doc, [
            Decoration.node(tr.selection.from, tr.selection.to, {
                class: 'pm-node-selected',
            }),
        ]);
    }
    if (tr.selection instanceof TextSelection || tr.selection instanceof AllSelection) {
        const decorations = getTopLevelNodesFromSelection(tr.selection, tr.doc).map(({ node, pos }) => {
            return Decoration.node(pos, pos + node.nodeSize, {
                class: 'pm-node-selected',
            });
        });
        return DecorationSet.create(tr.doc, decorations);
    }
    return DecorationSet.empty;
};
const getTopLevelNodesFromSelection = (selection, doc) => {
    const nodes = [];
    if (selection.from !== selection.to) {
        const { from, to } = selection;
        doc.nodesBetween(from, to, (node, pos) => {
            const withinSelection = from <= pos && pos + node.nodeSize <= to;
            if (node && !node.isText && node.type.spec.selectable !== false && withinSelection) {
                nodes.push({ node, pos });
                return false;
            }
            return true;
        });
    }
    return nodes;
};
//# sourceMappingURL=selection.js.map
