From 4dd761770a6921880cc715169d4d2fc9a57e96cd Mon Sep 17 00:00:00 2001
From: 07akioni <07akioni2@gmail.com>
Date: Thu, 18 Jun 2020 10:57:03 +0800
Subject: [PATCH 01/10] fix: can't separate input when mode=tags and open=false
---
examples/tags.tsx | 30 ++++++++++++++++++++-
src/Selector/MultipleSelector.tsx | 2 +-
tests/Multiple.test.tsx | 44 ++++++++++++++++++++++++++++++-
3 files changed, 73 insertions(+), 3 deletions(-)
diff --git a/examples/tags.tsx b/examples/tags.tsx
index 5e8d67af5..3e2763189 100644
--- a/examples/tags.tsx
+++ b/examples/tags.tsx
@@ -44,7 +44,7 @@ const Test: React.FC = () => {
onDeselect={(val, option) => {
console.log('deselected', val, option);
}}
- tokenSeparators={[' ', ',', '\n']}
+ tokenSeparators={[' ', ',']}
onFocus={() => console.log('focus')}
onBlur={() => console.log('blur')}
>
@@ -70,6 +70,34 @@ const Test: React.FC = () => {
toggle maxTagCount (null)
+ tags select with open = false
+
+
+
);
};
diff --git a/src/Selector/MultipleSelector.tsx b/src/Selector/MultipleSelector.tsx
index 7e0b6b29f..43eea3a6f 100644
--- a/src/Selector/MultipleSelector.tsx
+++ b/src/Selector/MultipleSelector.tsx
@@ -74,7 +74,7 @@ const SelectSelector: React.FC = props => {
}, []);
// ===================== Search ======================
- const inputValue = open ? searchValue : '';
+ const inputValue = open || mode === 'tags' ? searchValue : '';
const inputEditable: boolean = mode === 'tags' || (open && showSearch);
// We measure width and set to the input immediately
diff --git a/tests/Multiple.test.tsx b/tests/Multiple.test.tsx
index 10bdbbd3c..bcb014495 100644
--- a/tests/Multiple.test.tsx
+++ b/tests/Multiple.test.tsx
@@ -79,7 +79,49 @@ describe('Select.Multiple', () => {
expectOpen(wrapper, false);
});
- it(`shouldn't separate words when compositing`, () => {
+ it('tokenize input when mode=tags and open=false', () => {
+ const handleChange = jest.fn();
+ const handleSelect = jest.fn();
+ const wrapper = mount(
+ ,
+ );
+
+ wrapper.find('input').simulate('change', {
+ target: {
+ value: 'One',
+ },
+ });
+ expect(handleChange).not.toHaveBeenCalled();
+
+ handleChange.mockReset();
+ wrapper.find('input').simulate('change', {
+ target: {
+ value: 'One,Two,Three,',
+ },
+ });
+ expect(handleChange).toHaveBeenCalledWith(['One', 'Two', 'Three'], expect.anything());
+
+ handleChange.mockReset();
+ wrapper.find('input').simulate('change', {
+ target: {
+ value: 'One,Two,',
+ },
+ });
+ expect(handleChange).toHaveBeenCalledWith(['One', 'Two', 'Three'], expect.anything());
+
+ expect(wrapper.find('input').props().value).toBe('');
+ });
+
+ it('shouldn\'t separate words when compositing', () => {
const handleChange = jest.fn();
const handleSelect = jest.fn();
const wrapper = mount(
From 6795251ca4dd5cecc82a6f02219f9bba052d9d73 Mon Sep 17 00:00:00 2001
From: 07akioni <07akioni2@gmail.com>
Date: Thu, 18 Jun 2020 12:04:02 +0800
Subject: [PATCH 02/10] chore
---
index.js | 2 --
1 file changed, 2 deletions(-)
diff --git a/index.js b/index.js
index 3151c2a2a..fd4d7e5cf 100644
--- a/index.js
+++ b/index.js
@@ -1,3 +1 @@
-'use strict';
-
module.exports = require('./src/');
From d87b0467e2c9e78cfe64ed528c50978681a7ddde Mon Sep 17 00:00:00 2001
From: 07akioni <07akioni2@gmail.com>
Date: Sun, 28 Jun 2020 15:19:02 +0800
Subject: [PATCH 03/10] fix: keydown enter not work on tags mode when closed
---
examples/tags.tsx | 2 +-
src/Selector/index.tsx | 6 ++++++
src/generate.tsx | 15 +++++++++++++++
tests/Tags.test.tsx | 37 ++++++++++++++++++++++++++++++-------
4 files changed, 52 insertions(+), 8 deletions(-)
diff --git a/examples/tags.tsx b/examples/tags.tsx
index 3e2763189..20368ce26 100644
--- a/examples/tags.tsx
+++ b/examples/tags.tsx
@@ -44,7 +44,7 @@ const Test: React.FC = () => {
onDeselect={(val, option) => {
console.log('deselected', val, option);
}}
- tokenSeparators={[' ', ',']}
+ tokenSeparators={[' ', ',', '\n']}
onFocus={() => console.log('focus')}
onBlur={() => console.log('blur')}
>
diff --git a/src/Selector/index.tsx b/src/Selector/index.tsx
index 698896de9..19ead600b 100644
--- a/src/Selector/index.tsx
+++ b/src/Selector/index.tsx
@@ -78,6 +78,7 @@ export interface SelectorProps {
onToggleOpen: (open?: boolean) => void;
/** `onSearch` returns go next step boolean to check if need do toggle open */
onSearch: (searchText: string, fromTyping: boolean, isCompositing: boolean) => boolean;
+ onSearchEnter: (searchText: string, isCompositing: boolean) => void;
onSelect: (value: RawValueType, option: { selected: boolean }) => void;
onInputKeyDown?: React.KeyboardEventHandler;
@@ -100,6 +101,7 @@ const Selector: React.RefForwardingComponent =
showSearch,
onSearch,
+ onSearchEnter,
onToggleOpen,
onInputKeyDown,
@@ -130,6 +132,10 @@ const Selector: React.RefForwardingComponent =
onInputKeyDown(event);
}
+ if (which === KeyCode.ENTER) {
+ onSearchEnter((event.target as HTMLInputElement).value, compositionStatusRef.current);
+ }
+
if (![KeyCode.SHIFT, KeyCode.TAB, KeyCode.BACKSPACE, KeyCode.ESC].includes(which)) {
onToggleOpen(true);
}
diff --git a/src/generate.tsx b/src/generate.tsx
index 5336b1bfb..eebdbfaa5 100644
--- a/src/generate.tsx
+++ b/src/generate.tsx
@@ -673,6 +673,20 @@ export default function generateSelector<
return ret;
};
+ // Menu closed & mode is tags
+ const onSearchEnter =
+ mode === 'tags' && !mergedOpen
+ ? (searchText: string, isCompositing: boolean) => {
+ if (isCompositing) return;
+ const newRawValues = Array.from(new Set([...mergedRawValue, searchText]));
+ triggerChange(newRawValues);
+ newRawValues.forEach(newRawValue => {
+ triggerSelect(newRawValue, true, 'input');
+ });
+ setInnerSearchValue('');
+ }
+ : () => {};
+
// Close dropdown when disabled change
useEffect(() => {
if (innerOpen && !!disabled) {
@@ -1014,6 +1028,7 @@ export default function generateSelector<
searchValue={mergedSearchValue}
activeValue={activeValue}
onSearch={triggerSearch}
+ onSearchEnter={onSearchEnter}
onSelect={onInternalSelectionSelect}
/>
diff --git a/tests/Tags.test.tsx b/tests/Tags.test.tsx
index fea2d30af..b016e1fd4 100644
--- a/tests/Tags.test.tsx
+++ b/tests/Tags.test.tsx
@@ -73,8 +73,6 @@ describe('Select.Tags', () => {
,
);
- (wrapper.find('input').instance() as any).focus = jest.fn();
-
wrapper.find('input').simulate('change', { target: { value: '2,3,4' } });
expect(handleChange).toHaveBeenCalledWith(['2', '3', '4'], expect.anything());
@@ -90,15 +88,13 @@ describe('Select.Tags', () => {
it("shounld't separate words when compositing", () => {
const handleChange = jest.fn();
const handleSelect = jest.fn();
- const option2 = ;
const wrapper = mount(
,
);
- (wrapper.find('input').instance() as any).focus = jest.fn();
wrapper.find('input').simulate('compositionstart');
wrapper.find('input').simulate('change', { target: { value: '2,3,4' } });
expect(handleChange).not.toHaveBeenCalled();
@@ -115,6 +111,35 @@ describe('Select.Tags', () => {
expectOpen(wrapper, false);
});
+ it('should work when menu is closed', () => {
+ const handleChange = jest.fn();
+ const handleSelect = jest.fn();
+ const wrapper = mount(
+ ,
+ );
+ wrapper.find('input').simulate('compositionstart');
+ wrapper.find('input').simulate('change', { target: { value: 'Star Kirby' } });
+ wrapper.find('input').simulate('keydown', { which: KeyCode.ENTER });
+ expect(handleChange).not.toHaveBeenCalled();
+ handleChange.mockReset();
+ wrapper.find('input').simulate('compositionend');
+ wrapper.find('input').simulate('keydown', { which: KeyCode.ENTER });
+ expect(handleChange).toHaveBeenCalledWith(['Star Kirby'], expect.anything());
+ expect(handleSelect).toHaveBeenCalledTimes(1);
+ expect(findSelection(wrapper).text()).toEqual('Star Kirby');
+ expect(wrapper.find('input').props().value).toBe('');
+ expectOpen(wrapper, false);
+ });
+
it('paste content to split', () => {
const onChange = jest.fn();
const wrapper = mount(
@@ -221,8 +246,6 @@ describe('Select.Tags', () => {
};
const wrapper = mount();
- (wrapper.find('input').instance() as any).focus = jest.fn();
-
wrapper.find('input').simulate('change', { target: { value: '1,A,42' } });
expect(wrapper.find('span.A').length).toBe(1);
From 59612d607f932f0178579f6a7712a076883d9967 Mon Sep 17 00:00:00 2001
From: 07akioni <07akioni2@gmail.com>
Date: Sun, 28 Jun 2020 15:33:32 +0800
Subject: [PATCH 04/10] chore: use esm in entry
---
index.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/index.js b/index.js
index fd4d7e5cf..6f39cd49b 100644
--- a/index.js
+++ b/index.js
@@ -1 +1 @@
-module.exports = require('./src/');
+export * from './src'
From d0f9ff7bf8fddda0529662ab031748d599197865 Mon Sep 17 00:00:00 2001
From: 07akioni <07akioni2@gmail.com>
Date: Mon, 29 Jun 2020 13:23:16 +0800
Subject: [PATCH 05/10] fix: export default
---
index.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/index.js b/index.js
index 6f39cd49b..9b28da199 100644
--- a/index.js
+++ b/index.js
@@ -1 +1,2 @@
-export * from './src'
+export * from './src';
+export { default } from './src';
From 91b21a715e22ea46fe5767e51a239c725c681a17 Mon Sep 17 00:00:00 2001
From: 07akioni <07akioni2@gmail.com>
Date: Mon, 29 Jun 2020 14:10:18 +0800
Subject: [PATCH 06/10] refactor
---
index.js | 2 --
src/Selector/index.tsx | 8 ++++----
src/generate.tsx | 26 ++++++++++++--------------
3 files changed, 16 insertions(+), 20 deletions(-)
delete mode 100644 index.js
diff --git a/index.js b/index.js
deleted file mode 100644
index 9b28da199..000000000
--- a/index.js
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from './src';
-export { default } from './src';
diff --git a/src/Selector/index.tsx b/src/Selector/index.tsx
index 19ead600b..dfd5d7bfb 100644
--- a/src/Selector/index.tsx
+++ b/src/Selector/index.tsx
@@ -78,7 +78,7 @@ export interface SelectorProps {
onToggleOpen: (open?: boolean) => void;
/** `onSearch` returns go next step boolean to check if need do toggle open */
onSearch: (searchText: string, fromTyping: boolean, isCompositing: boolean) => boolean;
- onSearchEnter: (searchText: string, isCompositing: boolean) => void;
+ onSearchSubmit: (searchText: string) => void;
onSelect: (value: RawValueType, option: { selected: boolean }) => void;
onInputKeyDown?: React.KeyboardEventHandler;
@@ -101,7 +101,7 @@ const Selector: React.RefForwardingComponent =
showSearch,
onSearch,
- onSearchEnter,
+ onSearchSubmit,
onToggleOpen,
onInputKeyDown,
@@ -132,8 +132,8 @@ const Selector: React.RefForwardingComponent =
onInputKeyDown(event);
}
- if (which === KeyCode.ENTER) {
- onSearchEnter((event.target as HTMLInputElement).value, compositionStatusRef.current);
+ if (which === KeyCode.ENTER && mode === 'tags' && !compositionStatusRef.current && !open) {
+ onSearchSubmit((event.target as HTMLInputElement).value);
}
if (![KeyCode.SHIFT, KeyCode.TAB, KeyCode.BACKSPACE, KeyCode.ESC].includes(which)) {
diff --git a/src/generate.tsx b/src/generate.tsx
index eebdbfaa5..522d2edcb 100644
--- a/src/generate.tsx
+++ b/src/generate.tsx
@@ -673,19 +673,17 @@ export default function generateSelector<
return ret;
};
- // Menu closed & mode is tags
- const onSearchEnter =
- mode === 'tags' && !mergedOpen
- ? (searchText: string, isCompositing: boolean) => {
- if (isCompositing) return;
- const newRawValues = Array.from(new Set([...mergedRawValue, searchText]));
- triggerChange(newRawValues);
- newRawValues.forEach(newRawValue => {
- triggerSelect(newRawValue, true, 'input');
- });
- setInnerSearchValue('');
- }
- : () => {};
+ // Only triggered when menu is closed & mode is tags
+ // If mode isn't tag, press enter is not meaningful
+ // If menu is open, OptionList will take charge
+ const onSearchSubmit = (searchText: string) => {
+ const newRawValues = Array.from(new Set([...mergedRawValue, searchText]));
+ triggerChange(newRawValues);
+ newRawValues.forEach(newRawValue => {
+ triggerSelect(newRawValue, true, 'input');
+ });
+ setInnerSearchValue('');
+ };
// Close dropdown when disabled change
useEffect(() => {
@@ -1028,7 +1026,7 @@ export default function generateSelector<
searchValue={mergedSearchValue}
activeValue={activeValue}
onSearch={triggerSearch}
- onSearchEnter={onSearchEnter}
+ onSearchSubmit={onSearchSubmit}
onSelect={onInternalSelectionSelect}
/>
From bcb57a1bb2ec9f860f2ff99da03a303ab9c80b4f Mon Sep 17 00:00:00 2001
From: 07akioni <07akioni2@gmail.com>
Date: Mon, 29 Jun 2020 14:12:44 +0800
Subject: [PATCH 07/10] chore
---
src/generate.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/generate.tsx b/src/generate.tsx
index 522d2edcb..d8630301f 100644
--- a/src/generate.tsx
+++ b/src/generate.tsx
@@ -674,8 +674,8 @@ export default function generateSelector<
};
// Only triggered when menu is closed & mode is tags
- // If mode isn't tag, press enter is not meaningful
// If menu is open, OptionList will take charge
+ // If mode isn't tags, press enter is not meaningful
const onSearchSubmit = (searchText: string) => {
const newRawValues = Array.from(new Set([...mergedRawValue, searchText]));
triggerChange(newRawValues);
From 70f1da0117fd97f7e55c83c1da0d526242c0ff38 Mon Sep 17 00:00:00 2001
From: 07akioni <07akioni2@gmail.com>
Date: Mon, 29 Jun 2020 14:15:00 +0800
Subject: [PATCH 08/10] chore
---
src/generate.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/generate.tsx b/src/generate.tsx
index d8630301f..cf0631288 100644
--- a/src/generate.tsx
+++ b/src/generate.tsx
@@ -675,7 +675,7 @@ export default function generateSelector<
// Only triggered when menu is closed & mode is tags
// If menu is open, OptionList will take charge
- // If mode isn't tags, press enter is not meaningful
+ // If mode isn't tags, press enter is not meaningful when you can't see any option
const onSearchSubmit = (searchText: string) => {
const newRawValues = Array.from(new Set([...mergedRawValue, searchText]));
triggerChange(newRawValues);
From 840e9a24790f4bdf7feb240701ea3dbfee42d8e2 Mon Sep 17 00:00:00 2001
From: 07akioni <07akioni2@gmail.com>
Date: Mon, 29 Jun 2020 14:20:52 +0800
Subject: [PATCH 09/10] chore: comments
---
src/Selector/index.tsx | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/Selector/index.tsx b/src/Selector/index.tsx
index dfd5d7bfb..9df0ae193 100644
--- a/src/Selector/index.tsx
+++ b/src/Selector/index.tsx
@@ -133,6 +133,8 @@ const Selector: React.RefForwardingComponent =
}
if (which === KeyCode.ENTER && mode === 'tags' && !compositionStatusRef.current && !open) {
+ // When menu isn't open, OptionList won't trigger a value change
+ // So when enter is pressed, the tag's input value should be emit here to let selector know
onSearchSubmit((event.target as HTMLInputElement).value);
}
From afc12148fb023b13c82ec4c00160c96de169b047 Mon Sep 17 00:00:00 2001
From: 07akioni <07akioni2@gmail.com>
Date: Mon, 29 Jun 2020 14:21:57 +0800
Subject: [PATCH 10/10] chore: fix typo
---
src/Selector/index.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Selector/index.tsx b/src/Selector/index.tsx
index 9df0ae193..7dc36c7a5 100644
--- a/src/Selector/index.tsx
+++ b/src/Selector/index.tsx
@@ -134,7 +134,7 @@ const Selector: React.RefForwardingComponent =
if (which === KeyCode.ENTER && mode === 'tags' && !compositionStatusRef.current && !open) {
// When menu isn't open, OptionList won't trigger a value change
- // So when enter is pressed, the tag's input value should be emit here to let selector know
+ // So when enter is pressed, the tag's input value should be emitted here to let selector know
onSearchSubmit((event.target as HTMLInputElement).value);
}