define(["require", "exports", "tslib", "react", "react-dom", "../../Utilities", "./DetailsList.types", "./DetailsRowCheck", "../GroupedList/GroupSpacer", "./DetailsRowFields", "../../FocusZone", "../../utilities/selection/interfaces", "../../GroupedList", "../../Styling", "./DetailsRow.scss", "./DetailsRowCheck.scss"], function (require, exports, tslib_1, React, ReactDOM, Utilities_1, DetailsList_types_1, DetailsRowCheck_1, GroupSpacer_1, DetailsRowFields_1, FocusZone_1, interfaces_1, GroupedList_1, Styling_1, stylesImport, checkStylesImport) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    var styles = stylesImport;
    var checkStyles = checkStylesImport;
    var DEFAULT_DROPPING_CSS_CLASS = 'is-dropping';
    var DetailsRow = /** @class */ (function (_super) {
        tslib_1.__extends(DetailsRow, _super);
        function DetailsRow(props) {
            var _this = _super.call(this, props) || this;
            _this._cellMeasurer = Utilities_1.createRef();
            _this._focusZone = Utilities_1.createRef();
            _this._onRootRef = function (focusZone) {
                if (focusZone) {
                    // Need to resolve the actual DOM node, not the component. The element itself will be used for drag/drop and focusing.
                    _this._root = ReactDOM.findDOMNode(focusZone);
                }
                else {
                    _this._root = undefined;
                }
            };
            _this.state = {
                selectionState: _this._getSelectionState(props),
                columnMeasureInfo: undefined,
                isDropping: false,
                groupNestingDepth: props.groupNestingDepth
            };
            _this._droppingClassNames = '';
            _this._updateDroppingState = _this._updateDroppingState.bind(_this);
            _this._onToggleSelection = _this._onToggleSelection.bind(_this);
            return _this;
        }
        DetailsRow.prototype.componentDidMount = function () {
            var dragDropHelper = this.props.dragDropHelper;
            if (dragDropHelper) {
                this._dragDropSubscription = dragDropHelper.subscribe(this._root, this._events, this._getRowDragDropOptions());
            }
            this._events.on(this.props.selection, interfaces_1.SELECTION_CHANGE, this._onSelectionChanged);
            if (this.props.onDidMount && this.props.item) {
                // If the item appears later, we should wait for it before calling this method.
                this._hasMounted = true;
                this.props.onDidMount(this);
            }
        };
        DetailsRow.prototype.componentDidUpdate = function (previousProps) {
            var state = this.state;
            var _a = this.props, item = _a.item, onDidMount = _a.onDidMount;
            var columnMeasureInfo = state.columnMeasureInfo;
            if (this.props.itemIndex !== previousProps.itemIndex ||
                this.props.item !== previousProps.item ||
                this.props.dragDropHelper !== previousProps.dragDropHelper) {
                if (this._dragDropSubscription) {
                    this._dragDropSubscription.dispose();
                    delete this._dragDropSubscription;
                }
                if (this.props.dragDropHelper) {
                    this._dragDropSubscription = this.props.dragDropHelper.subscribe(this._root, this._events, this._getRowDragDropOptions());
                }
            }
            if (columnMeasureInfo && columnMeasureInfo.index >= 0 && this._cellMeasurer.value) {
                var newWidth = this._cellMeasurer.value.getBoundingClientRect().width;
                columnMeasureInfo.onMeasureDone(newWidth);
                this.setState({
                    columnMeasureInfo: undefined
                });
            }
            if (item && onDidMount && !this._hasMounted) {
                this._hasMounted = true;
                onDidMount(this);
            }
        };
        DetailsRow.prototype.componentWillUnmount = function () {
            var _a = this.props, item = _a.item, onWillUnmount = _a.onWillUnmount;
            // Only call the onWillUnmount callback if we have an item.
            if (onWillUnmount && item) {
                onWillUnmount(this);
            }
            if (this._dragDropSubscription) {
                this._dragDropSubscription.dispose();
                delete this._dragDropSubscription;
            }
        };
        DetailsRow.prototype.componentWillReceiveProps = function (newProps) {
            this.setState({
                selectionState: this._getSelectionState(newProps),
                groupNestingDepth: newProps.groupNestingDepth
            });
        };
        DetailsRow.prototype.render = function () {
            var _a = this.props, className = _a.className, columns = _a.columns, dragDropEvents = _a.dragDropEvents, item = _a.item, itemIndex = _a.itemIndex, _b = _a.onRenderCheck, onRenderCheck = _b === void 0 ? this._onRenderCheck : _b, onRenderItemColumn = _a.onRenderItemColumn, selectionMode = _a.selectionMode, viewport = _a.viewport, checkboxVisibility = _a.checkboxVisibility, getRowAriaLabel = _a.getRowAriaLabel, getRowAriaDescribedBy = _a.getRowAriaDescribedBy, checkButtonAriaLabel = _a.checkButtonAriaLabel, checkboxCellClassName = _a.checkboxCellClassName, 
            /** Alias rowFieldsAs as RowFields and default to DetailsRowFields if rowFieldsAs does not exist */
            _c = _a.rowFieldsAs, 
            /** Alias rowFieldsAs as RowFields and default to DetailsRowFields if rowFieldsAs does not exist */
            RowFields = _c === void 0 ? DetailsRowFields_1.DetailsRowFields : _c, selection = _a.selection, shimmer = _a.shimmer, compact = _a.compact;
            var _d = this.state, columnMeasureInfo = _d.columnMeasureInfo, isDropping = _d.isDropping, groupNestingDepth = _d.groupNestingDepth;
            var _e = this.state.selectionState, _f = _e.isSelected, isSelected = _f === void 0 ? false : _f, _g = _e.isSelectionModal, isSelectionModal = _g === void 0 ? false : _g;
            var isDraggable = Boolean(dragDropEvents && dragDropEvents.canDrag && dragDropEvents.canDrag(item));
            var droppingClassName = isDropping ? (this._droppingClassNames ? this._droppingClassNames : DEFAULT_DROPPING_CSS_CLASS) : '';
            var ariaLabel = getRowAriaLabel ? getRowAriaLabel(item) : null;
            var ariaDescribedBy = getRowAriaDescribedBy ? getRowAriaDescribedBy(item) : undefined;
            var canSelect = selection.canSelectItem(item);
            var isContentUnselectable = selectionMode === interfaces_1.SelectionMode.multiple;
            var showCheckbox = selectionMode !== interfaces_1.SelectionMode.none && checkboxVisibility !== DetailsList_types_1.CheckboxVisibility.hidden;
            var ariaSelected = (selectionMode === interfaces_1.SelectionMode.none) ? undefined : isSelected;
            var rowFields = (React.createElement(RowFields, { columns: columns, item: item, itemIndex: itemIndex, columnStartIndex: showCheckbox ? 1 : 0, onRenderItemColumn: onRenderItemColumn, shimmer: shimmer }));
            // Rendering Shimmer Animation outside the focus zone
            if (shimmer) {
                return (React.createElement("div", { className: Utilities_1.css(showCheckbox && styles.shimmerLeftBorder, !compact && styles.shimmerBottomBorder) }, rowFields));
            }
            return (React.createElement(FocusZone_1.FocusZone, tslib_1.__assign({}, Utilities_1.getNativeProps(this.props, Utilities_1.divProperties), { direction: FocusZone_1.FocusZoneDirection.horizontal, ref: this._onRootRef, componentRef: this._focusZone, role: 'row', "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, className: Utilities_1.css('ms-DetailsRow', className, Styling_1.AnimationClassNames.fadeIn400, styles.root, checkStyles.owner, droppingClassName, (_h = {},
                    _h["is-contentUnselectable " + styles.rootIsContentUnselectable] = isContentUnselectable,
                    _h["is-selected " + checkStyles.isSelected + " " + styles.rootIsSelected] = isSelected,
                    _h[styles.anySelected + " " + checkStyles.anySelected] = isSelectionModal,
                    _h["is-check-visible " + checkStyles.isVisible] = checkboxVisibility === DetailsList_types_1.CheckboxVisibility.always,
                    _h)), "data-is-focusable": true, "data-selection-index": itemIndex, "data-item-index": itemIndex, "aria-rowindex": itemIndex + 1, "data-is-draggable": isDraggable, draggable: isDraggable, "data-automationid": 'DetailsRow', style: { minWidth: viewport ? viewport.width : 0 }, "aria-selected": ariaSelected, allowFocusRoot: true }),
                showCheckbox && (React.createElement("div", { role: 'gridcell', "aria-colindex": 1, "data-selection-toggle": true, className: Utilities_1.css('ms-DetailsRow-cell', 'ms-DetailsRow-cellCheck', checkStyles.owner, styles.cell, styles.checkCell, checkboxCellClassName) }, onRenderCheck({
                    selected: isSelected,
                    anySelected: isSelectionModal,
                    title: checkButtonAriaLabel,
                    canSelect: canSelect
                }))),
                GroupSpacer_1.GroupSpacer({ count: groupNestingDepth - (this.props.collapseAllVisibility === GroupedList_1.CollapseAllVisibility.hidden ? 1 : 0) }),
                item && rowFields,
                columnMeasureInfo && (React.createElement("span", { role: 'presentation', className: Utilities_1.css('ms-DetailsRow-cellMeasurer ms-DetailsRow-cell', styles.cellMeasurer, styles.cell), ref: this._cellMeasurer },
                    React.createElement(RowFields, { columns: [columnMeasureInfo.column], item: item, itemIndex: itemIndex, columnStartIndex: (showCheckbox ? 1 : 0) + columns.length, onRenderItemColumn: onRenderItemColumn }))),
                React.createElement("span", { role: 'checkbox', className: Utilities_1.css(styles.checkCover), "aria-checked": isSelected, "data-selection-toggle": true })));
            var _h;
        };
        /**
         * measure cell at index. and call the call back with the measured cell width when finish measure
         *
         * @param {number} index (the cell index)
         * @param {(width: number) => void} onMeasureDone (the call back function when finish measure)
         */
        DetailsRow.prototype.measureCell = function (index, onMeasureDone) {
            var column = Utilities_1.assign({}, this.props.columns[index]);
            column.minWidth = 0;
            column.maxWidth = 999999;
            delete column.calculatedWidth;
            this.setState({
                columnMeasureInfo: {
                    index: index,
                    column: column,
                    onMeasureDone: onMeasureDone
                }
            });
        };
        DetailsRow.prototype.focus = function (forceIntoFirstElement) {
            if (forceIntoFirstElement === void 0) { forceIntoFirstElement = false; }
            return !!this._focusZone.value && this._focusZone.value.focus(forceIntoFirstElement);
        };
        DetailsRow.prototype._onRenderCheck = function (props) {
            return React.createElement(DetailsRowCheck_1.DetailsRowCheck, tslib_1.__assign({}, props));
        };
        DetailsRow.prototype._getSelectionState = function (props) {
            var itemIndex = props.itemIndex, selection = props.selection;
            return {
                isSelected: selection.isIndexSelected(itemIndex),
                isSelectionModal: !!selection.isModal && selection.isModal()
            };
        };
        DetailsRow.prototype._onSelectionChanged = function () {
            var selectionState = this._getSelectionState(this.props);
            if (!Utilities_1.shallowCompare(selectionState, this.state.selectionState)) {
                this.setState({
                    selectionState: selectionState
                });
            }
        };
        DetailsRow.prototype._onToggleSelection = function () {
            var selection = this.props.selection;
            selection.toggleIndexSelected(this.props.itemIndex);
        };
        DetailsRow.prototype._getRowDragDropOptions = function () {
            var _a = this.props, item = _a.item, itemIndex = _a.itemIndex, dragDropEvents = _a.dragDropEvents, eventsToRegister = _a.eventsToRegister;
            var options = {
                eventMap: eventsToRegister,
                selectionIndex: itemIndex,
                context: { data: item, index: itemIndex },
                canDrag: dragDropEvents.canDrag,
                canDrop: dragDropEvents.canDrop,
                onDragStart: dragDropEvents.onDragStart,
                updateDropState: this._updateDroppingState,
                onDrop: dragDropEvents.onDrop,
                onDragEnd: dragDropEvents.onDragEnd,
            };
            return options;
        };
        /**
         * update isDropping state based on the input value, which is used to change style during drag and drop
         *
         * when change to true, that means drag enter. we will add default dropping class name
         * or the custom dropping class name (return result from onDragEnter) to the root elemet.
         *
         * when change to false, that means drag leave. we will remove the dropping class name from root element.
         *
         * @private
         * @param {boolean} newValue (new isDropping state value)
         * @param {DragEvent} event (the event trigger dropping state change which can be dragenter, dragleave etc)
         */
        DetailsRow.prototype._updateDroppingState = function (newValue, event) {
            var _a = this.state, selectionState = _a.selectionState, isDropping = _a.isDropping;
            var _b = this.props, dragDropEvents = _b.dragDropEvents, item = _b.item;
            if (!newValue) {
                if (dragDropEvents.onDragLeave) {
                    dragDropEvents.onDragLeave(item, event);
                }
            }
            else {
                if (dragDropEvents.onDragEnter) {
                    this._droppingClassNames = dragDropEvents.onDragEnter(item, event);
                }
            }
            if (isDropping !== newValue) {
                this.setState({ selectionState: selectionState, isDropping: newValue });
            }
        };
        return DetailsRow;
    }(Utilities_1.BaseComponent));
    exports.DetailsRow = DetailsRow;
});
//# sourceMappingURL=DetailsRow.js.map