diff --git a/app/components/malio/input/InputEmail.vue b/app/components/malio/input/InputEmail.vue index 9b940d2..95bb5a7 100644 --- a/app/components/malio/input/InputEmail.vue +++ b/app/components/malio/input/InputEmail.vue @@ -40,6 +40,23 @@ :class="[iconStateClass, iconPositionClass]" /> + +
(), @@ -110,6 +130,9 @@ const props = withDefaults( success: '', iconSize: 24, iconColor: 'text-m-muted', + addable: false, + addIconName: 'mdi:plus', + addButtonLabel: 'Ajouter une adresse email', lowercase: false, reserveMessageSpace: true, }, @@ -177,6 +200,14 @@ const mergedLabelClass = computed(() => ), ) +const mergedAddButtonClass = computed(() => + twMerge( + 'absolute right-[10px] top-1/2 -translate-y-1/2 cursor-pointer transition-opacity hover:opacity-70', + iconStateClass.value, + props.disabled ? 'cursor-not-allowed opacity-40 hover:opacity-40' : '', + ), +) + const describedBy = computed(() => { const ids: string[] = [] if (props.hint && !hasSuccess.value && !hasError.value) ids.push(`${inputId.value}-hint`) @@ -187,6 +218,7 @@ const describedBy = computed(() => { const emit = defineEmits<{ (event: 'update:modelValue', value: string): void + (event: 'add'): void }>() const sanitizeEmail = (v: string) => { @@ -222,25 +254,38 @@ const onInput = (event: Event) => { emit('update:modelValue', sanitized) } +const onAdd = () => { + if (props.disabled || props.readonly) return + emit('add') +} + +const effectiveIconPosition = computed(() => + props.addable && props.iconName ? 'left' : props.iconPosition, +) + const iconInputPaddingClass = computed(() => { - if (!props.iconName) return '' - return props.iconPosition === 'left' ? '!pl-11 !pr-3' : '!pl-3 !pr-10' + const leftIcon = props.iconName && effectiveIconPosition.value === 'left' + const rightIcon = props.iconName && effectiveIconPosition.value === 'right' + const parts: string[] = [] + if (leftIcon) parts.push('!pl-11') + if (rightIcon || props.addable) parts.push('!pr-10') + return parts.join(' ') }) const disabled = computed(() => props.disabled) const labelPositionClass = computed(() => { - if (props.iconName && props.iconPosition === 'left') return 'left-11' + if (props.iconName && effectiveIconPosition.value === 'left') return 'left-11' return 'left-3' }) const focusPaddingClass = computed(() => { - if (props.iconName && props.iconPosition === 'left') return 'focus:!pl-11' + if (props.iconName && effectiveIconPosition.value === 'left') return 'focus:!pl-11' return 'focus:pl-[11px]' }) const iconPositionClass = computed(() => { - const sideClass = props.iconPosition === 'left' ? 'left-[10px]' : 'right-[10px]' + const sideClass = effectiveIconPosition.value === 'left' ? 'left-[10px]' : 'right-[10px]' return `pointer-events-none absolute ${sideClass} top-1/2 -translate-y-1/2` })