@atlaskit/editor-plugin-emoji
Version:
Emoji plugin for @atlaskit/editor-core
170 lines • 8.3 kB
JavaScript
import React, { useCallback, useEffect, useMemo } from 'react';
import { useIntl } from 'react-intl';
import { ACTION_SUBJECT_ID, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
import { getDomRefFromSelection } from '@atlaskit/editor-common/get-dom-ref-from-selection';
import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
import { Popup } from '@atlaskit/editor-common/ui';
import { OutsideClickTargetRefContext, withReactEditorViewOuterListeners as withOuterListeners } from '@atlaskit/editor-common/ui-react';
import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
import { akEditorFloatingDialogZIndex } from '@atlaskit/editor-shared-styles';
import { EmojiPicker } from '@atlaskit/emoji';
import { fg } from '@atlaskit/platform-feature-flags';
import { setInlineEmojiPopupOpen } from '../pm-plugins/actions';
const PopupWithListeners = withOuterListeners(Popup);
const emojiPopupMessages = {
emojiPickerAriaLabel: {
id: 'fabric.emoji.picker.aria.label',
defaultMessage: 'Emoji picker',
description: 'Accessible label for the emoji picker popup'
}
};
export const InlineEmojiPopupOld = ({
api,
popupsMountPoint,
popupsBoundariesElement,
popupsScrollableElement,
editorView,
onClose
}) => {
var _useSharedPluginState, _useSharedPluginState2, _api$analytics;
const {
emojiProvider,
inlineEmojiPopupOpen: isOpen
} = (_useSharedPluginState = (_useSharedPluginState2 = useSharedPluginState(api, ['emoji'])) === null || _useSharedPluginState2 === void 0 ? void 0 : _useSharedPluginState2.emojiState) !== null && _useSharedPluginState !== void 0 ? _useSharedPluginState : {};
const intl = useIntl();
useEffect(() => {
if (isOpen && fg('platform_editor_ease_of_use_metrics')) {
var _api$metrics;
api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : (_api$metrics = api.metrics) === null || _api$metrics === void 0 ? void 0 : _api$metrics.commands.handleIntentToStartEdit({
shouldStartTimer: false,
shouldPersistActiveSession: true
}));
}
}, [isOpen, api]);
const handleOnClose = useCallback(() => {
if (fg('platform_editor_ease_of_use_metrics')) {
var _api$metrics2;
api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : (_api$metrics2 = api.metrics) === null || _api$metrics2 === void 0 ? void 0 : _api$metrics2.commands.startActiveSessionTimer());
}
onClose === null || onClose === void 0 ? void 0 : onClose();
}, [onClose, api]);
const focusEditor = useCallback(() => {
// use requestAnimationFrame to run this async after the call
requestAnimationFrame(() => editorView.focus());
}, [editorView]);
const handleSelection = useCallback(emojiId => {
api.core.actions.execute(api.emoji.commands.insertEmoji(emojiId, INPUT_METHOD.PICKER));
handleOnClose();
}, [api.core.actions, api.emoji.commands, handleOnClose]);
if (!isOpen || !emojiProvider) {
return null;
}
const domRef = getDomRefFromSelection(editorView, ACTION_SUBJECT_ID.PICKER_EMOJI, api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions);
return /*#__PURE__*/React.createElement(PopupWithListeners, {
ariaLabel: intl.formatMessage(emojiPopupMessages.emojiPickerAriaLabel)
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
,
offset: [0, 12],
mountTo: popupsMountPoint,
boundariesElement: popupsBoundariesElement,
scrollableElement: popupsScrollableElement,
zIndex: akEditorFloatingDialogZIndex,
fitHeight: 350,
fitWidth: 350,
target: domRef,
onUnmount: focusEditor,
focusTrap: true,
preventOverflow: true,
handleClickOutside: handleOnClose,
handleEscapeKeydown: handleOnClose,
captureClick: true
}, /*#__PURE__*/React.createElement(OutsideClickTargetRefContext.Consumer, null, setOutsideClickTargetRef => /*#__PURE__*/React.createElement(EmojiPicker, {
emojiProvider: Promise.resolve(emojiProvider),
onPickerRef: setOutsideClickTargetRef,
onSelection: handleSelection
})));
};
const InlineEmojiPopupContent = ({
api,
popupsMountPoint,
popupsBoundariesElement,
popupsScrollableElement,
editorView
}) => {
var _api$metrics4, _api$metrics6, _api$analytics3;
const emojiProvider = useSharedPluginStateSelector(api, 'emoji.emojiProvider');
const intl = useIntl();
useEffect(() => {
if (fg('platform_editor_ease_of_use_metrics')) {
var _api$metrics3;
api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : (_api$metrics3 = api.metrics) === null || _api$metrics3 === void 0 ? void 0 : _api$metrics3.commands.handleIntentToStartEdit({
shouldStartTimer: false,
shouldPersistActiveSession: true
}));
}
}, [api === null || api === void 0 ? void 0 : api.core.actions, api === null || api === void 0 ? void 0 : (_api$metrics4 = api.metrics) === null || _api$metrics4 === void 0 ? void 0 : _api$metrics4.commands]);
const handleOnClose = useCallback(() => {
editorView.dispatch(setInlineEmojiPopupOpen(false)(editorView.state.tr));
if (fg('platform_editor_ease_of_use_metrics')) {
var _api$metrics5;
api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : (_api$metrics5 = api.metrics) === null || _api$metrics5 === void 0 ? void 0 : _api$metrics5.commands.startActiveSessionTimer());
}
}, [editorView, api.core.actions, (_api$metrics6 = api.metrics) === null || _api$metrics6 === void 0 ? void 0 : _api$metrics6.commands]);
const focusEditor = useCallback(() => {
// use requestAnimationFrame to run this async after the call
requestAnimationFrame(() => editorView.focus());
}, [editorView]);
const handleSelection = useCallback(emojiId => {
api.core.actions.execute(api.emoji.commands.insertEmoji(emojiId, INPUT_METHOD.PICKER));
handleOnClose();
}, [api.core.actions, api.emoji.commands, handleOnClose]);
const domRef = useMemo(() => {
var _api$analytics2;
return getDomRefFromSelection(editorView, ACTION_SUBJECT_ID.PICKER_EMOJI, api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions);
}, [editorView, api === null || api === void 0 ? void 0 : (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 ? void 0 : _api$analytics3.actions]);
if (!emojiProvider) {
return null;
}
return /*#__PURE__*/React.createElement(PopupWithListeners, {
ariaLabel: intl.formatMessage(emojiPopupMessages.emojiPickerAriaLabel)
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
,
offset: [0, 12],
mountTo: popupsMountPoint,
boundariesElement: popupsBoundariesElement,
scrollableElement: popupsScrollableElement,
zIndex: akEditorFloatingDialogZIndex,
fitHeight: 350,
fitWidth: 350,
target: domRef,
onUnmount: focusEditor,
focusTrap: true,
preventOverflow: true,
handleClickOutside: handleOnClose,
handleEscapeKeydown: handleOnClose,
captureClick: true
}, /*#__PURE__*/React.createElement(OutsideClickTargetRefContext.Consumer, null, setOutsideClickTargetRef => /*#__PURE__*/React.createElement(EmojiPicker, {
emojiProvider: Promise.resolve(emojiProvider),
onPickerRef: setOutsideClickTargetRef,
onSelection: handleSelection
})));
};
export const InlineEmojiPopup = /*#__PURE__*/React.memo(({
api,
popupsMountPoint,
popupsBoundariesElement,
popupsScrollableElement,
editorView
}) => {
const isOpen = useSharedPluginStateSelector(api, 'emoji.inlineEmojiPopupOpen');
if (!isOpen) {
return null;
}
return /*#__PURE__*/React.createElement(InlineEmojiPopupContent, {
api: api,
editorView: editorView,
popupsBoundariesElement: popupsBoundariesElement,
popupsMountPoint: popupsMountPoint,
popupsScrollableElement: popupsScrollableElement
});
});