Refactor #3965 - Refactor on OrderList

pull/4016/head
Bahadır Sofuoğlu 2023-06-02 12:10:49 +03:00
parent 155fb26785
commit 1950d500ea
3 changed files with 191 additions and 155 deletions

View File

@ -0,0 +1,146 @@
<script>
import BaseComponent from 'primevue/basecomponent';
import { useStyle } from 'primevue/usestyle';
const styles = `
.p-orderlist {
display: flex;
}
.p-orderlist-controls {
display: flex;
flex-direction: column;
justify-content: center;
}
.p-orderlist-list-container {
flex: 1 1 auto;
}
.p-orderlist-list {
list-style-type: none;
margin: 0;
padding: 0;
overflow: auto;
min-height: 12rem;
max-height: 24rem;
}
.p-orderlist-item {
cursor: pointer;
overflow: hidden;
position: relative;
}
.p-orderlist.p-state-disabled .p-orderlist-item,
.p-orderlist.p-state-disabled .p-button {
cursor: default;
}
.p-orderlist.p-state-disabled .p-orderlist-list {
overflow: hidden;
}
`;
const classes = {
root: ({ props }) => [
'p-orderlist p-component',
{
'p-orderlist-striped': props.stripedRows
}
],
controls: 'p-orderlist-controls',
header: 'p-orderlist-header',
container: 'p-orderlist-list-container',
list: 'p-orderlist-list',
item: ({ context }) => [
'p-orderlist-item',
{
'p-highlight': context.active,
'p-focus': context.focused
}
]
};
const { load: loadStyle } = useStyle(styles, { id: 'primevue_organizationchart_style', manual: true });
export default {
name: 'BaseOrganizationChart',
extends: BaseComponent,
props: {
modelValue: {
type: Array,
default: null
},
selection: {
type: Array,
default: null
},
dataKey: {
type: String,
default: null
},
listStyle: {
type: null,
default: null
},
metaKeySelection: {
type: Boolean,
default: true
},
responsive: {
type: Boolean,
default: true
},
breakpoint: {
type: String,
default: '960px'
},
stripedRows: {
type: Boolean,
default: false
},
tabindex: {
type: Number,
default: 0
},
listProps: {
type: null,
default: null
},
moveUpButtonProps: {
type: null,
default: null
},
moveTopButtonProps: {
type: null,
default: null
},
moveDownButtonProps: {
type: null,
default: null
},
moveBottomButtonProps: {
type: null,
default: null
},
'aria-labelledby': {
type: String,
default: null
},
'aria-label': {
type: String,
default: null
}
},
css: {
classes,
loadStyle
},
provide() {
return {
$parentInstance: this
};
}
};
</script>

View File

