Skip to content

Commit dd32e09

Browse files
authored
fix: multichar tigger with allowWhitespace (#199)
1 parent 8a38530 commit dd32e09

File tree

1 file changed

+75
-66
lines changed

1 file changed

+75
-66
lines changed

src/Textarea.jsx

Lines changed: 75 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,20 @@ import type {
1818
caretPositionType,
1919
outputType,
2020
triggerType,
21-
settingType
21+
settingType,
2222
} from "./types";
2323

2424
const DEFAULT_CARET_POSITION = "next";
2525

2626
const POSITION_CONFIGURATION = {
2727
X: {
2828
LEFT: "rta__autocomplete--left",
29-
RIGHT: "rta__autocomplete--right"
29+
RIGHT: "rta__autocomplete--right",
3030
},
3131
Y: {
3232
TOP: "rta__autocomplete--top",
33-
BOTTOM: "rta__autocomplete--bottom"
34-
}
33+
BOTTOM: "rta__autocomplete--bottom",
34+
},
3535
};
3636

3737
const errorMessage = (message: string) =>
@@ -41,29 +41,29 @@ const errorMessage = (message: string) =>
4141
);
4242

4343
const reservedRegexChars = [
44-
'.',
45-
'^',
46-
'$',
47-
'*',
48-
'+',
49-
'-',
50-
'?',
51-
'(',
52-
')',
53-
'[',
54-
']',
55-
'{',
56-
'}',
57-
'\\',
58-
'|',
59-
]
60-
61-
const escapeRegex = text =>
44+
".",
45+
"^",
46+
"$",
47+
"*",
48+
"+",
49+
"-",
50+
"?",
51+
"(",
52+
")",
53+
"[",
54+
"]",
55+
"{",
56+
"}",
57+
"\\",
58+
"|",
59+
];
60+
61+
const escapeRegex = (text) =>
6262
[...text]
63-
.map(character =>
63+
.map((character) =>
6464
reservedRegexChars.includes(character) ? `\\${character}` : character
6565
)
66-
.join('')
66+
.join("");
6767

6868
// The main purpose of this component is to figure out to which side the autocomplete should be opened
6969
type AutocompleteProps = {
@@ -75,7 +75,7 @@ type AutocompleteProps = {
7575
left: ?number,
7676
children: *,
7777
textareaRef: HTMLElement,
78-
renderToBody: ?boolean
78+
renderToBody: ?boolean,
7979
};
8080

8181
class Autocomplete extends React.Component<AutocompleteProps> {
@@ -192,7 +192,7 @@ class Autocomplete extends React.Component<AutocompleteProps> {
192192
const body = document.body;
193193
const autocompleteContainer = (
194194
<div
195-
ref={ref => {
195+
ref={(ref) => {
196196
// $FlowFixMe
197197
this.ref = ref;
198198
// $FlowFixMe
@@ -222,7 +222,7 @@ class ReactTextareaAutocomplete extends React.Component<
222222
boundariesElement: "body",
223223
scrollToItem: true,
224224
textAreaComponent: "textarea",
225-
renderToBody: false
225+
renderToBody: false,
226226
};
227227

228228
constructor(props: TextareaProps) {
@@ -253,7 +253,7 @@ class ReactTextareaAutocomplete extends React.Component<
253253
dataLoading: false,
254254
selectionEnd: 0,
255255
component: null,
256-
textToReplace: null
256+
textToReplace: null,
257257
};
258258

259259
escListenerInit = () => {
@@ -296,7 +296,7 @@ class ReactTextareaAutocomplete extends React.Component<
296296
if (value === null || value === undefined) return null;
297297

298298
return {
299-
value
299+
value,
300300
};
301301
}
302302

@@ -314,13 +314,13 @@ class ReactTextareaAutocomplete extends React.Component<
314314

315315
getSelectionPosition = (): ?{|
316316
selectionStart: number,
317-
selectionEnd: number
317+
selectionEnd: number,
318318
|} => {
319319
if (!this.textareaRef) return null;
320320

321321
return {
322322
selectionStart: this.textareaRef.selectionStart,
323-
selectionEnd: this.textareaRef.selectionEnd
323+
selectionEnd: this.textareaRef.selectionEnd,
324324
};
325325
};
326326

@@ -407,7 +407,7 @@ class ReactTextareaAutocomplete extends React.Component<
407407
if (onItemSelected) {
408408
onItemSelected({
409409
currentTrigger,
410-
item
410+
item,
411411
});
412412
}
413413

@@ -464,7 +464,7 @@ class ReactTextareaAutocomplete extends React.Component<
464464
this.setState(
465465
{
466466
value: newValue,
467-
dataLoading: false
467+
dataLoading: false,
468468
},
469469
() => {
470470
const insertedTrigger = this.tokenRegExpEnding.exec(newTokenString);
@@ -526,7 +526,7 @@ class ReactTextareaAutocomplete extends React.Component<
526526
if (typeof textToReplace === "string") {
527527
return {
528528
text: textToReplace,
529-
caretPosition: DEFAULT_CARET_POSITION
529+
caretPosition: DEFAULT_CARET_POSITION,
530530
};
531531
}
532532

@@ -551,7 +551,7 @@ class ReactTextareaAutocomplete extends React.Component<
551551

552552
return {
553553
text: `${currentTrigger}${item}${currentTrigger}`,
554-
caretPosition: DEFAULT_CARET_POSITION
554+
caretPosition: DEFAULT_CARET_POSITION,
555555
};
556556
};
557557
};
@@ -579,7 +579,7 @@ class ReactTextareaAutocomplete extends React.Component<
579579
}
580580

581581
this.setState({
582-
dataLoading: true
582+
dataLoading: true,
583583
});
584584

585585
let providedData = dataProvider(actualToken);
@@ -589,7 +589,7 @@ class ReactTextareaAutocomplete extends React.Component<
589589
}
590590

591591
providedData
592-
.then(data => {
592+
.then((data) => {
593593
if (!Array.isArray(data)) {
594594
throw new Error("Trigger provider has to provide an array!");
595595
}
@@ -610,10 +610,10 @@ class ReactTextareaAutocomplete extends React.Component<
610610
this.setState({
611611
dataLoading: false,
612612
data,
613-
component
613+
component,
614614
});
615615
})
616-
.catch(e => errorMessage(e.message));
616+
.catch((e) => errorMessage(e.message));
617617
};
618618

619619
_getSuggestions = (): ?Array<Object | string> => {
@@ -641,7 +641,7 @@ class ReactTextareaAutocomplete extends React.Component<
641641
}
642642
return 0;
643643
})
644-
.map(a => escapeRegex(a))
644+
.map((a) => escapeRegex(a))
645645
.join("|")})((?:(?!\\1)[^\\s])*$)`
646646
);
647647

@@ -657,9 +657,11 @@ class ReactTextareaAutocomplete extends React.Component<
657657
}
658658
return 0;
659659
})
660-
.map(a => escapeRegex(a))
660+
.map((a) => escapeRegex(a))
661661
.join("|")})$`
662662
);
663+
664+
console.log(this.tokenRegExpEnding);
663665
};
664666

665667
/**
@@ -668,13 +670,16 @@ class ReactTextareaAutocomplete extends React.Component<
668670
_closeAutocomplete = () => {
669671
const { currentTrigger } = this.state;
670672
this.escListenerDestroy();
671-
this.setState({
672-
data: null,
673-
dataLoading: false,
674-
currentTrigger: null
675-
}, () => {
676-
if(currentTrigger) this._onItemHighlightedHandler(null);
677-
});
673+
this.setState(
674+
{
675+
data: null,
676+
dataLoading: false,
677+
currentTrigger: null,
678+
},
679+
() => {
680+
if (currentTrigger) this._onItemHighlightedHandler(null);
681+
}
682+
);
678683
};
679684

680685
_cleanUpProps = (): Object => {
@@ -707,7 +712,7 @@ class ReactTextareaAutocomplete extends React.Component<
707712
"textAreaComponent",
708713
"renderToBody",
709714
"onItemSelected",
710-
"onItemHighlighted"
715+
"onItemHighlighted",
711716
];
712717

713718
// eslint-disable-next-line
@@ -724,7 +729,7 @@ class ReactTextareaAutocomplete extends React.Component<
724729
onChange,
725730
minChar,
726731
onCaretPositionChange,
727-
movePopupAsYouType
732+
movePopupAsYouType,
728733
} = this.props;
729734
const { top, left } = this.state;
730735

@@ -751,7 +756,7 @@ class ReactTextareaAutocomplete extends React.Component<
751756
}
752757

753758
this.setState({
754-
value
759+
value,
755760
});
756761

757762
const setTopLeft = () => {
@@ -763,11 +768,11 @@ class ReactTextareaAutocomplete extends React.Component<
763768
this.setState({
764769
// make position relative to textarea
765770
top: newTop - this.textareaRef.scrollTop || 0,
766-
left: newLeft
771+
left: newLeft,
767772
});
768773
};
769774

770-
const cleanLastTrigger = triggerLength => {
775+
const cleanLastTrigger = (triggerLength) => {
771776
this.lastTrigger = selectionEnd - triggerLength;
772777

773778
this._closeAutocomplete();
@@ -839,9 +844,9 @@ class ReactTextareaAutocomplete extends React.Component<
839844
this.state.currentTrigger &&
840845
trigger[this.state.currentTrigger].allowWhitespace
841846
) {
842-
tokenMatch = new RegExp(`${escapeRegex(this.state.currentTrigger)}.*$`).exec(
843-
value.slice(0, selectionEnd)
844-
);
847+
tokenMatch = new RegExp(
848+
`${escapeRegex(this.state.currentTrigger)}.*$`
849+
).exec(value.slice(0, selectionEnd));
845850
lastToken = tokenMatch && tokenMatch[0];
846851

847852
if (!lastToken) {
@@ -850,7 +855,11 @@ class ReactTextareaAutocomplete extends React.Component<
850855
}
851856

852857
currentTrigger =
853-
Object.keys(trigger).find(a => a === lastToken[0]) || null;
858+
Object.keys(trigger).find(
859+
(a) =>
860+
a.slice(0, currentTriggerLength + 1) ===
861+
lastToken.slice(0, currentTriggerLength + 1)
862+
) || null;
854863
}
855864

856865
const actualToken = lastToken.slice(1);
@@ -878,7 +887,7 @@ class ReactTextareaAutocomplete extends React.Component<
878887
selectionEnd,
879888
currentTrigger,
880889
textToReplace,
881-
actualToken
890+
actualToken,
882891
},
883892
() => {
884893
try {
@@ -958,14 +967,14 @@ class ReactTextareaAutocomplete extends React.Component<
958967
_onItemHighlightedHandler = (item: Object | string | null) => {
959968
const { onItemHighlighted } = this.props;
960969
const { currentTrigger } = this.state;
961-
if(onItemHighlighted) {
962-
if(typeof onItemHighlighted === "function") {
963-
onItemHighlighted({currentTrigger, item});
970+
if (onItemHighlighted) {
971+
if (typeof onItemHighlighted === "function") {
972+
onItemHighlighted({ currentTrigger, item });
964973
} else {
965974
throw new Error("`onItemHighlighted` has to be a function");
966975
}
967976
}
968-
}
977+
};
969978

970979
_dropdownScroll = (item: HTMLDivElement) => {
971980
const { scrollToItem } = this.props;
@@ -1034,15 +1043,15 @@ class ReactTextareaAutocomplete extends React.Component<
10341043
loaderStyle,
10351044
loaderClassName,
10361045
textAreaComponent,
1037-
renderToBody
1046+
renderToBody,
10381047
} = this.props;
10391048
const {
10401049
left,
10411050
top,
10421051
dataLoading,
10431052
component,
10441053
value,
1045-
textToReplace
1054+
textToReplace,
10461055
} = this.state;
10471056

10481057
const isAutocompleteOpen = this._isAutocompleteOpen();
@@ -1081,7 +1090,7 @@ class ReactTextareaAutocomplete extends React.Component<
10811090
/>
10821091
{isAutocompleteOpen && (
10831092
<Autocomplete
1084-
innerRef={ref => {
1093+
innerRef={(ref) => {
10851094
// $FlowFixMe
10861095
this.dropdownRef = ref;
10871096
}}
@@ -1164,7 +1173,7 @@ const triggerPropsCheck = ({ trigger }: { trigger: triggerType }) => {
11641173
dataProvider,
11651174
output,
11661175
afterWhitespace,
1167-
allowWhitespace
1176+
allowWhitespace,
11681177
} = triggerSetting;
11691178

11701179
if (!component || typeof component !== "function") {

0 commit comments

Comments
 (0)