Skip to content

Commit

Permalink
Add creatable option for combobox
Browse files Browse the repository at this point in the history
  • Loading branch information
bhavabhuthi committed Oct 4, 2024
1 parent 5d6f20a commit 7bd7cfe
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 79 deletions.
72 changes: 2 additions & 70 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions packages/opub-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "opub-ui",
"description": "OPub UI Library",
"version": "0.3.43",
"version": "0.3.44",
"private": false,
"license": "MIT",
"author": "CivicDataLab <[email protected]>",
Expand Down Expand Up @@ -192,4 +192,4 @@
"vite-tsconfig-paths": "^4.0.7",
"vitest": "^0.28.3"
}
}
}
14 changes: 14 additions & 0 deletions packages/opub-ui/src/components/Combobox/Combobox.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,20 @@ export const MultiSelect: Story = {
},
};

export const CreatableSelect: Story = {
args: {
label: 'Your favorite food',
placeholder: 'e.g., Apple, Burger',
list: options,
displaySelected: true,
selectedValue: [],
creatable: true,
onChange: (e: any) => {
console.log(e);
},
},
};

export const Tags: Story = {
args: {
label: 'Your favorite food',
Expand Down
54 changes: 47 additions & 7 deletions packages/opub-ui/src/components/Combobox/Combobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ export type ComboProps = {
* Add grouping to the combobox.
*/
group?: boolean;

/**
* Add creatable to the combobox.
*/
creatable?: boolean;
};

export const Combobox = React.forwardRef(
Expand All @@ -35,6 +40,7 @@ export const Combobox = React.forwardRef(
const [searchValue, setSearchValue] = useState('');
const deferredValue = React.useDeferredValue(searchValue);
const [selectedValues, setSelectedValues] = useState(props.selectedValue);
const [comboboxList, setComboboxList] = useState(props.list);

const combobox = useComboboxStore();
const ref = React.useRef(null);
Expand Down Expand Up @@ -96,17 +102,17 @@ export const Combobox = React.forwardRef(

const matches = useMemo(() => {
if (props.group) {
const items = matchSorter(props.list, deferredValue, {
const items = matchSorter(comboboxList, deferredValue, {
keys: ['label', 'value', 'type'],
});

return Object.entries(groupBy(items, 'type'));
}

return matchSorter(props.list, deferredValue, {
return matchSorter(comboboxList, deferredValue, {
keys: ['label', 'value'],
});
}, [deferredValue, props.list, props.selectedValue]);
}, [deferredValue, comboboxList, props.selectedValue]);

function removeTag(value: string) {
if (selectedValues && typeof selectedValues !== 'string') {
Expand Down Expand Up @@ -148,8 +154,6 @@ export const Combobox = React.forwardRef(
return (
<ComboboxProvider
setOpen={(e) => {
console.log();

if (e) {
setTimeout(() => {
combobox.getState().baseElement?.focus();
Expand All @@ -168,14 +172,40 @@ export const Combobox = React.forwardRef(
setSelectedValue={(e) => {
// for single select
if (typeof e === 'string') {
setSelectedValues(e);
if (comboboxList.findIndex((it) => it.value === e) < 0) {
setSelectedValues(e);
setComboboxList([
...comboboxList,
{
label: e,
value: e,
},
]);
} else {
setSelectedValues(e);
}
props.onChange && props.onChange(e);
return;
}

// for multi select
const selectedArr = e.map((value: string) => {
return props.list.find((item) => item.value === value);
if (comboboxList.findIndex((item) => item.value === value) > 0) {
return comboboxList.find((item) => item.value === value);
} else {
setComboboxList([
...comboboxList,
{
label: value,
value: value,
},
]);

return {
label: value,
value: value,
};
}
});

setSelectedValues(selectedArr);
Expand Down Expand Up @@ -210,6 +240,16 @@ export const Combobox = React.forwardRef(
{ '--popover-padding': 'var(--space-1)' } as React.CSSProperties
}
>
{matches.length === 0 && (
<>
<Item
item={{
value: searchValue,
label: `Create ${searchValue}`,
}}
/>
</>
)}
{matches.length > 0 ? (
<div className={styles.List}>
{props.group ? (
Expand Down

0 comments on commit 7bd7cfe

Please sign in to comment.