Skip to content

Commit

Permalink
feature: add prop multi to select change return
Browse files Browse the repository at this point in the history
  • Loading branch information
AdrianChacon committed May 14, 2024
1 parent 0faec72 commit a0923e0
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 15 deletions.
51 changes: 51 additions & 0 deletions src/components/Select/Select.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default {
tags: ['autodocs'],
args: {
id: 'select',
multi: false,
options: [
{
label: 'Option 1'
Expand Down Expand Up @@ -52,8 +53,30 @@ export const Default = {
}
};

export const DefaultWithMulti = {
args: {
multi: true
},
play: async ({canvasElement, step}: any) =>{
const canvas = within(canvasElement);
const select = await canvas.getByRole('select');
await step('render', async () =>{
expect(select).toBeInTheDocument();
});
await step('option selection', async () =>{
userEvent.click(select);
const menu = await canvas.findByRole('menu');
expect(menu).toBeVisible();
const option = await canvas.findByRole('cell-2');
userEvent.click(option);
userEvent.click(option);
});
}
};

export const DefaultWithIcons = {
args: {
multi: false,
options: [
{
label: 'Option 1',
Expand All @@ -78,3 +101,31 @@ export const DefaultWithIcons = {
canvas.getByRole('select');
}
};

export const DefaultMultiWithIcons = {
args: {
multi: true,
options: [
{
label: 'Option 1',
icon: <Dog width={20} height={20}/>
},
{
label: 'Option 2',
icon: <Cat width={20} height={20}/>
},
{
label: 'Option 3',
icon: <Cake width={20} height={20}/>
},
{
label: 'Option 4',
icon: <Calendar width={20} height={20}/>
}
],
},
play: async ({canvasElement}: any) =>{
const canvas = within(canvasElement);
canvas.getByRole('select');
}
};
52 changes: 37 additions & 15 deletions src/components/Select/Select.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useState, useEffect, ComponentPropsWithoutRef, CSSProperties } from 'react';
import { useState, useEffect, ComponentPropsWithoutRef, CSSProperties, Fragment } from 'react';
import styled from 'styled-components';

import Text from '../Text/Text';
import Color from '../../constants/Color';
import { ChevronDown, ChevronUp } from 'lucide-react'
import { ChevronDown, ChevronUp, Check } from 'lucide-react'

const Container = styled.div`
position: relative;
Expand Down Expand Up @@ -46,9 +46,8 @@ const Option = styled.div`
`

const Select = (props: Props) =>{

const [ showMenu, setShowMenu ] = useState(false);
const [ selectedItem, setSelectedItem ] = useState(props.options && props.options[0]);
const [ selectedValues, setSelectedValues ] = useState<Array<any>>([]);

useEffect(() =>{
window.addEventListener('click', (e) => closeMenu(e));
Expand All @@ -57,7 +56,7 @@ const Select = (props: Props) =>{

useEffect(() =>{
if(props.selectedItem){
setSelectedItem(props.selectedItem)
setSelectedValues([props.selectedItem]);
}
}, [props.selectedItem]);

Expand All @@ -81,7 +80,22 @@ const Select = (props: Props) =>{
if (!e) var e: any = window.event;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
setSelectedItem(option);
// setSelectedItem(option);
if (props.multi) {
setSelectedValues(prevValues => {
if (prevValues.includes(option)) {
// Si el valor ya está seleccionado, lo quitamos
return prevValues.filter(v => v !== option);
} else {
// Si el valor no está seleccionado, lo añadimos
const temp = [...prevValues, option]
temp.sort((a, b) => a.label.localeCompare(b.label))
return temp
}
});
} else {
setSelectedValues([option]);
}
setShowMenu(false);
props.onChange && props.onChange(option);
}
Expand All @@ -95,15 +109,21 @@ const Select = (props: Props) =>{
style={props.style}
onClick={onSelectClick}
>
{selectedItem?.icon}
{!props.hideTitle &&
<Text
type='p'
style={{flex: 1, fontSize: 14, color: props.style ? props.style.color : Color.text.full}}
>
{selectedItem?.label}
</Text>
}
<div style={{flex: 1, display: 'flex'}}>
{selectedValues.map((item, index) => (
<Fragment key={index}>
{item.icon}
{!props.hideTitle && (
<Text
type='p'
style={{ paddingRight: 10, paddingLeft: 10, fontSize: 14, color: props.style ? props.style.color : Color.text.full}}
>
{item.label}
</Text>
)}
</Fragment>
)).sort()}
</div>
{showMenu ?
<ChevronUp height={20} width={20}/>
:
Expand All @@ -122,6 +142,7 @@ const Select = (props: Props) =>{
key={props.id+'-cell-'+index}
onClick={(e: any) => onOptionClick(item, e)}
>
{props.multi && selectedValues.includes(item) && <Check width={20} height={20}/>}
{item.icon}
<Text type='p'>{item.label}</Text>
</Option>
Expand All @@ -139,6 +160,7 @@ export interface Props extends ComponentPropsWithoutRef<"div">{
hideTitle?: boolean,
options: Array<OptionProps>
selectedItem?: OptionProps
multi?: boolean,
onChange?: (option: any) => void
}
interface OptionProps {
Expand Down

0 comments on commit a0923e0

Please sign in to comment.