All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m7s
- Agregada prop 'align' al ReactionPicker (left/right) - Mensajes propios (fromMe): picker se alinea a la izquierda (right-0) - Mensajes recibidos: picker se alinea a la derecha (left-0) - Evita que el picker extienda la página horizontalmente
128 lines
4.2 KiB
Vue
128 lines
4.2 KiB
Vue
<template>
|
|
<div
|
|
v-if="visible"
|
|
class="absolute z-50 bg-[var(--wa-surface)] rounded-full shadow-lg border border-[var(--wa-border)] p-1 flex items-center gap-1"
|
|
:class="[
|
|
position === 'top' ? 'bottom-full mb-2' : 'top-full mt-2',
|
|
align === 'left' ? 'right-0' : 'left-0'
|
|
]"
|
|
@click.stop
|
|
>
|
|
<button
|
|
v-for="emoji in quickReactions"
|
|
:key="emoji"
|
|
class="w-8 h-8 flex items-center justify-center text-lg hover:bg-[var(--wa-bg-light)] rounded-full transition-transform hover:scale-125"
|
|
@click="selectReaction(emoji)"
|
|
>
|
|
{{ emoji }}
|
|
</button>
|
|
<button
|
|
class="w-8 h-8 flex items-center justify-center text-lg hover:bg-[var(--wa-bg-light)] rounded-full"
|
|
@click="showFullPicker = true"
|
|
title="Más emojis"
|
|
>
|
|
<UIcon name="i-lucide-plus" class="w-4 h-4 text-[var(--wa-text-muted)]" />
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Full emoji picker modal -->
|
|
<UModal v-model:open="showFullPicker" title="Elegir reacción" :ui="{ footer: 'justify-end' }">
|
|
<template #body>
|
|
<div class="grid grid-cols-8 gap-2 max-h-64 overflow-y-auto">
|
|
<button
|
|
v-for="emoji in allEmojis"
|
|
:key="emoji"
|
|
class="w-10 h-10 flex items-center justify-center text-2xl hover:bg-[var(--wa-bg-light)] rounded transition-transform hover:scale-110"
|
|
@click="selectReaction(emoji); showFullPicker = false"
|
|
>
|
|
{{ emoji }}
|
|
</button>
|
|
</div>
|
|
</template>
|
|
<template #footer>
|
|
<UButton variant="ghost" color="neutral" @click="showFullPicker = false">
|
|
Cancelar
|
|
</UButton>
|
|
</template>
|
|
</UModal>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
interface Props {
|
|
visible: boolean
|
|
position?: 'top' | 'bottom'
|
|
align?: 'left' | 'right'
|
|
}
|
|
|
|
withDefaults(defineProps<Props>(), {
|
|
visible: false,
|
|
position: 'top',
|
|
align: 'right'
|
|
})
|
|
|
|
const emit = defineEmits<{
|
|
select: [emoji: string]
|
|
close: []
|
|
}>()
|
|
|
|
const showFullPicker = ref(false)
|
|
|
|
// Quick reactions (WhatsApp style)
|
|
const quickReactions = ['👍', '❤️', '😂', '😮', '😢', '🙏']
|
|
|
|
// Extended emoji list
|
|
const allEmojis = [
|
|
// Smileys
|
|
'😀', '😃', '😄', '😁', '😆', '😅', '🤣', '😂',
|
|
'🙂', '🙃', '😉', '😊', '😇', '🥰', '😍', '🤩',
|
|
'😘', '😗', '😚', '😙', '🥲', '😋', '😛', '😜',
|
|
'🤪', '😝', '🤑', '🤗', '🤭', '🤫', '🤔', '🤐',
|
|
'🤨', '😐', '😑', '😶', '😏', '😒', '🙄', '😬',
|
|
'😮💨', '🤥', '😌', '😔', '😪', '🤤', '😴', '😷',
|
|
// Gestures
|
|
'👍', '👎', '👌', '🤌', '🤏', '✌️', '🤞', '🤟',
|
|
'🤘', '🤙', '👈', '👉', '👆', '👇', '☝️', '👋',
|
|
'🤚', '🖐️', '✋', '🖖', '👏', '🙌', '👐', '🤲',
|
|
'🤝', '🙏', '✍️', '💪', '🦾', '🦿', '🦵', '🦶',
|
|
// Hearts
|
|
'❤️', '🧡', '💛', '💚', '💙', '💜', '🖤', '🤍',
|
|
'🤎', '💔', '❣️', '💕', '💞', '💓', '💗', '💖',
|
|
'💘', '💝', '💟', '♥️', '💌', '💋', '👄', '👅',
|
|
// Objects
|
|
'🎉', '🎊', '🎈', '🎁', '🏆', '🥇', '🥈', '🥉',
|
|
'⚽', '🏀', '🏈', '⚾', '🎾', '🏐', '🎱', '🎮',
|
|
'🎵', '🎶', '🎤', '🎧', '🎸', '🎹', '🎺', '🎻',
|
|
'🍕', '🍔', '🍟', '🌭', '🍿', '🧁', '🍰', '🎂',
|
|
'☕', '🍵', '🍺', '🍻', '🥂', '🍷', '🥃', '🍸',
|
|
// Nature
|
|
'🌸', '🌺', '🌹', '🌷', '🌻', '🌼', '💐', '🌿',
|
|
'☀️', '🌙', '⭐', '🌟', '✨', '💫', '🔥', '💧',
|
|
'🌈', '☁️', '⛈️', '❄️', '☃️', '⚡', '🌊', '🌍',
|
|
// Animals
|
|
'🐶', '🐱', '🐭', '🐹', '🐰', '🦊', '🐻', '🐼',
|
|
'🐨', '🐯', '🦁', '🐮', '🐷', '🐸', '🐵', '🐔',
|
|
'🦄', '🐝', '🦋', '🐌', '🐞', '🐜', '🦗', '🕷️'
|
|
]
|
|
|
|
const selectReaction = (emoji: string) => {
|
|
emit('select', emoji)
|
|
emit('close')
|
|
}
|
|
|
|
// Close on click outside
|
|
onMounted(() => {
|
|
const handleClickOutside = () => {
|
|
emit('close')
|
|
}
|
|
|
|
// Delay to avoid immediate close
|
|
setTimeout(() => {
|
|
document.addEventListener('click', handleClickOutside)
|
|
}, 100)
|
|
|
|
onUnmounted(() => {
|
|
document.removeEventListener('click', handleClickOutside)
|
|
})
|
|
})
|
|
</script>
|