Refactor #5426 - For MultiSelect

pull/5507/head
tugcekucukoglu 2024-03-18 13:02:32 +03:00
parent d79ef6767d
commit 89e01ffe77
3 changed files with 34 additions and 38 deletions

View File

@ -9,8 +9,9 @@
*/ */
import { ButtonHTMLAttributes, HTMLAttributes, InputHTMLAttributes, TransitionProps, VNode } from 'vue'; import { ButtonHTMLAttributes, HTMLAttributes, InputHTMLAttributes, TransitionProps, VNode } from 'vue';
import { ComponentHooks } from '../basecomponent'; import { ComponentHooks } from '../basecomponent';
import { InputTextPassThroughOptions } from '../inputtext';
import { PassThroughOptions } from '../passthrough'; import { PassThroughOptions } from '../passthrough';
import { ClassComponent, GlobalComponentConstructor, PassThrough, HintedString } from '../ts-helpers'; import { ClassComponent, GlobalComponentConstructor, HintedString, PassThrough } from '../ts-helpers';
import { VirtualScrollerItemOptions, VirtualScrollerPassThroughOptionType, VirtualScrollerProps } from '../virtualscroller'; import { VirtualScrollerItemOptions, VirtualScrollerPassThroughOptionType, VirtualScrollerProps } from '../virtualscroller';
export declare type MultiSelectPassThroughOptionType = MultiSelectPassThroughAttributes | ((options: MultiSelectPassThroughMethodOptions) => MultiSelectPassThroughAttributes | string) | string | null | undefined; export declare type MultiSelectPassThroughOptionType = MultiSelectPassThroughAttributes | ((options: MultiSelectPassThroughMethodOptions) => MultiSelectPassThroughAttributes | string) | string | null | undefined;
@ -51,6 +52,20 @@ export interface MultiSelectPassThroughMethodOptions {
global: object | undefined; global: object | undefined;
} }
/**
* Custom shared passthrough(pt) option method.
*/
export interface MultiSelectSharedPassThroughMethodOptions {
/**
* Defines valid properties.
*/
props: MultiSelectProps;
/**
* Defines current inline state.
*/
state: MultiSelectState;
}
/** /**
* Custom change event. * Custom change event.
* @see {@link MultiSelectEmits.change} * @see {@link MultiSelectEmits.change}
@ -154,21 +169,14 @@ export interface MultiSelectPassThroughOptions {
*/ */
filterContainer?: MultiSelectPassThroughOptionType; filterContainer?: MultiSelectPassThroughOptionType;
/** /**
* Used to pass attributes to the filter input's DOM element. * Used to pass attributes to the InputText component.
* @see {@link InputTextPassThroughOptions}
*/ */
filterInput?: MultiSelectPassThroughOptionType; filterInput?: InputTextPassThroughOptions<MultiSelectSharedPassThroughMethodOptions>;
/** /**
* Used to pass attributes to the filter icon's DOM element. * Used to pass attributes to the filter icon's DOM element.
*/ */
filterIcon?: MultiSelectPassThroughOptionType; filterIcon?: MultiSelectPassThroughOptionType;
/**
* Used to pass attributes to the close button's DOM element.
*/
closeButton?: MultiSelectPassThroughOptionType;
/**
* Used to pass attributes to the close icon's DOM element.
*/
closeIcon?: MultiSelectPassThroughOptionType;
/** /**
* Used to pass attributes to the wrapper's DOM element. * Used to pass attributes to the wrapper's DOM element.
*/ */
@ -255,7 +263,7 @@ export interface MultiSelectState {
focused: boolean; focused: boolean;
/** /**
* Current focused item index as a number. * Current focused item index as a number.
* @defaultvalue -1 * @defaultValue -1
*/ */
focusedOptionIndex: number; focusedOptionIndex: number;
/** /**
@ -299,7 +307,7 @@ export interface MultiSelectProps {
*/ */
modelValue?: any; modelValue?: any;
/** /**
* An array of selectitems to display as the available options. * An array of select items to display as the available options.
*/ */
options?: any[] | undefined; options?: any[] | undefined;
/** /**

View File

@ -20,7 +20,7 @@
@focus="onFocus" @focus="onFocus"
@blur="onBlur" @blur="onBlur"
@keydown="onKeyDown" @keydown="onKeyDown"
v-bind="{ ...inputProps, ...ptm('hiddenInput') }" v-bind="ptm('hiddenInput')"
/> />
</div> </div>
<div :class="cx('labelContainer')" v-bind="ptm('labelContainer')"> <div :class="cx('labelContainer')" v-bind="ptm('labelContainer')">
@ -86,14 +86,17 @@
</template> </template>
</Checkbox> </Checkbox>
<div v-if="filter" :class="cx('filterContainer')" v-bind="ptm('filterContainer')"> <div v-if="filter" :class="cx('filterContainer')" v-bind="ptm('filterContainer')">
<input <MSInputText
ref="filterInput" ref="filterInput"
type="text"
:value="filterValue" :value="filterValue"
@vue:mounted="onFilterUpdated" @vue:mounted="onFilterUpdated"
@vue:updated="onFilterUpdated" @vue:updated="onFilterUpdated"
:class="cx('filterInput')" :class="cx('filterInput')"
:placeholder="filterPlaceholder" :placeholder="filterPlaceholder"
:invalid="invalid"
:disabled="disabled"
:variant="variant"
:unstyled="unstyled"
role="searchbox" role="searchbox"
autocomplete="off" autocomplete="off"
:aria-owns="id + '_list'" :aria-owns="id + '_list'"
@ -101,7 +104,8 @@
@keydown="onFilterKeyDown" @keydown="onFilterKeyDown"
@blur="onFilterBlur" @blur="onFilterBlur"
@input="onFilterChange" @input="onFilterChange"
v-bind="{ ...filterInputProps, ...ptm('filterInput') }" v-bind="filterInputProps"
:pt="ptm('filterInput')"
/> />
<slot name="filtericon" :class="cx('filterIcon')"> <slot name="filtericon" :class="cx('filterIcon')">
<component :is="filterIcon ? 'span' : 'SearchIcon'" :class="[cx('filterIcon'), filterIcon]" v-bind="ptm('filterIcon')" /> <component :is="filterIcon ? 'span' : 'SearchIcon'" :class="[cx('filterIcon'), filterIcon]" v-bind="ptm('filterIcon')" />
@ -110,11 +114,6 @@
<span v-if="filter" role="status" aria-live="polite" class="p-hidden-accessible" v-bind="ptm('hiddenFilterResult')" :data-p-hidden-accessible="true"> <span v-if="filter" role="status" aria-live="polite" class="p-hidden-accessible" v-bind="ptm('hiddenFilterResult')" :data-p-hidden-accessible="true">
{{ filterResultMessageText }} {{ filterResultMessageText }}
</span> </span>
<button v-ripple :class="cx('closeButton')" :aria-label="closeAriaLabel" @click="onCloseClick" type="button" v-bind="{ ...closeButtonProps, ...ptm('closeButton') }">
<slot name="closeicon" :class="cx('closeIcon')">
<component :is="closeIcon ? 'span' : 'TimesIcon'" :class="[cx('closeIcon'), closeIcon]" v-bind="ptm('closeIcon')" />
</slot>
</button>
</div> </div>
<div :class="cx('wrapper')" :style="{ 'max-height': virtualScrollerDisabled ? scrollHeight : '' }" v-bind="ptm('wrapper')"> <div :class="cx('wrapper')" :style="{ 'max-height': virtualScrollerDisabled ? scrollHeight : '' }" v-bind="ptm('wrapper')">
<VirtualScroller :ref="virtualScrollerRef" v-bind="virtualScrollerOptions" :items="visibleOptions" :style="{ height: scrollHeight }" :tabindex="-1" :disabled="virtualScrollerDisabled" :pt="ptm('virtualScroller')"> <VirtualScroller :ref="virtualScrollerRef" v-bind="virtualScrollerOptions" :items="visibleOptions" :style="{ height: scrollHeight }" :tabindex="-1" :disabled="virtualScrollerDisabled" :pt="ptm('virtualScroller')">
@ -205,6 +204,7 @@ import SearchIcon from 'primevue/icons/search';
import SpinnerIcon from 'primevue/icons/spinner'; import SpinnerIcon from 'primevue/icons/spinner';
import TimesIcon from 'primevue/icons/times'; import TimesIcon from 'primevue/icons/times';
import TimesCircleIcon from 'primevue/icons/timescircle'; import TimesCircleIcon from 'primevue/icons/timescircle';
import InputText from 'primevue/inputtext';
import OverlayEventBus from 'primevue/overlayeventbus'; import OverlayEventBus from 'primevue/overlayeventbus';
import Portal from 'primevue/portal'; import Portal from 'primevue/portal';
import Ripple from 'primevue/ripple'; import Ripple from 'primevue/ripple';
@ -451,9 +451,6 @@ export default {
DomHandler.focus(focusableEl); DomHandler.focus(focusableEl);
}, },
onCloseClick() {
this.hide(true);
},
onOptionSelect(event, option, index = -1, isFocus = false) { onOptionSelect(event, option, index = -1, isFocus = false) {
if (this.disabled || this.isOptionDisabled(option)) { if (this.disabled || this.isOptionDisabled(option)) {
return; return;
@ -697,7 +694,7 @@ export default {
this.alignOverlay(); this.alignOverlay();
this.scrollInView(); this.scrollInView();
this.autoFilterFocus && DomHandler.focus(this.$refs.filterInput); this.autoFilterFocus && DomHandler.focus(this.$refs.filterInput.$el);
}, },
onOverlayAfterEnter() { onOverlayAfterEnter() {
this.bindOutsideClickListener(); this.bindOutsideClickListener();
@ -1085,9 +1082,6 @@ export default {
toggleAllAriaLabel() { toggleAllAriaLabel() {
return this.$primevue.config.locale.aria ? this.$primevue.config.locale.aria[this.allSelected ? 'selectAll' : 'unselectAll'] : undefined; return this.$primevue.config.locale.aria ? this.$primevue.config.locale.aria[this.allSelected ? 'selectAll' : 'unselectAll'] : undefined;
}, },
closeAriaLabel() {
return this.$primevue.config.locale.aria ? this.$primevue.config.locale.aria.close : undefined;
},
virtualScrollerDisabled() { virtualScrollerDisabled() {
return !this.virtualScrollerOptions; return !this.virtualScrollerOptions;
} }
@ -1096,6 +1090,7 @@ export default {
ripple: Ripple ripple: Ripple
}, },
components: { components: {
MSInputText: InputText,
Checkbox, Checkbox,
VirtualScroller, VirtualScroller,
Portal, Portal,

View File

@ -32,7 +32,7 @@ const classes = {
trigger: 'p-multiselect-trigger', trigger: 'p-multiselect-trigger',
loadingIcon: 'p-multiselect-trigger-icon', loadingIcon: 'p-multiselect-trigger-icon',
dropdownIcon: 'p-multiselect-trigger-icon', dropdownIcon: 'p-multiselect-trigger-icon',
panel: ({ props, instance }) => [ panel: ({ instance }) => [
'p-multiselect-panel p-component', 'p-multiselect-panel p-component',
{ {
'p-ripple-disabled': instance.$primevue.config.ripple === false 'p-ripple-disabled': instance.$primevue.config.ripple === false
@ -40,15 +40,8 @@ const classes = {
], ],
header: 'p-multiselect-header', header: 'p-multiselect-header',
filterContainer: 'p-multiselect-filter-container', filterContainer: 'p-multiselect-filter-container',
filterInput: ({ props, instance }) => [ filterInput: 'p-multiselect-filter',
'p-multiselect-filter p-inputtext p-component',
{
'p-variant-filled': props.variant ? props.variant === 'filled' : instance.$primevue.config.inputStyle === 'filled'
}
],
filterIcon: 'p-multiselect-filter-icon', filterIcon: 'p-multiselect-filter-icon',
closeButton: 'p-multiselect-close p-link',
closeIcon: 'p-multiselect-close-icon',
wrapper: 'p-multiselect-items-wrapper', wrapper: 'p-multiselect-items-wrapper',
list: 'p-multiselect-items p-component', list: 'p-multiselect-items p-component',
itemGroup: 'p-multiselect-item-group', itemGroup: 'p-multiselect-item-group',