@instructure/ui-truncate-text 8.33.1 → 8.33.2-snapshot-5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/es/TruncateText/index.js +19 -51
- package/es/TruncateText/props.js +1 -0
- package/es/TruncateText/styles.js +0 -1
- package/es/TruncateText/theme.js +2 -2
- package/es/TruncateText/utils/cleanData.js +3 -31
- package/es/TruncateText/utils/cleanString.js +0 -5
- package/es/TruncateText/utils/measureText.js +8 -16
- package/es/TruncateText/utils/truncate.js +30 -82
- package/lib/TruncateText/index.js +19 -70
- package/lib/TruncateText/props.js +1 -3
- package/lib/TruncateText/styles.js +0 -2
- package/lib/TruncateText/theme.js +2 -3
- package/lib/TruncateText/utils/cleanData.js +2 -32
- package/lib/TruncateText/utils/cleanString.js +0 -6
- package/lib/TruncateText/utils/measureText.js +6 -17
- package/lib/TruncateText/utils/truncate.js +29 -92
- package/lib/index.js +0 -1
- package/package.json +14 -14
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
22
|
* SOFTWARE.
|
|
23
23
|
*/
|
|
24
|
+
|
|
24
25
|
import escapeHtml from 'escape-html';
|
|
25
26
|
import { cloneArray } from '@instructure/ui-utils';
|
|
26
27
|
import { logError as error } from '@instructure/console';
|
|
@@ -28,7 +29,6 @@ import { getComputedStyle, getBoundingClientRect, isVisible } from '@instructure
|
|
|
28
29
|
import measureText from './measureText';
|
|
29
30
|
import cleanString from './cleanString';
|
|
30
31
|
import cleanData from './cleanData';
|
|
31
|
-
|
|
32
32
|
/**
|
|
33
33
|
* ---
|
|
34
34
|
* parent: TruncateText
|
|
@@ -49,14 +49,11 @@ import cleanData from './cleanData';
|
|
|
49
49
|
*/
|
|
50
50
|
function truncate(element, options) {
|
|
51
51
|
const truncator = new Truncator(element, options);
|
|
52
|
-
|
|
53
52
|
if (truncator) {
|
|
54
53
|
return truncator.truncate();
|
|
55
54
|
}
|
|
56
|
-
|
|
57
55
|
return;
|
|
58
56
|
}
|
|
59
|
-
|
|
60
57
|
class Truncator {
|
|
61
58
|
constructor(element) {
|
|
62
59
|
let options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
|
|
@@ -80,161 +77,133 @@ class Truncator {
|
|
|
80
77
|
lineHeight: options.lineHeight || 1.2,
|
|
81
78
|
shouldTruncateWhenInvisible: !!options.shouldTruncateWhenInvisible
|
|
82
79
|
};
|
|
83
|
-
|
|
84
80
|
if (!element) {
|
|
85
81
|
error(false, '[Truncator] No element to truncate.');
|
|
86
82
|
return;
|
|
87
83
|
}
|
|
88
|
-
|
|
89
84
|
this._stage = element;
|
|
90
|
-
|
|
91
85
|
if (options.parent) {
|
|
92
86
|
this._parent = this._options.parent;
|
|
93
87
|
} else {
|
|
94
88
|
const parentEl = this._stage.parentElement ? this._stage.parentElement : void 0;
|
|
95
89
|
this._parent = this._options.maxLines === 'auto' ? parentEl : this._stage;
|
|
96
90
|
}
|
|
97
|
-
|
|
98
91
|
this.setup();
|
|
99
92
|
}
|
|
100
|
-
|
|
101
93
|
setup() {
|
|
102
94
|
if (!this._stage) {
|
|
103
95
|
return;
|
|
104
96
|
}
|
|
105
|
-
|
|
106
97
|
const _this$_options = this._options,
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const style = getComputedStyle(this._parent);
|
|
111
|
-
|
|
98
|
+
maxLines = _this$_options.maxLines,
|
|
99
|
+
truncate = _this$_options.truncate,
|
|
100
|
+
lineHeight = _this$_options.lineHeight;
|
|
101
|
+
const style = getComputedStyle(this._parent);
|
|
102
|
+
// if no explicit lineHeight is inherited, use lineHeight multiplier for calculations
|
|
112
103
|
const actualLineHeight = style.lineHeight === 'normal' ? lineHeight * parseFloat(style.fontSize) : parseFloat(style.lineHeight);
|
|
113
104
|
const node = this._stage.firstChild.children ? this._stage.firstChild : this._stage;
|
|
114
105
|
const nodeDataIndexes = [];
|
|
115
106
|
const stringData = [];
|
|
116
107
|
this._nodeMap = this.getNodeMap(node);
|
|
117
|
-
|
|
118
108
|
for (let i = 0; i < this._nodeMap.length; i++) {
|
|
119
109
|
const item = this._nodeMap[i];
|
|
120
|
-
|
|
121
110
|
if (truncate === 'word' && item.data[item.data.length - 1] === ' ') {
|
|
122
111
|
// remove random whitespace data between nodes
|
|
123
112
|
item.data.length -= 1;
|
|
124
113
|
}
|
|
125
|
-
|
|
126
114
|
stringData[i] = item.data;
|
|
127
|
-
|
|
128
115
|
for (let j = 0; j < item.data.length; j++) {
|
|
129
116
|
// map each word or character datum index to its corresponding node
|
|
130
117
|
nodeDataIndexes.push(i);
|
|
131
118
|
}
|
|
132
119
|
}
|
|
133
|
-
|
|
134
120
|
this._defaultStringData = cloneArray(stringData);
|
|
135
121
|
this._nodeDataIndexes = cloneArray(nodeDataIndexes);
|
|
136
122
|
this._maxHeight = maxLines === 'auto' ? getBoundingClientRect(this._parent).height : maxLines * actualLineHeight;
|
|
137
123
|
this._maxWidth = measureText(this._nodeMap.map(item => item.node), this._parent);
|
|
138
124
|
this._maxLines = maxLines === 'auto' ? Math.round(this._maxHeight / actualLineHeight) : maxLines;
|
|
139
125
|
}
|
|
140
|
-
|
|
141
126
|
getNodeMap(rootNode) {
|
|
142
127
|
const _this$_options2 = this._options,
|
|
143
|
-
|
|
144
|
-
|
|
128
|
+
shouldTruncateWhenInvisible = _this$_options2.shouldTruncateWhenInvisible,
|
|
129
|
+
truncate = _this$_options2.truncate;
|
|
145
130
|
const nodes = Array.from(rootNode.childNodes);
|
|
146
|
-
const map = [];
|
|
147
|
-
|
|
131
|
+
const map = [];
|
|
132
|
+
// parse child nodes and build a data map to associate each node with its data
|
|
148
133
|
nodes.forEach(node => {
|
|
149
134
|
if (node.nodeType === 1 || node.nodeType === 3) {
|
|
150
135
|
const shouldTruncate = shouldTruncateWhenInvisible ? true : isVisible(node, false);
|
|
151
136
|
const textContent = node.textContent + ' ';
|
|
152
137
|
map.push({
|
|
153
138
|
node,
|
|
154
|
-
data: truncate === 'word' ? shouldTruncate ?
|
|
139
|
+
data: truncate === 'word' ? shouldTruncate ?
|
|
140
|
+
// eslint-disable-next-line no-useless-escape
|
|
155
141
|
textContent.match(/.*?[\.\s\/]+?/g) : [''] : shouldTruncate ? node.textContent.split('') : []
|
|
156
142
|
});
|
|
157
143
|
}
|
|
158
144
|
});
|
|
159
145
|
return map;
|
|
160
146
|
}
|
|
161
|
-
|
|
162
147
|
getNodeIndexes(data) {
|
|
163
148
|
const nodeDataIndexes = [];
|
|
164
|
-
|
|
165
149
|
for (let i = 0; i < data.length; i++) {
|
|
166
150
|
for (let j = 0; j < data[i].length; j++) {
|
|
167
151
|
nodeDataIndexes.push([i, j]);
|
|
168
152
|
}
|
|
169
153
|
}
|
|
170
|
-
|
|
171
154
|
return nodeDataIndexes;
|
|
172
155
|
}
|
|
173
|
-
|
|
174
156
|
domString(data) {
|
|
175
157
|
let html = '';
|
|
176
|
-
|
|
177
158
|
for (let i = 0; i < data.length; i++) {
|
|
178
159
|
const mapItem = this._nodeMap[i];
|
|
179
160
|
const text = data[i].join('');
|
|
180
161
|
const safeText = escapeHtml(text);
|
|
181
|
-
|
|
182
162
|
if (mapItem.node.nodeType === Node.ELEMENT_NODE) {
|
|
183
163
|
const name = mapItem.node.nodeName;
|
|
184
164
|
const attr = mapItem.node.attributes;
|
|
185
165
|
let attributes = '';
|
|
186
|
-
|
|
187
166
|
for (let j = 0; j < attr.length; j++) {
|
|
188
167
|
const att = attr[j];
|
|
189
168
|
attributes += ` ${att.nodeName}="${att.nodeValue}"`;
|
|
190
169
|
}
|
|
191
|
-
|
|
192
170
|
html += `<${name}${attributes}>${safeText}</${name}>`;
|
|
193
171
|
} else if (mapItem.node.nodeType === 3) {
|
|
194
172
|
html += safeText;
|
|
195
173
|
}
|
|
196
174
|
}
|
|
197
|
-
|
|
198
175
|
return html;
|
|
199
176
|
}
|
|
200
|
-
|
|
201
177
|
checkFit(data) {
|
|
202
178
|
const html = this.domString(data);
|
|
203
179
|
const node = this._options.maxLines === 'auto' ? this._stage : this._parent;
|
|
204
180
|
let fits = true;
|
|
205
|
-
this._stage.innerHTML = html;
|
|
206
|
-
|
|
181
|
+
this._stage.innerHTML = html;
|
|
182
|
+
// allow a 0.5 px margin of error for browser calculation discrepancies
|
|
207
183
|
if (getBoundingClientRect(node).height - this._maxHeight > 0.5) {
|
|
208
184
|
fits = false;
|
|
209
185
|
}
|
|
210
|
-
|
|
211
186
|
return fits;
|
|
212
187
|
}
|
|
213
|
-
|
|
214
188
|
truncate() {
|
|
215
189
|
const _this$_options3 = this._options,
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
190
|
+
ellipsis = _this$_options3.ellipsis,
|
|
191
|
+
ignore = _this$_options3.ignore,
|
|
192
|
+
position = _this$_options3.position;
|
|
219
193
|
const middle = position === 'middle';
|
|
220
194
|
let truncated = false;
|
|
221
195
|
let truncatedText = '';
|
|
222
196
|
let stringData = null;
|
|
223
|
-
|
|
224
197
|
if (!this._stage) {
|
|
225
198
|
return;
|
|
226
199
|
}
|
|
227
|
-
|
|
228
200
|
const binarySearch = function (_low, _high, ev, middle) {
|
|
229
201
|
let _default = arguments.length > 4 && arguments[4] !== void 0 ? arguments[4] : null;
|
|
230
|
-
|
|
231
202
|
let low = _low;
|
|
232
203
|
let high = _high;
|
|
233
204
|
let bestResult = _default;
|
|
234
|
-
|
|
235
205
|
while (low <= high) {
|
|
236
206
|
const tryNumber = Math.floor((low + high) / 2);
|
|
237
|
-
|
|
238
207
|
if (ev(tryNumber, middle)) {
|
|
239
208
|
high = tryNumber - 1;
|
|
240
209
|
bestResult = tryNumber;
|
|
@@ -242,72 +211,65 @@ class Truncator {
|
|
|
242
211
|
low = tryNumber + 1;
|
|
243
212
|
}
|
|
244
213
|
}
|
|
245
|
-
|
|
246
214
|
return bestResult;
|
|
247
215
|
};
|
|
248
|
-
|
|
249
216
|
const truncateArray = (truncatedLength, originalArray, indexArray, middle) => {
|
|
250
217
|
let truncated = false;
|
|
251
218
|
const truncatedArray = cloneArray(originalArray);
|
|
252
|
-
|
|
253
219
|
switch (truncatedLength) {
|
|
254
220
|
// truncate nothing
|
|
255
221
|
case 0:
|
|
256
222
|
break;
|
|
257
|
-
// truncate all
|
|
258
223
|
|
|
224
|
+
// truncate all
|
|
259
225
|
case indexArray.length:
|
|
260
226
|
truncated = true;
|
|
261
|
-
|
|
262
227
|
for (let i = 0; i < truncatedArray.length; i++) {
|
|
263
228
|
truncatedArray[i] = [];
|
|
264
229
|
}
|
|
265
|
-
|
|
266
230
|
truncatedArray[0].push(ellipsis);
|
|
267
231
|
break;
|
|
268
|
-
// truncate a positive amount of elements
|
|
269
232
|
|
|
233
|
+
// truncate a positive amount of elements
|
|
270
234
|
default:
|
|
271
235
|
truncated = true;
|
|
272
|
-
|
|
273
236
|
if (middle) {
|
|
274
|
-
const dataHalves = Array(2);
|
|
275
|
-
|
|
237
|
+
const dataHalves = Array(2);
|
|
238
|
+
// calculate the indexes for two parts
|
|
276
239
|
dataHalves[0] = Math.floor((indexArray.length - truncatedLength - 1) / 2);
|
|
277
240
|
dataHalves[1] = dataHalves[0] + truncatedLength + 1;
|
|
278
241
|
const nodeHalves = dataHalves.map(index => indexArray[index]);
|
|
279
242
|
const sliceAmounts = Array(2);
|
|
280
243
|
sliceAmounts[0] = dataHalves[0] + 1;
|
|
281
|
-
sliceAmounts[1] = indexArray.length - truncatedLength - sliceAmounts[0];
|
|
244
|
+
sliceAmounts[1] = indexArray.length - truncatedLength - sliceAmounts[0];
|
|
282
245
|
|
|
246
|
+
// keep the first part
|
|
283
247
|
for (let i = 0; i <= nodeHalves[0]; i++) {
|
|
284
248
|
switch (true) {
|
|
285
249
|
case i < nodeHalves[0]:
|
|
286
250
|
sliceAmounts[0] -= truncatedArray[i].length;
|
|
287
251
|
break;
|
|
288
|
-
|
|
289
252
|
case i === nodeHalves[0]:
|
|
290
253
|
truncatedArray[i] = originalArray[i].slice(0, sliceAmounts[0]);
|
|
291
254
|
truncatedArray[i].push(ellipsis);
|
|
292
255
|
break;
|
|
293
256
|
}
|
|
294
|
-
}
|
|
295
|
-
|
|
257
|
+
}
|
|
296
258
|
|
|
259
|
+
// and the second part
|
|
297
260
|
for (let i = originalArray.length - 1; i >= nodeHalves[1]; i--) {
|
|
298
261
|
switch (true) {
|
|
299
262
|
case i > nodeHalves[1]:
|
|
300
263
|
sliceAmounts[1] -= originalArray[i].length;
|
|
301
264
|
break;
|
|
302
|
-
|
|
303
265
|
case i === nodeHalves[1]:
|
|
304
266
|
if (nodeHalves[1] > nodeHalves[0]) truncatedArray[i] = originalArray[i].slice(-sliceAmounts[1]);
|
|
305
267
|
if (nodeHalves[1] === nodeHalves[0]) truncatedArray[i] = truncatedArray[i].concat(originalArray[i].slice(-sliceAmounts[1]));
|
|
306
268
|
break;
|
|
307
269
|
}
|
|
308
|
-
}
|
|
309
|
-
|
|
270
|
+
}
|
|
310
271
|
|
|
272
|
+
// delete the middle
|
|
311
273
|
for (let i = nodeHalves[0] + 1; i < nodeHalves[1]; i++) {
|
|
312
274
|
truncatedArray[i] = [];
|
|
313
275
|
}
|
|
@@ -316,55 +278,44 @@ class Truncator {
|
|
|
316
278
|
const indexToTry = indexArray.length - truncatedLength - 1;
|
|
317
279
|
const nodeIndex = indexArray[indexToTry];
|
|
318
280
|
let sliceAmount = indexToTry + 1;
|
|
319
|
-
|
|
320
281
|
for (let i = 0; i < originalArray.length; i++) {
|
|
321
282
|
switch (true) {
|
|
322
283
|
case i < nodeIndex:
|
|
323
284
|
sliceAmount -= truncatedArray[i].length;
|
|
324
285
|
break;
|
|
325
|
-
|
|
326
286
|
case i === nodeIndex:
|
|
327
287
|
truncatedArray[i] = truncatedArray[i].slice(0, sliceAmount);
|
|
328
288
|
truncatedArray[i].push(ellipsis);
|
|
329
289
|
break;
|
|
330
|
-
|
|
331
290
|
case i > nodeIndex:
|
|
332
291
|
truncatedArray[i] = [];
|
|
333
292
|
break;
|
|
334
293
|
}
|
|
335
294
|
}
|
|
336
295
|
}
|
|
337
|
-
|
|
338
296
|
break;
|
|
339
297
|
}
|
|
340
|
-
|
|
341
298
|
return {
|
|
342
299
|
truncated,
|
|
343
300
|
truncatedArray
|
|
344
301
|
};
|
|
345
302
|
};
|
|
346
|
-
|
|
347
303
|
const truncateEvaluate = (truncatedLength, middle) => {
|
|
348
304
|
const _truncateArray = truncateArray(truncatedLength, this._defaultStringData, this._nodeDataIndexes, middle),
|
|
349
|
-
|
|
350
|
-
|
|
305
|
+
truncatedArray = _truncateArray.truncatedArray;
|
|
351
306
|
return this.checkFit(truncatedArray);
|
|
352
|
-
};
|
|
353
|
-
|
|
307
|
+
};
|
|
354
308
|
|
|
309
|
+
// find the best number of element to truncate
|
|
355
310
|
const finestMatch = binarySearch(0, this._nodeDataIndexes.length, truncateEvaluate, middle, this._nodeDataIndexes.length);
|
|
356
|
-
|
|
357
311
|
var _truncateArray2 = truncateArray(finestMatch, this._defaultStringData, this._nodeDataIndexes, middle);
|
|
358
|
-
|
|
359
312
|
truncated = _truncateArray2.truncated;
|
|
360
313
|
stringData = _truncateArray2.truncatedArray;
|
|
361
314
|
stringData = cleanData(stringData, this._options, true);
|
|
362
|
-
|
|
363
315
|
for (let i = 0; i < stringData.length; i++) {
|
|
364
316
|
const data = stringData[i];
|
|
365
317
|
truncatedText += data.join('');
|
|
366
318
|
}
|
|
367
|
-
|
|
368
319
|
if (truncated && !middle) {
|
|
369
320
|
truncatedText = cleanString(truncatedText.split(ellipsis)[0], ignore, false, true, true);
|
|
370
321
|
truncatedText += ellipsis;
|
|
@@ -372,7 +323,6 @@ class Truncator {
|
|
|
372
323
|
const halves = truncatedText.split(ellipsis);
|
|
373
324
|
truncatedText = cleanString(halves[0], ignore, false, true, true) + ellipsis + cleanString(halves[1], ignore, true, false, true);
|
|
374
325
|
}
|
|
375
|
-
|
|
376
326
|
return {
|
|
377
327
|
isTruncated: truncated,
|
|
378
328
|
text: truncatedText,
|
|
@@ -384,7 +334,5 @@ class Truncator {
|
|
|
384
334
|
}
|
|
385
335
|
};
|
|
386
336
|
}
|
|
387
|
-
|
|
388
337
|
}
|
|
389
|
-
|
|
390
338
|
export default truncate;
|
|
@@ -1,44 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
|
|
4
|
-
|
|
5
4
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
6
|
-
|
|
7
5
|
Object.defineProperty(exports, "__esModule", {
|
|
8
6
|
value: true
|
|
9
7
|
});
|
|
10
8
|
exports.default = exports.TruncateText = void 0;
|
|
11
|
-
|
|
12
9
|
var _react = _interopRequireWildcard(require("react"));
|
|
13
|
-
|
|
14
10
|
var _debounce = require("@instructure/debounce");
|
|
15
|
-
|
|
16
11
|
var _canUseDOM = require("@instructure/ui-dom-utils/lib/canUseDOM.js");
|
|
17
|
-
|
|
18
12
|
var _getBoundingClientRect = require("@instructure/ui-dom-utils/lib/getBoundingClientRect.js");
|
|
19
|
-
|
|
20
13
|
var _safeCloneElement = require("@instructure/ui-react-utils/lib/safeCloneElement.js");
|
|
21
|
-
|
|
22
14
|
var _ensureSingleChild = require("@instructure/ui-react-utils/lib/ensureSingleChild.js");
|
|
23
|
-
|
|
24
15
|
var _hack = require("@instructure/ui-react-utils/lib/hack.js");
|
|
25
|
-
|
|
26
16
|
var _console = require("@instructure/console");
|
|
27
|
-
|
|
28
17
|
var _testable = require("@instructure/ui-testable/lib/testable.js");
|
|
29
|
-
|
|
30
18
|
var _emotion = require("@instructure/emotion");
|
|
31
|
-
|
|
32
19
|
var _styles = _interopRequireDefault(require("./styles"));
|
|
33
|
-
|
|
34
20
|
var _theme = _interopRequireDefault(require("./theme"));
|
|
35
|
-
|
|
36
21
|
var _truncate = _interopRequireDefault(require("./utils/truncate"));
|
|
37
|
-
|
|
38
22
|
var _props = require("./props");
|
|
39
|
-
|
|
40
23
|
var _dec, _dec2, _dec3, _class, _class2;
|
|
41
|
-
|
|
42
24
|
/**
|
|
43
25
|
---
|
|
44
26
|
category: components
|
|
@@ -54,20 +36,16 @@ let TruncateText = (_dec = (0, _emotion.withStyle)(_styles.default, _theme.defau
|
|
|
54
36
|
this._stage = null;
|
|
55
37
|
this._wasTruncated = void 0;
|
|
56
38
|
this._resizeListener = void 0;
|
|
57
|
-
|
|
58
39
|
this.update = () => {
|
|
59
40
|
if (this.ref) {
|
|
60
41
|
this.setState(this.initialState);
|
|
61
42
|
}
|
|
62
43
|
};
|
|
63
|
-
|
|
64
44
|
this.state = this.initialState;
|
|
65
45
|
}
|
|
66
|
-
|
|
67
46
|
get _ref() {
|
|
68
47
|
return this.ref;
|
|
69
48
|
}
|
|
70
|
-
|
|
71
49
|
get initialState() {
|
|
72
50
|
return {
|
|
73
51
|
isTruncated: false,
|
|
@@ -76,13 +54,11 @@ let TruncateText = (_dec = (0, _emotion.withStyle)(_styles.default, _theme.defau
|
|
|
76
54
|
truncatedText: void 0
|
|
77
55
|
};
|
|
78
56
|
}
|
|
79
|
-
|
|
80
57
|
componentDidMount() {
|
|
81
58
|
const _this$props = this.props,
|
|
82
|
-
|
|
83
|
-
|
|
59
|
+
children = _this$props.children,
|
|
60
|
+
makeStyles = _this$props.makeStyles;
|
|
84
61
|
makeStyles === null || makeStyles === void 0 ? void 0 : makeStyles();
|
|
85
|
-
|
|
86
62
|
if (children) {
|
|
87
63
|
this.checkChildren();
|
|
88
64
|
const txt = (0, _ensureSingleChild.ensureSingleChild)(children);
|
|
@@ -92,10 +68,8 @@ let TruncateText = (_dec = (0, _emotion.withStyle)(_styles.default, _theme.defau
|
|
|
92
68
|
leading: true,
|
|
93
69
|
trailing: true
|
|
94
70
|
});
|
|
95
|
-
|
|
96
71
|
const _getBoundingClientRec = (0, _getBoundingClientRect.getBoundingClientRect)(this.ref),
|
|
97
|
-
|
|
98
|
-
|
|
72
|
+
origWidth = _getBoundingClientRec.width;
|
|
99
73
|
this._resizeListener = new ResizeObserver(entries => {
|
|
100
74
|
// requestAnimationFrame call is needed becuase some truncatetext test cases
|
|
101
75
|
// failed due to ResizeObserver was not able to deliver all observations within a single animation frame
|
|
@@ -103,39 +77,33 @@ let TruncateText = (_dec = (0, _emotion.withStyle)(_styles.default, _theme.defau
|
|
|
103
77
|
requestAnimationFrame(() => {
|
|
104
78
|
for (const entry of entries) {
|
|
105
79
|
const width = entry.contentRect.width;
|
|
106
|
-
|
|
107
80
|
if (origWidth !== width) {
|
|
108
81
|
this.props.debounce === 0 ? this.update() : this._debounced();
|
|
109
82
|
}
|
|
110
83
|
}
|
|
111
84
|
});
|
|
112
85
|
});
|
|
113
|
-
|
|
114
86
|
this._resizeListener.observe(this.ref);
|
|
115
87
|
}
|
|
116
88
|
}
|
|
117
|
-
|
|
118
89
|
componentWillUnmount() {
|
|
119
90
|
if (this._resizeListener) {
|
|
120
91
|
this._resizeListener.disconnect();
|
|
121
92
|
}
|
|
122
|
-
|
|
123
93
|
if (this._debounced) {
|
|
124
94
|
this._debounced.cancel();
|
|
125
95
|
}
|
|
126
96
|
}
|
|
127
|
-
|
|
128
97
|
componentDidUpdate(prevProps) {
|
|
129
98
|
const _this$props2 = this.props,
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
99
|
+
children = _this$props2.children,
|
|
100
|
+
onUpdate = _this$props2.onUpdate,
|
|
101
|
+
makeStyles = _this$props2.makeStyles;
|
|
133
102
|
makeStyles === null || makeStyles === void 0 ? void 0 : makeStyles();
|
|
134
103
|
const _this$state = this.state,
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
104
|
+
isTruncated = _this$state.isTruncated,
|
|
105
|
+
needsSecondRender = _this$state.needsSecondRender,
|
|
106
|
+
truncatedText = _this$state.truncatedText;
|
|
139
107
|
if (children) {
|
|
140
108
|
if (prevProps !== this.props) {
|
|
141
109
|
if (prevProps.children !== this.props.children) {
|
|
@@ -143,13 +111,11 @@ let TruncateText = (_dec = (0, _emotion.withStyle)(_styles.default, _theme.defau
|
|
|
143
111
|
this.checkChildren();
|
|
144
112
|
const txt = (0, _ensureSingleChild.ensureSingleChild)(children);
|
|
145
113
|
this._text = txt ? txt : void 0;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
|
|
114
|
+
}
|
|
115
|
+
// require the double render whenever props change
|
|
149
116
|
this.setState(this.initialState);
|
|
150
117
|
return;
|
|
151
118
|
}
|
|
152
|
-
|
|
153
119
|
if (!needsSecondRender && (isTruncated || this._wasTruncated)) {
|
|
154
120
|
onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate(isTruncated, truncatedText);
|
|
155
121
|
this._wasTruncated = isTruncated;
|
|
@@ -158,12 +124,10 @@ let TruncateText = (_dec = (0, _emotion.withStyle)(_styles.default, _theme.defau
|
|
|
158
124
|
}
|
|
159
125
|
}
|
|
160
126
|
}
|
|
161
|
-
|
|
162
127
|
checkChildren() {
|
|
163
128
|
(0, _console.logError)(!(() => {
|
|
164
129
|
let isTooDeep = false;
|
|
165
130
|
const text = (0, _ensureSingleChild.ensureSingleChild)(this.props.children);
|
|
166
|
-
|
|
167
131
|
_react.default.Children.forEach(text.props.children, child => {
|
|
168
132
|
if (child.props) {
|
|
169
133
|
_react.default.Children.forEach(child.props.children, grandChild => {
|
|
@@ -175,24 +139,20 @@ let TruncateText = (_dec = (0, _emotion.withStyle)(_styles.default, _theme.defau
|
|
|
175
139
|
});
|
|
176
140
|
}
|
|
177
141
|
});
|
|
178
|
-
|
|
179
142
|
return isTooDeep;
|
|
180
143
|
})(), `[TruncateText] Some children are too deep in the node tree and will not render.`);
|
|
181
144
|
}
|
|
182
|
-
|
|
183
145
|
truncate() {
|
|
184
146
|
if (!this.state.needsSecondRender) {
|
|
185
147
|
return;
|
|
186
148
|
}
|
|
187
|
-
|
|
188
149
|
if (_canUseDOM.canUseDOM) {
|
|
189
150
|
var _this$props$styles;
|
|
190
|
-
|
|
191
|
-
|
|
151
|
+
const result = (0, _truncate.default)(this._stage, {
|
|
152
|
+
...this.props,
|
|
192
153
|
parent: this.ref ? this.ref : void 0,
|
|
193
154
|
lineHeight: (_this$props$styles = this.props.styles) === null || _this$props$styles === void 0 ? void 0 : _this$props$styles.lineHeight
|
|
194
155
|
});
|
|
195
|
-
|
|
196
156
|
if (result) {
|
|
197
157
|
const element = this.renderChildren(result.isTruncated, result.data, result.constraints.width);
|
|
198
158
|
this.setState({
|
|
@@ -204,9 +164,8 @@ let TruncateText = (_dec = (0, _emotion.withStyle)(_styles.default, _theme.defau
|
|
|
204
164
|
}
|
|
205
165
|
} else {
|
|
206
166
|
var _this$ref, _this$ref2;
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
167
|
+
const textContent = (_this$ref = this.ref) !== null && _this$ref !== void 0 && _this$ref.textContent ? (_this$ref2 = this.ref) === null || _this$ref2 === void 0 ? void 0 : _this$ref2.textContent : void 0;
|
|
168
|
+
// if dom isn't available, use original children
|
|
210
169
|
this.setState({
|
|
211
170
|
needsSecondRender: false,
|
|
212
171
|
isTruncated: false,
|
|
@@ -215,47 +174,38 @@ let TruncateText = (_dec = (0, _emotion.withStyle)(_styles.default, _theme.defau
|
|
|
215
174
|
});
|
|
216
175
|
}
|
|
217
176
|
}
|
|
218
|
-
|
|
219
177
|
renderChildren(truncated, data, width) {
|
|
220
178
|
var _this$props$styles2;
|
|
221
|
-
|
|
222
179
|
if (!truncated) {
|
|
223
180
|
return this._text;
|
|
224
181
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
182
|
+
const childElements = [];
|
|
183
|
+
// iterate over each node used in the truncated string
|
|
228
184
|
for (let i = 0; i < data.length; i++) {
|
|
229
185
|
const item = data[i];
|
|
230
186
|
const element = this._text.props.children[i];
|
|
231
187
|
const nodeText = item.join('');
|
|
232
|
-
|
|
233
188
|
if (element && element.props) {
|
|
234
189
|
// if node is an html element and not just a string
|
|
235
190
|
childElements.push((0, _safeCloneElement.safeCloneElement)(element, element.props, nodeText));
|
|
236
191
|
} else {
|
|
237
192
|
childElements.push(nodeText);
|
|
238
193
|
}
|
|
239
|
-
}
|
|
194
|
+
}
|
|
195
|
+
// this spacer element is set to the max width the full text could
|
|
240
196
|
// potentially be without this, text in `width: auto` elements won't expand
|
|
241
197
|
// to accommodate more text, once truncated
|
|
242
|
-
|
|
243
|
-
|
|
244
198
|
childElements.push((0, _emotion.jsx)("span", {
|
|
245
199
|
css: (_this$props$styles2 = this.props.styles) === null || _this$props$styles2 === void 0 ? void 0 : _this$props$styles2.spacer,
|
|
246
200
|
style: {
|
|
247
201
|
width: width || void 0
|
|
248
202
|
}
|
|
249
203
|
}));
|
|
250
|
-
|
|
251
204
|
const children = _react.default.Children.map(childElements, child => child);
|
|
252
|
-
|
|
253
205
|
return this._text.props ? (0, _safeCloneElement.safeCloneElement)(this._text, this._text.props, children) : children;
|
|
254
206
|
}
|
|
255
|
-
|
|
256
207
|
render() {
|
|
257
208
|
var _this$props$styles3;
|
|
258
|
-
|
|
259
209
|
const truncatedElement = this.state.truncatedElement;
|
|
260
210
|
const children = this.props.children;
|
|
261
211
|
return (0, _emotion.jsx)("span", {
|
|
@@ -269,7 +219,6 @@ let TruncateText = (_dec = (0, _emotion.withStyle)(_styles.default, _theme.defau
|
|
|
269
219
|
}
|
|
270
220
|
}, (0, _ensureSingleChild.ensureSingleChild)(children))), truncatedElement);
|
|
271
221
|
}
|
|
272
|
-
|
|
273
222
|
}, _class2.displayName = "TruncateText", _class2.componentId = 'TruncateText', _class2.allowedProps = _props.allowedProps, _class2.propTypes = _props.propTypes, _class2.defaultProps = {
|
|
274
223
|
maxLines: 1,
|
|
275
224
|
ellipsis: '\u2026',
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
-
|
|
5
4
|
Object.defineProperty(exports, "__esModule", {
|
|
6
5
|
value: true
|
|
7
6
|
});
|
|
8
7
|
exports.propTypes = exports.allowedProps = void 0;
|
|
9
|
-
|
|
10
8
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
11
|
-
|
|
12
9
|
/*
|
|
13
10
|
* The MIT License (MIT)
|
|
14
11
|
*
|
|
@@ -32,6 +29,7 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
|
32
29
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
33
30
|
* SOFTWARE.
|
|
34
31
|
*/
|
|
32
|
+
|
|
35
33
|
const propTypes = {
|
|
36
34
|
children: _propTypes.default.node.isRequired,
|
|
37
35
|
maxLines: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),
|
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
-
|
|
8
7
|
/*
|
|
9
8
|
* The MIT License (MIT)
|
|
10
9
|
*
|
|
@@ -61,6 +60,5 @@ const generateStyle = componentTheme => {
|
|
|
61
60
|
lineHeight: componentTheme.lineHeight
|
|
62
61
|
};
|
|
63
62
|
};
|
|
64
|
-
|
|
65
63
|
var _default = generateStyle;
|
|
66
64
|
exports.default = _default;
|
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
-
|
|
8
7
|
/*
|
|
9
8
|
* The MIT License (MIT)
|
|
10
9
|
*
|
|
@@ -40,9 +39,9 @@ const generateComponentTheme = theme => {
|
|
|
40
39
|
fontFamily: typography === null || typography === void 0 ? void 0 : typography.fontFamily,
|
|
41
40
|
lineHeight: typography === null || typography === void 0 ? void 0 : typography.lineHeight
|
|
42
41
|
};
|
|
43
|
-
return {
|
|
42
|
+
return {
|
|
43
|
+
...componentVariables
|
|
44
44
|
};
|
|
45
45
|
};
|
|
46
|
-
|
|
47
46
|
var _default = generateComponentTheme;
|
|
48
47
|
exports.default = _default;
|