Refactor #3965 - For Splitter

pull/3997/head
Tuğçe Küçükoğlu 2023-05-24 11:54:19 +03:00
parent b752ba69e9
commit 6b3fe54feb
6 changed files with 180 additions and 113 deletions

View File

@ -0,0 +1,103 @@
<script>
import BaseComponent from 'primevue/basecomponent';
import { useStyle } from 'primevue/usestyle';
const styles = `
.p-splitter {
display: flex;
flex-wrap: nowrap;
}
.p-splitter-vertical {
flex-direction: column;
}
.p-splitter-gutter {
flex-grow: 0;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
cursor: col-resize;
}
.p-splitter-horizontal.p-splitter-resizing {
cursor: col-resize;
user-select: none;
}
.p-splitter-horizontal > .p-splitter-gutter > .p-splitter-gutter-handle {
height: 24px;
width: 100%;
}
.p-splitter-horizontal > .p-splitter-gutter {
cursor: col-resize;
}
.p-splitter-vertical.p-splitter-resizing {
cursor: row-resize;
user-select: none;
}
.p-splitter-vertical > .p-splitter-gutter {
cursor: row-resize;
}
.p-splitter-vertical > .p-splitter-gutter > .p-splitter-gutter-handle {
width: 24px;
height: 100%;
}
`;
const classes = {
root: ({ props }) => ['p-splitter p-component', 'p-splitter-' + props.layout],
gutter: 'p-splitter-gutter',
gutterHandler: 'p-splitter-gutter-handle'
};
const inlineStyles = {
root: ({ props }) => [{ display: 'flex', 'flex-wrap': 'nowrap' }, props.layout === 'vertical' ? { 'flex-direction': 'column' } : '']
};
const { load: loadStyle, unload: unloadStyle } = useStyle(styles, { id: 'primevue_splitter_style', manual: true });
export default {
name: 'BaseSplitter',
extends: BaseComponent,
props: {
layout: {
type: String,
default: 'horizontal'
},
gutterSize: {
type: Number,
default: 4
},
stateKey: {
type: String,
default: null
},
stateStorage: {
type: String,
default: 'session'
},
step: {
type: Number,
default: 5
}
},
css: {
classes,
inlineStyles
},
watch: {
isUnstyled: {
immediate: true,
handler(newValue) {
!newValue && loadStyle();
}
}
}
};
</script>

View File

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

View File

