|
|
|
const { getColor } = require('./themes')
|
|
|
|
const { qs } = require('../utils')
|
|
|
|
const { rgb2hsl, hex2rgb, rgb2hex, hsl2rgb } = require('../lib/color_utils')
|
|
|
|
|
|
|
|
module.exports = function initButtons (input) {
|
|
|
|
let container = qs('#action-buttons')
|
|
|
|
|
|
|
|
// current color palette
|
|
|
|
let palette = []
|
|
|
|
|
|
|
|
// button labels
|
|
|
|
let labels = []
|
|
|
|
|
|
|
|
// button colors
|
|
|
|
let colors = {}
|
|
|
|
|
|
|
|
// button elements
|
|
|
|
let buttons = []
|
|
|
|
|
|
|
|
// add a button element
|
|
|
|
let pushButton = function pushButton () {
|
|
|
|
let button = document.createElement('button')
|
|
|
|
button.classList.add('action-button')
|
|
|
|
button.setAttribute('data-n', buttons.length)
|
|
|
|
buttons.push(button)
|
|
|
|
container.appendChild(button)
|
|
|
|
|
|
|
|
button.addEventListener('click', e => {
|
|
|
|
// might as well use the attribute ¯\_(ツ)_/¯
|
|
|
|
let index = +button.getAttribute('data-n')
|
|
|
|
input.sendButton(index)
|
|
|
|
|
|
|
|
e.target.blur() // if it keeps focus, spacebar will push it
|
|
|
|
})
|
|
|
|
|
|
|
|
// this prevents button retaining focus after half-click/drag-away
|
|
|
|
button.addEventListener('mouseleave', e => {
|
|
|
|
e.target.blur()
|
|
|
|
})
|
|
|
|
|
|
|
|
return button
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove a button element
|
|
|
|
let popButton = function popButton () {
|
|
|
|
let button = buttons.pop()
|
|
|
|
button.parentNode.removeChild(button)
|
|
|
|
}
|
|
|
|
|
|
|
|
// sync with DOM
|
|
|
|
let update = function updateButtons () {
|
|
|
|
if (labels.length > buttons.length) {
|
|
|
|
for (let i = buttons.length; i < labels.length; i++) {
|
|
|
|
pushButton()
|
|
|
|
}
|
|
|
|
} else if (buttons.length > labels.length) {
|
|
|
|
for (let i = buttons.length; i > labels.length; i--) {
|
|
|
|
popButton()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let i = 0; i < labels.length; i++) {
|
|
|
|
let label = labels[i].trim()
|
|
|
|
let button = buttons[i]
|
|
|
|
let color = colors[i]
|
|
|
|
|
|
|
|
button.textContent = label || '\u00a0' // label or nbsp
|
|
|
|
|
|
|
|
if (!label) button.classList.add('inactive')
|
|
|
|
else button.classList.remove('inactive')
|
|
|
|
|
|
|
|
// 0 or undefined can be used to disable custom color
|
|
|
|
if (Number.isFinite(color) && color !== 0) {
|
|
|
|
const clr = getColor(color, palette)
|
|
|
|
button.style.background = clr
|
|
|
|
|
|
|
|
// darken the color a bit for the 3D side
|
|
|
|
const hsl = rgb2hsl(...hex2rgb(clr))
|
|
|
|
const hex = rgb2hex(...hsl2rgb(hsl[0], hsl[1], hsl[2] * 0.7))
|
|
|
|
button.style.boxShadow = `0 3px 0 ${hex}`
|
|
|
|
} else {
|
|
|
|
button.style.background = null
|
|
|
|
button.style.boxShadow = null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
update,
|
|
|
|
get labels () {
|
|
|
|
return labels
|
|
|
|
},
|
|
|
|
set labels (value) {
|
|
|
|
labels = value
|
|
|
|
update()
|
|
|
|
},
|
|
|
|
get colors () {
|
|
|
|
return colors
|
|
|
|
},
|
|
|
|
set colors (value) {
|
|
|
|
colors = value
|
|
|
|
update()
|
|
|
|
},
|
|
|
|
get palette () {
|
|
|
|
return palette
|
|
|
|
},
|
|
|
|
set palette (value) {
|
|
|
|
palette = value
|
|
|
|
update()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|