UNPKG

8.22 kBJavaScriptView Raw
1import { __extends } from "tslib";
2import * as React from 'react';
3import { Async, EventGroup, classNamesFunction } from '../../Utilities';
4import { initializeComponentRef } from '@uifabric/utilities';
5var getClassNames = classNamesFunction();
6var TRUNCATION_VERTICAL_OVERFLOW_THRESHOLD = 5;
7/**
8 * {@docCategory DocumentCard}
9 */
10var DocumentCardTitleBase = /** @class */ (function (_super) {
11 __extends(DocumentCardTitleBase, _super);
12 function DocumentCardTitleBase(props) {
13 var _this = _super.call(this, props) || this;
14 _this._titleElement = React.createRef();
15 _this._measureTitleElement = React.createRef();
16 // Truncate logic here way can't handle the case that chars with different widths are mixed very well.
17 // Let _shrinkTitle take care of that.
18 _this._truncateTitle = function () {
19 if (!_this.state.needMeasurement) {
20 return;
21 }
22 _this._async.requestAnimationFrame(_this._truncateWhenInAnimation);
23 };
24 _this._truncateWhenInAnimation = function () {
25 var originalTitle = _this.props.title;
26 var element = _this._measureTitleElement.current;
27 if (element) {
28 var style = getComputedStyle(element);
29 if (style.width && style.lineHeight && style.height) {
30 var clientWidth = element.clientWidth, scrollWidth = element.scrollWidth;
31 var lines = Math.floor((parseInt(style.height, 10) + TRUNCATION_VERTICAL_OVERFLOW_THRESHOLD) / parseInt(style.lineHeight, 10));
32 // Use overflow to predict truncated length.
33 // Take an example.The text is: A text with A very long text that need to be truncated.ppt
34 // if container is like
35 // |A text with A very| long text that need to be truncated.ppt
36 // The scroll width is 58, (take two | out of length)
37 // The client width is 18
38 // the overflow rate is scrollWidth/clientWidth which should be close to length(overflowText)/length(visualText)
39 // And the length of remaining text should be truncated is (original Length)/(58/18) -3 = 15.
40 // So that the logic can predict truncated text well.
41 // first piece will be `A text `, * second piece will be `ated.ppt`
42 // |A text ...ated.ppt|
43 var overFlowRate = scrollWidth / (parseInt(style.width, 10) * lines);
44 if (overFlowRate > 1) {
45 var truncatedLength = originalTitle.length / overFlowRate - 3 /** Saved for separator */;
46 return _this.setState({
47 truncatedTitleFirstPiece: originalTitle.slice(0, truncatedLength / 2),
48 truncatedTitleSecondPiece: originalTitle.slice(originalTitle.length - truncatedLength / 2),
49 clientWidth: clientWidth,
50 needMeasurement: false,
51 });
52 }
53 }
54 }
55 return _this.setState({ needMeasurement: false });
56 };
57 _this._shrinkTitle = function () {
58 var _a = _this.state, truncatedTitleFirstPiece = _a.truncatedTitleFirstPiece, truncatedTitleSecondPiece = _a.truncatedTitleSecondPiece;
59 if (truncatedTitleFirstPiece && truncatedTitleSecondPiece) {
60 var titleElement = _this._titleElement.current;
61 if (!titleElement) {
62 return;
63 }
64 if (titleElement.scrollHeight > titleElement.clientHeight + TRUNCATION_VERTICAL_OVERFLOW_THRESHOLD ||
65 titleElement.scrollWidth > titleElement.clientWidth) {
66 _this.setState({
67 truncatedTitleFirstPiece: truncatedTitleFirstPiece.slice(0, truncatedTitleFirstPiece.length - 1),
68 truncatedTitleSecondPiece: truncatedTitleSecondPiece.slice(1),
69 });
70 }
71 }
72 };
73 initializeComponentRef(_this);
74 _this._async = new Async(_this);
75 _this._events = new EventGroup(_this);
76 _this.state = {
77 truncatedTitleFirstPiece: '',
78 truncatedTitleSecondPiece: '',
79 previousTitle: props.title,
80 needMeasurement: !!props.shouldTruncate,
81 };
82 return _this;
83 }
84 DocumentCardTitleBase.prototype.componentDidUpdate = function () {
85 if (this.props.title !== this.state.previousTitle) {
86 this.setState({
87 truncatedTitleFirstPiece: undefined,
88 truncatedTitleSecondPiece: undefined,
89 clientWidth: undefined,
90 previousTitle: this.props.title,
91 needMeasurement: !!this.props.shouldTruncate,
92 });
93 }
94 this._events.off(window, 'resize', this._updateTruncation);
95 if (this.props.shouldTruncate) {
96 this._truncateTitle();
97 requestAnimationFrame(this._shrinkTitle);
98 this._events.on(window, 'resize', this._updateTruncation);
99 }
100 };
101 DocumentCardTitleBase.prototype.componentDidMount = function () {
102 if (this.props.shouldTruncate) {
103 this._truncateTitle();
104 this._events.on(window, 'resize', this._updateTruncation);
105 }
106 };
107 DocumentCardTitleBase.prototype.componentWillUnmount = function () {
108 this._events.dispose();
109 this._async.dispose();
110 };
111 DocumentCardTitleBase.prototype.render = function () {
112 var _a = this.props, title = _a.title, shouldTruncate = _a.shouldTruncate, showAsSecondaryTitle = _a.showAsSecondaryTitle, styles = _a.styles, theme = _a.theme, className = _a.className;
113 var _b = this.state, truncatedTitleFirstPiece = _b.truncatedTitleFirstPiece, truncatedTitleSecondPiece = _b.truncatedTitleSecondPiece, needMeasurement = _b.needMeasurement;
114 this._classNames = getClassNames(styles, {
115 theme: theme,
116 className: className,
117 showAsSecondaryTitle: showAsSecondaryTitle,
118 });
119 var documentCardTitle;
120 if (needMeasurement) {
121 documentCardTitle = (React.createElement("div", { className: this._classNames.root, ref: this._measureTitleElement, title: title, style: { whiteSpace: 'nowrap' } }, title));
122 }
123 else if (shouldTruncate && truncatedTitleFirstPiece && truncatedTitleSecondPiece) {
124 documentCardTitle = (React.createElement("div", { className: this._classNames.root, ref: this._titleElement, title: title },
125 truncatedTitleFirstPiece,
126 "\u2026",
127 truncatedTitleSecondPiece));
128 }
129 else {
130 documentCardTitle = (React.createElement("div", { className: this._classNames.root, ref: this._titleElement, title: title }, title));
131 }
132 return documentCardTitle;
133 };
134 DocumentCardTitleBase.prototype._updateTruncation = function () {
135 var _this = this;
136 this._async.requestAnimationFrame(function () {
137 // Only update truncation if the title's size has changed since the last time we truncated
138 if (_this._titleElement.current) {
139 var clientWidth = _this._titleElement.current.clientWidth;
140 // Throttle truncation so that it doesn't happen during a window resize
141 clearTimeout(_this._titleTruncationTimer);
142 if (_this.state.clientWidth !== clientWidth) {
143 _this._titleTruncationTimer = _this._async.setTimeout(function () {
144 return _this.setState({
145 truncatedTitleFirstPiece: undefined,
146 truncatedTitleSecondPiece: undefined,
147 needMeasurement: true,
148 });
149 }, 250);
150 }
151 }
152 });
153 };
154 return DocumentCardTitleBase;
155}(React.Component));
156export { DocumentCardTitleBase };
157//# sourceMappingURL=DocumentCardTitle.base.js.map
\No newline at end of file