vue3-avatar
Version:
A user avatar component for vue3. By default it uses light colors for Text and dark colors for Background.
258 lines (224 loc) • 9.34 kB
JavaScript
import { openBlock, createElementBlock, normalizeStyle, toDisplayString, createCommentVNode } from 'vue';
const lightColors = ["#F0F8FF", "#FAEBD7", "#00FFFF", "#7FFFD4", "#F0FFFF", "#F5F5DC", "#FFE4C4", "#FFEBCD", "#DEB887", "#5F9EA0", "#7FFF00", "#D2691E", "#FF7F50", "#6495ED", "#FFF8DC", "#00FFFF", "#B8860B", "#A9A9A9", "#A9A9A9", "#BDB76B", "#FF8C00", "#E9967A", "#8FBC8F", "#00CED1", "#FF1493", "#00BFFF", "#1E90FF", "#FFFAF0", "#FF00FF", "#DCDCDC", "#F8F8FF", "#FFD700", "#DAA520", "#808080", "#808080", "#ADFF2F", "#F0FFF0", "#FF69B4", "#CD5C5C", "#FFFFF0", "#F0E68C", "#E6E6FA", "#FFF0F5", "#7CFC00", "#FFFACD", "#ADD8E6", "#F08080", "#E0FFFF", "#FAFAD2", "#D3D3D3", "#D3D3D3", "#90EE90", "#FFB6C1", "#FFA07A", "#20B2AA", "#87CEFA", "#B0C4DE", "#FFFFE0", "#00FF00", "#32CD32", "#FAF0E6", "#FF00FF", "#66CDAA", "#BA55D3", "#9370D8", "#3CB371", "#7B68EE", "#00FA9A", "#48D1CC", "#F5FFFA", "#FFE4E1", "#FFE4B5", "#FFDEAD", "#FDF5E6", "#FFA500", "#FF4500", "#DA70D6", "#EEE8AA", "#98FB98", "#AFEEEE", "#D87093", "#FFEFD5", "#FFDAB9", "#CD853F", "#FFC0CB", "#DDA0DD", "#B0E0E6", "#FF0000", "#BC8F8F", "#FA8072", "#F4A460", "#FFF5EE", "#C0C0C0", "#87CEEB", "#FFFAFA", "#00FF7F", "#D2B48C", "#D8BFD8", "#FF6347", "#40E0D0", "#EE82EE", "#F5DEB3", "#FFFFFF", "#F5F5F5", "#FFFF00", "#9ACD32"];
const darkColors = ["#000000", "#0000FF", "#8A2BE2", "#A52A2A", "#DC143C", "#00008B", "#008B8B", "#006400", "#8B008B", "#556B2F", "#9932CC", "#8B0000", "#483D8B", "#2F4F4F", "#2F4F4F", "#9400D3", "#696969", "#696969", "#B22222", "#228B22", "#008000", "#4B0082", "#800000", "#0000CD", "#C71585", "#191970", "#000080", "#808000", "#6B8E23", "#800080", "#4169E1", "#8B4513", "#2E8B57", "#A0522D", "#6A5ACD", "#708090", "#708090", "#4682B4", "#008080"];
const BORDERCOLORS = {
ONLINE: "green",
OFFLINE: "grey",
AWAY: "orange",
BUSY: "red"
};
var script = {
name: "Avatar",
props: {
name: {
type: String,
required: true
},
color: {
type: String
},
background: {
type: String
},
size: {
type: Number,
default: 40
},
inverted: {
type: Boolean,
default: false
},
inline: {
type: Boolean,
default: false
},
rounded: {
type: Boolean,
default: true
},
imageSrc: {
type: String
},
border: {
type: Boolean,
default: true
},
borderColor: {
type: String,
default: "white"
},
customAvatarStyle: {
type: Object,
default: () => ({})
},
status: {
type: String,
default: null,
validator: function (value) {
return ["away", "online", "offline", "busy"].includes(value);
}
},
customStatusStyle: {
type: Object,
default: () => ({})
},
sameBorder: {
type: Boolean,
default: false
}
},
data: () => {
return {
imageError: false
};
},
computed: {
statusStyle() {
const defaultStatusStyle = {
height: `${this.size / 4}px`,
width: `${this.size / 4}px`,
backgroundColor: this.statusBackgroundColor,
border: `${this.size / 30}px solid ${this.sameBorder ? this.borderColor : 'white'}`
};
return Object.assign({}, defaultStatusStyle, this.customStatusStyle);
},
imageStyle() {
const defaultImageStyle = {
display: this.inline ? 'inline-flex' : 'flex',
borderRadius: this.rounded ? '50%' : '0',
margin: 0,
padding: 0,
alignItems: 'center',
justifyContent: 'center',
border: this.border ? `${this.size / 20}px solid ${this.borderColor}` : 'none'
};
return Object.assign({}, defaultImageStyle, this.customAvatarStyle);
},
avatarStyle() {
const defaultAvatarStyle = {
color: this.displayColor,
width: this.size + 'px',
height: this.size + 'px',
fontSize: this.fontSize + 'px',
background: this.displayBackground,
display: this.inline && 'inline-flex',
borderRadius: this.rounded && '50%',
border: this.border && `${this.size / 20}px solid ${this.borderColor}`
};
return Object.assign({}, defaultAvatarStyle, this.customAvatarStyle);
},
fontSize() {
const size = this.size || 40;
if (this.displayName.length == 1) return size / 2;else if (this.displayName.length == 2) return size / 2.5;
if (this.displayName.length == 3) return size / 3;else return 14;
},
displayName() {
let words = this.name.trim().split(/[- ]/);
words = words.filter(word => word !== "");
if (words.length >= 3) return words[0][0].toUpperCase() + words[1][0].toUpperCase() + words[words.length - 1][0].toUpperCase();else if (words.length == 2) return words[0][0].toUpperCase() + words[1][0].toUpperCase();else if (words.length == 1) return words[0][0].toUpperCase();else return "";
},
displayBackground() {
return this.background ? this.background : this.inverted ? this.lightColor : this.darkColor;
},
displayColor() {
return this.color ? this.color : this.inverted ? this.darkColor : this.lightColor;
},
asciiValue() {
const username = this.name.trim();
let ascii = 0;
for (let index = 0; index < username.length; index++) ascii += username.charCodeAt(index);
return ascii;
},
darkColor() {
return darkColors[this.asciiValue % darkColors.length];
},
lightColor() {
return lightColors[this.asciiValue % lightColors.length];
},
statusBackgroundColor() {
let color;
switch (this.status.toLowerCase()) {
case "away":
color = BORDERCOLORS.AWAY;
break;
case "online":
color = BORDERCOLORS.ONLINE;
break;
case "offline":
color = BORDERCOLORS.OFFLINE;
break;
default:
color = BORDERCOLORS.BUSY;
}
return color;
}
},
methods: {
showImage() {
return this.imageSrc && !this.imageError;
}
}
};
const _hoisted_1 = {
class: "container"
};
const _hoisted_2 = ["height", "width", "src", "alt"];
function render(_ctx, _cache, $props, $setup, $data, $options) {
return openBlock(), createElementBlock("div", _hoisted_1, [$options.showImage() ? (openBlock(), createElementBlock("img", {
key: 0,
style: normalizeStyle($options.imageStyle),
height: $props.size,
width: $props.size,
src: $props.imageSrc,
alt: $options.displayName,
onError: _cache[0] || (_cache[0] = $event => _ctx.imageError = true)
}, null, 44, _hoisted_2)) : (openBlock(), createElementBlock("div", {
key: 1,
style: normalizeStyle($options.avatarStyle),
class: "avatar noselect"
}, toDisplayString($options.displayName), 5)), $props.status ? (openBlock(), createElementBlock("div", {
key: 2,
class: "status-indicator",
style: normalizeStyle($options.statusStyle)
}, null, 4)) : createCommentVNode("", true)]);
}
function styleInject(css, ref) {
if ( ref === void 0 ) ref = {};
var insertAt = ref.insertAt;
if (!css || typeof document === 'undefined') { return; }
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
if (insertAt === 'top') {
if (head.firstChild) {
head.insertBefore(style, head.firstChild);
} else {
head.appendChild(style);
}
} else {
head.appendChild(style);
}
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
}
var css_248z = "\n@import url(\"https://fonts.googleapis.com/css2?family=Domine:wght@700&display=swap\");\n.avatar[data-v-3b51803e] {\n font-family: \"Domine\", serif;\n color: white;\n background: navy;\n font-size: 14px;\n width: 45px;\n height: 45px;\n border-radius: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 700;\n}\n.noselect[data-v-3b51803e] {\n -webkit-touch-callout: none; /* iOS Safari */\n -webkit-user-select: none; /* Safari */\n -khtml-user-select: none; /* Konqueror HTML */\n -moz-user-select: none; /* Old versions of Firefox */\n -ms-user-select: none; /* Internet Explorer/Edge */\n user-select: none; /* Non-prefixed version, currently supported by Chrome, Edge, Opera and Firefox */\n}\n.container[data-v-3b51803e] {\n position:relative;\n}\n.status-indicator[data-v-3b51803e] {\n position: absolute;\n bottom: 0;\n left: 0;\n border-radius: 50%;\n}\n";
styleInject(css_248z);
script.render = render;
script.__scopeId = "data-v-3b51803e";
// Import vue component
// IIFE injects install function into component, allowing component
// to be registered via Vue.use() as well as Vue.component(),
var entry_esm = /*#__PURE__*/(() => {
// Get component instance
const installable = script; // Attach install function executed by Vue.use()
installable.install = app => {
app.component('Avatar', installable);
};
return installable;
})(); // It's possible to expose named exports when writing components that can
// also be used as directives, etc. - eg. import { RollupDemoDirective } from 'rollup-demo';
// export const RollupDemoDirective = directive;
export { entry_esm as default };