/*!
 * Built by Revolist OU ❤️
 */
import { h, Host, } from "@stencil/core";
import ColumnService, { getCellEditor } from "../data/column.service";
import { codesLetter } from "../../utils/key.codes";
import { MOBILE_CLASS, SELECTION_BORDER_CLASS } from "../../utils/consts";
import { getRange, isRangeSingleCell } from "../../store/index";
import { collectModelsOfRange, getCell, getFocusCellBasedOnEvent, styleByCellProps, } from "./selection.utils";
import { isEditInput } from "../editors/edit.utils";
import { KeyboardService } from "./keyboard.service";
import { AutoFillService } from "./autofill.service";
import { verifyTouchTarget } from "../../utils/events";
import { getCellData } from "../../utils";
/**
 * Component for overlaying the grid with the selection.
 */
export class OverlaySelection {
    constructor() {
        /**
         * If true applys changes when cell closes if not Escape.
         */
        this.applyChangesOnClose = false;
        this.keyboardService = null;
        this.autoFillService = null;
        this.unsubscribeSelectionStore = [];
    }
    // #endregion
    // #region Listeners
    onMouseMove(e) {
        var _a;
        if (this.selectionStore.get('focus')) {
            (_a = this.autoFillService) === null || _a === void 0 ? void 0 : _a.selectionMouseMove(e);
        }
    }
    /**
     * Action finished inside the document.
     * Pointer left document, clear any active operation.
     */
    onMouseUp() {
        var _a;
        // Clear autofill selection
        // when pointer left document,
        // clear any active operation.
        (_a = this.autoFillService) === null || _a === void 0 ? void 0 : _a.clearAutoFillSelection(this.selectionStore.get('focus'), this.selectionStore.get('range'));
    }
    /**
     * Row drag started.
     * This event is fired when drag action started on cell.
     */
    onCellDrag(e) {
        var _a;
        // Invoke drag start on order editor.
        (_a = this.orderEditor) === null || _a === void 0 ? void 0 : _a.dragStart(e.detail);
    }
    /**
     * Get keyboard down from element.
     * This event is fired when keyboard key is released.
     */
    onKeyUp(e) {
        // Emit before key up event.
        this.beforeKeyUp.emit(Object.assign({ original: e }, this.getData()));
    }
    /**
     * Get keyboard down from element.
     * This event is fired when keyboard key is pressed.
     */
    onKeyDown(e) {
        var _a;
        // Emit before key down event and check if default prevention is set.
        const proxy = this.beforeKeyDown.emit(Object.assign({ original: e }, this.getData()));
        if (e.defaultPrevented || proxy.defaultPrevented) {
            return;
        }
        // Invoke key down on keyboard service.
        (_a = this.keyboardService) === null || _a === void 0 ? void 0 : _a.keyDown(e, this.range, !!this.selectionStore.get('edit'), {
            focus: this.selectionStore.get('focus'),
            range: this.selectionStore.get('range'),
        });
    }
    // #endregion
    /**
     * Selection & Keyboard
     */
    selectionServiceSet(selectionStore) {
        // clear subscriptions
        this.unsubscribeSelectionStore.forEach(v => v());
        this.unsubscribeSelectionStore.length = 0;
        this.unsubscribeSelectionStore.push(selectionStore.onChange('nextFocus', v => v && this.doFocus(v, v)));
        this.keyboardService = new KeyboardService({
            selectionStore,
            range: r => !!r && this.triggerRangeEvent(r),
            focus: (f, changes, focusNextViewport) => {
                if (focusNextViewport) {
                    this.beforeNextViewportFocus.emit(f);
                    return false;
                }
                else {
                    return this.doFocus(f, f, changes);
                }
            },
            change: val => {
                if (this.readonly) {
                    return;
                }
                this.doEdit(val);
            },
            cancel: async () => {
                var _a;
                await ((_a = this.revogrEdit) === null || _a === void 0 ? void 0 : _a.cancelChanges());
                this.closeEdit();
            },
            clearCell: () => !this.readonly && this.clearCell(),
            internalPaste: () => !this.readonly && this.beforeRegionPaste.emit(),
            getData: () => this.getData(),
            selectAll: () => this.selectAll.emit(),
        });
        this.createAutoFillService();
    }
    /** Autofill */
    createAutoFillService() {
        this.autoFillService = new AutoFillService({
            dimensionRow: this.dimensionRow,
            dimensionCol: this.dimensionCol,
            columnService: this.columnService,
            dataStore: this.dataStore,
            clearRangeDataApply: e => this.beforeRangeDataApply.emit(Object.assign(Object.assign(Object.assign({}, e), this.types), { rowDimension: Object.assign({}, this.dimensionRow.state), colDimension: Object.assign({}, this.dimensionCol.state) })),
            setTempRange: e => {
                const tempRangeEvent = this.beforeSetTempRange.emit(Object.assign(Object.assign({ tempRange: e }, this.getData()), this.types));
                if (tempRangeEvent.defaultPrevented) {
                    return null;
                }
                return this.setTempRange.emit(tempRangeEvent.detail.tempRange);
            },
            selectionChanged: e => this.selectionChange.emit(e),
            rangeCopy: e => this.beforeRangeCopyApply.emit(e),
            rangeDataApply: e => this.rangeEditApply.emit(e),
            setRange: e => !!e && this.triggerRangeEvent(e),
            getData: () => this.getData(),
        });
    }
    /** Columns */
    columnServiceSet() {
        var _a;
        (_a = this.columnService) === null || _a === void 0 ? void 0 : _a.destroy();
        this.columnService = new ColumnService(this.dataStore, this.colData);
        this.createAutoFillService();
    }
    connectedCallback() {
        this.columnServiceSet();
        this.selectionServiceSet(this.selectionStore);
    }
    disconnectedCallback() {
        var _a;
        // clear subscriptions
        this.unsubscribeSelectionStore.forEach(v => v());
        this.unsubscribeSelectionStore.length = 0;
        (_a = this.columnService) === null || _a === void 0 ? void 0 : _a.destroy();
    }
    async componentWillRender() {
        var _a, _b;
        const editCell = this.selectionStore.get('edit');
        if (!editCell) {
            await ((_b = (_a = this.revogrEdit) === null || _a === void 0 ? void 0 : _a.beforeDisconnect) === null || _b === void 0 ? void 0 : _b.call(_a));
        }
    }
    renderRange(range) {
        const cell = getCell(range, this.dimensionRow.state, this.dimensionCol.state);
        const styles = styleByCellProps(cell);
        return [
            h("div", { class: SELECTION_BORDER_CLASS, style: styles }, this.isMobileDevice && (h("div", { class: "range-handlers" }, h("span", { class: MOBILE_CLASS }), h("span", { class: MOBILE_CLASS })))),
        ];
    }
    renderEditor() {
        // Check if edit access
        const editCell = this.selectionStore.get('edit');
        // Readonly or Editor closed
        if (this.readonly || !editCell) {
            return null;
        }
        const enteredOrModelValue = editCell.val ||
            getCellData(this.columnService.rowDataModel(editCell.y, editCell.x).value);
        const editable = Object.assign(Object.assign({}, editCell), this.columnService.getSaveData(editCell.y, editCell.x, enteredOrModelValue));
        const renderEvent = this.beforeEditRender.emit(Object.assign(Object.assign({ range: Object.assign(Object.assign({}, editCell), { x1: editCell.x, y1: editCell.y }) }, this.types), { rowDimension: Object.assign({}, this.dimensionRow.state), colDimension: Object.assign({}, this.dimensionCol.state) }));
        // Render prevented
        if (renderEvent.defaultPrevented) {
            return null;
        }
        const cell = getCell(renderEvent.detail.range, renderEvent.detail.rowDimension, renderEvent.detail.colDimension);
        const styles = styleByCellProps(cell);
        return (h("revogr-edit", { style: styles, ref: el => (this.revogrEdit = el), additionalData: this.additionalData, editCell: editable, saveOnClose: this.applyChangesOnClose, onCelleditinit: (e) => {
                this.cellEditDone.emit(e.detail);
            }, column: this.columnService.rowDataModel(editCell.y, editCell.x), editor: getCellEditor(this.columnService.columns[editCell.x], this.editors) }));
    }
    onEditCell(e) {
        if (e.defaultPrevented) {
            return;
        }
        const saveEv = this.beforeCellSave.emit(e.detail);
        if (!saveEv.defaultPrevented) {
            this.cellEdit(saveEv.detail);
        }
        // if not clear navigate to next cell after edit
        if (!saveEv.detail.preventFocus) {
            this.focusNext();
        }
    }
    render() {
        var _a;
        const nodes = [];
        const editCell = this.renderEditor();
        // Editor
        if (editCell) {
            nodes.push(editCell);
        }
        else {
            const range = this.selectionStore.get('range');
            const focus = this.selectionStore.get('focus');
            // Clipboard
            if ((range || focus) && this.useClipboard) {
                nodes.push(h("revogr-clipboard", { readonly: this.readonly, onCopyregion: e => this.onCopy(e.detail), onClearregion: () => !this.readonly && this.clearCell(), ref: e => (this.clipboard = e), onPasteregion: e => this.onPaste(e.detail) }));
            }
            // Range
            if (range) {
                nodes.push(...this.renderRange(range));
            }
            // Autofill
            if (focus && !this.readonly && this.range) {
                nodes.push((_a = this.autoFillService) === null || _a === void 0 ? void 0 : _a.renderAutofill(range, focus, this.isMobileDevice));
            }
            // Order
            if (this.canDrag) {
                nodes.push(h("revogr-order-editor", { ref: e => (this.orderEditor = e), dataStore: this.dataStore, dimensionRow: this.dimensionRow, dimensionCol: this.dimensionCol, parent: this.element, rowType: this.types.rowType, onRowdragstartinit: e => this.rowDragStart(e) }));
            }
        }
        return (h(Host, { key: 'd936e8452e84c7a25ecd6502e929f1a5af69467f', class: { mobile: this.isMobileDevice }, onDblClick: (e) => this.onElementDblClick(e), onMouseDown: (e) => this.onElementMouseDown(e), onTouchStart: (e) => this.onElementMouseDown(e, true), onCloseedit: (e) => this.closeEdit(e),
            // it's done to be able to throw events from different levels, not just from editor
            onCelledit: (e) => this.onEditCell(e) }, nodes, h("slot", { key: 'cd3525d404aa44fd8d06e7fc459777acb8a9d585', name: "data" })));
    }
    /**
     * Executes the focus operation on the specified range of cells.
     */
    doFocus(focus, end, changes) {
        // 1. Trigger beforeFocus event
        const { defaultPrevented } = this.beforeFocusCell.emit(this.columnService.getSaveData(focus.y, focus.x));
        if (defaultPrevented) {
            return false;
        }
        const evData = Object.assign(Object.assign({ range: Object.assign(Object.assign({}, focus), { x1: end.x, y1: end.y }), next: changes }, this.types), { rowDimension: Object.assign({}, this.dimensionRow.state), colDimension: Object.assign({}, this.dimensionCol.state) });
        // 2. Trigger apply focus event
        const applyEvent = this.applyFocus.emit(evData);
        if (applyEvent.defaultPrevented) {
            return false;
        }
        const { range } = applyEvent.detail;
        // 3. Trigger focus event
        return !this.focusCell.emit(Object.assign({ focus: {
                x: range.x,
                y: range.y,
            }, end: {
                x: range.x1,
                y: range.y1,
            } }, applyEvent.detail)).defaultPrevented;
    }
    triggerRangeEvent(range) {
        const type = this.types.rowType;
        // 1. Apply range
        const applyEvent = this.beforeApplyRange.emit(Object.assign(Object.assign({ range: Object.assign({}, range) }, this.types), { rowDimension: Object.assign({}, this.dimensionRow.state), colDimension: Object.assign({}, this.dimensionCol.state) }));
        if (applyEvent.defaultPrevented) {
            return false;
        }
        const data = this.columnService.getRangeTransformedToProps(applyEvent.detail.range, this.dataStore);
        // 2. Before set range
        let e = this.beforeSetRange.emit(data);
        if (e.defaultPrevented) {
            return false;
        }
        // 3. Set range
        e = this.setRange.emit(Object.assign(Object.assign({}, applyEvent.detail.range), { type }));
        if (e.defaultPrevented) {
            return false;
        }
        return !e.defaultPrevented;
    }
    /**
     * Open Editor on DblClick
     */
    onElementDblClick(e) {
        // DblClick prevented outside - Editor will not open
        if (e.defaultPrevented) {
            return;
        }
        // Get data from the component
        const data = this.getData();
        const focusCell = getFocusCellBasedOnEvent(e, data);
        if (!focusCell) {
            return;
        }
        this.doEdit();
    }
    /**
     * Handle mouse down event on Host element
     */
    onElementMouseDown(e, touch = false) {
        var _a;
        // Get the target element from the event object
        const targetElement = e.target;
        // Ignore focus if clicked input
        if (isEditInput(targetElement) || e.defaultPrevented) {
            return;
        }
        // Get data from the component
        const data = this.getData();
        const focusCell = getFocusCellBasedOnEvent(e, data);
        if (!focusCell) {
            return;
        }
        // Set focus on the current cell
        this.focus(focusCell, this.range && e.shiftKey);
        // Initiate autofill selection
        if (this.range) {
            targetElement &&
                ((_a = this.autoFillService) === null || _a === void 0 ? void 0 : _a.selectionStart(targetElement, this.getData()));
            // Prevent default behavior for mouse events,
            // but only if target element is not a mobile input
            if (!touch) {
                e.preventDefault();
            }
            else if (verifyTouchTarget(e.touches[0], MOBILE_CLASS)) {
                // Prevent default behavior for touch events
                // if target element is a mobile input
                e.preventDefault();
            }
        }
    }
    /**
     * Start cell editing
     */
    doEdit(val = '') {
        var _a;
        if (this.canEdit()) {
            const focus = this.selectionStore.get('focus');
            if (!focus) {
                return;
            }
            const data = this.columnService.getSaveData(focus.y, focus.x);
            (_a = this.setEdit) === null || _a === void 0 ? void 0 : _a.emit(Object.assign(Object.assign({}, data), { val }));
        }
    }
    /**
     * Close editor event triggered
     * @param details - if it requires focus next
     */
    async closeEdit(e) {
        this.cancelEdit.emit();
        if (e === null || e === void 0 ? void 0 : e.detail) {
            await this.focusNext();
        }
    }
    /**
     * Edit finished.
     * Close Editor and save.
     */
    cellEdit(e) {
        const dataToSave = this.columnService.getSaveData(e.rgRow, e.rgCol, e.val);
        this.cellEditApply.emit(dataToSave);
    }
    getRegion() {
        const focus = this.selectionStore.get('focus');
        let range = this.selectionStore.get('range');
        if (!range) {
            range = getRange(focus, focus);
        }
        return range;
    }
    onCopy(e) {
        var _a;
        const range = this.getRegion();
        const canCopyEvent = this.beforeCopyRegion.emit(range);
        if (canCopyEvent.defaultPrevented) {
            return false;
        }
        let rangeData;
        if (range) {
            const { data, mapping } = this.columnService.copyRangeArray(range, this.dataStore);
            const event = this.rangeClipboardCopy.emit(Object.assign({ range,
                data,
                mapping }, this.types));
            if (!event.defaultPrevented) {
                rangeData = event.detail.data;
            }
        }
        (_a = this.clipboard) === null || _a === void 0 ? void 0 : _a.doCopy(e, rangeData);
        return true;
    }
    onPaste(data) {
        var _a;
        const focus = this.selectionStore.get('focus');
        const isEditing = this.selectionStore.get('edit') !== null;
        if (!focus || isEditing) {
            return;
        }
        let { changed, range } = this.columnService.getTransformedDataToApply(focus, data);
        const { defaultPrevented: canPaste } = this.rangeClipboardPaste.emit(Object.assign({ data: changed, models: collectModelsOfRange(changed, this.dataStore), range }, this.types));
        if (canPaste) {
            return;
        }
        (_a = this.autoFillService) === null || _a === void 0 ? void 0 : _a.onRangeApply(changed, range, range);
    }
    async focusNext() {
        var _a;
        const canFocus = await ((_a = this.keyboardService) === null || _a === void 0 ? void 0 : _a.keyChangeSelection(new KeyboardEvent('keydown', {
            code: codesLetter.ARROW_DOWN,
        }), this.range));
        if (!canFocus) {
            this.closeEdit();
        }
    }
    clearCell() {
        var _a;
        const range = this.selectionStore.get('range');
        if (range && !isRangeSingleCell(range)) {
            const data = this.columnService.getRangeStaticData(range, '');
            (_a = this.autoFillService) === null || _a === void 0 ? void 0 : _a.onRangeApply(data, range, range);
        }
        else if (this.canEdit()) {
            const focused = this.selectionStore.get('focus');
            if (!focused) {
                return;
            }
            const cell = this.columnService.getSaveData(focused.y, focused.x);
            this.cellEdit({
                rgRow: focused.y,
                rgCol: focused.x,
                val: '',
                type: cell.type,
                prop: cell.prop,
            });
        }
    }
    rowDragStart({ detail }) {
        detail.text = getCellData(this.columnService.rowDataModel(detail.cell.y, detail.cell.x).value);
    }
    /**
     * Verify if edit allowed.
     */
    canEdit() {
        var _a;
        if (this.readonly) {
            return false;
        }
        const focus = this.selectionStore.get('focus');
        return focus && !((_a = this.columnService) === null || _a === void 0 ? void 0 : _a.isReadOnly(focus.y, focus.x));
    }
    get edited() {
        return this.selectionStore.get('edit');
    }
    /**
     * Sets the focus on a cell and optionally edits a range.
     */
    focus(cell, isRangeEdit = false) {
        if (!cell)
            return false;
        const end = cell;
        const start = this.selectionStore.get('focus');
        if (isRangeEdit && start) {
            const range = getRange(start, end);
            if (range) {
                return this.triggerRangeEvent(range);
            }
        }
        return this.doFocus(cell, end);
    }
    get types() {
        return {
            rowType: this.dataStore.get('type'),
            colType: this.columnService.type,
        };
    }
    /**
     * Collect data
     */
    getData() {
        return {
            el: this.element,
            rows: this.dimensionRow.state,
            cols: this.dimensionCol.state,
            lastCell: this.lastCell,
            focus: this.selectionStore.get('focus'),
            range: this.selectionStore.get('range'),
            edit: this.selectionStore.get('edit'),
        };
    }
    static get is() { return "revogr-overlay-selection"; }
    static get originalStyleUrls() {
        return {
            "$": ["revogr-overlay-style.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["revogr-overlay-style.css"]
        };
    }
    static get properties() {
        return {
            "readonly": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Readonly mode."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "readonly"
            },
            "range": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Range selection allowed."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "range"
            },
            "canDrag": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Enable revogr-order-editor component (read more in revogr-order-editor component).\nAllows D&D."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "can-drag"
            },
            "useClipboard": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Enable revogr-clipboard component (read more in revogr-clipboard component).\nAllows copy/paste."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "use-clipboard"
            },
            "selectionStore": {
                "type": "unknown",
                "mutable": false,
                "complexType": {
                    "original": "Observable<SelectionStoreState>",
                    "resolved": "{ range: RangeArea | null; tempRange: RangeArea | null; tempRangeType: string | null; focus: Cell | null; edit: EditCellStore | null; lastCell: Cell | null; nextFocus: Cell | null; }",
                    "references": {
                        "Observable": {
                            "location": "import",
                            "path": "../../utils",
                            "id": "src/utils/index.ts::Observable",
                            "referenceLocation": "Observable"
                        },
                        "SelectionStoreState": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::SelectionStoreState",
                            "referenceLocation": "SelectionStoreState"
                        }
                    }
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Selection, range, focus."
                },
                "getter": false,
                "setter": false
            },
            "dimensionRow": {
                "type": "unknown",
                "mutable": false,
                "complexType": {
                    "original": "Observable<DimensionSettingsState>",
                    "resolved": "DimensionSettingsState",
                    "references": {
                        "Observable": {
                            "location": "import",
                            "path": "../../utils",
                            "id": "src/utils/index.ts::Observable",
                            "referenceLocation": "Observable"
                        },
                        "DimensionSettingsState": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::DimensionSettingsState",
                            "referenceLocation": "DimensionSettingsState"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Dimension settings Y."
                },
                "getter": false,
                "setter": false
            },
            "dimensionCol": {
                "type": "unknown",
                "mutable": false,
                "complexType": {
                    "original": "Observable<DimensionSettingsState>",
                    "resolved": "DimensionSettingsState",
                    "references": {
                        "Observable": {
                            "location": "import",
                            "path": "../../utils",
                            "id": "src/utils/index.ts::Observable",
                            "referenceLocation": "Observable"
                        },
                        "DimensionSettingsState": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::DimensionSettingsState",
                            "referenceLocation": "DimensionSettingsState"
                        }
                    }
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Dimension settings X."
                },
                "getter": false,
                "setter": false
            },
            "dataStore": {
                "type": "unknown",
                "mutable": false,
                "complexType": {
                    "original": "Observable<DSourceState<DataType, DimensionRows>>",
                    "resolved": "\"rgRow\" | \"rowPinEnd\" | \"rowPinStart\" | D | K",
                    "references": {
                        "Observable": {
                            "location": "import",
                            "path": "../../utils",
                            "id": "src/utils/index.ts::Observable",
                            "referenceLocation": "Observable"
                        },
                        "DSourceState": {
                            "location": "import",
                            "path": "@store",
                            "id": "src/store/index.ts::DSourceState",
                            "referenceLocation": "DSourceState"
                        },
                        "DataType": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::DataType",
                            "referenceLocation": "DataType"
                        },
                        "DimensionRows": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::DimensionRows",
                            "referenceLocation": "DimensionRows"
                        }
                    }
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Row data store."
                },
                "getter": false,
                "setter": false
            },
            "colData": {
                "type": "unknown",
                "mutable": false,
                "complexType": {
                    "original": "Observable<DSourceState<ColumnRegular, DimensionCols>>",
                    "resolved": "\"colPinEnd\" | \"colPinStart\" | \"rgCol\" | ColumnRegular<ColumnProp, DataType<any, ColumnProp>>",
                    "references": {
                        "Observable": {
                            "location": "import",
                            "path": "../../utils",
                            "id": "src/utils/index.ts::Observable",
                            "referenceLocation": "Observable"
                        },
                        "DSourceState": {
                            "location": "import",
                            "path": "@store",
                            "id": "src/store/index.ts::DSourceState",
                            "referenceLocation": "DSourceState"
                        },
                        "ColumnRegular": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::ColumnRegular",
                            "referenceLocation": "ColumnRegular"
                        },
                        "DimensionCols": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::DimensionCols",
                            "referenceLocation": "DimensionCols"
                        }
                    }
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Column data store."
                },
                "getter": false,
                "setter": false
            },
            "lastCell": {
                "type": "unknown",
                "mutable": false,
                "complexType": {
                    "original": "Cell",
                    "resolved": "Cell",
                    "references": {
                        "Cell": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::Cell",
                            "referenceLocation": "Cell"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Last real coordinates positions + 1."
                },
                "getter": false,
                "setter": false
            },
            "editors": {
                "type": "unknown",
                "mutable": false,
                "complexType": {
                    "original": "Editors",
                    "resolved": "{ [name: string]: EditorCtr; }",
                    "references": {
                        "Editors": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::Editors",
                            "referenceLocation": "Editors"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Custom editors register."
                },
                "getter": false,
                "setter": false
            },
            "applyChangesOnClose": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If true applys changes when cell closes if not Escape."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "apply-changes-on-close",
                "defaultValue": "false"
            },
            "additionalData": {
                "type": "any",
                "mutable": false,
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Additional data to pass to renderer."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "additional-data"
            },
            "isMobileDevice": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Is mobile view mode."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "is-mobile-device"
            }
        };
    }
    static get events() {
        return [{
                "method": "beforeCopyRegion",
                "name": "beforecopyregion",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Before clipboard copy happened. Validate data before copy.\nTo prevent the default behavior of editing data and use your own implementation, call `e.preventDefault()`."
                },
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                }
            }, {
                "method": "beforeRegionPaste",
                "name": "beforepasteregion",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Before region paste happened."
                },
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                }
            }, {
                "method": "cellEditApply",
                "name": "celleditapply",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Cell edit apply to the data source.\nTriggers datasource edit on the root level."
                },
                "complexType": {
                    "original": "BeforeSaveDataDetails",
                    "resolved": "BeforeSaveDataDetails<DataType, ColumnRegular<ColumnProp, DataType<any, ColumnProp>>>",
                    "references": {
                        "BeforeSaveDataDetails": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::BeforeSaveDataDetails",
                            "referenceLocation": "BeforeSaveDataDetails"
                        }
                    }
                }
            }, {
                "method": "beforeFocusCell",
                "name": "beforecellfocusinit",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Before cell focus."
                },
                "complexType": {
                    "original": "BeforeSaveDataDetails",
                    "resolved": "BeforeSaveDataDetails<DataType, ColumnRegular<ColumnProp, DataType<any, ColumnProp>>>",
                    "references": {
                        "BeforeSaveDataDetails": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::BeforeSaveDataDetails",
                            "referenceLocation": "BeforeSaveDataDetails"
                        }
                    }
                }
            }, {
                "method": "beforeNextViewportFocus",
                "name": "beforenextvpfocus",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Fired when change of viewport happens.\nUsually when we switch between pinned regions."
                },
                "complexType": {
                    "original": "Cell",
                    "resolved": "Cell",
                    "references": {
                        "Cell": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::Cell",
                            "referenceLocation": "Cell"
                        }
                    }
                }
            }, {
                "method": "setEdit",
                "name": "setedit",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Set edit cell."
                },
                "complexType": {
                    "original": "BeforeEdit",
                    "resolved": "BeforeSaveDataDetails<DataType, ColumnRegular<ColumnProp, DataType<any, ColumnProp>>>",
                    "references": {
                        "BeforeEdit": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::BeforeEdit",
                            "referenceLocation": "BeforeEdit"
                        }
                    }
                }
            }, {
                "method": "beforeApplyRange",
                "name": "beforeapplyrange",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Before range applied.\nFirst step in triggerRangeEvent."
                },
                "complexType": {
                    "original": "FocusRenderEvent",
                    "resolved": "FocusRenderEvent",
                    "references": {
                        "FocusRenderEvent": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::FocusRenderEvent",
                            "referenceLocation": "FocusRenderEvent"
                        }
                    }
                }
            }, {
                "method": "beforeSetRange",
                "name": "beforesetrange",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Before range selection applied.\nSecond step in triggerRangeEvent."
                },
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                }
            }, {
                "method": "setRange",
                "name": "setrange",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Set range.\nThird step in triggerRangeEvent."
                },
                "complexType": {
                    "original": "RangeArea & { type: MultiDimensionType }",
                    "resolved": "RangeArea & { type: MultiDimensionType; }",
                    "references": {
                        "RangeArea": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::RangeArea",
                            "referenceLocation": "RangeArea"
                        },
                        "MultiDimensionType": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::MultiDimensionType",
                            "referenceLocation": "MultiDimensionType"
                        }
                    }
                }
            }, {
                "method": "beforeEditRender",
                "name": "beforeeditrender",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Before editor render."
                },
                "complexType": {
                    "original": "FocusRenderEvent",
                    "resolved": "FocusRenderEvent",
                    "references": {
                        "FocusRenderEvent": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::FocusRenderEvent",
                            "referenceLocation": "FocusRenderEvent"
                        }
                    }
                }
            }, {
                "method": "selectAll",
                "name": "selectall",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Select all cells from keyboard."
                },
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                }
            }, {
                "method": "cancelEdit",
                "name": "canceledit",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Cancel edit. Used for editors support when editor close requested."
                },
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                }
            }, {
                "method": "setTempRange",
                "name": "settemprange",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Set temp range area during autofill."
                },
                "complexType": {
                    "original": "Nullable<TempRange> | null",
                    "resolved": "null | { type: string; area: RangeArea; }",
                    "references": {
                        "Nullable": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::Nullable",
                            "referenceLocation": "Nullable"
                        },
                        "TempRange": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::TempRange",
                            "referenceLocation": "TempRange"
                        }
                    }
                }
            }, {
                "method": "beforeSetTempRange",
                "name": "beforesettemprange",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Before set temp range area during autofill."
                },
                "complexType": {
                    "original": "{ tempRange: Nullable<TempRange> | null } & EventData & AllDimensionType",
                    "resolved": "{ tempRange: Nullable<TempRange> | null; } & EventData & AllDimensionType",
                    "references": {
                        "Nullable": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::Nullable",
                            "referenceLocation": "Nullable"
                        },
                        "TempRange": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::TempRange",
                            "referenceLocation": "TempRange"
                        },
                        "EventData": {
                            "location": "import",
                            "path": "./selection.utils",
                            "id": "src/components/overlay/selection.utils.ts::EventData",
                            "referenceLocation": "EventData"
                        },
                        "AllDimensionType": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::AllDimensionType",
                            "referenceLocation": "AllDimensionType"
                        }
                    }
                }
            }, {
                "method": "applyFocus",
                "name": "applyfocus",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Before cell get focused.\nTo prevent the default behavior of applying the edit data, you can call `e.preventDefault()`."
                },
                "complexType": {
                    "original": "FocusRenderEvent",
                    "resolved": "FocusRenderEvent",
                    "references": {
                        "FocusRenderEvent": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::FocusRenderEvent",
                            "referenceLocation": "FocusRenderEvent"
                        }
                    }
                }
            }, {
                "method": "focusCell",
                "name": "focuscell",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Cell get focused.\nTo prevent the default behavior of applying the edit data, you can call `e.preventDefault()`."
                },
                "complexType": {
                    "original": "ApplyFocusEvent & FocusRenderEvent",
                    "resolved": "ApplyFocusEvent & FocusRenderEvent",
                    "references": {
                        "ApplyFocusEvent": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::ApplyFocusEvent",
                            "referenceLocation": "ApplyFocusEvent"
                        },
                        "FocusRenderEvent": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::FocusRenderEvent",
                            "referenceLocation": "FocusRenderEvent"
                        }
                    }
                }
            }, {
                "method": "beforeRangeDataApply",
                "name": "beforerangedataapply",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Range data apply."
                },
                "complexType": {
                    "original": "FocusRenderEvent",
                    "resolved": "FocusRenderEvent",
                    "references": {
                        "FocusRenderEvent": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::FocusRenderEvent",
                            "referenceLocation": "FocusRenderEvent"
                        }
                    }
                }
            }, {
                "method": "selectionChange",
                "name": "selectionchangeinit",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Autofill data in range. First step in applyRangeWithData"
                },
                "complexType": {
                    "original": "ChangedRange",
                    "resolved": "{ type: DimensionRows; colType: DimensionCols; newRange: RangeArea; oldRange: RangeArea; mapping: OldNewRangeMapping; newData: { [newRowIndex: number]: DataType; }; }",
                    "references": {
                        "ChangedRange": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::ChangedRange",
                            "referenceLocation": "ChangedRange"
                        }
                    }
                }
            }, {
                "method": "beforeRangeCopyApply",
                "name": "beforerangecopyapply",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Before range copy."
                },
                "complexType": {
                    "original": "ChangedRange",
                    "resolved": "{ type: DimensionRows; colType: DimensionCols; newRange: RangeArea; oldRange: RangeArea; mapping: OldNewRangeMapping; newData: { [newRowIndex: number]: DataType; }; }",
                    "references": {
                        "ChangedRange": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::ChangedRange",
                            "referenceLocation": "ChangedRange"
                        }
                    }
                }
            }, {
                "method": "rangeEditApply",
                "name": "rangeeditapply",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Range data apply.\nTriggers datasource edit on the root level."
                },
                "complexType": {
                    "original": "BeforeRangeSaveDataDetails",
                    "resolved": "TModel",
                    "references": {
                        "BeforeRangeSaveDataDetails": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::BeforeRangeSaveDataDetails",
                            "referenceLocation": "BeforeRangeSaveDataDetails"
                        }
                    }
                }
            }, {
                "method": "rangeClipboardCopy",
                "name": "clipboardrangecopy",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Range copy."
                },
                "complexType": {
                    "original": "RangeClipboardCopyEventProps",
                    "resolved": "RangeClipboardCopyEventProps<any>",
                    "references": {
                        "RangeClipboardCopyEventProps": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::RangeClipboardCopyEventProps",
                            "referenceLocation": "RangeClipboardCopyEventProps"
                        }
                    }
                }
            }, {
                "method": "rangeClipboardPaste",
                "name": "clipboardrangepaste",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Range paste event."
                },
                "complexType": {
                    "original": "RangeClipboardPasteEvent",
                    "resolved": "RangeClipboardPasteEvent<DataType<any, ColumnProp>>",
                    "references": {
                        "RangeClipboardPasteEvent": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::RangeClipboardPasteEvent",
                            "referenceLocation": "RangeClipboardPasteEvent"
                        }
                    }
                }
            }, {
                "method": "beforeKeyDown",
                "name": "beforekeydown",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Before key up event proxy, used to prevent key up trigger.\nIf you have some custom behaviour event, use this event to check if it wasn't processed by internal logic.\nCall preventDefault()."
                },
                "complexType": {
                    "original": "{ original: KeyboardEvent } & EventData",
                    "resolved": "{ original: KeyboardEvent; } & EventData",
                    "references": {
                        "KeyboardEvent": {
                            "location": "global",
                            "id": "global::KeyboardEvent"
                        },
                        "EventData": {
                            "location": "import",
                            "path": "./selection.utils",
                            "id": "src/components/overlay/selection.utils.ts::EventData",
                            "referenceLocation": "EventData"
                        }
                    }
                }
            }, {
                "method": "beforeKeyUp",
                "name": "beforekeyup",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Before key down event proxy, used to prevent key down trigger.\nIf you have some custom behaviour event, use this event to check if it wasn't processed by internal logic.\nCall preventDefault()."
                },
                "complexType": {
                    "original": "{ original: KeyboardEvent } & EventData",
                    "resolved": "{ original: KeyboardEvent; } & EventData",
                    "references": {
                        "KeyboardEvent": {
                            "location": "global",
                            "id": "global::KeyboardEvent"
                        },
                        "EventData": {
                            "location": "import",
                            "path": "./selection.utils",
                            "id": "src/components/overlay/selection.utils.ts::EventData",
                            "referenceLocation": "EventData"
                        }
                    }
                }
            }, {
                "method": "beforeCellSave",
                "name": "beforecellsave",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Runs before cell save.\nCan be used to override or cancel original save."
                },
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                }
            }, {
                "method": "cellEditDone",
                "name": "celledit",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Runs when edit finished save started, first in chain event"
                },
                "complexType": {
                    "original": "SaveDataDetails",
                    "resolved": "{ rgRow: number; rgCol: number; type: DimensionRows; prop: ColumnProp; val: any; preventFocus?: boolean | undefined; }",
                    "references": {
                        "SaveDataDetails": {
                            "location": "import",
                            "path": "@type",
                            "id": "src/types/index.ts::SaveDataDetails",
                            "referenceLocation": "SaveDataDetails"
                        }
                    }
                }
            }];
    }
    static get elementRef() { return "element"; }
    static get watchers() {
        return [{
                "propName": "selectionStore",
                "methodName": "selectionServiceSet"
            }, {
                "propName": "dimensionRow",
                "methodName": "createAutoFillService"
            }, {
                "propName": "dimensionCol",
                "methodName": "createAutoFillService"
            }, {
                "propName": "dataStore",
                "methodName": "columnServiceSet"
            }, {
                "propName": "colData",
                "methodName": "columnServiceSet"
            }];
    }
    static get listeners() {
        return [{
                "name": "touchmove",
                "method": "onMouseMove",
                "target": "document",
                "capture": false,
                "passive": true
            }, {
                "name": "mousemove",
                "method": "onMouseMove",
                "target": "document",
                "capture": false,
                "passive": true
            }, {
                "name": "touchend",
                "method": "onMouseUp",
                "target": "document",
                "capture": false,
                "passive": true
            }, {
                "name": "mouseup",
                "method": "onMouseUp",
                "target": "document",
                "capture": false,
                "passive": true
            }, {
                "name": "mouseleave",
                "method": "onMouseUp",
                "target": "document",
                "capture": false,
                "passive": true
            }, {
                "name": "dragstartcell",
                "method": "onCellDrag",
                "target": undefined,
                "capture": false,
                "passive": false
            }, {
                "name": "keyup",
                "method": "onKeyUp",
                "target": "document",
                "capture": false,
                "passive": false
            }, {
                "name": "keydown",
                "method": "onKeyDown",
                "target": "document",
                "capture": false,
                "passive": false
            }];
    }
}
