Skip to content

Commit

Permalink
Merge pull request #82 from takenet/feature/select-with-image
Browse files Browse the repository at this point in the history
Feature/select with image
  • Loading branch information
samwx authored Nov 20, 2019
2 parents f2fa2d9 + 53aca1d commit 5ea8c19
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 45 deletions.
18 changes: 18 additions & 0 deletions sandbox/blipSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,45 @@ import { BlipSelect } from '../src/components/blipSelect'
const amazingSelect = document.getElementById('select')
const selectInstance = new BlipSelect({
onSelectOption: ($event) => console.log($event),
placeholderIcon: '<img src="https://png.pngtree.com/svg/20170418/work_155602.png" />',
descriptionPosition: 'bottom',
canAddOptions: {
text: 'Criar organização',
alwaysEnabled: true,
},
clearAfterAdd: false,
onAddOption: ({ $event: { value, label, element } }) => console.log(value, label, element),
})
const select = selectInstance.render({
options: [
{
label: 'Option 1',
description: 'My description here',
icon: '<img src="https://png.pngtree.com/svg/20170418/work_155602.png" />',
value: 'opt1',
},
{
label: 'Option 12',
description: 'My description here',
icon: '<img src="https://png.pngtree.com/svg/20170418/work_155602.png" />',
value: 'opt2',
},
{
label: 'Option 3',
description: 'My description here',
icon: '<img src="https://png.pngtree.com/svg/20170418/work_155602.png" />',
value: 'opt3',
},
{
label: 'Option 4',
description: 'My description here',
icon: '<img src="https://png.pngtree.com/svg/20170418/work_155602.png" />',
value: 'opt4',
},
{
label: 'Option 5',
description: 'My description here',
icon: '<img src="https://png.pngtree.com/svg/20170418/work_155602.png" />',
value: 'opt5',
},
],
Expand Down
2 changes: 1 addition & 1 deletion sandbox/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ import './blipTag'
import './blipTags'
import './blipLoading'
import './blipTabs'
import './blipToasts'
// import './blipToasts'
import './blipCarousel'
15 changes: 10 additions & 5 deletions src/components/blipSelect/CreatableOptionsList.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class CreatebleOptionsList extends Component {
newOption: '',
addOptionText: '',
emptyMessage: '',
alwaysEnabled: false,
blockNewEntries: false,
OptionCreator: undefined,
}
Expand All @@ -34,6 +35,7 @@ export class CreatebleOptionsList extends Component {
return new OptionCreator({
onOptionClick: this.options.onOptionClick,
onTryAccessInput: this.options.onTryAccessInput,
descriptionPosition: this.props.descriptionPosition,
}).render(optionProps)
}

Expand All @@ -57,10 +59,13 @@ export class CreatebleOptionsList extends Component {
* Check if current state allows to add new option
*/
_canAddOption(newOption) {
return newOption &&
newOption.trim() !== '' &&
!this.props.blockNewEntries &&
!this.props.options.some(o => o.label === newOption)
return (
this.options.alwaysEnabled ||
(newOption &&
newOption.trim() !== '' &&
!this.props.blockNewEntries &&
!this.props.options.some(o => o.label === newOption))
)
}

/**
Expand All @@ -76,7 +81,7 @@ export class CreatebleOptionsList extends Component {
*/
_renderAddOption(newOption) {
const addOptionHtml = this.options.addOptionText
? html`<small class="blip-prompt-add-option">${this.options.addOptionText}:</small>`
? html`<small class="blip-prompt-add-option">${this.options.addOptionText}</small>`
: ''

return this._canAddOption(newOption)
Expand Down
6 changes: 5 additions & 1 deletion src/components/blipSelect/OptionsList.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export class OptionsList extends Component {
this.props = {
options: [],
canAddOptions: false,
OptionCreator: SelectOption,
}
}

Expand All @@ -32,10 +33,13 @@ export class OptionsList extends Component {
...props,
}

const { OptionCreator } = this.props

const renderOption = (option) =>
new SelectOption({
new OptionCreator({
onOptionClick: this.options.onOptionClick,
onTryAccessInput: this.options.onTryAccessInput,
descriptionPosition: this.props.descriptionPosition,
}).render(option)

return html`
Expand Down
2 changes: 1 addition & 1 deletion src/components/blipSelect/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ new BlipSelect(element, {
canAddOptions: {
text: 'Add option',
},
onAddNewOption: ({ $event : { value, label, element }}) => console.log(value, label, element)
onAddOption: ({ $event : { value, label, element }}) => console.log(value, label, element)
})
```
---
Expand Down
23 changes: 20 additions & 3 deletions src/components/blipSelect/SelectOption.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { guid } from '@lib/utils'
import html from 'nanohtml'
import raw from 'nanohtml/raw'
import { OptionItem } from '../shared'

export class SelectOption extends OptionItem {
Expand All @@ -26,17 +27,33 @@ export class SelectOption extends OptionItem {
}

const fillOptionId = id => id || `blip-select__option-${guid()}`
const descriptionPosition = this.options.descriptionPosition || 'right'
const descriptionPositionClass = `blip-select__option--description-${descriptionPosition}`
const labelElement = html`<span class="blip-select__option__label">${this.props.label}</span>`
const descriptionElement = this.props.description ? html`<span class="blip-select__option__description">${this.props.description}</span>` : ''
const descriptionElement = this.props.description
? html`<span class="blip-select__option__description">${this.props.description}</span>`
: ''

const itemContentWithIcon = () => html`
<div class="blip-select__option--with-icon">
<div class="blip-select__option__icon">
${raw(this.props.icon)}
</div>
<div class="blip-select__option__content">
${labelElement}${descriptionElement}
</div>
</div>
`
const itemContent = () => html`${labelElement}${descriptionElement}`

return html`
<li tabindex="0"
onclick="${this.onOptionClick.bind(this)}"
onkeydown="${this.attachOptionKeyboardListeners.bind(this)}"
class="blip-select__option"
class="blip-select__option ${descriptionPositionClass}"
data-value="${this.props.value}"
id="${fillOptionId(this.props.id)}"
>${labelElement}${descriptionElement}</li>
>${this.props.icon ? itemContentWithIcon() : itemContent()}</li>
`
}

Expand Down
37 changes: 23 additions & 14 deletions src/components/blipSelect/index.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import Component from 'nanocomponent'
import { guid } from '@lib/utils'
import { OptionsList } from './OptionsList'
import { EventEmitter } from '@lib/eventEmitter'

import Component from 'nanocomponent'
import html from 'nanohtml'
import { CreatebleOptionsList } from './CreatableOptionsList'
import { SelectOption } from './SelectOption'

import raw from 'nanohtml/raw'
import ArrowDown from '../../img/arrow-down-slim.svg'

const ANIMATION_TIMEOUT = 300
export const blipSelectOptionClass = 'blip-select__option'

const ANIMATION_TIMEOUT = 300
const blipSelectOptionsClass = 'blip-select__options'
const blipSelectOptionOpenTopClass = 'blip-select__options--open-top'
export const blipSelectOptionClass = 'blip-select__option'
const blipSelectOptionSeletedClass = 'blip-select__option--selected'
const bpSelectHideLabelClass = 'bp-select-hide-label'
const bpSelectShowArrowClass = 'blip-select__show-arrow'
Expand All @@ -23,6 +21,7 @@ const bpCblipLightClass = 'bp-c-blip-light'
const bpInputWrapperFocusClass = 'bp-input-wrapper--focus'
const bpInputWrapperDisabledClass = 'bp-select-wrapper--disabled'
const bpInputWrapperInvalidClass = 'bp-select-wrapper--invalid'
const bpPlaceholderIconClass = 'bp-select-placeholder-icon'

export class BlipSelect extends Component {
/**
Expand All @@ -36,6 +35,8 @@ export class BlipSelect extends Component {
invalid: false,
enableBullet: false,
placeholder: 'Select...',
placeholderIcon: undefined,
descriptionPosition: 'right', // right || bottom
mode: 'select',
noResultsText: 'No results found',
clearAfterAdd: true, // Clear input after add new option
Expand Down Expand Up @@ -183,6 +184,7 @@ export class BlipSelect extends Component {
...this.props,
...props,
}

this.renderedOptionsList = this.optionsList.render(this._optionsListConfig())
const isReadOnly = () => this.configOptions.mode === 'select'
const hideLabelClass = () =>
Expand All @@ -193,9 +195,12 @@ export class BlipSelect extends Component {
(this.optionsList.props.options && this.optionsList.props.options.length > 0)
? bpSelectShowArrowClass
: ''

return html`
<div class="bp-input-wrapper blip-select ${this.props.disabled ? 'bp-select-wrapper--disabled' : ''}">
<div class="blip-select__shell">
${this.configOptions.placeholderIcon &&
raw(`<div class="${bpPlaceholderIconClass}">${this.configOptions.placeholderIcon}</div>`)}
<div class="blip-select__content">
<label class="bp-label bp-c-cloud bp-fw-bold ${hideLabelClass()}">${this.props.label}</label>
<input placeholder="${this.configOptions.placeholder}"
Expand Down Expand Up @@ -290,6 +295,7 @@ export class BlipSelect extends Component {
const defaults = {
options: this.props.options,
OptionCreator: this.configOptions.optionCreator,
descriptionPosition: this.configOptions.descriptionPosition,
}

return this.configOptions.canAddOptions
Expand Down Expand Up @@ -322,6 +328,7 @@ export class BlipSelect extends Component {
onTryAccessInput: () => this.input.focus(),
onAddOption: this._handleAddOption.bind(this),
addOptionText: this.configOptions.canAddOptions.text,
alwaysEnabled: this.configOptions.canAddOptions.alwaysEnabled,
})
}

Expand All @@ -345,12 +352,14 @@ export class BlipSelect extends Component {
$event: { newOption },
} = emitter

const newOptions = this.props.options.concat(newOption)
this.props.options = newOptions
if (newOption.value || newOption.label) {
const newOptions = this.props.options.concat(newOption)
this.props.options = newOptions

this.optionsList.render({
options: newOptions,
})
this.optionsList.render({
options: newOptions,
})
}

if (this.configOptions.clearAfterAdd) {
this.input.value = ''
Expand Down Expand Up @@ -678,11 +687,11 @@ export class BlipSelect extends Component {
const selectOptionsContainer = this.element.querySelector(
`.blip-select__options`,
)
selectOptionsContainer.style.display = 'block'
selectOptionsContainer.style.visibility = 'visible'

setTimeout(() => {
// Needed for animation
selectOptionsContainer.style.transform = 'scale(1)'
selectOptionsContainer.style.transform = 'scaleY(1)'
selectOptionsContainer.style.opacity = 1
})

Expand Down Expand Up @@ -737,12 +746,12 @@ export class BlipSelect extends Component {
// Callback invoked before select open
this.configOptions.onBeforeCloseSelect()

selectOptionsContainer.style.transform = 'scale(0)'
selectOptionsContainer.style.transform = 'scaleY(0)'
selectOptionsContainer.style.opacity = 0

setTimeout(() => {
// Needed for animation
selectOptionsContainer.style.display = 'none'
selectOptionsContainer.style.visibility = 'hidden'
selectOptionsContainer.classList.remove(blipSelectOptionOpenTopClass)
}, ANIMATION_TIMEOUT) // Milliseconds should be greater than value setted on transition css property

Expand Down
Loading

0 comments on commit 5ea8c19

Please sign in to comment.