vxe-pc-ui
Version:
A vue based PC component library
682 lines (681 loc) • 22.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _vue = require("vue");
var _ui = require("../../ui");
var _vn = require("../../ui/src/vn");
var _dom = require("../../ui/src/dom");
var _utils = require("../../ui/src/utils");
var _log = require("../../ui/src/log");
var _xeUtils = _interopRequireDefault(require("xe-utils"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _default = exports.default = (0, _vue.defineComponent)({
name: 'VxeSplit',
props: {
width: [Number, String],
height: [Number, String],
vertical: {
type: Boolean,
default: () => (0, _ui.getConfig)().split.vertical
},
border: {
type: Boolean,
default: () => (0, _ui.getConfig)().split.border
},
padding: {
type: Boolean,
default: () => (0, _ui.getConfig)().split.padding
},
resize: {
type: Boolean,
default: () => (0, _ui.getConfig)().split.resize
},
items: Array,
itemConfig: Object,
barConfig: Object,
actionConfig: Object
},
emits: ['action-dblclick', 'action-click', 'toggle-expand', 'resize-start', 'resize-drag', 'resize-end'],
setup(props, context) {
const {
emit,
slots
} = context;
const xID = _xeUtils.default.uniqueId();
const refElem = (0, _vue.ref)();
const reactData = (0, _vue.reactive)({
staticItems: [],
itemList: []
});
const internalData = {};
const computeItemOpts = (0, _vue.computed)(() => {
return Object.assign({}, (0, _ui.getConfig)().split.itemConfig, props.itemConfig);
});
const computeBarOpts = (0, _vue.computed)(() => {
return Object.assign({}, (0, _ui.getConfig)().split.barConfig, props.barConfig);
});
const computeActionOpts = (0, _vue.computed)(() => {
return Object.assign({}, (0, _ui.getConfig)().split.actionConfig, props.actionConfig);
});
const computeIsFoldNext = (0, _vue.computed)(() => {
const actionOpts = computeActionOpts.value;
return actionOpts.direction === 'next';
});
const computeVisibleItems = (0, _vue.computed)(() => {
return reactData.itemList.filter(item => item.isVisible);
});
const computeBarStyle = (0, _vue.computed)(() => {
const barOpts = computeBarOpts.value;
const {
width,
height
} = barOpts;
const stys = {};
if (height) {
stys.height = (0, _dom.toCssUnit)(height);
}
if (width) {
stys.width = (0, _dom.toCssUnit)(width);
}
return stys;
});
const computeMaps = {
computeItemOpts,
computeBarOpts,
computeActionOpts,
computeIsFoldNext
};
const refMaps = {
refElem
};
const $xeSplit = {
xID,
props,
context,
reactData,
internalData,
getRefMaps: () => refMaps,
getComputeMaps: () => computeMaps
};
const dispatchEvent = (type, params, evnt) => {
emit(type, (0, _ui.createEvent)(evnt, {
$split: $xeSplit
}, params));
};
const callSlot = (slotFunc, params) => {
if (slotFunc) {
if (_xeUtils.default.isString(slotFunc)) {
slotFunc = slots[slotFunc] || null;
}
if (_xeUtils.default.isFunction(slotFunc)) {
return (0, _vn.getSlotVNs)(slotFunc(params));
}
}
return [];
};
const getDefaultActionIcon = item => {
const {
vertical
} = props;
const {
showAction,
isExpand
} = item;
const isFoldNext = computeIsFoldNext.value;
const topIcon = 'SPLIT_TOP_ACTION';
const bottomIcon = 'SPLIT_BOTTOM_ACTION';
const leftIcon = 'SPLIT_LEFT_ACTION';
const rightIcon = 'SPLIT_RIGHT_ACTION';
if (showAction) {
let iconName = '';
if (isFoldNext) {
if (vertical) {
iconName = isExpand ? bottomIcon : topIcon;
} else {
iconName = isExpand ? rightIcon : leftIcon;
}
} else {
if (vertical) {
iconName = isExpand ? topIcon : bottomIcon;
} else {
iconName = isExpand ? leftIcon : rightIcon;
}
}
if (iconName) {
return (0, _ui.getIcon)()[iconName];
}
}
return '';
};
const reset = () => {
const {
itemList
} = reactData;
itemList.forEach(item => {
item.isExpand = true;
item.isVisible = true;
item.foldHeight = 0;
item.foldWidth = 0;
item.resizeHeight = 0;
item.resizeWidth = 0;
});
return (0, _vue.nextTick)();
};
const handleLoadItem = (list, isReset) => {
const {
staticItems
} = reactData;
const itemDef = {
isVisible: true,
isExpand: true,
renderWidth: 0,
resizeWidth: 0,
foldWidth: 0,
renderHeight: 0,
resizeHeight: 0,
foldHeight: 0
};
reactData.itemList = list.map(item => {
if (item.slots) {
_xeUtils.default.each(item.slots, func => {
if (!_xeUtils.default.isFunction(func)) {
if (!slots[func]) {
(0, _log.errLog)('vxe.error.notSlot', [func]);
}
}
});
}
return Object.assign({}, isReset ? null : itemDef, item, isReset ? itemDef : null, {
id: _xeUtils.default.uniqueId()
});
});
if (staticItems.length) {
(0, _log.errLog)('vxe.error.errConflicts', ['<vxe-split-pane ...>', 'items']);
}
return recalculate();
};
const loadItem = list => {
return handleLoadItem(list || [], false);
};
const reloadItem = list => {
return handleLoadItem(list || [], true);
};
const recalculate = () => {
return (0, _vue.nextTick)().then(() => {
const {
vertical
} = props;
const {
itemList
} = reactData;
const el = refElem.value;
if (!el) {
return;
}
const wrapperWidth = el.clientWidth;
const wrapperHeight = el.clientHeight;
if (!wrapperWidth || !wrapperHeight) {
return;
}
const itemOpts = computeItemOpts.value;
const allMinWidth = _xeUtils.default.toNumber(itemOpts.minWidth);
const allMinHeight = _xeUtils.default.toNumber(itemOpts.minHeight);
const residueItems = [];
if (vertical) {
let countHeight = 0;
itemList.forEach(item => {
const {
height
} = item;
let itemHeight = 0;
if (height) {
if ((0, _dom.isScale)(height)) {
itemHeight = wrapperHeight * _xeUtils.default.toNumber(height);
} else {
itemHeight = _xeUtils.default.toNumber(height);
}
item.renderHeight = itemHeight;
} else {
residueItems.push(item);
}
countHeight += itemHeight;
});
if (residueItems.length) {
const reMeanHeight = (wrapperHeight - countHeight) / residueItems.length;
residueItems.forEach(item => {
item.renderHeight = Math.max(_xeUtils.default.toNumber((0, _utils.getGlobalDefaultConfig)(item.minHeight, allMinHeight)), reMeanHeight);
});
}
} else {
let countWidth = 0;
itemList.forEach(item => {
const {
width
} = item;
let itemWidth = 0;
if (width) {
if ((0, _dom.isScale)(width)) {
itemWidth = wrapperWidth * _xeUtils.default.toNumber(width);
} else {
itemWidth = _xeUtils.default.toNumber(width);
}
item.renderWidth = itemWidth;
} else {
residueItems.push(item);
}
countWidth += itemWidth;
});
if (residueItems.length) {
const reMeanWidth = (wrapperWidth - countWidth) / residueItems.length;
residueItems.forEach(item => {
item.renderWidth = Math.max(_xeUtils.default.toNumber((0, _utils.getGlobalDefaultConfig)(item.minWidth, allMinWidth)), reMeanWidth);
});
}
}
});
};
const dragEvent = evnt => {
const {
resize,
vertical
} = props;
const {
itemList
} = reactData;
if (!resize) {
return;
}
evnt.preventDefault();
const barEl = evnt.currentTarget;
const handleEl = barEl.parentElement;
const el = refElem.value;
if (!el) {
return;
}
const itemId = handleEl.getAttribute('itemid');
const itemIndex = _xeUtils.default.findIndexOf(itemList, item => item.id === itemId);
const item = itemList[itemIndex];
if (!item) {
return;
}
if (!item.isExpand) {
return;
}
const isFoldNext = computeIsFoldNext.value;
const itemOpts = computeItemOpts.value;
const allMinWidth = _xeUtils.default.toNumber(itemOpts.minWidth);
const allMinHeight = _xeUtils.default.toNumber(itemOpts.minHeight);
const targetItem = itemList[itemIndex + (isFoldNext ? 1 : -1)];
const targetItemEl = targetItem ? el.querySelector(`.vxe-split-pane[itemid="${targetItem.id}"]`) : null;
const currItemEl = item ? el.querySelector(`.vxe-split-pane[itemid="${item.id}"]`) : null;
const targetWidth = targetItemEl ? targetItemEl.clientWidth : 0;
const currWidth = currItemEl ? currItemEl.clientWidth : 0;
const targetHeight = targetItemEl ? targetItemEl.clientHeight : 0;
const currHeight = currItemEl ? currItemEl.clientHeight : 0;
const targetMinWidth = _xeUtils.default.toNumber(targetItem ? (0, _utils.getGlobalDefaultConfig)(targetItem.minWidth, allMinWidth) : allMinWidth);
const currMinWidth = _xeUtils.default.toNumber((0, _utils.getGlobalDefaultConfig)(item.minWidth, allMinWidth));
const targetMinHeight = _xeUtils.default.toNumber(targetItem ? (0, _utils.getGlobalDefaultConfig)(targetItem.minHeight, allMinHeight) : allMinHeight);
const currMinHeight = _xeUtils.default.toNumber((0, _utils.getGlobalDefaultConfig)(item.minHeight, allMinHeight));
const disX = evnt.clientX;
const disY = evnt.clientY;
(0, _dom.addClass)(el, 'is--drag');
document.onmousemove = evnt => {
evnt.preventDefault();
if (vertical) {
const offsetTop = isFoldNext ? disY - evnt.clientY : evnt.clientY - disY;
if (offsetTop > 0) {
if (targetItem) {
if (currHeight - offsetTop >= currMinHeight) {
const reHeight = currHeight - offsetTop;
targetItem.resizeHeight = targetHeight + offsetTop;
item.resizeHeight = reHeight;
dispatchEvent('resize-drag', {
item,
name: item.name,
offsetHeight: offsetTop,
resizeHeight: reHeight,
offsetWidth: 0,
resizeWidth: 0
}, evnt);
}
}
} else {
if (targetItem) {
if (targetHeight + offsetTop >= targetMinHeight) {
const reHeight = currHeight - offsetTop;
targetItem.resizeHeight = targetHeight + offsetTop;
item.resizeHeight = reHeight;
dispatchEvent('resize-drag', {
item,
name: item.name,
offsetHeight: offsetTop,
resizeHeight: reHeight,
offsetWidth: 0,
resizeWidth: 0
}, evnt);
}
}
}
} else {
const offsetLeft = isFoldNext ? disX - evnt.clientX : evnt.clientX - disX;
if (offsetLeft > 0) {
if (targetItem) {
if (currWidth - offsetLeft >= currMinWidth) {
const reWidth = currWidth - offsetLeft;
targetItem.resizeWidth = targetWidth + offsetLeft;
item.resizeWidth = reWidth;
dispatchEvent('resize-drag', {
item,
name: item.name,
offsetHeight: 0,
resizeHeight: 0,
offsetWidth: offsetLeft,
resizeWidth: reWidth
}, evnt);
}
}
} else {
if (targetItem) {
if (targetWidth + offsetLeft >= targetMinWidth) {
const reWidth = currWidth - offsetLeft;
targetItem.resizeWidth = targetWidth + offsetLeft;
item.resizeWidth = reWidth;
dispatchEvent('resize-drag', {
item,
name: item.name,
offsetHeight: 0,
resizeHeight: 0,
offsetWidth: offsetLeft,
resizeWidth: reWidth
}, evnt);
}
}
}
}
};
document.onmouseup = evnt => {
document.onmousemove = null;
document.onmouseup = null;
(0, _dom.removeClass)(el, 'is--drag');
dispatchEvent('resize-end', {
item,
name: item.name,
resizeHeight: item.resizeHeight,
resizeWidth: item.resizeWidth
}, evnt);
recalculate();
};
dispatchEvent('resize-start', {
item,
name: item.name
}, evnt);
};
const handleItemActionEvent = evnt => {
const el = refElem.value;
if (!el) {
return;
}
const {
vertical
} = props;
const {
itemList
} = reactData;
const isFoldNext = computeIsFoldNext.value;
const btnEl = evnt.currentTarget;
const handleEl = btnEl.parentElement;
const itemId = handleEl.getAttribute('itemid');
const itemIndex = _xeUtils.default.findIndexOf(itemList, item => item.id === itemId);
const item = itemList[itemIndex];
const targetItem = itemList[itemIndex + (isFoldNext ? 1 : -1)];
if (item) {
const {
showAction,
isExpand
} = item;
if (showAction) {
if (vertical) {
if (targetItem) {
targetItem.isVisible = !isExpand;
targetItem.foldHeight = 0;
item.isExpand = !isExpand;
item.isVisible = true;
item.foldHeight = isExpand ? (targetItem.resizeHeight || targetItem.renderHeight) + (item.resizeHeight || item.renderHeight) : 0;
}
} else {
if (targetItem) {
targetItem.isVisible = !isExpand;
targetItem.foldWidth = 0;
item.isExpand = !isExpand;
item.isVisible = true;
item.foldWidth = isExpand ? (targetItem.resizeWidth || targetItem.renderWidth) + (item.resizeWidth || item.renderWidth) : 0;
}
}
dispatchEvent('toggle-expand', {
item,
name: item.name,
targetItem,
targetName: targetItem ? targetItem.name : '',
expanded: item.isExpand
}, evnt);
recalculate();
}
}
};
const handleActionDblclickEvent = evnt => {
const {
itemList
} = reactData;
const actionOpts = computeActionOpts.value;
const btnEl = evnt.currentTarget;
const handleEl = btnEl.parentElement;
const itemId = handleEl.getAttribute('itemid');
const itemIndex = _xeUtils.default.findIndexOf(itemList, item => item.id === itemId);
const item = itemList[itemIndex];
if (actionOpts.trigger === 'dblclick') {
handleItemActionEvent(evnt);
}
dispatchEvent('action-dblclick', {
item,
name: item ? item.name : ''
}, evnt);
};
const handleActionClickEvent = evnt => {
const {
itemList
} = reactData;
const actionOpts = computeActionOpts.value;
const btnEl = evnt.currentTarget;
const handleEl = btnEl.parentElement;
const itemId = handleEl.getAttribute('itemid');
const itemIndex = _xeUtils.default.findIndexOf(itemList, item => item.id === itemId);
const item = itemList[itemIndex];
if (actionOpts.trigger !== 'dblclick') {
handleItemActionEvent(evnt);
}
dispatchEvent('action-click', {
item,
name: item ? item.name : ''
}, evnt);
};
const handleGlobalResizeEvent = () => {
recalculate();
};
const splitMethods = {
dispatchEvent,
recalculate,
reset,
loadItem,
reloadItem
};
const splitPrivateMethods = {};
Object.assign($xeSplit, splitMethods, splitPrivateMethods);
const renderHandleBar = item => {
const barStyle = computeBarStyle.value;
const actionOpts = computeActionOpts.value;
const isFoldNext = computeIsFoldNext.value;
const {
id,
isExpand,
showAction
} = item;
return (0, _vue.h)('div', {
itemid: id,
class: ['vxe-split-pane-handle', isFoldNext ? 'to--next' : 'to--prev']
}, [(0, _vue.h)('div', {
class: 'vxe-split-pane-handle-bar',
style: barStyle,
onMousedown: dragEvent
}), showAction ? (0, _vue.h)('span', {
class: 'vxe-split-pane-action-btn',
onDblclick: handleActionDblclickEvent,
onClick: handleActionClickEvent
}, [(0, _vue.h)('i', {
class: (isExpand ? actionOpts.openIcon : actionOpts.closeIcon) || getDefaultActionIcon(item)
})]) : (0, _ui.renderEmptyElement)($xeSplit)]);
};
const renderItems = () => {
const {
border,
padding,
resize,
vertical
} = props;
const {
itemList
} = reactData;
const visibleItems = computeVisibleItems.value;
const isFoldNext = computeIsFoldNext.value;
const itemVNs = [];
itemList.forEach((item, index) => {
const {
id,
name,
slots,
renderHeight,
resizeHeight,
foldHeight,
renderWidth,
resizeWidth,
foldWidth,
isVisible,
isExpand
} = item;
const defaultSlot = slots ? slots.default : null;
const stys = {};
const itemWidth = isVisible ? foldWidth || resizeWidth || renderWidth : 0;
const itemHeight = isVisible ? foldHeight || resizeHeight || renderHeight : 0;
// 当只剩下一个可视区自动占用 100%
if (vertical) {
if (itemHeight) {
stys.height = visibleItems.length === 1 ? '100%' : (0, _dom.toCssUnit)(itemHeight);
}
} else {
if (itemWidth) {
stys.width = visibleItems.length === 1 ? '100%' : (0, _dom.toCssUnit)(itemWidth);
}
}
itemVNs.push((0, _vue.h)('div', {
itemid: id,
class: ['vxe-split-pane', vertical ? 'is--vertical' : 'is--horizontal', {
'is--resize': resize,
'is--padding': padding,
'is--border': border,
'is--height': itemHeight,
'is--width': itemWidth,
'is--fill': isVisible && !itemHeight && !itemWidth,
'is--handle': index > 0,
'is--expand': isExpand,
'is--hidden': !isVisible
}],
style: stys
}, [index && !isFoldNext ? renderHandleBar(item) : (0, _ui.renderEmptyElement)($xeSplit), (0, _vue.h)('div', {
itemid: id,
class: 'vxe-split-pane--wrapper'
}, [(0, _vue.h)('div', {
class: 'vxe-split-pane--inner'
}, defaultSlot ? callSlot(defaultSlot, {
name,
isVisible,
isExpand
}) : [])]), isFoldNext && index < itemList.length - 1 ? renderHandleBar(item) : (0, _ui.renderEmptyElement)($xeSplit)]));
});
return (0, _vue.h)('div', {
class: 'vxe-split-wrapper'
}, itemVNs);
};
const renderVN = () => {
const {
vertical,
width,
height
} = props;
const defaultSlot = slots.default;
const stys = {};
if (height) {
stys.height = (0, _dom.toCssUnit)(height);
}
if (width) {
stys.width = (0, _dom.toCssUnit)(width);
}
return (0, _vue.h)('div', {
ref: refElem,
class: ['vxe-split', vertical ? 'is--vertical' : 'is--horizontal'],
style: stys
}, [(0, _vue.h)('div', {
class: 'vxe-split-slots'
}, defaultSlot ? defaultSlot({}) : []), renderItems()]);
};
const itemFlag = (0, _vue.ref)(0);
(0, _vue.watch)(() => props.items ? props.items.length : -1, () => {
itemFlag.value++;
});
(0, _vue.watch)(() => props.items, () => {
itemFlag.value++;
});
(0, _vue.watch)(itemFlag, () => {
loadItem(props.items || []);
});
(0, _vue.watch)(() => reactData.staticItems, val => {
if (props.items && props.items.length) {
(0, _log.errLog)('vxe.error.errConflicts', ['<vxe-split-pane ...>', 'items']);
}
reactData.itemList = val;
recalculate();
});
let resizeObserver;
(0, _vue.onMounted)(() => {
(0, _vue.nextTick)(() => {
recalculate();
});
const el = refElem.value;
if (el) {
resizeObserver = _ui.globalResize.create(() => {
recalculate();
});
resizeObserver.observe(el);
}
_ui.globalEvents.on($xeSplit, 'resize', handleGlobalResizeEvent);
});
(0, _vue.onUnmounted)(() => {
if (resizeObserver) {
resizeObserver.disconnect();
}
_ui.globalEvents.off($xeSplit, 'resize');
});
(0, _vue.onActivated)(() => {
recalculate();
});
if (props.items) {
loadItem(props.items);
}
(0, _vue.provide)('$xeSplit', $xeSplit);
$xeSplit.renderVN = renderVN;
return $xeSplit;
},
render() {
return this.renderVN();
}
});