feat(ui) : prop reserveMessageSpace (défaut true) sur Select/SelectCheckbox/Checkbox/date/time
Ajoute reserveMessageSpace (défaut true) pour permettre de ne pas réserver la ligne de message d'aide quand aucun message n'est présent. Comportement inchangé par défaut. La famille date hérite via $attrs → CalendarField. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,7 @@ type CheckboxProps = {
|
|||||||
hint?: string
|
hint?: string
|
||||||
error?: string
|
error?: string
|
||||||
success?: string
|
success?: string
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const CheckboxForTest = Checkbox as DefineComponent<CheckboxProps>
|
const CheckboxForTest = Checkbox as DefineComponent<CheckboxProps>
|
||||||
@@ -171,4 +172,23 @@ describe('MalioCheckbox', () => {
|
|||||||
const wrapper = mountCheckbox({label: 'Champ'})
|
const wrapper = mountCheckbox({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 = mountCheckbox({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 = mountCheckbox({label: 'Champ', reserveMessageSpace: false})
|
||||||
|
expect(wrapper.find('[id$="-describedby"]').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false avec message : ligne rendue sans min-h', () => {
|
||||||
|
const wrapper = mountCheckbox({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]')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
</label>
|
</label>
|
||||||
|
|
||||||
<p
|
<p
|
||||||
|
v-if="reserveMessageSpace || hint || error || success"
|
||||||
:id="`${inputId}-describedby`"
|
:id="`${inputId}-describedby`"
|
||||||
:class="mergedMessageClass"
|
:class="mergedMessageClass"
|
||||||
>
|
>
|
||||||
@@ -60,6 +61,7 @@ const props = withDefaults(
|
|||||||
hint?: string
|
hint?: string
|
||||||
error?: string
|
error?: string
|
||||||
success?: string
|
success?: string
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
@@ -75,6 +77,7 @@ const props = withDefaults(
|
|||||||
hint: '',
|
hint: '',
|
||||||
error: '',
|
error: '',
|
||||||
success: '',
|
success: '',
|
||||||
|
reserveMessageSpace: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -121,7 +124,8 @@ const mergedLabelClass = computed(() =>
|
|||||||
|
|
||||||
const mergedMessageClass = computed(() =>
|
const mergedMessageClass = computed(() =>
|
||||||
twMerge(
|
twMerge(
|
||||||
'text-xs min-h-[1rem]',
|
'text-xs',
|
||||||
|
props.reserveMessageSpace ? 'min-h-[1rem]' : '',
|
||||||
hasError.value
|
hasError.value
|
||||||
? 'text-m-danger'
|
? 'text-m-danger'
|
||||||
: hasSuccess.value
|
: hasSuccess.value
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ type DateProps = {
|
|||||||
inputClass?: string
|
inputClass?: string
|
||||||
labelClass?: string
|
labelClass?: string
|
||||||
groupClass?: string
|
groupClass?: string
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const DateForTest = Date_ as DefineComponent<DateProps>
|
const DateForTest = Date_ as DefineComponent<DateProps>
|
||||||
@@ -236,4 +237,25 @@ describe('MalioDate', () => {
|
|||||||
expect(input.value).toBe('25/12/2026')
|
expect(input.value).toBe('25/12/2026')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('reserveMessageSpace', () => {
|
||||||
|
it('réserve l’espace message par défaut même sans message', () => {
|
||||||
|
const wrapper = mountDate({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 = mountDate({label: 'Champ', reserveMessageSpace: false})
|
||||||
|
expect(wrapper.find('[id$="-describedby"]').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false avec message : ligne rendue sans min-h', () => {
|
||||||
|
const wrapper = mountDate({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]')
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -85,10 +85,12 @@
|
|||||||
</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]' : '',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
{{ error || success || hint }}
|
{{ error || success || hint }}
|
||||||
@@ -126,6 +128,7 @@ const props = withDefaults(
|
|||||||
inputClass?: string
|
inputClass?: string
|
||||||
labelClass?: string
|
labelClass?: string
|
||||||
groupClass?: string
|
groupClass?: string
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
@@ -142,6 +145,7 @@ const props = withDefaults(
|
|||||||
inputClass: '',
|
inputClass: '',
|
||||||
labelClass: '',
|
labelClass: '',
|
||||||
groupClass: '',
|
groupClass: '',
|
||||||
|
reserveMessageSpace: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ type SelectProps = {
|
|||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
required?: boolean
|
required?: boolean
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const SelectForTest = Select as DefineComponent<SelectProps>
|
const SelectForTest = Select as DefineComponent<SelectProps>
|
||||||
@@ -359,4 +360,23 @@ describe('MalioSelect', () => {
|
|||||||
expect(trigger.attributes('aria-readonly')).toBeUndefined()
|
expect(trigger.attributes('aria-readonly')).toBeUndefined()
|
||||||
expect(trigger.attributes('disabled')).toBeDefined()
|
expect(trigger.attributes('disabled')).toBeDefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('réserve l’espace message par défaut même sans message', () => {
|
||||||
|
const wrapper = mount(SelectForTest, {props: {modelValue: null, 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 = mount(SelectForTest, {props: {modelValue: null, 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 = mount(SelectForTest, {props: {modelValue: null, 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]')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -166,6 +166,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<p
|
<p
|
||||||
|
v-if="reserveMessageSpace || hint || error || success"
|
||||||
:id="`${buttonId}-describedby`"
|
:id="`${buttonId}-describedby`"
|
||||||
:class="[
|
:class="[
|
||||||
hasError
|
hasError
|
||||||
@@ -173,7 +174,8 @@
|
|||||||
: hasSuccess
|
: hasSuccess
|
||||||
? 'text-m-success'
|
? 'text-m-success'
|
||||||
: 'text-m-muted',
|
: 'text-m-muted',
|
||||||
'mt-1 ml-[2px] text-xs min-h-[1rem]',
|
'mt-1 ml-[2px] text-xs',
|
||||||
|
reserveMessageSpace ? 'min-h-[1rem]' : '',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
{{ error || success || hint }}
|
{{ error || success || hint }}
|
||||||
@@ -210,6 +212,7 @@ const props = withDefaults(defineProps<{
|
|||||||
groupClass?: string
|
groupClass?: string
|
||||||
noOptionsText?: string
|
noOptionsText?: string
|
||||||
required?: boolean
|
required?: boolean
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}>(), {
|
}>(), {
|
||||||
options: () => [],
|
options: () => [],
|
||||||
emptyOptionLabel: '',
|
emptyOptionLabel: '',
|
||||||
@@ -226,6 +229,7 @@ const props = withDefaults(defineProps<{
|
|||||||
groupClass: '',
|
groupClass: '',
|
||||||
noOptionsText: 'Aucune option disponible',
|
noOptionsText: 'Aucune option disponible',
|
||||||
required: false,
|
required: false,
|
||||||
|
reserveMessageSpace: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ type SelectCheckboxProps = {
|
|||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
groupClass?: string
|
groupClass?: string
|
||||||
required?: boolean
|
required?: boolean
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const SelectCheckboxForTest = SelectCheckbox as DefineComponent<SelectCheckboxProps>
|
const SelectCheckboxForTest = SelectCheckbox as DefineComponent<SelectCheckboxProps>
|
||||||
@@ -346,4 +347,23 @@ describe('MalioSelectCheckbox', () => {
|
|||||||
expect(trigger.attributes('aria-readonly')).toBeUndefined()
|
expect(trigger.attributes('aria-readonly')).toBeUndefined()
|
||||||
expect(trigger.attributes('disabled')).toBeDefined()
|
expect(trigger.attributes('disabled')).toBeDefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('réserve l’espace message par défaut même sans message', () => {
|
||||||
|
const wrapper = mount(SelectCheckboxForTest, {props: {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 = mount(SelectCheckboxForTest, {props: {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 = mount(SelectCheckboxForTest, {props: {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]')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -215,6 +215,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<p
|
<p
|
||||||
|
v-if="reserveMessageSpace || hint || error || success"
|
||||||
:id="`${buttonId}-describedby`"
|
:id="`${buttonId}-describedby`"
|
||||||
:class="[
|
:class="[
|
||||||
hasError
|
hasError
|
||||||
@@ -222,7 +223,8 @@
|
|||||||
: hasSuccess
|
: hasSuccess
|
||||||
? 'text-m-success'
|
? 'text-m-success'
|
||||||
: 'text-m-muted',
|
: 'text-m-muted',
|
||||||
'mt-1 ml-[2px] text-xs min-h-[1rem]',
|
'mt-1 ml-[2px] text-xs',
|
||||||
|
reserveMessageSpace ? 'min-h-[1rem]' : '',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
{{ error || success || hint }}
|
{{ error || success || hint }}
|
||||||
@@ -263,6 +265,7 @@ const props = withDefaults(defineProps<{
|
|||||||
groupClass?: string
|
groupClass?: string
|
||||||
noOptionsText?: string
|
noOptionsText?: string
|
||||||
required?: boolean
|
required?: boolean
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}>(), {
|
}>(), {
|
||||||
modelValue: () => [],
|
modelValue: () => [],
|
||||||
options: () => [],
|
options: () => [],
|
||||||
@@ -283,6 +286,7 @@ const props = withDefaults(defineProps<{
|
|||||||
groupClass: '',
|
groupClass: '',
|
||||||
noOptionsText: 'Aucune option disponible',
|
noOptionsText: 'Aucune option disponible',
|
||||||
required: false,
|
required: false,
|
||||||
|
reserveMessageSpace: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ type TimeProps = {
|
|||||||
hint?: string
|
hint?: string
|
||||||
error?: string
|
error?: string
|
||||||
success?: string
|
success?: string
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const TimeForTest = Time as DefineComponent<TimeProps>
|
const TimeForTest = Time as DefineComponent<TimeProps>
|
||||||
@@ -86,4 +87,23 @@ describe('MalioTime', () => {
|
|||||||
const wrapper = mountTime({label: 'Champ'})
|
const wrapper = mountTime({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 = mountTime({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 = mountTime({label: 'Champ', reserveMessageSpace: false})
|
||||||
|
expect(wrapper.find('[id$="-describedby"]').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false avec message : ligne rendue sans min-h', () => {
|
||||||
|
const wrapper = mountTime({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]')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -58,6 +58,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p
|
<p
|
||||||
|
v-if="reserveMessageSpace || hint || error || success"
|
||||||
:id="`${inputId}-describedby`"
|
:id="`${inputId}-describedby`"
|
||||||
:class="[
|
:class="[
|
||||||
hasError
|
hasError
|
||||||
@@ -65,7 +66,8 @@
|
|||||||
: hasSuccess
|
: hasSuccess
|
||||||
? 'text-m-success'
|
? 'text-m-success'
|
||||||
: 'text-m-muted',
|
: 'text-m-muted',
|
||||||
'mt-1 ml-[2px] text-xs min-h-[1rem]',
|
'mt-1 ml-[2px] text-xs',
|
||||||
|
reserveMessageSpace ? 'min-h-[1rem]' : '',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
{{ error || success || hint }}
|
{{ error || success || hint }}
|
||||||
@@ -95,6 +97,7 @@ const props = withDefaults(
|
|||||||
hint?: string
|
hint?: string
|
||||||
error?: string
|
error?: string
|
||||||
success?: string
|
success?: string
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
@@ -110,6 +113,7 @@ const props = withDefaults(
|
|||||||
hint: '',
|
hint: '',
|
||||||
error: '',
|
error: '',
|
||||||
success: '',
|
success: '',
|
||||||
|
reserveMessageSpace: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ type TimePickerProps = {
|
|||||||
inputClass?: string
|
inputClass?: string
|
||||||
labelClass?: string
|
labelClass?: string
|
||||||
groupClass?: string
|
groupClass?: string
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const TimePickerForTest = TimePicker as DefineComponent<TimePickerProps>
|
const TimePickerForTest = TimePicker as DefineComponent<TimePickerProps>
|
||||||
@@ -120,4 +121,23 @@ describe('MalioTimePicker', () => {
|
|||||||
expect(label.classes()).toContain('text-black')
|
expect(label.classes()).toContain('text-black')
|
||||||
expect(icon.classes()).toContain('text-black')
|
expect(icon.classes()).toContain('text-black')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('réserve l’espace message par défaut même sans message', () => {
|
||||||
|
const wrapper = mountPicker({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 = mountPicker({label: 'Champ', reserveMessageSpace: false})
|
||||||
|
expect(wrapper.find('[id$="-describedby"]').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reserveMessageSpace=false avec message : ligne rendue sans min-h', () => {
|
||||||
|
const wrapper = mountPicker({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]')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -78,10 +78,12 @@
|
|||||||
</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]' : '',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
{{ error || success || hint }}
|
{{ error || success || hint }}
|
||||||
@@ -116,6 +118,7 @@ const props = withDefaults(
|
|||||||
inputClass?: string
|
inputClass?: string
|
||||||
labelClass?: string
|
labelClass?: string
|
||||||
groupClass?: string
|
groupClass?: string
|
||||||
|
reserveMessageSpace?: boolean
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
@@ -134,6 +137,7 @@ const props = withDefaults(
|
|||||||
inputClass: '',
|
inputClass: '',
|
||||||
labelClass: '',
|
labelClass: '',
|
||||||
groupClass: '',
|
groupClass: '',
|
||||||
|
reserveMessageSpace: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user