"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UITable = void 0;
const react_1 = __importDefault(require("react"));
const react_2 = require("@fluentui/react");
const UICheckbox_1 = require("../UICheckbox");
const UIInput_1 = require("../UIInput");
const UIDropdown_1 = require("../UIDropdown");
const UIComboBox_1 = require("../UIComboBox");
const UIDatePicker_1 = require("../UIDatePicker");
const UITable_helper_1 = require("./UITable-helper");
const types_1 = require("./types");
require("./UITable.scss");
/**
 * UITable component
 * based on: https://developer.microsoft.com/en-us/fluentui#/controls/web/detailslist
 *
 * @exports
 * @class {UITable}
 * @extends {React.Component<UITableProps, UITableState>}
 */
class UITable extends react_1.default.Component {
    /**
     * Initializes component properties.
     *
     * @param props
     */
    constructor(props) {
        super(props);
        this.inputRefs = {};
        this.activeElement = {};
        this.caretPosition = -1;
        this._onRenderRow = (props) => {
            if (!props) {
                return null;
            }
            const toggle = !!this.props.renderInputs;
            return react_1.default.createElement(react_2.DetailsRow, { "data-selection-toggle": toggle, rowFieldsAs: this.renderRowFields.bind(this), ...props });
        };
        this.onComboBoxChange = (option) => {
            this.setState((prevState) => {
                const editedCell = prevState.editedCell ?? this.activeElement;
                if (editedCell && option) {
                    editedCell.newValue = option.text;
                }
                return { editedCell };
            });
        };
        this.onDropdownCellValueChange = (selectedOption, item, rowIndex, column) => {
            const newValue = selectedOption.key;
            if (typeof this.props.onSave === 'function' &&
                typeof rowIndex === 'number' &&
                Number.isInteger(rowIndex) &&
                column) {
                const currentValue = this.props.items[rowIndex][column.key];
                const editedCell = { rowIndex, item, column, errorMessage: undefined };
                if (currentValue !== newValue) {
                    this.props.onSave(editedCell, newValue);
                }
                const field = column?.fieldName;
                if (field && item) {
                    item[field] = newValue;
                }
            }
            this.cancelEdit();
        };
        this.state = {
            columns: props.columns || [],
            items: props.items || []
        };
        this.tableRef = react_1.default.createRef();
        this.selection = new react_2.Selection({
            onSelectionChanged: () => {
                if (typeof this.props.onSelectionChange !== 'function') {
                    return;
                }
                this.props.onSelectionChange(this.selection.getSelectedIndices());
            }
        });
        if (this.props.selectionRef) {
            this.props.selectionRef.current = this.selection;
        }
        this.onTextInputChange = this.onTextInputChange.bind(this);
        this.onComboBoxChange = this.onComboBoxChange.bind(this);
        this.onDocumentMousedown = this.onDocumentMousedown.bind(this);
        this.onKeyDown = this.onKeyDown.bind(this);
        this.onComboBoxKeyDownCapture = this.onComboBoxKeyDownCapture.bind(this);
        this.validateCell = this.validateCell.bind(this);
        this.editNextCell = this.editNextCell.bind(this);
        this._onColumnClick = this._onColumnClick.bind(this);
        this._onCellRender = this._onCellRender.bind(this);
        this._onRenderCheckbox = this._onRenderCheckbox.bind(this);
        this._onRenderField = this._onRenderField?.bind(this);
        this._onRenderRow = this._onRenderRow?.bind(this);
        this._onRenderItemColumn = this._onRenderItemColumn?.bind(this);
        this._onCellActivation = this._onCellActivation?.bind(this);
    }
    componentDidMount() {
        this.onDocMousedown = this.onDocumentMousedown;
        document.addEventListener('mousedown', this.onDocMousedown, true);
        window.dispatchEvent(new Event('resize'));
        this._setTextRefs();
    }
    componentWillUnmount() {
        document.removeEventListener('mousedown', this.onDocMousedown);
    }
    /**
     * On component update.
     *
     * @param prevProps
     * @param prevState
     */
    componentDidUpdate(prevProps, prevState) {
        const scrollContainer = document.querySelector('.ms-ScrollablePane--contentContainer');
        if (scrollContainer) {
            const left = scrollContainer.scrollLeft || 0;
            requestAnimationFrame(() => (scrollContainer.scrollLeft = left));
        }
        if (prevProps.items !== this.props.items) {
            this.setState({ items: this.props.items });
            this._setTextRefs();
        }
        if (prevProps.columns !== this.props.columns) {
            this.setState({ columns: this.props.columns });
        }
        if (prevProps.dataSetKey !== this.props.dataSetKey) {
            this.setState({ editedCell: undefined });
        }
        if (typeof this.props.selectedRow !== 'undefined' && prevProps.selectedRow !== this.props.selectedRow) {
            (0, UITable_helper_1.scrollToRow)(this.props.selectedRow, this.tableRef?.current);
        }
        if (this.props.scrollToAddedRow) {
            const dataSetChanged = this.props.dataSetKey !== prevProps.dataSetKey;
            const { items } = this.state;
            const { items: prevItems } = prevState;
            const itemsDelta = items.length - prevItems.length;
            const shouldScrollToNewRow = !dataSetChanged && itemsDelta === 1;
            if (shouldScrollToNewRow && this.tableRef?.current) {
                const newRowIndex = items.length - 1;
                this.tableRef.current.scrollToIndex(newRowIndex);
            }
        }
        const { selectedColumnId } = this.props;
        const { selectedColumnId: prevSelectedColumnId } = prevProps;
        // Due to table rendering using columns data from state, instead of props,
        // to sync selected column change callback with rendered dataset change
        // selected column id/key needs to be stored on a state level along with columns data
        if (selectedColumnId !== prevSelectedColumnId) {
            this.setState({ selectedColumnId });
        }
        const columnIsSelected = typeof this.state.selectedColumnId !== 'undefined';
        const selectedColumnDidChange = prevState.selectedColumnId !== this.state.selectedColumnId;
        if (columnIsSelected && selectedColumnDidChange) {
            (0, UITable_helper_1.scrollToColumn)(this.state.selectedColumnId || '', this.state.columns, this.props.selectedRow || 0, this.props.showRowNumbers);
        }
        this._restoreCaretPosition();
    }
    /**
     * Restores the caret position. Caret position gets lost when validation finds issue in cell.
     */
    _restoreCaretPosition() {
        const editedCell = this.state.editedCell;
        if (this.caretPosition !== -1 && typeof editedCell?.rowIndex === 'number' && editedCell.column?.key) {
            const cell = (0, UITable_helper_1.getCellFromCoords)(editedCell.rowIndex, editedCell.column.key, this.props.columns, true);
            const input = cell.querySelector('input');
            if (input && input.selectionStart !== this.caretPosition) {
                input.setSelectionRange(this.caretPosition, this.caretPosition);
                this.caretPosition = -1;
            }
        }
    }
    _setTextRefs() {
        if (this.props.columns && this.props.items) {
            for (const rowIndexTmp in this.props.items) {
                for (const col of this.props.columns) {
                    if (col.editable === true && this.inputRefs) {
                        this.inputRefs[rowIndexTmp] = this.inputRefs[rowIndexTmp] || {};
                        this.inputRefs[rowIndexTmp][col.key] = react_1.default.createRef();
                    }
                }
            }
        }
    }
    /**
     * On render row fields event.
     *
     * @param props
     * @returns {JSX.Element}
     */
    renderRowFields(props) {
        // disabled is set to false when selectionMode === undefined || selectionMode === SelectionMode.single
        let disabled = false;
        const selectionMode = this.props.selectionMode;
        if (selectionMode === react_2.SelectionMode.multiple || selectionMode === react_2.SelectionMode.none) {
            disabled = true;
        }
        return (react_1.default.createElement("div", { "data-selection-disabled": disabled },
            react_1.default.createElement(react_2.DetailsRowFields, { ...props })));
    }
    /**
     * On render field event.
     *
     * @param props
     * @param defaultRender
     * @returns {null | JSX.Element}
     */
    _onRenderField(props, defaultRender) {
        if (!props || !defaultRender) {
            return null;
        }
        const cell = defaultRender(props);
        const { column, cellValueKey } = props;
        let key = column.key;
        if (cellValueKey !== undefined) {
            key += `-${cellValueKey}`;
        }
        const onClick = (e) => {
            const target = e?.target;
            const targetTag = target?.tagName;
            if (['INPUT', 'TEXTAREA', 'SELECT'].includes(targetTag)) {
                return;
            }
            const { item, rowIndex, column } = this.activeElement;
            this._onCellClick(e, item, rowIndex || 0, column);
        };
        // in app-migrator, show a warning message for library projects on main migration view
        if (props.item.hideCells && props.column.fieldName === 'moduleName' && !props.item.status) {
            return (react_1.default.createElement("div", { key: key, ...(cell?.props || {}), "data-is-focusable": true, onClick: onClick, tabIndex: "0", role: "gridcell" },
                cell?.props?.children || null,
                react_1.default.createElement("div", { className: "table-item-warning" }, "This is a reuse library and does not require input during migration")));
        }
        else {
            return (react_1.default.createElement("div", { key: key, ...(cell?.props || {}), "data-is-focusable": true, onClick: onClick, tabIndex: "0", role: "gridcell" }, cell?.props?.children || null));
        }
    }
    // just sets the active element property on the table, to track it later
    /**
     * On cell activation event.
     *
     * @param item
     * @param rowIndex
     * @param ev
     */
    _onCellActivation(item, rowIndex, ev) {
        const rowEl = ev?.target?.closest('.ms-DetailsRow');
        let column = {};
        const cells = rowEl?.querySelectorAll('.ms-DetailsRow-fields .ms-DetailsRow-cell');
        if (!cells?.length) {
            return;
        }
        // focusing cell, not the row
        const cellEl = ev?.target?.closest('.ms-DetailsRow-cell');
        if (cellEl) {
            const cellIdx = Array.from(cells).indexOf(cellEl);
            if (cellIdx === -1) {
                return;
            }
            column = this.props.columns[cellIdx];
            if (!column) {
                return;
            }
        }
        this.activeElement = { item, rowIndex: rowIndex || 0, column };
        if (this.props.renderInputs && column?.editable) {
            const isDropdown = this.activeElement?.column?.columnControlType === types_1.ColumnControlType?.UIDropdown;
            if (!isDropdown && this.state.editedCell?.column?.key !== this.activeElement?.column?.key) {
                this.setState({ editedCell: this.activeElement });
            }
        }
    }
    /**
     * On render item  column event.
     *
     * @param {UIDocument} item
     * @param {number} index
     * @param {UIColumn} column
     * @returns {React.ReactNode}
     */
    _onRenderItemColumn(item, index, column) {
        if (column?.key === '__row_number__') {
            return react_1.default.createElement("div", { className: "ms-DetailsList-row-number" }, (index || 0) + 1);
        }
        return item[column?.fieldName || ''] || '';
    }
    // Replace weird radio-button-checkboxes with proper checkboxes
    /**
     * On render checkbox event.
     *
     * @param {IDetailsListCheckboxProps | undefined} props
     * @returns {React.ReactElement}
     */
    _onRenderCheckbox(props) {
        return react_1.default.createElement(UICheckbox_1.UICheckbox, { ...props });
    }
    // COLUMN HEADER SORT
    /**
     * On column click event.
     *
     * @param ev
     * @param column
     */
    _onColumnClick(ev, column) {
        const { columns, items } = this.state;
        const newColumns = columns.slice();
        const currColumn = newColumns.find((currCol) => column.key === currCol.key);
        newColumns.forEach((newCol) => {
            if (newCol === currColumn) {
                currColumn.isSortedDescending = !currColumn.isSortedDescending;
                currColumn.isSorted = true;
            }
            else {
                newCol.isSorted = false;
                newCol.isSortedDescending = false;
            }
        });
        const field = currColumn.fieldName || currColumn.name || '';
        const newItems = (0, UITable_helper_1._copyAndSort)(items, field, currColumn.isSortedDescending);
        this.setState({ columns: newColumns, items: newItems });
    }
    // CELL EDITING
    /**
     * On start edit event call.
     *
     * @param rowIndex
     * @param item
     * @param column
     * @param errorMessage
     */
    startEdit(rowIndex, item, column, errorMessage) {
        const { editedCell } = this.state;
        const isAlreadyInEdit = editedCell?.rowIndex === rowIndex && column?.key && editedCell?.column?.key === column?.key;
        if (!isAlreadyInEdit) {
            this.setState({ editedCell: { rowIndex, item, column, errorMessage } });
            if (!this.props.renderInputs) {
                this.rerenderTable();
            }
        }
        requestAnimationFrame(() => {
            if (column?.columnControlType === types_1.ColumnControlType.UITextInput) {
                this.inputRefs?.[rowIndex][column?.key]?.current?.select();
            }
            else if (column?.columnControlType === types_1.ColumnControlType.UICombobox ||
                column?.columnControlType === types_1.ColumnControlType.UIBooleanSelect) {
                const combo = this.inputRefs?.[rowIndex][column?.key];
                (0, UITable_helper_1.getComboBoxInput)(combo)?.focus();
            }
            else if (column?.columnControlType === types_1.ColumnControlType.UIDatePicker) {
                this.inputRefs?.[rowIndex][column?.key]?.current?.select();
            }
            else if (column?.key) {
                const otherElement = this.inputRefs?.[rowIndex][column.key]?.current;
                otherElement.focus();
            }
        });
    }
    rerenderTable() {
        if (this.tableRef.current) {
            this.tableRef.current.forceUpdate();
        }
    }
    cancelEdit() {
        this.caretPosition = -1;
        this.setState({ editedCell: undefined });
        this.rerenderTable();
    }
    /**
     * Get the current string value from a cell editor ref.
     *
     * @param compRef - React ref to the cell editor control
     * @param columnControlType - type of the cell editor control
     * @returns current string value from the control
     */
    getRefValue(compRef, columnControlType) {
        if (columnControlType === types_1.ColumnControlType.UITextInput ||
            columnControlType === types_1.ColumnControlType.UIDatePicker) {
            return compRef?.current?.value || '';
        }
        if (columnControlType === types_1.ColumnControlType.UICombobox ||
            columnControlType === types_1.ColumnControlType.UIBooleanSelect) {
            const combo = compRef;
            return (0, UITable_helper_1.getComboBoxInput)(combo)?.value || '';
        }
        return '';
    }
    /**
     * On save cell event.
     *
     * @param cancelEdit
     * @param value
     */
    saveCell(cancelEdit = false, value) {
        this.caretPosition = -1;
        if (typeof this.props.onSave === 'function' && this.state.editedCell) {
            const { rowIndex, column } = this.state.editedCell;
            if (column?.columnControlType !== types_1.ColumnControlType.UIDropdown && !this.state.editedCell.errorMessage) {
                let compRef;
                if (column && this?.inputRefs?.[rowIndex]?.[column.key]) {
                    compRef = this?.inputRefs[rowIndex][column.key];
                }
                const currentValue = column && this.props.items[rowIndex][column.key];
                const refValue = this.getRefValue(compRef, column?.columnControlType);
                const newValue = value ?? refValue;
                if (currentValue !== newValue) {
                    this.props.onSave(this.state.editedCell, newValue);
                }
                const item = this.state.editedCell?.item;
                const field = column?.fieldName;
                if (field && item) {
                    item[field] = newValue;
                }
            }
        }
        if (cancelEdit) {
            this.cancelEdit();
        }
    }
    /**
     * On mouse down event.
     *
     * @param e
     */
    onDocumentMousedown(e) {
        const target = e.target; // needed for TSC
        if (target.closest('.ms-TextField, .ms-ComboBox, .ms-ComboBox-option, .ui-DatePicker') &&
            !this.props.renderInputs) {
            return;
        }
        if (this.state.editedCell) {
            if (this.state.editedCell.errorMessage) {
                e.preventDefault();
            }
            else {
                this.saveCell(true);
            }
        }
    }
    /**
     * On key down event.
     *
     * @param {React.KeyboardEvent<Element | IDropdown>} e
     * @returns {void}
     */
    onKeyDown(e) {
        if (!['Enter', 'Tab', 'Escape', 'ArrowDown', 'ArrowUp', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {
            return;
        }
        const isArrow = ['ArrowDown', 'ArrowUp', 'ArrowLeft', 'ArrowRight'].includes(e.key);
        const isInput = e.target.tagName === 'INPUT';
        if (isArrow && isInput) {
            e.stopPropagation();
            return;
        }
        e.preventDefault();
        if (e.key === 'Escape') {
            this.cancelEdit();
            (0, UITable_helper_1.focusEditedCell)(this.state.editedCell, this.props).catch(() => {
                // Ignore focus cell error
            });
            (0, UITable_helper_1.showFocus)();
            return;
        }
        if (this.state.editedCell?.errorMessage) {
            return;
        }
        e.stopPropagation();
        if (e.key === 'Enter' || e.key === 'Tab') {
            this.editNextCell(e.key, e.shiftKey);
        }
    }
    /**
     * On ComboBox keydown event call.
     *
     * @param e
     */
    onComboBoxKeyDownCapture(e) {
        if (e.key === 'Enter' || e.key === 'Tab') {
            // stop Enter from opening combobox
            e.stopPropagation();
            e.preventDefault();
            this.editNextCell(e.key, e.shiftKey);
        }
    }
    /**
     * On Edit next cell.
     *
     * @param key
     * @param shiftKey
     */
    editNextCell(key, shiftKey) {
        this.saveCell();
        let direction = '';
        if (key === 'Enter') {
            direction = shiftKey ? 'up' : 'down';
        }
        else if (key === 'Tab') {
            direction = shiftKey ? 'left' : 'right';
        }
        if (direction) {
            (0, UITable_helper_1.hideFocus)();
        }
        setTimeout(() => {
            (0, UITable_helper_1.focusEditedCell)(this.state.editedCell, this.props, direction)
                .then(() => {
                if (!direction) {
                    (0, UITable_helper_1.showFocus)();
                    return;
                }
                (0, UITable_helper_1.hideFocus)();
                const { rowIndex, item, column } = this.activeElement;
                this.startEdit(rowIndex, item, column);
            })
                .catch((e) => {
                throw e;
            });
        }, 100);
    }
    /**
     * On Cell click.
     *
     * @param e
     * @param item
     * @param rowIndex
     * @param column
     */
    _onCellClick(e, item, rowIndex, column) {
        const previousCellHasErrors = this.state.editedCell?.errorMessage;
        if (previousCellHasErrors) {
            return;
        }
        if (this.props.renderInputs) {
            return;
        }
        const el = e?.target;
        requestAnimationFrame(() => {
            // check the checkbox & focus the clicked cell
            if (el) {
                const fz = el.closest('.ms-FocusZone');
                if (fz?.click) {
                    fz.click();
                }
                const cell = el.closest('.ms-DetailsRow-cell');
                if (cell?.focus) {
                    cell.focus();
                }
            }
            if (column?.editable !== true) {
                (0, UITable_helper_1.showFocus)();
            }
        });
        if (rowIndex !== undefined && item && column?.editable === true) {
            e?.stopPropagation();
            requestAnimationFrame(() => this.startEdit(rowIndex, item, column));
        }
    }
    /**
     * Validates passed value for cell and updates "errorMessage" property based on validation result.
     *
     * @param editedCell Cell to validate
     * @param value
     */
    validateCell(editedCell, value) {
        const column = editedCell?.column;
        let errorMessage = '';
        if (column && typeof column.validate === 'function') {
            errorMessage = column.validate(value);
        }
        if (editedCell && editedCell.errorMessage !== errorMessage) {
            if (typeof editedCell.rowIndex === 'number' && editedCell.column?.key) {
                const cell = (0, UITable_helper_1.getCellFromCoords)(editedCell.rowIndex, editedCell.column.key, this.props.columns, true);
                const input = cell.querySelector('input');
                this.caretPosition = input.selectionStart || 0;
            }
            editedCell.errorMessage = errorMessage || undefined;
            // Rerender table to show error message
            this.rerenderTable();
        }
    }
    /**
     * On Text input change.
     *
     * @param e
     * @param newValue
     */
    onTextInputChange(e, newValue = '') {
        this.setState((prevState) => {
            const editedCell = prevState.editedCell ?? this.activeElement;
            if (editedCell) {
                editedCell.newValue = newValue;
                const column = editedCell.column;
                if (column && typeof column.validate === 'function') {
                    this.validateCell(editedCell, newValue);
                }
                if (this.props.renderInputs) {
                    this.saveCell(false, newValue);
                }
            }
            return { editedCell };
        });
    }
    /**
     * Gets input ref.
     *
     * @param rowIndex
     * @param column
     * @returns { React.RefObject<ITextField | IDropdown | HTMLDivElement> | undefined}
     */
    _getInputRef(rowIndex, column) {
        return typeof rowIndex === 'number' && typeof column?.key === 'string'
            ? this?.inputRefs?.[rowIndex]?.[column.key]
            : undefined;
    }
    /**
     * Renders dropdown.
     *
     * @param item
     * @param rowIndex
     * @param column
     * @returns {any}
     */
    _renderDropdown(item, rowIndex, column) {
        const compRef = this._getInputRef(rowIndex, column);
        return (react_1.default.createElement(UIDropdown_1.UIDropdown, { id: `dropdown_row${rowIndex}_col${column?.key}`, hidden: item.hideCells ?? false, placeholder: "Select an option", componentRef: compRef, options: column?.data.dropdownOptions, defaultSelectedKey: typeof column?.key === 'string' && item[column?.key]
                ? item[column?.key]
                : column?.data.defaultSelectedKey, onChange: (ev, text) => this.onDropdownCellValueChange(text, item, rowIndex, column), onKeyDown: this.onKeyDown }));
    }
    /**
     * Renders combobox.
     *
     * @param item
     * @param rowIndex
     * @param column
     * @returns {any}
     */
    _renderCombobox(item, rowIndex, column) {
        const compRef = this._getInputRef(rowIndex, column);
        const newValue = this.state.editedCell?.newValue;
        let value;
        if (column?.fieldName) {
            value = item[column?.fieldName];
        }
        if (typeof newValue !== 'undefined') {
            value = newValue;
        }
        const options = column?.comboboxOptions?.map((o) => ({ key: o, text: o })) || [];
        return (react_1.default.createElement(UIComboBox_1.UIComboBox, { highlight: true, defaultSelectedKey: value, allowFreeform: false, autoComplete: "on", shouldRestoreFocus: false, wrapperRef: compRef, errorMessage: this.state.editedCell?.errorMessage, openMenuOnClick: false, onPendingValueChanged: this.onComboBoxChange, onKeyDown: this.onKeyDown, onKeyDownCapture: this.onComboBoxKeyDownCapture, onClick: (e) => {
                e.stopPropagation();
            }, options: options }));
    }
    /**
     * Renders date picker.
     *
     * @param item
     * @param rowIndex
     * @param column
     * @param dateOnly
     * @returns {any}
     */
    _renderDatePicker(item, rowIndex, column, dateOnly = true) {
        const compRef = this._getInputRef(rowIndex, column);
        const newValue = this.state.editedCell?.newValue;
        let value;
        if (column?.fieldName) {
            value = item[column?.fieldName];
        }
        if (typeof newValue !== 'undefined') {
            value = newValue;
        }
        return (react_1.default.createElement(UIDatePicker_1.UIDatePicker, { defaultValue: value, componentRef: compRef, dateOnly: dateOnly, errorMessage: this.state.editedCell?.errorMessage, onChange: this.onTextInputChange, onKeyDown: this.onKeyDown, onClick: (e) => {
                e.stopPropagation();
            } }));
    }
    /**
     * Renders text input.
     *
     * @param item
     * @param rowIndex
     * @param column
     * @returns {any}
     */
    _renderTextInput(item, rowIndex, column) {
        const compRef = this._getInputRef(rowIndex, column);
        const newValue = this.state.editedCell?.newValue;
        let element;
        let value;
        if (column?.fieldName) {
            value = item[column?.fieldName];
        }
        if (typeof newValue !== 'undefined') {
            value = newValue;
        }
        if (!item.hideCells) {
            element = (react_1.default.createElement(UIInput_1.UITextInput, { defaultValue: value, componentRef: compRef, errorMessage: this.state.editedCell?.errorMessage, onChange: this.onTextInputChange, onKeyDown: this.onKeyDown, onClick: (e) => {
                    e.stopPropagation();
                } }));
        }
        return element;
    }
    /**
     * On cell render.
     *
     * @param item
     * @param rowIndex
     * @param column
     * @returns {any}
     */
    _onCellRender(item, rowIndex, column) {
        // inputs & dropdowns always visible
        if (this.props.renderInputs && rowIndex !== undefined) {
            if (column?.columnControlType === types_1.ColumnControlType.UIDropdown) {
                return this._renderDropdown(item, rowIndex, column);
            }
            return this._renderTextInput(item, rowIndex, column);
        }
        // inputs visible only in "edit mode" (after cell click)
        const editedCell = this.state.editedCell;
        const itsThisRow = editedCell?.rowIndex === rowIndex;
        const itsThisCol = editedCell && editedCell.column?.key === column?.key;
        const isCellInEditMode = itsThisRow && itsThisCol;
        if (isCellInEditMode && rowIndex !== undefined) {
            if (column?.columnControlType === types_1.ColumnControlType.UICombobox) {
                return this._renderCombobox(item, rowIndex, column);
            }
            else if (column?.columnControlType === types_1.ColumnControlType.UIBooleanSelect) {
                return this._renderCombobox(item, rowIndex, { ...column, comboboxOptions: ['true', 'false'] });
            }
            else if (column?.columnControlType === types_1.ColumnControlType.UIDatePicker) {
                return this._renderDatePicker(item, rowIndex, column, column?.type === 'Date');
            }
            else {
                return this._renderTextInput(item, rowIndex, column);
            }
        }
        const onClick = (e) => {
            e.stopPropagation();
            this._onCellClick(e, item, rowIndex || 0, column);
        };
        return (react_1.default.createElement("span", { style: { cursor: 'text', padding: 5 }, onClick: onClick }, item[column?.fieldName || 0]));
    }
    /**
     * @returns {JSX.Element}
     */
    render() {
        // get columns & items from props, so that detailsListProps does not contain them
        // because we want them to come from state, and be passed to component only once
        let { columns, items, checkboxVisibility, headerRenderer, selectionMode } = this.props;
        const { scrollablePaneProps, showRowNumbers, ...detailsListProps } = this.props;
        // get them from state if they exist
        if (this.state.columns) {
            columns = this.state.columns;
        }
        if (this.state.items) {
            items = this.state.items;
        }
        if (columns) {
            columns.forEach((col) => {
                col.onColumnClick = this._onColumnClick;
                if (col.editable === true) {
                    col.onRender = this._onCellRender;
                }
                else {
                    col.className = 'uneditable';
                }
                if (col.key === this.props.selectedColumnId) {
                    col.headerClassName = 'selected';
                }
            });
            columns = (0, UITable_helper_1.addRowNumbers)(columns, showRowNumbers);
        }
        const styles = (0, UITable_helper_1.getStylesForSelectedCell)(this.state);
        if (typeof checkboxVisibility === 'undefined') {
            checkboxVisibility = react_2.CheckboxVisibility.hidden;
        }
        if (typeof selectionMode === 'undefined') {
            selectionMode = react_2.SelectionMode.single;
        }
        if (typeof headerRenderer === 'undefined') {
            headerRenderer = UITable_helper_1._onHeaderRender;
        }
        const focusZoneProps = {
            direction: react_2.FocusZoneDirection.vertical,
            shouldEnterInnerZone: (ev) => {
                return ev.key === 'ArrowRight';
            }
        };
        return (react_1.default.createElement(react_2.ScrollablePane, { ...scrollablePaneProps, styles: { stickyAbove: { zIndex: 2 } } },
            react_1.default.createElement(react_2.DetailsList, { checkboxVisibility: checkboxVisibility, componentRef: this.tableRef, selection: this.selection, selectionMode: selectionMode, onRenderCheckbox: this._onRenderCheckbox, onRenderDetailsHeader: headerRenderer, onRenderField: this._onRenderField, onRenderRow: this._onRenderRow, onRenderItemColumn: this._onRenderItemColumn, layoutMode: react_2.DetailsListLayoutMode.fixedColumns, constrainMode: react_2.ConstrainMode.unconstrained, focusZoneProps: focusZoneProps, onActiveItemChanged: this._onCellActivation, ...detailsListProps, items: items, columns: columns, styles: styles })));
    }
}
exports.UITable = UITable;
//# sourceMappingURL=UITable.js.map