UNPKG

activator-oce-exporter

Version:

Extract Activator binder and convert it to valid OCE mono pacakge

231 lines (207 loc) 6.45 kB
import { getValueObject } from '../utils'; import { FusionLogger } from './fusion-logger'; import { FusionBase } from '../base'; export class FusionAligner { static get config() { return { vertical: [ 'top', 'center', 'bottom', ], horizontal: [ 'left', 'center', 'right', ], }; } /** * @param {Align} align * @returns {{styleFunc: String, positionFunc: String}} object with align functions */ static getAlignConfig({ direction, position }) { const directions = { vertical: { position: { top: 'alignSelfStart', center: 'alignSelfCenter', bottom: 'alignSelfEnd', }, style: 'getItemTopStyle', }, horizontal: { position: { left: 'justifyContentStart', center: 'justifyContentCenter', right: 'justifyContentEnd', }, style: 'getItemLeftStyle', }, }; return { styleFunc: directions[direction].style, positionFunc: directions[direction].position[position], }; } /** * Returns align config object. * @typedef {Object} Align * @property {String} direction - align direction * @property {String} position - align position */ /** * @param {string} query - element query * @param {Align} align * @returns {Array} array with aligned elements */ static applyAlignToItems({ query, align }) { const el = document.querySelector(`${query}`); let itemsToSave = []; if (el && this.isAlignPossible(align)) { itemsToSave = this.alignItems(el, align); } else { FusionLogger.error('Element is not exist or align object is invalid', 'FusionAligner'); } return itemsToSave; } /** * @param {Align} align */ static isAlignPossible({ direction, position }) { return this.config[direction] && this.config[direction].includes(position); } static alignSelfCenter({ parent, currentItem }) { return (parent.height - currentItem.height) / 2; } static justifyContentCenter({ parent }) { return (parent.width - parent.itemsTotalWidth) / 2; } static getParentBorderValue({ parent }) { const borderPropValue = parent.el.getAttribute('border-width'); return borderPropValue ? getValueObject(borderPropValue).num : 0; } static alignSelfStart({ parent }) { return this.getParentBorderValue({ parent }); } static justifyContentStart({ parent }) { return this.getParentBorderValue({ parent }); } static justifyContentEnd({ parent }) { return parent.width - parent.itemsTotalWidth - this.getParentBorderValue({ parent }); } static alignSelfEnd({ parent, currentItem }) { return parent.height - currentItem.height - this.getParentBorderValue({ parent }); } static getItemLeftStyle({ currentItem, currentItemsWidth }) { return { left: this.getValueWithUnit(currentItem.el, 'left', currentItemsWidth) }; } static getItemTopStyle(data) { const itemTop = this.getItemInitPosition(data); const { currentItem } = data; return { top: this.getValueWithUnit(currentItem.el, 'top', itemTop) }; } static getItemInitPosition(data) { const { align } = data; const { positionFunc } = this.getAlignConfig(align); return this[positionFunc](data); } static getValueWithUnit(el, style, value) { const styleValue = el.style[style] || el.style.getPropertyValue(`--${style}`); const { unit } = getValueObject(styleValue); return `${value}${unit}`; } static getItemData(item) { return { el: item, width: item.offsetWidth, height: item.offsetHeight, }; } static applyItemStyles(styles, item) { Object.keys(styles) .filter(key => item.style[key] !== styles[key]) .forEach((style) => { if (item.getAttribute(style)) { item.setElementProp(style, styles[style]); item.setAttribute(style, styles[style]); } else { item.style.setProperty(style, styles[style]); } }); } static getItemsForAlign(el) { return el.getChildComponents() .filter(item => item instanceof FusionBase) .sort((cur, next) => cur.offsetLeft - next.offsetLeft); } static isItemStyleChanged(styles, el) { return Object.keys(styles).some(key => el.style[key] !== styles[key]); } static getItemsTotalWidth(items) { return items.reduce((totalWidth, item) => { totalWidth += item.offsetWidth; return totalWidth; }, 0); } /** * Returns aligner config object. * @typedef {Object} Aligner * @property {Align} align * @property {Object} parent - data of the parent aligner element * @property {Object} currentItem - dynamic object with information about item to align * @property {Number} currentItemsWidth - dynamic field with current items width * @property {Array} alignedItems - dynamic array with items to align */ /** * @param {Element} el - parent wrapper with elements to align * @param {Align} align * @returns {Aligner} aligner */ static getAlignerData(el, { direction, position }) { const { width, height } = el.getBoundingClientRect(); const items = this.getItemsForAlign(el); const itemsTotalWidth = this.getItemsTotalWidth(items); return { align: { direction, position, }, parent: { el, width, height, items, itemsTotalWidth, }, currentItem: { eL: null, width: 0, height: 0, }, currentItemsWidth: 0, alignedItems: [], }; } /** * @param {Element} el - parent wrapper with elements to align * @param {Align} align. * @returns {Array} array with aligned elements */ static alignItems(el, align) { const data = this.getAlignerData(el, align); data.parent.items.reduce((totalWidth, item) => { data.currentItem = this.getItemData(item); const { styleFunc } = this.getAlignConfig(align); data.currentItemsWidth = totalWidth; const styles = { ...this[styleFunc](data) }; if (this.isItemStyleChanged(styles, item)) { this.applyItemStyles(styles, item); data.alignedItems.push({ id: item.id, styles }); } totalWidth += data.currentItem.width; return totalWidth; }, this.getItemInitPosition(data)); return data.alignedItems; } }