Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ function SelectComponent<T extends Option = Option>(
const {children, role = "listbox", customClassName, value} = props;
const [selectOwnState, dispatchSelectStateAction] = useReducer(selectStateReducer, {
focusedOptionIndex: -1,
isMenuOpen: false,
options: props.options || []
isMenuOpen: false
});
const selectRef = useRef<HTMLDivElement | null>(null);
const selectState = generateSelectState(selectOwnState, props);
Expand All @@ -47,6 +46,7 @@ function SelectComponent<T extends Option = Option>(
return (
<div
ref={selectRef}
data-testid={props.testid}
className={selectClassName}
role={role}
onKeyDown={handleSelectKeyDown}
Expand Down
5 changes: 3 additions & 2 deletions src/select/item/SelectItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ function SelectItemComponent<T extends Option = Option>(
) {
const selectState = useSelectContext();
const dispatchSelectStateAction = useSelectDispatchContext();
const {onSelect, value, focusedOptionIndex, shouldCloseOnSelect, options} = selectState;
const {onSelect, value, focusedOptionIndex, shouldCloseOnSelect, options, isMenuOpen} =
selectState;
const optionIndex = options.findIndex((opt) => opt?.id === option?.id);
const isSelected = Array.isArray(value)
? Boolean(value.find((currentOption) => currentOption.id === option?.id))
Expand Down Expand Up @@ -83,7 +84,7 @@ function SelectItemComponent<T extends Option = Option>(
payload: optionIndex
});

if (shouldCloseOnSelect) {
if (shouldCloseOnSelect && isMenuOpen) {
dispatchSelectStateAction({type: "TOGGLE_MENU_VISIBILITY"});
}
}
Expand Down
31 changes: 21 additions & 10 deletions src/select/typeahead/TypeaheadSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import TypeaheadInput, {
} from "../../form/input/typeahead/TypeaheadInput";
import {mapOptionsToTagShapes} from "../../tag/util/tagUtils";
import {TagShape} from "../../tag/Tag";
import {filterOptionsByKeyword} from "./util/typeaheadSelectUtils";
import {filterOutItemsByKey} from "../../core/utils/array/arrayUtils";
import Spinner from "../../spinner/Spinner";
import {KEYBOARD_EVENT_KEY} from "../../core/utils/keyboard/keyboardEventConstants";
Expand All @@ -19,6 +18,7 @@ import {
} from "../util/selectTypes";
import Select from "../Select";
import TypeheadSelectTrigger from "./trigger/TypeheadSelectTrigger";
import {filterOptionsByKeyword} from "./util/typeaheadSelectUtils";

import "./_typeahead-select.scss";

Expand All @@ -39,33 +39,32 @@ export interface TypeaheadSelectProps<
onTagRemove?: (option: Option) => void;
selectedOptionLimit?: number;
customClassName?: string;
shouldDisplaySelectedOptions?: boolean;
shouldFilterOptionsByKeyword?: boolean;
shouldDisplaySelectedOptions?: boolean;
isDisabled?: boolean;
customSpinner?: React.ReactNode;
shouldShowEmptyOptions?: boolean;
canOpenDropdownMenu?: boolean;
areOptionsFetching?: boolean;
}

/* eslint-disable complexity */
function TypeaheadSelect<T extends TypeaheadSelectOption = TypeaheadSelectOption>({
testid,
options,
selectedOptions,
typeaheadProps,
onTagRemove,
onKeywordChange,
onSelect,
customClassName,
selectedOptionLimit,
shouldDisplaySelectedOptions = true,
shouldFilterOptionsByKeyword = true,
isDisabled,
shouldFilterOptionsByKeyword,
shouldShowEmptyOptions = true,
canOpenDropdownMenu = true,
areOptionsFetching,
customSpinner,
onKeywordChange,
initialKeyword = "",
controlledKeyword
}: TypeaheadSelectProps<T>) {
Expand All @@ -78,11 +77,14 @@ function TypeaheadSelect<T extends TypeaheadSelectOption = TypeaheadSelectOption
const inputValue = typeof controlledKeyword === "string" ? controlledKeyword : keyword;

const tags = mapOptionsToTagShapes(selectedOptions);

const shouldDisplayOnlyTags = Boolean(
selectedOptionLimit && selectedOptions.length >= selectedOptionLimit
);

const canSelectMultiple = !selectedOptionLimit || selectedOptionLimit > 1;
const canSelectMultiple =
options.length > 1 && (!selectedOptionLimit || selectedOptionLimit > 1);

const shouldCloseOnSelect =
!canSelectMultiple ||
Boolean(selectedOptionLimit && selectedOptions.length >= selectedOptionLimit - 1);
Expand Down Expand Up @@ -124,6 +126,7 @@ function TypeaheadSelect<T extends TypeaheadSelectOption = TypeaheadSelectOption
return (
// TODO: Add isMenuOpenHook when we have it
<Select
testid={testid}
role={"listbox"}
onSelect={handleSelect}
options={computedDropdownOptions}
Expand All @@ -134,6 +137,7 @@ function TypeaheadSelect<T extends TypeaheadSelectOption = TypeaheadSelectOption
<TypeheadSelectTrigger
tags={shouldDisplaySelectedOptions ? tags : []}
handleTagRemove={handleRemove}
onClick={openDropdownMenu}
input={
!shouldDisplayOnlyTags && (
<TypeaheadInput
Expand Down Expand Up @@ -162,6 +166,7 @@ function TypeaheadSelect<T extends TypeaheadSelectOption = TypeaheadSelectOption
{option.title}
</Select.Item>
))}

{shouldShowEmptyOptions && !computedDropdownOptions.length && (
<p
data-testid={`${testid}.empty-message`}
Expand Down Expand Up @@ -192,14 +197,21 @@ function TypeaheadSelect<T extends TypeaheadSelectOption = TypeaheadSelectOption
onSelect(option);
setComputedDropdownOptions(options);
setKeyword("");
setShouldFocusOnInput(true);

if (shouldCloseOnSelect) {
setMenuVisibility(false);
} else {
setShouldFocusOnInput(true);
}
}
}

function handleRemove(tag: TagShape<Option>) {
if (onTagRemove) {
onTagRemove(tag.context!);
if (onTagRemove && tag.context) {
onTagRemove(tag.context);
setShouldFocusOnInput(true);
setMenuVisibility(false);
setKeyword("");
}
}

Expand Down Expand Up @@ -235,6 +247,5 @@ function TypeaheadSelect<T extends TypeaheadSelectOption = TypeaheadSelectOption
}
}
}
/* eslint-enable complexity */

export default TypeaheadSelect;
10 changes: 0 additions & 10 deletions src/select/typeahead/_typeahead-select.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,6 @@
width: 100%;
}

