react-textarea-with-suggest 2.0.0 → 2.1.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 CHANGED
@@ -1,9 +1,11 @@
1
1
  # react-textarea-with-suggest
2
2
  Textarea with suggest for React app v2.0.0
3
3
 
4
- ### Last changes:
5
- - supports TypeScript and new React versions
6
- - fixed bug with installing
4
+ ### Last changes
5
+ [You can find in CHANGELOG.md](./CHANGELOG.md)
6
+
7
+ ### Demo
8
+ [You can try component here](https://marylorian.github.io/react-textarea-with-suggest/)
7
9
 
8
10
  ## Install
9
11
  If you use npm
@@ -16,6 +18,28 @@ yarn add react-textarea-with-suggest
16
18
  ```
17
19
 
18
20
  ## Usage
21
+
22
+ ### For functional component
23
+ ```
24
+ import Textarea from "react-textarea-with-suggest";
25
+
26
+ const MyApp = (props) => {
27
+ const [text, setText] = useState<string>("")
28
+ const { results, search } = useMyOwnSearchResults();
29
+
30
+ return <Textarea
31
+ className="myapp-textarea"
32
+ value={text}
33
+ onChange={({ target }) => setText({ target.value })}
34
+ onSearch={(searchPhrase) => search(searchPhrase)}
35
+ suggestList={results}
36
+ searchMarker="@"
37
+ autoFocus
38
+ />
39
+ }
40
+ ```
41
+
42
+ ### For class component
19
43
  ```
20
44
  import Textarea from "react-textarea-with-suggest";
21
45
  import { search } from "../actions"
@@ -40,31 +64,34 @@ export default class MyApp extends React.Component {
40
64
 
41
65
  |Name|Default value|Required|Description|
42
66
  |----|-------------|--------|-----------|
43
- |autosizable|bool: false|no|using [`<TextareaAutosize>`](https://www.npmjs.com/package/react-textarea-autosize) instead of `<textarea>` if true|
67
+ |autosizable|boolean: false|no|using [`<TextareaAutosize>`](https://www.npmjs.com/package/react-textarea-autosize) instead of `<textarea>` if true|
68
+ |value|string: ""|no|initial text value for `<textarea>`|
44
69
  |className|string: ""|no|className property for `<textarea>` element|
45
70
  |searchMarker|char: "@"|no|after this symbol will be inited search and onSearch function|
46
- |onChange|func: () => {}|yes|function on change value in textarea|
47
- |onSearch|func: () => {}|yes|function after input of searchMarker into textarea|
48
- |onSuggestItemRender|func|no|custom function for rendering each item in suggest|
71
+ |searchRegexp|string: /@([a-z0\d\-.]+[a-z\d])/gim|no|default RegExp to detect search phrase after searchMarker|
72
+ |closeSuggestOnFocusOut|boolean: false|no|closes suggest on `focusout` and returns back on `focusin`|
73
+ |cancelSearchOnFocusOut|boolean: false|no|cancelling search on `focusout`|
74
+ |onChange|func: (event: React.ChangeEvent) => {}|no|function on change value in textarea|
75
+ |onSearch|func: (searchPhrase: string) => {}|yes|function after input of searchMarker into textarea|
76
+ |suggestList|array: (string OR CustomType)[]: []|no|rendering suggest when suggestList isn't empty, items rendering in customSuggestItemRenderer function|
77
+ |customSuggestItemRenderer|func: (searchListItem: string OR CustomType) => ReactNode|no|custom function for rendering each item in suggest|
49
78
  ```
50
- //onSuggestItemRender
79
+ //customSuggestItemRenderer
51
80
 
52
- item =>
53
- <div className="textarea-suggest-item" onClick={() => this.setResult(item)}>
54
- <div className="textarea-suggest-item--info">
55
- <div>{item}</div>
81
+ (item) =>
82
+ <div className="textarea-suggest-item" onClick={myOwnClickHandler}>
83
+ <div className="textarea-suggest-item__info">
84
+ <div>{item.name}</div>
85
+ <div>{item.description}</div>
56
86
  </div>
57
87
  </div>
58
88
  ```
59
89
  |||||
60
90
  |----|-------------|--------|-----------|
61
- |searchRegexp|string: /@([a-z0\d\-.]+[a-z\d])/gim|no||
62
- |suggestList|array: []|no|rendering suggest when suggestList isn't empty, items rendering in onSuggestItemRender function|
63
- |value|string: ""|no|text value for `<textarea>`|
64
91
  |any else params for `<textarea>`| - | - |https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#Attributes|
65
92
 
66
93
  ## Using libraries
67
94
  - "react-textarea-autosize" (optionally)
68
95
 
69
96
  ## License
70
- Copyright (c) 2019 Maria Lobareva Licensed under the [The MIT License (MIT)](http://opensource.org/licenses/MIT).
97
+ Copyright (c) 2019 Mariia Lobareva Licensed under the [The MIT License (MIT)](http://opensource.org/licenses/MIT).
@@ -1,16 +1,19 @@
1
1
  {
2
2
  "name": "example",
3
3
  "version": "0.1.0",
4
- "private": true,
4
+ "homepage": "https://marylorian.github.io/react-textarea-with-suggest/",
5
5
  "dependencies": {
6
- "react": "^16.14.0",
7
- "react-dom": "^16.14.0",
6
+ "react": "^17.0.0",
7
+ "react-dom": "^17.0.0",
8
8
  "react-scripts": "5.0.1",
9
9
  "react-textarea-with-suggest": "latest"
10
10
  },
11
11
  "scripts": {
12
12
  "start": "react-scripts start",
13
- "test": "react-scripts test"
13
+ "test": "react-scripts test",
14
+ "build": "react-scripts build",
15
+ "predeploy": "npm run build",
16
+ "deploy": "gh-pages -d build"
14
17
  },
15
18
  "eslintConfig": {
16
19
  "extends": [
@@ -31,7 +34,7 @@
31
34
  ]
32
35
  },
33
36
  "devDependencies": {
34
- "lodash.once": "^4.1.1",
37
+ "gh-pages": "^4.0.0",
35
38
  "react-textarea-autosize": "^8.4.0"
36
39
  }
37
40
  }
@@ -1,5 +1,4 @@
1
1
  .example {
2
- text-align: center;
3
2
  font-family: Arial, Helvetica, sans-serif;
4
3
  }
5
4
 
@@ -12,4 +11,20 @@
12
11
  .example__textarea__results {
13
12
  border-radius: 4px;
14
13
  border: 1px solid;
14
+ background-color: white;
15
+ }
16
+
17
+ .example__textarea__custom-item {
18
+ cursor: pointer;
19
+ padding: 4px 8px;
20
+ font-size: 8px;
21
+ text-align: left;
22
+ }
23
+
24
+ .example__textarea__custom-item p {
25
+ margin: 0;
26
+ }
27
+
28
+ .example__textarea__custom-item:hover {
29
+ background-color: burlywood;
15
30
  }
@@ -41,32 +41,186 @@ function App() {
41
41
  return (
42
42
  <div className="example">
43
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
44
 
52
- <p>Autosizable</p>
53
- <Textarea
54
- autosizable
55
- className="example__textarea"
56
- onChange={onChange}
57
- onSearch={onSearch}
58
- suggestList={results}
59
- />
45
+ <div className="example__item">
46
+ <p>Default</p>
47
+ <p>
48
+ <code>
49
+ {`<Textarea
50
+ className="example__textarea"
51
+ onChange={onChange}
52
+ onSearch={onSearch}
53
+ suggestList={results}
54
+ />`}
55
+ </code>
56
+ </p>
57
+ <Textarea
58
+ className="example__textarea"
59
+ onChange={onChange}
60
+ onSearch={onSearch}
61
+ suggestList={results}
62
+ />
63
+ </div>
60
64
 
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
- />
65
+ <div className="example__item">
66
+ <p>Autosizable</p>
67
+ <p>
68
+ <code>
69
+ {`<Textarea
70
+ autosizable
71
+ className="example__textarea"
72
+ onChange={onChange}
73
+ onSearch={onSearch}
74
+ suggestList={results}
75
+ />`}
76
+ </code>
77
+ </p>
78
+ <Textarea
79
+ autosizable
80
+ className="example__textarea"
81
+ onChange={onChange}
82
+ onSearch={onSearch}
83
+ suggestList={results}
84
+ />
85
+ </div>
86
+
87
+ <div className="example__item">
88
+ <p>With initial value</p>
89
+ <p>
90
+ <code>
91
+ {`<Textarea
92
+ autosizable
93
+ className="example__textarea"
94
+ value="Initial Value"
95
+ onChange={onChange}
96
+ onSearch={onSearch}
97
+ suggestList={results}
98
+ />`}
99
+ </code>
100
+ </p>
101
+ <Textarea
102
+ autosizable
103
+ className="example__textarea"
104
+ value="Initial Value"
105
+ onChange={onChange}
106
+ onSearch={onSearch}
107
+ suggestList={results}
108
+ />
109
+ </div>
110
+
111
+ <div className="example__item">
112
+ <p>With customSuggestItemRenderer</p>
113
+ <p>
114
+ <code>
115
+ {`<Textarea
116
+ autosizable
117
+ className="example__textarea"
118
+ onChange={onChange}
119
+ onSearch={onSearch}
120
+ suggestList={results}
121
+ customSuggestItemRenderer={(result, defaultOnClick) => (
122
+ <div
123
+ className="example__textarea__custom-item"
124
+ onClick={defaultOnClick}
125
+ >
126
+ <p>
127
+ Custom: <span>{result}</span>
128
+ </p>
129
+ </div>
130
+ )}
131
+ />`}
132
+ </code>
133
+ </p>
134
+ <Textarea
135
+ autosizable
136
+ className="example__textarea"
137
+ onChange={onChange}
138
+ onSearch={onSearch}
139
+ suggestList={results}
140
+ customSuggestItemRenderer={(result, defaultOnClick) => (
141
+ <div
142
+ className="example__textarea__custom-item"
143
+ onClick={defaultOnClick}
144
+ >
145
+ <p>
146
+ Custom: <span>{result}</span>
147
+ </p>
148
+ </div>
149
+ )}
150
+ />
151
+ </div>
152
+
153
+ <div className="example__item">
154
+ <p>With custom searchMarker "#"</p>
155
+ <p>
156
+ <code>
157
+ {`<Textarea
158
+ autosizable
159
+ className="example__textarea"
160
+ onChange={onChange}
161
+ onSearch={onSearch}
162
+ suggestList={results}
163
+ searchMarker="#"
164
+ />`}
165
+ </code>
166
+ </p>
167
+ <Textarea
168
+ autosizable
169
+ className="example__textarea"
170
+ onChange={onChange}
171
+ onSearch={onSearch}
172
+ suggestList={results}
173
+ searchMarker="#"
174
+ />
175
+ </div>
176
+
177
+ <div className="example__item">
178
+ <p>Closes suggests on focusout, returns back on focusin</p>
179
+ <p>
180
+ <code>
181
+ {`<Textarea
182
+ autosizable
183
+ className="example__textarea"
184
+ onChange={onChange}
185
+ onSearch={onSearch}
186
+ suggestList={results}
187
+ closeSuggestOnFocusOut
188
+ />`}
189
+ </code>
190
+ </p>
191
+ <Textarea
192
+ autosizable
193
+ className="example__textarea"
194
+ onChange={onChange}
195
+ onSearch={onSearch}
196
+ suggestList={results}
197
+ closeSuggestOnFocusOut
198
+ />
199
+ </div>
200
+
201
+ <div className="example__item">
202
+ <p>Cancelling search on focusout</p>
203
+ <p>
204
+ <code>
205
+ {`<Textarea
206
+ autosizable
207
+ className="example__textarea"
208
+ onChange={onChange}
209
+ onSearch={onSearch}
210
+ suggestList={results}
211
+ cancelSearchOnFocusOut
212
+ />`}
213
+ </code>
214
+ </p>
215
+ <Textarea
216
+ autosizable
217
+ className="example__textarea"
218
+ onChange={onChange}
219
+ onSearch={onSearch}
220
+ suggestList={results}
221
+ cancelSearchOnFocusOut
222
+ />
223
+ </div>
70
224
  </div>
71
225
  );
72
226
  }
package/lib/index.d.ts CHANGED
@@ -7,18 +7,20 @@
7
7
  *
8
8
  * LICENSE MIT.
9
9
  */
10
- import React, { ReactNode } from "react";
10
+ import React, { ReactNode, HTMLProps, ChangeEvent } from "react";
11
11
  import "../styles.css";
12
- interface TextareaSuggestProps<SuggestItemType> {
12
+ interface TextareaSuggestProps<SuggestItemType> extends Partial<Omit<HTMLProps<HTMLTextAreaElement>, "style">> {
13
13
  className?: string;
14
14
  autosizable?: boolean;
15
15
  searchMarker?: string;
16
16
  searchRegexp?: RegExp;
17
17
  suggestList?: SuggestItemType[];
18
18
  value?: string;
19
- onChange?: Function;
20
- onSearch: Function;
21
- customSuggestItemRenderer?: (suggestItem: SuggestItemType, defaultOnClick: (item: SuggestItemType) => void) => ReactNode;
19
+ closeSuggestOnFocusOut?: boolean;
20
+ cancelSearchOnFocusOut?: boolean;
21
+ onChange?: (event: ChangeEvent<HTMLTextAreaElement>) => void;
22
+ onSearch: (newValue: string) => void;
23
+ customSuggestItemRenderer?: (suggestItem: SuggestItemType) => ReactNode;
22
24
  }
23
- declare const TextareaSuggest: <SuggestItemType extends React.ReactNode>({ autosizable, value, searchMarker, searchRegexp: searchRegexpProp, suggestList, onSearch, onChange, customSuggestItemRenderer, ...props }: TextareaSuggestProps<SuggestItemType>) => JSX.Element;
25
+ declare const TextareaSuggest: <SuggestItemType extends React.ReactNode>({ autosizable, value, searchMarker, searchRegexp: searchRegexpProp, suggestList, closeSuggestOnFocusOut, cancelSearchOnFocusOut, onSearch, onChange, customSuggestItemRenderer, ...props }: TextareaSuggestProps<SuggestItemType>) => JSX.Element;
24
26
  export default TextareaSuggest;
package/lib/index.js CHANGED
@@ -1,2 +1,2 @@
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)};
1
+ Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("react-textarea-autosize");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var a=n(e),r=n(t),o=function(){return o=Object.assign||function(e){for(var t,n=1,a=arguments.length;n<a;n++)for(var r in t=arguments[n])Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e},o.apply(this,arguments)};function i(t){var n=e.useRef();return e.useEffect((function(){n.current=t}),[t]),n.current}var c=function(t){var n=t.textareaRef,r=t.values,o=void 0===r?[]:r,i=t.isHidden,c=t.className,l=t.customSuggestItemRenderer,u=t.onItemClickHandler;if(i||!(null==o?void 0:o.length)||!n.current)return null;var s=e.useMemo((function(){var e;return(null===(e=n.current)||void 0===e?void 0:e.getBoundingClientRect())||{}}),[n.current]),d=s.width,m=void 0===d?0:d,f=s.left,v=void 0===f?0:f,g=e.useCallback((function(t){return l?a.default.createElement(e.Fragment,{onMouseDown:u(t)},l(t)):a.default.createElement("div",{className:"textarea-suggest-item",onMouseDown:u(t)},a.default.createElement("div",{className:"textarea-suggest-item__info"},a.default.createElement("div",null,t)))}),[u,l]);return a.default.createElement("div",{className:"textarea-suggest__results ".concat(c?"".concat(c,"__results"):""),style:{position:"absolute",width:m,left:v}},o.map((function(t,n){return a.default.createElement(e.Fragment,{key:n},g(t))})))},l=e.forwardRef((function(e,t){return a.default.createElement("textarea",o({},e,{ref:t}))}));exports.default=function(t){var n=t.autosizable,u=void 0!==n&&n,s=t.value,d=void 0===s?"":s,m=t.searchMarker,f=void 0===m?"@":m,v=t.searchRegexp,g=t.suggestList,p=void 0===g?[]:g,b=t.closeSuggestOnFocusOut,h=void 0!==b&&b,w=t.cancelSearchOnFocusOut,k=void 0!==w&&w,x=t.onSearch,y=t.onChange,O=t.customSuggestItemRenderer,E=function(e,t){var n={};for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&t.indexOf(a)<0&&(n[a]=e[a]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var r=0;for(a=Object.getOwnPropertySymbols(e);r<a.length;r++)t.indexOf(a[r])<0&&Object.prototype.propertyIsEnumerable.call(e,a[r])&&(n[a[r]]=e[a[r]])}return n}(t,["autosizable","value","searchMarker","searchRegexp","suggestList","closeSuggestOnFocusOut","cancelSearchOnFocusOut","onSearch","onChange","customSuggestItemRenderer"]),S=e.useState(d),z=S[0],R=S[1],j=e.useState(null==d?void 0:d.includes(f)),I=j[0],_=j[1],C=e.useState(!0),M=C[0],F=C[1],q=i(z),N=i(d),P=e.useRef(null),T=u?r.default:l,B=e.useMemo((function(){return v?new RegExp(v):new RegExp("".concat(f,"([a-z0-9-_.]+[a-z0-9])"),"gim")}),[v]);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(){q!==d&&N!==d&&R(d)}),[z,d,q,N]);var H=e.useCallback((function(e){return setTimeout((function(){var t;h&&F(!0),k&&_(!1),null===(t=E.onBlur)||void 0===t||t.call(E,e)}),0)}),[h,k,E.onBlur]),D=e.useCallback((function(e){var t;M&&F(!1),null===(t=E.onFocus)||void 0===t||t.call(E,e)}),[h,k,E.onFocus]),L=e.useCallback((function(e){return function(){var t,n,a,r,o=null===(t=P.current)||void 0===t?void 0:t.selectionEnd,i=z.slice(0,o).lastIndexOf(f),c=z.slice(i);if(-1!==i){var l=(c.includes(" ")?c.indexOf(" "):z.length)+i,u=void 0;if(c.lastIndexOf(f)>0&&(l=c.lastIndexOf(f)+i),(!l||l<i)&&(l=z.length),u=z.slice(0,i||0)+z.slice(i).replace(z.slice(i,l),"".concat(f).concat(e," ")),P.current&&(P.current.value=u,P.current.focus()),function(){if("undefined"==typeof navigator||"undefined"==typeof window)return!1;var e,t=!1;return e=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(e)||/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(e.substr(0,4)))&&(t=!0),t}()){var s=u.slice(i).indexOf(" ")+i+1;null===(n=P.current)||void 0===n||n.setSelectionRange(s,s)}var d=new Event("onchange",{bubbles:!0,cancelable:!1});null===(r=null===(a=P.current)||void 0===a?void 0:a.onchange)||void 0===r||r.call(a,d),_(!1),R(u)}}}),[P,z]);return a.default.createElement("div",{className:"textarea-suggest"},a.default.createElement(T,o({},E,{onBlur:H,onFocus:D,ref:P,onChange:function(e){var t,n=e.currentTarget.value,a=void 0===n?z:n,r=e.isTrusted,i=void 0===r||r,c=null===(t=P.current)||void 0===t?void 0:t.selectionEnd,l=c?a.slice(c-1,c):a.slice(-1);if(R(a),l===f&&_(!0),a.includes(f)&&![" ","\n","\r"].includes(l)||!I||_(!1),l!==f&&I){var u=a.slice(0,c),s=u.slice(u.lastIndexOf(f)).match(B),d=s?s[0].slice(1):l;x(d)}return i?null==y?void 0:y(e):null==y?void 0:y(o(o({},e),{currentTarget:P.current,target:P.current}))},value:z||d})),a.default.createElement(c,{className:E.className,textareaRef:P,values:p,isHidden:M||!I,customSuggestItemRenderer:O,onItemClickHandler:L}))};
2
2
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,12 @@
1
+ import React, { ReactNode, RefObject } from "react";
2
+ import { Nullable } from "./utils";
3
+ interface SuggestProps<T> {
4
+ className?: string;
5
+ textareaRef: RefObject<Nullable<HTMLTextAreaElement>>;
6
+ values: T[];
7
+ isHidden?: boolean;
8
+ onItemClickHandler: (item: T) => () => void;
9
+ customSuggestItemRenderer?: (item: T) => ReactNode;
10
+ }
11
+ export declare const SuggestResults: <T extends React.ReactNode>({ textareaRef, values, isHidden, className, customSuggestItemRenderer, onItemClickHandler, }: SuggestProps<T>) => JSX.Element | null;
12
+ export {};
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "react-textarea-with-suggest",
3
- "version": "2.0.0",
3
+ "version": "2.1.1",
4
4
  "description": "Textarea with suggest for React app",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
7
7
  "dependencies": {
8
- "react-scripts": "^5.0.1",
9
8
  "react-textarea-autosize": "^8.4.0"
10
9
  },
11
10
  "files": [
@@ -16,8 +15,7 @@
16
15
  "prettier": "prettier --write .",
17
16
  "build:debug": "npm install && npm run build && rm -rf node_modules",
18
17
  "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"
18
+ "start": "rollup -c -w"
21
19
  },
22
20
  "license": "MIT",
23
21
  "eslintConfig": {
@@ -80,15 +78,12 @@
80
78
  "@rollup/plugin-babel": "^6.0.3",
81
79
  "@rollup/plugin-terser": "^0.2.1",
82
80
  "@rollup/plugin-typescript": "^10.0.1",
83
- "@types/lodash.once": "^4.1.7",
84
81
  "@types/react": "^18.0.26",
85
- "babel-core": "^6.26.3",
86
82
  "babel-loader": "^8.0.6",
87
83
  "css-loader": "^6.7.3",
88
84
  "prettier": "2.7.1",
89
85
  "rollup": "^2.79.1",
90
86
  "rollup-plugin-css-only": "^4.3.0",
91
- "terser": "^5.16.1",
92
87
  "typescript": "^4.9.4",
93
88
  "webpack": "^5.75.0",
94
89
  "webpack-cli": "^5.0.1",