feat(ui) : prop reserveMessageSpace (défaut true) sur la famille input
Ajoute une prop booléenne reserveMessageSpace (défaut true) aux 10 composants de la famille input. Par défaut, comportement inchangé (ligne message toujours rendue avec min-h-[1rem]). À false, la ligne ne prend aucun espace en l'absence de message, et s'affiche sans min-h quand un message est présent. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,7 @@ type InputProps = {
|
|||||||
iconPosition?: 'left' | 'right'
|
iconPosition?: 'left' | 'right'
|
||||||
iconSize?: string | number
|
iconSize?: string | number
|
||||||
iconColor?: string
|
iconColor?: string
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputForTest = Input as DefineComponent<InputProps>
|
const InputForTest = Input as DefineComponent<InputProps>
|
||||||
@@ -279,6 +280,25 @@ describe('MalioInputText', () => {
|
|||||||
expect(p.classes()).toContain('min-h-[1rem]')
|
expect(p.classes()).toContain('min-h-[1rem]')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('réserve l’espace message par défaut même sans message', () => {
|
||||||
|
const wrapper = mountInput({label: 'Champ'})
|
||||||
|
const msg = wrapper.find('[id$="-describedby"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false sans message : pas de ligne réservée', () => {
|
||||||
|
const wrapper = mountInput({label: 'Champ', reserveMessageSpace: false})
|
||||||
|
expect(wrapper.find('[id$="-describedby"]').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false avec message : ligne rendue sans min-h', () => {
|
||||||
|
const wrapper = mountInput({label: 'Champ', reserveMessageSpace: false, error: 'Erreur'})
|
||||||
|
const msg = wrapper.find('[id$="-describedby"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).not.toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
|
|
||||||
it('does not render label when label prop is missing', () => {
|
it('does not render label when label prop is missing', () => {
|
||||||
const wrapper = mountInput({labelClass: 'text-red-500'})
|
const wrapper = mountInput({labelClass: 'text-red-500'})
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ type InputAmountProps = {
|
|||||||
iconPosition?: 'left' | 'right'
|
iconPosition?: 'left' | 'right'
|
||||||
iconSize?: string | number
|
iconSize?: string | number
|
||||||
iconColor?: string
|
iconColor?: string
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputAmountForTest = InputAmount as DefineComponent<InputAmountProps>
|
const InputAmountForTest = InputAmount as DefineComponent<InputAmountProps>
|
||||||
@@ -210,4 +211,23 @@ describe('MalioInputAmount', () => {
|
|||||||
expect(wrapper.get('label').classes()).toContain('text-black')
|
expect(wrapper.get('label').classes()).toContain('text-black')
|
||||||
expect(wrapper.get('[data-test="icon"]').classes()).toContain('text-black')
|
expect(wrapper.get('[data-test="icon"]').classes()).toContain('text-black')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('réserve l’espace message par défaut même sans message', () => {
|
||||||
|
const wrapper = mountInputAmount({label: 'Champ'})
|
||||||
|
const msg = wrapper.find('[id$="-describedby"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false sans message : pas de ligne réservée', () => {
|
||||||
|
const wrapper = mountInputAmount({label: 'Champ', reserveMessageSpace: false})
|
||||||
|
expect(wrapper.find('[id$="-describedby"]').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false avec message : ligne rendue sans min-h', () => {
|
||||||
|
const wrapper = mountInputAmount({label: 'Champ', reserveMessageSpace: false, error: 'Erreur'})
|
||||||
|
const msg = wrapper.find('[id$="-describedby"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).not.toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<p
|
<p
|
||||||
|
v-if="reserveMessageSpace || hint || error || success"
|
||||||
:id="`${inputId}-describedby`"
|
:id="`${inputId}-describedby`"
|
||||||
:class="[
|
:class="[
|
||||||
hasError
|
hasError
|
||||||
@@ -51,7 +52,8 @@
|
|||||||
: hasSuccess
|
: hasSuccess
|
||||||
? 'text-m-success'
|
? 'text-m-success'
|
||||||
: 'text-m-muted',
|
: 'text-m-muted',
|
||||||
'mt-1 text-xs ml-[2px] min-h-[1rem]',
|
'mt-1 text-xs ml-[2px]',
|
||||||
|
reserveMessageSpace ? 'min-h-[1rem]' : '',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
{{ hint || error || success }}
|
{{ hint || error || success }}
|
||||||
@@ -89,6 +91,7 @@ const props = withDefaults(
|
|||||||
iconPosition?: 'left' | 'right'
|
iconPosition?: 'left' | 'right'
|
||||||
iconSize?: string | number
|
iconSize?: string | number
|
||||||
iconColor?: string
|
iconColor?: string
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
@@ -111,6 +114,7 @@ const props = withDefaults(
|
|||||||
success: '',
|
success: '',
|
||||||
iconSize: 20,
|
iconSize: 20,
|
||||||
iconColor: 'text-m-muted',
|
iconColor: 'text-m-muted',
|
||||||
|
reserveMessageSpace: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ type InputAutocompleteProps = {
|
|||||||
noResultsText?: string
|
noResultsText?: string
|
||||||
loadingText?: string
|
loadingText?: string
|
||||||
minSearchText?: string
|
minSearchText?: string
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputAutocompleteForTest = InputAutocomplete as DefineComponent<InputAutocompleteProps>
|
const InputAutocompleteForTest = InputAutocomplete as DefineComponent<InputAutocompleteProps>
|
||||||
@@ -543,4 +544,23 @@ describe('MalioInputAutocomplete', () => {
|
|||||||
expect(wrapper.get('[data-test="icon-left"]').classes()).toContain('text-black')
|
expect(wrapper.get('[data-test="icon-left"]').classes()).toContain('text-black')
|
||||||
expect(wrapper.get('[data-test="chevron"]').classes()).toContain('text-black')
|
expect(wrapper.get('[data-test="chevron"]').classes()).toContain('text-black')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('réserve l’espace message par défaut même sans message', () => {
|
||||||
|
const wrapper = mountComponent({label: 'Champ', options})
|
||||||
|
const msg = wrapper.find('[id$="-describedby"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false sans message : pas de ligne réservée', () => {
|
||||||
|
const wrapper = mountComponent({label: 'Champ', options, reserveMessageSpace: false})
|
||||||
|
expect(wrapper.find('[id$="-describedby"]').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false avec message : ligne rendue sans min-h', () => {
|
||||||
|
const wrapper = mountComponent({label: 'Champ', options, reserveMessageSpace: false, error: 'Erreur'})
|
||||||
|
const msg = wrapper.find('[id$="-describedby"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).not.toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -136,10 +136,12 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<p
|
<p
|
||||||
|
v-if="reserveMessageSpace || hint || error || success"
|
||||||
:id="`${inputId}-describedby`"
|
:id="`${inputId}-describedby`"
|
||||||
:class="[
|
:class="[
|
||||||
hasError ? 'text-m-danger' : hasSuccess ? 'text-m-success' : 'text-m-muted',
|
hasError ? 'text-m-danger' : hasSuccess ? 'text-m-success' : 'text-m-muted',
|
||||||
'mt-1 ml-[2px] text-xs min-h-[1rem]',
|
'mt-1 ml-[2px] text-xs',
|
||||||
|
reserveMessageSpace ? 'min-h-[1rem]' : '',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
{{ hint || error || success }}
|
{{ hint || error || success }}
|
||||||
@@ -188,6 +190,7 @@ const props = withDefaults(
|
|||||||
noResultsText?: string
|
noResultsText?: string
|
||||||
loadingText?: string
|
loadingText?: string
|
||||||
minSearchText?: string
|
minSearchText?: string
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
@@ -216,6 +219,7 @@ const props = withDefaults(
|
|||||||
noResultsText: 'Aucun résultat',
|
noResultsText: 'Aucun résultat',
|
||||||
loadingText: 'Chargement…',
|
loadingText: 'Chargement…',
|
||||||
minSearchText: 'Tapez pour rechercher',
|
minSearchText: 'Tapez pour rechercher',
|
||||||
|
reserveMessageSpace: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ type InputEmailProps = {
|
|||||||
iconSize?: string | number
|
iconSize?: string | number
|
||||||
iconColor?: string
|
iconColor?: string
|
||||||
lowercase?: boolean
|
lowercase?: boolean
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputEmailForTest = InputEmail as DefineComponent<InputEmailProps>
|
const InputEmailForTest = InputEmail as DefineComponent<InputEmailProps>
|
||||||
@@ -295,4 +296,23 @@ describe('MalioInputEmail', () => {
|
|||||||
expect(wrapper.get('label').classes()).toContain('text-black')
|
expect(wrapper.get('label').classes()).toContain('text-black')
|
||||||
expect(wrapper.get('[data-test="icon"]').classes()).toContain('text-black')
|
expect(wrapper.get('[data-test="icon"]').classes()).toContain('text-black')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('réserve l’espace message par défaut même sans message', () => {
|
||||||
|
const wrapper = mountComponent({label: 'Champ'})
|
||||||
|
const msg = wrapper.find('[id$="-describedby"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false sans message : pas de ligne réservée', () => {
|
||||||
|
const wrapper = mountComponent({label: 'Champ', reserveMessageSpace: false})
|
||||||
|
expect(wrapper.find('[id$="-describedby"]').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false avec message : ligne rendue sans min-h', () => {
|
||||||
|
const wrapper = mountComponent({label: 'Champ', reserveMessageSpace: false, error: 'Erreur'})
|
||||||
|
const msg = wrapper.find('[id$="-describedby"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).not.toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<p
|
<p
|
||||||
|
v-if="reserveMessageSpace || hint || error || success"
|
||||||
:id="`${inputId}-describedby`"
|
:id="`${inputId}-describedby`"
|
||||||
:class="[
|
:class="[
|
||||||
hasError
|
hasError
|
||||||
@@ -49,7 +50,8 @@
|
|||||||
: hasSuccess
|
: hasSuccess
|
||||||
? 'text-m-success'
|
? 'text-m-success'
|
||||||
: 'text-m-muted',
|
: 'text-m-muted',
|
||||||
'mt-1 text-xs ml-[2px] min-h-[1rem]',
|
'mt-1 text-xs ml-[2px]',
|
||||||
|
reserveMessageSpace ? 'min-h-[1rem]' : '',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
{{ hint || error || success }}
|
{{ hint || error || success }}
|
||||||
@@ -87,6 +89,7 @@ const props = withDefaults(
|
|||||||
iconSize?: string | number
|
iconSize?: string | number
|
||||||
iconColor?: string
|
iconColor?: string
|
||||||
lowercase?: boolean
|
lowercase?: boolean
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
@@ -108,6 +111,7 @@ const props = withDefaults(
|
|||||||
iconSize: 24,
|
iconSize: 24,
|
||||||
iconColor: 'text-m-muted',
|
iconColor: 'text-m-muted',
|
||||||
lowercase: false,
|
lowercase: false,
|
||||||
|
reserveMessageSpace: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ type InputNumberProps = {
|
|||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
min?: number | string
|
min?: number | string
|
||||||
max?: number | string
|
max?: number | string
|
||||||
|
error?: string
|
||||||
|
hint?: string
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputNumberForTest = InputNumber as DefineComponent<InputNumberProps>
|
const InputNumberForTest = InputNumber as DefineComponent<InputNumberProps>
|
||||||
@@ -173,4 +176,23 @@ describe('MalioInputNumber', () => {
|
|||||||
const wrapper = mountInputNumber({label: 'Champ'})
|
const wrapper = mountInputNumber({label: 'Champ'})
|
||||||
expect(wrapper.find('[data-test="required-mark"]').exists()).toBe(false)
|
expect(wrapper.find('[data-test="required-mark"]').exists()).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('réserve l’espace message par défaut même sans message', () => {
|
||||||
|
const wrapper = mountInputNumber({label: 'Champ'})
|
||||||
|
const msg = wrapper.find('[id$="-describedby"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false sans message : pas de ligne réservée', () => {
|
||||||
|
const wrapper = mountInputNumber({label: 'Champ', reserveMessageSpace: false})
|
||||||
|
expect(wrapper.find('[id$="-describedby"]').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false avec message : ligne rendue sans min-h', () => {
|
||||||
|
const wrapper = mountInputNumber({label: 'Champ', reserveMessageSpace: false, error: 'Erreur'})
|
||||||
|
const msg = wrapper.find('[id$="-describedby"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).not.toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -51,6 +51,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<p
|
<p
|
||||||
|
v-if="reserveMessageSpace || hint || error || success"
|
||||||
:id="`${inputId}-describedby`"
|
:id="`${inputId}-describedby`"
|
||||||
:class="[
|
:class="[
|
||||||
hasError
|
hasError
|
||||||
@@ -58,7 +59,8 @@
|
|||||||
: hasSuccess
|
: hasSuccess
|
||||||
? 'text-m-success'
|
? 'text-m-success'
|
||||||
: 'text-m-muted',
|
: 'text-m-muted',
|
||||||
'text-xs ml-[2px] min-h-[1rem]',
|
'text-xs ml-[2px]',
|
||||||
|
reserveMessageSpace ? 'min-h-[1rem]' : '',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
{{ hint || error || success }}
|
{{ hint || error || success }}
|
||||||
@@ -91,6 +93,7 @@ const props = withDefaults(
|
|||||||
hint?: string
|
hint?: string
|
||||||
error?: string
|
error?: string
|
||||||
success?: string
|
success?: string
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
@@ -108,6 +111,7 @@ const props = withDefaults(
|
|||||||
hint: '',
|
hint: '',
|
||||||
error: '',
|
error: '',
|
||||||
success: '',
|
success: '',
|
||||||
|
reserveMessageSpace: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ type InputPasswordProps = {
|
|||||||
error?: string
|
error?: string
|
||||||
success?: string
|
success?: string
|
||||||
displayIcon?: boolean
|
displayIcon?: boolean
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputPasswordForTest = InputPassword as DefineComponent<InputPasswordProps>
|
const InputPasswordForTest = InputPassword as DefineComponent<InputPasswordProps>
|
||||||
@@ -227,4 +228,23 @@ describe('MalioInputPassword', () => {
|
|||||||
await wrapper.get('[data-test="icon"]').trigger('click')
|
await wrapper.get('[data-test="icon"]').trigger('click')
|
||||||
expect(wrapper.get('input').attributes('type')).toBe('text')
|
expect(wrapper.get('input').attributes('type')).toBe('text')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('réserve l’espace message par défaut même sans message', () => {
|
||||||
|
const wrapper = mountComponent({label: 'Champ'})
|
||||||
|
const msg = wrapper.find('[id$="-describedby"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false sans message : pas de ligne réservée', () => {
|
||||||
|
const wrapper = mountComponent({label: 'Champ', reserveMessageSpace: false})
|
||||||
|
expect(wrapper.find('[id$="-describedby"]').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false avec message : ligne rendue sans min-h', () => {
|
||||||
|
const wrapper = mountComponent({label: 'Champ', reserveMessageSpace: false, error: 'Erreur'})
|
||||||
|
const msg = wrapper.find('[id$="-describedby"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).not.toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<p
|
<p
|
||||||
|
v-if="reserveMessageSpace || hint || error || success"
|
||||||
:id="`${inputId}-describedby`"
|
:id="`${inputId}-describedby`"
|
||||||
:class="[
|
:class="[
|
||||||
hasError
|
hasError
|
||||||
@@ -54,7 +55,8 @@
|
|||||||
: hasSuccess
|
: hasSuccess
|
||||||
? 'text-m-success'
|
? 'text-m-success'
|
||||||
: 'text-m-muted',
|
: 'text-m-muted',
|
||||||
'mt-1 text-xs ml-[2px] min-h-[1rem]',
|
'mt-1 text-xs ml-[2px]',
|
||||||
|
reserveMessageSpace ? 'min-h-[1rem]' : '',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
{{ hint || error || success }}
|
{{ hint || error || success }}
|
||||||
@@ -90,6 +92,7 @@ const props = withDefaults(
|
|||||||
error?: string
|
error?: string
|
||||||
success?: string
|
success?: string
|
||||||
displayIcon?: boolean
|
displayIcon?: boolean
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
@@ -109,6 +112,7 @@ const props = withDefaults(
|
|||||||
error: '',
|
error: '',
|
||||||
success: '',
|
success: '',
|
||||||
displayIcon: true,
|
displayIcon: true,
|
||||||
|
reserveMessageSpace: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ type InputPhoneProps = {
|
|||||||
addable?: boolean
|
addable?: boolean
|
||||||
addIconName?: string
|
addIconName?: string
|
||||||
addButtonLabel?: string
|
addButtonLabel?: string
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputPhoneForTest = InputPhone as DefineComponent<InputPhoneProps>
|
const InputPhoneForTest = InputPhone as DefineComponent<InputPhoneProps>
|
||||||
@@ -383,4 +384,23 @@ describe('MalioInputPhone', () => {
|
|||||||
|
|
||||||
expect(wrapper.emitted('update:modelValue')).toBeDefined()
|
expect(wrapper.emitted('update:modelValue')).toBeDefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('réserve l’espace message par défaut même sans message', () => {
|
||||||
|
const wrapper = mountComponent({label: 'Champ'})
|
||||||
|
const msg = wrapper.find('[id$="-describedby"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false sans message : pas de ligne réservée', () => {
|
||||||
|
const wrapper = mountComponent({label: 'Champ', reserveMessageSpace: false})
|
||||||
|
expect(wrapper.find('[id$="-describedby"]').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false avec message : ligne rendue sans min-h', () => {
|
||||||
|
const wrapper = mountComponent({label: 'Champ', reserveMessageSpace: false, error: 'Erreur'})
|
||||||
|
const msg = wrapper.find('[id$="-describedby"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).not.toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -60,6 +60,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<p
|
<p
|
||||||
|
v-if="reserveMessageSpace || hint || error || success"
|
||||||
:id="`${inputId}-describedby`"
|
:id="`${inputId}-describedby`"
|
||||||
:class="[
|
:class="[
|
||||||
hasError
|
hasError
|
||||||
@@ -67,7 +68,8 @@
|
|||||||
: hasSuccess
|
: hasSuccess
|
||||||
? 'text-m-success'
|
? 'text-m-success'
|
||||||
: 'text-m-muted',
|
: 'text-m-muted',
|
||||||
'mt-1 text-xs ml-[2px] min-h-[1rem]',
|
'mt-1 text-xs ml-[2px]',
|
||||||
|
reserveMessageSpace ? 'min-h-[1rem]' : '',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
{{ hint || error || success }}
|
{{ hint || error || success }}
|
||||||
@@ -110,6 +112,7 @@ const props = withDefaults(
|
|||||||
addable?: boolean
|
addable?: boolean
|
||||||
addIconName?: string
|
addIconName?: string
|
||||||
addButtonLabel?: string
|
addButtonLabel?: string
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
@@ -134,6 +137,7 @@ const props = withDefaults(
|
|||||||
addable: false,
|
addable: false,
|
||||||
addIconName: 'mdi:plus',
|
addIconName: 'mdi:plus',
|
||||||
addButtonLabel: 'Ajouter un numéro',
|
addButtonLabel: 'Ajouter un numéro',
|
||||||
|
reserveMessageSpace: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ type InputRichTextProps = {
|
|||||||
labelClass?: string
|
labelClass?: string
|
||||||
editorClass?: string
|
editorClass?: string
|
||||||
required?: boolean
|
required?: boolean
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputRichTextForTest = InputRichText as DefineComponent<InputRichTextProps>
|
const InputRichTextForTest = InputRichText as DefineComponent<InputRichTextProps>
|
||||||
@@ -187,4 +188,23 @@ describe('MalioInputRichText', () => {
|
|||||||
|
|
||||||
expect(wrapper.find('[data-test="required-mark"]').exists()).toBe(false)
|
expect(wrapper.find('[data-test="required-mark"]').exists()).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('réserve l’espace message par défaut même sans message', async () => {
|
||||||
|
const wrapper = await mountComponent({label: 'Champ'})
|
||||||
|
const msg = wrapper.find('[id$="-describedby"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false sans message : pas de ligne réservée', async () => {
|
||||||
|
const wrapper = await mountComponent({label: 'Champ', reserveMessageSpace: false})
|
||||||
|
expect(wrapper.find('[id$="-describedby"]').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false avec message : ligne rendue sans min-h', async () => {
|
||||||
|
const wrapper = await mountComponent({label: 'Champ', reserveMessageSpace: false, error: 'Erreur'})
|
||||||
|
const msg = wrapper.find('[id$="-describedby"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).not.toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -185,6 +185,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p
|
<p
|
||||||
|
v-if="reserveMessageSpace || hint || error || success"
|
||||||
:id="`${editorId}-describedby`"
|
:id="`${editorId}-describedby`"
|
||||||
:class="[
|
:class="[
|
||||||
hasError
|
hasError
|
||||||
@@ -192,7 +193,8 @@
|
|||||||
: hasSuccess
|
: hasSuccess
|
||||||
? 'text-m-success'
|
? 'text-m-success'
|
||||||
: 'text-m-muted',
|
: 'text-m-muted',
|
||||||
'mt-1 text-xs ml-[2px] min-h-[1rem]',
|
'mt-1 text-xs ml-[2px]',
|
||||||
|
reserveMessageSpace ? 'min-h-[1rem]' : '',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
{{ error || success || hint }}
|
{{ error || success || hint }}
|
||||||
@@ -235,6 +237,7 @@ const props = withDefaults(
|
|||||||
labelClass?: string
|
labelClass?: string
|
||||||
editorClass?: string
|
editorClass?: string
|
||||||
required?: boolean
|
required?: boolean
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
@@ -253,6 +256,7 @@ const props = withDefaults(
|
|||||||
labelClass: '',
|
labelClass: '',
|
||||||
editorClass: '',
|
editorClass: '',
|
||||||
required: false,
|
required: false,
|
||||||
|
reserveMessageSpace: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<p
|
<p
|
||||||
|
v-if="reserveMessageSpace || hint || error || success"
|
||||||
:id="`${inputId}-describedby`"
|
:id="`${inputId}-describedby`"
|
||||||
:class="[
|
:class="[
|
||||||
hasError
|
hasError
|
||||||
@@ -51,7 +52,8 @@
|
|||||||
: hasSuccess
|
: hasSuccess
|
||||||
? 'text-m-success'
|
? 'text-m-success'
|
||||||
: 'text-m-muted',
|
: 'text-m-muted',
|
||||||
'mt-1 text-xs ml-[2px] min-h-[1rem]',
|
'mt-1 text-xs ml-[2px]',
|
||||||
|
reserveMessageSpace ? 'min-h-[1rem]' : '',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
{{ hint || error || success }}
|
{{ hint || error || success }}
|
||||||
@@ -94,6 +96,7 @@ const props = withDefaults(
|
|||||||
iconSize?: string | number
|
iconSize?: string | number
|
||||||
iconColor?: string
|
iconColor?: string
|
||||||
mask?: string | MaskInputOptions
|
mask?: string | MaskInputOptions
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
@@ -117,6 +120,7 @@ const props = withDefaults(
|
|||||||
iconSize: 24,
|
iconSize: 24,
|
||||||
iconColor: 'text-m-muted',
|
iconColor: 'text-m-muted',
|
||||||
mask: undefined,
|
mask: undefined,
|
||||||
|
reserveMessageSpace: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ type InputTextAreaProps = {
|
|||||||
error?: string
|
error?: string
|
||||||
success?: string
|
success?: string
|
||||||
rounded?: string
|
rounded?: string
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputTextAreaForTest = InputTextArea as DefineComponent<InputTextAreaProps>
|
const InputTextAreaForTest = InputTextArea as DefineComponent<InputTextAreaProps>
|
||||||
@@ -213,4 +214,23 @@ describe('MalioInputTextArea', () => {
|
|||||||
const wrapper = mount(InputTextAreaForTest, {props: {label: 'Champ', readonly: true, modelValue: 'du texte'}})
|
const wrapper = mount(InputTextAreaForTest, {props: {label: 'Champ', readonly: true, modelValue: 'du texte'}})
|
||||||
expect(wrapper.get('label').classes()).toContain('text-black')
|
expect(wrapper.get('label').classes()).toContain('text-black')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('réserve l’espace message par défaut même sans message', () => {
|
||||||
|
const wrapper = mount(InputTextAreaForTest, {props: {label: 'Champ'}})
|
||||||
|
const msg = wrapper.find('[data-test="message-line"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false sans message : pas de ligne réservée', () => {
|
||||||
|
const wrapper = mount(InputTextAreaForTest, {props: {label: 'Champ', reserveMessageSpace: false}})
|
||||||
|
expect(wrapper.find('[data-test="message-line"]').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false avec message : ligne rendue sans min-h', () => {
|
||||||
|
const wrapper = mount(InputTextAreaForTest, {props: {label: 'Champ', reserveMessageSpace: false, error: 'Erreur'}})
|
||||||
|
const msg = wrapper.find('[data-test="message-line"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).not.toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -63,7 +63,10 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="mt-1 flex items-center justify-between gap-2 text-xs min-h-[1rem]"
|
v-if="reserveMessageSpace || hint || error || success"
|
||||||
|
data-test="message-line"
|
||||||
|
class="mt-1 flex items-center justify-between gap-2 text-xs"
|
||||||
|
:class="reserveMessageSpace ? 'min-h-[1rem]' : ''"
|
||||||
>
|
>
|
||||||
<p
|
<p
|
||||||
:id="`${inputId}-describedby`"
|
:id="`${inputId}-describedby`"
|
||||||
@@ -114,6 +117,7 @@ const props = withDefaults(
|
|||||||
success?: string
|
success?: string
|
||||||
rounded?: string
|
rounded?: string
|
||||||
groupClass?: string
|
groupClass?: string
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
|
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
@@ -140,6 +144,7 @@ const props = withDefaults(
|
|||||||
minResizeHeight: 40,
|
minResizeHeight: 40,
|
||||||
maxResizeHeight: 320,
|
maxResizeHeight: 320,
|
||||||
groupClass: '',
|
groupClass: '',
|
||||||
|
reserveMessageSpace: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ type InputUploadProps = {
|
|||||||
displayIcon?: boolean
|
displayIcon?: boolean
|
||||||
accept?: string
|
accept?: string
|
||||||
required?: boolean
|
required?: boolean
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputUploadForTest = InputUpload as DefineComponent<InputUploadProps>
|
const InputUploadForTest = InputUpload as DefineComponent<InputUploadProps>
|
||||||
@@ -240,4 +241,23 @@ describe('MalioInputUpload', () => {
|
|||||||
await wrapper.get('input[type="text"]').trigger('click')
|
await wrapper.get('input[type="text"]').trigger('click')
|
||||||
expect(clickSpy).not.toHaveBeenCalled()
|
expect(clickSpy).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('réserve l’espace message par défaut même sans message', () => {
|
||||||
|
const wrapper = mountComponent({label: 'Champ'})
|
||||||
|
const msg = wrapper.find('[id$="-describedby"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false sans message : pas de ligne réservée', () => {
|
||||||
|
const wrapper = mountComponent({label: 'Champ', reserveMessageSpace: false})
|
||||||
|
expect(wrapper.find('[id$="-describedby"]').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false avec message : ligne rendue sans min-h', () => {
|
||||||
|
const wrapper = mountComponent({label: 'Champ', reserveMessageSpace: false, error: 'Erreur'})
|
||||||
|
const msg = wrapper.find('[id$="-describedby"]')
|
||||||
|
expect(msg.exists()).toBe(true)
|
||||||
|
expect(msg.classes()).not.toContain('min-h-[1rem]')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -52,6 +52,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<p
|
<p
|
||||||
|
v-if="reserveMessageSpace || hint || error || success"
|
||||||
:id="`${inputId}-describedby`"
|
:id="`${inputId}-describedby`"
|
||||||
:class="[
|
:class="[
|
||||||
hasError
|
hasError
|
||||||
@@ -59,7 +60,8 @@
|
|||||||
: hasSuccess
|
: hasSuccess
|
||||||
? 'text-m-success'
|
? 'text-m-success'
|
||||||
: 'text-m-muted',
|
: 'text-m-muted',
|
||||||
'mt-1 text-xs ml-[2px] min-h-[1rem]',
|
'mt-1 text-xs ml-[2px]',
|
||||||
|
reserveMessageSpace ? 'min-h-[1rem]' : '',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
{{ hint || error || success }}
|
{{ hint || error || success }}
|
||||||
@@ -92,6 +94,7 @@ const props = withDefaults(
|
|||||||
displayIcon?: boolean
|
displayIcon?: boolean
|
||||||
accept?: string
|
accept?: string
|
||||||
required?: boolean
|
required?: boolean
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
@@ -108,6 +111,7 @@ const props = withDefaults(
|
|||||||
displayIcon: true,
|
displayIcon: true,
|
||||||
accept: '',
|
accept: '',
|
||||||
required: false,
|
required: false,
|
||||||
|
reserveMessageSpace: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user