AutoComplete option list scroll behavior fixes
parent
0125015937
commit
dc34e05a1b
|
@ -190,6 +190,10 @@ export interface AutoCompletePassThroughOptions {
|
||||||
* @see {@link VirtualScrollerPassThroughOptionType}
|
* @see {@link VirtualScrollerPassThroughOptionType}
|
||||||
*/
|
*/
|
||||||
virtualScroller?: VirtualScrollerPassThroughOptionType;
|
virtualScroller?: VirtualScrollerPassThroughOptionType;
|
||||||
|
/**
|
||||||
|
* Used to pass attributes to the list container's DOM element.
|
||||||
|
*/
|
||||||
|
listContainer?: AutoCompletePassThroughOptionType;
|
||||||
/**
|
/**
|
||||||
* Used to pass attributes to the list's DOM element.
|
* Used to pass attributes to the list's DOM element.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -121,55 +121,55 @@
|
||||||
</span>
|
</span>
|
||||||
<Portal :appendTo="appendTo">
|
<Portal :appendTo="appendTo">
|
||||||
<transition name="p-connected-overlay" @enter="onOverlayEnter" @after-enter="onOverlayAfterEnter" @leave="onOverlayLeave" @after-leave="onOverlayAfterLeave" v-bind="ptm('transition')">
|
<transition name="p-connected-overlay" @enter="onOverlayEnter" @after-enter="onOverlayAfterEnter" @leave="onOverlayLeave" @after-leave="onOverlayAfterLeave" v-bind="ptm('transition')">
|
||||||
<div
|
<div v-if="overlayVisible" :ref="overlayRef" :id="panelId" :class="[cx('overlay'), panelClass, overlayClass]" :style="{ ...panelStyle, ...overlayStyle }" @click="onOverlayClick" @keydown="onOverlayKeyDown" v-bind="ptm('overlay')">
|
||||||
v-if="overlayVisible"
|
|
||||||
:ref="overlayRef"
|
|
||||||
:id="panelId"
|
|
||||||
:class="[cx('overlay'), panelClass, overlayClass]"
|
|
||||||
:style="{ ...panelStyle, ...overlayStyle, 'max-height': virtualScrollerDisabled ? scrollHeight : '' }"
|
|
||||||
@click="onOverlayClick"
|
|
||||||
@keydown="onOverlayKeyDown"
|
|
||||||
v-bind="ptm('overlay')"
|
|
||||||
>
|
|
||||||
<slot name="header" :value="modelValue" :suggestions="visibleOptions"></slot>
|
<slot name="header" :value="modelValue" :suggestions="visibleOptions"></slot>
|
||||||
<VirtualScroller :ref="virtualScrollerRef" v-bind="virtualScrollerOptions" :style="{ height: scrollHeight }" :items="visibleOptions" :tabindex="-1" :disabled="virtualScrollerDisabled" :pt="ptm('virtualScroller')">
|
<div :class="cx('listContainer')" :style="{ 'max-height': virtualScrollerDisabled ? scrollHeight : '' }" v-bind="ptm('listContainer')">
|
||||||
<template v-slot:content="{ styleClass, contentRef, items, getItemOptions, contentStyle, itemSize }">
|
<VirtualScroller :ref="virtualScrollerRef" v-bind="virtualScrollerOptions" :style="{ height: scrollHeight }" :items="visibleOptions" :tabindex="-1" :disabled="virtualScrollerDisabled" :pt="ptm('virtualScroller')">
|
||||||
<ul :ref="(el) => listRef(el, contentRef)" :id="id + '_list'" :class="[cx('list'), styleClass]" :style="contentStyle" role="listbox" :aria-label="listAriaLabel" v-bind="ptm('list')">
|
<template v-slot:content="{ styleClass, contentRef, items, getItemOptions, contentStyle, itemSize }">
|
||||||
<template v-for="(option, i) of items" :key="getOptionRenderKey(option, getOptionIndex(i, getItemOptions))">
|
<ul :ref="(el) => listRef(el, contentRef)" :id="id + '_list'" :class="[cx('list'), styleClass]" :style="contentStyle" role="listbox" :aria-label="listAriaLabel" v-bind="ptm('list')">
|
||||||
<li v-if="isOptionGroup(option)" :id="id + '_' + getOptionIndex(i, getItemOptions)" :style="{ height: itemSize ? itemSize + 'px' : undefined }" :class="cx('optionGroup')" role="option" v-bind="ptm('optionGroup')">
|
<template v-for="(option, i) of items" :key="getOptionRenderKey(option, getOptionIndex(i, getItemOptions))">
|
||||||
<slot name="optiongroup" :option="option.optionGroup" :index="getOptionIndex(i, getItemOptions)">{{ getOptionGroupLabel(option.optionGroup) }}</slot>
|
<li
|
||||||
|
v-if="isOptionGroup(option)"
|
||||||
|
:id="id + '_' + getOptionIndex(i, getItemOptions)"
|
||||||
|
:style="{ height: itemSize ? itemSize + 'px' : undefined }"
|
||||||
|
:class="cx('optionGroup')"
|
||||||
|
role="option"
|
||||||
|
v-bind="ptm('optionGroup')"
|
||||||
|
>
|
||||||
|
<slot name="optiongroup" :option="option.optionGroup" :index="getOptionIndex(i, getItemOptions)">{{ getOptionGroupLabel(option.optionGroup) }}</slot>
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
v-else
|
||||||
|
:id="id + '_' + getOptionIndex(i, getItemOptions)"
|
||||||
|
v-ripple
|
||||||
|
:style="{ height: itemSize ? itemSize + 'px' : undefined }"
|
||||||
|
:class="cx('option', { option, i, getItemOptions })"
|
||||||
|
role="option"
|
||||||
|
:aria-label="getOptionLabel(option)"
|
||||||
|
:aria-selected="isSelected(option)"
|
||||||
|
:aria-disabled="isOptionDisabled(option)"
|
||||||
|
:aria-setsize="ariaSetSize"
|
||||||
|
:aria-posinset="getAriaPosInset(getOptionIndex(i, getItemOptions))"
|
||||||
|
@click="onOptionSelect($event, option)"
|
||||||
|
@mousemove="onOptionMouseMove($event, getOptionIndex(i, getItemOptions))"
|
||||||
|
:data-p-selected="isSelected(option)"
|
||||||
|
:data-p-focus="focusedOptionIndex === getOptionIndex(i, getItemOptions)"
|
||||||
|
:data-p-disabled="isOptionDisabled(option)"
|
||||||
|
v-bind="getPTOptions(option, getItemOptions, i, 'option')"
|
||||||
|
>
|
||||||
|
<slot name="option" :option="option" :index="getOptionIndex(i, getItemOptions)">{{ getOptionLabel(option) }}</slot>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
<li v-if="!items || (items && items.length === 0)" :class="cx('emptyMessage')" role="option" v-bind="ptm('emptyMessage')">
|
||||||
|
<slot name="empty">{{ searchResultMessageText }}</slot>
|
||||||
</li>
|
</li>
|
||||||
<li
|
</ul>
|
||||||
v-else
|
</template>
|
||||||
:id="id + '_' + getOptionIndex(i, getItemOptions)"
|
<template v-if="$slots.loader" v-slot:loader="{ options }">
|
||||||
v-ripple
|
<slot name="loader" :options="options"></slot>
|
||||||
:style="{ height: itemSize ? itemSize + 'px' : undefined }"
|
</template>
|
||||||
:class="cx('option', { option, i, getItemOptions })"
|
</VirtualScroller>
|
||||||
role="option"
|
</div>
|
||||||
:aria-label="getOptionLabel(option)"
|
|
||||||
:aria-selected="isSelected(option)"
|
|
||||||
:aria-disabled="isOptionDisabled(option)"
|
|
||||||
:aria-setsize="ariaSetSize"
|
|
||||||
:aria-posinset="getAriaPosInset(getOptionIndex(i, getItemOptions))"
|
|
||||||
@click="onOptionSelect($event, option)"
|
|
||||||
@mousemove="onOptionMouseMove($event, getOptionIndex(i, getItemOptions))"
|
|
||||||
:data-p-selected="isSelected(option)"
|
|
||||||
:data-p-focus="focusedOptionIndex === getOptionIndex(i, getItemOptions)"
|
|
||||||
:data-p-disabled="isOptionDisabled(option)"
|
|
||||||
v-bind="getPTOptions(option, getItemOptions, i, 'option')"
|
|
||||||
>
|
|
||||||
<slot name="option" :option="option" :index="getOptionIndex(i, getItemOptions)">{{ getOptionLabel(option) }}</slot>
|
|
||||||
</li>
|
|
||||||
</template>
|
|
||||||
<li v-if="!items || (items && items.length === 0)" :class="cx('emptyMessage')" role="option" v-bind="ptm('emptyMessage')">
|
|
||||||
<slot name="empty">{{ searchResultMessageText }}</slot>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</template>
|
|
||||||
<template v-if="$slots.loader" v-slot:loader="{ options }">
|
|
||||||
<slot name="loader" :options="options"></slot>
|
|
||||||
</template>
|
|
||||||
</VirtualScroller>
|
|
||||||
<slot name="footer" :value="modelValue" :suggestions="visibleOptions"></slot>
|
<slot name="footer" :value="modelValue" :suggestions="visibleOptions"></slot>
|
||||||
<span role="status" aria-live="polite" class="p-hidden-accessible" v-bind="ptm('hiddenSelectedMessage')" :data-p-hidden-accessible="true">
|
<span role="status" aria-live="polite" class="p-hidden-accessible" v-bind="ptm('hiddenSelectedMessage')" :data-p-hidden-accessible="true">
|
||||||
{{ selectedMessageText }}
|
{{ selectedMessageText }}
|
||||||
|
|
|
@ -54,6 +54,10 @@ export enum AutoCompleteClasses {
|
||||||
* Class name of the list element
|
* Class name of the list element
|
||||||
*/
|
*/
|
||||||
list = 'p-autocomplete-list',
|
list = 'p-autocomplete-list',
|
||||||
|
/**
|
||||||
|
* Class name of the list container element
|
||||||
|
*/
|
||||||
|
listContainer = 'p-autocomplete-list-container',
|
||||||
/**
|
/**
|
||||||
* Class name of the option group element
|
* Class name of the option group element
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -84,6 +84,10 @@ const theme = ({ dt }) => `
|
||||||
box-shadow: ${dt('autocomplete.overlay.shadow')};
|
box-shadow: ${dt('autocomplete.overlay.shadow')};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.p-autocomplete-list-container {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.p-autocomplete-list {
|
.p-autocomplete-list {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -172,7 +176,7 @@ const theme = ({ dt }) => `
|
||||||
.p-variant-filled.p-autocomplete-input-multiple {
|
.p-variant-filled.p-autocomplete-input-multiple {
|
||||||
background: ${dt('autocomplete.filled.background')};
|
background: ${dt('autocomplete.filled.background')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-autocomplete:not(.p-disabled):hover .p-variant-filled.p-autocomplete-input-multiple {
|
.p-autocomplete:not(.p-disabled):hover .p-variant-filled.p-autocomplete-input-multiple {
|
||||||
background: ${dt('autocomplete.filled.hover.background')};
|
background: ${dt('autocomplete.filled.hover.background')};
|
||||||
}
|
}
|
||||||
|
@ -278,6 +282,7 @@ const classes = {
|
||||||
loader: 'p-autocomplete-loader',
|
loader: 'p-autocomplete-loader',
|
||||||
dropdown: 'p-autocomplete-dropdown',
|
dropdown: 'p-autocomplete-dropdown',
|
||||||
overlay: 'p-autocomplete-overlay p-component',
|
overlay: 'p-autocomplete-overlay p-component',
|
||||||
|
listContainer: 'p-autocomplete-list-container',
|
||||||
list: 'p-autocomplete-list',
|
list: 'p-autocomplete-list',
|
||||||
optionGroup: 'p-autocomplete-option-group',
|
optionGroup: 'p-autocomplete-option-group',
|
||||||
option: ({ instance, option, i, getItemOptions }) => [
|
option: ({ instance, option, i, getItemOptions }) => [
|
||||||
|
|
Loading…
Reference in New Issue