Refactor #3924 - For Tree

pull/3938/head
Tuğçe Küçükoğlu 2023-05-07 22:21:37 +03:00
parent 6a4226a4e0
commit e10c1cf988
5 changed files with 158 additions and 19 deletions

View File

@ -77,6 +77,12 @@ const TreeProps = [
type: 'string',
default: 'null',
description: 'Height of the scroll viewport in fixed units or the "flex" keyword for a dynamic size.'
},
{
name: 'pt',
type: 'any',
default: 'null',
description: 'Uses to pass attributes to DOM elements inside the component.'
}
];

View File

@ -63,6 +63,7 @@ import { TextareaPassThroughOptions } from '../textarea';
import { TieredMenuPassThroughOptions } from '../tieredmenu';
import { ToastPassThroughOptions } from '../toast';
import { ToolbarPassThroughOptions } from '../toolbar';
import { TreePassThroughOptions } from '../tree';
import { VirtualScrollerPassThroughOptions } from '../virtualscroller';
interface PrimeVueConfiguration {
@ -148,6 +149,7 @@ interface PrimeVuePTOptions {
tieredmenu?: TieredMenuPassThroughOptions;
toast?: ToastPassThroughOptions;
toolbar?: ToolbarPassThroughOptions;
tree?: TreePassThroughOptions;
virtualscroller?: VirtualScrollerPassThroughOptions;
}

View File

@ -10,6 +10,16 @@
import { VNode } from 'vue';
import { ClassComponent, GlobalComponentConstructor } from '../ts-helpers';
export declare type TreePassThroughOptionType = TreePassThroughAttributes | ((options: TreePassThroughMethodOptions) => TreePassThroughAttributes) | null | undefined;
/**
* Custom passthrough(pt) option method.
*/
export interface TreePassThroughMethodOptions {
props: TreeProps;
state: TreeState;
}
/**
* Custom TreeNode metadata.
*/
@ -90,6 +100,106 @@ export interface TreeSelectionKeys {
[key: string]: any;
}
/**
* Custom passthrough(pt) options.
* @see {@link TreeProps.pt}
*/
export interface TreePassThroughOptions {
/**
* Uses to pass attributes to the root's DOM element.
*/
root?: TreePassThroughOptionType;
/**
* Uses to pass attributes to the loading overlay's DOM element.
*/
loadingOverlay?: TreePassThroughOptionType;
/**
* Uses to pass attributes to the loading icon's DOM element.
*/
loadingIcon?: TreePassThroughOptionType;
/**
* Uses to pass attributes to the filter container's DOM element.
*/
filterContainer?: TreePassThroughOptionType;
/**
* Uses to pass attributes to the input's DOM element.
*/
input?: TreePassThroughOptionType;
/**
* Uses to pass attributes to the search icon's DOM element.
*/
searchIcon?: TreePassThroughOptionType;
/**
* Uses to pass attributes to the wrapper's DOM element.
*/
wrapper?: TreePassThroughOptionType;
/**
* Uses to pass attributes to the container's DOM element.
*/
container?: TreePassThroughOptionType;
/**
* Uses to pass attributes to the node's DOM element.
*/
node?: TreePassThroughOptionType;
/**
* Uses to pass attributes to the content's DOM element.
*/
content?: TreePassThroughOptionType;
/**
* Uses to pass attributes to the toggler's DOM element.
*/
toggler?: TreePassThroughOptionType;
/**
* Uses to pass attributes to the toggler icon's DOM element.
*/
togglerIcon?: TreePassThroughOptionType;
/**
* Uses to pass attributes to the checkbox container's DOM element.
*/
checkboxContainer?: TreePassThroughOptionType;
/**
* Uses to pass attributes to the checkbox's DOM element.
*/
checkbox?: TreePassThroughOptionType;
/**
* Uses to pass attributes to the checkbox icon's DOM element.
*/
checkboxIcon?: TreePassThroughOptionType;
/**
* Uses to pass attributes to the node icon's DOM element.
*/
nodeIcon?: TreePassThroughOptionType;
/**
* Uses to pass attributes to the label's DOM element.
*/
label?: TreePassThroughOptionType;
/**
* Uses to pass attributes to the subgroup's DOM element.
*/
subgroup?: TreePassThroughOptionType;
}
/**
* Custom passthrough attributes for each DOM elements
*/
export interface TreePassThroughAttributes {
[key: string]: any;
}
/**
* Defines current inline state in Tree component.
*/
export interface TreeState {
/**
* Current expanded keys state.
*/
d_expandedKeys: TreeExpandedKeys;
/**
* Current filter value state as a string.
*/
filterValue: string;
}
/**
* Defines valid properties in Tree component.
*/
@ -161,6 +271,11 @@ export interface TreeProps {
* Identifier of the underlying menu element.
*/
'aria-labelledby'?: string | undefined;
/**
* Uses to pass attributes to DOM elements inside the component.
* @type {TreePassThroughOptions}
*/
pt?: TreePassThroughOptions;
}
/**

View File

@ -1,21 +1,21 @@
<template>
<div :class="containerClass">
<div :class="containerClass" v-bind="ptm('root')">
<template v-if="loading">
<div class="p-tree-loading-overlay p-component-overlay">
<div class="p-tree-loading-overlay p-component-overlay" v-bind="ptm('loadingOverlay')">
<slot name="loadingicon">
<i v-if="loadingIcon" :class="['p-tree-loading-icon pi-spin', loadingIcon]" />
<SpinnerIcon v-else spin class="p-tree-loading-icon" />
<i v-if="loadingIcon" :class="['p-tree-loading-icon pi-spin', loadingIcon]" v-bind="ptm('loadingIcon')" />
<SpinnerIcon v-else spin class="p-tree-loading-icon" v-bind="ptm('loadingIcon')" />
</slot>
</div>
</template>
<div v-if="filter" class="p-tree-filter-container">
<input v-model="filterValue" type="text" autocomplete="off" class="p-tree-filter p-inputtext p-component" :placeholder="filterPlaceholder" @keydown="onFilterKeydown" />
<div v-if="filter" class="p-tree-filter-container" v-bind="ptm('filterContainer')">
<input v-model="filterValue" type="text" autocomplete="off" class="p-tree-filter p-inputtext p-component" :placeholder="filterPlaceholder" @keydown="onFilterKeydown" v-bind="ptm('input')" />
<slot name="searchicon">
<SearchIcon class="p-tree-filter-icon" />
<SearchIcon class="p-tree-filter-icon" v-bind="ptm('searchIcon')" />
</slot>
</div>
<div class="p-tree-wrapper" :style="{ maxHeight: scrollHeight }">
<ul class="p-tree-container" role="tree" :aria-labelledby="ariaLabelledby" :aria-label="ariaLabel">
<div class="p-tree-wrapper" :style="{ maxHeight: scrollHeight }" v-bind="ptm('wrapper')">
<ul class="p-tree-container" role="tree" :aria-labelledby="ariaLabelledby" :aria-label="ariaLabel" v-bind="ptm('container')">
<TreeNode
v-for="(node, index) of valueToRender"
:key="node.key"
@ -29,6 +29,7 @@
:selectionMode="selectionMode"
:selectionKeys="selectionKeys"
@checkbox-change="onCheckboxChange"
:pt="pt"
></TreeNode>
</ul>
</div>
@ -36,6 +37,7 @@
</template>
<script>
import BaseComponent from 'primevue/basecomponent';
import SearchIcon from 'primevue/icons/search';
import SpinnerIcon from 'primevue/icons/spinner';
import { ObjectUtils } from 'primevue/utils';
@ -43,6 +45,7 @@ import TreeNode from './TreeNode.vue';
export default {
name: 'Tree',
extends: BaseComponent,
emits: ['node-expand', 'node-collapse', 'update:expandedKeys', 'update:selectionKeys', 'node-select', 'node-unselect'],
props: {
value: {

View File

@ -12,26 +12,27 @@
:aria-checked="ariaChecked"
:tabindex="index === 0 ? 0 : -1"
@keydown="onKeyDown"
v-bind="getPTOptions('node')"
>
<div :class="contentClass" @click="onClick" @touchend="onTouchEnd" :style="node.style">
<button v-ripple type="button" class="p-tree-toggler p-link" @click="toggle" tabindex="-1" aria-hidden="true">
<div :class="contentClass" @click="onClick" @touchend="onTouchEnd" :style="node.style" v-bind="getPTOptions('content')">
<button v-ripple type="button" class="p-tree-toggler p-link" @click="toggle" tabindex="-1" aria-hidden="true" v-bind="getPTOptions('toggler')">
<component v-if="templates['togglericon']" :is="templates['togglericon']" :node="node" :expanded="expanded" class="p-tree-toggler-icon" />
<component v-else-if="expanded" :is="node.expandedIcon ? 'span' : 'ChevronDownIcon'" class="p-tree-toggler-icon" />
<component v-else :is="node.collapsedIcon ? 'span' : 'ChevronRightIcon'" class="p-tree-toggler-icon" />
<component v-else-if="expanded" :is="node.expandedIcon ? 'span' : 'ChevronDownIcon'" class="p-tree-toggler-icon" v-bind="getPTOptions('togglerIcon')" />
<component v-else :is="node.collapsedIcon ? 'span' : 'ChevronRightIcon'" class="p-tree-toggler-icon" v-bind="getPTOptions('togglerIcon')" />
</button>
<div v-if="checkboxMode" class="p-checkbox p-component" aria-hidden="true">
<div :class="checkboxClass" role="checkbox">
<div v-if="checkboxMode" class="p-checkbox p-component" aria-hidden="true" v-bind="getPTOptions('checkboxContainer')">
<div :class="checkboxClass" role="checkbox" v-bind="getPTOptions('checkbox')">
<component v-if="templates['checkboxicon']" :is="templates['checkboxicon']" :checked="checked" :partialChecked="partialChecked" class="p-checkbox-icon" />
<component v-else :is="checked ? 'CheckIcon' : partialChecked ? 'MinusIcon' : null" class="p-checkbox-icon" />
<component v-else :is="checked ? 'CheckIcon' : partialChecked ? 'MinusIcon' : null" class="p-checkbox-icon" v-bind="getPTOptions('checkboxIcon')" />
</div>
</div>
<span :class="icon"></span>
<span class="p-treenode-label">
<span :class="icon" v-bind="getPTOptions('nodeIcon')"></span>
<span class="p-treenode-label" v-bind="getPTOptions('label')">
<component v-if="templates[node.type] || templates['default']" :is="templates[node.type] || templates['default']" :node="node" />
<template v-else>{{ label(node) }}</template>
</span>
</div>
<ul v-if="hasChildren && expanded" class="p-treenode-children" role="group">
<ul v-if="hasChildren && expanded" class="p-treenode-children" role="group" v-bind="ptm('subgroup')">
<TreeNode
v-for="childNode of node.children"
:key="childNode.key"
@ -44,12 +45,14 @@
:selectionMode="selectionMode"
:selectionKeys="selectionKeys"
@checkbox-change="propagateUp"
:pt="pt"
/>
</ul>
</li>
</template>
<script>
import BaseComponent from 'primevue/basecomponent';
import CheckIcon from 'primevue/icons/check';
import ChevronDownIcon from 'primevue/icons/chevrondown';
import ChevronRightIcon from 'primevue/icons/chevronright';
@ -59,6 +62,7 @@ import { DomHandler } from 'primevue/utils';
export default {
name: 'TreeNode',
extends: BaseComponent,
emits: ['node-toggle', 'node-click', 'checkbox-change'],
props: {
node: {
@ -110,6 +114,15 @@ export default {
onChildNodeToggle(node) {
this.$emit('node-toggle', node);
},
getPTOptions(key) {
return this.ptm(key, {
context: {
expanded: this.expanded,
selected: this.selected,
checked: this.checked
}
});
},
onClick(event) {
if (this.toggleClicked || DomHandler.hasClass(event.target, 'p-tree-toggler') || DomHandler.hasClass(event.target.parentElement, 'p-tree-toggler')) {
this.toggleClicked = false;