visbug-lib
Version:
<p align="center"> <img src="./assets/visbug.png" width="300" height="300" alt="visbug"> <br> <a href="https://www.npmjs.org/package/visbug"><img src="https://img.shields.io/npm/v/visbug.svg?style=flat" alt="npm latest version number"></a> <a href
191 lines (173 loc) • 5.21 kB
JavaScript
import hotkeys from 'hotkeys-js'
import { metaKey, getStyle, showHideSelected } from '../utilities/'
const key_events = 'up,down,left,right'
.split(',')
.reduce((events, event) =>
`${events},${event},shift+${event}`
, '')
.substring(1)
const command_events = `${metaKey}+up,${metaKey}+down`
export function Font({selection}) {
hotkeys(key_events, (e, handler) => {
if (e.cancelBubble) return
e.preventDefault()
let selectedNodes = selection()
, keys = handler.key.split('+')
if (keys.includes('left') || keys.includes('right'))
keys.includes('shift')
? changeKerning(selectedNodes, handler.key)
: changeAlignment(selectedNodes, handler.key)
else
keys.includes('shift')
? changeLeading(selectedNodes, handler.key)
: changeFontSize(selectedNodes, handler.key)
})
hotkeys(command_events, (e, handler) => {
e.preventDefault()
let keys = handler.key.split('+')
changeFontWeight(selection(), keys.includes('up') ? 'up' : 'down')
})
hotkeys('cmd+b', e => {
selection().forEach(el =>
el.style.fontWeight =
el.style.fontWeight == 'bold'
? null
: 'bold')
})
hotkeys('cmd+i', e => {
selection().forEach(el =>
el.style.fontStyle =
el.style.fontStyle == 'italic'
? null
: 'italic')
})
return () => {
hotkeys.unbind(key_events)
hotkeys.unbind(command_events)
hotkeys.unbind('cmd+b,cmd+i')
hotkeys.unbind('up,down,left,right')
}
}
export function changeLeading(els, direction) {
els
.map(el => showHideSelected(el))
.map(el => ({
el,
style: 'lineHeight',
current: parseInt(getStyle(el, 'lineHeight')),
amount: 1,
negative: direction.split('+').includes('down'),
}))
.map(payload =>
Object.assign(payload, {
current: payload.current == 'normal' || isNaN(payload.current)
? 1.14 * parseInt(getStyle(payload.el, 'fontSize')) // document this choice
: payload.current
}))
.map(payload =>
Object.assign(payload, {
value: payload.negative
? payload.current - payload.amount
: payload.current + payload.amount
}))
.forEach(({el, style, value}) =>
el.style[style] = `${value}px`)
}
export function changeKerning(els, direction) {
els
.map(el => showHideSelected(el))
.map(el => ({
el,
style: 'letterSpacing',
current: parseFloat(getStyle(el, 'letterSpacing')),
amount: .1,
negative: direction.split('+').includes('left'),
}))
.map(payload =>
Object.assign(payload, {
current: payload.current == 'normal' || isNaN(payload.current)
? 0
: payload.current
}))
.map(payload =>
Object.assign(payload, {
value: payload.negative
? (payload.current - payload.amount).toFixed(2)
: (payload.current + payload.amount).toFixed(2)
}))
.forEach(({el, style, value}) =>
el.style[style] = `${value <= -2 ? -2 : value}px`)
}
export function changeFontSize(els, direction) {
els
.map(el => showHideSelected(el))
.map(el => ({
el,
style: 'fontSize',
current: parseInt(getStyle(el, 'fontSize')),
amount: direction.split('+').includes('shift') ? 10 : 1,
negative: direction.split('+').includes('down'),
}))
.map(payload =>
Object.assign(payload, {
font_size: payload.negative
? payload.current - payload.amount
: payload.current + payload.amount
}))
.forEach(({el, style, font_size}) =>
el.style[style] = `${font_size <= 6 ? 6 : font_size}px`)
}
const weightMap = {
normal: 2,
bold: 5,
light: 0,
"": 2,
"100":0,"200":1,"300":2,"400":3,"500":4,"600":5,"700":6,"800":7,"900":8
}
const weightOptions = [100,200,300,400,500,600,700,800,900]
export function changeFontWeight(els, direction) {
els
.map(el => showHideSelected(el))
.map(el => ({
el,
style: 'fontWeight',
current: getStyle(el, 'fontWeight'),
direction: direction.split('+').includes('down'),
}))
.map(payload =>
Object.assign(payload, {
value: payload.direction
? weightMap[payload.current] - 1
: weightMap[payload.current] + 1
}))
.forEach(({el, style, value}) =>
el.style[style] = weightOptions[value < 0 ? 0 : value >= weightOptions.length
? weightOptions.length
: value
])
}
const alignMap = {
start: 0,
left: 0,
center: 1,
right: 2,
}
const alignOptions = ['left','center','right']
export function changeAlignment(els, direction) {
els
.map(el => showHideSelected(el))
.map(el => ({
el,
style: 'textAlign',
current: getStyle(el, 'textAlign'),
direction: direction.split('+').includes('left'),
}))
.map(payload =>
Object.assign(payload, {
value: payload.direction
? alignMap[payload.current] - 1
: alignMap[payload.current] + 1
}))
.forEach(({el, style, value}) =>
el.style[style] = alignOptions[value < 0 ? 0 : value >= 2 ? 2: value])
}