Skip to content

Commit

Permalink
Add basic Dropdown stories
Browse files Browse the repository at this point in the history
  • Loading branch information
pbuba committed Nov 10, 2021
1 parent 9b5d68c commit a6ef4b0
Show file tree
Hide file tree
Showing 8 changed files with 7,733 additions and 4,931 deletions.
12 changes: 9 additions & 3 deletions .storybook/main.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
module.exports = {
stories: ['../stories/**/*.stories.tsx'],
addons: ['@storybook/addon-actions', '@storybook/addon-links'],
};
"stories": [
"../stories/*.stories.mdx",
"../stories/*.stories.@(js|jsx|ts|tsx)"
],
"addons": [
"@storybook/addon-links",
"@storybook/addon-essentials"
]
}
9 changes: 9 additions & 0 deletions .storybook/preview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
}
183 changes: 96 additions & 87 deletions example/Dropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,106 +1,115 @@
import React, {useCallback, useEffect} from 'react';
import React, {ChangeEvent, KeyboardEvent, useCallback, useEffect, useMemo, useState} from 'react';
import ReactDOM from 'react-dom';
import {useDropdown, DropdownState, ReducerAction} from '../src';
import './Dropdown.css';

type Option = {
label: string;
export type Item = {
name: string;
value: string;
}
};

type DropdownProps = {
items: Array<Option>;
value?: Option;
onChange?(value: Option): void;
root?: HTMLElement;
autoScroll?: boolean;
type Props = {
onSelect: (item: Item) => void;
value?: Item;
}
export const Dropdown = ({
items,
value,
onChange = () => {},
autoScroll,
root,
}: DropdownProps) => {

const reducer = (state: DropdownState, action: ReducerAction<Option>) => {
console.log('Reducer', state, action);
switch (action.type) {
default:
return state;
}

const items: Item[] = [
{
name: 'NewYork',
value: 'NewYork'
},
{
name: 'Moscow',
value: 'Moscow'
},
{
name: 'London',
value: 'London'
},
{
name: 'Amsterdam',
value: 'Amsterdam'
},
];



export const Dropdown: React.FC<Props> = ({onSelect, value}) => {
const [inputValue, setInputValue] = useState<string>('');

const handleSelect = (item: Item) => {
setInputValue(item.name);
onSelect(item);
}

const options = useMemo(() => {
return items.filter(item => item.name.includes(inputValue));
}, [inputValue])

const {
isOpen,
getInputProps,
highlightedIndex,
getWrapperProps,
getItemProps,
getInputProps,
getMenuProps,
highlightedIndex,
getItemProps,
setOpen,
} = useDropdown<Option>({
reducer,
onSelect: (value: Option) => {
onChange(value);
},
items,
autoScroll,
root
})

const inputProps = getInputProps();

const handleInputKeyDown = useCallback((ev: KeyboardEvent) => {
switch (ev.key) {
case 'Backspace':
onChange(null);
}
}, []);
} = useDropdown<Item>({items: options, onSelect: handleSelect})

const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setOpen(true);

setInputValue(event.target.value);
onSelect(undefined);
};

useEffect(() => {
inputProps.ref.current.addEventListener('keydown', handleInputKeyDown);
const handleKeyDown = (event: KeyboardEvent) => {
switch (event.code) {
case 'ArrowDown':
setOpen(true);
break;

return () => {
inputProps.ref.current.removeEventListener('keydown', handleInputKeyDown);
// case 'Backspace':
// if(inputValue === value?.name) {
// onSelect(undefined);
// }
// break;
}
}, [inputProps]);

const toggle = useCallback(() => {
setOpen(!isOpen);
}, [isOpen])

return (
<div>
<div {...getWrapperProps()} className="wrapper">
<span>{value?.label}</span>
<input
type="text"
className="input"
value={value?.label}
{...inputProps}
/>
<span onClick={toggle}>{isOpen ? '-' : '+'}</span>
</div>
{
isOpen && (
ReactDOM.createPortal(
<ul className="menu" {...getMenuProps()}>
{
items.map((item, index) => (
<li
className={`item ${highlightedIndex === index ? 'active' : ''}`}
{...getItemProps(item, index)}>
{item.label}
</li>
))
}
</ul>,
document.body
)
}

)
}
</div>
)
const handleBlur = () => {
console.log('blur');
setInputValue('');
}

return <div className='wrapper' {...getWrapperProps()} onKeyDown={handleKeyDown} onBlur={handleBlur}>

<input
className='input'
type="text" id="input" {...getInputProps()}
placeholder='Select city'
value={inputValue}
onChange={handleChange}
autoComplete='off'

/>

{isOpen &&
<ul className='menu' {...getMenuProps() as any}>
{options.length === 0 ?
<li>No data</li>
: options.map(
(item: Item, index) =>
<li
key={item.value}
className={highlightedIndex === index ? 'item active' : 'item'}
{...getItemProps(item, index)}
>
{item.name}
</li>
)
}
</ul>
}
</div>
}
Loading

0 comments on commit a6ef4b0

Please sign in to comment.