rabbit-simple-ui
Version:
A simple UI component library based on JavaScript
141 lines (105 loc) • 4.09 kB
text/typescript
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { $el, bind, getStrTypeAttr, removeAttrs, setCss, setHtml } from '../../dom-utils';
import { warn } from '../../mixins';
import { type, validComps } from '../../utils';
import PREFIX from '../prefix';
interface Config {
config(
el: string
): {
events({ onError }: AvatarEvent): void;
};
}
interface AvatarEvent {
onError: (event: Event) => void;
}
class Avatar implements Config {
readonly VERSION: string;
readonly COMPONENTS: NodeListOf<Element>;
constructor() {
this.VERSION = 'v1.0';
this.COMPONENTS = $el('r-avatar', { all: true });
this._create(this.COMPONENTS);
}
public config(
el: string
): {
events({ onError }: AvatarEvent): void;
} {
const target = $el(el) as HTMLElement;
validComps(target, 'avatar');
const AvatarImage = target.querySelector('img');
return {
events({ onError }: AvatarEvent) {
if (!AvatarImage) {
warn(
`Unable to add an event where the image failed to load for the current avatar --> "${el}"`
);
return;
}
bind(AvatarImage, 'error', (event: Event) => onError && type.isFn(onError, event));
}
};
}
private _create(COMPONENTS: NodeListOf<Element>): void {
COMPONENTS.forEach((node) => {
const { icon, src, alt, size } = this._attrs(node);
this._setSize(node, size);
this._setIcon(node, icon);
this._setImage(node, src, alt);
this._setText(node, icon, src);
removeAttrs(node, ['icon', 'src', 'alt']);
});
}
private _setSize(node: Element, size: string): void {
if (!size) return;
const _size = Number(size);
if (!_size) return;
setCss(node, 'width', `${_size}px`);
setCss(node, 'height', `${_size}px`);
setCss(node, 'fontSize', `${_size / 2}px`);
node.removeAttribute('size');
}
private _setIcon(node: Element, icon: string): void {
if (!icon) return;
node.classList.add(`${PREFIX.avatar}-icon`);
const AvatarIcon = `<i class="${PREFIX.icon} ${PREFIX.icon}-${icon}"></i>`;
setHtml(node, AvatarIcon);
}
private _setImage(node: Element, src: string, alt: string): void {
if (!src) return;
node.classList.add(`${PREFIX.avatar}-image`);
const AvatarImage = `<img src="${src}" alt="${alt}" />`;
setHtml(node, AvatarImage);
}
private _setText(node: Element, icon: string, src: string): void {
if (icon || src) return;
if (!setHtml(node)) return;
const text = setHtml(node);
const AvatarText = `<span class="${PREFIX.avatar}-string">${text}</span>`;
setHtml(node, AvatarText);
this._setScale(node);
}
// 防止字符型头像的字体溢出边界
private _setScale(node: Element) {
const children = node.querySelector(`.${PREFIX.avatar}-string`)! as HTMLElement;
if (!children) return;
const avatarWidth = node.getBoundingClientRect().width;
const childrenWidth = children.offsetWidth;
if (avatarWidth - 8 < childrenWidth) {
const newScale = `scale(${(avatarWidth - 8) / childrenWidth}) translateX(-50%)`;
setCss(children, 'transform', `${newScale}`);
} else {
setCss(children, 'transform', 'scale(1) translateX(-50%)');
}
}
private _attrs(node: Element) {
return {
icon: getStrTypeAttr(node, 'icon', ''),
src: getStrTypeAttr(node, 'src', ''),
alt: getStrTypeAttr(node, 'alt', ''),
size: getStrTypeAttr(node, 'size', '')
};
}
}
export default Avatar;