UNPKG

office-ui-fabric-react

Version:

Reusable React components for building experiences for Microsoft 365.

157 lines 8.22 kB
import { __extends } from "tslib"; import * as React from 'react'; import { Async, EventGroup, classNamesFunction } from '../../Utilities'; import { initializeComponentRef } from '@uifabric/utilities'; var getClassNames = classNamesFunction(); var TRUNCATION_VERTICAL_OVERFLOW_THRESHOLD = 5; /** * {@docCategory DocumentCard} */ var DocumentCardTitleBase = /** @class */ (function (_super) { __extends(DocumentCardTitleBase, _super); function DocumentCardTitleBase(props) { var _this = _super.call(this, props) || this; _this._titleElement = React.createRef(); _this._measureTitleElement = React.createRef(); // Truncate logic here way can't handle the case that chars with different widths are mixed very well. // Let _shrinkTitle take care of that. _this._truncateTitle = function () { if (!_this.state.needMeasurement) { return; } _this._async.requestAnimationFrame(_this._truncateWhenInAnimation); }; _this._truncateWhenInAnimation = function () { var originalTitle = _this.props.title; var element = _this._measureTitleElement.current; if (element) { var style = getComputedStyle(element); if (style.width && style.lineHeight && style.height) { var clientWidth = element.clientWidth, scrollWidth = element.scrollWidth; var lines = Math.floor((parseInt(style.height, 10) + TRUNCATION_VERTICAL_OVERFLOW_THRESHOLD) / parseInt(style.lineHeight, 10)); // Use overflow to predict truncated length. // Take an example.The text is: A text with A very long text that need to be truncated.ppt // if container is like // |A text with A very| long text that need to be truncated.ppt // The scroll width is 58, (take two | out of length) // The client width is 18 // the overflow rate is scrollWidth/clientWidth which should be close to length(overflowText)/length(visualText) // And the length of remaining text should be truncated is (original Length)/(58/18) -3 = 15. // So that the logic can predict truncated text well. // first piece will be `A text `, * second piece will be `ated.ppt` // |A text ...ated.ppt| var overFlowRate = scrollWidth / (parseInt(style.width, 10) * lines); if (overFlowRate > 1) { var truncatedLength = originalTitle.length / overFlowRate - 3 /** Saved for separator */; return _this.setState({ truncatedTitleFirstPiece: originalTitle.slice(0, truncatedLength / 2), truncatedTitleSecondPiece: originalTitle.slice(originalTitle.length - truncatedLength / 2), clientWidth: clientWidth, needMeasurement: false, }); } } } return _this.setState({ needMeasurement: false }); }; _this._shrinkTitle = function () { var _a = _this.state, truncatedTitleFirstPiece = _a.truncatedTitleFirstPiece, truncatedTitleSecondPiece = _a.truncatedTitleSecondPiece; if (truncatedTitleFirstPiece && truncatedTitleSecondPiece) { var titleElement = _this._titleElement.current; if (!titleElement) { return; } if (titleElement.scrollHeight > titleElement.clientHeight + TRUNCATION_VERTICAL_OVERFLOW_THRESHOLD || titleElement.scrollWidth > titleElement.clientWidth) { _this.setState({ truncatedTitleFirstPiece: truncatedTitleFirstPiece.slice(0, truncatedTitleFirstPiece.length - 1), truncatedTitleSecondPiece: truncatedTitleSecondPiece.slice(1), }); } } }; initializeComponentRef(_this); _this._async = new Async(_this); _this._events = new EventGroup(_this); _this.state = { truncatedTitleFirstPiece: '', truncatedTitleSecondPiece: '', previousTitle: props.title, needMeasurement: !!props.shouldTruncate, }; return _this; } DocumentCardTitleBase.prototype.componentDidUpdate = function () { if (this.props.title !== this.state.previousTitle) { this.setState({ truncatedTitleFirstPiece: undefined, truncatedTitleSecondPiece: undefined, clientWidth: undefined, previousTitle: this.props.title, needMeasurement: !!this.props.shouldTruncate, }); } this._events.off(window, 'resize', this._updateTruncation); if (this.props.shouldTruncate) { this._truncateTitle(); requestAnimationFrame(this._shrinkTitle); this._events.on(window, 'resize', this._updateTruncation); } }; DocumentCardTitleBase.prototype.componentDidMount = function () { if (this.props.shouldTruncate) { this._truncateTitle(); this._events.on(window, 'resize', this._updateTruncation); } }; DocumentCardTitleBase.prototype.componentWillUnmount = function () { this._events.dispose(); this._async.dispose(); }; DocumentCardTitleBase.prototype.render = function () { var _a = this.props, title = _a.title, shouldTruncate = _a.shouldTruncate, showAsSecondaryTitle = _a.showAsSecondaryTitle, styles = _a.styles, theme = _a.theme, className = _a.className; var _b = this.state, truncatedTitleFirstPiece = _b.truncatedTitleFirstPiece, truncatedTitleSecondPiece = _b.truncatedTitleSecondPiece, needMeasurement = _b.needMeasurement; this._classNames = getClassNames(styles, { theme: theme, className: className, showAsSecondaryTitle: showAsSecondaryTitle, }); var documentCardTitle; if (needMeasurement) { documentCardTitle = (React.createElement("div", { className: this._classNames.root, ref: this._measureTitleElement, title: title, style: { whiteSpace: 'nowrap' } }, title)); } else if (shouldTruncate && truncatedTitleFirstPiece && truncatedTitleSecondPiece) { documentCardTitle = (React.createElement("div", { className: this._classNames.root, ref: this._titleElement, title: title }, truncatedTitleFirstPiece, "\u2026", truncatedTitleSecondPiece)); } else { documentCardTitle = (React.createElement("div", { className: this._classNames.root, ref: this._titleElement, title: title }, title)); } return documentCardTitle; }; DocumentCardTitleBase.prototype._updateTruncation = function () { var _this = this; this._async.requestAnimationFrame(function () { // Only update truncation if the title's size has changed since the last time we truncated if (_this._titleElement.current) { var clientWidth = _this._titleElement.current.clientWidth; // Throttle truncation so that it doesn't happen during a window resize clearTimeout(_this._titleTruncationTimer); if (_this.state.clientWidth !== clientWidth) { _this._titleTruncationTimer = _this._async.setTimeout(function () { return _this.setState({ truncatedTitleFirstPiece: undefined, truncatedTitleSecondPiece: undefined, needMeasurement: true, }); }, 250); } } }); }; return DocumentCardTitleBase; }(React.Component)); export { DocumentCardTitleBase }; //# sourceMappingURL=DocumentCardTitle.base.js.map