Skip to content

Commit

Permalink
migrate avatar to composition api
Browse files Browse the repository at this point in the history
  • Loading branch information
Haberkamp committed Sep 19, 2024
1 parent 70443d9 commit 6632a92
Showing 1 changed file with 141 additions and 160 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<span
ref="MtAvatar"
ref="avatarRef"
class="mt-avatar"
:class="'mt-avatar__' + variant"
:style="[avatarImage, avatarColor, avatarSize, avatarInitialsSize]"
Expand All @@ -10,16 +10,27 @@
<span v-if="showInitials" class="mt-avatar__initials">
{{ avatarInitials }}
</span>

<span v-if="showPlaceholder">
<mt-icon color="var(--color-icon-brand-default)" name="default-avatar-single" />
<mt-icon name="regular-user" />
</span>
</slot>
</span>
</template>

<script lang="ts">
<script setup lang="ts">
import cloneDeep from "lodash-es/cloneDeep";
import { defineComponent, type StyleValue } from "vue";
import MtIcon from "../mt-icon/mt-icon.vue";
import {
reactive,
computed,
onMounted,
ref,
watch,
nextTick,
type CSSProperties,
type PropType,
} from "vue";
const colors = [
"#FFD700",
Expand All @@ -36,172 +47,142 @@ const colors = [
"#3CCA88",
];
export default defineComponent({
name: "MtAvatar",
props: {
color: {
type: String,
required: false,
default: "",
},
size: {
type: String,
required: false,
default: null,
},
firstName: {
type: String,
required: false,
default: "",
},
lastName: {
type: String,
required: false,
default: "",
},
imageUrl: {
type: String,
required: false,
default: null,
},
placeholder: {
type: Boolean,
required: false,
default: false,
},
sourceContext: {
type: Object,
required: false,
default: null,
},
variant: {
type: String,
required: false,
default: "circle",
validator: (value: string) => ["circle", "square"].includes(value),
},
const props = defineProps({
color: {
type: String,
required: false,
default: "",
},
data() {
return {
fontSize: 16,
lineHeight: 16,
};
size: {
type: String,
required: false,
default: null,
},
computed: {
avatarSize(): {
width: string;
height: string;
} {
return {
width: this.size,
height: this.size,
};
},
avatarInitials(): string {
const firstNameLetter = this.firstName ? this.firstName[0] : "";
const lastNameLetter = this.lastName ? this.lastName[0] : "";
return firstNameLetter + lastNameLetter;
},
avatarInitialsSize(): {
"font-size": string;
"line-height": string;
} {
return {
"font-size": `${this.fontSize}px`,
"line-height": `${this.lineHeight}px`,
};
},
avatarImage():
| {
"background-image": string;
}
| StyleValue {
if (this.imageUrl) {
return { "background-image": `url('${this.imageUrl}')` };
}
if (!this.sourceContext?.avatarMedia?.url) {
return {};
}
const avatarMedia = cloneDeep(this.sourceContext.avatarMedia);
// @ts-expect-error - thumbnails exists
const thumbnailImage = avatarMedia.thumbnails.sort((a, b) => a.width - b.width)[0];
const previewImageUrl = thumbnailImage ? thumbnailImage.url : avatarMedia.url;
return { "background-image": `url('${previewImageUrl}')` };
},
avatarColor(): {
"background-color": string;
} {
if (this.color.length) {
return {
"background-color": this.color,
};
}
const firstNameLength = this.firstName ? this.firstName.length : 0;
const lastNameLength = this.lastName ? this.lastName.length : 0;
const nameLength = firstNameLength + lastNameLength;
const color = colors[nameLength % colors.length];
return {
"background-color": color,
};
},
hasAvatarImage(): boolean {
// @ts-expect-error - background-image exists in avatarImage
return !!this.avatarImage && !!this.avatarImage["background-image"];
},
showPlaceholder(): boolean {
return this.placeholder && !this.hasAvatarImage;
},
showInitials(): boolean {
return !this.placeholder && !this.hasAvatarImage;
},
firstName: {
type: String,
required: false,
default: "",
},
watch: {
size() {
this.$nextTick(() => {
this.generateAvatarInitialsSize();
});
},
lastName: {
type: String,
required: false,
default: "",
},
mounted() {
this.mountedComponent();
imageUrl: {
type: String,
required: false,
default: null,
},
placeholder: {
type: Boolean,
required: false,
default: false,
},
sourceContext: {
type: Object as PropType<{
avatarMedia: { url: string; thumbnails: { width: number; url: string }[] } | undefined;
}>,
required: false,
default: null,
},
variant: {
type: String,
required: false,
default: "circle",
validator: (value: string) => ["circle", "square"].includes(value),
},
});
const sizes = reactive({
fontSize: 16,
lineHeight: 16,
});
const avatarSize = computed(() => ({
width: props.size,
height: props.size,
}));
const avatarInitials = computed(() => {
const firstNameLetter = props.firstName ? props.firstName[0] : "";
const lastNameLetter = props.lastName ? props.lastName[0] : "";
methods: {
mountedComponent() {
this.generateAvatarInitialsSize();
},
return firstNameLetter + lastNameLetter;
});
const avatarInitialsSize = computed(() => ({
"font-size": `${sizes.fontSize / 16}rem`,
"line-height": `${sizes.lineHeight / 16}rem`,
}));
generateAvatarInitialsSize() {
if (!this.$refs.MtAvatar) {
return;
}
const avatarRef = ref<HTMLElement | null>(null);
function generateAvatarInitialsSize() {
if (!avatarRef.value) return;
// @ts-expect-error - offsetHeight exists on element
const avatarSize = this.$refs.MtAvatar.offsetHeight;
const avatarSize = avatarRef.value.offsetHeight;
this.fontSize = Math.round(avatarSize * 0.4);
this.lineHeight = Math.round(avatarSize * 0.98);
},
sizes.fontSize = Math.round(avatarSize * 0.4);
sizes.lineHeight = Math.round(avatarSize * 0.98);
}
onMounted(() => {
generateAvatarInitialsSize();
});
watch(
() => props.size,
() => {
nextTick(() => {
generateAvatarInitialsSize();
});
},
);
const avatarImage = computed<CSSProperties>(() => {
if (props.imageUrl) {
return { "background-image": `url('${props.imageUrl}')` };
}
if (!props.sourceContext?.avatarMedia?.url) {
return {};
}
const avatarMedia = cloneDeep(props.sourceContext.avatarMedia);
const thumbnailImage = avatarMedia.thumbnails.sort((a, b) => a.width - b.width)[0];
const previewImageUrl = thumbnailImage ? thumbnailImage.url : avatarMedia.url;
return { "background-image": `url('${previewImageUrl}')` };
});
const hasAvatarImage = computed(() => {
return !!avatarImage.value && !!avatarImage.value["background-image"];
});
const showPlaceholder = computed(() => {
return props.placeholder && !hasAvatarImage.value;
});
const showInitials = computed(() => {
return !props.placeholder && !hasAvatarImage.value;
});
const avatarColor = computed<CSSProperties>(() => {
if (props.color.length) {
return {
"background-color": props.color,
};
}
const firstNameLength = props.firstName ? props.firstName.length : 0;
const lastNameLength = props.lastName ? props.lastName.length : 0;
const nameLength = firstNameLength + lastNameLength;
const color = colors[nameLength % colors.length];
return {
"background-color": color,
};
});
</script>

Expand Down

0 comments on commit 6632a92

Please sign in to comment.