ldc-crm/resources/ts/bo/components/ClaimMessageCollapseComponent.vue
2025-08-04 16:03:38 +02:00

98 lines
2.1 KiB
Vue

<template>
<div class="expandable-text">
<div
ref="textRef"
class="text-content"
:class="{ 'expanded overflow-scroll': expanded, 'overflow-hidden': !expanded }"
:style="expanded ? {} : { maxHeight: collapsedHeight + 'px' }"
>
{{ text }}
</div>
<button
v-if="needsToggle"
class="btn btn-sm btn-link toggle-button p-0"
@click="expanded = !expanded"
>
{{ expanded ? trans.methods.__('Voir moins') : trans.methods.__('Voir plus') }}
</button>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, useAttrs, watch, computed, nextTick } from "vue";
import trans from "./../../modules/trans";
defineOptions({
name: "ClaimMessageCollapseComponent",
});
// * ATTRIBUTES
const attrs = useAttrs();
// * PROPS
const props = defineProps({
message: {
type: String,
default: "",
},
lineHeight: {
type: Number,
default: 24,
},
collapsedLines: {
type: Number,
default: 2,
},
});
// * REFS
const textRef = ref<HTMLElement | null>(null);
// * DATA
const text = ref<string>(props.message);
const lineHeight = ref<number>(props.lineHeight);
const collapsedLines = ref<number>(props.collapsedLines);
const expanded = ref(false);
const needsToggle = ref(false);
// * COMPUTED
const isUsedWithProps = computed<boolean>(() => attrs.json === undefined);
const collapsedHeight = computed(() => lineHeight.value * collapsedLines.value);
const checkOverflow = () => {
if (textRef.value) {
needsToggle.value = textRef.value.scrollHeight > collapsedHeight.value;
}
};
onMounted(() => {
const json = String(attrs.json ?? "{}"),
data = JSON.parse(json);
if (!isUsedWithProps.value) {
text.value = data.message;
}
nextTick(() => {
checkOverflow();
});
});
watch(() => text, () => {
nextTick(() => {
checkOverflow();
});
});
</script>
<style scoped lang="scss">
.expandable-text {
.text-content {
transition: max-height 0.3s ease-out;
white-space: pre-wrap;
max-height: 0;
}
.text-content.expanded {
max-height: 20rem;
}
}
</style>