mirror of
https://github.com/primefaces/primevue.git
synced 2025-05-09 00:42:36 +00:00
Fixed #3802 - Improve folder structure for nuxt configurations
This commit is contained in:
parent
851950270b
commit
f5fe822afb
563 changed files with 1703 additions and 1095 deletions
164
components/lib/organizationchart/OrganizationChart.d.ts
vendored
Executable file
164
components/lib/organizationchart/OrganizationChart.d.ts
vendored
Executable file
|
@ -0,0 +1,164 @@
|
|||
/**
|
||||
*
|
||||
* OrganizationChart visualizes hierarchical organization data.
|
||||
*
|
||||
* [Live Demo](https://primevue.org/organizationchart)
|
||||
*
|
||||
* @module organizationchart
|
||||
*
|
||||
*/
|
||||
import { VNode } from 'vue';
|
||||
import { ClassComponent, GlobalComponentConstructor } from '../ts-helpers';
|
||||
|
||||
/**
|
||||
* Defines valid properties in OrganizationChartNode.
|
||||
*/
|
||||
export interface OrganizationChartNode {
|
||||
/**
|
||||
* Unique identifier of the node. (required)
|
||||
*/
|
||||
key: any;
|
||||
/**
|
||||
* Type of the node to match a template.
|
||||
*/
|
||||
type?: string;
|
||||
/**
|
||||
* Style class of the node content.
|
||||
*/
|
||||
styleClass?: string;
|
||||
/**
|
||||
* Data represented by the node.
|
||||
*/
|
||||
data?: any;
|
||||
/**
|
||||
* Whether node is selectable when selection is enabled.
|
||||
* @defaultValue true
|
||||
*/
|
||||
selectable?: boolean;
|
||||
/**
|
||||
* Whether node is collapsible when node expansion is enabled.
|
||||
* @defaultValue true
|
||||
*/
|
||||
collapsible?: boolean;
|
||||
/**
|
||||
* Children nodes array.
|
||||
*/
|
||||
children?: OrganizationChartNode[];
|
||||
/**
|
||||
* Optional keys
|
||||
*/
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface OrganizationChartSelectionKeys {
|
||||
/**
|
||||
* Optional keys
|
||||
*/
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface OrganizationChartCollapsedKeys {
|
||||
/**
|
||||
* Optional keys
|
||||
*/
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines valid properties in OrganizationChart component.
|
||||
*/
|
||||
export interface OrganizationChartProps {
|
||||
/**
|
||||
* Value of the component.
|
||||
*/
|
||||
value?: OrganizationChartNode;
|
||||
/**
|
||||
* A map instance of key-value pairs to represented the selected nodes.
|
||||
*/
|
||||
selectionKeys?: OrganizationChartSelectionKeys;
|
||||
/**
|
||||
* Type of the selection.
|
||||
*/
|
||||
selectionMode?: 'single' | 'multiple' | undefined;
|
||||
/**
|
||||
* A map instance of key-value pairs to represented the collapsed nodes.
|
||||
*/
|
||||
collapsedKeys?: OrganizationChartCollapsedKeys;
|
||||
/**
|
||||
* Whether the nodes can be expanded or toggled.
|
||||
* @defaultValue false
|
||||
*/
|
||||
collapsible?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines valid slots in OrganizationChart component.
|
||||
*/
|
||||
export interface OrganizationChartSlots {
|
||||
/**
|
||||
* Custom content template.
|
||||
*/
|
||||
default(node: any): VNode[];
|
||||
/**
|
||||
* Dynamic content template.
|
||||
* @todo
|
||||
*/
|
||||
[key: string]: (node: any) => VNode[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines valid emits in OrganizationChart component.
|
||||
*/
|
||||
export interface OrganizationChartEmits {
|
||||
/**
|
||||
* Emitted when the value changes.
|
||||
* @param {*} value - New value.
|
||||
*/
|
||||
'update:selectionKeys'(value: any): void;
|
||||
/**
|
||||
* Emitted when the value changes.
|
||||
* @param {boolean} value - New value.
|
||||
*/
|
||||
'update:collapsedKeys'(value: boolean): void;
|
||||
/**
|
||||
* Callback to invoke when a suggestion is selected.
|
||||
* @param {OrganizationChartNode} node - Node instance.
|
||||
*/
|
||||
'node-select'(node: OrganizationChartNode): void;
|
||||
/**
|
||||
* Callback to invoke when a node is unselected.
|
||||
* @param {OrganizationChartNode} node - Node instance.
|
||||
*/
|
||||
'node-unselect'(node: OrganizationChartNode): void;
|
||||
/**
|
||||
* Callback to invoke when a node is expanded.
|
||||
* @param {OrganizationChartNode} node - Node instance.
|
||||
*/
|
||||
'node-expand'(node: OrganizationChartNode): void;
|
||||
/**
|
||||
* Callback to invoke when a node is collapsed.
|
||||
* @param {OrganizationChartNode} node - Node instance.
|
||||
*/
|
||||
'node-collapsed'(node: OrganizationChartNode): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* **PrimeVue - OrganizationChart**
|
||||
*
|
||||
* _OrganizationChart visualizes hierarchical organization data._
|
||||
*
|
||||
* [Live Demo](https://www.primevue.org/organizationchart/)
|
||||
* --- ---
|
||||
* 
|
||||
*
|
||||
* @group Component
|
||||
*/
|
||||
declare class OrganizationChart extends ClassComponent<OrganizationChartProps, OrganizationChartSlots, OrganizationChartEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
OrganizationChart: GlobalComponentConstructor<OrganizationChart>;
|
||||
}
|
||||
}
|
||||
|
||||
export default OrganizationChart;
|
167
components/lib/organizationchart/OrganizationChart.spec.js
Normal file
167
components/lib/organizationchart/OrganizationChart.spec.js
Normal file
|
@ -0,0 +1,167 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
import OrganizationChart from './OrganizationChart.vue';
|
||||
|
||||
describe('OrganizationChart.vue', () => {
|
||||
let wrapper;
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = mount(OrganizationChart, {
|
||||
props: {
|
||||
value: {
|
||||
key: '0',
|
||||
type: 'person',
|
||||
styleClass: 'p-person',
|
||||
data: { label: 'CEO', name: 'Walter White', avatar: 'walter.jpg' },
|
||||
children: [
|
||||
{
|
||||
key: '0_0',
|
||||
type: 'person',
|
||||
styleClass: 'p-person',
|
||||
data: { label: 'CFO', name: 'Saul Goodman', avatar: 'saul.jpg' },
|
||||
children: [
|
||||
{
|
||||
key: '0_0_0',
|
||||
data: { label: 'Tax' },
|
||||
selectable: false,
|
||||
styleClass: 'department-cfo'
|
||||
},
|
||||
{
|
||||
key: '0_0_1',
|
||||
data: { label: 'Legal' },
|
||||
selectable: false,
|
||||
styleClass: 'department-cfo'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: '0_1',
|
||||
type: 'person',
|
||||
styleClass: 'p-person',
|
||||
data: { label: 'COO', name: 'Mike E.', avatar: 'mike.jpg' },
|
||||
children: [
|
||||
{
|
||||
key: '0_1_0',
|
||||
data: { label: 'Operations' },
|
||||
selectable: false,
|
||||
styleClass: 'department-coo'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: '0_2',
|
||||
type: 'person',
|
||||
styleClass: 'p-person',
|
||||
data: { label: 'CTO', name: 'Jesse Pinkman', avatar: 'jesse.jpg' },
|
||||
children: [
|
||||
{
|
||||
key: '0_2_0',
|
||||
data: { label: 'Development' },
|
||||
selectable: false,
|
||||
styleClass: 'department-cto',
|
||||
children: [
|
||||
{
|
||||
key: '0_2_0_0',
|
||||
data: { label: 'Analysis' },
|
||||
selectable: false,
|
||||
styleClass: 'department-cto'
|
||||
},
|
||||
{
|
||||
key: '0_2_0_1',
|
||||
data: { label: 'Front End' },
|
||||
selectable: false,
|
||||
styleClass: 'department-cto'
|
||||
},
|
||||
{
|
||||
key: '0_2_0_2',
|
||||
data: { label: 'Back End' },
|
||||
selectable: false,
|
||||
styleClass: 'department-cto'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: '0_2_1',
|
||||
data: { label: 'QA' },
|
||||
selectable: false,
|
||||
styleClass: 'department-cto'
|
||||
},
|
||||
{
|
||||
key: '0_2_2',
|
||||
data: { label: 'R&D' },
|
||||
selectable: false,
|
||||
styleClass: 'department-cto'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
collapsible: true,
|
||||
selectionMode: 'single',
|
||||
selectionKeys: {}
|
||||
},
|
||||
slots: {
|
||||
slots: {
|
||||
default: `
|
||||
<template #default="slotProps">
|
||||
<span>{{slotProps.node.data.label}}</span>
|
||||
</template>
|
||||
`,
|
||||
person: `
|
||||
<template #person="slotProps">
|
||||
<div class="node-header ui-corner-top">{{slotProps.node.data.label}}</div>
|
||||
<div class="node-content">
|
||||
<img :src="'images/organization/' + slotProps.node.data.avatar" width="32">
|
||||
<div>{{slotProps.node.data.name}}</div>
|
||||
</div>
|
||||
</template>
|
||||
`
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should exist', () => {
|
||||
expect(wrapper.find('.p-organizationchart.p-component').exists()).toBe(true);
|
||||
expect(wrapper.find('table.p-organizationchart-table').exists()).toBe(true);
|
||||
expect(wrapper.findAll('.p-node-toggler-icon').length).toBe(5);
|
||||
expect(wrapper.find('.p-node-toggler-icon').classes()).toContain('pi-chevron-down');
|
||||
});
|
||||
|
||||
it('should collapsed and expand', async () => {
|
||||
await wrapper.vm.onNodeToggle(wrapper.vm.value);
|
||||
|
||||
expect(wrapper.find('.p-node-toggler-icon').classes()).toContain('pi-chevron-up');
|
||||
expect(wrapper.emitted()['node-collapse'][0]).toEqual([wrapper.vm.value]);
|
||||
expect(wrapper.emitted()['update:collapsedKeys'][0]).toEqual([{ 0: true }]);
|
||||
expect(wrapper.vm.d_collapsedKeys).toEqual({ 0: true });
|
||||
|
||||
await wrapper.vm.onNodeToggle(wrapper.vm.value);
|
||||
|
||||
expect(wrapper.find('.p-node-toggler-icon').classes()).toContain('pi-chevron-down');
|
||||
expect(wrapper.emitted()['node-expand'][0]).toEqual([wrapper.vm.value]);
|
||||
expect(wrapper.emitted()['update:collapsedKeys'][0]).toEqual([{}]);
|
||||
expect(wrapper.vm.d_collapsedKeys).toEqual({});
|
||||
});
|
||||
|
||||
it('should item select and unselect', async () => {
|
||||
const contents = wrapper.findAll('.p-organizationchart-node-content');
|
||||
|
||||
await wrapper.vm.onNodeClick(wrapper.vm.value);
|
||||
|
||||
expect(wrapper.emitted()['node-select'][0]).toEqual([wrapper.vm.value]);
|
||||
expect(wrapper.emitted()['update:selectionKeys'][0]).toEqual([{ 0: true }]);
|
||||
|
||||
await wrapper.setProps({ selectionKeys: { 0: true } });
|
||||
|
||||
expect(contents[0].classes()).toContain('p-highlight');
|
||||
|
||||
await wrapper.vm.onNodeClick(wrapper.vm.value);
|
||||
|
||||
expect(wrapper.emitted()['node-unselect'][0]).toEqual([wrapper.vm.value]);
|
||||
expect(wrapper.emitted()['update:selectionKeys'][1]).toEqual([{}]);
|
||||
|
||||
await wrapper.setProps({ selectionKeys: {} });
|
||||
|
||||
expect(contents[0].classes()).not.toContain('p-highlight');
|
||||
});
|
||||
});
|
141
components/lib/organizationchart/OrganizationChart.vue
Executable file
141
components/lib/organizationchart/OrganizationChart.vue
Executable file
|
@ -0,0 +1,141 @@
|
|||
<template>
|
||||
<div class="p-organizationchart p-component">
|
||||
<OrganizationChartNode :node="value" :templates="$slots" @node-toggle="onNodeToggle" :collapsedKeys="d_collapsedKeys" :collapsible="collapsible" @node-click="onNodeClick" :selectionMode="selectionMode" :selectionKeys="selectionKeys" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import OrganizationChartNode from './OrganizationChartNode.vue';
|
||||
|
||||
export default {
|
||||
name: 'OrganizationChart',
|
||||
emits: ['node-unselect', 'node-select', 'update:selectionKeys', 'node-expand', 'node-collapse', 'update:collapsedKeys'],
|
||||
props: {
|
||||
value: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
selectionKeys: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
selectionMode: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
collapsible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
collapsedKeys: {
|
||||
type: null,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
d_collapsedKeys: this.collapsedKeys || {}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
collapsedKeys(newValue) {
|
||||
this.d_collapsedKeys = newValue;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onNodeClick(node) {
|
||||
const key = node.key;
|
||||
|
||||
if (this.selectionMode) {
|
||||
let _selectionKeys = this.selectionKeys ? { ...this.selectionKeys } : {};
|
||||
|
||||
if (_selectionKeys[key]) {
|
||||
delete _selectionKeys[key];
|
||||
this.$emit('node-unselect', node);
|
||||
} else {
|
||||
if (this.selectionMode === 'single') {
|
||||
_selectionKeys = {};
|
||||
}
|
||||
|
||||
_selectionKeys[key] = true;
|
||||
this.$emit('node-select', node);
|
||||
}
|
||||
|
||||
this.$emit('update:selectionKeys', _selectionKeys);
|
||||
}
|
||||
},
|
||||
onNodeToggle(node) {
|
||||
const key = node.key;
|
||||
|
||||
if (this.d_collapsedKeys[key]) {
|
||||
delete this.d_collapsedKeys[key];
|
||||
this.$emit('node-expand', node);
|
||||
} else {
|
||||
this.d_collapsedKeys[key] = true;
|
||||
this.$emit('node-collapse', node);
|
||||
}
|
||||
|
||||
this.d_collapsedKeys = { ...this.d_collapsedKeys };
|
||||
this.$emit('update:collapsedKeys', this.d_collapsedKeys);
|
||||
}
|
||||
},
|
||||
components: {
|
||||
OrganizationChartNode: OrganizationChartNode
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.p-organizationchart-table {
|
||||
border-spacing: 0;
|
||||
border-collapse: separate;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.p-organizationchart-table > tbody > tr > td {
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
padding: 0 0.75rem;
|
||||
}
|
||||
|
||||
.p-organizationchart-node-content {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.p-organizationchart-node-content .p-node-toggler {
|
||||
position: absolute;
|
||||
bottom: -0.75rem;
|
||||
margin-left: -0.75rem;
|
||||
z-index: 2;
|
||||
left: 50%;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.p-organizationchart-node-content .p-node-toggler .p-node-toggler-icon {
|
||||
position: relative;
|
||||
top: 0.25rem;
|
||||
}
|
||||
|
||||
.p-organizationchart-line-down {
|
||||
margin: 0 auto;
|
||||
height: 20px;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
.p-organizationchart-line-right {
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
.p-organizationchart-line-left {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.p-organizationchart-selectable-node {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
137
components/lib/organizationchart/OrganizationChartNode.vue
Executable file
137
components/lib/organizationchart/OrganizationChartNode.vue
Executable file
|
@ -0,0 +1,137 @@
|
|||
<template>
|
||||
<table class="p-organizationchart-table">
|
||||
<tbody>
|
||||
<tr v-if="node">
|
||||
<td :colspan="colspan">
|
||||
<div :class="nodeContentClass" @click="onNodeClick">
|
||||
<component :is="templates[node.type] || templates['default']" :node="node" />
|
||||
<a v-if="toggleable" tabindex="0" class="p-node-toggler" @click="toggleNode" @keydown="onKeydown">
|
||||
<i class="p-node-toggler-icon pi" :class="{ 'pi-chevron-down': expanded, 'pi-chevron-up': !expanded }"></i>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr :style="childStyle" class="p-organizationchart-lines">
|
||||
<td :colspan="colspan">
|
||||
<div class="p-organizationchart-line-down"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr :style="childStyle" class="p-organizationchart-lines">
|
||||
<template v-if="node.children && node.children.length === 1">
|
||||
<td :colspan="colspan">
|
||||
<div class="p-organizationchart-line-down"></div>
|
||||
</td>
|
||||
</template>
|
||||
<template v-if="node.children && node.children.length > 1">
|
||||
<template v-for="(child, i) of node.children" :key="child.key">
|
||||
<td class="p-organizationchart-line-left" :class="{ 'p-organizationchart-line-top': !(i === 0) }"> </td>
|
||||
<td class="p-organizationchart-line-right" :class="{ 'p-organizationchart-line-top': !(i === node.children.length - 1) }"> </td>
|
||||
</template>
|
||||
</template>
|
||||
</tr>
|
||||
<tr :style="childStyle" class="p-organizationchart-nodes">
|
||||
<td v-for="child of node.children" :key="child.key" colspan="2">
|
||||
<OrganizationChartNode
|
||||
:node="child"
|
||||
:templates="templates"
|
||||
:collapsedKeys="collapsedKeys"
|
||||
@node-toggle="onChildNodeToggle"
|
||||
:collapsible="collapsible"
|
||||
:selectionMode="selectionMode"
|
||||
:selectionKeys="selectionKeys"
|
||||
@node-click="onChildNodeClick"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { DomHandler } from 'primevue/utils';
|
||||
|
||||
export default {
|
||||
name: 'OrganizationChartNode',
|
||||
emits: ['node-click', 'node-toggle'],
|
||||
props: {
|
||||
node: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
templates: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
collapsible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
collapsedKeys: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
selectionKeys: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
selectionMode: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onNodeClick(event) {
|
||||
if (DomHandler.hasClass(event.target, 'p-node-toggler') || DomHandler.hasClass(event.target, 'p-node-toggler-icon')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.selectionMode) {
|
||||
this.$emit('node-click', this.node);
|
||||
}
|
||||
},
|
||||
onChildNodeClick(node) {
|
||||
this.$emit('node-click', node);
|
||||
},
|
||||
toggleNode() {
|
||||
this.$emit('node-toggle', this.node);
|
||||
},
|
||||
onChildNodeToggle(node) {
|
||||
this.$emit('node-toggle', node);
|
||||
},
|
||||
onKeydown(event) {
|
||||
if (event.code === 'Enter' || event.code === 'Space') {
|
||||
this.toggleNode();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
nodeContentClass() {
|
||||
return ['p-organizationchart-node-content', this.node.styleClass, { 'p-organizationchart-selectable-node': this.selectable, 'p-highlight': this.selected }];
|
||||
},
|
||||
leaf() {
|
||||
return this.node.leaf === false ? false : !(this.node.children && this.node.children.length);
|
||||
},
|
||||
colspan() {
|
||||
return this.node.children && this.node.children.length ? this.node.children.length * 2 : null;
|
||||
},
|
||||
childStyle() {
|
||||
return {
|
||||
visibility: !this.leaf && this.expanded ? 'inherit' : 'hidden'
|
||||
};
|
||||
},
|
||||
expanded() {
|
||||
return this.collapsedKeys[this.node.key] === undefined;
|
||||
},
|
||||
selectable() {
|
||||
return this.selectionMode && this.node.selectable !== false;
|
||||
},
|
||||
selected() {
|
||||
return this.selectable && this.selectionKeys && this.selectionKeys[this.node.key] === true;
|
||||
},
|
||||
toggleable() {
|
||||
return this.collapsible && this.node.collapsible !== false && !this.leaf;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
9
components/lib/organizationchart/package.json
Normal file
9
components/lib/organizationchart/package.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"main": "./organizationchart.cjs.js",
|
||||
"module": "./organizationchart.esm.js",
|
||||
"unpkg": "./organizationchart.min.js",
|
||||
"types": "./OrganizationChart.d.ts",
|
||||
"browser": {
|
||||
"./sfc": "./OrganizationChart.vue"
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue