react-show-more-text 1.6.2 → 1.7.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/README.md +3 -3
- package/lib/ShowMoreText.js +77 -103
- package/lib/Truncate.js +216 -203
- package/package.json +2 -3
- package/lib/ShowMoreText.css +0 -8
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# React Show More Text 1.
|
|
1
|
+
# React Show More Text 1.7.1
|
|
2
2
|
|
|
3
3
|
[![NPM version][npm-image]][npm-url]
|
|
4
4
|
[![Downloads][downloads-image]][npm-url]
|
|
5
5
|
[![Build status][travis-image]][travis-url]
|
|
6
6
|
|
|
7
|
-
The text surrounded by the component will be truncated. Anything surrounded by the component could be evaluated as text. The component react-show-more-text/ShowMoreText is fork of react-show-more/ShowMore, applied improvements, works with React 16.x.x, React 18.x.x
|
|
7
|
+
The text surrounded by the component will be truncated. Anything surrounded by the component could be evaluated as text. The component react-show-more-text/ShowMoreText is fork of react-show-more/ShowMore, applied improvements, added onClick event, works with React 16.x.x, React 18.x.x, Next.Js 13.3.x and upper.
|
|
8
8
|
|
|
9
9
|
## Demo
|
|
10
10
|
|
|
@@ -83,7 +83,7 @@ class Foo extends Component {
|
|
|
83
83
|
| more | string, React node | 'Show more' | The text to display in the anchor element to show more. | `'Show more'`, `<span>Show more</span>` |
|
|
84
84
|
| less | string, React node | 'Show less' | The text to display in the anchor element to show less. | `'Show less'`, `<span>Show less</span>` |
|
|
85
85
|
| className | string | '' | Class name(s) to add on component content wrapper div. | `'wrapper-class'`, `'wrapper-class-1 wrapper-class-2'` |
|
|
86
|
-
| anchorClass | string | '' | Class name(s) to add to the anchor elements. | `'my-anchor-class'`, `'class-1 class-2'` |
|
|
86
|
+
| anchorClass | string | 'show-more-less-clickable' | Class name(s) to add to the anchor elements. Should be the name of a css class defined globally by you. | `'my-anchor-class'`, `'class-1 class-2'` |
|
|
87
87
|
| onClick | Function | | Function executed on click on 'Show more' or 'Show less' | `onClick={this.executeOnClick}` |
|
|
88
88
|
| expanded | boolean | 'false' | Control the text to be shown as expanded | `expanded={true}` |
|
|
89
89
|
| expandByClick | boolean | 'true' | Cancel the default anchor click expand behavior | `expandByClick={false}` |
|
package/lib/ShowMoreText.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
4
3
|
Object.defineProperty(exports, "__esModule", {
|
|
5
4
|
value: true
|
|
6
5
|
});
|
|
@@ -8,141 +7,116 @@ exports.default = void 0;
|
|
|
8
7
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
8
|
var _propTypes = require("prop-types");
|
|
10
9
|
var _Truncate = _interopRequireDefault(require("./Truncate"));
|
|
11
|
-
require("./ShowMoreText.css");
|
|
12
10
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
-
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function
|
|
14
|
-
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null ||
|
|
15
|
-
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
16
|
-
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
17
|
-
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
18
|
-
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
|
|
19
|
-
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
|
|
20
|
-
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
|
|
21
|
-
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
|
|
22
|
-
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
|
|
23
|
-
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
|
|
24
|
-
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
|
11
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
12
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
25
13
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
_defineProperty(_assertThisInitialized(_this), "handleTruncate", function (truncated) {
|
|
35
|
-
if (_this._isMounted && truncated !== _this.state.truncated) {
|
|
36
|
-
_this.setState({
|
|
37
|
-
truncated: truncated
|
|
14
|
+
class ShowMoreText extends _react.Component {
|
|
15
|
+
constructor(props) {
|
|
16
|
+
super(props);
|
|
17
|
+
_defineProperty(this, "_isMounted", false);
|
|
18
|
+
_defineProperty(this, "handleTruncate", truncated => {
|
|
19
|
+
if (this._isMounted && truncated !== this.state.truncated) {
|
|
20
|
+
this.setState({
|
|
21
|
+
truncated
|
|
38
22
|
});
|
|
39
23
|
if (truncated) {
|
|
40
|
-
|
|
24
|
+
this.truncateRef.onResize();
|
|
41
25
|
}
|
|
42
|
-
|
|
26
|
+
this.props.onTruncate && this.props.onTruncate();
|
|
43
27
|
}
|
|
44
28
|
});
|
|
45
|
-
_defineProperty(
|
|
29
|
+
_defineProperty(this, "toggleLines", event => {
|
|
46
30
|
event.preventDefault();
|
|
47
|
-
var _self =
|
|
31
|
+
var _self = this;
|
|
48
32
|
if (!_self.props.expandByClick) {
|
|
49
33
|
if (_self.props.onClick) {
|
|
50
34
|
_self.props.onClick(_self.state.expanded, event);
|
|
51
35
|
}
|
|
52
36
|
return;
|
|
53
37
|
}
|
|
54
|
-
if (
|
|
55
|
-
|
|
56
|
-
expanded: !
|
|
57
|
-
},
|
|
38
|
+
if (this._isMounted) {
|
|
39
|
+
this.setState({
|
|
40
|
+
expanded: !this.state.expanded
|
|
41
|
+
}, () => {
|
|
58
42
|
if (_self.props.onClick) {
|
|
59
43
|
_self.props.onClick(_self.state.expanded, event);
|
|
60
44
|
}
|
|
61
45
|
});
|
|
62
46
|
}
|
|
63
47
|
});
|
|
64
|
-
|
|
48
|
+
this.state = {
|
|
65
49
|
expanded: false,
|
|
66
50
|
truncated: false
|
|
67
51
|
};
|
|
68
|
-
return _this;
|
|
69
52
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
expanded: _self.props.expanded
|
|
78
|
-
});
|
|
79
|
-
}
|
|
53
|
+
componentDidMount() {
|
|
54
|
+
this._isMounted = true;
|
|
55
|
+
var _self = this;
|
|
56
|
+
if (this._isMounted) {
|
|
57
|
+
this.setState({
|
|
58
|
+
expanded: _self.props.expanded
|
|
59
|
+
});
|
|
80
60
|
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
lines: !expanded && lines,
|
|
109
|
-
ellipsis: /*#__PURE__*/_react.default.createElement("span", null, truncatedEndingComponent, /*#__PURE__*/_react.default.createElement("span", {
|
|
110
|
-
className: anchorClass,
|
|
111
|
-
onClick: this.toggleLines
|
|
112
|
-
}, more)),
|
|
113
|
-
onTruncate: this.handleTruncate,
|
|
114
|
-
ref: function ref(_ref) {
|
|
115
|
-
return _this2.truncateRef = _ref;
|
|
116
|
-
}
|
|
117
|
-
}, keepNewLines ? children.split('\n').map(function (line, i, arr) {
|
|
118
|
-
line = /*#__PURE__*/_react.default.createElement("span", {
|
|
119
|
-
key: i
|
|
120
|
-
}, line);
|
|
121
|
-
if (i === arr.length - 1) {
|
|
122
|
-
return line;
|
|
123
|
-
} else {
|
|
124
|
-
return [line, /*#__PURE__*/_react.default.createElement("br", {
|
|
125
|
-
key: i + 'br'
|
|
126
|
-
})];
|
|
127
|
-
}
|
|
128
|
-
}) : children), !truncated && expanded && /*#__PURE__*/_react.default.createElement("span", null, ' ', /*#__PURE__*/_react.default.createElement("span", {
|
|
61
|
+
}
|
|
62
|
+
componentWillUnmount() {
|
|
63
|
+
this._isMounted = false;
|
|
64
|
+
}
|
|
65
|
+
render() {
|
|
66
|
+
const {
|
|
67
|
+
children,
|
|
68
|
+
more,
|
|
69
|
+
less,
|
|
70
|
+
lines,
|
|
71
|
+
anchorClass,
|
|
72
|
+
className,
|
|
73
|
+
width,
|
|
74
|
+
keepNewLines,
|
|
75
|
+
truncatedEndingComponent,
|
|
76
|
+
onTruncate
|
|
77
|
+
} = this.props;
|
|
78
|
+
const {
|
|
79
|
+
expanded,
|
|
80
|
+
truncated
|
|
81
|
+
} = this.state;
|
|
82
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
|
83
|
+
className: className
|
|
84
|
+
}, /*#__PURE__*/_react.default.createElement(_Truncate.default, {
|
|
85
|
+
width: width,
|
|
86
|
+
lines: !expanded && lines,
|
|
87
|
+
ellipsis: /*#__PURE__*/_react.default.createElement("span", null, truncatedEndingComponent, /*#__PURE__*/_react.default.createElement("span", {
|
|
129
88
|
className: anchorClass,
|
|
130
89
|
onClick: this.toggleLines
|
|
131
|
-
},
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
90
|
+
}, more)),
|
|
91
|
+
onTruncate: this.handleTruncate,
|
|
92
|
+
ref: ref => this.truncateRef = ref
|
|
93
|
+
}, keepNewLines ? children.split("\n").map((line, i, arr) => {
|
|
94
|
+
line = /*#__PURE__*/_react.default.createElement("span", {
|
|
95
|
+
key: i
|
|
96
|
+
}, line);
|
|
97
|
+
if (i === arr.length - 1) {
|
|
98
|
+
return line;
|
|
99
|
+
} else {
|
|
100
|
+
return [line, /*#__PURE__*/_react.default.createElement("br", {
|
|
101
|
+
key: i + "br"
|
|
102
|
+
})];
|
|
103
|
+
}
|
|
104
|
+
}) : children), !truncated && expanded && /*#__PURE__*/_react.default.createElement("span", null, " ", /*#__PURE__*/_react.default.createElement("span", {
|
|
105
|
+
className: anchorClass,
|
|
106
|
+
onClick: this.toggleLines
|
|
107
|
+
}, less)));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
136
110
|
_defineProperty(ShowMoreText, "defaultProps", {
|
|
137
111
|
lines: 3,
|
|
138
|
-
more:
|
|
139
|
-
less:
|
|
140
|
-
anchorClass:
|
|
112
|
+
more: "Show more",
|
|
113
|
+
less: "Show less",
|
|
114
|
+
anchorClass: "show-more-less-clickable",
|
|
141
115
|
onClick: undefined,
|
|
142
116
|
expanded: false,
|
|
143
117
|
width: 0,
|
|
144
118
|
keepNewLines: false,
|
|
145
|
-
truncatedEndingComponent:
|
|
119
|
+
truncatedEndingComponent: "... ",
|
|
146
120
|
expandByClick: true,
|
|
147
121
|
onTruncate: undefined
|
|
148
122
|
});
|
package/lib/Truncate.js
CHANGED
|
@@ -1,150 +1,154 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
4
3
|
Object.defineProperty(exports, "__esModule", {
|
|
5
4
|
value: true
|
|
6
5
|
});
|
|
7
6
|
exports.default = void 0;
|
|
8
7
|
var _react = _interopRequireDefault(require("react"));
|
|
9
8
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
10
|
-
var _excluded = ["children", "ellipsis", "lines"];
|
|
11
9
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
12
10
|
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
13
|
-
function
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
11
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } /**
|
|
12
|
+
* LICENSE
|
|
13
|
+
* https://github.com/pablosichert/react-truncate/blob/master/LICENSE.md
|
|
14
|
+
*
|
|
15
|
+
* ISC License
|
|
16
|
+
Copyright (c) 2016, One.com
|
|
17
|
+
|
|
18
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is
|
|
19
|
+
hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
|
|
22
|
+
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE
|
|
23
|
+
FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
24
|
+
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
25
|
+
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
26
|
+
*/ // Initial version of react-truncate module (v2.4.0)
|
|
27
|
+
class Truncate extends _react.default.Component {
|
|
28
|
+
constructor() {
|
|
31
29
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
32
30
|
args[_key] = arguments[_key];
|
|
33
31
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
_defineProperty(
|
|
37
|
-
|
|
38
|
-
var _self = _assertThisInitialized(_this),
|
|
32
|
+
super(...args);
|
|
33
|
+
_defineProperty(this, "state", {});
|
|
34
|
+
_defineProperty(this, "extractReplaceLinksKeys", content => {
|
|
35
|
+
var _self = this,
|
|
39
36
|
i = 0;
|
|
40
|
-
|
|
37
|
+
this.replacedLinks = [];
|
|
41
38
|
content.replace(/(<a[\s]+([^>]+)>((?:.(?!\<\/a\>))*.)<\/a>)/g, function () {
|
|
42
|
-
|
|
43
|
-
item.key =
|
|
39
|
+
const item = Array.prototype.slice.call(arguments, 1, 4);
|
|
40
|
+
item.key = "[" + "@".repeat(item[2].length - 1) + "=" + i++ + "]";
|
|
44
41
|
_self.replacedLinks.push(item);
|
|
45
42
|
content = content.replace(item[0], item.key);
|
|
46
43
|
});
|
|
47
44
|
return content;
|
|
48
45
|
});
|
|
49
|
-
_defineProperty(
|
|
50
|
-
|
|
46
|
+
_defineProperty(this, "restoreReplacedLinks", content => {
|
|
47
|
+
this.replacedLinks.forEach(item => {
|
|
51
48
|
content = content.replace(item.key, item[0]);
|
|
52
49
|
});
|
|
53
|
-
return
|
|
50
|
+
return this.createMarkup(content);
|
|
54
51
|
});
|
|
55
|
-
_defineProperty(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
div.innerHTML =
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
test.innerHTML =
|
|
63
|
-
if (test[contentKey].replace(/\r\n|\r/g,
|
|
64
|
-
div.innerHTML = div.innerHTML.replace(/<br.*?[\/]?>/gi,
|
|
52
|
+
_defineProperty(this, "innerText", node => {
|
|
53
|
+
const div = document.createElement("div");
|
|
54
|
+
const contentKey = "innerText" in window.HTMLElement.prototype ? "innerText" : "textContent";
|
|
55
|
+
const content = node.innerHTML.replace(/\r\n|\r|\n/g, " ");
|
|
56
|
+
div.innerHTML = this.extractReplaceLinksKeys(content);
|
|
57
|
+
let text = div[contentKey];
|
|
58
|
+
const test = document.createElement("div");
|
|
59
|
+
test.innerHTML = "foo<br/>bar";
|
|
60
|
+
if (test[contentKey].replace(/\r\n|\r/g, "\n") !== "foo\nbar") {
|
|
61
|
+
div.innerHTML = div.innerHTML.replace(/<br.*?[\/]?>/gi, "\n");
|
|
65
62
|
text = div[contentKey];
|
|
66
63
|
}
|
|
67
64
|
return text;
|
|
68
65
|
});
|
|
69
|
-
_defineProperty(
|
|
70
|
-
|
|
66
|
+
_defineProperty(this, "onResize", () => {
|
|
67
|
+
this.calcTargetWidth();
|
|
71
68
|
});
|
|
72
|
-
_defineProperty(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
69
|
+
_defineProperty(this, "onTruncate", didTruncate => {
|
|
70
|
+
const {
|
|
71
|
+
onTruncate
|
|
72
|
+
} = this.props;
|
|
73
|
+
if (typeof onTruncate === "function") {
|
|
74
|
+
this.timeout = window.requestAnimationFrame(() => {
|
|
76
75
|
onTruncate(didTruncate);
|
|
77
76
|
});
|
|
78
77
|
}
|
|
79
78
|
});
|
|
80
|
-
_defineProperty(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
79
|
+
_defineProperty(this, "calcTargetWidth", callback => {
|
|
80
|
+
const {
|
|
81
|
+
elements: {
|
|
82
|
+
target
|
|
83
|
+
},
|
|
84
|
+
calcTargetWidth,
|
|
85
|
+
canvasContext,
|
|
86
|
+
props: {
|
|
87
|
+
width
|
|
88
|
+
}
|
|
89
|
+
} = this;
|
|
86
90
|
|
|
87
91
|
// Calculation is no longer relevant, since node has been removed
|
|
88
92
|
if (!target) {
|
|
89
93
|
return;
|
|
90
94
|
}
|
|
91
|
-
|
|
95
|
+
const targetWidth = width ||
|
|
92
96
|
// Floor the result to deal with browser subpixel precision
|
|
93
97
|
Math.floor(target.parentNode.getBoundingClientRect().width);
|
|
94
98
|
|
|
95
99
|
// Delay calculation until parent node is inserted to the document
|
|
96
100
|
// Mounting order in React is ChildComponent, ParentComponent
|
|
97
101
|
if (!targetWidth) {
|
|
98
|
-
return window.requestAnimationFrame(
|
|
99
|
-
return calcTargetWidth(callback);
|
|
100
|
-
});
|
|
102
|
+
return window.requestAnimationFrame(() => calcTargetWidth(callback));
|
|
101
103
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
+
const style = window.getComputedStyle(target);
|
|
105
|
+
const font = [style["font-weight"], style["font-style"], style["font-size"], style["font-family"]].join(" ");
|
|
104
106
|
canvasContext.font = font;
|
|
105
|
-
|
|
106
|
-
targetWidth
|
|
107
|
+
this.setState({
|
|
108
|
+
targetWidth
|
|
107
109
|
}, callback);
|
|
108
110
|
});
|
|
109
|
-
_defineProperty(
|
|
110
|
-
return
|
|
111
|
+
_defineProperty(this, "measureWidth", text => {
|
|
112
|
+
return this.canvasContext.measureText(text).width;
|
|
111
113
|
});
|
|
112
|
-
_defineProperty(
|
|
114
|
+
_defineProperty(this, "ellipsisWidth", node => {
|
|
113
115
|
return node.offsetWidth;
|
|
114
116
|
});
|
|
115
|
-
_defineProperty(
|
|
116
|
-
return text.replace(/\s+$/,
|
|
117
|
+
_defineProperty(this, "trimRight", text => {
|
|
118
|
+
return text.replace(/\s+$/, "");
|
|
117
119
|
});
|
|
118
|
-
_defineProperty(
|
|
120
|
+
_defineProperty(this, "createMarkup", str => {
|
|
119
121
|
return /*#__PURE__*/_react.default.createElement("span", {
|
|
120
122
|
dangerouslySetInnerHTML: {
|
|
121
123
|
__html: str
|
|
122
124
|
}
|
|
123
125
|
});
|
|
124
126
|
});
|
|
125
|
-
_defineProperty(
|
|
126
|
-
|
|
127
|
-
elements
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
127
|
+
_defineProperty(this, "getLines", () => {
|
|
128
|
+
const {
|
|
129
|
+
elements,
|
|
130
|
+
props: {
|
|
131
|
+
lines: numLines,
|
|
132
|
+
ellipsis,
|
|
133
|
+
trimWhitespace
|
|
134
|
+
},
|
|
135
|
+
state: {
|
|
136
|
+
targetWidth
|
|
137
|
+
},
|
|
138
|
+
innerText,
|
|
139
|
+
measureWidth,
|
|
140
|
+
onTruncate,
|
|
141
|
+
trimRight,
|
|
142
|
+
renderLine,
|
|
143
|
+
restoreReplacedLinks
|
|
144
|
+
} = this;
|
|
145
|
+
const lines = [];
|
|
146
|
+
const text = innerText(elements.text);
|
|
147
|
+
const textLines = text.split("\n").map(line => line.split(" "));
|
|
148
|
+
let didTruncate = true;
|
|
149
|
+
const ellipsisWidth = this.ellipsisWidth(this.elements.ellipsis);
|
|
150
|
+
for (let line = 1; line <= numLines; line++) {
|
|
151
|
+
const textWords = textLines[0];
|
|
148
152
|
|
|
149
153
|
// Handle newline
|
|
150
154
|
if (textWords.length === 0) {
|
|
@@ -153,7 +157,7 @@ var Truncate = /*#__PURE__*/function (_React$Component) {
|
|
|
153
157
|
line--;
|
|
154
158
|
continue;
|
|
155
159
|
}
|
|
156
|
-
|
|
160
|
+
let resultLine = textWords.join(" ");
|
|
157
161
|
if (measureWidth(resultLine) <= targetWidth) {
|
|
158
162
|
if (textLines.length === 1) {
|
|
159
163
|
// Line is end of text and fits without truncating
|
|
@@ -165,72 +169,71 @@ var Truncate = /*#__PURE__*/function (_React$Component) {
|
|
|
165
169
|
}
|
|
166
170
|
if (line === numLines) {
|
|
167
171
|
// Binary search determining the longest possible line inluding truncate string
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
172
|
+
const textRest = textWords.join(" ");
|
|
173
|
+
let lower = 0;
|
|
174
|
+
let upper = textRest.length - 1;
|
|
171
175
|
while (lower <= upper) {
|
|
172
|
-
|
|
173
|
-
|
|
176
|
+
const middle = Math.floor((lower + upper) / 2);
|
|
177
|
+
const testLine = textRest.slice(0, middle + 1);
|
|
174
178
|
if (measureWidth(testLine) + ellipsisWidth <= targetWidth) {
|
|
175
179
|
lower = middle + 1;
|
|
176
180
|
} else {
|
|
177
181
|
upper = middle - 1;
|
|
178
182
|
}
|
|
179
183
|
}
|
|
180
|
-
|
|
184
|
+
let lastLineText = textRest.slice(0, lower);
|
|
181
185
|
if (trimWhitespace) {
|
|
182
186
|
lastLineText = trimRight(lastLineText);
|
|
183
187
|
|
|
184
188
|
// Remove blank lines from the end of text
|
|
185
189
|
while (!lastLineText.length && lines.length) {
|
|
186
|
-
|
|
190
|
+
const prevLine = lines.pop();
|
|
187
191
|
lastLineText = trimRight(prevLine);
|
|
188
192
|
}
|
|
189
193
|
}
|
|
190
|
-
if (lastLineText.substr(lastLineText.length - 2) ===
|
|
194
|
+
if (lastLineText.substr(lastLineText.length - 2) === "][") {
|
|
191
195
|
lastLineText = lastLineText.substring(0, lastLineText.length - 1);
|
|
192
196
|
}
|
|
193
|
-
;
|
|
194
|
-
lastLineText = lastLineText.replace(/\[@+$/, '');
|
|
197
|
+
lastLineText = lastLineText.replace(/\[@+$/, "");
|
|
195
198
|
lastLineText = restoreReplacedLinks(lastLineText);
|
|
196
199
|
resultLine = /*#__PURE__*/_react.default.createElement("span", null, lastLineText, ellipsis);
|
|
197
200
|
} else {
|
|
198
201
|
// Binary search determining when the line breaks
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
while (
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if (measureWidth(
|
|
205
|
-
|
|
202
|
+
let lower = 0;
|
|
203
|
+
let upper = textWords.length - 1;
|
|
204
|
+
while (lower <= upper) {
|
|
205
|
+
const middle = Math.floor((lower + upper) / 2);
|
|
206
|
+
const testLine = textWords.slice(0, middle + 1).join(" ");
|
|
207
|
+
if (measureWidth(testLine) <= targetWidth) {
|
|
208
|
+
lower = middle + 1;
|
|
206
209
|
} else {
|
|
207
|
-
|
|
210
|
+
upper = middle - 1;
|
|
208
211
|
}
|
|
209
212
|
}
|
|
210
213
|
|
|
211
214
|
// The first word of this line is too long to fit it
|
|
212
|
-
if (
|
|
215
|
+
if (lower === 0) {
|
|
213
216
|
// Jump to processing of last line
|
|
214
217
|
line = numLines - 1;
|
|
215
218
|
continue;
|
|
216
219
|
}
|
|
217
|
-
resultLine = textWords.slice(0,
|
|
220
|
+
resultLine = textWords.slice(0, lower).join(" ");
|
|
218
221
|
resultLine = restoreReplacedLinks(resultLine);
|
|
219
|
-
textLines[0].splice(0,
|
|
222
|
+
textLines[0].splice(0, lower);
|
|
220
223
|
}
|
|
221
224
|
lines.push(resultLine);
|
|
222
225
|
}
|
|
223
226
|
onTruncate(didTruncate);
|
|
224
227
|
return lines.map(renderLine);
|
|
225
228
|
});
|
|
226
|
-
_defineProperty(
|
|
229
|
+
_defineProperty(this, "renderLine", (line, i, arr) => {
|
|
227
230
|
if (i === arr.length - 1) {
|
|
228
231
|
return /*#__PURE__*/_react.default.createElement("span", {
|
|
229
232
|
key: i
|
|
230
233
|
}, line);
|
|
231
234
|
} else {
|
|
232
|
-
|
|
233
|
-
key: i +
|
|
235
|
+
const br = /*#__PURE__*/_react.default.createElement("br", {
|
|
236
|
+
key: i + "br"
|
|
234
237
|
});
|
|
235
238
|
if (line) {
|
|
236
239
|
return [/*#__PURE__*/_react.default.createElement("span", {
|
|
@@ -241,102 +244,113 @@ var Truncate = /*#__PURE__*/function (_React$Component) {
|
|
|
241
244
|
}
|
|
242
245
|
}
|
|
243
246
|
});
|
|
244
|
-
_defineProperty(
|
|
247
|
+
_defineProperty(this, "styles", {
|
|
245
248
|
ellipsis: {
|
|
246
|
-
position:
|
|
247
|
-
visibility:
|
|
249
|
+
position: "fixed",
|
|
250
|
+
visibility: "hidden",
|
|
248
251
|
top: 0,
|
|
249
252
|
left: 0
|
|
250
253
|
}
|
|
251
254
|
});
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
return _this;
|
|
255
|
+
this.elements = {};
|
|
256
|
+
this.replacedLinks = [];
|
|
255
257
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
window.addEventListener('resize', onResize);
|
|
271
|
-
}
|
|
272
|
-
}, {
|
|
273
|
-
key: "componentDidUpdate",
|
|
274
|
-
value: function componentDidUpdate(prevProps) {
|
|
275
|
-
// Render was based on outdated refs and needs to be rerun
|
|
276
|
-
if (this.props.children !== prevProps.children) {
|
|
277
|
-
this.forceUpdate();
|
|
258
|
+
componentDidMount() {
|
|
259
|
+
const {
|
|
260
|
+
elements: {
|
|
261
|
+
text
|
|
262
|
+
},
|
|
263
|
+
calcTargetWidth,
|
|
264
|
+
onResize
|
|
265
|
+
} = this;
|
|
266
|
+
const canvas = document.createElement("canvas");
|
|
267
|
+
this.canvasContext = canvas.getContext("2d");
|
|
268
|
+
calcTargetWidth(() => {
|
|
269
|
+
// Node not needed in document tree to read its content
|
|
270
|
+
if (text && text.parentNode) {
|
|
271
|
+
text.parentNode.removeChild(text);
|
|
278
272
|
}
|
|
273
|
+
});
|
|
274
|
+
window.addEventListener("resize", onResize);
|
|
275
|
+
}
|
|
276
|
+
componentDidUpdate(prevProps) {
|
|
277
|
+
// Render was based on outdated refs and needs to be rerun
|
|
278
|
+
if (this.props.children !== prevProps.children) {
|
|
279
|
+
this.forceUpdate();
|
|
280
|
+
}
|
|
279
281
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
}
|
|
282
|
+
// If the width prop has changed, recalculate size of contents
|
|
283
|
+
if (this.props.width !== prevProps.width) {
|
|
284
|
+
this.calcTargetWidth();
|
|
284
285
|
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
286
|
+
}
|
|
287
|
+
componentWillUnmount() {
|
|
288
|
+
const {
|
|
289
|
+
elements: {
|
|
290
|
+
ellipsis
|
|
291
|
+
},
|
|
292
|
+
onResize,
|
|
293
|
+
timeout
|
|
294
|
+
} = this;
|
|
295
|
+
if (ellipsis.parentNode) {
|
|
296
|
+
ellipsis.parentNode.removeChild(ellipsis);
|
|
296
297
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
298
|
+
window.removeEventListener("resize", onResize);
|
|
299
|
+
window.cancelAnimationFrame(timeout);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Shim innerText to consistently break lines at <br/> but not at \n
|
|
303
|
+
|
|
304
|
+
render() {
|
|
305
|
+
const {
|
|
306
|
+
elements: {
|
|
307
|
+
target
|
|
308
|
+
},
|
|
309
|
+
props: {
|
|
310
|
+
children,
|
|
311
|
+
ellipsis,
|
|
312
|
+
lines,
|
|
313
|
+
...spanProps
|
|
314
|
+
},
|
|
315
|
+
state: {
|
|
316
|
+
targetWidth
|
|
317
|
+
},
|
|
318
|
+
getLines,
|
|
319
|
+
onTruncate
|
|
320
|
+
} = this;
|
|
321
|
+
let text;
|
|
322
|
+
const mounted = !!(target && targetWidth);
|
|
323
|
+
if (typeof window !== "undefined" && mounted) {
|
|
324
|
+
if (lines > 0) {
|
|
325
|
+
text = getLines();
|
|
326
|
+
} else {
|
|
327
|
+
text = children;
|
|
328
|
+
onTruncate(false);
|
|
319
329
|
}
|
|
320
|
-
delete spanProps.onTruncate;
|
|
321
|
-
delete spanProps.trimWhitespace;
|
|
322
|
-
return /*#__PURE__*/_react.default.createElement("span", _extends({}, spanProps, {
|
|
323
|
-
ref: function ref(targetEl) {
|
|
324
|
-
_this2.elements.target = targetEl;
|
|
325
|
-
}
|
|
326
|
-
}), /*#__PURE__*/_react.default.createElement("span", null, text), /*#__PURE__*/_react.default.createElement("span", {
|
|
327
|
-
ref: function ref(textEl) {
|
|
328
|
-
_this2.elements.text = textEl;
|
|
329
|
-
}
|
|
330
|
-
}, children), /*#__PURE__*/_react.default.createElement("span", {
|
|
331
|
-
ref: function ref(ellipsisEl) {
|
|
332
|
-
_this2.elements.ellipsis = ellipsisEl;
|
|
333
|
-
},
|
|
334
|
-
style: this.styles.ellipsis
|
|
335
|
-
}, ellipsis));
|
|
336
330
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
331
|
+
delete spanProps.onTruncate;
|
|
332
|
+
delete spanProps.trimWhitespace;
|
|
333
|
+
return /*#__PURE__*/_react.default.createElement("span", _extends({}, spanProps, {
|
|
334
|
+
ref: targetEl => {
|
|
335
|
+
this.elements.target = targetEl;
|
|
336
|
+
}
|
|
337
|
+
}), /*#__PURE__*/_react.default.createElement("span", {
|
|
338
|
+
style: {
|
|
339
|
+
display: "block",
|
|
340
|
+
maxWidth: spanProps.width > 0 ? "".concat(spanProps.width, "px") : "unset"
|
|
341
|
+
}
|
|
342
|
+
}, text), /*#__PURE__*/_react.default.createElement("span", {
|
|
343
|
+
ref: textEl => {
|
|
344
|
+
this.elements.text = textEl;
|
|
345
|
+
}
|
|
346
|
+
}, children), /*#__PURE__*/_react.default.createElement("span", {
|
|
347
|
+
ref: ellipsisEl => {
|
|
348
|
+
this.elements.ellipsis = ellipsisEl;
|
|
349
|
+
},
|
|
350
|
+
style: this.styles.ellipsis
|
|
351
|
+
}, ellipsis));
|
|
352
|
+
}
|
|
353
|
+
}
|
|
340
354
|
exports.default = Truncate;
|
|
341
355
|
_defineProperty(Truncate, "propTypes", {
|
|
342
356
|
children: _propTypes.default.node,
|
|
@@ -347,10 +361,9 @@ _defineProperty(Truncate, "propTypes", {
|
|
|
347
361
|
onTruncate: _propTypes.default.func
|
|
348
362
|
});
|
|
349
363
|
_defineProperty(Truncate, "defaultProps", {
|
|
350
|
-
children:
|
|
351
|
-
ellipsis:
|
|
364
|
+
children: "",
|
|
365
|
+
ellipsis: "…",
|
|
352
366
|
lines: 1,
|
|
353
367
|
trimWhitespace: false,
|
|
354
368
|
width: 0
|
|
355
|
-
});
|
|
356
|
-
;
|
|
369
|
+
});
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-show-more-text",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "The text surrounded by the component will be truncated. Anything surrounded by the component could be evaluated as text. The component react-show-more-text/ShowMoreText is fork of react-show-more/ShowMore, applied improvements, works with React 16.x.x, added onClick event.",
|
|
5
5
|
"main": "lib/ShowMoreText.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"lib"
|
|
8
8
|
],
|
|
9
9
|
"scripts": {
|
|
10
|
-
"compile": "./node_modules/.bin/babel src/ShowMoreText.js src/Truncate.js --out-dir lib
|
|
10
|
+
"compile": "./node_modules/.bin/babel src/ShowMoreText.js src/Truncate.js --out-dir lib",
|
|
11
11
|
"compile:watch": "onchange \"src/**/*.js\" -- npm run compile --silent --source-maps",
|
|
12
12
|
"coverage": "nyc npm test && nyc report --reporter=text-lcov",
|
|
13
13
|
"lint": "eslint .",
|
|
@@ -83,7 +83,6 @@
|
|
|
83
83
|
"react-dom": "^16.14.0"
|
|
84
84
|
},
|
|
85
85
|
"dependencies": {
|
|
86
|
-
"@babel/polyfill": "^7.12.1",
|
|
87
86
|
"prop-types": "^15.7.2"
|
|
88
87
|
},
|
|
89
88
|
"browserslist": "> 0.25%, not dead"
|