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:
Thaïs
2024-02-24 08:50:32 -03:00
committed by GitHub
parent a993155fb0
commit 3d809d5317
16 changed files with 926 additions and 82 deletions

View File

@ -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 }}
/>

View File

@ -53,3 +53,7 @@ export const Open: Story = {
export const Disabled: Story = {
args: { disabled: true },
};
export const WithSearch: Story = {
args: { withSearchInput: true },
};