@instructure/ui-truncate-text 10.16.1-snapshot-0 → 10.16.1
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 +1 -1
- package/es/TruncateText/__new-tests__/TruncateText.test.js +26 -10
- package/es/TruncateText/index.js +17 -14
- package/es/TruncateText/utils/__new-tests__/measureText.test.js +31 -23
- package/lib/TruncateText/__new-tests__/TruncateText.test.js +28 -13
- package/lib/TruncateText/index.js +15 -14
- package/lib/TruncateText/utils/__new-tests__/measureText.test.js +38 -30
- package/package.json +15 -15
- package/src/TruncateText/__new-tests__/TruncateText.test.tsx +0 -1
- package/src/TruncateText/index.tsx +6 -6
- package/src/TruncateText/props.ts +1 -1
- package/src/TruncateText/utils/__new-tests__/measureText.test.tsx +0 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/types/TruncateText/__new-tests__/TruncateText.test.d.ts.map +1 -1
- package/types/TruncateText/index.d.ts +1 -3
- package/types/TruncateText/index.d.ts.map +1 -1
- package/types/TruncateText/props.d.ts +1 -1
- package/types/TruncateText/props.d.ts.map +1 -1
- package/types/TruncateText/utils/__new-tests__/measureText.test.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
-
## [10.16.1
|
|
6
|
+
## [10.16.1](https://github.com/instructure/instructure-ui/compare/v10.16.0...v10.16.1) (2025-04-22)
|
|
7
7
|
|
|
8
8
|
**Note:** Version bump only for package @instructure/ui-truncate-text
|
|
9
9
|
|
|
@@ -23,12 +23,12 @@ var _TruncateText, _TruncateText2, _TruncateText3, _TruncateText4, _TruncateText
|
|
|
23
23
|
* SOFTWARE.
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import React from 'react';
|
|
27
26
|
import { render, waitFor } from '@testing-library/react';
|
|
28
27
|
import { vi, expect } from 'vitest';
|
|
29
28
|
import '@testing-library/jest-dom';
|
|
30
29
|
import { runAxeCheck } from '@instructure/ui-axe-check';
|
|
31
30
|
import { TruncateText } from '../index';
|
|
31
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
32
32
|
const defaultText = 'Hello world! This is a long string that should truncate';
|
|
33
33
|
describe('<TruncateText />', () => {
|
|
34
34
|
let consoleErrorMock;
|
|
@@ -40,11 +40,18 @@ describe('<TruncateText />', () => {
|
|
|
40
40
|
consoleErrorMock.mockRestore();
|
|
41
41
|
});
|
|
42
42
|
it('should warn if children prop receives too deep of a node tree', async () => {
|
|
43
|
-
render(
|
|
43
|
+
render(_jsx("div", {
|
|
44
44
|
style: {
|
|
45
45
|
width: '200px'
|
|
46
|
-
}
|
|
47
|
-
|
|
46
|
+
},
|
|
47
|
+
children: _TruncateText || (_TruncateText = _jsxs(TruncateText, {
|
|
48
|
+
children: ["Hello world!", ' ', _jsx("strong", {
|
|
49
|
+
children: _jsx("span", {
|
|
50
|
+
children: "This is a"
|
|
51
|
+
})
|
|
52
|
+
}), ' ', "long string that should truncate"]
|
|
53
|
+
}))
|
|
54
|
+
}));
|
|
48
55
|
const expectedErrorMessage = 'Some children are too deep in the node tree and will not render.';
|
|
49
56
|
await waitFor(() => {
|
|
50
57
|
expect(consoleErrorMock).toHaveBeenCalledWith(expect.stringContaining(expectedErrorMessage), expect.any(String));
|
|
@@ -53,21 +60,30 @@ describe('<TruncateText />', () => {
|
|
|
53
60
|
it('should handle the empty string as a child', async () => {
|
|
54
61
|
let error = false;
|
|
55
62
|
try {
|
|
56
|
-
const _render = render(_TruncateText2 || (_TruncateText2 =
|
|
63
|
+
const _render = render(_TruncateText2 || (_TruncateText2 = _jsx(TruncateText, {
|
|
64
|
+
children: ''
|
|
65
|
+
}))),
|
|
57
66
|
rerender = _render.rerender;
|
|
58
|
-
rerender(_TruncateText3 || (_TruncateText3 =
|
|
59
|
-
|
|
67
|
+
rerender(_TruncateText3 || (_TruncateText3 = _jsx(TruncateText, {
|
|
68
|
+
children: 'hello world'
|
|
69
|
+
})));
|
|
70
|
+
rerender(_TruncateText4 || (_TruncateText4 = _jsx(TruncateText, {
|
|
71
|
+
children: ''
|
|
72
|
+
})));
|
|
60
73
|
} catch (_e) {
|
|
61
74
|
error = true;
|
|
62
75
|
}
|
|
63
76
|
expect(error).toBe(false);
|
|
64
77
|
});
|
|
65
78
|
it('should meet a11y standards', async () => {
|
|
66
|
-
const _render2 = render(
|
|
79
|
+
const _render2 = render(_jsx("div", {
|
|
67
80
|
style: {
|
|
68
81
|
width: '200px'
|
|
69
|
-
}
|
|
70
|
-
|
|
82
|
+
},
|
|
83
|
+
children: _TruncateText5 || (_TruncateText5 = _jsx(TruncateText, {
|
|
84
|
+
children: defaultText
|
|
85
|
+
}))
|
|
86
|
+
})),
|
|
71
87
|
container = _render2.container;
|
|
72
88
|
const axeCheck = await runAxeCheck(container);
|
|
73
89
|
expect(axeCheck).toBe(true);
|
package/es/TruncateText/index.js
CHANGED
|
@@ -22,18 +22,19 @@ var _dec, _dec2, _dec3, _class, _TruncateText;
|
|
|
22
22
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
23
|
* SOFTWARE.
|
|
24
24
|
*/
|
|
25
|
-
|
|
26
|
-
import
|
|
25
|
+
|
|
26
|
+
import { Children, Component } from 'react';
|
|
27
27
|
import { debounce } from '@instructure/debounce';
|
|
28
28
|
import { canUseDOM, getBoundingClientRect } from '@instructure/ui-dom-utils';
|
|
29
29
|
import { safeCloneElement, ensureSingleChild, hack } from '@instructure/ui-react-utils';
|
|
30
30
|
import { logError as error } from '@instructure/console';
|
|
31
31
|
import { testable } from '@instructure/ui-testable';
|
|
32
|
-
import { withStyle
|
|
32
|
+
import { withStyle } from '@instructure/emotion';
|
|
33
33
|
import generateStyle from './styles';
|
|
34
34
|
import generateComponentTheme from './theme';
|
|
35
35
|
import truncate from './utils/truncate';
|
|
36
36
|
import { propTypes, allowedProps } from './props';
|
|
37
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
37
38
|
/**
|
|
38
39
|
---
|
|
39
40
|
category: components
|
|
@@ -142,9 +143,9 @@ let TruncateText = (_dec = withStyle(generateStyle, generateComponentTheme), _de
|
|
|
142
143
|
error(!(() => {
|
|
143
144
|
let isTooDeep = false;
|
|
144
145
|
const text = ensureSingleChild(this.props.children);
|
|
145
|
-
|
|
146
|
+
Children.forEach(text.props.children, child => {
|
|
146
147
|
if (child.props) {
|
|
147
|
-
|
|
148
|
+
Children.forEach(child.props.children, grandChild => {
|
|
148
149
|
// currently we don't support node trees deeper than 2 levels
|
|
149
150
|
// truncation will still occur on their text content, but their actual node structure will be lost
|
|
150
151
|
if (grandChild.props) {
|
|
@@ -209,29 +210,31 @@ let TruncateText = (_dec = withStyle(generateStyle, generateComponentTheme), _de
|
|
|
209
210
|
// this spacer element is set to the max width the full text could
|
|
210
211
|
// potentially be without this, text in `width: auto` elements won't expand
|
|
211
212
|
// to accommodate more text, once truncated
|
|
212
|
-
childElements.push(
|
|
213
|
+
childElements.push(_jsx("span", {
|
|
213
214
|
css: (_this$props$styles2 = this.props.styles) === null || _this$props$styles2 === void 0 ? void 0 : _this$props$styles2.spacer,
|
|
214
215
|
style: {
|
|
215
216
|
width: width || void 0
|
|
216
217
|
}
|
|
217
218
|
}));
|
|
218
|
-
const children =
|
|
219
|
+
const children = Children.map(childElements, child => child);
|
|
219
220
|
return this._text.props ? safeCloneElement(this._text, this._text.props, children) : children;
|
|
220
221
|
}
|
|
221
222
|
render() {
|
|
222
223
|
var _this$props$styles3;
|
|
223
224
|
const truncatedElement = this.state.truncatedElement;
|
|
224
225
|
const children = this.props.children;
|
|
225
|
-
return
|
|
226
|
+
return _jsxs("span", {
|
|
226
227
|
css: (_this$props$styles3 = this.props.styles) === null || _this$props$styles3 === void 0 ? void 0 : _this$props$styles3.truncateText,
|
|
227
228
|
ref: el => {
|
|
228
229
|
this.ref = el;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
230
|
+
},
|
|
231
|
+
children: [children && (truncatedElement ? null : _jsx("span", {
|
|
232
|
+
ref: el => {
|
|
233
|
+
this._stage = el;
|
|
234
|
+
},
|
|
235
|
+
children: ensureSingleChild(children)
|
|
236
|
+
})), truncatedElement]
|
|
237
|
+
});
|
|
235
238
|
}
|
|
236
239
|
}, _TruncateText.displayName = "TruncateText", _TruncateText.componentId = 'TruncateText', _TruncateText.allowedProps = allowedProps, _TruncateText.propTypes = propTypes, _TruncateText.defaultProps = {
|
|
237
240
|
maxLines: 1,
|
|
@@ -23,11 +23,11 @@ var _div, _div2, _div3, _div4;
|
|
|
23
23
|
* SOFTWARE.
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import React from 'react';
|
|
27
26
|
import { render, screen } from '@testing-library/react';
|
|
28
27
|
import { vi, expect } from 'vitest';
|
|
29
28
|
import '@testing-library/jest-dom';
|
|
30
29
|
import measureText from '../measureText';
|
|
30
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
31
31
|
const baseStyle = {
|
|
32
32
|
fontSize: '16px',
|
|
33
33
|
fontFamily: 'Arial',
|
|
@@ -67,34 +67,39 @@ describe('measureText', () => {
|
|
|
67
67
|
expect(width).toBe(0);
|
|
68
68
|
});
|
|
69
69
|
it('should calculate text width correctly', () => {
|
|
70
|
-
render(_div || (_div =
|
|
70
|
+
render(_div || (_div = _jsxs("div", {
|
|
71
71
|
"data-testid": "stage",
|
|
72
|
-
style: baseStyle
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
style: baseStyle,
|
|
73
|
+
children: ["Lorem ipsum ", _jsx("span", {
|
|
74
|
+
style: baseStyle,
|
|
75
|
+
children: "DOLOR SIT AMET."
|
|
76
|
+
})]
|
|
77
|
+
})));
|
|
76
78
|
const stage = screen.getByTestId('stage');
|
|
77
79
|
const nodes = getNodes(stage);
|
|
78
80
|
const width = measureText(nodes, stage);
|
|
79
81
|
expect(width).toBe(270);
|
|
80
82
|
});
|
|
81
83
|
it('should account for different nodes', async () => {
|
|
82
|
-
const _render = render(_div2 || (_div2 =
|
|
84
|
+
const _render = render(_div2 || (_div2 = _jsxs("div", {
|
|
83
85
|
"data-testid": "stage",
|
|
84
|
-
style: baseStyle
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
style: baseStyle,
|
|
87
|
+
children: ["Lorem ipsum ", _jsx("span", {
|
|
88
|
+
style: baseStyle,
|
|
89
|
+
children: "DOLOR SIT AMET."
|
|
90
|
+
})]
|
|
91
|
+
}))),
|
|
88
92
|
rerender = _render.rerender;
|
|
89
93
|
const stage = screen.getByTestId('stage');
|
|
90
94
|
const nodes = getNodes(stage);
|
|
91
95
|
const width = measureText(nodes, stage);
|
|
92
96
|
|
|
93
97
|
// Set child
|
|
94
|
-
rerender(_div3 || (_div3 =
|
|
98
|
+
rerender(_div3 || (_div3 = _jsx("div", {
|
|
95
99
|
"data-testid": "stage",
|
|
96
|
-
style: baseStyle
|
|
97
|
-
|
|
100
|
+
style: baseStyle,
|
|
101
|
+
children: "Lorem ipsum DOLOR SIT AMET."
|
|
102
|
+
})));
|
|
98
103
|
const stage2 = screen.getByTestId('stage');
|
|
99
104
|
const nodes2 = getNodes(stage2);
|
|
100
105
|
const width2 = measureText(nodes2, stage2);
|
|
@@ -107,10 +112,11 @@ describe('measureText', () => {
|
|
|
107
112
|
fontStyle: 'italic',
|
|
108
113
|
fontFamily: 'Arial'
|
|
109
114
|
};
|
|
110
|
-
render(
|
|
115
|
+
render(_jsx("div", {
|
|
111
116
|
"data-testid": "stage",
|
|
112
|
-
style: mockedStyle
|
|
113
|
-
|
|
117
|
+
style: mockedStyle,
|
|
118
|
+
children: "Lorem ipsum"
|
|
119
|
+
}));
|
|
114
120
|
const stage = screen.getByTestId('stage');
|
|
115
121
|
const nodes = getNodes(stage);
|
|
116
122
|
measureText(nodes, stage);
|
|
@@ -122,10 +128,11 @@ describe('measureText', () => {
|
|
|
122
128
|
expect(context.font).toBe('bold italic 20px Arial');
|
|
123
129
|
});
|
|
124
130
|
it('should account for letter spacing styles', async () => {
|
|
125
|
-
const _render2 = render(_div4 || (_div4 =
|
|
131
|
+
const _render2 = render(_div4 || (_div4 = _jsx("div", {
|
|
126
132
|
"data-testid": "stage",
|
|
127
|
-
style: baseStyle
|
|
128
|
-
|
|
133
|
+
style: baseStyle,
|
|
134
|
+
children: "Lorem ipsum"
|
|
135
|
+
}))),
|
|
129
136
|
rerender = _render2.rerender;
|
|
130
137
|
const stage = screen.getByTestId('stage');
|
|
131
138
|
const nodes = getNodes(stage);
|
|
@@ -133,13 +140,14 @@ describe('measureText', () => {
|
|
|
133
140
|
expect(width).toBe(110); // default mocked width (text.length * 10)
|
|
134
141
|
|
|
135
142
|
// Set letterSpacing
|
|
136
|
-
rerender(
|
|
143
|
+
rerender(_jsx("div", {
|
|
137
144
|
"data-testid": "stage2",
|
|
138
145
|
style: {
|
|
139
146
|
...baseStyle,
|
|
140
147
|
letterSpacing: '5px'
|
|
141
|
-
}
|
|
142
|
-
|
|
148
|
+
},
|
|
149
|
+
children: "Lorem ipsum"
|
|
150
|
+
}));
|
|
143
151
|
const stage2 = screen.getByTestId('stage2');
|
|
144
152
|
const nodes2 = getNodes(stage2);
|
|
145
153
|
const width2 = measureText(nodes2, stage2);
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var _react = _interopRequireDefault(require("react"));
|
|
5
|
-
var _react2 = require("@testing-library/react");
|
|
3
|
+
var _react = require("@testing-library/react");
|
|
6
4
|
var _vitest = require("vitest");
|
|
7
5
|
require("@testing-library/jest-dom");
|
|
8
6
|
var _runAxeCheck = require("@instructure/ui-axe-check/lib/runAxeCheck.js");
|
|
9
7
|
var _index = require("../index");
|
|
8
|
+
var _jsxRuntime = require("@emotion/react/jsx-runtime");
|
|
10
9
|
var _TruncateText, _TruncateText2, _TruncateText3, _TruncateText4, _TruncateText5;
|
|
11
10
|
/*
|
|
12
11
|
* The MIT License (MIT)
|
|
@@ -42,34 +41,50 @@ describe('<TruncateText />', () => {
|
|
|
42
41
|
consoleErrorMock.mockRestore();
|
|
43
42
|
});
|
|
44
43
|
it('should warn if children prop receives too deep of a node tree', async () => {
|
|
45
|
-
(0,
|
|
44
|
+
(0, _react.render)((0, _jsxRuntime.jsx)("div", {
|
|
46
45
|
style: {
|
|
47
46
|
width: '200px'
|
|
48
|
-
}
|
|
49
|
-
|
|
47
|
+
},
|
|
48
|
+
children: _TruncateText || (_TruncateText = (0, _jsxRuntime.jsxs)(_index.TruncateText, {
|
|
49
|
+
children: ["Hello world!", ' ', (0, _jsxRuntime.jsx)("strong", {
|
|
50
|
+
children: (0, _jsxRuntime.jsx)("span", {
|
|
51
|
+
children: "This is a"
|
|
52
|
+
})
|
|
53
|
+
}), ' ', "long string that should truncate"]
|
|
54
|
+
}))
|
|
55
|
+
}));
|
|
50
56
|
const expectedErrorMessage = 'Some children are too deep in the node tree and will not render.';
|
|
51
|
-
await (0,
|
|
57
|
+
await (0, _react.waitFor)(() => {
|
|
52
58
|
(0, _vitest.expect)(consoleErrorMock).toHaveBeenCalledWith(_vitest.expect.stringContaining(expectedErrorMessage), _vitest.expect.any(String));
|
|
53
59
|
});
|
|
54
60
|
});
|
|
55
61
|
it('should handle the empty string as a child', async () => {
|
|
56
62
|
let error = false;
|
|
57
63
|
try {
|
|
58
|
-
const _render = (0,
|
|
64
|
+
const _render = (0, _react.render)(_TruncateText2 || (_TruncateText2 = (0, _jsxRuntime.jsx)(_index.TruncateText, {
|
|
65
|
+
children: ''
|
|
66
|
+
}))),
|
|
59
67
|
rerender = _render.rerender;
|
|
60
|
-
rerender(_TruncateText3 || (_TruncateText3 =
|
|
61
|
-
|
|
68
|
+
rerender(_TruncateText3 || (_TruncateText3 = (0, _jsxRuntime.jsx)(_index.TruncateText, {
|
|
69
|
+
children: 'hello world'
|
|
70
|
+
})));
|
|
71
|
+
rerender(_TruncateText4 || (_TruncateText4 = (0, _jsxRuntime.jsx)(_index.TruncateText, {
|
|
72
|
+
children: ''
|
|
73
|
+
})));
|
|
62
74
|
} catch (_e) {
|
|
63
75
|
error = true;
|
|
64
76
|
}
|
|
65
77
|
(0, _vitest.expect)(error).toBe(false);
|
|
66
78
|
});
|
|
67
79
|
it('should meet a11y standards', async () => {
|
|
68
|
-
const _render2 = (0,
|
|
80
|
+
const _render2 = (0, _react.render)((0, _jsxRuntime.jsx)("div", {
|
|
69
81
|
style: {
|
|
70
82
|
width: '200px'
|
|
71
|
-
}
|
|
72
|
-
|
|
83
|
+
},
|
|
84
|
+
children: _TruncateText5 || (_TruncateText5 = (0, _jsxRuntime.jsx)(_index.TruncateText, {
|
|
85
|
+
children: defaultText
|
|
86
|
+
}))
|
|
87
|
+
})),
|
|
73
88
|
container = _render2.container;
|
|
74
89
|
const axeCheck = await (0, _runAxeCheck.runAxeCheck)(container);
|
|
75
90
|
(0, _vitest.expect)(axeCheck).toBe(true);
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
|
|
4
3
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
5
4
|
Object.defineProperty(exports, "__esModule", {
|
|
6
5
|
value: true
|
|
7
6
|
});
|
|
8
7
|
exports.default = exports.TruncateText = void 0;
|
|
9
|
-
var _react =
|
|
8
|
+
var _react = require("react");
|
|
10
9
|
var _debounce = require("@instructure/debounce");
|
|
11
10
|
var _canUseDOM = require("@instructure/ui-dom-utils/lib/canUseDOM.js");
|
|
12
11
|
var _getBoundingClientRect = require("@instructure/ui-dom-utils/lib/getBoundingClientRect.js");
|
|
@@ -20,6 +19,7 @@ var _styles = _interopRequireDefault(require("./styles"));
|
|
|
20
19
|
var _theme = _interopRequireDefault(require("./theme"));
|
|
21
20
|
var _truncate = _interopRequireDefault(require("./utils/truncate"));
|
|
22
21
|
var _props = require("./props");
|
|
22
|
+
var _jsxRuntime = require("@emotion/react/jsx-runtime");
|
|
23
23
|
var _dec, _dec2, _dec3, _class, _TruncateText;
|
|
24
24
|
/*
|
|
25
25
|
* The MIT License (MIT)
|
|
@@ -44,7 +44,6 @@ var _dec, _dec2, _dec3, _class, _TruncateText;
|
|
|
44
44
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
45
45
|
* SOFTWARE.
|
|
46
46
|
*/
|
|
47
|
-
/** @jsx jsx */
|
|
48
47
|
/**
|
|
49
48
|
---
|
|
50
49
|
category: components
|
|
@@ -153,9 +152,9 @@ let TruncateText = exports.TruncateText = (_dec = (0, _emotion.withStyle)(_style
|
|
|
153
152
|
(0, _console.logError)(!(() => {
|
|
154
153
|
let isTooDeep = false;
|
|
155
154
|
const text = (0, _ensureSingleChild.ensureSingleChild)(this.props.children);
|
|
156
|
-
_react.
|
|
155
|
+
_react.Children.forEach(text.props.children, child => {
|
|
157
156
|
if (child.props) {
|
|
158
|
-
_react.
|
|
157
|
+
_react.Children.forEach(child.props.children, grandChild => {
|
|
159
158
|
// currently we don't support node trees deeper than 2 levels
|
|
160
159
|
// truncation will still occur on their text content, but their actual node structure will be lost
|
|
161
160
|
if (grandChild.props) {
|
|
@@ -220,29 +219,31 @@ let TruncateText = exports.TruncateText = (_dec = (0, _emotion.withStyle)(_style
|
|
|
220
219
|
// this spacer element is set to the max width the full text could
|
|
221
220
|
// potentially be without this, text in `width: auto` elements won't expand
|
|
222
221
|
// to accommodate more text, once truncated
|
|
223
|
-
childElements.push((0,
|
|
222
|
+
childElements.push((0, _jsxRuntime.jsx)("span", {
|
|
224
223
|
css: (_this$props$styles2 = this.props.styles) === null || _this$props$styles2 === void 0 ? void 0 : _this$props$styles2.spacer,
|
|
225
224
|
style: {
|
|
226
225
|
width: width || void 0
|
|
227
226
|
}
|
|
228
227
|
}));
|
|
229
|
-
const children = _react.
|
|
228
|
+
const children = _react.Children.map(childElements, child => child);
|
|
230
229
|
return this._text.props ? (0, _safeCloneElement.safeCloneElement)(this._text, this._text.props, children) : children;
|
|
231
230
|
}
|
|
232
231
|
render() {
|
|
233
232
|
var _this$props$styles3;
|
|
234
233
|
const truncatedElement = this.state.truncatedElement;
|
|
235
234
|
const children = this.props.children;
|
|
236
|
-
return (0,
|
|
235
|
+
return (0, _jsxRuntime.jsxs)("span", {
|
|
237
236
|
css: (_this$props$styles3 = this.props.styles) === null || _this$props$styles3 === void 0 ? void 0 : _this$props$styles3.truncateText,
|
|
238
237
|
ref: el => {
|
|
239
238
|
this.ref = el;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
239
|
+
},
|
|
240
|
+
children: [children && (truncatedElement ? null : (0, _jsxRuntime.jsx)("span", {
|
|
241
|
+
ref: el => {
|
|
242
|
+
this._stage = el;
|
|
243
|
+
},
|
|
244
|
+
children: (0, _ensureSingleChild.ensureSingleChild)(children)
|
|
245
|
+
})), truncatedElement]
|
|
246
|
+
});
|
|
246
247
|
}
|
|
247
248
|
}, _TruncateText.displayName = "TruncateText", _TruncateText.componentId = 'TruncateText', _TruncateText.allowedProps = _props.allowedProps, _TruncateText.propTypes = _props.propTypes, _TruncateText.defaultProps = {
|
|
248
249
|
maxLines: 1,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
-
var _react =
|
|
5
|
-
var _react2 = require("@testing-library/react");
|
|
4
|
+
var _react = require("@testing-library/react");
|
|
6
5
|
var _vitest = require("vitest");
|
|
7
6
|
require("@testing-library/jest-dom");
|
|
8
7
|
var _measureText = _interopRequireDefault(require("../measureText"));
|
|
8
|
+
var _jsxRuntime = require("@emotion/react/jsx-runtime");
|
|
9
9
|
var _div, _div2, _div3, _div4;
|
|
10
10
|
/*
|
|
11
11
|
* The MIT License (MIT)
|
|
@@ -69,35 +69,40 @@ describe('measureText', () => {
|
|
|
69
69
|
(0, _vitest.expect)(width).toBe(0);
|
|
70
70
|
});
|
|
71
71
|
it('should calculate text width correctly', () => {
|
|
72
|
-
(0,
|
|
72
|
+
(0, _react.render)(_div || (_div = (0, _jsxRuntime.jsxs)("div", {
|
|
73
73
|
"data-testid": "stage",
|
|
74
|
-
style: baseStyle
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
style: baseStyle,
|
|
75
|
+
children: ["Lorem ipsum ", (0, _jsxRuntime.jsx)("span", {
|
|
76
|
+
style: baseStyle,
|
|
77
|
+
children: "DOLOR SIT AMET."
|
|
78
|
+
})]
|
|
79
|
+
})));
|
|
80
|
+
const stage = _react.screen.getByTestId('stage');
|
|
79
81
|
const nodes = getNodes(stage);
|
|
80
82
|
const width = (0, _measureText.default)(nodes, stage);
|
|
81
83
|
(0, _vitest.expect)(width).toBe(270);
|
|
82
84
|
});
|
|
83
85
|
it('should account for different nodes', async () => {
|
|
84
|
-
const _render = (0,
|
|
86
|
+
const _render = (0, _react.render)(_div2 || (_div2 = (0, _jsxRuntime.jsxs)("div", {
|
|
85
87
|
"data-testid": "stage",
|
|
86
|
-
style: baseStyle
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
style: baseStyle,
|
|
89
|
+
children: ["Lorem ipsum ", (0, _jsxRuntime.jsx)("span", {
|
|
90
|
+
style: baseStyle,
|
|
91
|
+
children: "DOLOR SIT AMET."
|
|
92
|
+
})]
|
|
93
|
+
}))),
|
|
90
94
|
rerender = _render.rerender;
|
|
91
|
-
const stage =
|
|
95
|
+
const stage = _react.screen.getByTestId('stage');
|
|
92
96
|
const nodes = getNodes(stage);
|
|
93
97
|
const width = (0, _measureText.default)(nodes, stage);
|
|
94
98
|
|
|
95
99
|
// Set child
|
|
96
|
-
rerender(_div3 || (_div3 =
|
|
100
|
+
rerender(_div3 || (_div3 = (0, _jsxRuntime.jsx)("div", {
|
|
97
101
|
"data-testid": "stage",
|
|
98
|
-
style: baseStyle
|
|
99
|
-
|
|
100
|
-
|
|
102
|
+
style: baseStyle,
|
|
103
|
+
children: "Lorem ipsum DOLOR SIT AMET."
|
|
104
|
+
})));
|
|
105
|
+
const stage2 = _react.screen.getByTestId('stage');
|
|
101
106
|
const nodes2 = getNodes(stage2);
|
|
102
107
|
const width2 = (0, _measureText.default)(nodes2, stage2);
|
|
103
108
|
(0, _vitest.expect)(width).toEqual(width2);
|
|
@@ -109,11 +114,12 @@ describe('measureText', () => {
|
|
|
109
114
|
fontStyle: 'italic',
|
|
110
115
|
fontFamily: 'Arial'
|
|
111
116
|
};
|
|
112
|
-
(0,
|
|
117
|
+
(0, _react.render)((0, _jsxRuntime.jsx)("div", {
|
|
113
118
|
"data-testid": "stage",
|
|
114
|
-
style: mockedStyle
|
|
115
|
-
|
|
116
|
-
|
|
119
|
+
style: mockedStyle,
|
|
120
|
+
children: "Lorem ipsum"
|
|
121
|
+
}));
|
|
122
|
+
const stage = _react.screen.getByTestId('stage');
|
|
117
123
|
const nodes = getNodes(stage);
|
|
118
124
|
(0, _measureText.default)(nodes, stage);
|
|
119
125
|
|
|
@@ -124,25 +130,27 @@ describe('measureText', () => {
|
|
|
124
130
|
(0, _vitest.expect)(context.font).toBe('bold italic 20px Arial');
|
|
125
131
|
});
|
|
126
132
|
it('should account for letter spacing styles', async () => {
|
|
127
|
-
const _render2 = (0,
|
|
133
|
+
const _render2 = (0, _react.render)(_div4 || (_div4 = (0, _jsxRuntime.jsx)("div", {
|
|
128
134
|
"data-testid": "stage",
|
|
129
|
-
style: baseStyle
|
|
130
|
-
|
|
135
|
+
style: baseStyle,
|
|
136
|
+
children: "Lorem ipsum"
|
|
137
|
+
}))),
|
|
131
138
|
rerender = _render2.rerender;
|
|
132
|
-
const stage =
|
|
139
|
+
const stage = _react.screen.getByTestId('stage');
|
|
133
140
|
const nodes = getNodes(stage);
|
|
134
141
|
const width = (0, _measureText.default)(nodes, stage);
|
|
135
142
|
(0, _vitest.expect)(width).toBe(110); // default mocked width (text.length * 10)
|
|
136
143
|
|
|
137
144
|
// Set letterSpacing
|
|
138
|
-
rerender(
|
|
145
|
+
rerender((0, _jsxRuntime.jsx)("div", {
|
|
139
146
|
"data-testid": "stage2",
|
|
140
147
|
style: {
|
|
141
148
|
...baseStyle,
|
|
142
149
|
letterSpacing: '5px'
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
|
|
150
|
+
},
|
|
151
|
+
children: "Lorem ipsum"
|
|
152
|
+
}));
|
|
153
|
+
const stage2 = _react.screen.getByTestId('stage2');
|
|
146
154
|
const nodes2 = getNodes(stage2);
|
|
147
155
|
const width2 = (0, _measureText.default)(nodes2, stage2);
|
|
148
156
|
(0, _vitest.expect)(width2).toBe(165); // default mocked width + letterOffset (text.length * letterSpacing)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instructure/ui-truncate-text",
|
|
3
|
-
"version": "10.16.1
|
|
3
|
+
"version": "10.16.1",
|
|
4
4
|
"description": "A TruncateText component made by Instructure Inc.",
|
|
5
5
|
"author": "Instructure, Inc. Engineering and Product Design",
|
|
6
6
|
"module": "./es/index.js",
|
|
@@ -24,24 +24,24 @@
|
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@babel/runtime": "^7.26.0",
|
|
27
|
-
"@instructure/console": "10.16.1
|
|
28
|
-
"@instructure/debounce": "10.16.1
|
|
29
|
-
"@instructure/emotion": "10.16.1
|
|
30
|
-
"@instructure/shared-types": "10.16.1
|
|
31
|
-
"@instructure/ui-dom-utils": "10.16.1
|
|
32
|
-
"@instructure/ui-react-utils": "10.16.1
|
|
33
|
-
"@instructure/ui-testable": "10.16.1
|
|
34
|
-
"@instructure/ui-utils": "10.16.1
|
|
27
|
+
"@instructure/console": "10.16.1",
|
|
28
|
+
"@instructure/debounce": "10.16.1",
|
|
29
|
+
"@instructure/emotion": "10.16.1",
|
|
30
|
+
"@instructure/shared-types": "10.16.1",
|
|
31
|
+
"@instructure/ui-dom-utils": "10.16.1",
|
|
32
|
+
"@instructure/ui-react-utils": "10.16.1",
|
|
33
|
+
"@instructure/ui-testable": "10.16.1",
|
|
34
|
+
"@instructure/ui-utils": "10.16.1",
|
|
35
35
|
"escape-html": "^1.0.3",
|
|
36
36
|
"prop-types": "^15.8.1"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@instructure/ui-axe-check": "10.16.1
|
|
40
|
-
"@instructure/ui-babel-preset": "10.16.1
|
|
41
|
-
"@instructure/ui-color-utils": "10.16.1
|
|
42
|
-
"@instructure/ui-test-utils": "10.16.1
|
|
43
|
-
"@instructure/ui-text": "10.16.1
|
|
44
|
-
"@instructure/ui-themes": "10.16.1
|
|
39
|
+
"@instructure/ui-axe-check": "10.16.1",
|
|
40
|
+
"@instructure/ui-babel-preset": "10.16.1",
|
|
41
|
+
"@instructure/ui-color-utils": "10.16.1",
|
|
42
|
+
"@instructure/ui-test-utils": "10.16.1",
|
|
43
|
+
"@instructure/ui-text": "10.16.1",
|
|
44
|
+
"@instructure/ui-themes": "10.16.1",
|
|
45
45
|
"@testing-library/jest-dom": "^6.6.3",
|
|
46
46
|
"@testing-library/react": "^16.0.1",
|
|
47
47
|
"@types/escape-html": "^1.0.4",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
22
|
* SOFTWARE.
|
|
23
23
|
*/
|
|
24
|
-
|
|
25
|
-
import
|
|
24
|
+
|
|
25
|
+
import { Children, Component } from 'react'
|
|
26
26
|
|
|
27
27
|
import { debounce } from '@instructure/debounce'
|
|
28
28
|
import type { Debounced } from '@instructure/debounce'
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
} from '@instructure/ui-react-utils'
|
|
35
35
|
import { logError as error } from '@instructure/console'
|
|
36
36
|
import { testable } from '@instructure/ui-testable'
|
|
37
|
-
import { withStyle
|
|
37
|
+
import { withStyle } from '@instructure/emotion'
|
|
38
38
|
|
|
39
39
|
import generateStyle from './styles'
|
|
40
40
|
import generateComponentTheme from './theme'
|
|
@@ -176,9 +176,9 @@ class TruncateText extends Component<TruncateTextProps, TruncateTextState> {
|
|
|
176
176
|
!(() => {
|
|
177
177
|
let isTooDeep = false
|
|
178
178
|
const text = ensureSingleChild(this.props.children)!
|
|
179
|
-
|
|
179
|
+
Children.forEach(text.props.children, (child) => {
|
|
180
180
|
if (child.props) {
|
|
181
|
-
|
|
181
|
+
Children.forEach(child.props.children, (grandChild) => {
|
|
182
182
|
// currently we don't support node trees deeper than 2 levels
|
|
183
183
|
// truncation will still occur on their text content, but their actual node structure will be lost
|
|
184
184
|
if (grandChild.props) {
|
|
@@ -266,7 +266,7 @@ class TruncateText extends Component<TruncateTextProps, TruncateTextState> {
|
|
|
266
266
|
/>
|
|
267
267
|
)
|
|
268
268
|
|
|
269
|
-
const children =
|
|
269
|
+
const children = Children.map(childElements, (child) => child)
|
|
270
270
|
return this._text!.props
|
|
271
271
|
? safeCloneElement(this._text!, this._text!.props, children)
|
|
272
272
|
: children
|