501 lines
14 KiB
JavaScript
501 lines
14 KiB
JavaScript
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.findPopupContainer = findPopupContainer;
|
|
exports.toTitle = toTitle;
|
|
exports.toArray = toArray;
|
|
exports.createRef = createRef;
|
|
exports.flatToHierarchy = flatToHierarchy;
|
|
exports.resetAriaId = resetAriaId;
|
|
exports.generateAriaId = generateAriaId;
|
|
exports.isLabelInValue = isLabelInValue;
|
|
exports.parseSimpleTreeData = parseSimpleTreeData;
|
|
exports.isPosRelated = isPosRelated;
|
|
exports.cleanEntity = cleanEntity;
|
|
exports.getFilterTree = getFilterTree;
|
|
exports.formatInternalValue = formatInternalValue;
|
|
exports.getLabel = getLabel;
|
|
exports.formatSelectorValue = formatSelectorValue;
|
|
exports.convertDataToTree = convertDataToTree;
|
|
exports.convertTreeToEntities = convertTreeToEntities;
|
|
exports.getHalfCheckedKeys = getHalfCheckedKeys;
|
|
exports.conductCheck = exports.UNSELECTABLE_ATTRIBUTE = exports.UNSELECTABLE_STYLE = void 0;
|
|
|
|
var _react = _interopRequireDefault(require("react"));
|
|
|
|
var _warning = _interopRequireDefault(require("warning"));
|
|
|
|
var _util = require("rc-tree/lib/util");
|
|
|
|
var _toArray = _interopRequireDefault(require("rc-util/lib/Children/toArray"));
|
|
|
|
var _class = require("rc-util/lib/Dom/class");
|
|
|
|
var _strategies = require("./strategies");
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
|
|
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
|
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
|
|
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
|
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
|
|
var warnDeprecatedLabel = false; // =================== DOM =====================
|
|
|
|
function findPopupContainer(node, prefixClass) {
|
|
var current = node;
|
|
|
|
while (current) {
|
|
if ((0, _class.hasClass)(current, prefixClass)) {
|
|
return current;
|
|
}
|
|
|
|
current = current.parentNode;
|
|
}
|
|
|
|
return null;
|
|
} // =================== MISC ====================
|
|
|
|
|
|
function toTitle(title) {
|
|
if (typeof title === 'string') {
|
|
return title;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function toArray(data) {
|
|
if (data === undefined || data === null) return [];
|
|
return Array.isArray(data) ? data : [data];
|
|
} // Shallow copy of React 16.3 createRef api
|
|
|
|
|
|
function createRef() {
|
|
var func = function setRef(node) {
|
|
func.current = node;
|
|
};
|
|
|
|
return func;
|
|
} // =============== Legacy ===============
|
|
|
|
|
|
var UNSELECTABLE_STYLE = {
|
|
userSelect: 'none',
|
|
WebkitUserSelect: 'none'
|
|
};
|
|
exports.UNSELECTABLE_STYLE = UNSELECTABLE_STYLE;
|
|
var UNSELECTABLE_ATTRIBUTE = {
|
|
unselectable: 'unselectable'
|
|
};
|
|
/**
|
|
* Convert position list to hierarchy structure.
|
|
* This is little hack since use '-' to split the position.
|
|
*/
|
|
|
|
exports.UNSELECTABLE_ATTRIBUTE = UNSELECTABLE_ATTRIBUTE;
|
|
|
|
function flatToHierarchy(positionList) {
|
|
if (!positionList.length) {
|
|
return [];
|
|
}
|
|
|
|
var entrances = {}; // Prepare the position map
|
|
|
|
var posMap = {};
|
|
var parsedList = positionList.slice().map(function (entity) {
|
|
var clone = _objectSpread({}, entity, {
|
|
fields: entity.pos.split('-')
|
|
});
|
|
|
|
delete clone.children;
|
|
return clone;
|
|
});
|
|
parsedList.forEach(function (entity) {
|
|
posMap[entity.pos] = entity;
|
|
});
|
|
parsedList.sort(function (a, b) {
|
|
return a.fields.length - b.fields.length;
|
|
}); // Create the hierarchy
|
|
|
|
parsedList.forEach(function (entity) {
|
|
var parentPos = entity.fields.slice(0, -1).join('-');
|
|
var parentEntity = posMap[parentPos];
|
|
|
|
if (!parentEntity) {
|
|
entrances[entity.pos] = entity;
|
|
} else {
|
|
parentEntity.children = parentEntity.children || [];
|
|
parentEntity.children.push(entity);
|
|
} // Some time position list provide `key`, we don't need it
|
|
|
|
|
|
delete entity.key;
|
|
delete entity.fields;
|
|
});
|
|
return Object.keys(entrances).map(function (key) {
|
|
return entrances[key];
|
|
});
|
|
} // =============== Accessibility ===============
|
|
|
|
|
|
var ariaId = 0;
|
|
|
|
function resetAriaId() {
|
|
ariaId = 0;
|
|
}
|
|
|
|
function generateAriaId(prefix) {
|
|
ariaId += 1;
|
|
return "".concat(prefix, "_").concat(ariaId);
|
|
}
|
|
|
|
function isLabelInValue(props) {
|
|
var treeCheckable = props.treeCheckable,
|
|
treeCheckStrictly = props.treeCheckStrictly,
|
|
labelInValue = props.labelInValue;
|
|
|
|
if (treeCheckable && treeCheckStrictly) {
|
|
return true;
|
|
}
|
|
|
|
return labelInValue || false;
|
|
} // =================== Tree ====================
|
|
|
|
|
|
function parseSimpleTreeData(treeData, _ref) {
|
|
var id = _ref.id,
|
|
pId = _ref.pId,
|
|
rootPId = _ref.rootPId;
|
|
var keyNodes = {};
|
|
var rootNodeList = []; // Fill in the map
|
|
|
|
var nodeList = treeData.map(function (node) {
|
|
var clone = _objectSpread({}, node);
|
|
|
|
var key = clone[id];
|
|
keyNodes[key] = clone;
|
|
clone.key = clone.key || key;
|
|
return clone;
|
|
}); // Connect tree
|
|
|
|
nodeList.forEach(function (node) {
|
|
var parentKey = node[pId];
|
|
var parent = keyNodes[parentKey]; // Fill parent
|
|
|
|
if (parent) {
|
|
parent.children = parent.children || [];
|
|
parent.children.push(node);
|
|
} // Fill root tree node
|
|
|
|
|
|
if (parentKey === rootPId || !parent && rootPId === null) {
|
|
rootNodeList.push(node);
|
|
}
|
|
});
|
|
return rootNodeList;
|
|
}
|
|
/**
|
|
* Detect if position has relation.
|
|
* e.g. 1-2 related with 1-2-3
|
|
* e.g. 1-3-2 related with 1
|
|
* e.g. 1-2 not related with 1-21
|
|
*/
|
|
|
|
|
|
function isPosRelated(pos1, pos2) {
|
|
var fields1 = pos1.split('-');
|
|
var fields2 = pos2.split('-');
|
|
var minLen = Math.min(fields1.length, fields2.length);
|
|
|
|
for (var i = 0; i < minLen; i += 1) {
|
|
if (fields1[i] !== fields2[i]) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
/**
|
|
* This function is only used on treeNode check (none treeCheckStrictly but has searchInput).
|
|
* We convert entity to { node, pos, children } format.
|
|
* This is legacy bug but we still need to do with it.
|
|
* @param entity
|
|
*/
|
|
|
|
|
|
function cleanEntity(_ref2) {
|
|
var node = _ref2.node,
|
|
pos = _ref2.pos,
|
|
children = _ref2.children;
|
|
var instance = {
|
|
node: node,
|
|
pos: pos
|
|
};
|
|
|
|
if (children) {
|
|
instance.children = children.map(cleanEntity);
|
|
}
|
|
|
|
return instance;
|
|
}
|
|
/**
|
|
* Get a filtered TreeNode list by provided treeNodes.
|
|
* [Legacy] Since `Tree` use `key` as map but `key` will changed by React,
|
|
* we have to convert `treeNodes > data > treeNodes` to keep the key.
|
|
* Such performance hungry!
|
|
*
|
|
* We pass `Component` as argument is to fix eslint issue.
|
|
*/
|
|
|
|
|
|
function getFilterTree(treeNodes, searchValue, filterFunc, valueEntities, Component) {
|
|
if (!searchValue) {
|
|
return null;
|
|
}
|
|
|
|
function mapFilteredNodeToData(node) {
|
|
if (!node) return null;
|
|
var match = false;
|
|
|
|
if (filterFunc(searchValue, node)) {
|
|
match = true;
|
|
}
|
|
|
|
var children = (0, _toArray["default"])(node.props.children).map(mapFilteredNodeToData).filter(function (n) {
|
|
return n;
|
|
});
|
|
|
|
if (children.length || match) {
|
|
return _react["default"].createElement(Component, _extends({}, node.props, {
|
|
key: valueEntities[node.props.value].key
|
|
}), children);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
return treeNodes.map(mapFilteredNodeToData).filter(function (node) {
|
|
return node;
|
|
});
|
|
} // =================== Value ===================
|
|
|
|
/**
|
|
* Convert value to array format to make logic simplify.
|
|
*/
|
|
|
|
|
|
function formatInternalValue(value, props) {
|
|
var valueList = toArray(value); // Parse label in value
|
|
|
|
if (isLabelInValue(props)) {
|
|
return valueList.map(function (val) {
|
|
if (typeof val !== 'object' || !val) {
|
|
return {
|
|
value: '',
|
|
label: ''
|
|
};
|
|
}
|
|
|
|
return val;
|
|
});
|
|
}
|
|
|
|
return valueList.map(function (val) {
|
|
return {
|
|
value: val
|
|
};
|
|
});
|
|
}
|
|
|
|
function getLabel(wrappedValue, entity, treeNodeLabelProp) {
|
|
if (wrappedValue.label) {
|
|
return wrappedValue.label;
|
|
}
|
|
|
|
if (entity && entity.node.props) {
|
|
return entity.node.props[treeNodeLabelProp];
|
|
} // Since value without entity will be in missValueList.
|
|
// This code will never reached, but we still need this in case.
|
|
|
|
|
|
return wrappedValue.value;
|
|
}
|
|
/**
|
|
* Convert internal state `valueList` to user needed value list.
|
|
* This will return an array list. You need check if is not multiple when return.
|
|
*
|
|
* `allCheckedNodes` is used for `treeCheckStrictly`
|
|
*/
|
|
|
|
|
|
function formatSelectorValue(valueList, props, valueEntities) {
|
|
var treeNodeLabelProp = props.treeNodeLabelProp,
|
|
treeCheckable = props.treeCheckable,
|
|
treeCheckStrictly = props.treeCheckStrictly,
|
|
showCheckedStrategy = props.showCheckedStrategy; // Will hide some value if `showCheckedStrategy` is set
|
|
|
|
if (treeCheckable && !treeCheckStrictly) {
|
|
var values = {};
|
|
valueList.forEach(function (wrappedValue) {
|
|
values[wrappedValue.value] = wrappedValue;
|
|
});
|
|
var hierarchyList = flatToHierarchy(valueList.map(function (_ref3) {
|
|
var value = _ref3.value;
|
|
return valueEntities[value];
|
|
}));
|
|
|
|
if (showCheckedStrategy === _strategies.SHOW_PARENT) {
|
|
// Only get the parent checked value
|
|
return hierarchyList.map(function (_ref4) {
|
|
var value = _ref4.node.props.value;
|
|
return {
|
|
label: getLabel(values[value], valueEntities[value], treeNodeLabelProp),
|
|
value: value
|
|
};
|
|
});
|
|
}
|
|
|
|
if (showCheckedStrategy === _strategies.SHOW_CHILD) {
|
|
// Only get the children checked value
|
|
var targetValueList = []; // Find the leaf children
|
|
|
|
var traverse = function traverse(_ref5) {
|
|
var value = _ref5.node.props.value,
|
|
children = _ref5.children;
|
|
|
|
if (!children || children.length === 0) {
|
|
targetValueList.push({
|
|
label: getLabel(values[value], valueEntities[value], treeNodeLabelProp),
|
|
value: value
|
|
});
|
|
return;
|
|
}
|
|
|
|
children.forEach(function (entity) {
|
|
traverse(entity);
|
|
});
|
|
};
|
|
|
|
hierarchyList.forEach(function (entity) {
|
|
traverse(entity);
|
|
});
|
|
return targetValueList;
|
|
}
|
|
}
|
|
|
|
return valueList.map(function (wrappedValue) {
|
|
return {
|
|
label: getLabel(wrappedValue, valueEntities[wrappedValue.value], treeNodeLabelProp),
|
|
value: wrappedValue.value
|
|
};
|
|
});
|
|
}
|
|
/**
|
|
* Use `rc-tree` convertDataToTree to convert treeData to TreeNodes.
|
|
* This will change the label to title value
|
|
*/
|
|
|
|
|
|
function processProps(props) {
|
|
var title = props.title,
|
|
label = props.label,
|
|
key = props.key,
|
|
value = props.value;
|
|
|
|
var cloneProps = _objectSpread({}, props); // Warning user not to use deprecated label prop.
|
|
|
|
|
|
if (label && !title) {
|
|
if (!warnDeprecatedLabel) {
|
|
(0, _warning["default"])(false, "'label' in treeData is deprecated. Please use 'title' instead.");
|
|
warnDeprecatedLabel = true;
|
|
}
|
|
|
|
cloneProps.title = label;
|
|
}
|
|
|
|
if (!key) {
|
|
cloneProps.key = value;
|
|
}
|
|
|
|
return cloneProps;
|
|
}
|
|
|
|
function convertDataToTree(treeData) {
|
|
return (0, _util.convertDataToTree)(treeData, {
|
|
processProps: processProps
|
|
});
|
|
}
|
|
/**
|
|
* Use `rc-tree` convertTreeToEntities for entities calculation.
|
|
* We have additional entities of `valueEntities`
|
|
*/
|
|
|
|
|
|
function initWrapper(wrapper) {
|
|
return _objectSpread({}, wrapper, {
|
|
valueEntities: {}
|
|
});
|
|
}
|
|
|
|
function processEntity(entity, wrapper) {
|
|
var value = entity.node.props.value;
|
|
entity.value = value; // This should be empty, or will get error message.
|
|
|
|
var currentEntity = wrapper.valueEntities[value];
|
|
|
|
if (currentEntity) {
|
|
(0, _warning["default"])(false, "Conflict! value of node '".concat(entity.key, "' (").concat(value, ") has already used by node '").concat(currentEntity.key, "'."));
|
|
}
|
|
|
|
wrapper.valueEntities[value] = entity;
|
|
}
|
|
|
|
function convertTreeToEntities(treeNodes) {
|
|
return (0, _util.convertTreeToEntities)(treeNodes, {
|
|
initWrapper: initWrapper,
|
|
processEntity: processEntity
|
|
});
|
|
}
|
|
/**
|
|
* https://github.com/ant-design/ant-design/issues/13328
|
|
* We need calculate the half check key when searchValue is set.
|
|
*/
|
|
// TODO: This logic may better move to rc-tree
|
|
|
|
|
|
function getHalfCheckedKeys(valueList, valueEntities) {
|
|
var values = {}; // Fill checked keys
|
|
|
|
valueList.forEach(function (_ref6) {
|
|
var value = _ref6.value;
|
|
values[value] = false;
|
|
}); // Fill half checked keys
|
|
|
|
valueList.forEach(function (_ref7) {
|
|
var value = _ref7.value;
|
|
var current = valueEntities[value];
|
|
|
|
while (current && current.parent) {
|
|
var parentValue = current.parent.value;
|
|
if (parentValue in values) break;
|
|
values[parentValue] = true;
|
|
current = current.parent;
|
|
}
|
|
}); // Get half keys
|
|
|
|
return Object.keys(values).filter(function (value) {
|
|
return values[value];
|
|
}).map(function (value) {
|
|
return valueEntities[value].key;
|
|
});
|
|
}
|
|
|
|
var conductCheck = _util.conductCheck;
|
|
exports.conductCheck = conductCheck; |