UNPKG

@atlaskit/mention

Version:

A React component used to display user profiles in a list for 'Mention' functionality

238 lines (234 loc) 9.26 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var _logger = _interopRequireDefault(require("../../util/logger")); var _mouse = require("../../util/mouse"); var _MentionItem = _interopRequireDefault(require("../MentionItem")); var _MentionListError = _interopRequireDefault(require("../MentionListError")); var _MessagesIntlProvider = _interopRequireDefault(require("../MessagesIntlProvider")); var _Scrollable = _interopRequireDefault(require("../Scrollable")); var _styles = require("./styles"); function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } function wrapIndex(mentions, index) { var len = mentions.length; var newIndex = index; while (newIndex < 0 && len > 0) { newIndex += len; } return newIndex % len; } function getKey(index, mentions) { return mentions && mentions[index] && mentions[index].id; } function getIndex(key, mentions) { var index; if (mentions) { index = 0; while (index < mentions.length && mentions[index].id !== key) { index++; } if (index === mentions.length) { index = undefined; } } return index; } var MentionList = exports.default = /*#__PURE__*/function (_React$PureComponent) { function MentionList(props) { var _this; (0, _classCallCheck2.default)(this, MentionList); _this = _callSuper(this, MentionList, [props]); // API (0, _defineProperty2.default)(_this, "selectNext", function () { var newIndex = wrapIndex(_this.props.mentions, _this.state.selectedIndex + 1); _this.selectIndex(newIndex); }); (0, _defineProperty2.default)(_this, "selectPrevious", function () { var newIndex = wrapIndex(_this.props.mentions, _this.state.selectedIndex - 1); _this.selectIndex(newIndex); }); (0, _defineProperty2.default)(_this, "selectIndex", function (index, callback) { var mentions = _this.props.mentions; _this.setState({ selectedIndex: index, selectedKey: getKey(index, mentions) }, callback); }); (0, _defineProperty2.default)(_this, "selectId", function (id, callback) { var mentions = _this.props.mentions; var index = getIndex(id, mentions); if (index !== undefined) { _this.setState({ selectedIndex: index, selectedKey: id }, callback); } }); (0, _defineProperty2.default)(_this, "chooseCurrentSelection", function () { var _this$props = _this.props, mentions = _this$props.mentions, onSelection = _this$props.onSelection; var selectedIndex = _this.state.selectedIndex; var selectedMention = mentions && mentions[selectedIndex || 0]; (0, _logger.default)('ak-mention-list.chooseCurrentSelection', selectedMention); if (onSelection && selectedMention) { onSelection(selectedMention); } }); (0, _defineProperty2.default)(_this, "mentionsCount", function () { var mentions = _this.props.mentions; return mentions && mentions.length || 0; }); (0, _defineProperty2.default)(_this, "selectIndexOnHover", function (mention, event) { if (!event) { return; } var mousePosition = (0, _mouse.mouseLocation)(event); if ((0, _mouse.actualMouseMove)(_this.lastMousePosition, mousePosition)) { _this.selectId(mention.id); } _this.lastMousePosition = mousePosition; }); (0, _defineProperty2.default)(_this, "itemSelected", function (mention) { _this.selectId(mention.id, function () { _this.chooseCurrentSelection(); }); }); (0, _defineProperty2.default)(_this, "handleScrollableRef", function (ref) { _this.scrollable = ref; }); _this.setDefaultSelectionState(); return _this; } (0, _inherits2.default)(MentionList, _React$PureComponent); return (0, _createClass2.default)(MentionList, [{ key: "UNSAFE_componentWillReceiveProps", value: function UNSAFE_componentWillReceiveProps(nextProps) { // adjust selection var mentions = nextProps.mentions; var selectedKey = this.state.selectedKey; if (mentions) { if (!selectedKey) { // don't explicitly set any selected index and go with default behaviour return; } for (var i = 0; i < mentions.length; i++) { if (selectedKey === mentions[i].id) { this.setState({ selectedIndex: i }); return; } } // existing selection not in results so clear any current selection state and go with default behaviour this.setDefaultSelectionState(); } } }, { key: "componentDidUpdate", value: function componentDidUpdate() { var mentions = this.props.mentions; var selectedIndex = this.state.selectedIndex; if (mentions && mentions[selectedIndex]) { this.revealItem(mentions[selectedIndex].id); } // FIXME - a React version of this _may_ be required for Confluence // integration tests. Will remove / fix once known // emit(elem, mentionListRenderedEvent); } }, { key: "revealItem", value: // Internal function revealItem(key) { var item = this.items[key]; if (item && this.scrollable) { this.scrollable.reveal(item); } } /** * The default selection state is to chose index 0 and not have any particular key selected */ }, { key: "setDefaultSelectionState", value: function setDefaultSelectionState() { this.state = { selectedIndex: 0, selectedKey: undefined }; } }, { key: "renderItems", value: function renderItems() { var _this2 = this; var mentions = this.props.mentions; if (mentions && mentions.length) { this.items = {}; return /*#__PURE__*/_react.default.createElement("div", null, this.props.initialHighlightElement, mentions.map(function (mention, idx) { var key = mention.id; var item = /*#__PURE__*/_react.default.createElement(_MentionItem.default, { mention: mention, selected: _this2.isSelectedMention(mention, idx), key: key, onMouseMove: _this2.selectIndexOnHover /* Cannot use onclick, as onblur will close the element, and prevent * onClick from firing. */, onSelection: _this2.itemSelected, ref: function ref(_ref) { if (_ref) { _this2.items[key] = _ref; } else { delete _this2.items[key]; } } }); return item; })); } return null; } }, { key: "isSelectedMention", value: function isSelectedMention(mention, index) { var selectedKey = this.state.selectedKey; return selectedKey ? selectedKey === mention.id : index === 0; } }, { key: "render", value: function render() { var _this$props2 = this.props, mentions = _this$props2.mentions, resourceError = _this$props2.resourceError; var hasMentions = mentions && mentions.length; // If we get an error, but existing mentions are displayed, lets // just continue to show the existing mentions we have var mustShowError = resourceError && !hasMentions; var errorSection; var resultSection; if (mustShowError) { errorSection = /*#__PURE__*/_react.default.createElement(_MentionListError.default, { error: resourceError }); } else if (hasMentions) { resultSection = /*#__PURE__*/_react.default.createElement(_Scrollable.default, { ref: this.handleScrollableRef }, this.renderItems()); } return /*#__PURE__*/_react.default.createElement(_MessagesIntlProvider.default, null, /*#__PURE__*/_react.default.createElement(_styles.MentionListStyle, { empty: !hasMentions && !resourceError }, errorSection, resultSection)); } }]); }(_react.default.PureComponent);