react-textarea-with-suggest 1.1.2 → 2.0.0
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 +5 -3
- package/example/README.md +20 -0
- package/example/package.json +37 -0
- package/example/public/index.html +43 -0
- package/example/src/App.css +15 -0
- package/example/src/App.js +74 -0
- package/example/src/index.js +10 -0
- package/lib/index.d.ts +24 -0
- package/lib/index.js +2 -273
- package/lib/index.js.map +1 -0
- package/lib/styles.css +39 -0
- package/lib/utils.d.ts +3 -0
- package/package.json +36 -15
- package/src/index.js +0 -213
- package/styles.css +0 -29
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# react-textarea-with-suggest
|
|
2
|
-
Textarea with suggest for React app
|
|
2
|
+
Textarea with suggest for React app v2.0.0
|
|
3
|
+
|
|
4
|
+
### Last changes:
|
|
5
|
+
- supports TypeScript and new React versions
|
|
6
|
+
- fixed bug with installing
|
|
3
7
|
|
|
4
8
|
## Install
|
|
5
9
|
If you use npm
|
|
@@ -60,8 +64,6 @@ item =>
|
|
|
60
64
|
|any else params for `<textarea>`| - | - |https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#Attributes|
|
|
61
65
|
|
|
62
66
|
## Using libraries
|
|
63
|
-
- "prop-types"
|
|
64
|
-
- "lodash.once"
|
|
65
67
|
- "react-textarea-autosize" (optionally)
|
|
66
68
|
|
|
67
69
|
## License
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Example application with react-textarea-with-suggest
|
|
2
|
+
|
|
3
|
+
This small application was created to present use cases of react-textarea-with-suggest package
|
|
4
|
+
|
|
5
|
+
## Available Scripts
|
|
6
|
+
|
|
7
|
+
In the project directory, you can run:
|
|
8
|
+
|
|
9
|
+
### `npm start`
|
|
10
|
+
|
|
11
|
+
Runs the app in the development mode.\
|
|
12
|
+
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
|
|
13
|
+
|
|
14
|
+
The page will reload when you make changes.\
|
|
15
|
+
You may also see any lint errors in the console.
|
|
16
|
+
|
|
17
|
+
## Learn More
|
|
18
|
+
|
|
19
|
+
To learn more, check out the [Readme](https://github.com/marylorian/react-textarea-with-suggest).
|
|
20
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "example",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"dependencies": {
|
|
6
|
+
"react": "^16.14.0",
|
|
7
|
+
"react-dom": "^16.14.0",
|
|
8
|
+
"react-scripts": "5.0.1",
|
|
9
|
+
"react-textarea-with-suggest": "latest"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"start": "react-scripts start",
|
|
13
|
+
"test": "react-scripts test"
|
|
14
|
+
},
|
|
15
|
+
"eslintConfig": {
|
|
16
|
+
"extends": [
|
|
17
|
+
"react-app",
|
|
18
|
+
"react-app/jest"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"browserslist": {
|
|
22
|
+
"production": [
|
|
23
|
+
">0.2%",
|
|
24
|
+
"not dead",
|
|
25
|
+
"not op_mini all"
|
|
26
|
+
],
|
|
27
|
+
"development": [
|
|
28
|
+
"last 1 chrome version",
|
|
29
|
+
"last 1 firefox version",
|
|
30
|
+
"last 1 safari version"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"lodash.once": "^4.1.1",
|
|
35
|
+
"react-textarea-autosize": "^8.4.0"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
+
<meta name="theme-color" content="#000000" />
|
|
8
|
+
<meta
|
|
9
|
+
name="description"
|
|
10
|
+
content="Web site created using create-react-app"
|
|
11
|
+
/>
|
|
12
|
+
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
|
13
|
+
<!--
|
|
14
|
+
manifest.json provides metadata used when your web app is installed on a
|
|
15
|
+
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
|
16
|
+
-->
|
|
17
|
+
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
|
18
|
+
<!--
|
|
19
|
+
Notice the use of %PUBLIC_URL% in the tags above.
|
|
20
|
+
It will be replaced with the URL of the `public` folder during the build.
|
|
21
|
+
Only files inside the `public` folder can be referenced from the HTML.
|
|
22
|
+
|
|
23
|
+
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
|
24
|
+
work correctly both with client-side routing and a non-root public URL.
|
|
25
|
+
Learn how to configure a non-root public URL by running `npm run build`.
|
|
26
|
+
-->
|
|
27
|
+
<title>React App</title>
|
|
28
|
+
</head>
|
|
29
|
+
<body>
|
|
30
|
+
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
31
|
+
<div id="root"></div>
|
|
32
|
+
<!--
|
|
33
|
+
This HTML file is a template.
|
|
34
|
+
If you open it directly in the browser, you will see an empty page.
|
|
35
|
+
|
|
36
|
+
You can add webfonts, meta tags, or analytics to this file.
|
|
37
|
+
The build step will place the bundled scripts into the <body> tag.
|
|
38
|
+
|
|
39
|
+
To begin the development, run `npm start` or `yarn start`.
|
|
40
|
+
To create a production bundle, use `npm run build` or `yarn build`.
|
|
41
|
+
-->
|
|
42
|
+
</body>
|
|
43
|
+
</html>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
.example {
|
|
2
|
+
text-align: center;
|
|
3
|
+
font-family: Arial, Helvetica, sans-serif;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.example__textarea {
|
|
7
|
+
border-radius: 4px;
|
|
8
|
+
padding: 12px;
|
|
9
|
+
font-family: Arial, Helvetica, sans-serif;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.example__textarea__results {
|
|
13
|
+
border-radius: 4px;
|
|
14
|
+
border: 1px solid;
|
|
15
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import Textarea from "react-textarea-with-suggest";
|
|
3
|
+
import "./App.css";
|
|
4
|
+
|
|
5
|
+
const randomResults = [
|
|
6
|
+
"Hello",
|
|
7
|
+
"The Result",
|
|
8
|
+
"Harry Potter",
|
|
9
|
+
"The Lord Of The Rings",
|
|
10
|
+
"The Matrix",
|
|
11
|
+
"The Truman Show",
|
|
12
|
+
"Home Alone",
|
|
13
|
+
"Cat In The Hat",
|
|
14
|
+
"Alice In Worderland",
|
|
15
|
+
"The Night Knight",
|
|
16
|
+
"The Dark Knight",
|
|
17
|
+
"Dark Night",
|
|
18
|
+
"The Long Night",
|
|
19
|
+
"Good bye",
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
function App() {
|
|
23
|
+
const [results, setResults] = useState(undefined);
|
|
24
|
+
|
|
25
|
+
const onSearch = (searchPhrase) => {
|
|
26
|
+
console.log("onSearch", searchPhrase);
|
|
27
|
+
|
|
28
|
+
const start = Math.floor(Math.random() * 10);
|
|
29
|
+
const length = Math.floor(Math.random() * 10);
|
|
30
|
+
const newResults = randomResults
|
|
31
|
+
.slice(start, start + length)
|
|
32
|
+
.filter(Boolean);
|
|
33
|
+
|
|
34
|
+
setResults(newResults);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const onChange = (e) => {
|
|
38
|
+
console.log("onChange", e.target.value);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<div className="example">
|
|
43
|
+
<h1>TextareaWithSuggest Example</h1>
|
|
44
|
+
<p>Default</p>
|
|
45
|
+
<Textarea
|
|
46
|
+
className="example__textarea"
|
|
47
|
+
onChange={onChange}
|
|
48
|
+
onSearch={onSearch}
|
|
49
|
+
suggestList={results}
|
|
50
|
+
/>
|
|
51
|
+
|
|
52
|
+
<p>Autosizable</p>
|
|
53
|
+
<Textarea
|
|
54
|
+
autosizable
|
|
55
|
+
className="example__textarea"
|
|
56
|
+
onChange={onChange}
|
|
57
|
+
onSearch={onSearch}
|
|
58
|
+
suggestList={results}
|
|
59
|
+
/>
|
|
60
|
+
|
|
61
|
+
<p>With initial value</p>
|
|
62
|
+
<Textarea
|
|
63
|
+
autosizable
|
|
64
|
+
className="example__textarea"
|
|
65
|
+
value="Initial Value"
|
|
66
|
+
onChange={onChange}
|
|
67
|
+
onSearch={onSearch}
|
|
68
|
+
suggestList={results}
|
|
69
|
+
/>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export default App;
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React textarea with suggest v2.0.0
|
|
3
|
+
*
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) 2019-present,
|
|
6
|
+
* by Mariia Lobareva (marialobareva97@gmail.com).
|
|
7
|
+
*
|
|
8
|
+
* LICENSE MIT.
|
|
9
|
+
*/
|
|
10
|
+
import React, { ReactNode } from "react";
|
|
11
|
+
import "../styles.css";
|
|
12
|
+
interface TextareaSuggestProps<SuggestItemType> {
|
|
13
|
+
className?: string;
|
|
14
|
+
autosizable?: boolean;
|
|
15
|
+
searchMarker?: string;
|
|
16
|
+
searchRegexp?: RegExp;
|
|
17
|
+
suggestList?: SuggestItemType[];
|
|
18
|
+
value?: string;
|
|
19
|
+
onChange?: Function;
|
|
20
|
+
onSearch: Function;
|
|
21
|
+
customSuggestItemRenderer?: (suggestItem: SuggestItemType, defaultOnClick: (item: SuggestItemType) => void) => ReactNode;
|
|
22
|
+
}
|
|
23
|
+
declare const TextareaSuggest: <SuggestItemType extends React.ReactNode>({ autosizable, value, searchMarker, searchRegexp: searchRegexpProp, suggestList, onSearch, onChange, customSuggestItemRenderer, ...props }: TextareaSuggestProps<SuggestItemType>) => JSX.Element;
|
|
24
|
+
export default TextareaSuggest;
|
package/lib/index.js
CHANGED
|
@@ -1,273 +1,2 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
var _react = _interopRequireDefault(require("react"));
|
|
4
|
-
|
|
5
|
-
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
6
|
-
|
|
7
|
-
var _lodash = _interopRequireDefault(require("lodash.once"));
|
|
8
|
-
|
|
9
|
-
var _reactTextareaAutosize = _interopRequireDefault(require("react-textarea-autosize"));
|
|
10
|
-
|
|
11
|
-
require("../styles.css");
|
|
12
|
-
|
|
13
|
-
var _class, _temp;
|
|
14
|
-
|
|
15
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
16
|
-
|
|
17
|
-
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
|
|
18
|
-
|
|
19
|
-
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
|
20
|
-
|
|
21
|
-
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
|
22
|
-
|
|
23
|
-
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
|
24
|
-
|
|
25
|
-
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
26
|
-
|
|
27
|
-
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; }
|
|
28
|
-
|
|
29
|
-
function _extends() { _extends = Object.assign || 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); }
|
|
30
|
-
|
|
31
|
-
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
32
|
-
|
|
33
|
-
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); } }
|
|
34
|
-
|
|
35
|
-
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
|
36
|
-
|
|
37
|
-
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
|
|
38
|
-
|
|
39
|
-
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
|
|
40
|
-
|
|
41
|
-
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
|
42
|
-
|
|
43
|
-
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 } }); if (superClass) _setPrototypeOf(subClass, superClass); }
|
|
44
|
-
|
|
45
|
-
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
|
|
46
|
-
|
|
47
|
-
module.exports = (_temp = _class =
|
|
48
|
-
/*#__PURE__*/
|
|
49
|
-
function (_React$Component) {
|
|
50
|
-
_inherits(TextareaSuggest, _React$Component);
|
|
51
|
-
|
|
52
|
-
function TextareaSuggest() {
|
|
53
|
-
var _getPrototypeOf2;
|
|
54
|
-
|
|
55
|
-
var _this;
|
|
56
|
-
|
|
57
|
-
_classCallCheck(this, TextareaSuggest);
|
|
58
|
-
|
|
59
|
-
for (var _len = arguments.length, _args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
60
|
-
_args[_key] = arguments[_key];
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
_this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(TextareaSuggest)).call.apply(_getPrototypeOf2, [this].concat(_args)));
|
|
64
|
-
_this._textarea = null;
|
|
65
|
-
_this._element = null;
|
|
66
|
-
_this.state = {
|
|
67
|
-
needStartSearch: _this.props.value && _this.props.value.includes(_this.props.searchMarker),
|
|
68
|
-
text: _this.props.value || ""
|
|
69
|
-
};
|
|
70
|
-
_this.defaultProps = {
|
|
71
|
-
autosizable: false,
|
|
72
|
-
searchMarker: "@",
|
|
73
|
-
searchRegexp: /@([a-z0\d\-.]+[a-z\d])/gim,
|
|
74
|
-
suggestList: []
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
_this._mobileAndTabletCheck = function () {
|
|
78
|
-
var check = false;
|
|
79
|
-
|
|
80
|
-
(function (a) {
|
|
81
|
-
if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(a.substr(0, 4))) check = true;
|
|
82
|
-
})(navigator.userAgent || navigator.vendor || window.opera);
|
|
83
|
-
|
|
84
|
-
return check;
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
_this.onChange = function (_ref) {
|
|
88
|
-
var args = _extends({}, _ref);
|
|
89
|
-
|
|
90
|
-
var _this$props = _this.props,
|
|
91
|
-
searchMarker = _this$props.searchMarker,
|
|
92
|
-
searchRegexp = _this$props.searchRegexp;
|
|
93
|
-
var needStartSearch = _this.state.needStartSearch;
|
|
94
|
-
var _args$currentTarget = args.currentTarget,
|
|
95
|
-
currentTarget = _args$currentTarget === void 0 ? {} : _args$currentTarget,
|
|
96
|
-
_args$isTrusted = args.isTrusted,
|
|
97
|
-
isTrusted = _args$isTrusted === void 0 ? true : _args$isTrusted;
|
|
98
|
-
var _currentTarget$value = currentTarget.value,
|
|
99
|
-
value = _currentTarget$value === void 0 ? _this.state.text : _currentTarget$value;
|
|
100
|
-
var selectionEnd = _this._textarea.selectionEnd;
|
|
101
|
-
var last = selectionEnd ? value.slice(selectionEnd - 1, selectionEnd) : value.slice(-1);
|
|
102
|
-
|
|
103
|
-
_this.setState({
|
|
104
|
-
text: value
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
if (last === searchMarker) {
|
|
108
|
-
_this.setState({
|
|
109
|
-
needStartSearch: true
|
|
110
|
-
}); //TODO: clear suggestList here
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (!value.includes(searchMarker) && needStartSearch) {
|
|
115
|
-
_this.setState({
|
|
116
|
-
needStartSearch: false
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (last !== searchMarker && needStartSearch) {
|
|
121
|
-
var textWithResults = value.slice(0, selectionEnd);
|
|
122
|
-
var results = textWithResults.slice(textWithResults.lastIndexOf(searchMarker)).match(new RegExp(searchRegexp));
|
|
123
|
-
var result = results ? results[0].slice(1) : last;
|
|
124
|
-
|
|
125
|
-
_this.props.onSearch(result);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (isTrusted) return _this.props.onChange(args);
|
|
129
|
-
return _this.props.onChange(_objectSpread({}, args, {
|
|
130
|
-
currentTarget: _this._textarea,
|
|
131
|
-
target: _this._textarea
|
|
132
|
-
}));
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
_this.setResult = function (result) {
|
|
136
|
-
var searchMarker = _this.props.searchMarker;
|
|
137
|
-
var currentText = _this.state.text;
|
|
138
|
-
var selectionEnd = _this._textarea.selectionEnd;
|
|
139
|
-
var position = currentText.slice(0, selectionEnd).lastIndexOf(searchMarker);
|
|
140
|
-
var textWithResult = currentText.slice(position);
|
|
141
|
-
|
|
142
|
-
if (position !== -1) {
|
|
143
|
-
var endPosition = (textWithResult.includes(" ") ? textWithResult.indexOf(" ") : currentText.length) + position;
|
|
144
|
-
var newValue;
|
|
145
|
-
|
|
146
|
-
if (textWithResult.lastIndexOf(searchMarker) > 0) {
|
|
147
|
-
endPosition = textWithResult.lastIndexOf(searchMarker) + position;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if (!endPosition || endPosition < position) {
|
|
151
|
-
endPosition = currentText.length;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
newValue = currentText.slice(0, position || 0) + currentText.slice(position).replace(currentText.slice(position, endPosition), "".concat(searchMarker).concat(result, " "));
|
|
155
|
-
_this._textarea.value = newValue;
|
|
156
|
-
|
|
157
|
-
_this._textarea.focus();
|
|
158
|
-
|
|
159
|
-
if (_this._mobileAndTabletCheck()) {
|
|
160
|
-
var endCaretPosition = newValue.slice(position).indexOf(" ") + position + 1;
|
|
161
|
-
|
|
162
|
-
_this._textarea.setSelectionRange(endCaretPosition, endCaretPosition);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
var event = new Event("onchange", {
|
|
166
|
-
bubbles: true,
|
|
167
|
-
cancelable: false
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
_this._element._onChange(event);
|
|
171
|
-
|
|
172
|
-
_this.setState({
|
|
173
|
-
needStartSearch: false,
|
|
174
|
-
text: newValue
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
_this.renderSuggestItem = function (item, index) {
|
|
180
|
-
if (_this.props.onSuggestItemRender) return _this.props.onSuggestItemRender(item);
|
|
181
|
-
return _react.default.createElement("div", {
|
|
182
|
-
key: index,
|
|
183
|
-
className: "textarea-suggest-item",
|
|
184
|
-
onClick: function onClick() {
|
|
185
|
-
return _this.setResult(item);
|
|
186
|
-
}
|
|
187
|
-
}, _react.default.createElement("div", {
|
|
188
|
-
className: "textarea-suggest-item--info"
|
|
189
|
-
}, _react.default.createElement("div", null, item)));
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
_this.renderSearchResults = function () {
|
|
193
|
-
var suggestList = _this.props.suggestList;
|
|
194
|
-
|
|
195
|
-
if (_this.state.needStartSearch && suggestList && suggestList.length && _this._textare) {
|
|
196
|
-
var curHeight = _this._textarea.getBoundingClientRect().height;
|
|
197
|
-
|
|
198
|
-
return _react.default.createElement("div", {
|
|
199
|
-
className: "textarea-suggest--results",
|
|
200
|
-
style: {
|
|
201
|
-
top: curHeight
|
|
202
|
-
}
|
|
203
|
-
}, suggestList.map(function (item, index) {
|
|
204
|
-
return _this.renderSuggestItem(item, index);
|
|
205
|
-
}));
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
return null;
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
return _this;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
_createClass(TextareaSuggest, [{
|
|
215
|
-
key: "componentDidMount",
|
|
216
|
-
value: function componentDidMount() {
|
|
217
|
-
var _this2 = this;
|
|
218
|
-
|
|
219
|
-
this.initialize = (0, _lodash.default)(function (el) {
|
|
220
|
-
var className = _this2.props.className;
|
|
221
|
-
var elem = document.getElementsByClassName(className)[0];
|
|
222
|
-
_this2._textarea = elem;
|
|
223
|
-
_this2._element = el;
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
if (this.props.searchMarker.length > 1) {
|
|
227
|
-
throw new TypeError("Max length of searchMarker is 1 symbol. Please change your searchMarker to char");
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}, {
|
|
231
|
-
key: "componentDidUpdate",
|
|
232
|
-
value: function componentDidUpdate(prevProps, prevState, snapshot) {
|
|
233
|
-
if (prevState.text !== this.props.value && prevProps.value !== this.props.value) {
|
|
234
|
-
this.setState({
|
|
235
|
-
text: this.props.value
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}, {
|
|
240
|
-
key: "render",
|
|
241
|
-
value: function render() {
|
|
242
|
-
var _this$props2 = this.props,
|
|
243
|
-
autosizable = _this$props2.autosizable,
|
|
244
|
-
value = _this$props2.value,
|
|
245
|
-
props = _objectWithoutProperties(_this$props2, ["autosizable", "value"]);
|
|
246
|
-
|
|
247
|
-
var searchResults = this.renderSearchResults();
|
|
248
|
-
return _react.default.createElement("div", {
|
|
249
|
-
className: "textarea-suggest"
|
|
250
|
-
}, autosizable ? _react.default.createElement(_reactTextareaAutosize.default, _extends({}, props, {
|
|
251
|
-
ref: this.initialize,
|
|
252
|
-
onChange: this.onChange,
|
|
253
|
-
value: this.state.text || value
|
|
254
|
-
})) : _react.default.createElement("textarea", _extends({}, props, {
|
|
255
|
-
ref: this.initialize,
|
|
256
|
-
onChange: this.onChange,
|
|
257
|
-
value: this.state.text || value
|
|
258
|
-
})), searchResults);
|
|
259
|
-
}
|
|
260
|
-
}]);
|
|
261
|
-
|
|
262
|
-
return TextareaSuggest;
|
|
263
|
-
}(_react.default.Component), _class.propTypes = {
|
|
264
|
-
autosizable: _propTypes.default.bool,
|
|
265
|
-
className: _propTypes.default.string.isRequired,
|
|
266
|
-
onChange: _propTypes.default.func.isRequired,
|
|
267
|
-
onSearch: _propTypes.default.func.isRequired,
|
|
268
|
-
onSuggestItemRender: _propTypes.default.func,
|
|
269
|
-
searchMarker: _propTypes.default.string,
|
|
270
|
-
searchRegexp: _propTypes.default.any,
|
|
271
|
-
suggestList: _propTypes.default.array,
|
|
272
|
-
value: _propTypes.default.string
|
|
273
|
-
}, _temp);
|
|
1
|
+
Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("react-textarea-autosize");function a(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var n=a(e),r=a(t),i=function(){return i=Object.assign||function(e){for(var t,a=1,n=arguments.length;a<n;a++)for(var r in t=arguments[a])Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e},i.apply(this,arguments)};function o(e,t){var a={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(a[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var r=0;for(n=Object.getOwnPropertySymbols(e);r<n.length;r++)t.indexOf(n[r])<0&&Object.prototype.propertyIsEnumerable.call(e,n[r])&&(a[n[r]]=e[n[r]])}return a}function c(t){var a=e.useRef();return e.useEffect((function(){a.current=t}),[t]),a.current}var l=e.forwardRef((function(e,t){return n.default.createElement("textarea",i({},e,{ref:t}))}));exports.default=function(t){var a=t.autosizable,s=void 0!==a&&a,u=t.value,d=void 0===u?"":u,m=t.searchMarker,f=void 0===m?"@":m,p=t.searchRegexp,g=t.suggestList,v=void 0===g?[]:g,b=t.onSearch,h=t.onChange,w=t.customSuggestItemRenderer,k=o(t,["autosizable","value","searchMarker","searchRegexp","suggestList","onSearch","onChange","customSuggestItemRenderer"]),y=e.useState(d),x=y[0],O=y[1],E=e.useState(null==d?void 0:d.includes(f)),z=E[0],j=E[1],R=c(x),_=c(d),S=e.useRef(null),M=s?r.default:l,q=e.useMemo((function(){return p?new RegExp(p):new RegExp("".concat(f,"([a-z0-9-_.]+[a-z0-9])"),"gim")}),[p]);e.useEffect((function(){if(f.length>1)throw new TypeError("Max length of searchMarker is 1 symbol. Please change your searchMarker to char")}),[]),e.useEffect((function(){R!==d&&_!==d&&O(d)}),[x,d,R,_]);var I=function(e){var t,a,n,r,i,o,c=null===(t=S.current)||void 0===t?void 0:t.selectionEnd,l=x.slice(0,c).lastIndexOf(f),s=x.slice(l);if(-1!==l){var u=(s.includes(" ")?s.indexOf(" "):x.length)+l,d=void 0;if(s.lastIndexOf(f)>0&&(u=s.lastIndexOf(f)+l),(!u||u<l)&&(u=x.length),d=x.slice(0,l||0)+x.slice(l).replace(x.slice(l,u),"".concat(f).concat(e," ")),S.current&&(S.current.value=d,S.current.focus()),o=!1,i=navigator.userAgent||navigator.vendor||"opera"in window&&window.opera,(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(i)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(i.substr(0,4)))&&(o=!0),o){var m=d.slice(l).indexOf(" ")+l+1;null===(a=S.current)||void 0===a||a.setSelectionRange(m,m)}var p=new Event("onchange",{bubbles:!0,cancelable:!1});null===(r=null===(n=S.current)||void 0===n?void 0:n.onchange)||void 0===r||r.call(n,p),j(!1),O(d)}},C=e.useCallback((function(e){var t=function(){return I(e)};return w?w(e,t):n.default.createElement("div",{className:"textarea-suggest-item",onClick:t},n.default.createElement("div",{className:"textarea-suggest-item__info"},n.default.createElement("div",null,e)))}),[I,w]),P=e.useMemo((function(){var t;if(z&&v&&v.length&&S.current){var a=null===(t=S.current)||void 0===t?void 0:t.getBoundingClientRect(),r=a.width,i=a.left;return n.default.createElement("div",{className:"textarea-suggest__results ".concat(k.className,"__results"),style:{position:"absolute",width:r,left:i}},v.map((function(t,a){return n.default.createElement(e.Fragment,{key:t&&"object"==typeof t&&"id"in t?t.id:a},C(t))})))}return null}),[z,v,S]);return n.default.createElement("div",{className:"textarea-suggest"},n.default.createElement(M,i({},k,{ref:S,onChange:function(e){var t,a=o(e,[]),n=a.currentTarget,r=void 0===n?{}:n,c=a.isTrusted,l=void 0===c||c,s=r.value,u=void 0===s?x:s,d=null===(t=S.current)||void 0===t?void 0:t.selectionEnd,m=d?u.slice(d-1,d):u.slice(-1);if(O(u),m===f&&j(!0),u.includes(f)&&![" ","\n","\r"].includes(m)||!z||j(!1),m!==f&&z){var p=u.slice(0,d),g=p.slice(p.lastIndexOf(f)).match(q),v=g?g[0].slice(1):m;b(v)}return l?null==h?void 0:h(a):null==h?void 0:h(i(i({},a),{currentTarget:S.current,target:S.current}))},value:x||d})),P)};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
package/lib/styles.css
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
.textarea-suggest {
|
|
2
|
+
resize: none;
|
|
3
|
+
}
|
|
4
|
+
.textarea-suggest__results {
|
|
5
|
+
position: absolute;
|
|
6
|
+
z-index: 150;
|
|
7
|
+
min-width: 220px;
|
|
8
|
+
margin: 0 16px;
|
|
9
|
+
animation: ascent 0.2s forwards;
|
|
10
|
+
border-radius: 9px;
|
|
11
|
+
background-color: #fff;
|
|
12
|
+
box-shadow: 0 3px 12px #c1c1c1;
|
|
13
|
+
}
|
|
14
|
+
.textarea-suggest__info {
|
|
15
|
+
position: absolute;
|
|
16
|
+
bottom: 8px;
|
|
17
|
+
right: 8px;
|
|
18
|
+
}
|
|
19
|
+
.textarea-suggest__info-item {
|
|
20
|
+
line-height: 20px;
|
|
21
|
+
margin: 16px 0;
|
|
22
|
+
}
|
|
23
|
+
.textarea-suggest-item {
|
|
24
|
+
display: flex;
|
|
25
|
+
padding: 4px 8px 0;
|
|
26
|
+
}
|
|
27
|
+
.textarea-suggest-item:first-child {
|
|
28
|
+
padding-top: 8px;
|
|
29
|
+
}
|
|
30
|
+
.textarea-suggest-item:last-child {
|
|
31
|
+
padding-bottom: 8px;
|
|
32
|
+
}
|
|
33
|
+
.textarea-suggest-item:hover {
|
|
34
|
+
background-color: #f2f3f9;
|
|
35
|
+
}
|
|
36
|
+
.textarea-suggest-item--info {
|
|
37
|
+
margin-left: 8px;
|
|
38
|
+
}
|
|
39
|
+
|
package/lib/utils.d.ts
ADDED
package/package.json
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-textarea-with-suggest",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Textarea with suggest for React app",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
|
+
"types": "lib/index.d.ts",
|
|
6
7
|
"dependencies": {
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"react": "^16.8.6",
|
|
10
|
-
"react-dom": "^16.8.6",
|
|
11
|
-
"react-scripts": "3.0.1",
|
|
12
|
-
"react-textarea-autosize": "^7.1.0"
|
|
8
|
+
"react-scripts": "^5.0.1",
|
|
9
|
+
"react-textarea-autosize": "^8.4.0"
|
|
13
10
|
},
|
|
11
|
+
"files": [
|
|
12
|
+
"lib",
|
|
13
|
+
"example"
|
|
14
|
+
],
|
|
14
15
|
"scripts": {
|
|
15
|
-
"
|
|
16
|
+
"prettier": "prettier --write .",
|
|
17
|
+
"build:debug": "npm install && npm run build && rm -rf node_modules",
|
|
18
|
+
"build": "rollup -c",
|
|
19
|
+
"start": "rollup -c -w",
|
|
20
|
+
"build:old": "npm run prettier && babel --extensions .tsx ./src -d ./lib --source-maps && cp ./src/index.d.ts ./lib"
|
|
16
21
|
},
|
|
17
22
|
"license": "MIT",
|
|
18
23
|
"eslintConfig": {
|
|
@@ -29,7 +34,7 @@
|
|
|
29
34
|
"react",
|
|
30
35
|
"react-component"
|
|
31
36
|
],
|
|
32
|
-
"author": "
|
|
37
|
+
"author": "Mariia Lobareva",
|
|
33
38
|
"bugs": {
|
|
34
39
|
"url": "https://github.com/marylorian/react-textarea-with-suggest/issues"
|
|
35
40
|
},
|
|
@@ -49,7 +54,8 @@
|
|
|
49
54
|
"babel": {
|
|
50
55
|
"presets": [
|
|
51
56
|
"@babel/preset-env",
|
|
52
|
-
"@babel/preset-react"
|
|
57
|
+
"@babel/preset-react",
|
|
58
|
+
"@babel/preset-typescript"
|
|
53
59
|
],
|
|
54
60
|
"plugins": [
|
|
55
61
|
[
|
|
@@ -60,18 +66,33 @@
|
|
|
60
66
|
]
|
|
61
67
|
]
|
|
62
68
|
},
|
|
69
|
+
"peerDependencies": {
|
|
70
|
+
"react": "^17.0.0 || ^18.2.0",
|
|
71
|
+
"react-dom": "^17.0.0 || ^18.2.0"
|
|
72
|
+
},
|
|
63
73
|
"devDependencies": {
|
|
64
74
|
"@babel/cli": "^7.5.5",
|
|
65
75
|
"@babel/core": "^7.0.0-0",
|
|
66
76
|
"@babel/plugin-proposal-class-properties": "^7.5.5",
|
|
67
77
|
"@babel/preset-env": "^7.5.5",
|
|
68
78
|
"@babel/preset-react": "^7.0.0",
|
|
79
|
+
"@babel/preset-typescript": "^7.18.6",
|
|
80
|
+
"@rollup/plugin-babel": "^6.0.3",
|
|
81
|
+
"@rollup/plugin-terser": "^0.2.1",
|
|
82
|
+
"@rollup/plugin-typescript": "^10.0.1",
|
|
83
|
+
"@types/lodash.once": "^4.1.7",
|
|
84
|
+
"@types/react": "^18.0.26",
|
|
85
|
+
"babel-core": "^6.26.3",
|
|
69
86
|
"babel-loader": "^8.0.6",
|
|
70
|
-
"css-loader": "^
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
87
|
+
"css-loader": "^6.7.3",
|
|
88
|
+
"prettier": "2.7.1",
|
|
89
|
+
"rollup": "^2.79.1",
|
|
90
|
+
"rollup-plugin-css-only": "^4.3.0",
|
|
91
|
+
"terser": "^5.16.1",
|
|
92
|
+
"typescript": "^4.9.4",
|
|
93
|
+
"webpack": "^5.75.0",
|
|
94
|
+
"webpack-cli": "^5.0.1",
|
|
95
|
+
"webpack-dev-server": "^4.11.1",
|
|
75
96
|
"webpack-merge": "^4.2.1"
|
|
76
97
|
}
|
|
77
98
|
}
|
package/src/index.js
DELETED
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
/** React textarea with suggest v1.0.0
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* Copyright (c) 2019-present,
|
|
5
|
-
* by Maria Lobareva (marialobareva97@gmail.com).
|
|
6
|
-
*
|
|
7
|
-
* LICENSE MIT.
|
|
8
|
-
*/
|
|
9
|
-
import React from 'react';
|
|
10
|
-
import PropTypes from 'prop-types';
|
|
11
|
-
import once from "lodash.once";
|
|
12
|
-
import TextareaAutosize from "react-textarea-autosize";
|
|
13
|
-
import "../styles.css";
|
|
14
|
-
|
|
15
|
-
module.exports = class TextareaSuggest extends React.Component {
|
|
16
|
-
_textarea = null;
|
|
17
|
-
_element = null;
|
|
18
|
-
|
|
19
|
-
state = {
|
|
20
|
-
needStartSearch: this.props.value && this.props.value.includes(this.props.searchMarker),
|
|
21
|
-
text: this.props.value || ""
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
static propTypes = {
|
|
25
|
-
autosizable: PropTypes.bool,
|
|
26
|
-
className: PropTypes.string.isRequired,
|
|
27
|
-
onChange: PropTypes.func.isRequired,
|
|
28
|
-
onSearch: PropTypes.func.isRequired,
|
|
29
|
-
onSuggestItemRender: PropTypes.func,
|
|
30
|
-
searchMarker: PropTypes.string,
|
|
31
|
-
searchRegexp: PropTypes.any,
|
|
32
|
-
suggestList: PropTypes.array,
|
|
33
|
-
value: PropTypes.string
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
defaultProps = {
|
|
37
|
-
autosizable: false,
|
|
38
|
-
searchMarker: "@",
|
|
39
|
-
searchRegexp: /@([a-z0\d\-.]+[a-z\d])/gim,
|
|
40
|
-
suggestList: []
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
componentDidMount() {
|
|
44
|
-
this.initialize = once(el => {
|
|
45
|
-
const {className} = this.props;
|
|
46
|
-
const elem = document.getElementsByClassName(className)[0];
|
|
47
|
-
this._textarea = elem;
|
|
48
|
-
this._element = el;
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
if (this.props.searchMarker.length > 1) {
|
|
52
|
-
throw new TypeError("Max length of searchMarker is 1 symbol. Please change your searchMarker to char");
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
componentDidUpdate(prevProps, prevState, snapshot) {
|
|
57
|
-
if (
|
|
58
|
-
prevState.text !== this.props.value &&
|
|
59
|
-
prevProps.value !== this.props.value
|
|
60
|
-
) {
|
|
61
|
-
this.setState({ text: this.props.value });
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
_mobileAndTabletCheck = () => {
|
|
66
|
-
let check = false;
|
|
67
|
-
(function (a) {
|
|
68
|
-
if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(a.substr(0, 4))) check = true;
|
|
69
|
-
})(navigator.userAgent || navigator.vendor || window.opera);
|
|
70
|
-
return check;
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
onChange = ({...args}) => {
|
|
74
|
-
const {searchMarker, searchRegexp} = this.props;
|
|
75
|
-
const {needStartSearch} = this.state;
|
|
76
|
-
const {currentTarget = {}, isTrusted = true} = args;
|
|
77
|
-
const {value = this.state.text} = currentTarget;
|
|
78
|
-
let selectionEnd = this._textarea.selectionEnd;
|
|
79
|
-
let last = selectionEnd
|
|
80
|
-
? value.slice(selectionEnd - 1, selectionEnd)
|
|
81
|
-
: value.slice(-1);
|
|
82
|
-
|
|
83
|
-
this.setState({text: value});
|
|
84
|
-
|
|
85
|
-
if (last === searchMarker) {
|
|
86
|
-
this.setState({needStartSearch: true});
|
|
87
|
-
//TODO: clear suggestList here
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if (!value.includes(searchMarker) && needStartSearch) {
|
|
91
|
-
this.setState({needStartSearch: false});
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (last !== searchMarker && needStartSearch) {
|
|
95
|
-
let textWithResults = value.slice(0, selectionEnd);
|
|
96
|
-
let results = textWithResults
|
|
97
|
-
.slice(textWithResults.lastIndexOf(searchMarker)).match(new RegExp(searchRegexp));
|
|
98
|
-
let result = results ? results[0].slice(1) : last;
|
|
99
|
-
|
|
100
|
-
this.props.onSearch(result);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (isTrusted) return this.props.onChange(args);
|
|
104
|
-
return this.props.onChange({
|
|
105
|
-
...args,
|
|
106
|
-
currentTarget: this._textarea,
|
|
107
|
-
target: this._textarea
|
|
108
|
-
});
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
setResult = (result) => {
|
|
112
|
-
const {searchMarker} = this.props;
|
|
113
|
-
const {text: currentText} = this.state;
|
|
114
|
-
let selectionEnd = this._textarea.selectionEnd;
|
|
115
|
-
let position = currentText.slice(0, selectionEnd).lastIndexOf(searchMarker);
|
|
116
|
-
let textWithResult = currentText.slice(position);
|
|
117
|
-
|
|
118
|
-
if (position !== -1) {
|
|
119
|
-
let endPosition =
|
|
120
|
-
(textWithResult.includes(" ")
|
|
121
|
-
? textWithResult.indexOf(" ")
|
|
122
|
-
: currentText.length) + position;
|
|
123
|
-
let newValue;
|
|
124
|
-
|
|
125
|
-
if (textWithResult.lastIndexOf(searchMarker) > 0) {
|
|
126
|
-
endPosition = textWithResult.lastIndexOf(searchMarker) + position;
|
|
127
|
-
}
|
|
128
|
-
if (!endPosition || endPosition < position) {
|
|
129
|
-
endPosition = currentText.length;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
newValue =
|
|
133
|
-
currentText.slice(0, position || 0) +
|
|
134
|
-
currentText
|
|
135
|
-
.slice(position)
|
|
136
|
-
.replace(currentText.slice(position, endPosition), `${searchMarker}${result} `);
|
|
137
|
-
|
|
138
|
-
this._textarea.value = newValue;
|
|
139
|
-
this._textarea.focus();
|
|
140
|
-
|
|
141
|
-
if (this._mobileAndTabletCheck()) {
|
|
142
|
-
let endCaretPosition =
|
|
143
|
-
newValue.slice(position).indexOf(" ") + position + 1;
|
|
144
|
-
this._textarea.setSelectionRange(endCaretPosition, endCaretPosition);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
let event = new Event("onchange", {
|
|
148
|
-
bubbles: true,
|
|
149
|
-
cancelable: false
|
|
150
|
-
});
|
|
151
|
-
this._element._onChange(event);
|
|
152
|
-
|
|
153
|
-
this.setState({needStartSearch: false, text: newValue});
|
|
154
|
-
}
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
renderSuggestItem = (item, index) => {
|
|
158
|
-
if (this.props.onSuggestItemRender) return this.props.onSuggestItemRender(item);
|
|
159
|
-
return (
|
|
160
|
-
<div
|
|
161
|
-
key={index}
|
|
162
|
-
className="textarea-suggest-item"
|
|
163
|
-
onClick={() => this.setResult(item)}
|
|
164
|
-
>
|
|
165
|
-
<div className="textarea-suggest-item--info">
|
|
166
|
-
<div>{item}</div>
|
|
167
|
-
</div>
|
|
168
|
-
</div>
|
|
169
|
-
);
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
renderSearchResults = () => {
|
|
173
|
-
const {suggestList} = this.props;
|
|
174
|
-
|
|
175
|
-
if (this.state.needStartSearch && suggestList && suggestList.length && this._textare) {
|
|
176
|
-
let curHeight = this._textarea.getBoundingClientRect().height;
|
|
177
|
-
|
|
178
|
-
return (
|
|
179
|
-
<div className="textarea-suggest--results" style={{top: curHeight}}>
|
|
180
|
-
{suggestList.map((item, index) => {
|
|
181
|
-
return this.renderSuggestItem(item, index);
|
|
182
|
-
})}
|
|
183
|
-
</div>
|
|
184
|
-
);
|
|
185
|
-
}
|
|
186
|
-
return null;
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
render() {
|
|
190
|
-
const {autosizable, value, ...props} = this.props;
|
|
191
|
-
const searchResults = this.renderSearchResults();
|
|
192
|
-
|
|
193
|
-
return (
|
|
194
|
-
<div className="textarea-suggest">
|
|
195
|
-
{autosizable
|
|
196
|
-
? (<TextareaAutosize
|
|
197
|
-
{...props}
|
|
198
|
-
ref={this.initialize}
|
|
199
|
-
onChange={this.onChange}
|
|
200
|
-
value={this.state.text || value}
|
|
201
|
-
/>)
|
|
202
|
-
: (<textarea
|
|
203
|
-
{...props}
|
|
204
|
-
ref={this.initialize}
|
|
205
|
-
onChange={this.onChange}
|
|
206
|
-
value={this.state.text || value}
|
|
207
|
-
/>)
|
|
208
|
-
}
|
|
209
|
-
{searchResults}
|
|
210
|
-
</div>
|
|
211
|
-
);
|
|
212
|
-
}
|
|
213
|
-
};
|
package/styles.css
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
.textarea-suggest {
|
|
2
|
-
resize: none; }
|
|
3
|
-
.textarea-suggest--results {
|
|
4
|
-
position: absolute;
|
|
5
|
-
z-index: 150;
|
|
6
|
-
min-width: 220px;
|
|
7
|
-
margin: 0 16px;
|
|
8
|
-
animation: ascent .2s forwards;
|
|
9
|
-
border-radius: 9px;
|
|
10
|
-
background-color: #fff;
|
|
11
|
-
box-shadow: 0 3px 12px #c1c1c1; }
|
|
12
|
-
.textarea-suggest--info {
|
|
13
|
-
position: absolute;
|
|
14
|
-
bottom: 8px;
|
|
15
|
-
right: 8px; }
|
|
16
|
-
.textarea-suggest--info-item {
|
|
17
|
-
line-height: 20px;
|
|
18
|
-
margin: 16px 0; }
|
|
19
|
-
.textarea-suggest-item {
|
|
20
|
-
display: flex;
|
|
21
|
-
padding: 4px 8px 0; }
|
|
22
|
-
.textarea-suggest-item:first-child {
|
|
23
|
-
padding-top: 8px; }
|
|
24
|
-
.textarea-suggest-item:last-child {
|
|
25
|
-
padding-bottom: 8px; }
|
|
26
|
-
.textarea-suggest-item:hover {
|
|
27
|
-
background-color: #f2f3f9; }
|
|
28
|
-
.textarea-suggest-item--info {
|
|
29
|
-
margin-left: 8px; }
|