@ -211,6 +211,11 @@ export interface OrderListProps {
* @type {OrderListPassThroughOptions} * @type {OrderListPassThroughOptions}
*/ */
pt?: OrderListPassThroughOptions; pt?: OrderListPassThroughOptions;
/**
* When enabled, it removes component related styles in the core.
* @defaultValue false
*/
unstyled?: boolean;
} }
/** /**

View File

@ -1,29 +1,29 @@
<template> <template>
<div :class="containerClass" v-bind="ptm('root')"> <div :class="cx('root')" v-bind="ptm('root')">
<div class="p-orderlist-controls" v-bind="ptm('controls')"> <div :class="cx('controls')" v-bind="ptm('controls')">
<slot name="controlsstart"></slot> <slot name="controlsstart"></slot>
<OLButton type="button" @click="moveUp" :aria-label="moveUpAriaLabel" :disabled="moveDisabled()" v-bind="moveUpButtonProps" :pt="ptm('moveUpButton')"> <OLButton type="button" @click="moveUp" :aria-label="moveUpAriaLabel" :disabled="moveDisabled()" v-bind="moveUpButtonProps" :pt="ptm('moveUpButton')" :unstyle="unstyled">
<template #icon> <template #icon>
<slot name="moveupicon"> <slot name="moveupicon">
<AngleUpIcon v-bind="ptm('moveUpButton')['icon']" /> <AngleUpIcon v-bind="ptm('moveUpButton')['icon']" />
</slot> </slot>
</template> </template>
</OLButton> </OLButton>
<OLButton type="button" @click="moveTop" :aria-label="moveTopAriaLabel" :disabled="moveDisabled()" v-bind="moveTopButtonProps" :pt="ptm('moveTopButton')"> <OLButton type="button" @click="moveTop" :aria-label="moveTopAriaLabel" :disabled="moveDisabled()" v-bind="moveTopButtonProps" :pt="ptm('moveTopButton')" :unstyle="unstyled">
<template #icon> <template #icon>
<slot name="movetopicon"> <slot name="movetopicon">
<AngleDoubleUpIcon v-bind="ptm('moveTopButton')['icon']" /> <AngleDoubleUpIcon v-bind="ptm('moveTopButton')['icon']" />
</slot> </slot>
</template> </template>
</OLButton> </OLButton>
<OLButton type="button" @click="moveDown" :aria-label="moveDownAriaLabel" :disabled="moveDisabled()" v-bind="moveDownButtonProps" :pt="ptm('moveDownButton')"> <OLButton type="button" @click="moveDown" :aria-label="moveDownAriaLabel" :disabled="moveDisabled()" v-bind="moveDownButtonProps" :pt="ptm('moveDownButton')" :unstyle="unstyled">
<template #icon> <template #icon>
<slot name="movedownicon"> <slot name="movedownicon">
<AngleDownIcon v-bind="ptm('moveDownButton')['icon']" /> <AngleDownIcon v-bind="ptm('moveDownButton')['icon']" />
</slot> </slot>
</template> </template>
</OLButton> </OLButton>
<OLButton type="button" @click="moveBottom" :aria-label="moveBottomAriaLabel" :disabled="moveDisabled()" v-bind="moveBottomButtonProps" :pt="ptm('moveBottomButton')"> <OLButton type="button" @click="moveBottom" :aria-label="moveBottomAriaLabel" :disabled="moveDisabled()" v-bind="moveBottomButtonProps" :pt="ptm('moveBottomButton')" :unstyle="unstyled">
<template #icon> <template #icon>
<slot name="movebottomicon"> <slot name="movebottomicon">
<AngleDoubleDownIcon v-bind="ptm('moveBottomButton')['icon']" /> <AngleDoubleDownIcon v-bind="ptm('moveBottomButton')['icon']" />
@ -32,8 +32,8 @@
</OLButton> </OLButton>
<slot name="controlsend"></slot> <slot name="controlsend"></slot>
</div> </div>
<div class="p-orderlist-list-container" v-bind="ptm('container')"> <div :class="cx('container')" v-bind="ptm('container')">
<div v-if="$slots.header" class="p-orderlist-header" v-bind="ptm('header')"> <div v-if="$slots.header" :class="cx('header')" v-bind="ptm('header')">
<slot name="header"></slot> <slot name="header"></slot>
</div> </div>
<transition-group <transition-group
@ -41,7 +41,7 @@
:id="id + '_list'" :id="id + '_list'"
name="p-orderlist-flip" name="p-orderlist-flip"
tag="ul" tag="ul"
class="p-orderlist-list" :class="cx('list')"
:style="listStyle" :style="listStyle"
role="listbox" role="listbox"
aria-multiselectable="true" aria-multiselectable="true"
@ -59,7 +59,15 @@
:id="id + '_' + i" :id="id + '_' + i"
v-ripple v-ripple
role="option" role="option"
:class="itemClass(item, `${id}_${i}`)" :class="
cx('item', {
context: {
active: isSelected(item),
focused: `${id}_${i}` === focusedOptionId
}
})
"
:data-p-highlight="isSelected(item)"
@click="onItemClick($event, item, i)" @click="onItemClick($event, item, i)"
@touchend="onItemTouchEnd" @touchend="onItemTouchEnd"
:aria-selected="isSelected(item)" :aria-selected="isSelected(item)"
@ -75,7 +83,7 @@
</template> </template>
<script> <script>
import BaseComponent from 'primevue/basecomponent'; import BaseOrderList from './BaseOrderList.vue';
import Button from 'primevue/button'; import Button from 'primevue/button';
import AngleDoubleDownIcon from 'primevue/icons/angledoubledown'; import AngleDoubleDownIcon from 'primevue/icons/angledoubledown';
import AngleDoubleUpIcon from 'primevue/icons/angledoubleup'; import AngleDoubleUpIcon from 'primevue/icons/angledoubleup';
@ -86,74 +94,8 @@ import { DomHandler, ObjectUtils, UniqueComponentId } from 'primevue/utils';
export default { export default {
name: 'OrderList', name: 'OrderList',
extends: BaseComponent, extends: BaseOrderList,
emits: ['update:modelValue', 'reorder', 'update:selection', 'selection-change', 'focus', 'blur'], emits: ['update:modelValue', 'reorder', 'update:selection', 'selection-change', 'focus', 'blur'],
props: {
modelValue: {
type: Array,
default: null
},
selection: {
type: Array,
default: null
},
dataKey: {
type: String,
default: null
},
listStyle: {
type: null,
default: null
},
metaKeySelection: {
type: Boolean,
default: true
},
responsive: {
type: Boolean,
default: true
},
breakpoint: {
type: String,
default: '960px'
},
stripedRows: {
type: Boolean,
default: false
},
tabindex: {
type: Number,
default: 0
},
listProps: {
type: null,
default: null
},
moveUpButtonProps: {
type: null,
default: null
},
moveTopButtonProps: {
type: null,
default: null
},
moveDownButtonProps: {
type: null,
default: null
},
moveBottomButtonProps: {
type: null,
default: null
},
'aria-labelledby': {
type: String,
default: null
},
'aria-label': {
type: String,
default: null
}
},
itemTouched: false, itemTouched: false,
reorderDirection: null, reorderDirection: null,
styleElement: null, styleElement: null,
@ -203,7 +145,8 @@ export default {
return ObjectUtils.findIndexInList(item, this.d_selection) != -1; return ObjectUtils.findIndexInList(item, this.d_selection) != -1;
}, },
onListFocus(event) { onListFocus(event) {
const selectedFirstItem = DomHandler.findSingle(this.list, 'li.p-orderlist-item.p-highlight'); const selectedFirstItem = DomHandler.findSingle(this.list, '[data-p-highlight="true"]');
const findIndex = ObjectUtils.findIndexInList(selectedFirstItem, this.list.children); const findIndex = ObjectUtils.findIndexInList(selectedFirstItem, this.list.children);
this.focused = true; this.focused = true;
@ -282,8 +225,8 @@ export default {
}, },
onHomeKey(event) { onHomeKey(event) {
if (event.ctrlKey && event.shiftKey) { if (event.ctrlKey && event.shiftKey) {
const items = DomHandler.find(this.list, 'li.p-orderlist-item'); const items = DomHandler.find(this.list, '[data-pc-section="item"]');
const focusedItem = DomHandler.findSingle(this.list, `li.p-orderlist-item[id=${this.focusedOptionIndex}]`); const focusedItem = DomHandler.findSingle(this.list, `[data-pc-section="item"][id=${this.focusedOptionIndex}]`);
const matchedOptionIndex = [...items].findIndex((item) => item === focusedItem); const matchedOptionIndex = [...items].findIndex((item) => item === focusedItem);
this.d_selection = [...this.modelValue].slice(0, matchedOptionIndex + 1); this.d_selection = [...this.modelValue].slice(0, matchedOptionIndex + 1);
@ -296,21 +239,21 @@ export default {
}, },
onEndKey(event) { onEndKey(event) {
if (event.ctrlKey && event.shiftKey) { if (event.ctrlKey && event.shiftKey) {
const items = DomHandler.find(this.list, 'li.p-orderlist-item'); const items = DomHandler.find(this.list, '[data-pc-section="item"]');
const focusedItem = DomHandler.findSingle(this.list, `li.p-orderlist-item[id=${this.focusedOptionIndex}]`); const focusedItem = DomHandler.findSingle(this.list, `[data-pc-section="item"][id=${this.focusedOptionIndex}]`);
const matchedOptionIndex = [...items].findIndex((item) => item === focusedItem); const matchedOptionIndex = [...items].findIndex((item) => item === focusedItem);
this.d_selection = [...this.modelValue].slice(matchedOptionIndex, items.length); this.d_selection = [...this.modelValue].slice(matchedOptionIndex, items.length);
this.$emit('update:selection', this.d_selection); this.$emit('update:selection', this.d_selection);
} else { } else {
this.changeFocusedOptionIndex(DomHandler.find(this.list, 'li.p-orderlist-item').length - 1); this.changeFocusedOptionIndex(DomHandler.find(this.list, '[data-pc-section="item"]').length - 1);
} }
event.preventDefault(); event.preventDefault();
}, },
onEnterKey(event) { onEnterKey(event) {
const items = DomHandler.find(this.list, 'li.p-orderlist-item'); const items = DomHandler.find(this.list, '[data-pc-section="item"]');
const focusedItem = DomHandler.findSingle(this.list, `li.p-orderlist-item[id=${this.focusedOptionIndex}]`); const focusedItem = DomHandler.findSingle(this.list, `[data-pc-section="item"][id=${this.focusedOptionIndex}]`);
const matchedOptionIndex = [...items].findIndex((item) => item === focusedItem); const matchedOptionIndex = [...items].findIndex((item) => item === focusedItem);
this.onItemClick(event, this.modelValue[matchedOptionIndex], matchedOptionIndex); this.onItemClick(event, this.modelValue[matchedOptionIndex], matchedOptionIndex);
@ -319,9 +262,9 @@ export default {
}, },
onSpaceKey(event) { onSpaceKey(event) {
if (event.shiftKey) { if (event.shiftKey) {
const items = DomHandler.find(this.list, 'li.p-orderlist-item'); const items = DomHandler.find(this.list, '[data-pc-section="item"]');
const selectedItemIndex = ObjectUtils.findIndexInList(this.d_selection[0], [...this.modelValue]); const selectedItemIndex = ObjectUtils.findIndexInList(this.d_selection[0], [...this.modelValue]);
const focusedItem = DomHandler.findSingle(this.list, `li.p-orderlist-item[id=${this.focusedOptionIndex}]`); const focusedItem = DomHandler.findSingle(this.list, `[data-pc-section="item"][id=${this.focusedOptionIndex}]`);
const matchedOptionIndex = [...items].findIndex((item) => item === focusedItem); const matchedOptionIndex = [...items].findIndex((item) => item === focusedItem);
this.d_selection = [...this.modelValue].slice(Math.min(selectedItemIndex, matchedOptionIndex), Math.max(selectedItemIndex, matchedOptionIndex) + 1); this.d_selection = [...this.modelValue].slice(Math.min(selectedItemIndex, matchedOptionIndex), Math.max(selectedItemIndex, matchedOptionIndex) + 1);
@ -331,19 +274,19 @@ export default {
} }
}, },
findNextOptionIndex(index) { findNextOptionIndex(index) {
const items = DomHandler.find(this.list, 'li.p-orderlist-item'); const items = DomHandler.find(this.list, '[data-pc-section="item"]');
const matchedOptionIndex = [...items].findIndex((link) => link.id === index); const matchedOptionIndex = [...items].findIndex((link) => link.id === index);
return matchedOptionIndex > -1 ? matchedOptionIndex + 1 : 0; return matchedOptionIndex > -1 ? matchedOptionIndex + 1 : 0;
}, },
findPrevOptionIndex(index) { findPrevOptionIndex(index) {
const items = DomHandler.find(this.list, 'li.p-orderlist-item'); const items = DomHandler.find(this.list, '[data-pc-section="item"]');
const matchedOptionIndex = [...items].findIndex((link) => link.id === index); const matchedOptionIndex = [...items].findIndex((link) => link.id === index);
return matchedOptionIndex > -1 ? matchedOptionIndex - 1 : 0; return matchedOptionIndex > -1 ? matchedOptionIndex - 1 : 0;
}, },
changeFocusedOptionIndex(index) { changeFocusedOptionIndex(index) {
const items = DomHandler.find(this.list, 'li.p-orderlist-item'); const items = DomHandler.find(this.list, '[data-pc-section="item"]');
let order = index >= items.length ? items.length - 1 : index < 0 ? 0 : index; let order = index >= items.length ? items.length - 1 : index < 0 ? 0 : index;
@ -351,7 +294,7 @@ export default {
this.scrollInView(this.focusedOptionIndex); this.scrollInView(this.focusedOptionIndex);
}, },
scrollInView(id) { scrollInView(id) {
const element = DomHandler.findSingle(this.list, `li[id="${id}"]`); const element = DomHandler.findSingle(this.list, `[data-pc-section="item"][id="${id}"]`);
if (element) { if (element) {
element.scrollIntoView && element.scrollIntoView({ block: 'nearest', inline: 'start' }); element.scrollIntoView && element.scrollIntoView({ block: 'nearest', inline: 'start' });
@ -470,7 +413,8 @@ export default {
const selectedIndex = ObjectUtils.findIndexInList(item, this.d_selection); const selectedIndex = ObjectUtils.findIndexInList(item, this.d_selection);
const selected = selectedIndex != -1; const selected = selectedIndex != -1;
const metaSelection = this.itemTouched ? false : this.metaKeySelection; const metaSelection = this.itemTouched ? false : this.metaKeySelection;
const selectedId = DomHandler.find(this.list, '.p-orderlist-item')[index].getAttribute('id');
const selectedId = DomHandler.find(this.list, '[data-pc-section="item"]')[index].getAttribute('id');
this.focusedOptionIndex = selectedId; this.focusedOptionIndex = selectedId;
@ -504,28 +448,17 @@ export default {
findNextItem(item) { findNextItem(item) {
let nextItem = item.nextElementSibling; let nextItem = item.nextElementSibling;
if (nextItem) return !DomHandler.hasClass(nextItem, 'p-orderlist-item') ? this.findNextItem(nextItem) : nextItem; if (nextItem) return !(DomHandler.getAttribute(nextItem, 'data-p-section') === 'item') ? this.findNextItem(nextItem) : nextItem;
else return null; else return null;
}, },
findPrevItem(item) { findPrevItem(item) {
let prevItem = item.previousElementSibling; let prevItem = item.previousElementSibling;
if (prevItem) return !DomHandler.hasClass(prevItem, 'p-orderlist-item') ? this.findPrevItem(prevItem) : prevItem; if (prevItem) return !(DomHandler.getAttribute(nextItem, 'data-p-section') === 'item') ? this.findPrevItem(prevItem) : prevItem;
else return null; else return null;
}, },
findFirstItem() {
return DomHandler.findSingle(this.list, '.p-orderlist-item');
},
findLastItem() {
const items = DomHandler.find(this.list, '.p-orderlist-item');
return items[items.length - 1];
},
itemClass(item, id) {
return ['p-orderlist-item', { 'p-highlight': this.isSelected(item), 'p-focus': id === this.focusedOptionId }];
},
updateListScroll() { updateListScroll() {
const listItems = DomHandler.find(this.list, '.p-orderlist-item.p-highlight'); const listItems = DomHandler.find(this.list, '[data-pc-section="item"][data-p-highlight="true"]');
if (listItems && listItems.length) { if (listItems && listItems.length) {
switch (this.reorderDirection) { switch (this.reorderDirection) {
@ -598,14 +531,6 @@ export default {
} }
}, },
computed: { computed: {
containerClass() {
return [
'p-orderlist p-component',
{
'p-orderlist-striped': this.stripedRows
}
];
},
attributeSelector() { attributeSelector() {
return UniqueComponentId(); return UniqueComponentId();
}, },
@ -637,43 +562,3 @@ export default {
} }
}; };
</script> </script>
<style>
.p-orderlist {
display: flex;
}
.p-orderlist-controls {
display: flex;
flex-direction: column;
justify-content: center;
}
.p-orderlist-list-container {
flex: 1 1 auto;
}
.p-orderlist-list {
list-style-type: none;
margin: 0;
padding: 0;
overflow: auto;
min-height: 12rem;
max-height: 24rem;
}
.p-orderlist-item {
cursor: pointer;
overflow: hidden;
position: relative;
}
.p-orderlist.p-state-disabled .p-orderlist-item,
.p-orderlist.p-state-disabled .p-button {
cursor: default;
}
.p-orderlist.p-state-disabled .p-orderlist-list {
overflow: hidden;
}
</style>