Update #3965 - For Dock
parent
931edf0158
commit
a8fd3ce6a8
|
@ -0,0 +1,185 @@
|
|||
<script>
|
||||
import BaseComponent from 'primevue/basecomponent';
|
||||
import { useStyle } from 'primevue/usestyle';
|
||||
|
||||
const styles = `
|
||||
.p-dock {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.p-dock-list-container {
|
||||
display: flex;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.p-dock-list {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.p-dock-item {
|
||||
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.p-dock-link {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.p-dock-item-second-prev,
|
||||
.p-dock-item-second-next {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
.p-dock-item-prev,
|
||||
.p-dock-item-next {
|
||||
transform: scale(1.4);
|
||||
}
|
||||
|
||||
.p-dock-item-current {
|
||||
transform: scale(1.6);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Position */
|
||||
/* top */
|
||||
.p-dock-top {
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.p-dock-top .p-dock-item {
|
||||
transform-origin: center top;
|
||||
}
|
||||
|
||||
/* bottom */
|
||||
.p-dock-bottom {
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.p-dock-bottom .p-dock-item {
|
||||
transform-origin: center bottom;
|
||||
}
|
||||
|
||||
/* right */
|
||||
.p-dock-right {
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.p-dock-right .p-dock-item {
|
||||
transform-origin: center right;
|
||||
}
|
||||
|
||||
.p-dock-right .p-dock-list {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* left */
|
||||
.p-dock-left {
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.p-dock-left .p-dock-item {
|
||||
transform-origin: center left;
|
||||
}
|
||||
|
||||
.p-dock-left .p-dock-list {
|
||||
flex-direction: column;
|
||||
}
|
||||
`;
|
||||
|
||||
const classes = {
|
||||
root: ({ props }) => ['p-dock p-component', `p-dock-${props.position}`, props.class],
|
||||
container: 'p-dock-list-container',
|
||||
menu: 'p-dock-list',
|
||||
menuitem: ({ instance, processedItem, index, id }) => [
|
||||
'p-dock-item',
|
||||
{
|
||||
'p-focus': instance.isItemActive(id),
|
||||
'p-disabled': instance.disabled(processedItem),
|
||||
'p-dock-item-second-prev': instance.currentIndex - 2 === index,
|
||||
'p-dock-item-prev': instance.currentIndex - 1 === index,
|
||||
'p-dock-item-current': instance.currentIndex === index,
|
||||
'p-dock-item-next': instance.currentIndex + 1 === index,
|
||||
'p-dock-item-second-next': instance.currentIndex + 2 === index
|
||||
}
|
||||
],
|
||||
content: 'p-menuitem-content',
|
||||
action: ({ props, isActive, isExactActive }) => [
|
||||
'p-dock-link',
|
||||
{
|
||||
'router-link-active': isActive,
|
||||
'router-link-active-exact': props.exact && isExactActive
|
||||
}
|
||||
],
|
||||
icon: 'p-dock-icon'
|
||||
};
|
||||
|
||||
const { load: loadStyle } = useStyle(styles, { id: 'primevue_dock_style', manual: true });
|
||||
|
||||
export default {
|
||||
name: 'BaseDock',
|
||||
extends: BaseComponent,
|
||||
props: {
|
||||
position: {
|
||||
type: String,
|
||||
default: 'bottom'
|
||||
},
|
||||
model: null,
|
||||
class: null,
|
||||
style: null,
|
||||
tooltipOptions: null,
|
||||
exact: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
menuId: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
tabindex: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
'aria-label': {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
'aria-labelledby': {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
css: {
|
||||
classes,
|
||||
loadStyle
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
$parentInstance: this
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -171,6 +171,11 @@ export interface DockProps {
|
|||
* @type {DockPassThroughOptions}
|
||||
*/
|
||||
pt?: DockPassThroughOptions;
|
||||
/**
|
||||
* When enabled, it removes component related styles in the core.
|
||||
* @defaultValue false
|
||||
*/
|
||||
unstyled?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,161 +1,18 @@
|
|||
<template>
|
||||
<div :class="containerClass" :style="style" v-bind="ptm('root')">
|
||||
<div :class="cx('root')" :style="style" v-bind="ptm('root')">
|
||||
<DockSub :model="model" :templates="$slots" :exact="exact" :tooltipOptions="tooltipOptions" :position="position" :menuId="menuId" :aria-label="ariaLabel" :aria-labelledby="ariaLabelledby" :tabindex="tabindex" :pt="pt"></DockSub>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseComponent from 'primevue/basecomponent';
|
||||
import BaseDock from './BaseDock.vue';
|
||||
import DockSub from './DockSub.vue';
|
||||
|
||||
export default {
|
||||
name: 'Dock',
|
||||
extends: BaseComponent,
|
||||
props: {
|
||||
position: {
|
||||
type: String,
|
||||
default: 'bottom'
|
||||
},
|
||||
model: null,
|
||||
class: null,
|
||||
style: null,
|
||||
tooltipOptions: null,
|
||||
exact: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
menuId: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
tabindex: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
'aria-label': {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
'aria-labelledby': {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
return ['p-dock p-component', `p-dock-${this.position}`, this.class];
|
||||
}
|
||||
},
|
||||
extends: BaseDock,
|
||||
components: {
|
||||
DockSub
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.p-dock {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.p-dock-list-container {
|
||||
display: flex;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.p-dock-list {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.p-dock-item {
|
||||
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.p-dock-link {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.p-dock-item-second-prev,
|
||||
.p-dock-item-second-next {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
.p-dock-item-prev,
|
||||
.p-dock-item-next {
|
||||
transform: scale(1.4);
|
||||
}
|
||||
|
||||
.p-dock-item-current {
|
||||
transform: scale(1.6);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Position */
|
||||
/* top */
|
||||
.p-dock-top {
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.p-dock-top .p-dock-item {
|
||||
transform-origin: center top;
|
||||
}
|
||||
|
||||
/* bottom */
|
||||
.p-dock-bottom {
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.p-dock-bottom .p-dock-item {
|
||||
transform-origin: center bottom;
|
||||
}
|
||||
|
||||
/* right */
|
||||
.p-dock-right {
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.p-dock-right .p-dock-item {
|
||||
transform-origin: center right;
|
||||
}
|
||||
|
||||
.p-dock-right .p-dock-list {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* left */
|
||||
.p-dock-left {
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.p-dock-left .p-dock-item {
|
||||
transform-origin: center left;
|
||||
}
|
||||
|
||||
.p-dock-left .p-dock-list {
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<div class="p-dock-list-container" v-bind="ptm('container')">
|
||||
<div :class="cx('container')" v-bind="ptm('container')">
|
||||
<ul
|
||||
ref="list"
|
||||
:id="id"
|
||||
class="p-dock-list"
|
||||
:class="cx('menu')"
|
||||
role="menu"
|
||||
:aria-orientation="position === 'bottom' || position === 'top' ? 'horizontal' : 'vertical'"
|
||||
:aria-activedescendant="focused ? focusedOptionId : undefined"
|
||||
|
@ -19,21 +19,23 @@
|
|||
<template v-for="(processedItem, index) of model" :key="index">
|
||||
<li
|
||||
:id="getItemId(index)"
|
||||
:class="itemClass(processedItem, index, getItemId(index))"
|
||||
:class="cx('menuitem', { processedItem, index, id: getItemId(index) })"
|
||||
role="menuitem"
|
||||
:aria-label="processedItem.label"
|
||||
:aria-disabled="disabled(processedItem)"
|
||||
@click="onItemClick($event, processedItem)"
|
||||
@mouseenter="onItemMouseEnter(index)"
|
||||
v-bind="getPTOptions(getItemId(index), 'menuitem')"
|
||||
:data-p-focused="isItemActive(getItemId(index))"
|
||||
:data-p-disabled="disabled(processedItem) || false"
|
||||
>
|
||||
<div class="p-menuitem-content" v-bind="getPTOptions(getItemId(index), 'content')">
|
||||
<div :class="cx('content')" v-bind="getPTOptions(getItemId(index), 'content')">
|
||||
<template v-if="!templates['item']">
|
||||
<router-link v-if="processedItem.to && !disabled(processedItem)" v-slot="{ navigate, href, isActive, isExactActive }" :to="processedItem.to" custom>
|
||||
<a
|
||||
v-tooltip:[tooltipOptions]="{ value: processedItem.label, disabled: !tooltipOptions }"
|
||||
:href="href"
|
||||
:class="linkClass({ isActive, isExactActive })"
|
||||
:class="cx('action', { isActive, isExactActive })"
|
||||
:target="processedItem.target"
|
||||
tabindex="-1"
|
||||
aria-hidden="true"
|
||||
|
@ -41,25 +43,25 @@
|
|||
v-bind="getPTOptions(getItemId(index), 'action')"
|
||||
>
|
||||
<template v-if="!templates['icon']">
|
||||
<span v-ripple :class="['p-dock-icon', processedItem.icon]" v-bind="getPTOptions(getItemId(index), 'icon')"></span>
|
||||
<span v-ripple :class="[cx('icon'), processedItem.icon]" v-bind="getPTOptions(getItemId(index), 'icon')"></span>
|
||||
</template>
|
||||
<component v-else :is="templates['icon']" :item="processedItem"></component>
|
||||
<component v-else :is="templates['icon']" :item="processedItem" :class="cx('icon')"></component>
|
||||
</a>
|
||||
</router-link>
|
||||
<a
|
||||
v-else
|
||||
v-tooltip:[tooltipOptions]="{ value: processedItem.label, disabled: !tooltipOptions }"
|
||||
:href="processedItem.url"
|
||||
:class="linkClass()"
|
||||
:class="cx('action')"
|
||||
:target="processedItem.target"
|
||||
tabindex="-1"
|
||||
aria-hidden="true"
|
||||
v-bind="getPTOptions(getItemId(index), 'action')"
|
||||
>
|
||||
<template v-if="!templates['icon']">
|
||||
<span v-ripple :class="['p-dock-icon', processedItem.icon]" v-bind="getPTOptions(getItemId(index), 'icon')"></span>
|
||||
<span v-ripple :class="[cx('icon'), processedItem.icon]" v-bind="getPTOptions(getItemId(index), 'icon')"></span>
|
||||
</template>
|
||||
<component v-else :is="templates['icon']" :item="processedItem"></component>
|
||||
<component v-else :is="templates['icon']" :item="processedItem" :class="cx('icon')"></component>
|
||||
</a>
|
||||
</template>
|
||||
<component v-else :is="templates['item']" :item="processedItem" :index="index"></component>
|
||||
|
@ -146,7 +148,7 @@ export default {
|
|||
});
|
||||
},
|
||||
isSameMenuItem(event) {
|
||||
return event.currentTarget && (event.currentTarget.isSameNode(event.target) || event.currentTarget.isSameNode(event.target.closest('.p-menuitem')));
|
||||
return event.currentTarget && (event.currentTarget.isSameNode(event.target) || event.currentTarget.isSameNode(event.target.closest('[data-pc-section="menuitem"]')));
|
||||
},
|
||||
isItemActive(id) {
|
||||
return id === this.focusedOptionIndex;
|
||||
|
@ -241,56 +243,33 @@ export default {
|
|||
this.changeFocusedOptionIndex(0);
|
||||
},
|
||||
onEndKey() {
|
||||
this.changeFocusedOptionIndex(DomHandler.find(this.$refs.list, 'li.p-dock-item:not(.p-disabled)').length - 1);
|
||||
this.changeFocusedOptionIndex(DomHandler.find(this.$refs.list, 'li[data-pc-section="menuitem"][data-p-disabled="false"]').length - 1);
|
||||
},
|
||||
onSpaceKey() {
|
||||
const element = DomHandler.findSingle(this.$refs.list, `li[id="${`${this.focusedOptionIndex}`}"]`);
|
||||
const anchorElement = element && DomHandler.findSingle(element, '.p-dock-link');
|
||||
const anchorElement = element && DomHandler.findSingle(element, '[data-pc-section="action"]');
|
||||
|
||||
anchorElement ? anchorElement.click() : element && element.click();
|
||||
},
|
||||
findNextOptionIndex(index) {
|
||||
const menuitems = DomHandler.find(this.$refs.list, 'li.p-dock-item:not(.p-disabled)');
|
||||
const menuitems = DomHandler.find(this.$refs.list, 'li[data-pc-section="menuitem"][data-p-disabled="false"]');
|
||||
const matchedOptionIndex = [...menuitems].findIndex((link) => link.id === index);
|
||||
|
||||
return matchedOptionIndex > -1 ? matchedOptionIndex + 1 : 0;
|
||||
},
|
||||
findPrevOptionIndex(index) {
|
||||
const menuitems = DomHandler.find(this.$refs.list, 'li.p-dock-item:not(.p-disabled)');
|
||||
const menuitems = DomHandler.find(this.$refs.list, 'li[data-pc-section="menuitem"][data-p-disabled="false"]');
|
||||
const matchedOptionIndex = [...menuitems].findIndex((link) => link.id === index);
|
||||
|
||||
return matchedOptionIndex > -1 ? matchedOptionIndex - 1 : 0;
|
||||
},
|
||||
changeFocusedOptionIndex(index) {
|
||||
const menuitems = DomHandler.find(this.$refs.list, 'li.p-dock-item:not(.p-disabled)');
|
||||
const menuitems = DomHandler.find(this.$refs.list, 'li[data-pc-section="menuitem"][data-p-disabled="false"]');
|
||||
|
||||
let order = index >= menuitems.length ? menuitems.length - 1 : index < 0 ? 0 : index;
|
||||
|
||||
this.focusedOptionIndex = menuitems[order].getAttribute('id');
|
||||
},
|
||||
itemClass(item, index, id) {
|
||||
return [
|
||||
'p-dock-item',
|
||||
{
|
||||
'p-focus': this.isItemActive(id),
|
||||
'p-disabled': this.disabled(item),
|
||||
'p-dock-item-second-prev': this.currentIndex - 2 === index,
|
||||
'p-dock-item-prev': this.currentIndex - 1 === index,
|
||||
'p-dock-item-current': this.currentIndex === index,
|
||||
'p-dock-item-next': this.currentIndex + 1 === index,
|
||||
'p-dock-item-second-next': this.currentIndex + 2 === index
|
||||
}
|
||||
];
|
||||
},
|
||||
linkClass(routerProps) {
|
||||
return [
|
||||
'p-dock-link',
|
||||
{
|
||||
'router-link-active': routerProps && routerProps.isActive,
|
||||
'router-link-active-exact': this.exact && routerProps && routerProps.isExactActive
|
||||
}
|
||||
];
|
||||
},
|
||||
disabled(item) {
|
||||
return typeof item.disabled === 'function' ? item.disabled() : item.disabled;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue