UNPKG

@aplus-frontend/antdv

Version:

Vue basic component library maintained based on ant-design-vue

562 lines (561 loc) 23.2 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.SELECTION_NONE = exports.SELECTION_INVERT = exports.SELECTION_COLUMN = exports.SELECTION_ALL = void 0; exports.default = useSelection; var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2")); var _vue = require("vue"); var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _DownOutlined = _interopRequireDefault(require("@ant-design/icons-vue/lib/icons/DownOutlined")); var _vcTable = require("../../vc-table"); var _util = require("../../vc-tree/util"); var _conductUtil = require("../../vc-tree/utils/conductUtil"); var _treeUtil = require("../../vc-tree/utils/treeUtil"); var _devWarning = _interopRequireDefault(require("../../vc-util/devWarning")); var _useMergedState = _interopRequireDefault(require("../../_util/hooks/useMergedState")); var _useState = _interopRequireDefault(require("../../_util/hooks/useState")); var _checkbox = _interopRequireDefault(require("../../checkbox")); var _dropdown = _interopRequireDefault(require("../../dropdown")); var _menu = _interopRequireDefault(require("../../menu")); var _radio = _interopRequireDefault(require("../../radio")); var _useMaxLevel = _interopRequireDefault(require("../../vc-tree/useMaxLevel")); // TODO: warning if use ajax!!! const SELECTION_COLUMN = exports.SELECTION_COLUMN = {}; const SELECTION_ALL = exports.SELECTION_ALL = 'SELECT_ALL'; const SELECTION_INVERT = exports.SELECTION_INVERT = 'SELECT_INVERT'; const SELECTION_NONE = exports.SELECTION_NONE = 'SELECT_NONE'; const EMPTY_LIST = []; function flattenData(childrenColumnName, data) { let list = []; (data || []).forEach(record => { list.push(record); if (record && typeof record === 'object' && childrenColumnName in record) { list = [...list, ...flattenData(childrenColumnName, record[childrenColumnName])]; } }); return list; } function useSelection(rowSelectionRef, configRef) { const mergedRowSelection = (0, _vue.computed)(() => { const temp = rowSelectionRef.value || {}; const { checkStrictly = true } = temp; return (0, _extends2.default)((0, _extends2.default)({}, temp), { checkStrictly }); }); // ========================= Keys ========================= const [mergedSelectedKeys, setMergedSelectedKeys] = (0, _useMergedState.default)(mergedRowSelection.value.selectedRowKeys || mergedRowSelection.value.defaultSelectedRowKeys || EMPTY_LIST, { value: (0, _vue.computed)(() => mergedRowSelection.value.selectedRowKeys) }); // ======================== Caches ======================== const preserveRecordsRef = (0, _vue.shallowRef)(new Map()); const updatePreserveRecordsCache = keys => { if (mergedRowSelection.value.preserveSelectedRowKeys) { const newCache = new Map(); // Keep key if mark as preserveSelectedRowKeys keys.forEach(key => { let record = configRef.getRecordByKey(key); if (!record && preserveRecordsRef.value.has(key)) { record = preserveRecordsRef.value.get(key); } newCache.set(key, record); }); // Refresh to new cache preserveRecordsRef.value = newCache; } }; (0, _vue.watchEffect)(() => { updatePreserveRecordsCache(mergedSelectedKeys.value); }); const keyEntities = (0, _vue.computed)(() => mergedRowSelection.value.checkStrictly ? null : (0, _treeUtil.convertDataToEntities)(configRef.data.value, { externalGetKey: configRef.getRowKey.value, childrenPropName: configRef.childrenColumnName.value }).keyEntities); // Get flatten data const flattedData = (0, _vue.computed)(() => flattenData(configRef.childrenColumnName.value, configRef.pageData.value)); // Get all checkbox props const checkboxPropsMap = (0, _vue.computed)(() => { const map = new Map(); const getRowKey = configRef.getRowKey.value; const getCheckboxProps = mergedRowSelection.value.getCheckboxProps; flattedData.value.forEach((record, index) => { const key = getRowKey(record, index); const checkboxProps = (getCheckboxProps ? getCheckboxProps(record) : null) || {}; map.set(key, checkboxProps); if (process.env.NODE_ENV !== 'production' && ('checked' in checkboxProps || 'defaultChecked' in checkboxProps)) { (0, _devWarning.default)(false, 'Table', 'Do not set `checked` or `defaultChecked` in `getCheckboxProps`. Please use `selectedRowKeys` instead.'); } }); return map; }); const { maxLevel, levelEntities } = (0, _useMaxLevel.default)(keyEntities); const isCheckboxDisabled = r => { var _a; return !!((_a = checkboxPropsMap.value.get(configRef.getRowKey.value(r))) === null || _a === void 0 ? void 0 : _a.disabled); }; const selectKeysState = (0, _vue.computed)(() => { if (mergedRowSelection.value.checkStrictly) { return [mergedSelectedKeys.value || [], []]; } const { checkedKeys, halfCheckedKeys } = (0, _conductUtil.conductCheck)(mergedSelectedKeys.value, true, keyEntities.value, maxLevel.value, levelEntities.value, isCheckboxDisabled); return [checkedKeys || [], halfCheckedKeys]; }); const derivedSelectedKeys = (0, _vue.computed)(() => selectKeysState.value[0]); const derivedHalfSelectedKeys = (0, _vue.computed)(() => selectKeysState.value[1]); const derivedSelectedKeySet = (0, _vue.computed)(() => { const keys = mergedRowSelection.value.type === 'radio' ? derivedSelectedKeys.value.slice(0, 1) : derivedSelectedKeys.value; return new Set(keys); }); const derivedHalfSelectedKeySet = (0, _vue.computed)(() => mergedRowSelection.value.type === 'radio' ? new Set() : new Set(derivedHalfSelectedKeys.value)); // Save last selected key to enable range selection const [lastSelectedKey, setLastSelectedKey] = (0, _useState.default)(null); // // Reset if rowSelection reset // we use computed to reset, donot need setMergedSelectedKeys again like react // https://github.com/vueComponent/ant-design-vue/issues/4885 // watchEffect(() => { // if (!rowSelectionRef.value) { // setMergedSelectedKeys([]); // } // }); const setSelectedKeys = keys => { let availableKeys; let records; updatePreserveRecordsCache(keys); const { preserveSelectedRowKeys, onChange: onSelectionChange } = mergedRowSelection.value; const { getRecordByKey } = configRef; if (preserveSelectedRowKeys) { availableKeys = keys; records = keys.map(key => preserveRecordsRef.value.get(key)); } else { // Filter key which not exist in the `dataSource` availableKeys = []; records = []; keys.forEach(key => { const record = getRecordByKey(key); if (record !== undefined) { availableKeys.push(key); records.push(record); } }); } setMergedSelectedKeys(availableKeys); onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(availableKeys, records); }; // ====================== Selections ====================== // Trigger single `onSelect` event const triggerSingleSelection = (key, selected, keys, event) => { const { onSelect } = mergedRowSelection.value; const { getRecordByKey } = configRef || {}; if (onSelect) { const rows = keys.map(k => getRecordByKey(k)); onSelect(getRecordByKey(key), selected, rows, event); } setSelectedKeys(keys); }; const mergedSelections = (0, _vue.computed)(() => { const { onSelectInvert, onSelectNone, selections, hideSelectAll } = mergedRowSelection.value; const { data, pageData, getRowKey, locale: tableLocale } = configRef; if (!selections || hideSelectAll) { return null; } const selectionList = selections === true ? [SELECTION_ALL, SELECTION_INVERT, SELECTION_NONE] : selections; return selectionList.map(selection => { if (selection === SELECTION_ALL) { return { key: 'all', text: tableLocale.value.selectionAll, onSelect() { setSelectedKeys(data.value.map((record, index) => getRowKey.value(record, index)).filter(key => { const checkProps = checkboxPropsMap.value.get(key); return !(checkProps === null || checkProps === void 0 ? void 0 : checkProps.disabled) || derivedSelectedKeySet.value.has(key); })); } }; } if (selection === SELECTION_INVERT) { return { key: 'invert', text: tableLocale.value.selectInvert, onSelect() { const keySet = new Set(derivedSelectedKeySet.value); pageData.value.forEach((record, index) => { const key = getRowKey.value(record, index); const checkProps = checkboxPropsMap.value.get(key); if (!(checkProps === null || checkProps === void 0 ? void 0 : checkProps.disabled)) { if (keySet.has(key)) { keySet.delete(key); } else { keySet.add(key); } } }); const keys = Array.from(keySet); if (onSelectInvert) { (0, _devWarning.default)(false, 'Table', '`onSelectInvert` will be removed in future. Please use `onChange` instead.'); onSelectInvert(keys); } setSelectedKeys(keys); } }; } if (selection === SELECTION_NONE) { return { key: 'none', text: tableLocale.value.selectNone, onSelect() { onSelectNone === null || onSelectNone === void 0 ? void 0 : onSelectNone(); setSelectedKeys(Array.from(derivedSelectedKeySet.value).filter(key => { const checkProps = checkboxPropsMap.value.get(key); return checkProps === null || checkProps === void 0 ? void 0 : checkProps.disabled; })); } }; } return selection; }); }); const flattedDataLength = (0, _vue.computed)(() => flattedData.value.length); // ======================= Columns ======================== const transformColumns = columns => { var _a; const { onSelectAll, onSelectMultiple, columnWidth: selectionColWidth, type: selectionType, fixed, renderCell: customizeRenderCell, hideSelectAll, checkStrictly } = mergedRowSelection.value; const { prefixCls, getRecordByKey, getRowKey, expandType, getPopupContainer } = configRef; if (!rowSelectionRef.value) { if (process.env.NODE_ENV !== 'production') { (0, _devWarning.default)(!columns.includes(SELECTION_COLUMN), 'Table', '`rowSelection` is not config but `SELECTION_COLUMN` exists in the `columns`.'); } return columns.filter(col => col !== SELECTION_COLUMN); } // Support selection let cloneColumns = columns.slice(); const keySet = new Set(derivedSelectedKeySet.value); // Record key only need check with enabled const recordKeys = flattedData.value.map(getRowKey.value).filter(key => !checkboxPropsMap.value.get(key).disabled); const checkedCurrentAll = recordKeys.every(key => keySet.has(key)); const checkedCurrentSome = recordKeys.some(key => keySet.has(key)); const onSelectAllChange = () => { const changeKeys = []; if (checkedCurrentAll) { recordKeys.forEach(key => { keySet.delete(key); changeKeys.push(key); }); } else { recordKeys.forEach(key => { if (!keySet.has(key)) { keySet.add(key); changeKeys.push(key); } }); } const keys = Array.from(keySet); onSelectAll === null || onSelectAll === void 0 ? void 0 : onSelectAll(!checkedCurrentAll, keys.map(k => getRecordByKey(k)), changeKeys.map(k => getRecordByKey(k))); setSelectedKeys(keys); }; // ===================== Render ===================== // Title Cell let title; if (selectionType !== 'radio') { let customizeSelections; if (mergedSelections.value) { const menu = (0, _vue.createVNode)(_menu.default, { "getPopupContainer": getPopupContainer.value }, { default: () => [mergedSelections.value.map((selection, index) => { const { key, text, onSelect: onSelectionClick } = selection; return (0, _vue.createVNode)(_menu.default.Item, { "key": key || index, "onClick": () => { onSelectionClick === null || onSelectionClick === void 0 ? void 0 : onSelectionClick(recordKeys); } }, { default: () => [text] }); })] }); customizeSelections = (0, _vue.createVNode)("div", { "class": `${prefixCls.value}-selection-extra` }, [(0, _vue.createVNode)(_dropdown.default, { "overlay": menu, "getPopupContainer": getPopupContainer.value }, { default: () => [(0, _vue.createVNode)("span", null, [(0, _vue.createVNode)(_DownOutlined.default, null, null)])] })]); } const allDisabledData = flattedData.value.map((record, index) => { const key = getRowKey.value(record, index); const checkboxProps = checkboxPropsMap.value.get(key) || {}; return (0, _extends2.default)({ checked: keySet.has(key) }, checkboxProps); }).filter(_ref => { let { disabled } = _ref; return disabled; }); const allDisabled = !!allDisabledData.length && allDisabledData.length === flattedDataLength.value; const allDisabledAndChecked = allDisabled && allDisabledData.every(_ref2 => { let { checked } = _ref2; return checked; }); const allDisabledSomeChecked = allDisabled && allDisabledData.some(_ref3 => { let { checked } = _ref3; return checked; }); title = !hideSelectAll && (0, _vue.createVNode)("div", { "class": `${prefixCls.value}-selection` }, [(0, _vue.createVNode)(_checkbox.default, { "checked": !allDisabled ? !!flattedDataLength.value && checkedCurrentAll : allDisabledAndChecked, "indeterminate": !allDisabled ? !checkedCurrentAll && checkedCurrentSome : !allDisabledAndChecked && allDisabledSomeChecked, "onChange": onSelectAllChange, "disabled": flattedDataLength.value === 0 || allDisabled, "aria-label": customizeSelections ? 'Custom selection' : 'Select all', "skipGroup": true }, null), customizeSelections]); } // Body Cell let renderCell; if (selectionType === 'radio') { renderCell = _ref4 => { let { record, index } = _ref4; const key = getRowKey.value(record, index); const checked = keySet.has(key); return { node: (0, _vue.createVNode)(_radio.default, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, checkboxPropsMap.value.get(key)), {}, { "checked": checked, "onClick": e => e.stopPropagation(), "onChange": event => { if (!keySet.has(key)) { triggerSingleSelection(key, true, [key], event.nativeEvent); } } }), null), checked }; }; } else { renderCell = _ref5 => { let { record, index } = _ref5; var _a; const key = getRowKey.value(record, index); const checked = keySet.has(key); const indeterminate = derivedHalfSelectedKeySet.value.has(key); const checkboxProps = checkboxPropsMap.value.get(key); let mergedIndeterminate; if (expandType.value === 'nest') { mergedIndeterminate = indeterminate; (0, _devWarning.default)(typeof (checkboxProps === null || checkboxProps === void 0 ? void 0 : checkboxProps.indeterminate) !== 'boolean', 'Table', 'set `indeterminate` using `rowSelection.getCheckboxProps` is not allowed with tree structured dataSource.'); } else { mergedIndeterminate = (_a = checkboxProps === null || checkboxProps === void 0 ? void 0 : checkboxProps.indeterminate) !== null && _a !== void 0 ? _a : indeterminate; } // Record checked return { node: (0, _vue.createVNode)(_checkbox.default, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, checkboxProps), {}, { "indeterminate": mergedIndeterminate, "checked": checked, "skipGroup": true, "onClick": e => e.stopPropagation(), "onChange": _ref6 => { let { nativeEvent } = _ref6; const { shiftKey } = nativeEvent; let startIndex = -1; let endIndex = -1; // Get range of this if (shiftKey && checkStrictly) { const pointKeys = new Set([lastSelectedKey.value, key]); recordKeys.some((recordKey, recordIndex) => { if (pointKeys.has(recordKey)) { if (startIndex === -1) { startIndex = recordIndex; } else { endIndex = recordIndex; return true; } } return false; }); } if (endIndex !== -1 && startIndex !== endIndex && checkStrictly) { // Batch update selections const rangeKeys = recordKeys.slice(startIndex, endIndex + 1); const changedKeys = []; if (checked) { rangeKeys.forEach(recordKey => { if (keySet.has(recordKey)) { changedKeys.push(recordKey); keySet.delete(recordKey); } }); } else { rangeKeys.forEach(recordKey => { if (!keySet.has(recordKey)) { changedKeys.push(recordKey); keySet.add(recordKey); } }); } const keys = Array.from(keySet); onSelectMultiple === null || onSelectMultiple === void 0 ? void 0 : onSelectMultiple(!checked, keys.map(recordKey => getRecordByKey(recordKey)), changedKeys.map(recordKey => getRecordByKey(recordKey))); setSelectedKeys(keys); } else { // Single record selected const originCheckedKeys = derivedSelectedKeys.value; if (checkStrictly) { const checkedKeys = checked ? (0, _util.arrDel)(originCheckedKeys, key) : (0, _util.arrAdd)(originCheckedKeys, key); triggerSingleSelection(key, !checked, checkedKeys, nativeEvent); } else { // Always fill first const result = (0, _conductUtil.conductCheck)([...originCheckedKeys, key], true, keyEntities.value, maxLevel.value, levelEntities.value, isCheckboxDisabled); const { checkedKeys, halfCheckedKeys } = result; let nextCheckedKeys = checkedKeys; // If remove, we do it again to correction if (checked) { const tempKeySet = new Set(checkedKeys); tempKeySet.delete(key); nextCheckedKeys = (0, _conductUtil.conductCheck)(Array.from(tempKeySet), { checked: false, halfCheckedKeys }, keyEntities.value, maxLevel.value, levelEntities.value, isCheckboxDisabled).checkedKeys; } triggerSingleSelection(key, !checked, nextCheckedKeys, nativeEvent); } } setLastSelectedKey(key); } }), null), checked }; }; } const renderSelectionCell = _ref7 => { let { record, index } = _ref7; const { node, checked } = renderCell({ record, index }); if (customizeRenderCell) { return customizeRenderCell(checked, record, index, node); } return node; }; // Insert selection column if not exist if (!cloneColumns.includes(SELECTION_COLUMN)) { // Always after expand icon if (cloneColumns.findIndex(col => { var _a; return ((_a = col[_vcTable.INTERNAL_COL_DEFINE]) === null || _a === void 0 ? void 0 : _a.columnType) === 'EXPAND_COLUMN'; }) === 0) { const [expandColumn, ...restColumns] = cloneColumns; cloneColumns = [expandColumn, SELECTION_COLUMN, ...restColumns]; } else { // Normal insert at first column cloneColumns = [SELECTION_COLUMN, ...cloneColumns]; } } // Deduplicate selection column const selectionColumnIndex = cloneColumns.indexOf(SELECTION_COLUMN); if (process.env.NODE_ENV !== 'production' && cloneColumns.filter(col => col === SELECTION_COLUMN).length > 1) { (0, _devWarning.default)(false, 'Table', 'Multiple `SELECTION_COLUMN` exist in `columns`.'); } cloneColumns = cloneColumns.filter((column, index) => column !== SELECTION_COLUMN || index === selectionColumnIndex); // Fixed column logic const prevCol = cloneColumns[selectionColumnIndex - 1]; const nextCol = cloneColumns[selectionColumnIndex + 1]; let mergedFixed = fixed; if (mergedFixed === undefined) { if ((nextCol === null || nextCol === void 0 ? void 0 : nextCol.fixed) !== undefined) { mergedFixed = nextCol.fixed; } else if ((prevCol === null || prevCol === void 0 ? void 0 : prevCol.fixed) !== undefined) { mergedFixed = prevCol.fixed; } } if (mergedFixed && prevCol && ((_a = prevCol[_vcTable.INTERNAL_COL_DEFINE]) === null || _a === void 0 ? void 0 : _a.columnType) === 'EXPAND_COLUMN' && prevCol.fixed === undefined) { prevCol.fixed = mergedFixed; } // Replace with real selection column const selectionColumn = { fixed: mergedFixed, width: selectionColWidth, className: `${prefixCls.value}-selection-column`, title: mergedRowSelection.value.columnTitle || title, customRender: renderSelectionCell, [_vcTable.INTERNAL_COL_DEFINE]: { class: `${prefixCls.value}-selection-col` } }; return cloneColumns.map(col => col === SELECTION_COLUMN ? selectionColumn : col); }; return [transformColumns, derivedSelectedKeySet]; }