UNPKG

@atlassian/aui

Version:

Atlassian User Interface Framework

135 lines (116 loc) 3.65 kB
'use strict'; import skate from 'skatejs'; import _ from './underscore'; const SIZE = { SMALL: { name: 'small', px: 20, radius: 9, }, MEDIUM: { name: 'medium', px: 30, radius: 13.5, }, LARGE: { name: 'large', px: 50, radius: 22.5, }, }; const DEFAULTS = { filled: false, size: SIZE.MEDIUM.name, }; function setMiddleTop(element) { const svg = element.querySelector('svg'); const parent = element.parentNode; const svgDomRect = svg.getBoundingClientRect(); const parentDomRect = parent.getBoundingClientRect(); const currentSpinnerTop = svgDomRect.top - parentDomRect.top; svg.style.top = `${(parentDomRect.height - svgDomRect.height) / 2 - currentSpinnerTop}px`; } function removeMiddleTop(element) { element.querySelector('svg').style.top = '0px'; } function validateSize(size) { let result = SIZE.MEDIUM.name; size = size.toLowerCase(); const possibleSizes = Object.keys(SIZE).map(key => key.toLowerCase()); if (possibleSizes.indexOf(size) > -1) { result = size; } return result; } function setSize(element, size, radius) { const svg = element.querySelector('svg'); const circle = element.querySelector('circle'); svg.setAttribute('size', size); svg.setAttribute('height', size); svg.setAttribute('width', size); svg.setAttribute('viewBox', `0 0 ${size} ${size}`); const circleSize = size / 2; circle.setAttribute('cx', circleSize); circle.setAttribute('cy', circleSize); circle.setAttribute('r', radius); } function refresh(element) { if (element._data.IS_COMPONENT_ATTACHED) { const { px, radius } = _.find(SIZE, s => s.name === element._data.size) || SIZE.MEDIUM; setSize(element, px, radius); if (element._data.filled) { setMiddleTop(element); } else { removeMiddleTop(element); } } } skate('aui-spinner', { template(element) { element._data.IS_COMPONENT_ATTACHED = false; element.innerHTML = `<div class="aui-spinner spinner"> <svg focusable="false" size="${SIZE.MEDIUM.px}" height="${SIZE.MEDIUM.px}" width="${SIZE.MEDIUM.px}" viewBox="0 0 ${SIZE.MEDIUM.px} ${SIZE.MEDIUM.px}"> <circle cx="${SIZE.MEDIUM.px / 2}" cy="${SIZE.MEDIUM.px / 2}" r="${SIZE.MEDIUM.radius}"></circle> </svg> </div>`; if (!element.hasAttribute('size')) { element.setAttribute('size', SIZE.MEDIUM.name); } }, attached(element) { element._data.IS_COMPONENT_ATTACHED = true; refresh(element); }, attributes: { filled: { created: function(element) { element._data.filled = true; refresh(element); }, removed: function(element) { element._data.filled = false; refresh(element); } }, size(element, data) { element._data.size = validateSize(data.newValue); refresh(element); }, }, prototype: { get _data() { return this.__data || (this._data = _.defaults({}, DEFAULTS)); }, set _data(data) { return this.__data = data; }, set filled(isFilled) { !!isFilled ? this.setAttribute('filled', '') : this.removeAttribute('filled'); }, set size(newSize) { const size = validateSize(newSize); this.setAttribute('size', size); }, }, });