Skip to content

Commit

Permalink
fix(kotti-fields): dont emit blur event when interacting with the con…
Browse files Browse the repository at this point in the history
…tent inside the field container
  • Loading branch information
santiagoballadares committed Feb 26, 2025
1 parent f0b7ea6 commit c50e5c7
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 109 deletions.
26 changes: 20 additions & 6 deletions packages/kotti-ui/source/kotti-field-currency/KtFieldCurrency.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<template>
<KtField :field="modifiedField" :helpTextSlot="$slots.helpText">
<input ref="inputRef" v-bind="inputProps" @blur="onBlur" @input="onInput" />
<KtField
ref="ktFieldRef"
:field="modifiedField"
:helpTextSlot="$slots.helpText"
>
<input ref="inputRef" v-bind="inputProps" @input="onInput" />
</KtField>
</template>

Expand All @@ -12,7 +16,12 @@ import type { InputHTMLAttributes } from 'vue/types/jsx'
import { Yoco } from '@3yourmind/yoco'
import { KtField } from '../kotti-field'
import { useField, useForceUpdate } from '../kotti-field/hooks'
import {
useEmitBlur,
useField,
useForceUpdate,
useKtFieldRef,
} from '../kotti-field/hooks'
import { useI18nContext } from '../kotti-i18n/hooks'
import type { KottiI18n } from '../kotti-i18n/types'
import { makeProps } from '../make-props'
Expand Down Expand Up @@ -57,6 +66,13 @@ export default defineComponent({
})
const i18nContext = useI18nContext()
const ktFieldRef = useKtFieldRef()
useEmitBlur({
emit,
field,
fieldTarget: computed(() => ktFieldRef.value?.inputContainerRef ?? null),
})
const currencyFormat = computed<KottiI18n.CurrencyMap[string]>(() => {
const result = i18nContext.currencyMap[props.currency]
Expand Down Expand Up @@ -176,13 +192,11 @@ export default defineComponent({
}),
),
inputRef,
ktFieldRef,
modifiedField: computed(() => ({
...field,
prefix: currencyFormat.value.symbol,
})),
onBlur: () => {
emit('blur', field.currentValue)
},
onInput: (event: Event) => {
const value = (event.target as HTMLInputElement).value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
</template>

<script lang="ts">
import type { Ref } from 'vue'
import {
computed,
defineComponent,
Expand All @@ -49,7 +48,7 @@ import type { InputHTMLAttributes, TextareaHTMLAttributes } from 'vue/types/jsx'
import { Yoco } from '@3yourmind/yoco'
import { useField, useForceUpdate } from '../kotti-field/hooks'
import { useField, useForceUpdate, useKtFieldRef } from '../kotti-field/hooks'
import type { KottiField } from '../kotti-field/types'
import { useTranslationNamespace } from '../kotti-i18n/hooks'
import { makeProps } from '../make-props'
Expand All @@ -75,9 +74,7 @@ export default defineComponent({
const { forceUpdate, forceUpdateKey } = useForceUpdate()
const translations = useTranslationNamespace('KtFieldInlineEdit')
const ktFieldRef = ref<{
inputContainerWrapperRef: Ref<HTMLDivElement>
} | null>(null)
const ktFieldRef = useKtFieldRef()
const inputContainerWrapperRef = ref<HTMLDivElement | null>(null)
const inputRef = ref<Nullable<FieldInlineEditElement>>(null)
Expand Down
49 changes: 17 additions & 32 deletions packages/kotti-ui/source/kotti-field-number/KtFieldNumber.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<KtField v-bind="{ field }" :helpTextSlot="$slots.helpText">
<KtField v-bind="{ field }" ref="ktFieldRef" :helpTextSlot="$slots.helpText">
<div
ref="wrapperRef"
class="kt-field-number"
Expand All @@ -11,7 +11,6 @@
>
<div
v-if="!hideChangeButtons"
ref="decrementButtonRef"
class="kt-field-number__button"
:class="decrementButtonClasses"
:data-test="`${inputProps['data-test']}-decrement`"
Expand All @@ -36,7 +35,6 @@
</div>
<div
v-if="!hideChangeButtons"
ref="incrementButtonRef"
class="kt-field-number__button"
:class="incrementButtonClasses"
:data-test="`${inputProps['data-test']}-increment`"
Expand Down Expand Up @@ -66,7 +64,13 @@ import type { InputHTMLAttributes } from 'vue/types/jsx'
import { Yoco } from '@3yourmind/yoco'
import { KtField } from '../kotti-field'
import { useField, useForceUpdate, useInput } from '../kotti-field/hooks'
import {
useEmitBlur,
useField,
useForceUpdate,
useInput,
useKtFieldRef,
} from '../kotti-field/hooks'
import type { KottiField } from '../kotti-field/types'
import { useI18nContext } from '../kotti-i18n/hooks'
import type { KottiI18n } from '../kotti-i18n/types'
Expand Down Expand Up @@ -102,8 +106,14 @@ export default defineComponent({
const { focusInput } = useInput(field.inputProps.id)
const { forceUpdate, forceUpdateKey } = useForceUpdate()
const i18nContext = useI18nContext()
const ktFieldRef = useKtFieldRef()
useEmitBlur({
emit,
field,
fieldTarget: computed(() => ktFieldRef.value?.inputContainerRef ?? null),
})
const isDecrementEnabled = computed(
() =>
Expand Down Expand Up @@ -250,29 +260,9 @@ export default defineComponent({
}
const wrapperRef = ref<HTMLDivElement | null>(null)
const incrementButtonRef = ref<HTMLDivElement | null>(null)
const decrementButtonRef = ref<HTMLDivElement | null>(null)
/**
* last element to capture the click or focus event
*/
const lastEventTarget = ref<EventTarget | null>(null)
const isFieldTargeted = (target: Event['target'] | null): boolean =>
isOrContainsEventTarget(inputRef.value, target) ||
isOrContainsEventTarget(decrementButtonRef.value, target) ||
isOrContainsEventTarget(incrementButtonRef.value, target)
const onClickOrFocusChange = (event: Event) => {
if (event.target === null || props.isDisabled) return
const wasFieldTargetedBefore = isFieldTargeted(lastEventTarget.value)
const isFieldTargetedNow = isFieldTargeted(event.target)
if (!isFieldTargetedNow && wasFieldTargetedBefore)
emit('blur', field.currentValue)
lastEventTarget.value = event.target
}
isOrContainsEventTarget(inputRef.value, target)
const onKeyup = (event: KeyboardEvent) => {
if (!isFieldTargeted(event.target)) return
Expand All @@ -282,28 +272,22 @@ export default defineComponent({
}
onBeforeMount(() => {
window.addEventListener('click', onClickOrFocusChange, true)
window.addEventListener('focus', onClickOrFocusChange, true)
window.addEventListener('keyup', onKeyup, true)
})
onUnmounted(() => {
window.removeEventListener('click', onClickOrFocusChange)
window.removeEventListener('focus', onClickOrFocusChange)
window.removeEventListener('keyup', onKeyup)
})
return {
decrementButtonClasses: computed(() => ({
'kt-field-number__button--is-disabled': !isDecrementEnabled.value,
})),
decrementButtonRef,
decrementValue,
field,
incrementButtonClasses: computed(() => ({
'kt-field-number__button--is-disabled': !isIncrementEnabled.value,
})),
incrementButtonRef,
incrementValue,
inputProps: computed(
(): InputHTMLAttributes &
Expand All @@ -326,6 +310,7 @@ export default defineComponent({
}),
),
inputRef,
ktFieldRef,
onBlur: () => {
forceUpdateDisplayedValue(field.currentValue)
},
Expand Down
25 changes: 18 additions & 7 deletions packages/kotti-ui/source/kotti-field-password/KtFieldPassword.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
<template>
<KtField
v-bind="{ field }"
ref="ktFieldRef"
:getEmptyValue="() => null"
:helpTextSlot="$slots.helpText"
@visibilityChange="handleVisibilityChange"
>
<input v-bind="inputProps" @blur="onBlur" @input="onInput" />
<input v-bind="inputProps" @input="onInput" />
</KtField>
</template>

Expand All @@ -14,14 +15,17 @@ import { computed, defineComponent, ref } from 'vue'
import type { InputHTMLAttributes } from 'vue/types/jsx'
import { KtField } from '../kotti-field'
import { useField, useForceUpdate } from '../kotti-field/hooks'
import {
useEmitBlur,
useField,
useForceUpdate,
useKtFieldRef,
} from '../kotti-field/hooks'
import { makeProps } from '../make-props'
import { KOTTI_FIELD_PASSWORD_SUPPORTS } from './constants'
import { KottiFieldPassword } from './types'
const VALUE_PLACEHOLDER = '•••'
export default defineComponent({
name: 'KtFieldPassword',
components: { KtField },
Expand All @@ -36,6 +40,15 @@ export default defineComponent({
})
const fieldType = ref('password')
const { forceUpdate, forceUpdateKey } = useForceUpdate()
const ktFieldRef = useKtFieldRef()
useEmitBlur({
emit,
field,
fieldTarget: computed(() => ktFieldRef.value?.inputContainerRef ?? null),
valueOverride: '•••',
})
return {
field,
handleVisibilityChange: () => {
Expand All @@ -57,9 +70,7 @@ export default defineComponent({
value: field.currentValue ?? '',
}),
),
onBlur: () => {
emit('blur', field.currentValue === null ? null : VALUE_PLACEHOLDER)
},
ktFieldRef,
onInput: (event: Event) => {
const newValue = (event.target as HTMLInputElement).value
field.setValue(newValue === '' ? null : newValue)
Expand Down
Loading

0 comments on commit c50e5c7

Please sign in to comment.