@atlassian/aui
Version:
Atlassian User Interface Framework
135 lines (116 loc) • 3.65 kB
JavaScript
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);
},
},
});
;