feat: add Display calendar settings (#4164)
* feat: add Color calendar setting Closes #4067 * fix: fix wrong imports * feat: add Display calendar settings Closes #4068 * feat: add 12h/24h in Format option labels * fix tests * Fix * Fix --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -1,3 +1,4 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
@ -5,20 +6,30 @@ import { IconChevronDown } from '@/ui/display/icon';
|
||||
import { IconComponent } from '@/ui/display/icon/types/IconComponent';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
|
||||
import { SelectHotkeyScope } from '../types/SelectHotkeyScope';
|
||||
|
||||
export type SelectOption<Value extends string | number | null> = {
|
||||
value: Value;
|
||||
label: string;
|
||||
Icon?: IconComponent;
|
||||
};
|
||||
|
||||
export type SelectProps<Value extends string | number | null> = {
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
dropdownId: string;
|
||||
dropdownWidth?: `${string}px` | 'auto' | number;
|
||||
fullWidth?: boolean;
|
||||
label?: string;
|
||||
onChange?: (value: Value) => void;
|
||||
options: { value: Value; label: string; Icon?: IconComponent }[];
|
||||
options: SelectOption<Value>[];
|
||||
value?: Value;
|
||||
withSearchInput?: boolean;
|
||||
};
|
||||
|
||||
const StyledControlContainer = styled.div<{
|
||||
@ -63,15 +74,28 @@ export const Select = <Value extends string | number | null>({
|
||||
className,
|
||||
disabled,
|
||||
dropdownId,
|
||||
dropdownWidth = 176,
|
||||
fullWidth,
|
||||
label,
|
||||
onChange,
|
||||
options,
|
||||
value,
|
||||
withSearchInput,
|
||||
}: SelectProps<Value>) => {
|
||||
const theme = useTheme();
|
||||
const [searchInputValue, setSearchInputValue] = useState('');
|
||||
|
||||
const selectedOption =
|
||||
options.find(({ value: key }) => key === value) || options[0];
|
||||
const filteredOptions = useMemo(
|
||||
() =>
|
||||
searchInputValue
|
||||
? options.filter(({ label }) =>
|
||||
label.toLowerCase().includes(searchInputValue.toLowerCase()),
|
||||
)
|
||||
: options,
|
||||
[options, searchInputValue],
|
||||
);
|
||||
|
||||
const { closeDropdown } = useDropdown(dropdownId);
|
||||
|
||||
@ -101,23 +125,37 @@ export const Select = <Value extends string | number | null>({
|
||||
{!!label && <StyledLabel>{label}</StyledLabel>}
|
||||
<Dropdown
|
||||
dropdownId={dropdownId}
|
||||
dropdownMenuWidth={176}
|
||||
dropdownMenuWidth={dropdownWidth}
|
||||
dropdownPlacement="bottom-start"
|
||||
clickableComponent={selectControl}
|
||||
dropdownComponents={
|
||||
<DropdownMenuItemsContainer>
|
||||
{options.map((option) => (
|
||||
<MenuItem
|
||||
key={option.value}
|
||||
LeftIcon={option.Icon}
|
||||
text={option.label}
|
||||
onClick={() => {
|
||||
onChange?.(option.value);
|
||||
closeDropdown();
|
||||
}}
|
||||
<>
|
||||
{!!withSearchInput && (
|
||||
<DropdownMenuSearchInput
|
||||
autoFocus
|
||||
value={searchInputValue}
|
||||
onChange={(event) => setSearchInputValue(event.target.value)}
|
||||
/>
|
||||
))}
|
||||
</DropdownMenuItemsContainer>
|
||||
)}
|
||||
{!!withSearchInput && !!filteredOptions.length && (
|
||||
<DropdownMenuSeparator />
|
||||
)}
|
||||
{!!filteredOptions.length && (
|
||||
<DropdownMenuItemsContainer hasMaxHeight>
|
||||
{filteredOptions.map((option) => (
|
||||
<MenuItem
|
||||
key={option.value}
|
||||
LeftIcon={option.Icon}
|
||||
text={option.label}
|
||||
onClick={() => {
|
||||
onChange?.(option.value);
|
||||
closeDropdown();
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</DropdownMenuItemsContainer>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
dropdownHotkeyScope={{ scope: SelectHotkeyScope.Select }}
|
||||
/>
|
||||
|
||||
@ -53,3 +53,7 @@ export const Open: Story = {
|
||||
export const Disabled: Story = {
|
||||
args: { disabled: true },
|
||||
};
|
||||
|
||||
export const WithSearch: Story = {
|
||||
args: { withSearchInput: true },
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user