Skip to content

Commit

Permalink
Placeholder added in select & props structure set to standard
Browse files Browse the repository at this point in the history
  • Loading branch information
neilveil committed Oct 14, 2023
1 parent d6d4b91 commit 49e42eb
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 40 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "mumpui",
"description": "A light-weight flexible & elegant design system for developers.",
"version": "1.3.0",
"version": "1.4.0",
"main": "dist/index.js",
"author": "neilveil",
"repository": "neilveil/mumpui",
Expand Down
34 changes: 26 additions & 8 deletions src/lib/components/select/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React, { useEffect, useRef, useState } from 'react'
import { default as Multi } from './multi'
import { default as Native } from './native'
import { default as search } from './search'
import Placeholder from '../placeholder'

export type option = {
key: string
Expand All @@ -12,8 +13,8 @@ export type option = {

type props = Omit<React.InputHTMLAttributes<HTMLDivElement>, 'onChange' | 'value'> & {
options?: option[]
value?: option
onChange?: (value?: option) => void
value?: string
onChange?: (value: string) => void
onSearch?: (search: string) => void
simpleSearch?: boolean
placeholder?: any
Expand Down Expand Up @@ -50,14 +51,22 @@ export default function Main({
if (ref.current && !ref.current.contains(e.target)) setOptionsVisible(false)
}

const keyListener = (e: any) => {
if (e.key === 'Escape') setOptionsVisible(false)
}

useEffect(() => {
window.addEventListener('click', clickListener)
return () => window.removeEventListener('click', clickListener)
window.addEventListener('keyup', keyListener)
return () => {
window.removeEventListener('click', clickListener)
window.removeEventListener('keyup', keyListener)
}
}, [])

const _onSelect = (selected: option) => {
if (onSearch) onSearch('')
if (onChange) onChange(selected)
if (onChange) onChange(selected.key)
setOptionsVisible(false)
_setSearch('')
}
Expand All @@ -67,7 +76,9 @@ export default function Main({
if (simpleSearch) _setSearch(search)
}

if (value) options = options.filter(x => value.key !== x.key)
const selectedOptions = options.find(x => x.key === value)

if (value) options = options.filter(x => value !== x.key)

if (_search) options = search(_search, options)

Expand All @@ -79,9 +90,9 @@ export default function Main({
className={className}
onClick={() => !disabled && setOptionsVisible(!optionsVisible)}
>
<div className='mp-select-single'>{value ? valueHOC(value) : placeholder}</div>
<div className='mp-select-single'>{selectedOptions ? valueHOC(selectedOptions) : placeholder}</div>

{optionsVisible && !!(options.length || onSearch || simpleSearch) && (
{optionsVisible && (
<div className='mp-input-expanded-area'>
{!!(onSearch || simpleSearch || clearable) && (
<div
Expand All @@ -102,14 +113,15 @@ export default function Main({
}}
className='mp-select-search'
onBlur={() => _setSearch('')}
value={_search}
autoFocus
/>
) : (
<div className='mp-select-search'>&nbsp;</div>
)}

{!!clearable && (
<div className='mp-select-clear' onClick={() => !!onChange && onChange()}>
<div className='mp-select-clear' onClick={() => !!onChange && onChange('')}>
Clear
</div>
)}
Expand All @@ -128,6 +140,12 @@ export default function Main({
{optionHOC(x)}
</div>
))}

{!options.length && (
<div onClick={() => _setSearch('')} style={{ display: 'flex', justifyContent: 'center' }}>
<Placeholder style={{ width: '50%', padding: '2rem 2rem' }} empty />
</div>
)}
</div>
)}
</div>
Expand Down
62 changes: 41 additions & 21 deletions src/lib/components/select/multi.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React, { useEffect, useRef, useState } from 'react'
import { type option } from '.'
import search from './search'
import Placeholder from '../placeholder'

type multiple = Omit<React.InputHTMLAttributes<HTMLDivElement>, 'onChange' | 'value'> & {
options?: option[]
value?: option[]
onChange?: (value: option[]) => void
value?: string[]
onChange?: (value: string[]) => void
onSearch?: (search: string) => void
simpleSearch?: boolean
placeholder?: any
Expand Down Expand Up @@ -41,14 +42,22 @@ export default function Main({
if (ref.current && !ref.current.contains(e.target)) setOptionsVisible(false)
}

const keyListener = (e: any) => {
if (e.key === 'Escape') setOptionsVisible(false)
}

useEffect(() => {
window.addEventListener('click', clickListener)
return () => window.removeEventListener('click', clickListener)
window.addEventListener('keyup', keyListener)
return () => {
window.removeEventListener('click', clickListener)
window.removeEventListener('keyup', keyListener)
}
}, [])

const _onChange = (selected: option) => {
if (onSearch) onSearch('')
if (onChange) onChange(value.concat(selected))
if (onChange) onChange(value.concat(selected.key))
_setSearch('')

const inputEl = ref.current.querySelector('input')
Expand All @@ -63,23 +72,27 @@ export default function Main({
if (simpleSearch) _setSearch(search)
}

const selectedKey = value.map(x => x.key)

const valueEl = value.map((x, i) => (
<div key={i} className='mp-select-chip'>
{x.label}
<CrossIcon
color='var(--mp-c-font-light)'
onClick={e => {
if (disabled) return
e.stopPropagation()
if (onChange) onChange(value.filter(y => y.key !== x.key))
}}
/>
</div>
))
const valueEl = value.map((x, i) => {
const option = options.find(y => y.key === x)

if (!option) return null

options = options.filter(x => !selectedKey.includes(x.key))
return (
<div key={i} className='mp-select-chip'>
{option.label}
<CrossIcon
color='var(--mp-c-font-light)'
onClick={e => {
if (disabled) return
e.stopPropagation()
if (onChange) onChange(value.filter(y => y !== x))
}}
/>
</div>
)
})

options = options.filter(x => !value.includes(x.key))

if (_search) options = search(_search, options)

Expand All @@ -93,7 +106,7 @@ export default function Main({
>
<div className='mp-select-multi'>{value.length ? valueEl : placeholder}</div>

{optionsVisible && !!(options.length || onSearch || simpleSearch) && (
{optionsVisible && (
<div className='mp-input-expanded-area'>
{!!(onSearch || simpleSearch || clearable) && (
<div
Expand All @@ -114,6 +127,7 @@ export default function Main({
}}
onBlur={() => _setSearch('')}
className='mp-select-search'
value={_search}
autoFocus
/>
) : (
Expand All @@ -140,6 +154,12 @@ export default function Main({
{optionHOC(x)}
</div>
))}

{!options.length && (
<div onClick={() => _setSearch('')} style={{ display: 'flex', justifyContent: 'center' }}>
<Placeholder style={{ width: '50%', padding: '2rem 2rem' }} empty />
</div>
)}
</div>
)}
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/docs/multiSelect/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as snippets from './snippets'
import data from 'data'

export default function Main() {
const [value, setValue] = useState<typeof data.countries>([data.countries[0]])
const [value, setValue] = useState([data.countries[0].key])

return (
<Docs name='multiSelect'>
Expand Down
9 changes: 2 additions & 7 deletions src/pages/docs/select/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import * as snippets from './snippets'
import data from 'data'

export default function Main() {
const [value, setValue] = useState<(typeof data.countries)[0] | undefined>(data.countries[0])
const [valueNative, setValueNative] = useState('india')
const [value, setValue] = useState('india')

return (
<Docs name='select'>
Expand Down Expand Up @@ -53,11 +52,7 @@ export default function Main() {

<Docs.Showcase title='⭐ Native select component' code={snippets.s2}>
<Field label='Native Select' style={{ maxWidth: '15rem' }}>
<Select.Native
options={data.countries}
value={valueNative}
onChange={valueNative => setValueNative(valueNative)}
/>
<Select.Native options={data.countries} value={value} onChange={valueNative => setValue(valueNative)} />
</Field>
</Docs.Showcase>

Expand Down
4 changes: 2 additions & 2 deletions src/pages/home/showcases.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,15 @@ export default {
select: {
...metagraph.select,
Component() {
const [value, setValue] = useState<(typeof data.countries)[0] | undefined>(data.countries[0])
const [value, setValue] = useState(data.countries[0].key)

return <Select options={data.countries} value={value} onChange={value => setValue(value)} />
}
},
multiSelect: {
...metagraph.multiSelect,
Component() {
const [value, setValue] = useState<typeof data.countries>([data.countries[0]])
const [value, setValue] = useState([data.countries[0].key])

return <Select.Multi options={data.countries} value={value} onChange={value => setValue(value)} />
}
Expand Down

0 comments on commit 49e42eb

Please sign in to comment.