@ -1,54 +1,34 @@
<template> <template>
<div :class="containerClass" v-bind="ptm('root')"> <div :class="cx('root')" :style="sx('root')" :data-p-resizing="false" v-bind="ptm('root')">
<template v-for="(panel, i) of panels" :key="i"> <template v-for="(panel, i) of panels" :key="i">
<component :is="panel" tabindex="-1"></component> <component :is="panel" tabindex="-1"></component>
<div <div
v-if="i !== panels.length - 1" v-if="i !== panels.length - 1"
class="p-splitter-gutter" ref="gutter"
:class="cx('gutter')"
role="separator" role="separator"
tabindex="-1" tabindex="-1"
@mousedown="onGutterMouseDown($event, i)" @mousedown="onGutterMouseDown($event, i)"
@touchstart="onGutterTouchStart($event, i)" @touchstart="onGutterTouchStart($event, i)"
@touchmove="onGutterTouchMove($event, i)" @touchmove="onGutterTouchMove($event, i)"
@touchend="onGutterTouchEnd($event, i)" @touchend="onGutterTouchEnd($event, i)"
:data-p-gutter-resizing="false"
v-bind="ptm('gutter')" v-bind="ptm('gutter')"
> >
<div class="p-splitter-gutter-handle" tabindex="0" :style="gutterStyle" :aria-orientation="layout" :aria-valuenow="prevSize" @keyup="onGutterKeyUp" @keydown="onGutterKeyDown($event, i)" v-bind="ptm('gutterhandler')"></div> <div :class="cx('gutterHandler')" tabindex="0" :style="[gutterStyle]" :aria-orientation="layout" :aria-valuenow="prevSize" @keyup="onGutterKeyUp" @keydown="onGutterKeyDown($event, i)" v-bind="ptm('gutterHandler')"></div>
</div> </div>
</template> </template>
</div> </div>
</template> </template>
<script> <script>
import BaseComponent from 'primevue/basecomponent';
import { DomHandler, ObjectUtils } from 'primevue/utils'; import { DomHandler, ObjectUtils } from 'primevue/utils';
import BaseSplitter from './BaseSplitter.vue';
export default { export default {
name: 'Splitter', name: 'Splitter',
extends: BaseComponent, extends: BaseSplitter,
emits: ['resizestart', 'resizeend'], emits: ['resizestart', 'resizeend'],
props: {
layout: {
type: String,
default: 'horizontal'
},
gutterSize: {
type: Number,
default: 4
},
stateKey: {
type: String,
default: null
},
stateStorage: {
type: String,
default: 'session'
},
step: {
type: Number,
default: 5
}
},
dragging: false, dragging: false,
mouseMoveListener: null, mouseMoveListener: null,
mouseUpListener: null, mouseUpListener: null,
@ -78,7 +58,7 @@ export default {
} }
if (!initialized) { if (!initialized) {
let children = [...this.$el.children].filter((child) => DomHandler.hasClass(child, 'p-splitter-panel')); let children = [...this.$el.children].filter((child) => child.getAttribute('data-pc-name') === 'splitterpanel');
let _panelSizes = []; let _panelSizes = [];
this.panels.map((panel, i) => { this.panels.map((panel, i) => {
@ -124,8 +104,8 @@ export default {
this.prevPanelIndex = index; this.prevPanelIndex = index;
this.$emit('resizestart', { originalEvent: event, sizes: this.panelSizes }); this.$emit('resizestart', { originalEvent: event, sizes: this.panelSizes });
DomHandler.addClass(this.gutterElement, 'p-splitter-gutter-resizing'); this.$refs.gutter[index].setAttribute('data-p-gutter-resizing', true);
DomHandler.addClass(this.$el, 'p-splitter-resizing'); this.$el.setAttribute('data-p-resizing', true);
}, },
onResize(event, step, isKeyDown) { onResize(event, step, isKeyDown) {
let newPos, newPrevPanelSize, newNextPanelSize; let newPos, newPrevPanelSize, newNextPanelSize;
@ -161,8 +141,8 @@ export default {
} }
this.$emit('resizeend', { originalEvent: event, sizes: this.panelSizes }); this.$emit('resizeend', { originalEvent: event, sizes: this.panelSizes });
DomHandler.removeClass(this.gutterElement, 'p-splitter-gutter-resizing'); this.$refs.gutter.forEach((gutter) => gutter.setAttribute('data-p-gutter-resizing', false));
DomHandler.removeClass(this.$el, 'p-splitter-resizing'); this.$el.setAttribute('data-p-resizing', false);
this.clear(); this.clear();
}, },
repeat(event, index, step) { repeat(event, index, step) {
@ -347,7 +327,7 @@ export default {
if (stateString) { if (stateString) {
this.panelSizes = JSON.parse(stateString); this.panelSizes = JSON.parse(stateString);
let children = [...this.$el.children].filter((child) => DomHandler.hasClass(child, 'p-splitter-panel')); let children = [...this.$el.children].filter((child) => child.getAttribute('data-pc-name') === 'splitterpanel');
children.forEach((child, i) => { children.forEach((child, i) => {
child.style.flexBasis = 'calc(' + this.panelSizes[i] + '% - ' + (this.panels.length - 1) * this.gutterSize + 'px)'; child.style.flexBasis = 'calc(' + this.panelSizes[i] + '% - ' + (this.panels.length - 1) * this.gutterSize + 'px)';
@ -360,9 +340,6 @@ export default {
} }
}, },
computed: { computed: {
containerClass() {
return ['p-splitter p-component', 'p-splitter-' + this.layout];
},
panels() { panels() {
const panels = []; const panels = [];
@ -390,64 +367,3 @@ export default {
} }
}; };
</script> </script>
<style>
.p-splitter {
display: flex;
flex-wrap: nowrap;
}
.p-splitter-vertical {
flex-direction: column;
}
.p-splitter-panel {
flex-grow: 1;
}
.p-splitter-panel-nested {
display: flex;
}
.p-splitter-panel .p-splitter {
flex-grow: 1;
border: 0 none;
}
.p-splitter-gutter {
flex-grow: 0;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
cursor: col-resize;
}
.p-splitter-horizontal.p-splitter-resizing {
cursor: col-resize;
user-select: none;
}
.p-splitter-horizontal > .p-splitter-gutter > .p-splitter-gutter-handle {
height: 24px;
width: 100%;
}
.p-splitter-horizontal > .p-splitter-gutter {
cursor: col-resize;
}
.p-splitter-vertical.p-splitter-resizing {
cursor: row-resize;
user-select: none;
}
.p-splitter-vertical > .p-splitter-gutter {
cursor: row-resize;
}
.p-splitter-vertical > .p-splitter-gutter > .p-splitter-gutter-handle {
width: 24px;
height: 100%;
}
</style>

View File

@ -0,0 +1,51 @@
<script>
import BaseComponent from 'primevue/basecomponent';
import { useStyle } from 'primevue/usestyle';
const styles = `
.p-splitter-panel {
flex-grow: 1;
}
.p-splitter-panel-nested {
display: flex;
}
.p-splitter-panel .p-splitter {
flex-grow: 1;
border: 0 none;
}
`;
const classes = {
root: ({ instance }) => ['p-splitter-panel', { 'p-splitter-panel-nested': instance.isNested }]
};
const { load: loadStyle, unload: unloadStyle } = useStyle(styles, { id: 'primevue_splitterpanel_style', manual: true });
export default {
name: 'BaseSplitterPanel',
extends: BaseComponent,
props: {
size: {
type: Number,
default: null
},
minSize: {
type: Number,
default: null
}
},
css: {
classes
},
watch: {
isUnstyled: {
immediate: true,
handler(newValue) {
!newValue && loadStyle();
}
}
}
};
</script>

View File

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

View File

@ -1,29 +1,16 @@
<template> <template>
<div ref="container" :class="containerClass" v-bind="ptm('root')"> <div ref="container" :class="cx('root')" data-pc-name="splitterpanel" v-bind="ptm('root')">
<slot></slot> <slot></slot>
</div> </div>
</template> </template>
<script> <script>
import BaseComponent from 'primevue/basecomponent'; import BaseSplitterPanel from './BaseSplitterPanel.vue';
export default { export default {
name: 'SplitterPanel', name: 'SplitterPanel',
extends: BaseComponent, extends: BaseSplitterPanel,
props: {
size: {
type: Number,
default: null
},
minSize: {
type: Number,
default: null
}
},
computed: { computed: {
containerClass() {
return ['p-splitter-panel', { 'p-splitter-panel-nested': this.isNested }];
},
isNested() { isNested() {
return this.$slots.default().some((child) => { return this.$slots.default().some((child) => {
return child.type.name === 'Splitter'; return child.type.name === 'Splitter';