From 5fca919269d2c60c76fbae45de76605aca47bf68 Mon Sep 17 00:00:00 2001 From: jorge-cob Date: Thu, 1 Jul 2021 20:51:15 +0200 Subject: [PATCH 1/2] New field feature enable in multi select --- src/lib/interfaces.ts | 2 ++ src/select-panel/add.tsx | 15 ++++++++++ src/select-panel/index.tsx | 23 +++++++++++++- src/style.css | 9 ++++++ stories/enabled-new-field.stories.tsx | 43 +++++++++++++++++++++++++++ 5 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 src/select-panel/add.tsx create mode 100644 stories/enabled-new-field.stories.tsx diff --git a/src/lib/interfaces.ts b/src/lib/interfaces.ts index ea68ace..54d0c39 100644 --- a/src/lib/interfaces.ts +++ b/src/lib/interfaces.ts @@ -33,4 +33,6 @@ export interface ISelectProps { ClearSelectedIcon?: ReactNode; defaultIsOpen?: boolean; isOpen?: boolean; + enableNewFields?: boolean; + onNewField?: Function; } diff --git a/src/select-panel/add.tsx b/src/select-panel/add.tsx new file mode 100644 index 0000000..39a3577 --- /dev/null +++ b/src/select-panel/add.tsx @@ -0,0 +1,15 @@ +import React from "react"; + +export const Add = () => ( + + + + +); diff --git a/src/select-panel/index.tsx b/src/select-panel/index.tsx index cf05056..1134ccc 100644 --- a/src/select-panel/index.tsx +++ b/src/select-panel/index.tsx @@ -17,6 +17,7 @@ import { KEY } from "../lib/constants"; import { debounce } from "../lib/debounce"; import { filterOptions } from "../lib/fuzzy-match-utils"; import { Cross } from "./cross"; +import { Add } from "./add"; import SelectItem from "./select-item"; import SelectList from "./select-list"; @@ -39,6 +40,8 @@ const SelectPanel = () => { hasSelectAll, ClearIcon, debounceDuration, + enableNewFields, + onNewField=()=>{} } = useMultiSelect(); const listRef = useRef(); @@ -126,6 +129,10 @@ const SelectPanel = () => { setFocusIndex(FocusType.SEARCH); }; + const handleNewField = () => { + onNewField(searchText) + }; + const getFilteredOptions = async () => customFilterOptions ? await customFilterOptions(options, searchTextForFilter) @@ -203,7 +210,21 @@ const SelectPanel = () => { onClick={(_e, index) => handleItemClicked(index)} /> ) : ( -
  • {t("noOptions")}
  • + enableNewFields ? ( +
  • + +
  • + ) : ( +
  • {t("noOptions")}
  • + ) + )} diff --git a/src/style.css b/src/style.css index eccf4d3..ebf43c8 100644 --- a/src/style.css +++ b/src/style.css @@ -137,6 +137,15 @@ display: none; } +.rmsc .search-new-field-button { + cursor: pointer; +} + +.rmsc .search-new-field-button > span { + float: left; + line-height: 24px; +} + .rmsc .item-renderer { display: flex; align-items: baseline; diff --git a/stories/enabled-new-field.stories.tsx b/stories/enabled-new-field.stories.tsx new file mode 100644 index 0000000..16fc9f1 --- /dev/null +++ b/stories/enabled-new-field.stories.tsx @@ -0,0 +1,43 @@ +import { text, withKnobs } from "@storybook/addon-knobs"; +import React, { useState } from "react"; + +import MultiSelect from "../src/multi-select"; + +export default { + title: "Multiselect", + decorators: [withKnobs], +}; + +const INITIAL_OPTIONS = [ + { label: "Grapes 🍇", value: "grapes" }, + { label: "Mango 🥭", value: "mango", disabled: true }, + { label: "Strawberry 🍓", value: "strawberry" }, +]; + +export const ExampleNewField = () => { + + function handleNewField(newVal) { + setOptions([...options, {label: newVal, value: newVal.toLowerCase()}]); + } + + const [options, setOptions] = useState(INITIAL_OPTIONS); + const [selected, setSelected] = useState([]); + + return ( +
    +
    {JSON.stringify(selected)}
    + +
    + ); +}; + +ExampleNewField.story = { + name: "New field", +}; From cb7b3191ad77bcd1879382c3c329183329445d53 Mon Sep 17 00:00:00 2001 From: jorge-cob Date: Fri, 2 Jul 2021 13:24:10 +0200 Subject: [PATCH 2/2] Changes in response to PR comment --- src/hooks/use-multi-select.tsx | 1 + src/lib/interfaces.ts | 4 ++-- src/select-panel/add.tsx | 15 --------------- src/select-panel/index.tsx | 22 ++++++---------------- src/style.css | 10 +++++----- stories/enabled-new-field.stories.tsx | 4 ++-- 6 files changed, 16 insertions(+), 40 deletions(-) delete mode 100644 src/select-panel/add.tsx diff --git a/src/hooks/use-multi-select.tsx b/src/hooks/use-multi-select.tsx index de359ee..d1dceaf 100644 --- a/src/hooks/use-multi-select.tsx +++ b/src/hooks/use-multi-select.tsx @@ -10,6 +10,7 @@ const defaultStrings = { search: "Search", selectAll: "Select All", selectSomeItems: "Select...", + create: "Create", }; const defaultProps: Partial = { diff --git a/src/lib/interfaces.ts b/src/lib/interfaces.ts index 54d0c39..df3e910 100644 --- a/src/lib/interfaces.ts +++ b/src/lib/interfaces.ts @@ -33,6 +33,6 @@ export interface ISelectProps { ClearSelectedIcon?: ReactNode; defaultIsOpen?: boolean; isOpen?: boolean; - enableNewFields?: boolean; - onNewField?: Function; + isCreatable?: boolean; + onCreate?: Function; } diff --git a/src/select-panel/add.tsx b/src/select-panel/add.tsx deleted file mode 100644 index 39a3577..0000000 --- a/src/select-panel/add.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from "react"; - -export const Add = () => ( - - - - -); diff --git a/src/select-panel/index.tsx b/src/select-panel/index.tsx index 1134ccc..c5a2738 100644 --- a/src/select-panel/index.tsx +++ b/src/select-panel/index.tsx @@ -17,7 +17,6 @@ import { KEY } from "../lib/constants"; import { debounce } from "../lib/debounce"; import { filterOptions } from "../lib/fuzzy-match-utils"; import { Cross } from "./cross"; -import { Add } from "./add"; import SelectItem from "./select-item"; import SelectList from "./select-list"; @@ -40,8 +39,8 @@ const SelectPanel = () => { hasSelectAll, ClearIcon, debounceDuration, - enableNewFields, - onNewField=()=>{} + isCreatable, + onCreate=()=>{} } = useMultiSelect(); const listRef = useRef(); @@ -130,7 +129,8 @@ const SelectPanel = () => { }; const handleNewField = () => { - onNewField(searchText) + onCreate(searchText); + onChange([...value, {label: searchText, value: searchText.toLowerCase()}]); }; const getFilteredOptions = async () => @@ -210,21 +210,11 @@ const SelectPanel = () => { onClick={(_e, index) => handleItemClicked(index)} /> ) : ( - enableNewFields ? ( -
  • - -
  • + isCreatable ? ( +
  • {t("create")} "{searchText}"
  • ) : (
  • {t("noOptions")}
  • ) - )} diff --git a/src/style.css b/src/style.css index ebf43c8..7ff152c 100644 --- a/src/style.css +++ b/src/style.css @@ -137,13 +137,13 @@ display: none; } -.rmsc .search-new-field-button { - cursor: pointer; +.rmsc .add-option { + padding: var(--rmsc-p); + text-align: left; } -.rmsc .search-new-field-button > span { - float: left; - line-height: 24px; +.rmsc .add-option:hover { + background: var(--rmsc-hover); } .rmsc .item-renderer { diff --git a/stories/enabled-new-field.stories.tsx b/stories/enabled-new-field.stories.tsx index 16fc9f1..ba0c28f 100644 --- a/stories/enabled-new-field.stories.tsx +++ b/stories/enabled-new-field.stories.tsx @@ -31,8 +31,8 @@ export const ExampleNewField = () => { value={selected} onChange={setSelected} labelledBy={text("labelledBy", "Select Fruits")} - enableNewFields - onNewField={handleNewField} + isCreatable + onCreate={handleNewField} /> );