@fluentui/react
Version:
Reusable React components for building web experiences.
173 lines • 9.58 kB
JavaScript
define(["require", "exports", "tslib", "react", "../../Utilities", "@fluentui/utilities", "./DocumentCard.base", "@fluentui/react-window-provider", "../../utilities/dom"], function (require, exports, tslib_1, React, Utilities_1, utilities_1, DocumentCard_base_1, react_window_provider_1, dom_1) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DocumentCardTitleBase = void 0;
var getClassNames = (0, Utilities_1.classNamesFunction)();
var TRUNCATION_VERTICAL_OVERFLOW_THRESHOLD = 5;
/**
* {@docCategory DocumentCard}
*/
var DocumentCardTitleBase = /** @class */ (function (_super) {
tslib_1.__extends(DocumentCardTitleBase, _super);
function DocumentCardTitleBase(props) {
var _this = _super.call(this, props) || this;
_this._titleElement = 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._needMeasurement) {
return;
}
_this._async.requestAnimationFrame(_this._truncateWhenInAnimation);
};
_this._truncateWhenInAnimation = function () {
var originalTitle = _this.props.title;
var element = _this._titleElement.current;
if (element) {
var style = getComputedStyle(element);
if (style.width && style.lineHeight && style.height) {
var clientWidth = element.clientWidth, scrollWidth = element.scrollWidth;
_this._clientWidth = clientWidth;
var lines = Math.floor((parseInt(style.height, 10) + TRUNCATION_VERTICAL_OVERFLOW_THRESHOLD) / parseInt(style.lineHeight, 10));
element.style.whiteSpace = '';
// 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),
});
}
}
}
};
_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),
});
}
}
};
(0, utilities_1.initializeComponentRef)(_this);
_this._async = new Utilities_1.Async(_this);
_this._events = new Utilities_1.EventGroup(_this);
_this._clientWidth = undefined;
_this.state = {
truncatedTitleFirstPiece: undefined,
truncatedTitleSecondPiece: undefined,
};
return _this;
}
DocumentCardTitleBase.prototype.componentDidUpdate = function (prevProps) {
var _this = this;
if (this.props.title !== prevProps.title) {
this.setState({
truncatedTitleFirstPiece: undefined,
truncatedTitleSecondPiece: undefined,
});
}
if (prevProps.shouldTruncate !== this.props.shouldTruncate) {
var win = (0, dom_1.getWindowEx)(this.context);
if (this.props.shouldTruncate) {
this._truncateTitle();
this._async.requestAnimationFrame(this._shrinkTitle);
this._events.on(win, 'resize', this._updateTruncation);
}
else {
this._events.off(win, 'resize', this._updateTruncation);
}
}
else if (this._needMeasurement) {
this._async.requestAnimationFrame(function () {
_this._truncateWhenInAnimation();
_this._shrinkTitle();
});
}
};
DocumentCardTitleBase.prototype.componentDidMount = function () {
if (this.props.shouldTruncate) {
this._truncateTitle();
var win = (0, dom_1.getWindowEx)(this.context);
this._events.on(win, 'resize', this._updateTruncation);
}
};
DocumentCardTitleBase.prototype.componentWillUnmount = function () {
this._events.dispose();
this._async.dispose();
};
DocumentCardTitleBase.prototype.render = function () {
var _this = this;
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;
this._classNames = getClassNames(styles, {
theme: theme,
className: className,
showAsSecondaryTitle: showAsSecondaryTitle,
});
if (shouldTruncate && truncatedTitleFirstPiece && truncatedTitleSecondPiece) {
return (React.createElement(DocumentCard_base_1.DocumentCardContext.Consumer, null, function (_a) {
var role = _a.role, tabIndex = _a.tabIndex;
return (React.createElement("div", { className: _this._classNames.root, ref: _this._titleElement, title: title, tabIndex: tabIndex, role: role },
truncatedTitleFirstPiece,
"\u2026",
truncatedTitleSecondPiece));
}));
}
else {
return (React.createElement(DocumentCard_base_1.DocumentCardContext.Consumer, null, function (_a) {
var role = _a.role, tabIndex = _a.tabIndex;
return (React.createElement("div", { className: _this._classNames.root, ref: _this._titleElement, title: title, tabIndex: tabIndex, role: role, style: _this._needMeasurement ? { whiteSpace: 'nowrap' } : undefined }, title));
}));
}
};
Object.defineProperty(DocumentCardTitleBase.prototype, "_needMeasurement", {
/**
* In measuring, it will render a same style text with whiteSpace: 'nowrap', to get overflow rate.
* So that the logic can predict truncated text well.
*/
get: function () {
return !!this.props.shouldTruncate && this._clientWidth === undefined;
},
enumerable: false,
configurable: true
});
DocumentCardTitleBase.prototype._updateTruncation = function () {
var _this = this;
if (this._timerId) {
return;
}
this._timerId = this._async.setTimeout(function () {
delete _this._timerId;
_this._clientWidth = undefined;
_this.setState({
truncatedTitleFirstPiece: undefined,
truncatedTitleSecondPiece: undefined,
});
}, 250);
};
DocumentCardTitleBase.contextType = react_window_provider_1.WindowContext;
return DocumentCardTitleBase;
}(React.Component));
exports.DocumentCardTitleBase = DocumentCardTitleBase;
});
//# sourceMappingURL=DocumentCardTitle.base.js.map