UNPKG

vxe-pc-ui

Version:
682 lines (681 loc) 22.4 kB
"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(); } });