.typeahead-select__header-container {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: flex-start;

border: 1px solid var(--default-border-color);
border-radius: var(--small-border-radius);
}

.typeahead-select--can-select-multiple {
.input {
height: auto;
Expand Down
7 changes: 5 additions & 2 deletions src/select/typeahead/trigger/TypeheadSelectTrigger.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,17 @@ export interface TypeheadSelectTriggerProps {
handleTagRemove: (tag: TagShape) => void;
customClassName?: string;
input?: React.ReactNode;
onClick?: VoidFunction;
}
function TypeheadSelectTrigger({
handleTagRemove,
tags,
customClassName,
input
input,
onClick
}: TypeheadSelectTriggerProps) {
return (
<Select.Trigger customClassName={"typeahead-select-trigger"}>
<Select.Trigger customClassName={"typeahead-select-trigger"} onClick={onClick}>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's see why this was added and if it's necessary

<List
customClassName={classNames(
"typeahead-select-trigger__tag-list",
Expand All @@ -41,6 +43,7 @@ function TypeheadSelectTrigger({
</ListItem>
)}
</List>

{input}
</Select.Trigger>
);
Expand Down
8 changes: 6 additions & 2 deletions src/select/typeahead/trigger/_typehead-select-trigger.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@

padding: 0;

border: 1px solid var(--default-border-color);
border-radius: var(--small-border-radius);
.typeahead-select__input {
.input {
border: none;
border-radius: 8px;
}
}
}

.typeahead-select-trigger__tag-list {
Expand Down
Loading