Merge branch 'master' into issue-3166
commit
13b9fd9537
api-generator/components
components
api/test
autocomplete
breadcrumb
calendar
checkbox
chip
confirmationservice
confirmdialog
confirmpopup
contextmenu
datatable
editor
fileupload
listbox
megamenu
menubar
multiselect
orderlist
panel
panelmenu
picklist
radiobutton
rating
speeddial
splitbutton
tabmenu
tabview
tieredmenu
pages
autocomplete
panelmenu
sidebar
tabmenu
treetable
|
@ -387,11 +387,15 @@ const AutoCompleteSlots = [
|
|||
},
|
||||
{
|
||||
name: 'content',
|
||||
description: 'Custom content for the virtual scroller'
|
||||
description: 'Custom content for the virtual scroller.'
|
||||
},
|
||||
{
|
||||
name: 'loader',
|
||||
description: 'Custom content for the virtual scroller loader items'
|
||||
description: 'Custom content for the virtual scroller loader items.'
|
||||
},
|
||||
{
|
||||
name: 'empty',
|
||||
description: 'Custom empty template when there is no data to display.'
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
@ -46,6 +46,12 @@ const SidebarProps = [
|
|||
type: 'string',
|
||||
default: 'close',
|
||||
description: 'Aria label of the close icon.'
|
||||
},
|
||||
{
|
||||
name: 'blockScroll',
|
||||
type: 'boolean',
|
||||
default: 'false',
|
||||
description: 'Whether background scroll should be blocked when sidebar is visible.'
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
@ -0,0 +1,298 @@
|
|||
import { afterEach } from 'vitest';
|
||||
import FilterService from '../FilterService';
|
||||
const filters = FilterService.filters;
|
||||
|
||||
import { ObjectUtils } from 'primevue/utils';
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
const checkParametersNullOrUndefined = (filterType) => {
|
||||
it('When value parameter is undefined', () => {
|
||||
expect(filters[filterType]('value', undefined)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('When value parameter is null', () => {
|
||||
expect(filters[filterType]('value', null)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('When filter parameter is undefined', () => {
|
||||
expect(filters[filterType](undefined, 'filter')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('When filter parameter is null', () => {
|
||||
expect(filters[filterType](undefined, 'filter')).toBeFalsy();
|
||||
});
|
||||
};
|
||||
|
||||
describe('FilterService', () => {
|
||||
describe('StartsWith filter test', () => {
|
||||
checkParametersNullOrUndefined('startsWith');
|
||||
it('When value and filter parameter is not null or undefined', () => {
|
||||
vi.spyOn(ObjectUtils, 'removeAccents').mockReturnValue('value');
|
||||
|
||||
const startsWith = filters.startsWith('value', 'filter', 'tr');
|
||||
|
||||
expect(startsWith).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Contains filter test', () => {
|
||||
checkParametersNullOrUndefined('contains');
|
||||
|
||||
it('When value and filter parameter is not null or undefined', () => {
|
||||
vi.spyOn(ObjectUtils, 'removeAccents').mockReturnValue('value');
|
||||
|
||||
const contains = filters.contains('value', 'filter', 'tr');
|
||||
|
||||
expect(contains).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('NotContains filter test', () => {
|
||||
checkParametersNullOrUndefined('notContains');
|
||||
|
||||
it('When value and filter parameter is not null or undefined', () => {
|
||||
vi.spyOn(ObjectUtils, 'removeAccents').mockReturnValue('value');
|
||||
|
||||
const notContains = filters.notContains('value', 'filter', 'tr');
|
||||
|
||||
expect(notContains).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('endsWith filter test', () => {
|
||||
checkParametersNullOrUndefined('endsWith');
|
||||
|
||||
it('When value and filter parameter is not null or undefined', () => {
|
||||
vi.spyOn(ObjectUtils, 'removeAccents').mockReturnValue('value');
|
||||
|
||||
const endsWith = filters.endsWith('value', 'filter', 'tr');
|
||||
|
||||
expect(endsWith).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('equals filter test', () => {
|
||||
checkParametersNullOrUndefined('equals');
|
||||
|
||||
it('When value and filter parameter has getTime property', () => {
|
||||
const getTimeMock = vi.fn(() => true);
|
||||
const equals = filters.equals({ getTime: getTimeMock }, { getTime: getTimeMock }, 'tr');
|
||||
|
||||
expect(equals).toBeTruthy();
|
||||
});
|
||||
|
||||
it('When value and filter parameter is not null or undefined', () => {
|
||||
vi.spyOn(ObjectUtils, 'removeAccents').mockReturnValue('value');
|
||||
|
||||
const equals = filters.equals('value', 'filter', 'tr');
|
||||
|
||||
expect(equals).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('notEquals filter test', () => {
|
||||
it('When filter parameter is undefined', () => {
|
||||
expect(filters.notEquals('value', undefined)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('When value parameter is undefined', () => {
|
||||
expect(filters.notEquals(undefined, 'filter')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('When value parameter is null', () => {
|
||||
expect(filters.notEquals(undefined, 'filter')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('When value and filter parameter has getTime property', () => {
|
||||
const getTimeMock = vi.fn(() => true);
|
||||
const notEquals = filters.notEquals({ getTime: getTimeMock }, { getTime: getTimeMock }, 'tr');
|
||||
|
||||
expect(notEquals).toBeFalsy();
|
||||
});
|
||||
|
||||
it('When value and filter parameter is not null or undefined', () => {
|
||||
vi.spyOn(ObjectUtils, 'removeAccents').mockReturnValue('value');
|
||||
|
||||
const notEquals = filters.notEquals('value', 'filter', 'tr');
|
||||
|
||||
expect(notEquals).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('in filter test', () => {
|
||||
checkParametersNullOrUndefined('in');
|
||||
|
||||
it('When value parameter equal to any filter word', () => {
|
||||
vi.spyOn(ObjectUtils, 'removeAccents').mockImplementation((value, filter) => value === filter);
|
||||
|
||||
const inFilter = filters.in('e', 'filter');
|
||||
|
||||
expect(inFilter).toBeTruthy();
|
||||
});
|
||||
|
||||
it('When value parameter not equal to any filter word', () => {
|
||||
vi.spyOn(ObjectUtils, 'removeAccents').mockImplementation((value, filter) => value === filter);
|
||||
|
||||
const inFilter = filters.in('d', 'filter');
|
||||
|
||||
expect(inFilter).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('between filter test', () => {
|
||||
checkParametersNullOrUndefined('between');
|
||||
it('When value has getTime func and smaller than filter[0]', () => {
|
||||
const filterGetTime = vi.fn(() => 1);
|
||||
const filterGetTime1 = vi.fn(() => 3);
|
||||
const valueGetTime = vi.fn(() => 2);
|
||||
|
||||
const between = filters.between({ getTime: valueGetTime }, [{ getTime: filterGetTime }, { getTime: filterGetTime1 }], 'tr');
|
||||
|
||||
expect(between).toBeTruthy();
|
||||
});
|
||||
|
||||
it('When value has getTime func and smaller than filter[0]', () => {
|
||||
const filter = 1;
|
||||
const filter1 = 2;
|
||||
const value = 2;
|
||||
|
||||
const between = filters.between(value, [filter, filter1], 'tr');
|
||||
|
||||
expect(between).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('lt filter test', () => {
|
||||
checkParametersNullOrUndefined('lt');
|
||||
it('When value has getTime func and smaller than filter', () => {
|
||||
const filterGetTime = vi.fn(() => 2);
|
||||
const valueGetTime = vi.fn(() => 1);
|
||||
|
||||
const lt = filters.lt({ getTime: valueGetTime }, { getTime: filterGetTime });
|
||||
|
||||
expect(lt).toBeTruthy();
|
||||
});
|
||||
|
||||
it('When value smaller than filter', () => {
|
||||
const filter = 2;
|
||||
const value = 1;
|
||||
|
||||
const lt = filters.lt(value, filter);
|
||||
|
||||
expect(lt).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('lte filter test', () => {
|
||||
checkParametersNullOrUndefined('lte');
|
||||
it('When value has getTime func and smaller than filter', () => {
|
||||
const filterGetTime = vi.fn(() => 2);
|
||||
const valueGetTime = vi.fn(() => 1);
|
||||
|
||||
const lte = filters.lte({ getTime: valueGetTime }, { getTime: filterGetTime });
|
||||
|
||||
expect(lte).toBeTruthy();
|
||||
});
|
||||
|
||||
it('When value smaller than filter', () => {
|
||||
const filter = 2;
|
||||
const value = 1;
|
||||
|
||||
const lte = filters.lte(value, filter);
|
||||
|
||||
expect(lte).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('gt filter test', () => {
|
||||
checkParametersNullOrUndefined('gt');
|
||||
it('When value has getTime func and smaller than filter[0]', () => {
|
||||
const filterGetTime = vi.fn(() => 2);
|
||||
const valueGetTime = vi.fn(() => 1);
|
||||
|
||||
const gt = filters.gt({ getTime: valueGetTime }, { getTime: filterGetTime });
|
||||
|
||||
expect(gt).toBeFalsy();
|
||||
});
|
||||
|
||||
it('When value smaller than filter[0]', () => {
|
||||
const filter = 2;
|
||||
const value = 1;
|
||||
|
||||
const gt = filters.gt(value, filter);
|
||||
|
||||
expect(gt).toBeFalsy();
|
||||
});
|
||||
});
|
||||
describe('gte filter test', () => {
|
||||
checkParametersNullOrUndefined('gte');
|
||||
it('When value has getTime func and smaller than filter[0]', () => {
|
||||
const filterGetTime = vi.fn(() => 2);
|
||||
const valueGetTime = vi.fn(() => 1);
|
||||
|
||||
const gte = filters.gte({ getTime: valueGetTime }, { getTime: filterGetTime });
|
||||
|
||||
expect(gte).toBeFalsy();
|
||||
});
|
||||
|
||||
it('When value parameter smaller than filter[0]', () => {
|
||||
const filter = 2;
|
||||
const value = 1;
|
||||
|
||||
const gte = filters.gte(value, filter);
|
||||
|
||||
expect(gte).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('dateIs filter test', () => {
|
||||
checkParametersNullOrUndefined('dateIs');
|
||||
it('When value and filter are equal', () => {
|
||||
const filter = new Date(1993, 6, 28, 14, 39, 7);
|
||||
const value = new Date(1993, 6, 28, 14, 39, 7);
|
||||
|
||||
const dateIs = filters.dateIs(value, filter);
|
||||
|
||||
expect(dateIs).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('dateIsNot filter test', () => {
|
||||
checkParametersNullOrUndefined('dateIsNot');
|
||||
it('When value and filter are not equal', () => {
|
||||
const filter = new Date(1993, 6, 28, 14, 39, 7);
|
||||
const value = new Date(1993, 6, 28, 14, 39, 7);
|
||||
|
||||
const dateIsNot = filters.dateIsNot(value, filter);
|
||||
|
||||
expect(dateIsNot).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('dateBefore filter test', () => {
|
||||
checkParametersNullOrUndefined('dateBefore');
|
||||
it('When filter value bigger than value', () => {
|
||||
const filter = new Date(1996, 6, 28, 14, 39, 8);
|
||||
const value = new Date(1993, 6, 28, 14, 39, 7);
|
||||
|
||||
const dateBefore = filters.dateBefore(value, filter);
|
||||
|
||||
expect(dateBefore).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('dateAfter filter test', () => {
|
||||
checkParametersNullOrUndefined('dateAfter');
|
||||
it('When value is not smaller than value', () => {
|
||||
const filter = new Date(1996, 6, 28, 14, 39, 8);
|
||||
const value = new Date(1993, 6, 28, 14, 39, 7);
|
||||
|
||||
const dateAfter = filters.dateAfter(value, filter);
|
||||
|
||||
expect(dateAfter).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -381,6 +381,10 @@ export interface AutoCompleteSlots {
|
|||
*/
|
||||
options: any[];
|
||||
}) => VNode[];
|
||||
/**
|
||||
* Custom empty template when there is no data to display.
|
||||
*/
|
||||
empty: () => VNode[];
|
||||
}
|
||||
|
||||
export declare type AutoCompleteEmits = {
|
||||
|
|
|
@ -119,6 +119,9 @@
|
|||
<!--TODO: Deprecated since v3.16.0-->
|
||||
</li>
|
||||
</template>
|
||||
<li v-if="!items || (items && items.length === 0)" class="p-autocomplete-empty-message" role="option">
|
||||
<slot name="empty">{{ searchResultMessageText }}</slot>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
<template v-if="$slots.loader" v-slot:loader="{ options }">
|
||||
|
@ -323,7 +326,7 @@ export default {
|
|||
watch: {
|
||||
suggestions() {
|
||||
if (this.searching) {
|
||||
ObjectUtils.isNotEmpty(this.suggestions) ? this.show() : this.hide();
|
||||
ObjectUtils.isNotEmpty(this.suggestions) ? this.show() : !!this.$slots.empty ? this.show() : this.hide();
|
||||
this.focusedOptionIndex = this.overlayVisible && this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1;
|
||||
this.searching = false;
|
||||
}
|
||||
|
@ -663,29 +666,19 @@ export default {
|
|||
this.multiple && event.stopPropagation(); // To prevent onArrowRightKeyOnMultiple method
|
||||
},
|
||||
onHomeKey(event) {
|
||||
const target = event.currentTarget;
|
||||
const len = target.value.length;
|
||||
|
||||
if (event.shiftKey) {
|
||||
event.currentTarget.setSelectionRange(0, len);
|
||||
} else {
|
||||
event.currentTarget.setSelectionRange(0, 0);
|
||||
}
|
||||
const { currentTarget } = event;
|
||||
const len = currentTarget.value.length;
|
||||
|
||||
currentTarget.setSelectionRange(0, event.shiftKey ? len : 0);
|
||||
this.focusedOptionIndex = -1;
|
||||
|
||||
event.preventDefault();
|
||||
},
|
||||
onEndKey(event) {
|
||||
const target = event.currentTarget;
|
||||
const len = target.value.length;
|
||||
|
||||
if (event.shiftKey) {
|
||||
event.currentTarget.setSelectionRange(0, len);
|
||||
} else {
|
||||
target.setSelectionRange(len, len);
|
||||
}
|
||||
const { currentTarget } = event;
|
||||
const len = currentTarget.value.length;
|
||||
|
||||
currentTarget.setSelectionRange(event.shiftKey ? 0 : len, len);
|
||||
this.focusedOptionIndex = -1;
|
||||
|
||||
event.preventDefault();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<nav class="p-breadcrumb p-component">
|
||||
<ol class="p-breadcrumb-list">
|
||||
<BreadcrumbItem v-if="home" :item="home" class="p-breadcrumb-home" :template="$slots.item" :exact="exact" />
|
||||
<BreadcrumbItem v-if="home" :item="home" class="p-breadcrumb-home" :exact="exact" />
|
||||
<template v-for="item of model" :key="item.label">
|
||||
<li class="p-menuitem-separator">
|
||||
<span class="pi pi-chevron-right" aria-hidden="true"></span>
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
import { RouterLinkStub, shallowMount } from '@vue/test-utils';
|
||||
import { beforeEach, expect } from 'vitest';
|
||||
import BreadcrumbItem from './BreadcrumbItem.vue';
|
||||
|
||||
let wrapper = null;
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallowMount(BreadcrumbItem, {
|
||||
global: {
|
||||
mocks: {
|
||||
$router: {
|
||||
currentRoute: {
|
||||
path: vi.fn()
|
||||
},
|
||||
navigate: () => true
|
||||
}
|
||||
},
|
||||
stubs: {
|
||||
'router-link': RouterLinkStub
|
||||
}
|
||||
},
|
||||
props: {
|
||||
item: { label: 'Computer', visible: () => true },
|
||||
template: null
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('BreadcrumbItem', () => {
|
||||
it('When component is mount, text should be exists', () => {
|
||||
expect(wrapper.find('.p-menuitem-text').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('When tag is triggered, onClick method should be called', async () => {
|
||||
const onClickSpy = vi.spyOn(wrapper.vm, 'onClick');
|
||||
const tag = wrapper.find('a');
|
||||
|
||||
tag.trigger('click');
|
||||
expect(tag.exists()).toBe(true);
|
||||
expect(onClickSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('When onClick method called and item has a command callback, callback should be triggered', async () => {
|
||||
await wrapper.setProps({ item: { label: 'Computer', visible: () => false, command: vi.fn() } });
|
||||
|
||||
const spy = vi.spyOn(wrapper.vm.item, 'command');
|
||||
|
||||
wrapper.vm.onClick();
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('When linkClass method called and isActive-isExactActive, tag classes should be effected', async () => {
|
||||
await wrapper.setProps({ exact: true });
|
||||
|
||||
expect(wrapper.vm.linkClass({ isActive: true, isExactActive: true })).toEqual([
|
||||
'p-menuitem-link',
|
||||
{
|
||||
'router-link-active': true,
|
||||
'router-link-active-exact': true
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
it('When item prop has a visible, visible method should be return falsy', async () => {
|
||||
await wrapper.setProps({ item: { label: 'Computer', visible: false, command: vi.fn() } });
|
||||
|
||||
expect(wrapper.vm.visible()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('When item prop has a disabled function, disabled method should be return truthy', async () => {
|
||||
await wrapper.setProps({ item: { disabled: () => true } });
|
||||
|
||||
expect(wrapper.vm.disabled()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('When item prop has a label function, disabled method should be return truthy', async () => {
|
||||
await wrapper.setProps({ item: { label: () => true } });
|
||||
|
||||
expect(wrapper.vm.label()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('When item prop has a icon, icon element class should contain item prop icon', async () => {
|
||||
await wrapper.setProps({ item: { icon: 'pi-discord' } });
|
||||
|
||||
expect(wrapper.find('a > span').classes()).toContain('pi-discord');
|
||||
});
|
||||
});
|
|
@ -1,7 +1,7 @@
|
|||
import { HTMLAttributes, InputHTMLAttributes, VNode } from 'vue';
|
||||
import { ClassComponent, GlobalComponentConstructor } from '../ts-helpers';
|
||||
|
||||
type CalendarValueType = Date | Date[] | undefined;
|
||||
type CalendarValueType = string | Date | string[] | Date[] | undefined;
|
||||
|
||||
type CalendarSlotDateType = { day: number; month: number; year: number; today: boolean; selectable: boolean };
|
||||
|
||||
|
|
|
@ -1783,7 +1783,7 @@ export default {
|
|||
throw 'Invalid Time';
|
||||
}
|
||||
|
||||
this.pm = ampm === this.$primevue.config.locale.am || ampm === this.$primevue.config.locale.am.toLowerCase();
|
||||
this.pm = ampm === this.$primevue.config.locale.pm || ampm === this.$primevue.config.locale.pm.toLowerCase();
|
||||
let time = this.parseTime(timeString);
|
||||
|
||||
value.setHours(time.hour);
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
:id="inputId"
|
||||
type="checkbox"
|
||||
:value="value"
|
||||
:class="inputClass"
|
||||
:style="inputStyle"
|
||||
:name="name"
|
||||
:checked="checked"
|
||||
:tabindex="tabindex"
|
||||
|
@ -21,7 +19,7 @@
|
|||
v-bind="inputProps"
|
||||
/>
|
||||
</div>
|
||||
<div ref="box" :class="['p-checkbox-box', { 'p-highlight': checked, 'p-disabled': disabled, 'p-focus': focused }]">
|
||||
<div ref="box" :class="['p-checkbox-box', inputClass, { 'p-highlight': checked, 'p-disabled': disabled, 'p-focus': focused }]" :style="inputStyle">
|
||||
<span :class="['p-checkbox-icon', { 'pi pi-check': checked }]"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -14,6 +14,10 @@ describe('Chip.vue', () => {
|
|||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('should exists', () => {
|
||||
expect(wrapper.find('.p-chip.p-component').exists()).toBe(true);
|
||||
expect(wrapper.find('.p-chip-icon').classes()).toContain('pi-primevue');
|
||||
|
@ -26,4 +30,19 @@ describe('Chip.vue', () => {
|
|||
|
||||
expect(wrapper.find('.p-chip.p-component').exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('When removable is true and keydown triggered OnKeydown method should be called', async () => {
|
||||
const closeSpy = vi.spyOn(wrapper.vm, 'onKeydown');
|
||||
|
||||
await wrapper.find('.p-chip-remove-icon').trigger('keydown');
|
||||
|
||||
expect(closeSpy).toHaveBeenCalled();
|
||||
});
|
||||
it('When onKeyDown method triggered close method should be called', async () => {
|
||||
const closeSpy = vi.spyOn(wrapper.vm, 'close');
|
||||
|
||||
await wrapper.vm.onKeydown({ key: 'Enter' });
|
||||
|
||||
expect(closeSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Vue, { Plugin } from 'vue';
|
||||
import { Plugin } from 'vue';
|
||||
import { ConfirmationOptions } from '../confirmationoptions';
|
||||
|
||||
declare const plugin: Plugin;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<CDialog v-model:visible="visible" role="alertdialog" class="p-confirm-dialog" :modal="true" :header="header" :blockScroll="blockScroll" :position="position" :breakpoints="breakpoints" :closeOnEscape="closeOnEscape" @update:visible="onHide">
|
||||
<template v-if="!$slots.message">
|
||||
<i :class="iconClass" />
|
||||
<span class="p-confirm-dialog-message">{{ message }}</span>
|
||||
<i v-if="confirmation.icon" :class="iconClass" />
|
||||
<span :class="{ 'p-confirm-dialog-message': confirmation.icon }">{{ message }}</span>
|
||||
</template>
|
||||
<component v-else :is="$slots.message" :message="confirmation"></component>
|
||||
<template #footer>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<Portal>
|
||||
<transition name="p-confirm-popup" @enter="onEnter" @leave="onLeave" @after-leave="onAfterLeave">
|
||||
<transition name="p-confirm-popup" @enter="onEnter" @after-enter="onAfterEnter" @leave="onLeave" @after-leave="onAfterLeave">
|
||||
<div v-if="visible" :ref="containerRef" v-focustrap role="alertdialog" :class="containerClass" :aria-modal="visible" @click="onOverlayClick" @keydown="onOverlayKeydown" v-bind="$attrs">
|
||||
<template v-if="!$slots.message">
|
||||
<div class="p-confirm-popup-content">
|
||||
|
@ -35,7 +35,9 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
confirmation: null
|
||||
confirmation: null,
|
||||
autoFocusAccept: null,
|
||||
autoFocusReject: null
|
||||
};
|
||||
},
|
||||
target: null,
|
||||
|
@ -129,13 +131,18 @@ export default {
|
|||
}
|
||||
},
|
||||
onEnter(el) {
|
||||
this.focus();
|
||||
this.autoFocusAccept = this.confirmation.defaultFocus === undefined || this.confirmation.defaultFocus === 'accept' ? true : false;
|
||||
this.autoFocusReject = this.confirmation.defaultFocus === 'reject' ? true : false;
|
||||
|
||||
this.bindOutsideClickListener();
|
||||
this.bindScrollListener();
|
||||
this.bindResizeListener();
|
||||
|
||||
ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
|
||||
},
|
||||
onAfterEnter() {
|
||||
this.focus();
|
||||
},
|
||||
onLeave() {
|
||||
this.unbindOutsideClickListener();
|
||||
this.unbindScrollListener();
|
||||
|
@ -221,7 +228,7 @@ export default {
|
|||
let focusTarget = this.container.querySelector('[autofocus]');
|
||||
|
||||
if (focusTarget) {
|
||||
focusTarget.focus();
|
||||
focusTarget.focus({ preventScroll: true }); // Firefox requires preventScroll
|
||||
}
|
||||
},
|
||||
isTargetClicked(event) {
|
||||
|
@ -276,12 +283,6 @@ export default {
|
|||
},
|
||||
rejectClass() {
|
||||
return ['p-confirm-popup-reject p-button-sm', this.confirmation ? this.confirmation.rejectClass || 'p-button-text' : null];
|
||||
},
|
||||
autoFocusAccept() {
|
||||
return this.confirmation.defaultFocus === undefined || this.confirmation.defaultFocus === 'accept' ? true : false;
|
||||
},
|
||||
autoFocusReject() {
|
||||
return this.confirmation.defaultFocus === 'reject' ? true : false;
|
||||
}
|
||||
},
|
||||
components: {
|
||||
|
|
|
@ -107,8 +107,8 @@ export default {
|
|||
getItemKey(processedItem) {
|
||||
return this.getItemId(processedItem);
|
||||
},
|
||||
getItemProp(processedItem, name) {
|
||||
return processedItem && processedItem.item ? ObjectUtils.getItemValue(processedItem.item[name]) : undefined;
|
||||
getItemProp(processedItem, name, params) {
|
||||
return processedItem && processedItem.item ? ObjectUtils.getItemValue(processedItem.item[name], params) : undefined;
|
||||
},
|
||||
getItemLabel(processedItem) {
|
||||
return this.getItemProp(processedItem, 'label');
|
||||
|
@ -129,9 +129,7 @@ export default {
|
|||
return ObjectUtils.isNotEmpty(processedItem.items);
|
||||
},
|
||||
onItemClick(event, processedItem) {
|
||||
const command = this.getItemProp(processedItem, 'command');
|
||||
|
||||
command && command({ originalEvent: event, item: processedItem.item });
|
||||
this.getItemProp(processedItem, 'command', { originalEvent: event, item: processedItem.item });
|
||||
this.$emit('item-click', { originalEvent: event, processedItem, isFocus: true });
|
||||
},
|
||||
onItemMouseEnter(event, processedItem) {
|
||||
|
|
|
@ -4,7 +4,7 @@ import { VirtualScrollerProps } from '../virtualscroller';
|
|||
|
||||
type DataTablePaginatorPositionType = 'top' | 'bottom' | 'both' | undefined;
|
||||
|
||||
type DataTableSortFieldType = string | ((item: any) => string) | undefined;
|
||||
type DataTableSortFieldType = string | ((item: any) => string) | undefined | null;
|
||||
|
||||
type DataTableDataKeyType = string | ((item: any) => string) | undefined;
|
||||
|
||||
|
@ -684,7 +684,7 @@ export interface DataTableProps {
|
|||
/**
|
||||
* One or more field names to use in row grouping.
|
||||
*/
|
||||
groupRowsBy?: (field: string) => object | string[] | string | undefined;
|
||||
groupRowsBy?: ((field: string) => object) | string[] | string | undefined;
|
||||
/**
|
||||
* Whether the row groups can be expandable.
|
||||
*/
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<button class="ql-italic" type="button"></button>
|
||||
<button class="ql-underline" type="button"></button>
|
||||
</span>
|
||||
<span class="ql-formats">
|
||||
<span :key="reRenderColorKey" class="ql-formats">
|
||||
<select class="ql-color"></select>
|
||||
<select class="ql-background"></select>
|
||||
</span>
|
||||
|
@ -69,10 +69,16 @@ export default {
|
|||
editorStyle: null,
|
||||
modules: null
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
reRenderColorKey: 0
|
||||
};
|
||||
},
|
||||
quill: null,
|
||||
watch: {
|
||||
modelValue(newValue, oldValue) {
|
||||
if (newValue !== oldValue && this.quill && !this.quill.hasFocus()) {
|
||||
this.reRenderColorKey++;
|
||||
this.renderValue(newValue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -252,11 +252,11 @@ export interface FileUploadSlots {
|
|||
/**
|
||||
* Function to remove an uploaded file.
|
||||
*/
|
||||
removeUploadedFileCallback: () => void;
|
||||
removeUploadedFileCallback: (index: number) => void;
|
||||
/**
|
||||
* Function to remove a file.
|
||||
*/
|
||||
removeFileCallback: () => void;
|
||||
removeFileCallback: (index: number) => void;
|
||||
/**
|
||||
* Uploaded progress as number.
|
||||
*/
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
:aria-setsize="ariaSetSize"
|
||||
:aria-posinset="getAriaPosInset(getOptionIndex(i, getItemOptions))"
|
||||
@click="onOptionSelect($event, option, getOptionIndex(i, getItemOptions))"
|
||||
@mousedown="onOptionMouseDown($event, getOptionIndex(i, getItemOptions))"
|
||||
@mousemove="onOptionMouseMove($event, getOptionIndex(i, getItemOptions))"
|
||||
@touchend="onOptionTouchEnd()"
|
||||
>
|
||||
|
@ -254,7 +255,7 @@ export default {
|
|||
},
|
||||
onListFocus(event) {
|
||||
this.focused = true;
|
||||
this.focusedOptionIndex = this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1;
|
||||
this.focusedOptionIndex = this.focusedOptionIndex !== -1 ? this.focusedOptionIndex : this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1;
|
||||
this.$emit('focus', event);
|
||||
},
|
||||
onListBlur(event) {
|
||||
|
@ -332,6 +333,9 @@ export default {
|
|||
this.optionTouched = false;
|
||||
index !== -1 && (this.focusedOptionIndex = index);
|
||||
},
|
||||
onOptionMouseDown(event, index) {
|
||||
this.changeFocusedOptionIndex(event, index);
|
||||
},
|
||||
onOptionMouseMove(event, index) {
|
||||
if (this.focusOnHover) {
|
||||
this.changeFocusedOptionIndex(event, index);
|
||||
|
|
|
@ -118,8 +118,8 @@ export default {
|
|||
getItemKey(processedItem) {
|
||||
return this.getItemId(processedItem);
|
||||
},
|
||||
getItemProp(processedItem, name) {
|
||||
return processedItem && processedItem.item ? ObjectUtils.getItemValue(processedItem.item[name]) : undefined;
|
||||
getItemProp(processedItem, name, params) {
|
||||
return processedItem && processedItem.item ? ObjectUtils.getItemValue(processedItem.item[name], params) : undefined;
|
||||
},
|
||||
getItemLabel(processedItem) {
|
||||
return this.getItemProp(processedItem, 'label');
|
||||
|
@ -140,9 +140,7 @@ export default {
|
|||
return ObjectUtils.isNotEmpty(processedItem.items);
|
||||
},
|
||||
onItemClick(event, processedItem) {
|
||||
const command = this.getItemProp(processedItem, 'command');
|
||||
|
||||
command && command({ originalEvent: event, item: processedItem.item });
|
||||
this.getItemProp(processedItem, 'command', { originalEvent: event, item: processedItem.item });
|
||||
this.$emit('item-click', { originalEvent: event, processedItem, isFocus: true });
|
||||
},
|
||||
onItemMouseEnter(event, processedItem) {
|
||||
|
|
|
@ -109,8 +109,8 @@ export default {
|
|||
getItemKey(processedItem) {
|
||||
return this.getItemId(processedItem);
|
||||
},
|
||||
getItemProp(processedItem, name) {
|
||||
return processedItem && processedItem.item ? ObjectUtils.getItemValue(processedItem.item[name]) : undefined;
|
||||
getItemProp(processedItem, name, params) {
|
||||
return processedItem && processedItem.item ? ObjectUtils.getItemValue(processedItem.item[name], params) : undefined;
|
||||
},
|
||||
getItemLabel(processedItem) {
|
||||
return this.getItemProp(processedItem, 'label');
|
||||
|
@ -131,9 +131,7 @@ export default {
|
|||
return ObjectUtils.isNotEmpty(processedItem.items);
|
||||
},
|
||||
onItemClick(event, processedItem) {
|
||||
const command = this.getItemProp(processedItem, 'command');
|
||||
|
||||
command && command({ originalEvent: event, item: processedItem.item });
|
||||
this.getItemProp(processedItem, 'command', { originalEvent: event, item: processedItem.item });
|
||||
this.$emit('item-click', { originalEvent: event, processedItem, isFocus: true });
|
||||
},
|
||||
onItemMouseEnter(event, processedItem) {
|
||||
|
|
|
@ -660,8 +660,12 @@ export default {
|
|||
pressedInInputText && (this.focusedOptionIndex = -1);
|
||||
},
|
||||
onHomeKey(event, pressedInInputText = false) {
|
||||
const { currentTarget } = event;
|
||||
|
||||
if (pressedInInputText) {
|
||||
event.currentTarget.setSelectionRange(0, 0);
|
||||
const len = currentTarget.value.length;
|
||||
|
||||
currentTarget.setSelectionRange(0, event.shiftKey ? len : 0);
|
||||
this.focusedOptionIndex = -1;
|
||||
} else {
|
||||
let metaKey = event.metaKey || event.ctrlKey;
|
||||
|
@ -679,11 +683,12 @@ export default {
|
|||
event.preventDefault();
|
||||
},
|
||||
onEndKey(event, pressedInInputText = false) {
|
||||
if (pressedInInputText) {
|
||||
const target = event.currentTarget;
|
||||
const len = target.value.length;
|
||||
const { currentTarget } = event;
|
||||
|
||||
target.setSelectionRange(len, len);
|
||||
if (pressedInInputText) {
|
||||
const len = currentTarget.value.length;
|
||||
|
||||
currentTarget.setSelectionRange(event.shiftKey ? 0 : len, len);
|
||||
this.focusedOptionIndex = -1;
|
||||
} else {
|
||||
let metaKey = event.metaKey || event.ctrlKey;
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
v-bind="listProps"
|
||||
>
|
||||
<template v-for="(item, i) of modelValue" :key="getItemKey(item, i)">
|
||||
<li :id="id + '_' + i" v-ripple role="option" :class="itemClass(item, `${id}_${i}`)" @click="onItemClick($event, item, i)" @touchend="onItemTouchEnd" :aria-selected="isSelected(item)">
|
||||
<li :id="id + '_' + i" v-ripple role="option" :class="itemClass(item, `${id}_${i}`)" @click="onItemClick($event, item, i)" @touchend="onItemTouchEnd" :aria-selected="isSelected(item)" @mousedown="onOptionMouseDown(i)">
|
||||
<slot name="item" :item="item" :index="i"> </slot>
|
||||
</li>
|
||||
</template>
|
||||
|
@ -148,9 +148,12 @@ export default {
|
|||
},
|
||||
onListFocus(event) {
|
||||
const selectedFirstItem = DomHandler.findSingle(this.list, 'li.p-orderlist-item.p-highlight');
|
||||
const index = selectedFirstItem ? ObjectUtils.findIndexInList(selectedFirstItem, this.list.children) : '0';
|
||||
const findIndex = ObjectUtils.findIndexInList(selectedFirstItem, this.list.children);
|
||||
|
||||
this.focused = true;
|
||||
|
||||
const index = this.focusedOptionIndex !== -1 ? this.focusedOptionIndex : selectedFirstItem ? findIndex : -1;
|
||||
|
||||
this.changeFocusedOptionIndex(index);
|
||||
this.$emit('focus', event);
|
||||
},
|
||||
|
@ -195,6 +198,10 @@ export default {
|
|||
break;
|
||||
}
|
||||
},
|
||||
onOptionMouseDown(index) {
|
||||
this.focused = true;
|
||||
this.focusedOptionIndex = index;
|
||||
},
|
||||
onArrowDownKey(event) {
|
||||
const optionIndex = this.findNextOptionIndex(this.focusedOptionIndex);
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ export default {
|
|||
collapsed: Boolean,
|
||||
toggleButtonProps: {
|
||||
type: null,
|
||||
defaault: null
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
|
|
@ -201,11 +201,10 @@ export default {
|
|||
},
|
||||
changeActiveItem(event, item, selfActive = false) {
|
||||
if (!this.isItemDisabled(item)) {
|
||||
this.activeItem = selfActive ? item : this.activeItem && ObjectUtils.equals(item, this.activeItem) ? null : item;
|
||||
|
||||
const active = this.isItemActive(item);
|
||||
const eventName = active ? 'panel-open' : 'panel-close';
|
||||
const eventName = !active ? 'panel-open' : 'panel-close';
|
||||
|
||||
this.activeItem = selfActive ? item : this.activeItem && this.activeItem === item ? null : item;
|
||||
this.changeExpandedKeys({ item, expanded: !active });
|
||||
this.$emit(eventName, { originalEvent: event, item });
|
||||
}
|
||||
|
|
|
@ -96,8 +96,8 @@ export default {
|
|||
getItemKey(processedItem) {
|
||||
return this.getItemId(processedItem);
|
||||
},
|
||||
getItemProp(processedItem, name) {
|
||||
return processedItem && processedItem.item ? ObjectUtils.getItemValue(processedItem.item[name]) : undefined;
|
||||
getItemProp(processedItem, name, params) {
|
||||
return processedItem && processedItem.item ? ObjectUtils.getItemValue(processedItem.item[name], params) : undefined;
|
||||
},
|
||||
getItemLabel(processedItem) {
|
||||
return this.getItemProp(processedItem, 'label');
|
||||
|
@ -118,9 +118,7 @@ export default {
|
|||
return ObjectUtils.isNotEmpty(processedItem.items);
|
||||
},
|
||||
onItemClick(event, processedItem) {
|
||||
const command = this.getItemProp(processedItem, 'command');
|
||||
|
||||
command && command({ originalEvent: event, item: processedItem.item });
|
||||
this.getItemProp(processedItem, 'command', { originalEvent: event, item: processedItem.item });
|
||||
this.$emit('item-toggle', { processedItem, expanded: !this.isItemActive(processedItem) });
|
||||
},
|
||||
onItemToggle(event) {
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
@click="onItemClick($event, item, i, 0)"
|
||||
@dblclick="onItemDblClick($event, item, 0)"
|
||||
@touchend="onItemTouchEnd"
|
||||
@mousedown="onOptionMouseDown(i, 'sourceList')"
|
||||
role="option"
|
||||
:aria-selected="isSelected(item, 0)"
|
||||
>
|
||||
|
@ -80,6 +81,7 @@
|
|||
@click="onItemClick($event, item, i, 1)"
|
||||
@dblclick="onItemDblClick($event, item, 1)"
|
||||
@keydown="onItemKeyDown($event, 'targetList')"
|
||||
@mousedown="onOptionMouseDown(i, 'targetList')"
|
||||
@touchend="onItemTouchEnd"
|
||||
role="option"
|
||||
:aria-selected="isSelected(item, 1)"
|
||||
|
@ -236,9 +238,12 @@ export default {
|
|||
},
|
||||
onListFocus(event, listType) {
|
||||
const selectedFirstItem = DomHandler.findSingle(this.$refs[listType].$el, 'li.p-picklist-item.p-highlight');
|
||||
const index = selectedFirstItem ? ObjectUtils.findIndexInList(selectedFirstItem, this.$refs[listType].$el.children) : '0';
|
||||
const findIndex = ObjectUtils.findIndexInList(selectedFirstItem, this.$refs[listType].$el.children);
|
||||
|
||||
this.focused[listType] = true;
|
||||
|
||||
const index = this.focusedOptionIndex !== -1 ? this.focusedOptionIndex : selectedFirstItem ? findIndex : -1;
|
||||
|
||||
this.changeFocusedOptionIndex(index, listType);
|
||||
this.$emit('focus', event);
|
||||
},
|
||||
|
@ -247,6 +252,10 @@ export default {
|
|||
this.focusedOptionIndex = -1;
|
||||
this.$emit('blur', event);
|
||||
},
|
||||
onOptionMouseDown(index, listType) {
|
||||
this.focused[listType] = true;
|
||||
this.focusedOptionIndex = index;
|
||||
},
|
||||
moveUp(event, listIndex) {
|
||||
if (this.d_selection && this.d_selection[listIndex]) {
|
||||
let valueList = [...this.modelValue[listIndex]];
|
||||
|
|
|
@ -18,17 +18,74 @@ describe('RadioButton.vue', () => {
|
|||
expect(wrapper.find('input').attributes().type).toBe('radio');
|
||||
});
|
||||
|
||||
it('should clicked', async () => {
|
||||
await wrapper.vm.onClick({});
|
||||
it('When disabled true and onClick triggered click emit should not be called', async () => {
|
||||
await wrapper.setProps({ disabled: true });
|
||||
await wrapper.vm.onClick();
|
||||
|
||||
expect(wrapper.emitted()['update:modelValue'][0]).toEqual(['Tatooine']);
|
||||
expect(wrapper.emitted().change[0]).toEqual([{}]);
|
||||
expect(wrapper.emitted()['click']).toEqual(undefined);
|
||||
expect(wrapper.emitted()['update:modelValue']).toEqual(undefined);
|
||||
});
|
||||
|
||||
it('should checked', async () => {
|
||||
it('When disabled false and onClick triggered click emit should be called', async () => {
|
||||
await wrapper.vm.onClick();
|
||||
|
||||
expect(wrapper.emitted()['update:modelValue'].length).toEqual(1);
|
||||
expect(wrapper.emitted().change.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('When value and modelValue equal and onClick triggered change emit should not be called', async () => {
|
||||
await wrapper.setProps({ modelValue: 'test', value: 'test' });
|
||||
await wrapper.vm.onClick();
|
||||
|
||||
expect(wrapper.emitted()['change']).toEqual(undefined);
|
||||
});
|
||||
|
||||
it('When modelValue changed, Checked should be effected', async () => {
|
||||
await wrapper.setProps({ modelValue: 'Tatooine' });
|
||||
|
||||
expect(wrapper.vm.checked).toBe(true);
|
||||
expect(wrapper.find('.p-radiobutton').classes()).toContain('p-radiobutton-checked');
|
||||
});
|
||||
|
||||
it('When component cliked OnClick method should be called', async () => {
|
||||
const spy = vi.spyOn(wrapper.vm, 'onClick');
|
||||
|
||||
await wrapper.find('.p-radiobutton').trigger('click');
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('When component focused onFocus method should be called', async () => {
|
||||
await wrapper.setProps({ inputId: 'test' });
|
||||
|
||||
const spy = vi.spyOn(wrapper.vm, 'onFocus');
|
||||
|
||||
await wrapper.find('#test').trigger('focus');
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('When onFocus method triggered, false should be true', async () => {
|
||||
await wrapper.vm.onFocus();
|
||||
|
||||
expect(wrapper.vm.focused).toBeTruthy();
|
||||
expect(wrapper.emitted().focus.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('When component blur onBlur method should be called', async () => {
|
||||
await wrapper.setProps({ inputId: 'test' });
|
||||
|
||||
const blurSpy = vi.spyOn(wrapper.vm, 'onBlur');
|
||||
|
||||
await wrapper.find('#test').trigger('blur');
|
||||
|
||||
expect(blurSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('When onBlur method triggered, false should be false', async () => {
|
||||
await wrapper.vm.onBlur();
|
||||
|
||||
expect(wrapper.vm.focus).toBeFalsy();
|
||||
expect(wrapper.emitted().blur.length).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { VNode } from 'vue';
|
||||
import { ClassComponent, GlobalComponentConstructor } from '../ts-helpers';
|
||||
|
||||
export interface RatingChangeEvent {
|
||||
|
|
|
@ -44,6 +44,10 @@ export interface SidebarProps {
|
|||
* Default value is true.
|
||||
*/
|
||||
modal?: boolean | undefined;
|
||||
/**
|
||||
* Whether background scroll should be blocked when sidebar is visible.
|
||||
*/
|
||||
blockScroll?: boolean | undefined;
|
||||
}
|
||||
|
||||
export interface SidebarSlots {
|
||||
|
|
|
@ -2,7 +2,6 @@ import { mount } from '@vue/test-utils';
|
|||
import PrimeVue from 'primevue/config';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import Sidebar from './Sidebar.vue';
|
||||
|
||||
describe('Sidebar.vue', () => {
|
||||
let wrapper;
|
||||
|
||||
|
@ -15,7 +14,7 @@ describe('Sidebar.vue', () => {
|
|||
}
|
||||
},
|
||||
props: {
|
||||
visible: true,
|
||||
visible: false,
|
||||
bazeZIndex: 1000
|
||||
},
|
||||
slots: {
|
||||
|
@ -23,95 +22,76 @@ describe('Sidebar.vue', () => {
|
|||
header: `<span class="header">Header Template</span>`
|
||||
}
|
||||
});
|
||||
wrapper.setProps({ visible: true });
|
||||
});
|
||||
|
||||
it('should exist', () => {
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('When component is mounted, sidebar should be exist', () => {
|
||||
expect(wrapper.find('.p-sidebar.p-component').exists()).toBe(true);
|
||||
expect(wrapper.find('.p-sidebar').classes()).toContain('p-sidebar-left');
|
||||
expect(wrapper.find('.p-sidebar').classes()).toContain('p-sidebar-active');
|
||||
});
|
||||
|
||||
it('should close', async () => {
|
||||
await wrapper.vm.hide();
|
||||
it('When mask element triggered, sidebar should be hide', async () => {
|
||||
const unbindOutsideClickListenerSpy = vi.spyOn(wrapper.vm, 'unbindOutsideClickListener');
|
||||
|
||||
expect(wrapper.emitted()['update:visible'][0]).toEqual([false]);
|
||||
await wrapper.find('.p-sidebar-mask').trigger('mousedown');
|
||||
|
||||
await wrapper.setProps({ visible: false });
|
||||
|
||||
expect(wrapper.find('.p-sidebar.p-component').exists()).toBe(false);
|
||||
expect(wrapper.emitted()['update:visible'].length).toBe(1);
|
||||
expect(unbindOutsideClickListenerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should set position', async () => {
|
||||
await wrapper.setProps({ position: 'bottom' });
|
||||
it('When transition trigger to onEnter, sidebar should be visible', async () => {
|
||||
const focusSpy = vi.spyOn(wrapper.vm, 'focus');
|
||||
|
||||
expect(wrapper.find('.p-sidebar').classes()).toContain('p-sidebar-bottom');
|
||||
await wrapper.vm.onEnter();
|
||||
|
||||
expect(wrapper.emitted().show.length).toBe(1);
|
||||
expect(wrapper.vm.maskVisible).toBeTruthy();
|
||||
expect(focusSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should set position', async () => {
|
||||
await wrapper.setProps({ position: 'full' });
|
||||
it('When transition trigger to onLeave, unbindOutsideClickListener should be triggered', async () => {
|
||||
const unbindOutsideClickListenerSpy = vi.spyOn(wrapper.vm, 'unbindOutsideClickListener');
|
||||
|
||||
expect(wrapper.vm.fullScreen).toBe(true);
|
||||
expect(wrapper.find('.p-sidebar').classes()).toContain('p-sidebar-full');
|
||||
await wrapper.vm.onLeave();
|
||||
|
||||
expect(wrapper.emitted().hide.length).toBe(1);
|
||||
expect(unbindOutsideClickListenerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should have custom close icon when provided', async () => {
|
||||
await wrapper.setProps({ closeIcon: 'pi pi-discord' });
|
||||
const icon = wrapper.find('.p-sidebar-close-icon');
|
||||
it('When transition trigger to onAfterEnter, bindOutsideClickListener should be triggered', async () => {
|
||||
const bindOutsideClickListenerSpy = vi.spyOn(wrapper.vm, 'bindOutsideClickListener');
|
||||
|
||||
expect(icon.classes()).toContain('pi-discord');
|
||||
await wrapper.vm.onAfterEnter();
|
||||
|
||||
expect(bindOutsideClickListenerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should header slot rendered', () => {
|
||||
expect(wrapper.find('.p-sidebar-header').exists()).toBe(true);
|
||||
expect(wrapper.find('.p-sidebar-header-content').exists()).toBe(true);
|
||||
expect(wrapper.find('span.header').exists()).toBe(true);
|
||||
expect(wrapper.find('span.header').text()).toBe('Header Template');
|
||||
it('When keydown is triggered , hide method should be triggered', async () => {
|
||||
const hideSpy = vi.spyOn(wrapper.vm, 'hide');
|
||||
|
||||
await wrapper.find('.p-sidebar').trigger('keydown', { code: 'Escape' });
|
||||
|
||||
expect(hideSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should default slot rendered', () => {
|
||||
expect(wrapper.find('h3').exists()).toBe(true);
|
||||
expect(wrapper.find('h3').text()).toBe('Left Sidebar');
|
||||
it('When keydown is triggered , hide method should be triggered', async () => {
|
||||
const hideSpy = vi.spyOn(wrapper.vm, 'hide');
|
||||
|
||||
await wrapper.find('.p-sidebar-close').trigger('click');
|
||||
|
||||
expect(hideSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should keydown work', async () => {
|
||||
const event = { code: 'Escape' };
|
||||
it('When component is unmount , unbindOutsideClickListenerSpy method should be triggered', async () => {
|
||||
const unbindOutsideClickListenerSpy = vi.spyOn(wrapper.vm, 'unbindOutsideClickListener');
|
||||
|
||||
await wrapper.vm.onKeydown(event);
|
||||
await wrapper.unmount();
|
||||
|
||||
expect(wrapper.emitted()['update:visible'][0]).toEqual([false]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when visible is false', () => {
|
||||
let wrapper;
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = mount(Sidebar, {
|
||||
global: {
|
||||
plugins: [PrimeVue],
|
||||
stubs: {
|
||||
teleport: true,
|
||||
transition: false
|
||||
}
|
||||
},
|
||||
props: {
|
||||
visible: true,
|
||||
bazeZIndex: 1000
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should show and hide emit work', async () => {
|
||||
expect(wrapper.emitted()['show'][0]).toEqual([]);
|
||||
|
||||
await wrapper.setProps({ visible: false });
|
||||
|
||||
expect(wrapper.emitted()['hide'][0]).toEqual([]);
|
||||
});
|
||||
|
||||
it('should be destroyed', () => {
|
||||
wrapper.unmount();
|
||||
expect(wrapper.componentVM.container).toBe(null);
|
||||
expect(wrapper.componentVM.mask).toBe(null);
|
||||
expect(unbindOutsideClickListenerSpy).toHaveBeenCalled();
|
||||
expect(Sidebar.container).toBe(null);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
<template>
|
||||
<Portal>
|
||||
<transition name="p-sidebar" @enter="onEnter" @leave="onLeave" @after-leave="onAfterLeave" appear>
|
||||
<div v-if="visible" :ref="containerRef" v-focustrap :class="containerClass" role="complementary" :aria-modal="modal" @keydown="onKeydown" v-bind="$attrs">
|
||||
<div :ref="headerContainerRef" class="p-sidebar-header">
|
||||
<div v-if="$slots.header" class="p-sidebar-header-content">
|
||||
<slot name="header"></slot>
|
||||
<div v-if="maskVisible" ref="mask" style="maskStyle" :class="maskClasses" @mousedown="onMaskClick">
|
||||
<transition name="p-sidebar" @after-enter="onAfterEnter" @enter="onEnter" @leave="onLeave" @after-leave="onAfterLeave" appear>
|
||||
<div :ref="containerRef" v-focustrap :class="containerClass" role="complementary" :aria-modal="modal" @keydown="onKeydown" v-bind="$attrs">
|
||||
<div :ref="headerContainerRef" class="p-sidebar-header">
|
||||
<div v-if="$slots.header" class="p-sidebar-header-content">
|
||||
<slot name="header"></slot>
|
||||
</div>
|
||||
<button v-if="showCloseIcon" :ref="closeButtonRef" v-ripple autofocus type="button" class="p-sidebar-close p-sidebar-icon p-link" :aria-label="closeAriaLabel" @click="hide">
|
||||
<span :class="['p-sidebar-close-icon', closeIcon]" />
|
||||
</button>
|
||||
</div>
|
||||
<div :ref="contentRef" class="p-sidebar-content">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<button v-if="showCloseIcon" :ref="closeButtonRef" v-ripple autofocus type="button" class="p-sidebar-close p-sidebar-icon p-link" :aria-label="closeAriaLabel" @click="hide">
|
||||
<span :class="['p-sidebar-close-icon', closeIcon]" />
|
||||
</button>
|
||||
</div>
|
||||
<div :ref="contentRef" class="p-sidebar-content">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</transition>
|
||||
</div>
|
||||
</Portal>
|
||||
</template>
|
||||
|
||||
|
@ -26,7 +28,6 @@ import { DomHandler, ZIndexUtils } from 'primevue/utils';
|
|||
|
||||
export default {
|
||||
name: 'Sidebar',
|
||||
inheritAttrs: false,
|
||||
emits: ['update:visible', 'show', 'hide'],
|
||||
props: {
|
||||
visible: {
|
||||
|
@ -60,50 +61,69 @@ export default {
|
|||
modal: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
blockScroll: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
mask: null,
|
||||
maskClickListener: null,
|
||||
container: null,
|
||||
content: null,
|
||||
headerContainer: null,
|
||||
closeButton: null,
|
||||
beforeUnmount() {
|
||||
this.destroyModal();
|
||||
outsideClickListener: null,
|
||||
data() {
|
||||
return {
|
||||
maskVisible: false
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
visible(val) {
|
||||
this.maskVisible = val;
|
||||
}
|
||||
},
|
||||
|
||||
beforeUnmount() {
|
||||
if (this.container && this.autoZIndex) {
|
||||
ZIndexUtils.clear(this.container);
|
||||
}
|
||||
|
||||
this.unbindOutsideClickListener();
|
||||
this.container = null;
|
||||
},
|
||||
methods: {
|
||||
hide() {
|
||||
this.$emit('update:visible', false);
|
||||
|
||||
this.unbindOutsideClickListener();
|
||||
this.blockScroll && DomHandler.removeClass(document.body, 'p-overflow-hidden');
|
||||
},
|
||||
onEnter(el) {
|
||||
onEnter() {
|
||||
this.$emit('show');
|
||||
|
||||
if (this.autoZIndex) {
|
||||
ZIndexUtils.set('modal', el, this.baseZIndex || this.$primevue.config.zIndex.modal);
|
||||
ZIndexUtils.set('modal', this.$refs.mask, this.baseZIndex || this.$primevue.config.zIndex.modal);
|
||||
}
|
||||
|
||||
this.maskVisible = true;
|
||||
this.focus();
|
||||
|
||||
if (this.modal && !this.fullScreen) {
|
||||
this.enableModality();
|
||||
}
|
||||
},
|
||||
onLeave() {
|
||||
this.$emit('hide');
|
||||
DomHandler.addClass(this.$refs.mask, 'p-component-overlay-leave');
|
||||
|
||||
if (this.modal && !this.fullScreen) {
|
||||
this.disableModality();
|
||||
this.$emit('hide');
|
||||
this.unbindOutsideClickListener();
|
||||
},
|
||||
onAfterLeave() {
|
||||
if (this.autoZIndex) {
|
||||
ZIndexUtils.clear(this.mask);
|
||||
}
|
||||
},
|
||||
onAfterLeave(el) {
|
||||
if (this.autoZIndex) {
|
||||
ZIndexUtils.clear(el);
|
||||
onAfterEnter() {
|
||||
this.bindOutsideClickListener();
|
||||
|
||||
if (this.blockScroll) {
|
||||
DomHandler.addClass(document.body, 'p-overflow-hidden');
|
||||
}
|
||||
},
|
||||
focus() {
|
||||
|
@ -123,54 +143,14 @@ export default {
|
|||
|
||||
focusTarget && focusTarget.focus();
|
||||
},
|
||||
enableModality() {
|
||||
if (!this.mask) {
|
||||
this.mask = document.createElement('div');
|
||||
this.mask.setAttribute('class', 'p-sidebar-mask p-component-overlay p-component-overlay-enter');
|
||||
this.mask.style.zIndex = String(parseInt(this.container.style.zIndex, 10) - 1);
|
||||
|
||||
if (this.dismissable) {
|
||||
this.bindMaskClickListener();
|
||||
}
|
||||
|
||||
document.body.appendChild(this.mask);
|
||||
DomHandler.addClass(document.body, 'p-overflow-hidden');
|
||||
}
|
||||
},
|
||||
disableModality() {
|
||||
if (this.mask) {
|
||||
DomHandler.addClass(this.mask, 'p-component-overlay-leave');
|
||||
this.mask.addEventListener('animationend', () => {
|
||||
this.destroyModal();
|
||||
});
|
||||
}
|
||||
},
|
||||
bindMaskClickListener() {
|
||||
if (!this.maskClickListener) {
|
||||
this.maskClickListener = () => {
|
||||
this.hide();
|
||||
};
|
||||
|
||||
this.mask.addEventListener('click', this.maskClickListener);
|
||||
}
|
||||
},
|
||||
onKeydown(event) {
|
||||
if (event.code === 'Escape') {
|
||||
this.hide();
|
||||
}
|
||||
},
|
||||
unbindMaskClickListener() {
|
||||
if (this.maskClickListener) {
|
||||
this.mask.removeEventListener('click', this.maskClickListener);
|
||||
this.maskClickListener = null;
|
||||
}
|
||||
},
|
||||
destroyModal() {
|
||||
if (this.mask) {
|
||||
this.unbindMaskClickListener();
|
||||
document.body.removeChild(this.mask);
|
||||
DomHandler.removeClass(document.body, 'p-overflow-hidden');
|
||||
this.mask = null;
|
||||
onMaskClick(event) {
|
||||
if (this.dismissable && this.modal && this.$refs.mask === event.target) {
|
||||
this.hide();
|
||||
}
|
||||
},
|
||||
containerRef(el) {
|
||||
|
@ -184,16 +164,43 @@ export default {
|
|||
},
|
||||
closeButtonRef(el) {
|
||||
this.closeButton = el;
|
||||
},
|
||||
getPositionClass() {
|
||||
const positions = ['left', 'right', 'top', 'bottom'];
|
||||
const pos = positions.find((item) => item === this.position);
|
||||
|
||||
return pos ? `p-sidebar-${pos}` : '';
|
||||
},
|
||||
bindOutsideClickListener() {
|
||||
if (!this.outsideClickListener) {
|
||||
this.outsideClickListener = (event) => {
|
||||
if (!this.modal && this.isOutsideClicked(event) && this.dismissable) {
|
||||
this.hide();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('click', this.outsideClickListener);
|
||||
}
|
||||
},
|
||||
unbindOutsideClickListener() {
|
||||
if (this.outsideClickListener) {
|
||||
document.removeEventListener('click', this.outsideClickListener);
|
||||
this.outsideClickListener = null;
|
||||
}
|
||||
},
|
||||
isOutsideClicked(event) {
|
||||
return this.container && !this.container.contains(event.target);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
return [
|
||||
'p-sidebar p-component p-sidebar-' + this.position,
|
||||
'p-sidebar p-component',
|
||||
this.getPositionClass(),
|
||||
{
|
||||
'p-sidebar-active': this.visible,
|
||||
'p-input-filled': this.$primevue.config.inputStyle === 'filled',
|
||||
'p-ripple-disabled': this.$primevue.config.ripple === false
|
||||
'p-ripple-disabled': this.$primevue.config.ripple === false,
|
||||
'p-sidebar-full': this.fullScreen
|
||||
}
|
||||
];
|
||||
},
|
||||
|
@ -202,6 +209,18 @@ export default {
|
|||
},
|
||||
closeAriaLabel() {
|
||||
return this.$primevue.config.locale.aria ? this.$primevue.config.locale.aria.close : undefined;
|
||||
},
|
||||
maskClasses() {
|
||||
return [
|
||||
'p-sidebar-mask',
|
||||
this.getPositionClass(),
|
||||
{
|
||||
'p-component-overlay p-component-overlay-enter': this.modal,
|
||||
'p-sidebar-mask-scrollblocker': this.blockScroll,
|
||||
'p-sidebar-visible': this.maskVisible,
|
||||
'p-sidebar-full': this.fullScreen
|
||||
}
|
||||
];
|
||||
}
|
||||
},
|
||||
directives: {
|
||||
|
@ -215,134 +234,183 @@ export default {
|
|||
</script>
|
||||
|
||||
<style>
|
||||
.p-sidebar {
|
||||
.p-sidebar-mask {
|
||||
position: fixed;
|
||||
transition: transform 0.3s;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: none;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
pointer-events: none;
|
||||
background-color: transparent;
|
||||
transition-property: background-color;
|
||||
}
|
||||
|
||||
.p-sidebar-visible {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.p-sidebar-mask.p-component-overlay {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.p-sidebar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
pointer-events: auto;
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
position: relative;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.p-sidebar-content {
|
||||
position: relative;
|
||||
overflow-y: auto;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.p-sidebar-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.p-sidebar-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.p-sidebar-left {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 20rem;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.p-sidebar-right {
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 20rem;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.p-sidebar-top {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 10rem;
|
||||
}
|
||||
|
||||
.p-sidebar-bottom {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 10rem;
|
||||
}
|
||||
|
||||
.p-sidebar-full {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
-webkit-transition: none;
|
||||
.p-sidebar-full .p-sidebar {
|
||||
transition: none;
|
||||
transform: none;
|
||||
width: 100vw !important;
|
||||
height: 100vh !important;
|
||||
max-height: 100%;
|
||||
top: 0px !important;
|
||||
left: 0px !important;
|
||||
}
|
||||
|
||||
/* Animation */
|
||||
/* Center */
|
||||
.p-sidebar-left.p-sidebar-enter-from,
|
||||
.p-sidebar-left.p-sidebar-leave-to {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
.p-sidebar-right.p-sidebar-enter-from,
|
||||
.p-sidebar-right.p-sidebar-leave-to {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
.p-sidebar-top.p-sidebar-enter-from,
|
||||
.p-sidebar-top.p-sidebar-leave-to {
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
||||
.p-sidebar-bottom.p-sidebar-enter-from,
|
||||
.p-sidebar-bottom.p-sidebar-leave-to {
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
.p-sidebar-full.p-sidebar-enter-from,
|
||||
.p-sidebar-full.p-sidebar-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.p-sidebar-full.p-sidebar-enter-active,
|
||||
.p-sidebar-full.p-sidebar-leave-active {
|
||||
transition: opacity 400ms cubic-bezier(0.25, 0.8, 0.25, 1);
|
||||
}
|
||||
|
||||
.p-sidebar-left.p-sidebar-sm,
|
||||
.p-sidebar-right.p-sidebar-sm {
|
||||
/* Position */
|
||||
.p-sidebar-left {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.p-sidebar-right {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.p-sidebar-top {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.p-sidebar-bottom {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
/* Size */
|
||||
.p-sidebar-left .p-sidebar {
|
||||
width: 20rem;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.p-sidebar-right .p-sidebar {
|
||||
width: 20rem;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.p-sidebar-top .p-sidebar {
|
||||
height: 10rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.p-sidebar-bottom .p-sidebar {
|
||||
height: 10rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.p-sidebar-left .p-sidebar-sm,
|
||||
.p-sidebar-right .p-sidebar-sm {
|
||||
width: 20rem;
|
||||
}
|
||||
|
||||
.p-sidebar-left.p-sidebar-md,
|
||||
.p-sidebar-right.p-sidebar-md {
|
||||
.p-sidebar-left .p-sidebar-md,
|
||||
.p-sidebar-right .p-sidebar-md {
|
||||
width: 40rem;
|
||||
}
|
||||
|
||||
.p-sidebar-left.p-sidebar-lg,
|
||||
.p-sidebar-right.p-sidebar-lg {
|
||||
.p-sidebar-left .p-sidebar-lg,
|
||||
.p-sidebar-right .p-sidebar-lg {
|
||||
width: 60rem;
|
||||
}
|
||||
|
||||
.p-sidebar-top.p-sidebar-sm,
|
||||
.p-sidebar-bottom.p-sidebar-sm {
|
||||
.p-sidebar-top .p-sidebar-sm,
|
||||
.p-sidebar-bottom .p-sidebar-sm {
|
||||
height: 10rem;
|
||||
}
|
||||
|
||||
.p-sidebar-top.p-sidebar-md,
|
||||
.p-sidebar-bottom.p-sidebar-md {
|
||||
.p-sidebar-top .p-sidebar-md,
|
||||
.p-sidebar-bottom .p-sidebar-md {
|
||||
height: 20rem;
|
||||
}
|
||||
|
||||
.p-sidebar-top.p-sidebar-lg,
|
||||
.p-sidebar-bottom.p-sidebar-lg {
|
||||
.p-sidebar-top .p-sidebar-lg,
|
||||
.p-sidebar-bottom .p-sidebar-lg {
|
||||
height: 30rem;
|
||||
}
|
||||
|
||||
.p-sidebar-left .p-sidebar-view,
|
||||
.p-sidebar-right .p-sidebar-view,
|
||||
.p-sidebar-top .p-sidebar-view,
|
||||
.p-sidebar-bottom .p-sidebar-view {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.p-sidebar-left .p-sidebar-content,
|
||||
.p-sidebar-right .p-sidebar-content,
|
||||
.p-sidebar-top .p-sidebar-content,
|
||||
.p-sidebar-bottom .p-sidebar-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 64em) {
|
||||
.p-sidebar-left.p-sidebar-lg,
|
||||
.p-sidebar-left.p-sidebar-md,
|
||||
.p-sidebar-right.p-sidebar-lg,
|
||||
.p-sidebar-right.p-sidebar-md {
|
||||
.p-sidebar-left .p-sidebar-lg,
|
||||
.p-sidebar-left .p-sidebar-md,
|
||||
.p-sidebar-right .p-sidebar-lg,
|
||||
.p-sidebar-right .p-sidebar-md {
|
||||
width: 20rem;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -536,6 +536,9 @@ export default {
|
|||
.p-speeddial {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.p-speeddial-button {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
|
@ -548,6 +551,7 @@ export default {
|
|||
justify-content: center;
|
||||
transition: top 0s linear 0.2s;
|
||||
pointer-events: none;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.p-speeddial-item {
|
||||
|
|
|
@ -27,6 +27,7 @@ import { UniqueComponentId } from 'primevue/utils';
|
|||
|
||||
export default {
|
||||
name: 'SplitButton',
|
||||
emits: ['click'],
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
|
@ -91,6 +92,8 @@ export default {
|
|||
},
|
||||
onDefaultButtonClick(event) {
|
||||
this.$refs.menu.hide(event);
|
||||
|
||||
this.$emit('click');
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<span class="p-menuitem-text">{{ label(item) }}</span>
|
||||
</a>
|
||||
</template>
|
||||
<component v-else :is="$slots.item" :item="item"></component>
|
||||
<component v-else :is="$slots.item" :item="item" :index="i"></component>
|
||||
</li>
|
||||
</router-link>
|
||||
<li v-else-if="visible(item)" ref="tab" :class="getItemClass(item, i)" role="presentation" @click="onItemClick($event, item, i)" @keydown="onKeydownItem($event, item, i)">
|
||||
|
@ -31,7 +31,7 @@
|
|||
<span class="p-menuitem-text">{{ label(item) }}</span>
|
||||
</a>
|
||||
</template>
|
||||
<component v-else :is="$slots.item" :item="item"></component>
|
||||
<component v-else :is="$slots.item" :item="item" :index="i"></component>
|
||||
</li>
|
||||
</template>
|
||||
<li ref="inkbar" class="p-tabmenu-ink-bar"></li>
|
||||
|
|
|
@ -99,11 +99,11 @@ export default {
|
|||
},
|
||||
previousButtonProps: {
|
||||
type: null,
|
||||
defaault: null
|
||||
default: null
|
||||
},
|
||||
nextButtonProps: {
|
||||
type: null,
|
||||
defaault: null
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
|
|
@ -96,8 +96,8 @@ export default {
|
|||
getItemKey(processedItem) {
|
||||
return this.getItemId(processedItem);
|
||||
},
|
||||
getItemProp(processedItem, name) {
|
||||
return processedItem && processedItem.item ? ObjectUtils.getItemValue(processedItem.item[name]) : undefined;
|
||||
getItemProp(processedItem, name, params) {
|
||||
return processedItem && processedItem.item ? ObjectUtils.getItemValue(processedItem.item[name], params) : undefined;
|
||||
},
|
||||
getItemLabel(processedItem) {
|
||||
return this.getItemProp(processedItem, 'label');
|
||||
|
@ -118,9 +118,7 @@ export default {
|
|||
return ObjectUtils.isNotEmpty(processedItem.items);
|
||||
},
|
||||
onItemClick(event, processedItem) {
|
||||
const command = this.getItemProp(processedItem, 'command');
|
||||
|
||||
command && command({ originalEvent: event, item: processedItem.item });
|
||||
this.getItemProp(processedItem, 'command', { originalEvent: event, item: processedItem.item });
|
||||
this.$emit('item-click', { originalEvent: event, processedItem, isFocus: true });
|
||||
},
|
||||
onItemMouseEnter(event, processedItem) {
|
||||
|
|
|
@ -562,6 +562,10 @@ export default {
|
|||
<td>loader</td>
|
||||
<td>options: Options of the loader items for virtualscroller</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>empty</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -605,6 +609,10 @@ export default {
|
|||
<td>p-autocomplete-token-label</td>
|
||||
<td>Label of a selected item in multiple mode.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>p-autocomplete-empty-message</td>
|
||||
<td>Container element when there is no suggestion to display.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>p-overlay-open</td>
|
||||
<td>Container element when overlay is visible.</td>
|
||||
|
|
|
@ -681,7 +681,7 @@ export default {
|
|||
<Button type="button" icon="pi pi-plus" label="Expand All" @click="expandAll" class="mr-2" />
|
||||
<Button type="button" icon="pi pi-minus" label="Collapse All" @click="collapseAll" />
|
||||
</div>
|
||||
<PanelMenu :model="items" :expandedKeys="expandedKeys" />
|
||||
<PanelMenu :model="items" v-model:expandedKeys="expandedKeys" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -867,7 +867,7 @@ export default {
|
|||
<Button type="button" icon="pi pi-plus" label="Expand All" @click="expandAll" class="mr-2" />
|
||||
<Button type="button" icon="pi pi-minus" label="Collapse All" @click="collapseAll" />
|
||||
</div>
|
||||
<PanelMenu :model="items" :expandedKeys="expandedKeys" />
|
||||
<PanelMenu :model="items" v-model:expandedKeys="expandedKeys" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -1053,7 +1053,7 @@ export default {
|
|||
<p-button type="button" icon="pi pi-plus" label="Expand All" @click="expandAll" class="mr-2"></p-button>
|
||||
<p-button type="button" icon="pi pi-minus" label="Collapse All" @click="collapseAll"></p-button>
|
||||
</div>
|
||||
<p-panelmenu :model="items" :expanded-keys="expandedKeys"></p-panelmenu>
|
||||
<p-panelmenu :model="items" v-model:expanded-keys="expandedKeys"></p-panelmenu>
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
|
|
|
@ -121,6 +121,12 @@ import Sidebar from 'primevue/sidebar';
|
|||
<b> Deprecated: </b> <i>aria.close</i> can be used in defaults to PrimeVue <router-link to="/locale">Locale</router-link> configuration.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>blockScroll</td>
|
||||
<td>boolean</td>
|
||||
<td>true</td>
|
||||
<td>Whether background scroll should be blocked when sidebar is visible.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
@ -159,7 +159,10 @@ export default {
|
|||
<tbody>
|
||||
<tr>
|
||||
<td>item</td>
|
||||
<td>item: Menuitem instance</td>
|
||||
<td>
|
||||
item: Menuitem instance<br />
|
||||
index: Index of the menuitem instance
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -212,7 +212,7 @@ export default class NodeService {
|
|||
<Button type="button" icon="pi pi-plus" label="Expand All" @click="expandAll" />
|
||||
<Button type="button" icon="pi pi-minus" label="Collapse All" @click="collapseAll" />
|
||||
</div>
|
||||
<Tree :value="nodes" :expandedKeys="expandedKeys"></Tree>
|
||||
<Tree :value="nodes" v-model:expandedKeys="expandedKeys"></Tree>
|
||||
|
||||
</code></pre>
|
||||
|
||||
|
@ -894,7 +894,7 @@ export default {
|
|||
<Button type="button" icon="pi pi-plus" label="Expand All" @click="expandAll" />
|
||||
<Button type="button" icon="pi pi-minus" label="Collapse All" @click="collapseAll" />
|
||||
</div>
|
||||
<Tree :value="nodes" :expandedKeys="expandedKeys"></Tree>
|
||||
<Tree :value="nodes" v-model:expandedKeys="expandedKeys"></Tree>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -958,7 +958,7 @@ export default {
|
|||
<Button type="button" icon="pi pi-plus" label="Expand All" @click="expandAll" />
|
||||
<Button type="button" icon="pi pi-minus" label="Collapse All" @click="collapseAll" />
|
||||
</div>
|
||||
<Tree :value="nodes" :expandedKeys="expandedKeys"></Tree>
|
||||
<Tree :value="nodes" v-model:expandedKeys="expandedKeys"></Tree>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -1018,7 +1018,7 @@ export default {
|
|||
<p-button type="button" icon="pi pi-plus" label="Expand All" @click="expandAll"></p-button>
|
||||
<p-button type="button" icon="pi pi-minus" label="Collapse All" @click="collapseAll"></p-button>
|
||||
</div>
|
||||
<p-tree :value="nodes" :expanded-keys="expandedKeys"></p-tree>
|
||||
<p-tree :value="nodes" v-model:expanded-keys="expandedKeys"></p-tree>
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<Button type="button" icon="pi pi-plus" label="Expand All" @click="expandAll" />
|
||||
<Button type="button" icon="pi pi-minus" label="Collapse All" @click="collapseAll" />
|
||||
</div>
|
||||
<Tree :value="nodes" :expandedKeys="expandedKeys"></Tree>
|
||||
<Tree v-model:expandedKeys="expandedKeys" :value="nodes"></Tree>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -647,7 +647,7 @@ export default {
|
|||
<Button type="button" icon="pi pi-plus" label="Expand All" @click="expandAll" />
|
||||
<Button type="button" icon="pi pi-minus" label="Collapse All" @click="collapseAll" />
|
||||
</div>
|
||||
<TreeTable :value="nodes" :expandedKeys="expandedKeys">
|
||||
<TreeTable :value="nodes" v-model:expandedKeys="expandedKeys">
|
||||
<Column field="name" header="Name" :expander="true"></Column>
|
||||
<Column field="size" header="Size"></Column>
|
||||
<Column field="type" header="Type"></Column>
|
||||
|
@ -1917,7 +1917,7 @@ export default {
|
|||
<Button type="button" icon="pi pi-plus" label="Expand All" @click="expandAll" />
|
||||
<Button type="button" icon="pi pi-minus" label="Collapse All" @click="collapseAll" />
|
||||
</div>
|
||||
<TreeTable :value="nodes" :expandedKeys="expandedKeys">
|
||||
<TreeTable :value="nodes" v-model:expandedKeys="expandedKeys">
|
||||
<Column field="name" header="Name" :expander="true"></Column>
|
||||
<Column field="size" header="Size"></Column>
|
||||
<Column field="type" header="Type"></Column>
|
||||
|
@ -2008,7 +2008,7 @@ button {
|
|||
<Button type="button" icon="pi pi-plus" label="Expand All" @click="expandAll" />
|
||||
<Button type="button" icon="pi pi-minus" label="Collapse All" @click="collapseAll" />
|
||||
</div>
|
||||
<TreeTable :value="nodes" :expandedKeys="expandedKeys">
|
||||
<TreeTable :value="nodes" v-model:expandedKeys="expandedKeys">
|
||||
<Column field="name" header="Name" :expander="true"></Column>
|
||||
<Column field="size" header="Size"></Column>
|
||||
<Column field="type" header="Type"></Column>
|
||||
|
@ -2093,7 +2093,7 @@ button {
|
|||
<p-button type="button" icon="pi pi-plus" label="Expand All" @click="expandAll"></p-button>
|
||||
<p-button type="button" icon="pi pi-minus" label="Collapse All" @click="collapseAll"></p-button>
|
||||
</div>
|
||||
<p-treetable :value="nodes" :expanded-keys="expandedKeys">
|
||||
<p-treetable :value="nodes" v-model:expanded-keys="expandedKeys">
|
||||
<p-column field="name" header="Name" :expander="true"></p-column>
|
||||
<p-column field="size" header="Size"></p-column>
|
||||
<p-column field="type" header="Type"></p-column>
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
<Button type="button" icon="pi pi-plus" label="Expand All" @click="expandAll" />
|
||||
<Button type="button" icon="pi pi-minus" label="Collapse All" @click="collapseAll" />
|
||||
</div>
|
||||
<TreeTable :value="nodes" :expandedKeys="expandedKeys">
|
||||
<TreeTable v-model:expandedKeys="expandedKeys" :value="nodes">
|
||||
<Column field="name" header="Name" :expander="true"></Column>
|
||||
<Column field="size" header="Size"></Column>
|
||||
<Column field="type" header="Type"></Column>
|
||||
|
|
Loading…
Reference in New Issue