forked from devhatt/pet-dex-frontend
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Alexandre Gomes <[email protected]> feat: create emit event for dropdown component chore: dropdown parameter received fix: dropdown html ajusted chore: change padding value for rem fix: fit: change error message from Portuguese to English BREAKING CHANGE: fit: change error message from Portuguese to English fix devhatt#47 chore: method of adding and removing items implemented fix: fix: implemeted emit in add and remove method refactor: Dropdown component refactor chore: test and storybook for Dropdown component test: tested the dropdwon component fix: message error for english chore: add label and width in props chore: implemented receive css class by props chore: adjusting dropdwon's position property fix: removes unnecessary tests fix: tests names fix: changing component classes to BEM css fix: Dropdown component style ajusted chore: toggleDropdown, openDropdown, closeDropdown, setLabel, getLabel, setValue, getValue, clearOptions, clearDropdown methods implemented fix: closeDropdown fixed reactor: refactor dropdown component fix: setValue and OnSelect methods fixed
- Loading branch information
Showing
8 changed files
with
1,712 additions
and
1,178 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { Component } from 'pet-dex-utilities'; | ||
import './index.scss'; | ||
|
||
const events = ['text:change', 'value:change', 'select', 'unselect']; | ||
|
||
const html = ` | ||
<li data-select='option' class="dropdown__options--option"></li> | ||
`; | ||
|
||
export default function DropdownItem({ text = '', value = '' } = {}) { | ||
Component.call(this, { html, events }); | ||
|
||
this.setText(text); | ||
this.setValue(value); | ||
|
||
this.selected.get('option').addEventListener('click', () => this.toggle()); | ||
} | ||
|
||
DropdownItem.prototype = Object.assign( | ||
DropdownItem.prototype, | ||
Component.prototype, | ||
{ | ||
getText() { | ||
return this.selected.get('option').textContent; | ||
}, | ||
|
||
setText(text = '') { | ||
this.emit('text:change', text); | ||
this.selected.get('option').textContent = text; | ||
}, | ||
|
||
getValue() { | ||
return this.selected.get('option').dataset.value; | ||
}, | ||
|
||
setValue(value = '') { | ||
this.emit('value:change', value); | ||
this.selected.get('option').dataset.value = value; | ||
}, | ||
|
||
isSelected() { | ||
return this.selected.get('option').dataset.selected === 'true'; | ||
}, | ||
|
||
toggle(condition = this.isSelected()) { | ||
if (condition) this.unselect(); | ||
else this.select(); | ||
}, | ||
|
||
select() { | ||
this.selected.get('option').dataset.selected = true; | ||
this.emit('select', this); | ||
}, | ||
|
||
unselect() { | ||
this.selected.get('option').dataset.selected = false; | ||
this.emit('unselect', this); | ||
}, | ||
}, | ||
); |
14 changes: 14 additions & 0 deletions
14
src/components/Dropdown/components/DropdownItem/index.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
@use '~styles/colors.scss' as colors; | ||
|
||
.dropdown__options--option { | ||
padding: 0.3rem; | ||
|
||
&:hover { | ||
background-color: colors.$blue500; | ||
} | ||
|
||
&--selected, | ||
&[data-selected='true'] { | ||
color: colors.$blue600; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
import { Component } from 'pet-dex-utilities'; | ||
import DropdownItem from './components/DropdownItem'; | ||
import './index.scss'; | ||
|
||
const events = [ | ||
'select', | ||
'unselect', | ||
'item:add', | ||
'item:remove', | ||
'open', | ||
'close', | ||
'value:change', | ||
'text:change', | ||
'items:clear', | ||
]; | ||
|
||
const html = ` | ||
<div class="dropdown" data-select="dropdown-container"> | ||
<div class="dropdown__toggle" data-select="dropdown-toggle"> | ||
<span class="dropdown__selected dropdown__selected--label" data-select="dropdown-selected"></span> | ||
<span class="dropdown__icon" data-select="dropdown-icon"> | ||
<svg fill="currentColor" stroke-width="0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="overflow: visible; color: currentcolor;" height="1em" width="1em"> | ||
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z"></path> | ||
</svg> | ||
</span> | ||
</div> | ||
<ul class="dropdown__options" data-select="dropdown-options"></ul> | ||
</div> | ||
`; | ||
|
||
export default function Dropdown({ | ||
items = [], | ||
placeholder = 'Select an option', | ||
value = null, | ||
cssClass = '', | ||
} = {}) { | ||
Component.call(this, { html, events }); | ||
|
||
this.placeholder = placeholder; | ||
this.items = new Map(); | ||
this.itemSelected = null; | ||
|
||
this.onSelect = (item) => { | ||
const existsAndIsDifferent = this.itemSelected != null && this.itemSelected !== item; | ||
if (existsAndIsDifferent) this.itemSelected.unselect(); | ||
|
||
this.itemSelected = item; | ||
this.setValue(item.getValue()); | ||
this.emit('select', item); | ||
|
||
if (this.isOpen()) this.close(); | ||
}; | ||
|
||
this.onUnselect = (item) => { | ||
const isDifferent = this.itemSelected !== item; | ||
if (isDifferent) return; | ||
|
||
this.itemSelected = null; | ||
this.setValue(null); | ||
this.emit('unselect', item); | ||
}; | ||
|
||
items.map((item) => this.addItem(item)); | ||
this.setValue(value); | ||
|
||
this.selected | ||
.get('dropdown-toggle') | ||
.addEventListener('click', () => this.toggle()); | ||
|
||
const closeOnClickOutside = (event) => { | ||
const isOutside = !event | ||
.composedPath() | ||
.includes(this.selected.get('dropdown-container')); | ||
|
||
if (!isOutside) return; | ||
|
||
if (this.isOpen()) this.close(); | ||
}; | ||
|
||
this.listen('mount', () => document.addEventListener('click', closeOnClickOutside), | ||
); | ||
this.listen('unmount', () => document.removeEventListener('click', closeOnClickOutside), | ||
); | ||
|
||
if (cssClass) { | ||
this.selected.get('dropdown-container').classList.add(cssClass); | ||
} | ||
} | ||
|
||
Dropdown.prototype = Object.assign(Dropdown.prototype, Component.prototype, { | ||
addItem(props = {}) { | ||
if (this.items.has(props.value)) return; | ||
|
||
const item = new DropdownItem(props); | ||
const $list = this.selected.get('dropdown-options'); | ||
item.mount($list); | ||
item.listen('select', this.onSelect); | ||
item.listen('unselect', this.onUnselect); | ||
this.items.set(props.value, item); | ||
this.emit('item:add', item); | ||
}, | ||
|
||
removeItem(value = '') { | ||
if (!this.items.has(value)) return; | ||
|
||
const item = this.items.get(value); | ||
item.unmount(); | ||
this.items.delete(value); | ||
|
||
if (item.getValue() === this.getValue()) { | ||
this.setValue(null); | ||
} | ||
|
||
this.emit('item:remove', item); | ||
}, | ||
|
||
isOpen() { | ||
return this.selected | ||
.get('dropdown-container') | ||
.classList.contains('dropdown--open'); | ||
}, | ||
|
||
toggle(condition = this.isOpen()) { | ||
if (condition) this.close(); | ||
else this.open(); | ||
}, | ||
|
||
open() { | ||
if (this.items.size === 0) return; | ||
|
||
const $container = this.selected.get('dropdown-container'); | ||
$container.classList.add('dropdown--open'); | ||
this.emit('open'); | ||
}, | ||
|
||
close() { | ||
const $container = this.selected.get('dropdown-container'); | ||
$container.classList.remove('dropdown--open'); | ||
this.emit('close'); | ||
}, | ||
|
||
getValue() { | ||
const { value } = this.selected.get('dropdown-selected').dataset; | ||
if (value == null) return null; | ||
return value; | ||
}, | ||
|
||
setValue(value = null) { | ||
if (value == null) { | ||
if (this.itemSelected != null) { | ||
this.itemSelected.unselect(); | ||
return; | ||
} | ||
|
||
this.setText(this.placeholder, true); | ||
this.emit('value:change', null); | ||
delete this.selected.get('dropdown-selected').dataset.value; | ||
|
||
return; | ||
} | ||
|
||
if (!this.items.has(value)) return; | ||
|
||
const item = this.items.get(value); | ||
this.setText(item.getText()); | ||
this.selected.get('dropdown-selected').dataset.value = item.getValue(); | ||
this.emit('value:change', item.getValue()); | ||
}, | ||
|
||
getText() { | ||
return this.selected.get('dropdown-selected').textContent; | ||
}, | ||
|
||
setText(text = '', isPlaceholder = false) { | ||
const $container = this.selected.get('dropdown-selected'); | ||
$container.classList.toggle('dropdown__selected--label', isPlaceholder); | ||
$container.textContent = text; | ||
this.emit('text:change', text); | ||
}, | ||
|
||
clearItems() { | ||
this.items.forEach((item) => this.removeItem(item.getValue())); | ||
this.close(); | ||
this.emit('items:clear', this); | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
@use '~styles/colors.scss' as colors; | ||
@use '~styles/fonts.scss' as fonts; | ||
|
||
.dropdown { | ||
width: fit-content; | ||
|
||
font-family: fonts.$primaryFont; | ||
color: colors.$gray800; | ||
font-size: 1.4rem; | ||
font-weight: fonts.$semiBold; | ||
|
||
position: relative; | ||
|
||
&--open { | ||
.dropdown__toggle { | ||
.dropdown__icon { | ||
rotate: 180deg; | ||
} | ||
} | ||
|
||
.dropdown__options { | ||
display: block; | ||
} | ||
} | ||
|
||
&:hover { | ||
cursor: pointer; | ||
} | ||
|
||
&__options { | ||
width: 100%; | ||
|
||
display: none; | ||
|
||
margin: 0; | ||
padding: 1rem; | ||
box-sizing: border-box; | ||
|
||
position: absolute; | ||
z-index: 2; | ||
|
||
list-style: none; | ||
|
||
background-color: rgb(255, 255, 255); | ||
|
||
box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.2); | ||
border-radius: 1.4rem; | ||
|
||
animation: dropdownAnimation 0.3s ease-out; | ||
} | ||
|
||
&__toggle { | ||
width: 100%; | ||
|
||
display: flex; | ||
gap: 2rem; | ||
|
||
justify-content: space-between; | ||
|
||
padding: 1rem; | ||
|
||
box-sizing: border-box; | ||
|
||
background-color: rgb(255, 255, 255); | ||
|
||
box-shadow: 0 0 5px 0 rgb(216, 216, 216); | ||
border-radius: 1.4rem; | ||
|
||
.dropdown__icon { | ||
color: colors.$gray600; | ||
|
||
transition: transform 0.4s ease-out; | ||
} | ||
|
||
.dropdown__selected { | ||
&--label { | ||
color: colors.$gray600; | ||
font-weight: 400; | ||
} | ||
} | ||
} | ||
} | ||
|
||
@keyframes dropdownAnimation { | ||
from { | ||
transform: translateY(-2.5rem); | ||
opacity: 0; | ||
} | ||
|
||
to { | ||
transform: translateY(0); | ||
opacity: 1; | ||
} | ||
} |
Oops, something went wrong.