UNPKG

@atlaskit/mention

Version:

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

205 lines (203 loc) 6.96 kB
import _defineProperty from "@babel/runtime/helpers/defineProperty"; import { Text } from '@atlaskit/primitives/compiled'; import withAnalyticsEvents from '@atlaskit/analytics-next/withAnalyticsEvents'; import React from 'react'; import { IntlProvider, injectIntl } from 'react-intl-next'; import { fireAnalyticsMentionTypeaheadEvent } from '../../util/analytics'; import uniqueId from '../../util/id'; import debug from '../../util/logger'; import Popup from '../Popup'; import ResourcedMentionList from '../ResourcedMentionList'; import { MentionPickerInfoStyle, MentionPickerStyle } from './styles'; /** * @class MentionPicker */ export class MentionPicker extends React.PureComponent { constructor(props) { super(props); _defineProperty(this, "selectNext", () => { if (this.mentionListRef) { this.mentionListRef.selectNext(); } }); _defineProperty(this, "selectPrevious", () => { if (this.mentionListRef) { this.mentionListRef.selectPrevious(); } }); _defineProperty(this, "selectIndex", (index, callback) => { if (this.mentionListRef) { this.mentionListRef.selectIndex(index, callback); } }); _defineProperty(this, "selectId", (id, callback) => { if (this.mentionListRef) { this.mentionListRef.selectId(id, callback); } }); _defineProperty(this, "chooseCurrentSelection", () => { if (this.mentionListRef) { this.mentionListRef.chooseCurrentSelection(); } }); _defineProperty(this, "mentionsCount", () => { if (this.mentionListRef) { return this.mentionListRef.mentionsCount(); } return 0; }); /** * Called after the 'visible' state is changed to decide whether the onOpen or onClose * handlers should be called. * * It should be noted that the visible state of the component is not considered in * this function. Instead the old state and new state should be passed as parameters. */ _defineProperty(this, "onFilterVisibilityChange", (oldVisibility, newVisibility) => { if (oldVisibility !== newVisibility) { if (newVisibility) { if (this.props.onOpen) { this.props.onOpen(); } } else { if (this.props.onClose) { this.props.onClose(); } } } }); // internal, used for callbacks _defineProperty(this, "filterChange", (mentions, query, stats) => { debug('ak-mention-picker.filterChange', mentions.length); const wasVisible = this.state.visible; const visible = mentions.length > 0; this.setState({ visible }); this.onFilterVisibilityChange(wasVisible, visible); fireAnalyticsMentionTypeaheadEvent(this.props)('rendered', stats && stats.duration, mentions.map(mention => mention.id), query); }); _defineProperty(this, "filterError", error => { debug('ak-mention-picker.filterError', error); const wasVisible = this.state.visible; this.setState({ visible: true, info: undefined }); this.onFilterVisibilityChange(wasVisible, true); }); _defineProperty(this, "filterInfo", info => { debug('ak-mention-picker.filterInfo', info); this.setState({ info }); }); _defineProperty(this, "handleMentionListRef", ref => { this.mentionListRef = ref; }); this.subscriberKey = uniqueId('ak-mention-picker'); this.state = { visible: false }; this.applyPropChanges({}, props); } componentDidMount() { this.subscribeResourceProvider(this.props.resourceProvider); } UNSAFE_componentWillReceiveProps(nextProps) { this.applyPropChanges(this.props, nextProps); } componentWillUnmount() { this.unsubscribeResourceProvider(this.props.resourceProvider); } // Internal applyPropChanges(prevProps, nextProps) { const oldResourceProvider = prevProps.resourceProvider; const newResourceProvider = nextProps.resourceProvider; const resourceProviderChanged = oldResourceProvider !== newResourceProvider; // resource provider if (resourceProviderChanged) { this.unsubscribeResourceProvider(oldResourceProvider); this.subscribeResourceProvider(newResourceProvider); } } subscribeResourceProvider(resourceProvider) { if (resourceProvider) { resourceProvider.subscribe(this.subscriberKey, this.filterChange, this.filterError, this.filterInfo, undefined); } } unsubscribeResourceProvider(resourceProvider) { if (resourceProvider) { resourceProvider.unsubscribe(this.subscriberKey); } } render() { const { resourceProvider, presenceProvider, onSelection, query, target, position, zIndex, offsetX, offsetY, intl } = this.props; const { visible, info } = this.state; const resourceMentionList = /*#__PURE__*/React.createElement(ResourcedMentionList, { resourceProvider: resourceProvider, presenceProvider: presenceProvider, onSelection: onSelection, query: query, ref: this.handleMentionListRef }); const infoContent = info && !visible ? /*#__PURE__*/React.createElement(MentionPickerInfoStyle, null, /*#__PURE__*/React.createElement(Text, { as: "p" }, info)) : null; let content; if (position) { debug('target, position', target, position); if (target) { content = /*#__PURE__*/React.createElement(Popup, { target: target, relativePosition: position, zIndex: zIndex, offsetX: offsetX, offsetY: offsetY }, /*#__PURE__*/React.createElement(IntlProvider, { locale: (intl === null || intl === void 0 ? void 0 : intl.locale) || 'en' }, /*#__PURE__*/React.createElement("div", null, resourceMentionList, infoContent))); } else { // don't show if we have a position, but no target yet content = null; } } else { content = /*#__PURE__*/React.createElement("div", null, resourceMentionList, infoContent); } return ( /*#__PURE__*/ /* old classnames are essential for Confluence tests */ React.createElement(MentionPickerStyle // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 , { className: "ak-mention-picker", visible: visible || info }, content) ); } } _defineProperty(MentionPicker, "defaultProps", { onSelection: () => {}, onOpen: () => {}, onClose: () => {} }); const MentionPickerWithIntl = injectIntl(MentionPicker, { forwardRef: true }); // @ts-ignore: [PIT-1685] Fails in post-office due to backwards incompatibility issue with React 18 export const MentionPickerWithAnalytics = withAnalyticsEvents({})(MentionPickerWithIntl); export default MentionPickerWithAnalytics;