UNPKG

element-plus

Version:

A Component Library for Vue3.0

576 lines (554 loc) 21.9 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var vue = require('vue'); var locale = require('../locale'); var ElButton = require('../el-button'); var ElCheckbox = require('../el-checkbox'); var ElCheckboxGroup = require('../el-checkbox-group'); var ElInput = require('../el-input'); var constants = require('../utils/constants'); var form = require('../el-form'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var ElButton__default = /*#__PURE__*/_interopDefaultLegacy(ElButton); var ElCheckbox__default = /*#__PURE__*/_interopDefaultLegacy(ElCheckbox); var ElCheckboxGroup__default = /*#__PURE__*/_interopDefaultLegacy(ElCheckboxGroup); var ElInput__default = /*#__PURE__*/_interopDefaultLegacy(ElInput); const CHECKED_CHANGE_EVENT = 'checked-change'; const useCheck = (props, panelState, emit) => { const labelProp = vue.computed(() => props.props.label || 'label'); const keyProp = vue.computed(() => props.props.key || 'key'); const disabledProp = vue.computed(() => props.props.disabled || 'disabled'); const filteredData = vue.computed(() => { return props.data.filter(item => { if (typeof props.filterMethod === 'function') { return props.filterMethod(panelState.query, item); } else { const label = item[labelProp.value] || item[keyProp.value].toString(); return label.toLowerCase().includes(panelState.query.toLowerCase()); } }); }); const checkableData = vue.computed(() => { return filteredData.value.filter(item => !item[disabledProp.value]); }); const checkedSummary = vue.computed(() => { const checkedLength = panelState.checked.length; const dataLength = props.data.length; const { noChecked, hasChecked } = props.format; if (noChecked && hasChecked) { return checkedLength > 0 ? hasChecked .replace(/\${checked}/g, checkedLength.toString()) .replace(/\${total}/g, dataLength.toString()) : noChecked.replace(/\${total}/g, dataLength.toString()); } else { return `${checkedLength}/${dataLength}`; } }); const isIndeterminate = vue.computed(() => { const checkedLength = panelState.checked.length; return checkedLength > 0 && checkedLength < checkableData.value.length; }); const updateAllChecked = () => { const checkableDataKeys = checkableData.value.map(item => item[keyProp.value]); panelState.allChecked = checkableDataKeys.length > 0 && checkableDataKeys.every(item => panelState.checked.includes(item)); }; const handleAllCheckedChange = (value) => { panelState.checked = value ? checkableData.value.map(item => item[keyProp.value]) : []; }; vue.watch(() => panelState.checked, (val, oldVal) => { updateAllChecked(); if (panelState.checkChangeByUser) { const movedKeys = val .concat(oldVal) .filter(v => !val.includes(v) || !oldVal.includes(v)); emit(CHECKED_CHANGE_EVENT, val, movedKeys); } else { emit(CHECKED_CHANGE_EVENT, val); panelState.checkChangeByUser = true; } }); vue.watch(checkableData, () => { updateAllChecked(); }); vue.watch(() => props.data, () => { const checked = []; const filteredDataKeys = filteredData.value.map(item => item[keyProp.value]); panelState.checked.forEach(item => { if (filteredDataKeys.includes(item)) { checked.push(item); } }); panelState.checkChangeByUser = false; panelState.checked = checked; }); vue.watch(() => props.defaultChecked, (val, oldVal) => { if (oldVal && val.length === oldVal.length && val.every(item => oldVal.includes(item))) return; const checked = []; const checkableDataKeys = checkableData.value.map(item => item[keyProp.value]); val.forEach(item => { if (checkableDataKeys.includes(item)) { checked.push(item); } }); panelState.checkChangeByUser = false; panelState.checked = checked; }, { immediate: true, }); return { labelProp, keyProp, disabledProp, filteredData, checkableData, checkedSummary, isIndeterminate, updateAllChecked, handleAllCheckedChange, }; }; var script = vue.defineComponent({ name: 'ElTransferPanel', components: { ElCheckboxGroup: ElCheckboxGroup__default['default'], ElCheckbox: ElCheckbox__default['default'], ElInput: ElInput__default['default'], OptionContent: ({ option }) => option, }, props: { data: { type: Array, default() { return []; }, }, optionRender: Function, placeholder: String, title: String, filterable: Boolean, format: Object, filterMethod: Function, defaultChecked: Array, props: Object, }, emits: [CHECKED_CHANGE_EVENT], setup(props, { emit, slots }) { const panelState = vue.reactive({ checked: [], allChecked: false, query: '', inputHover: false, checkChangeByUser: true, }); const { labelProp, keyProp, disabledProp, filteredData, checkedSummary, isIndeterminate, handleAllCheckedChange, } = useCheck(props, panelState, emit); const hasNoMatch = vue.computed(() => { return panelState.query.length > 0 && filteredData.value.length === 0; }); const inputIcon = vue.computed(() => { return panelState.query.length > 0 && panelState.inputHover ? 'circle-close' : 'search'; }); const hasFooter = vue.computed(() => !!slots.default()[0].children.length); const clearQuery = () => { if (inputIcon.value === 'circle-close') { panelState.query = ''; } }; const { checked, allChecked, query, inputHover, checkChangeByUser, } = vue.toRefs(panelState); return { labelProp, keyProp, disabledProp, filteredData, checkedSummary, isIndeterminate, handleAllCheckedChange, checked, allChecked, query, inputHover, checkChangeByUser, hasNoMatch, inputIcon, hasFooter, clearQuery, t: locale.t, }; }, }); const _hoisted_1 = { class: "el-transfer-panel" }; const _hoisted_2 = { class: "el-transfer-panel__header" }; const _hoisted_3 = { key: 0, class: "el-transfer-panel__footer" }; function render(_ctx, _cache, $props, $setup, $data, $options) { const _component_el_checkbox = vue.resolveComponent("el-checkbox"); const _component_el_input = vue.resolveComponent("el-input"); const _component_option_content = vue.resolveComponent("option-content"); const _component_el_checkbox_group = vue.resolveComponent("el-checkbox-group"); return (vue.openBlock(), vue.createBlock("div", _hoisted_1, [ vue.createVNode("p", _hoisted_2, [ vue.createVNode(_component_el_checkbox, { modelValue: _ctx.allChecked, "onUpdate:modelValue": _cache[1] || (_cache[1] = $event => (_ctx.allChecked = $event)), indeterminate: _ctx.isIndeterminate, onChange: _ctx.handleAllCheckedChange }, { default: vue.withCtx(() => [ vue.createTextVNode(vue.toDisplayString(_ctx.title) + " ", 1 /* TEXT */), vue.createVNode("span", null, vue.toDisplayString(_ctx.checkedSummary), 1 /* TEXT */) ]), _: 1 /* STABLE */ }, 8 /* PROPS */, ["modelValue", "indeterminate", "onChange"]) ]), vue.createVNode("div", { class: ['el-transfer-panel__body', _ctx.hasFooter ? 'is-with-footer' : ''] }, [ (_ctx.filterable) ? (vue.openBlock(), vue.createBlock(_component_el_input, { key: 0, modelValue: _ctx.query, "onUpdate:modelValue": _cache[3] || (_cache[3] = $event => (_ctx.query = $event)), class: "el-transfer-panel__filter", size: "small", placeholder: _ctx.placeholder, onMouseenter: _cache[4] || (_cache[4] = $event => (_ctx.inputHover = true)), onMouseleave: _cache[5] || (_cache[5] = $event => (_ctx.inputHover = false)) }, { prefix: vue.withCtx(() => [ vue.createVNode("i", { class: ['el-input__icon', 'el-icon-' + _ctx.inputIcon], onClick: _cache[2] || (_cache[2] = (...args) => (_ctx.clearQuery && _ctx.clearQuery(...args))) }, null, 2 /* CLASS */) ]), _: 1 /* STABLE */ }, 8 /* PROPS */, ["modelValue", "placeholder"])) : vue.createCommentVNode("v-if", true), vue.withDirectives(vue.createVNode(_component_el_checkbox_group, { modelValue: _ctx.checked, "onUpdate:modelValue": _cache[6] || (_cache[6] = $event => (_ctx.checked = $event)), class: [{ 'is-filterable': _ctx.filterable }, "el-transfer-panel__list"] }, { default: vue.withCtx(() => [ (vue.openBlock(true), vue.createBlock(vue.Fragment, null, vue.renderList(_ctx.filteredData, (item) => { return (vue.openBlock(), vue.createBlock(_component_el_checkbox, { key: item[_ctx.keyProp], class: "el-transfer-panel__item", label: item[_ctx.keyProp], disabled: item[_ctx.disabledProp] }, { default: vue.withCtx(() => [ vue.createVNode(_component_option_content, { option: _ctx.optionRender(item) }, null, 8 /* PROPS */, ["option"]) ]), _: 2 /* DYNAMIC */ }, 1032 /* PROPS, DYNAMIC_SLOTS */, ["label", "disabled"])) }), 128 /* KEYED_FRAGMENT */)) ]), _: 1 /* STABLE */ }, 8 /* PROPS */, ["modelValue", "class"]), [ [vue.vShow, !_ctx.hasNoMatch && _ctx.data.length > 0] ]), vue.withDirectives(vue.createVNode("p", { class: "el-transfer-panel__empty" }, vue.toDisplayString(_ctx.hasNoMatch ? _ctx.t('el.transfer.noMatch') : _ctx.t('el.transfer.noData')), 513 /* TEXT, NEED_PATCH */), [ [vue.vShow, _ctx.hasNoMatch || _ctx.data.length === 0] ]) ], 2 /* CLASS */), (_ctx.hasFooter) ? (vue.openBlock(), vue.createBlock("p", _hoisted_3, [ vue.renderSlot(_ctx.$slots, "default") ])) : vue.createCommentVNode("v-if", true) ])) } script.render = render; script.__file = "packages/transfer/src/transfer-panel.vue"; const useComputedData = (props) => { const propsKey = vue.computed(() => props.props.key); const dataObj = vue.computed(() => { return props.data.reduce((o, cur) => (o[cur[propsKey.value]] = cur) && o, {}); }); const sourceData = vue.computed(() => { return props.data.filter(item => !props.modelValue.includes(item[propsKey.value])); }); const targetData = vue.computed(() => { if (props.targetOrder === 'original') { return props.data.filter(item => props.modelValue.includes(item[propsKey.value])); } else { return props.modelValue.reduce((arr, cur) => { const val = dataObj.value[cur]; if (val) { arr.push(val); } return arr; }, []); } }); return { propsKey, sourceData, targetData, }; }; const LEFT_CHECK_CHANGE_EVENT = 'left-check-change'; const RIGHT_CHECK_CHANGE_EVENT = 'right-check-change'; const useCheckedChange = (checkedState, emit) => { const onSourceCheckedChange = (val, movedKeys) => { checkedState.leftChecked = val; if (movedKeys === undefined) return; emit(LEFT_CHECK_CHANGE_EVENT, val, movedKeys); }; const onTargetCheckedChange = (val, movedKeys) => { checkedState.rightChecked = val; if (movedKeys === undefined) return; emit(RIGHT_CHECK_CHANGE_EVENT, val, movedKeys); }; return { onSourceCheckedChange, onTargetCheckedChange, }; }; const UPDATE_MODEL_EVENT = 'update:modelValue'; const useMove = (props, checkedState, propsKey, emit) => { const _emit = (value, type, checked) => { emit(UPDATE_MODEL_EVENT, value); emit(CHANGE_EVENT, value, type, checked); }; const addToLeft = () => { const currentValue = props.modelValue.slice(); checkedState.rightChecked.forEach(item => { const index = currentValue.indexOf(item); if (index > -1) { currentValue.splice(index, 1); } }); _emit(currentValue, 'left', checkedState.rightChecked); }; const addToRight = () => { let currentValue = props.modelValue.slice(); const itemsToBeMoved = props.data .filter((item) => { const itemKey = item[propsKey.value]; return checkedState.leftChecked.includes(itemKey) && !props.modelValue.includes(itemKey); }) .map(item => item[propsKey.value]); currentValue = props.targetOrder === 'unshift' ? itemsToBeMoved.concat(currentValue) : currentValue.concat(itemsToBeMoved); _emit(currentValue, 'right', checkedState.leftChecked); }; return { addToLeft, addToRight, }; }; const CHANGE_EVENT = 'change'; var script$1 = vue.defineComponent({ name: 'ElTransfer', components: { TransferPanel: script, ElButton: ElButton__default['default'], }, props: { data: { type: Array, default: () => [], }, titles: { type: Array, default: () => [], }, buttonTexts: { type: Array, default: () => [], }, filterPlaceholder: { type: String, default: '', }, filterMethod: Function, leftDefaultChecked: { type: Array, default: () => [], }, rightDefaultChecked: { type: Array, default: () => [], }, renderContent: Function, modelValue: { type: Array, default: () => [], }, format: { type: Object, default: () => ({}), }, filterable: { type: Boolean, default: false, }, props: { type: Object, default: () => ({ label: 'label', key: 'key', disabled: 'disabled', }), }, targetOrder: { type: String, default: 'original', validator: (val) => { return ['original', 'push', 'unshift'].includes(val); }, }, }, emits: [ constants.UPDATE_MODEL_EVENT, CHANGE_EVENT, LEFT_CHECK_CHANGE_EVENT, RIGHT_CHECK_CHANGE_EVENT, ], setup(props, { emit, slots }) { const elFormItem = vue.inject(form.elFormItemKey, {}); const checkedState = vue.reactive({ leftChecked: [], rightChecked: [], }); const { propsKey, sourceData, targetData, } = useComputedData(props); const { onSourceCheckedChange, onTargetCheckedChange, } = useCheckedChange(checkedState, emit); const { addToLeft, addToRight, } = useMove(props, checkedState, propsKey, emit); const leftPanel = vue.ref(null); const rightPanel = vue.ref(null); const clearQuery = (which) => { if (which === 'left') { leftPanel.value.query = ''; } else if (which === 'right') { rightPanel.value.query = ''; } }; const hasButtonTexts = vue.computed(() => props.buttonTexts.length === 2); const leftPanelTitle = vue.computed(() => props.titles[0] || locale.t('el.transfer.titles.0')); const rightPanelTitle = vue.computed(() => props.titles[1] || locale.t('el.transfer.titles.1')); const panelFilterPlaceholder = vue.computed(() => props.filterPlaceholder || locale.t('el.transfer.filterPlaceholder')); vue.watch(() => props.modelValue, val => { var _a; (_a = elFormItem.formItemMitt) === null || _a === void 0 ? void 0 : _a.emit('el.form.change', val); }); const optionRender = vue.computed(() => option => { if (props.renderContent) return props.renderContent(vue.h, option); if (slots.default) return slots.default({ option }); return vue.h('span', option[props.props.label] || option[props.props.key]); }); return Object.assign(Object.assign({ sourceData, targetData, onSourceCheckedChange, onTargetCheckedChange, addToLeft, addToRight }, vue.toRefs(checkedState)), { hasButtonTexts, leftPanelTitle, rightPanelTitle, panelFilterPlaceholder, clearQuery, optionRender }); }, }); const _hoisted_1$1 = { class: "el-transfer" }; const _hoisted_2$1 = { class: "el-transfer__buttons" }; const _hoisted_3$1 = /*#__PURE__*/vue.createVNode("i", { class: "el-icon-arrow-left" }, null, -1 /* HOISTED */); const _hoisted_4 = { key: 0 }; const _hoisted_5 = { key: 0 }; const _hoisted_6 = /*#__PURE__*/vue.createVNode("i", { class: "el-icon-arrow-right" }, null, -1 /* HOISTED */); function render$1(_ctx, _cache, $props, $setup, $data, $options) { const _component_transfer_panel = vue.resolveComponent("transfer-panel"); const _component_el_button = vue.resolveComponent("el-button"); return (vue.openBlock(), vue.createBlock("div", _hoisted_1$1, [ vue.createVNode(_component_transfer_panel, { ref: "leftPanel", data: _ctx.sourceData, "option-render": _ctx.optionRender, placeholder: _ctx.panelFilterPlaceholder, title: _ctx.leftPanelTitle, filterable: _ctx.filterable, format: _ctx.format, "filter-method": _ctx.filterMethod, "default-checked": _ctx.leftDefaultChecked, props: _ctx.props, onCheckedChange: _ctx.onSourceCheckedChange }, { default: vue.withCtx(() => [ vue.renderSlot(_ctx.$slots, "left-footer") ]), _: 3 /* FORWARDED */ }, 8 /* PROPS */, ["data", "option-render", "placeholder", "title", "filterable", "format", "filter-method", "default-checked", "props", "onCheckedChange"]), vue.createVNode("div", _hoisted_2$1, [ vue.createVNode(_component_el_button, { type: "primary", class: ['el-transfer__button', _ctx.hasButtonTexts ? 'is-with-texts' : ''], disabled: _ctx.rightChecked.length === 0, onClick: _ctx.addToLeft }, { default: vue.withCtx(() => [ _hoisted_3$1, (_ctx.buttonTexts[0] !== undefined) ? (vue.openBlock(), vue.createBlock("span", _hoisted_4, vue.toDisplayString(_ctx.buttonTexts[0]), 1 /* TEXT */)) : vue.createCommentVNode("v-if", true) ]), _: 1 /* STABLE */ }, 8 /* PROPS */, ["class", "disabled", "onClick"]), vue.createVNode(_component_el_button, { type: "primary", class: ['el-transfer__button', _ctx.hasButtonTexts ? 'is-with-texts' : ''], disabled: _ctx.leftChecked.length === 0, onClick: _ctx.addToRight }, { default: vue.withCtx(() => [ (_ctx.buttonTexts[1] !== undefined) ? (vue.openBlock(), vue.createBlock("span", _hoisted_5, vue.toDisplayString(_ctx.buttonTexts[1]), 1 /* TEXT */)) : vue.createCommentVNode("v-if", true), _hoisted_6 ]), _: 1 /* STABLE */ }, 8 /* PROPS */, ["class", "disabled", "onClick"]) ]), vue.createVNode(_component_transfer_panel, { ref: "rightPanel", data: _ctx.targetData, "option-render": _ctx.optionRender, placeholder: _ctx.panelFilterPlaceholder, filterable: _ctx.filterable, format: _ctx.format, "filter-method": _ctx.filterMethod, title: _ctx.rightPanelTitle, "default-checked": _ctx.rightDefaultChecked, props: _ctx.props, onCheckedChange: _ctx.onTargetCheckedChange }, { default: vue.withCtx(() => [ vue.renderSlot(_ctx.$slots, "right-footer") ]), _: 3 /* FORWARDED */ }, 8 /* PROPS */, ["data", "option-render", "placeholder", "filterable", "format", "filter-method", "title", "default-checked", "props", "onCheckedChange"]) ])) } script$1.render = render$1; script$1.__file = "packages/transfer/src/index.vue"; script$1.install = (app) => { app.component(script$1.name, script$1); }; const _Transfer = script$1; exports.default = _Transfer;