amis
Version:
一种MIS页面生成工具
481 lines (480 loc) • 25.1 kB
JavaScript
"use strict";
/**
* @file Tree
* @description 树形组件
* @author fex
*/
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var react_1 = tslib_1.__importDefault(require("react"));
var helper_1 = require("../utils/helper");
var Checkboxes_1 = require("./Checkboxes");
var theme_1 = require("../theme");
var Options_1 = require("../renderers/Form/Options");
var icons_1 = require("./icons");
var TreeSelector = /** @class */ (function (_super) {
tslib_1.__extends(TreeSelector, _super);
function TreeSelector() {
return _super !== null && _super.apply(this, arguments) || this;
}
TreeSelector.prototype.componentWillMount = function () {
var props = this.props;
this.setState({
value: Checkboxes_1.value2array(props.value, {
joinValues: props.joinValues,
extractValue: props.extractValue,
multiple: props.multiple,
delimiter: props.delimiter,
valueField: props.valueField,
options: props.data
}),
unfolded: this.syncUnFolded(props),
editItem: null,
addItem: null,
addingItem: null,
editingItem: null,
addTop: false // 添加一级
});
};
TreeSelector.prototype.componentWillReceiveProps = function (nextProps) {
var toUpdate = {};
if (this.props.value !== nextProps.value || this.props.data !== nextProps.data) {
toUpdate.value = Checkboxes_1.value2array(nextProps.value, {
joinValues: nextProps.joinValues,
extractValue: nextProps.extractValue,
multiple: nextProps.multiple,
delimiter: nextProps.delimiter,
valueField: nextProps.valueField,
options: nextProps.data
});
}
if (this.props.data !== nextProps.data) {
toUpdate.unfolded = this.syncUnFolded(nextProps);
}
this.setState(toUpdate);
};
TreeSelector.prototype.syncUnFolded = function (props) {
// 初始化树节点的展开状态
var unfolded = {};
var _a = this.props, foldedField = _a.foldedField, unfoldedField = _a.unfoldedField;
helper_1.eachTree(props.data, function (node, index, level) {
if (node.children && node.children.length) {
var ret = true;
if (unfoldedField && typeof node[unfoldedField] !== 'undefined') {
ret = !!node[unfoldedField];
}
else if (foldedField && typeof node[foldedField] !== 'undefined') {
ret = !node[foldedField];
}
else {
ret = !!props.initiallyOpen;
if (!ret && level <= props.unfoldedLevel) {
ret = true;
}
}
unfolded[node[props.valueField]] = ret;
}
});
return unfolded;
};
TreeSelector.prototype.toggleUnfolded = function (node) {
var _a;
this.setState({
addItem: null,
unfolded: tslib_1.__assign(tslib_1.__assign({}, this.state.unfolded), (_a = {}, _a[node[this.props.valueField]] = !this.state.unfolded[node[this.props.valueField]], _a))
});
};
TreeSelector.prototype.clearSelect = function () {
var _this = this;
this.setState({
value: []
}, function () {
var _a = _this.props, joinValues = _a.joinValues, rootValue = _a.rootValue, onChange = _a.onChange;
onChange(joinValues ? rootValue : []);
});
};
TreeSelector.prototype.handleSelect = function (node, value) {
var _this = this;
this.setState({
value: [node]
}, function () {
var _a = _this.props, joinValues = _a.joinValues, valueField = _a.valueField, onChange = _a.onChange;
onChange(joinValues ? node[valueField] : node);
});
};
TreeSelector.prototype.handleCheck = function (item, checked) {
var _this = this;
var props = this.props;
var value = this.state.value.concat();
var idx = value.indexOf(item);
var onlyChildren = this.props.onlyChildren;
if (checked) {
~idx || value.push(item);
if (!props.cascade) {
var children = item.children ? item.children.concat([]) : [];
if (onlyChildren) {
// 父级选中的时候,子节点也都选中,但是自己不选中
!~idx && children.length && value.shift();
while (children.length) {
var child = children.shift();
var index = value.indexOf(child);
if (child.children) {
children.push.apply(children, child.children);
}
else {
~index || value.push(child);
}
}
}
else {
// 只要父节点选择了,子节点就不需要了,全部去掉勾选. withChildren时相反
while (children.length) {
var child = children.shift();
var index = value.indexOf(child);
if (~index) {
value.splice(index, 1);
}
if (props.withChildren) {
value.push(child);
}
if (child.children && child.children.length) {
children.push.apply(children, child.children);
}
}
}
}
}
else if (!checked) {
~idx && value.splice(idx, 1);
if (!props.cascade && (props.withChildren || onlyChildren)) {
var children = item.children ? item.children.concat([]) : [];
while (children.length) {
var child = children.shift();
var index = value.indexOf(child);
if (~index) {
value.splice(index, 1);
}
if (child.children && child.children.length) {
children.push.apply(children, child.children);
}
}
}
}
this.setState({
value: value
}, function () {
var _a = _this.props, joinValues = _a.joinValues, extractValue = _a.extractValue, valueField = _a.valueField, delimiter = _a.delimiter, onChange = _a.onChange;
onChange(joinValues
? value.map(function (item) { return item[valueField]; }).join(delimiter)
: extractValue
? value.map(function (item) { return item[valueField]; })
: value);
});
};
TreeSelector.prototype.handleAdd = function (item, isFolder) {
var _a;
var _b = this.props, addMode = _b.addMode, openAddDialog = _b.openAddDialog, valueField = _b.valueField;
var unfolded = this.state.unfolded;
if (addMode === 'dialog') {
openAddDialog && openAddDialog(item ? item : null);
}
else if (addMode === 'normal') {
// item 为 null 时为添加一级
if (item) {
// 添加时,默认折叠的文件夹需要展开
if (isFolder && !unfolded[item[valueField]]) {
unfolded = tslib_1.__assign(tslib_1.__assign({}, unfolded), (_a = {}, _a[item[valueField]] = !unfolded[item[valueField]], _a));
}
this.setState({
addItem: item,
editItem: null,
unfolded: unfolded
});
}
else {
this.setState({
addTop: true,
editItem: null,
addItem: null
});
}
}
};
TreeSelector.prototype.handleEdit = function (item) {
var _a = this.props, editMode = _a.editMode, openEditDialog = _a.openEditDialog;
var addItem = this.state.addItem;
if (editMode === 'dialog') {
openEditDialog && openEditDialog(item);
addItem && this.setState({
addItem: null
});
}
else if (editMode === 'normal') {
this.setState({
editItem: item,
addItem: null
});
}
};
TreeSelector.prototype.handleRemove = function (item) {
var onRemove = this.props.onRemove;
onRemove && onRemove(item);
};
TreeSelector.prototype.handleConfirmOnAdd = function () {
var onAdd = this.props.onAdd;
var _a = this.state, parent = _a.addItem, addingItem = _a.addingItem;
onAdd && onAdd(tslib_1.__assign(tslib_1.__assign({}, addingItem), { parent: parent }));
this.setState({
addingItem: null,
addItem: null,
addTop: false
});
};
TreeSelector.prototype.handleCancelOnAdd = function () {
this.setState({
addItem: null,
addTop: false
});
};
TreeSelector.prototype.handleConfirmOnEdit = function () {
var onEdit = this.props.onEdit;
var _a = this.state, editingItem = _a.editingItem, prevItem = _a.editItem;
onEdit && onEdit(tslib_1.__assign(tslib_1.__assign({}, editingItem), { prev: prevItem }));
this.setState({
editingItem: null,
editItem: null
});
};
TreeSelector.prototype.handleCancelOnEdit = function () {
this.setState({
editItem: null
});
};
TreeSelector.prototype.handleChangeOnAdd = function (value) {
this.setState({
addingItem: {
label: value
}
});
};
TreeSelector.prototype.handleChangeOnEdit = function (item, value) {
var editItem = this.state.editItem;
this.setState({
editingItem: tslib_1.__assign(tslib_1.__assign({}, item), { label: value || editItem['label'] })
});
};
TreeSelector.prototype.renderList = function (list, value, uncheckable) {
var _this = this;
var _a = this.props, itemClassName = _a.itemClassName, showIcon = _a.showIcon, showRadio = _a.showRadio, multiple = _a.multiple, disabled = _a.disabled, _b = _a.nameField, nameField = _b === void 0 ? '' : _b, _c = _a.valueField, valueField = _c === void 0 ? '' : _c, _d = _a.iconField, iconField = _d === void 0 ? '' : _d, _e = _a.disabledField, disabledField = _e === void 0 ? '' : _e, cascade = _a.cascade, selfDisabledAffectChildren = _a.selfDisabledAffectChildren, onlyChildren = _a.onlyChildren, cx = _a.classnames, highlightTxt = _a.highlightTxt, data = _a.data, maxLength = _a.maxLength, minLength = _a.minLength, addable = _a.addable, editable = _a.editable, removable = _a.removable;
var _f = this.state, addItem = _f.addItem, editItem = _f.editItem, unfolded = _f.unfolded, addTop = _f.addTop, stateValue = _f.value;
var childrenChecked = 0;
var ret = list.map(function (item, key) {
if (!helper_1.isVisible(item, data)) {
return null;
}
var checked = !!~value.indexOf(item);
var selfDisabled = item[disabledField];
var selfChecked = !!uncheckable || checked;
var childrenItems = null;
var tmpChildrenChecked = false;
if (item.children && item.children.length) {
childrenItems = _this.renderList(item.children, value, cascade
? false
: uncheckable || (selfDisabledAffectChildren ? selfDisabled : false) || (multiple && checked));
tmpChildrenChecked = !!childrenItems.childrenChecked;
if (!selfChecked && onlyChildren && item.children.length === childrenItems.childrenChecked) {
selfChecked = true;
}
childrenItems = childrenItems.dom;
}
if (tmpChildrenChecked || checked) {
childrenChecked++;
}
var nodeDisabled = !!uncheckable || !!disabled || selfDisabled;
if (!nodeDisabled &&
((maxLength && !selfChecked && stateValue.length >= maxLength) ||
(minLength && selfChecked && stateValue.length <= minLength))) {
nodeDisabled = true;
}
var checkbox = multiple ? (react_1.default.createElement("label", { className: cx("Checkbox Checkbox--checkbox Checkbox--sm") },
react_1.default.createElement("input", { type: "checkbox", disabled: nodeDisabled, checked: selfChecked, onChange: function (e) { return _this.handleCheck(item, e.currentTarget.checked); } }),
react_1.default.createElement("i", null))) : showRadio ? (react_1.default.createElement("label", { className: cx("Checkbox Checkbox--radio Checkbox--sm") },
react_1.default.createElement("input", { type: "radio", disabled: nodeDisabled, checked: checked, onChange: function () { return _this.handleSelect(item); } }),
react_1.default.createElement("i", null))) : null;
var isLeaf = !item.children || !item.children.length;
return (react_1.default.createElement("li", { key: key, className: cx("Tree-item " + (itemClassName || ''), {
'Tree-item--isLeaf': isLeaf
}) },
!editItem || helper_1.isObject(editItem) && editItem[valueField] !== item[valueField] ? (react_1.default.createElement("a", null,
!isLeaf ? (react_1.default.createElement("i", { onClick: function () { return _this.toggleUnfolded(item); }, className: cx('Tree-itemArrow', {
'is-folded': !unfolded[item[valueField]],
}) })) : null,
showIcon ? (react_1.default.createElement("i", { className: cx("Tree-itemIcon " + (item[iconField] ||
(childrenItems ? 'Tree-folderIcon' : 'Tree-leafIcon'))) })) : null,
checkbox,
react_1.default.createElement("span", { className: cx('Tree-itemText', {
'is-children-checked': multiple && !cascade && tmpChildrenChecked && !nodeDisabled,
'is-checked': checked,
'is-disabled': nodeDisabled,
}), onClick: function () {
return !nodeDisabled &&
(multiple ? _this.handleCheck(item, !selfChecked) : _this.handleSelect(item));
} }, highlightTxt ? Options_1.highlight(item[nameField], highlightTxt) : item[nameField]),
!nodeDisabled
&& !addTop
&& !addItem
&& !editItem ? (react_1.default.createElement("span", { className: cx('Tree-item-icons') },
addable ? react_1.default.createElement(icons_1.Icon, { icon: "plus", className: "icon", onClick: function () { return _this.handleAdd(item, !isLeaf); } }) : null,
removable ? react_1.default.createElement(icons_1.Icon, { icon: "minus", className: "icon", onClick: function () { return _this.handleRemove(item); } }) : null,
editable ? react_1.default.createElement(icons_1.Icon, { icon: "pencil", className: "icon", onClick: function () { return _this.handleEdit(item); } }) : null)) : null)) : (react_1.default.createElement("div", { className: cx('Tree-item--isEdit') },
react_1.default.createElement("input", { defaultValue: item['label'], onChange: function (e) { return _this.handleChangeOnEdit(item, e.currentTarget.value); } }),
react_1.default.createElement(icons_1.Icon, { icon: "check", className: "icon", onClick: _this.handleConfirmOnEdit }),
react_1.default.createElement(icons_1.Icon, { icon: "close", className: "icon", onClick: _this.handleCancelOnEdit }))),
((childrenItems && unfolded[item[valueField]]) || addItem && (addItem[valueField] === item[valueField])) ? (react_1.default.createElement("ul", { className: cx('Tree-sublist') },
addItem && addItem[valueField] === item[valueField] ? (react_1.default.createElement("li", null,
react_1.default.createElement("input", { onChange: function (e) { return _this.handleChangeOnAdd(e.currentTarget.value); } }),
react_1.default.createElement(icons_1.Icon, { icon: "check", className: "icon", onClick: _this.handleConfirmOnAdd }),
react_1.default.createElement(icons_1.Icon, { icon: "close", className: "icon", onClick: _this.handleCancelOnAdd }))) : null,
childrenItems)) : null));
});
return {
dom: ret,
childrenChecked: childrenChecked
};
};
TreeSelector.prototype.render = function () {
var _this = this;
var _a = this.props, className = _a.className, placeholder = _a.placeholder, hideRoot = _a.hideRoot, rootLabel = _a.rootLabel, showIcon = _a.showIcon, cx = _a.classnames, addable = _a.addable;
var data = this.props.data;
var _b = this.state, value = _b.value, addTop = _b.addTop;
return (react_1.default.createElement("div", { className: cx("Tree " + (className || '')) }, data && data.length ? (react_1.default.createElement("ul", { className: cx('Tree-list') }, hideRoot ? (this.renderList(data, value, false).dom) : (react_1.default.createElement("li", { className: cx('Tree-item Tree-rootItem') },
react_1.default.createElement("a", null,
showIcon ? react_1.default.createElement("i", { className: cx('Tree-itemIcon Tree-rootIcon') }) : null,
react_1.default.createElement("label", { className: cx('Tree-itemLabel', {
'is-checked': !value || !value.length
}) },
react_1.default.createElement("span", { className: cx('Tree-itemText'), onClick: this.clearSelect }, rootLabel))),
addable ? (react_1.default.createElement("div", { className: cx('Tree-addTop') },
!addTop ? (react_1.default.createElement("p", { onClick: function () { return _this.handleAdd(null, false); } },
react_1.default.createElement(icons_1.Icon, { icon: "plus", className: "icon" }),
react_1.default.createElement("span", null, "\u6DFB\u52A0\u4E00\u7EA7"))) : null,
addTop ? (react_1.default.createElement("div", { className: cx('Tree-addTop-input') },
react_1.default.createElement("input", { onChange: function (e) { return _this.handleChangeOnAdd(e.currentTarget.value); } }),
react_1.default.createElement(icons_1.Icon, { icon: "check", className: "icon", onClick: this.handleConfirmOnAdd }),
react_1.default.createElement(icons_1.Icon, { icon: "close", className: "icon", onClick: this.handleCancelOnAdd }))) : null)) : null,
react_1.default.createElement("ul", { className: cx('Tree-sublist') }, this.renderList(data, value, false).dom))))) : (react_1.default.createElement("div", { className: cx('Tree-placeholder') }, placeholder))));
};
var _a, _b, _c, _d, _e;
TreeSelector.defaultProps = {
showIcon: true,
initiallyOpen: true,
unfoldedLevel: 0,
showRadio: false,
multiple: false,
disabled: false,
withChildren: false,
onlyChildren: false,
nameField: 'name',
valueField: 'value',
iconField: 'icon',
unfoldedField: 'unfolded',
foldedField: 'foled',
disabledField: 'disabled',
joinValues: true,
extractValue: false,
delimiter: ',',
hideRoot: true,
rootLabel: '顶级',
rootValue: 0,
cascade: false,
selfDisabledAffectChildren: true
};
tslib_1.__decorate([
helper_1.autobind,
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [Object]),
tslib_1.__metadata("design:returntype", void 0)
], TreeSelector.prototype, "toggleUnfolded", null);
tslib_1.__decorate([
helper_1.autobind,
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", []),
tslib_1.__metadata("design:returntype", void 0)
], TreeSelector.prototype, "clearSelect", null);
tslib_1.__decorate([
helper_1.autobind,
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [Object, Object]),
tslib_1.__metadata("design:returntype", void 0)
], TreeSelector.prototype, "handleSelect", null);
tslib_1.__decorate([
helper_1.autobind,
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [Object, Boolean]),
tslib_1.__metadata("design:returntype", void 0)
], TreeSelector.prototype, "handleCheck", null);
tslib_1.__decorate([
helper_1.autobind,
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [typeof (_a = typeof Checkboxes_1.Option !== "undefined" && Checkboxes_1.Option) === "function" ? _a : Object, Boolean]),
tslib_1.__metadata("design:returntype", void 0)
], TreeSelector.prototype, "handleAdd", null);
tslib_1.__decorate([
helper_1.autobind,
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [typeof (_b = typeof Checkboxes_1.Option !== "undefined" && Checkboxes_1.Option) === "function" ? _b : Object]),
tslib_1.__metadata("design:returntype", void 0)
], TreeSelector.prototype, "handleEdit", null);
tslib_1.__decorate([
helper_1.autobind,
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [typeof (_c = typeof Checkboxes_1.Option !== "undefined" && Checkboxes_1.Option) === "function" ? _c : Object]),
tslib_1.__metadata("design:returntype", void 0)
], TreeSelector.prototype, "handleRemove", null);
tslib_1.__decorate([
helper_1.autobind,
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", []),
tslib_1.__metadata("design:returntype", void 0)
], TreeSelector.prototype, "handleConfirmOnAdd", null);
tslib_1.__decorate([
helper_1.autobind,
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", []),
tslib_1.__metadata("design:returntype", void 0)
], TreeSelector.prototype, "handleCancelOnAdd", null);
tslib_1.__decorate([
helper_1.autobind,
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", []),
tslib_1.__metadata("design:returntype", void 0)
], TreeSelector.prototype, "handleConfirmOnEdit", null);
tslib_1.__decorate([
helper_1.autobind,
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", []),
tslib_1.__metadata("design:returntype", void 0)
], TreeSelector.prototype, "handleCancelOnEdit", null);
tslib_1.__decorate([
helper_1.autobind,
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [String]),
tslib_1.__metadata("design:returntype", void 0)
], TreeSelector.prototype, "handleChangeOnAdd", null);
tslib_1.__decorate([
helper_1.autobind,
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [typeof (_d = typeof Checkboxes_1.Option !== "undefined" && Checkboxes_1.Option) === "function" ? _d : Object, String]),
tslib_1.__metadata("design:returntype", void 0)
], TreeSelector.prototype, "handleChangeOnEdit", null);
tslib_1.__decorate([
helper_1.autobind,
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [typeof (_e = typeof Checkboxes_1.Options !== "undefined" && Checkboxes_1.Options) === "function" ? _e : Object, Array, Boolean]),
tslib_1.__metadata("design:returntype", Object)
], TreeSelector.prototype, "renderList", null);
return TreeSelector;
}(react_1.default.Component));
exports.TreeSelector = TreeSelector;
exports.default = theme_1.themeable(TreeSelector);
//# sourceMappingURL=./components/Tree.js.map