shineout
Version:
Shein 前端组件库
655 lines (549 loc) • 22.5 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.default = void 0;
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose"));
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
var _react = _interopRequireDefault(require("react"));
var _immer = _interopRequireDefault(require("immer"));
var _classnames = _interopRequireDefault(require("classnames"));
var _is = require("../utils/is");
var _component = require("../component");
var _uid = require("../utils/uid");
var _Tree = _interopRequireDefault(require("../Datum/Tree"));
var _styles = require("../Select/styles");
var _styles2 = require("./styles");
var _Result = _interopRequireDefault(require("./Result"));
var _List = _interopRequireDefault(require("./List"));
var _FilterList = _interopRequireDefault(require("./FilterList"));
var _document = require("../utils/dom/document");
var _element = require("../utils/dom/element");
var _AbsoluteList = _interopRequireDefault(require("../AnimationList/AbsoluteList"));
var _config = require("../config");
var OptionList = (0, _AbsoluteList.default)(function (_ref) {
var focus = _ref.focus,
getRef = _ref.getRef,
other = (0, _objectWithoutPropertiesLoose2.default)(_ref, ["focus", "getRef"]);
return focus ? _react.default.createElement("div", (0, _extends2.default)({}, other, {
ref: getRef
})) : null;
});
var isDescendent = function isDescendent(el, id) {
if (el.getAttribute('data-id') === id) return true;
if (!el.parentElement) return false;
return isDescendent(el.parentElement, id);
};
var DefaultProps = {
data: [],
height: 300,
clearable: true,
showArrow: true,
expandTrigger: 'click',
childrenKey: 'children'
};
var Cascader =
/*#__PURE__*/
function (_PureComponent) {
(0, _inheritsLoose2.default)(Cascader, _PureComponent);
function Cascader(props) {
var _this;
_this = _PureComponent.call(this, props) || this;
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "pathChangeTimer", void 0);
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "datum", void 0);
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "selectId", void 0);
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "isRendered", void 0);
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "lastFoucs", void 0);
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "shouldUpdateAfterRef", void 0);
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "ref", void 0);
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "close", void 0);
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "handleBlur", void 0);
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "handleClick", void 0);
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "input", void 0);
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "lastValue", void 0);
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "element", void 0);
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "renderPending", void 0);
_this.state = {
focus: false,
path: [],
position: 'drop-down'
};
_this.datum = new _Tree.default({
data: props.data,
loader: props.loader,
keygen: props.keygen,
mode: props.mode,
onChange: props.onChange,
value: props.value,
disabled: typeof props.disabled === 'function' ? props.disabled : undefined,
childrenKey: props.childrenKey || DefaultProps.childrenKey,
unmatch: props.unmatch
});
_this.isRendered = false;
_this.selectId = "select_" + (0, _uid.getUidStr)();
_this.handleClick = _this.handleState.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), true);
_this.handleBlur = _this.handleState.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), false);
_this.handleFocus = _this.handleFocus.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
_this.handleKeyDown = _this.handleKeyDown.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
_this.handleClickAway = _this.handleClickAway.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
_this.handlePathChange = _this.handlePathChange.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
_this.handleClear = _this.handleClear.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
_this.shouldFocus = _this.shouldFocus.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
_this.bindRef = _this.bindRef.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
_this.handleChange = _this.handleChange.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
_this.bindInput = _this.bindInput.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
_this.handleRemove = _this.handleRemove.bind((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)));
_this.close = _this.handleBlur;
var componentRef = {
close: _this.close
};
if (props.getComponentRef) {
if ((0, _is.isFunc)(props.getComponentRef)) {
props.getComponentRef(componentRef);
} else {
props.getComponentRef.current = componentRef;
}
}
return _this;
}
var _proto = Cascader.prototype;
_proto.componentDidMount = function componentDidMount() {
_PureComponent.prototype.componentDidMount.call(this);
this.setOpenEvent();
this.updatePathByValue();
if (this.props.mode !== undefined && this.props.loader && [0, 1, 2].includes(this.props.mode)) {
console.error(new Error("The mode " + this.props.mode + " is not supported when loader setted. Only 3 or 4 can be set."));
}
};
_proto.componentDidUpdate = function componentDidUpdate(prevProps, prevState) {
this.datum.mode = this.props.mode;
this.datum.updateDisabled(this.props.disabled);
this.setOpenEvent();
var _this$props = this.props,
onFilter = _this$props.onFilter,
filterText = _this$props.filterText;
if (prevProps.sourceData !== this.props.sourceData) this.datum.setData(this.props.sourceData, true);
if (prevProps.value !== this.props.value) {
this.datum.setValue(this.props.value || []);
this.updatePathByValue();
}
if (prevState.focus !== this.state.focus && !this.state.focus || prevProps.open !== this.props.open && !this.props.open) {
if (onFilter) {
setTimeout(function () {
onFilter('');
}, 400);
}
if (this.shouldFinal) {
this.updatePathByValue(true);
}
}
if (filterText !== undefined && prevProps.filterText !== filterText) {
this.updatePath();
}
};
_proto.componentWillUnmount = function componentWillUnmount() {
_PureComponent.prototype.componentWillUnmount.call(this);
this.clearClickAway();
};
_proto.setOpenEvent = function setOpenEvent() {
var focus = this.focus || this.props.inputFocus;
if (this.lastFoucs !== focus) if (focus) {
this.bindClickAway();
} else if (this.lastFoucs !== undefined) {
this.clearClickAway();
}
this.lastFoucs = focus;
};
_proto.bindRef = function bindRef(el) {
this.ref = el;
};
_proto.bindClickAway = function bindClickAway() {
document.addEventListener('mousedown', this.handleClickAway);
};
_proto.bindInput = function bindInput(input) {
this.input = input;
};
_proto.clearClickAway = function clearClickAway() {
document.removeEventListener('mousedown', this.handleClickAway);
};
_proto.shouldFocus = function shouldFocus(el) {
if (el.getAttribute('data-id') === this.selectId) return true;
if ((0, _element.getParent)(el, "." + (0, _styles2.cascaderClass)('result'))) return true;
return false;
};
_proto.updatePath = function updatePath() {
var _this$props2 = this.props,
firstMatchNode = _this$props2.firstMatchNode,
keygen = _this$props2.keygen,
filterText = _this$props2.filterText;
if (!filterText || !firstMatchNode) {
this.setState({
path: []
});
return;
}
var key = (0, _uid.getKey)(firstMatchNode, keygen);
var current = this.datum.getPath(key);
if (!current) return;
this.setState((0, _immer.default)(function (draft) {
draft.path = [].concat(current.path, [key]);
}));
};
_proto.updatePathByValue = function updatePathByValue(force) {
var _this$props3 = this.props,
mode = _this$props3.mode,
value = _this$props3.value;
if (mode !== undefined) return;
if (value === this.lastValue && !force) return;
if (!value || !value.length) {
this.setState({
path: []
});
} else {
var v = value[value.length - 1];
var data = this.datum.getDataById(v);
if (data === null || this.datum.isUnMatch(data)) return;
try {
var id = this.datum.getKey(data, '');
var _ref2 = this.datum.getPath(id) || {},
path = _ref2.path;
path = path || [];
this.handlePathChange(id, null, path);
} catch (e) {
console.error(e);
}
}
};
_proto.handleClickAway = function handleClickAway(e) {
var desc = isDescendent(e.target, this.selectId);
if (!desc) {
if (this.props.inputFocus) this.props.onBlur();
this.handleState(false);
}
};
_proto.handlePathChange = function handlePathChange(id, data, path, fromClick) {
var _this2 = this;
var _this$props4 = this.props,
childrenKey = _this$props4.childrenKey,
finalDismiss = _this$props4.finalDismiss,
loader = _this$props4.loader;
if (fromClick && data && childrenKey) {
var leaf = !data[childrenKey] || data[childrenKey].length === 0;
if (loader && typeof loader === 'function' && data[childrenKey] === undefined) {
leaf = false;
}
if (finalDismiss && leaf) this.handleState(false);
}
if (this.pathChangeTimer) {
clearTimeout(this.pathChangeTimer);
this.pathChangeTimer = null;
}
this.pathChangeTimer = setTimeout(function () {
_this2.setState({
path: [].concat(path, [id])
});
}, 50);
};
_proto.handleFocus = function handleFocus(e) {
if (!this.shouldFocus(e.target)) return;
this.props.onFocus(e);
};
_proto.handleClear = function handleClear() {
var _this3 = this;
var mode = this.props.mode;
this.setState({
path: []
});
if (mode !== undefined) this.datum.setValue([]);
this.handleChange([]); // force close
setTimeout(function () {
return _this3.handleState(false);
}, 10);
};
_proto.handleRemove = function handleRemove(node) {
var onChange = this.props.onChange;
this.datum.set(this.datum.getKey(node), 0);
if (onChange) onChange(this.datum.getValue(), node);
};
_proto.handleState = function handleState(focus, e) {
if (this.props.disabled === true) return;
if (focus === this.focus) return; // click close icon
if (focus && e && e.target.classList.contains((0, _styles2.cascaderClass)('close'))) return; // if remove node, return
if (e && (0, _element.getParent)(e.target, "." + (0, _styles2.cascaderClass)('remove-container'))) return;
var _this$props5 = this.props,
_this$props5$height = _this$props5.height,
height = _this$props5$height === void 0 ? DefaultProps.height : _this$props5$height,
onCollapse = _this$props5.onCollapse;
var position = this.props.position;
if (!position) {
var windowHeight = _document.docSize.height;
var bottom = height + this.element.getBoundingClientRect().bottom;
if (bottom > windowHeight) position = 'drop-up';
}
if (onCollapse) onCollapse(focus);
this.setState({
focus: focus,
position: position || 'drop-down'
});
if (focus) {
this.renderPending = false;
}
};
_proto.handleKeyDown = function handleKeyDown(e) {
if (e.keyCode === 13) {
e.preventDefault();
this.handleState(!this.focus);
} // fot close the list
if (e.keyCode === 9) {
this.props.onBlur(); // e.preventDefault()
if (this.focus) {
this.handleState(false);
}
}
};
_proto.handleChange = function handleChange() {
var _this$props6 = this.props,
onChange = _this$props6.onChange,
onFilter = _this$props6.onFilter,
mode = _this$props6.mode,
emptyAfterSelect = _this$props6.emptyAfterSelect,
filterText = _this$props6.filterText;
if (this.input) {
this.input.reset();
this.input.focus();
}
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
var value = args[0];
this.lastValue = value;
if (onChange) {
onChange.apply(void 0, args);
}
if (onFilter && filterText) {
if (!(mode !== undefined && !emptyAfterSelect)) {
onFilter('');
}
}
};
_proto.renderList = function renderList() {
var _this4 = this;
var _this$props7 = this.props,
data = _this$props7.data,
keygen = _this$props7.keygen,
renderItem = _this$props7.renderItem,
mode = _this$props7.mode,
loader = _this$props7.loader,
expandTrigger = _this$props7.expandTrigger,
childrenKey = _this$props7.childrenKey,
height = _this$props7.height;
var path = this.state.path;
var props = {
datum: this.datum,
renderItem: renderItem,
keygen: keygen,
loader: loader,
onPathChange: this.handlePathChange,
onChange: this.handleChange,
multiple: mode !== undefined,
expandTrigger: expandTrigger,
childrenKey: childrenKey,
shouldFinal: this.shouldFinal
};
var tempData = data;
var list = [_react.default.createElement(_List.default, (0, _extends2.default)({}, props, {
text: undefined,
key: "root",
data: tempData,
id: path[0],
parentId: "",
path: []
}))];
var childs = path.map(function (p, i) {
tempData = tempData && tempData instanceof Array && tempData.find(function (d) {
var nid = _this4.datum.getKey(d, path[i - 1]);
return nid === p;
});
if (tempData && tempData[childrenKey] && tempData[childrenKey].length > 0) {
tempData = tempData[childrenKey];
return _react.default.createElement(_List.default, (0, _extends2.default)({}, props, {
key: p,
text: undefined,
data: tempData,
id: path[i + 1],
parentId: path[i],
path: path.slice(0, i + 1)
}));
}
return null;
});
if (childs) {
list = list.concat(childs);
}
var listStyle = data && data.length === 0 ? {
height: 'auto',
width: '100%'
} : {
height: height
};
return _react.default.createElement("div", {
ref: this.bindRef,
style: listStyle
}, list);
};
_proto.renderAbsoluteList = function renderAbsoluteList() {
var _this$props8 = this.props,
absolute = _this$props8.absolute,
zIndex = _this$props8.zIndex,
renderOptionList = _this$props8.renderOptionList,
loading = _this$props8.loading;
var position = this.state.position;
var focus = this.focus;
var className = (0, _classnames.default)((0, _styles.selectClass)('options'), (0, _styles2.cascaderClass)('options'));
var rootClass = (0, _classnames.default)((0, _styles2.cascaderClass)(focus && 'focus', (0, _config.isRTL)() && 'rtl'), (0, _styles.selectClass)(this.state.position));
if (!focus && !this.isRendered) return null;
if (!this.element) {
this.shouldUpdateAfterRef = true;
return null;
}
this.isRendered = true;
var list = this.renderList();
return _react.default.createElement(OptionList, {
autoAdapt: true,
rootClass: rootClass,
className: className,
position: position,
absolute: absolute,
focus: focus,
parentElement: this.element,
"data-id": this.selectId,
zIndex: zIndex
}, renderOptionList ? renderOptionList(list, {
loading: !!loading
}) : list);
};
_proto.renderFilterList = function renderFilterList() {
var _this$props9 = this.props,
absolute = _this$props9.absolute,
onFilter = _this$props9.onFilter,
wideMatch = _this$props9.wideMatch,
filterText = _this$props9.filterText,
zIndex = _this$props9.zIndex,
data = _this$props9.data,
childrenKey = _this$props9.childrenKey,
renderItem = _this$props9.renderItem,
expandTrigger = _this$props9.expandTrigger,
filterDataChange = _this$props9.filterDataChange,
height = _this$props9.height,
loading = _this$props9.loading,
renderOptionList = _this$props9.renderOptionList;
var position = this.state.position;
var focus = this.focus;
var className = (0, _classnames.default)((0, _styles2.cascaderClass)(focus && 'focus', (0, _config.isRTL)() && 'rtl'), (0, _styles.selectClass)(this.state.position));
return _react.default.createElement(_FilterList.default, {
shouldFinal: this.shouldFinal,
fixed: "min",
rootClass: className,
position: position,
absolute: absolute,
focus: focus,
parentElement: this.element,
"data-id": this.selectId,
zIndex: zIndex,
data: data,
childrenKey: childrenKey,
renderItem: renderItem,
expandTrigger: expandTrigger,
filterDataChange: filterDataChange,
datum: this.datum,
onChange: this.handleChange,
onPathChange: this.handlePathChange,
wideMatch: wideMatch,
onFilter: onFilter,
filterText: filterText,
height: height,
loading: loading,
renderOptionList: renderOptionList
});
};
_proto.renderPanel = function renderPanel() {
var _this$props10 = this.props,
filterText = _this$props10.filterText,
data = _this$props10.data,
mode = _this$props10.mode,
loading = _this$props10.loading;
if (loading) return this.renderFilterList();
if (!filterText || filterText && mode !== undefined || data && data.length === 0) return this.renderAbsoluteList();
return this.renderFilterList();
};
_proto.render = function render() {
var _this5 = this;
var _this$props11 = this.props,
placeholder = _this$props11.placeholder,
disabled = _this$props11.disabled,
size = _this$props11.size,
other = (0, _objectWithoutPropertiesLoose2.default)(_this$props11, ["placeholder", "disabled", "size"]);
var focus = this.focus;
var className = (0, _classnames.default)((0, _styles2.cascaderClass)('_', size, focus && 'focus', other.mode !== undefined && 'multiple', disabled === true && 'disabled', (0, _config.isRTL)() && 'rtl'), (0, _styles.selectClass)(this.state.position, focus && 'focus'));
return _react.default.createElement("div", {
// eslint-disable-next-line
tabIndex: disabled === true ? -1 : 0,
className: className,
onFocus: this.handleFocus,
onClick: this.handleClick,
"data-id": this.selectId,
onKeyDown: this.handleKeyDown,
ref: function ref(el) {
_this5.element = el;
if (el && _this5.shouldUpdateAfterRef) {
_this5.shouldUpdateAfterRef = false;
_this5.forceUpdate();
}
}
}, _react.default.createElement(_Result.default, (0, _extends2.default)({}, other, {
focus: focus,
multiple: other.mode !== undefined,
datum: this.datum,
placeholder: placeholder,
onClear: this.handleClear,
onPathChange: this.handlePathChange,
bindInput: this.bindInput,
handleRemove: this.handleRemove,
selectId: this.selectId,
showList: this.handleClick,
size: size
})), this.renderPanel());
};
(0, _createClass2.default)(Cascader, [{
key: "focus",
get: function get() {
if ('open' in this.props) {
return !!this.props.open;
}
return this.state.focus;
}
}, {
key: "shouldFinal",
get: function get() {
var _this$props12 = this.props,
expandTrigger = _this$props12.expandTrigger,
final = _this$props12.final;
return expandTrigger === 'hover-only' || !!final;
}
}]);
return Cascader;
}(_component.PureComponent);
(0, _defineProperty2.default)(Cascader, "defaultProps", DefaultProps);
Cascader.defaultProps = {
clearable: true,
expandTrigger: 'click',
height: 300,
data: [],
childrenKey: 'children',
showArrow: true
};
var _default = Cascader;
exports.default = _default;