UNPKG

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

213 lines (186 loc) 6.62 kB
import hotkeys from 'hotkeys-js' import { metaKey, getStyle } 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,${metaKey}+left,${metaKey}+right,${metaKey}+shift+up,${metaKey}+shift+down,${metaKey}+shift+left,${metaKey}+shift+right` export function Flex({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') ? changeHDistribution(selectedNodes, handler.key) : changeHAlignment(selectedNodes, handler.key) else keys.includes('shift') ? changeVDistribution(selectedNodes, handler.key) : changeVAlignment(selectedNodes, handler.key) }) hotkeys(command_events, (e, handler) => { e.preventDefault() let selectedNodes = selection() , keys = handler.key.split('+') if (keys.includes('left') || keys.includes('right')) keys.includes('shift') ? changeOrder(selectedNodes, handler.key) : changeDirection(selectedNodes, 'row') else keys.includes('shift') ? changeWrap(selectedNodes, handler.key) : changeDirection(selectedNodes, 'column') }) return () => { hotkeys.unbind(key_events) hotkeys.unbind(command_events) hotkeys.unbind('up,down,left,right') } } const ensureFlex = el => { el.style.display = 'flex' return el } const accountForOtherJustifyContent = (cur, want) => { if (want == 'align' && (cur != 'flex-start' && cur != 'center' && cur != 'flex-end')) cur = 'normal' else if (want == 'distribute' && (cur != 'space-around' && cur != 'space-between')) cur = 'normal' return cur } // todo: support reversing direction export function changeDirection(els, value) { els .map(ensureFlex) .map(el => { el.style.flexDirection = value }) } const h_alignMap = {normal: 0,'flex-start': 0,'center': 1,'flex-end': 2,} const h_alignOptions = ['flex-start','center','flex-end'] export function changeHAlignment(els, direction) { els .map(ensureFlex) .map(el => ({ el, style: 'justifyContent', current: accountForOtherJustifyContent(getStyle(el, 'justifyContent'), 'align'), direction: direction.split('+').includes('left'), })) .map(payload => Object.assign(payload, { value: payload.direction ? h_alignMap[payload.current] - 1 : h_alignMap[payload.current] + 1 })) .forEach(({el, style, value}) => el.style[style] = h_alignOptions[value < 0 ? 0 : value >= 2 ? 2: value]) } const v_alignMap = {normal: 0,'flex-start': 0,'center': 1,'flex-end': 2,} const v_alignOptions = ['flex-start','center','flex-end'] export function changeVAlignment(els, direction) { els .map(ensureFlex) .map(el => ({ el, style: 'alignItems', current: getStyle(el, 'alignItems'), direction: direction.split('+').includes('up'), })) .map(payload => Object.assign(payload, { value: payload.direction ? h_alignMap[payload.current] - 1 : h_alignMap[payload.current] + 1 })) .forEach(({el, style, value}) => el.style[style] = v_alignOptions[value < 0 ? 0 : value >= 2 ? 2: value]) } const h_distributionMap = {normal: 1,'space-around': 0,'': 1,'space-between': 2,} const h_distributionOptions = ['space-around','','space-between'] export function changeHDistribution(els, direction) { els .map(ensureFlex) .map(el => ({ el, style: 'justifyContent', current: accountForOtherJustifyContent(getStyle(el, 'justifyContent'), 'distribute'), direction: direction.split('+').includes('left'), })) .map(payload => Object.assign(payload, { value: payload.direction ? h_distributionMap[payload.current] - 1 : h_distributionMap[payload.current] + 1 })) .forEach(({el, style, value}) => el.style[style] = h_distributionOptions[value < 0 ? 0 : value >= 2 ? 2: value]) } const v_distributionMap = {normal: 1,'space-around': 0,'': 1,'space-between': 2,} const v_distributionOptions = ['space-around','','space-between'] export function changeVDistribution(els, direction) { els .map(ensureFlex) .map(el => ({ el, style: 'alignContent', current: getStyle(el, 'alignContent'), direction: direction.split('+').includes('up'), })) .map(payload => Object.assign(payload, { value: payload.direction ? v_distributionMap[payload.current] - 1 : v_distributionMap[payload.current] + 1 })) .forEach(({el, style, value}) => el.style[style] = v_distributionOptions[value < 0 ? 0 : value >= 2 ? 2: value]) } const orderMap = {row: 0, 'row-reverse': 1, column: 2, 'column-reverse': 3,} const orderOptions = ['row', 'row-reverse', 'column', 'column-reverse'] export function changeOrder(els, direction) { els .map(ensureFlex) .map(el => ({ el, style: 'flexDirection', current: getStyle(el, 'flexDirection'), direction: direction.split('+').includes('left'), })) .map(payload => Object.assign(payload, { value: payload.direction ? orderMap[payload.current] === 1 || orderMap[payload.current] === 3 ? orderMap[payload.current] : orderMap[payload.current] + 1 : orderMap[payload.current] === 0 || orderMap[payload.current] === 2 ? orderMap[payload.current] : orderMap[payload.current] - 1 })) .forEach(({el, style, value}) => el.style[style] = orderOptions[value]) } const wrapMap = {nowrap: 0, 'wrap': 1,} const wrapOptions = ['nowrap', 'wrap'] export function changeWrap(els, direction) { els .map(ensureFlex) .map(el => ({ el, style: 'flexWrap', current: getStyle(el, 'flexWrap'), direction: direction.split('+').includes('up'), })) .map(payload => Object.assign(payload, { value: payload.direction ? wrapMap[payload.current] === 0 ? wrapMap[payload.current] : wrapMap[payload.current] - 1 : wrapMap[payload.current] === 1 ? wrapMap[payload.current] : wrapMap[payload.current] + 1 })) .forEach(({el, style, value}) => el.style[style] = wrapOptions[value]) }