UNPKG

@atlaskit/editor-plugin-find-replace

Version:

find replace plugin for @atlaskit/editor-core

275 lines (274 loc) 10.8 kB
import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import React, { useState, useRef, useEffect } from 'react'; import { injectIntl } from 'react-intl'; import Button from '@atlaskit/button/new'; import { ACTION, ACTION_SUBJECT, EVENT_TYPE, TRIGGER_METHOD } from '@atlaskit/editor-common/analytics'; import { findReplaceMessages as messages } from '@atlaskit/editor-common/messages'; import { ValidMessage } from '@atlaskit/form'; import ChevronDownIcon from '@atlaskit/icon/core/chevron-down'; import ChevronUpIcon from '@atlaskit/icon/core/chevron-up'; // eslint-disable-next-line @atlaskit/design-system/no-emotion-primitives -- to be migrated to @atlaskit/primitives/compiled – go/akcss import { Box, Inline, Text, xcss } from '@atlaskit/primitives'; import Textfield from '@atlaskit/textfield'; import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals'; import { FindReplaceTooltipButton } from './FindReplaceTooltipButton'; var replaceContainerStyles = xcss({ padding: 'space.100' }); var replaceWithLabelStyle = xcss({ paddingBottom: 'space.050' }); var actionButtonContainerStyles = xcss({ paddingTop: 'space.200' }); var actionButtonParentInlineStyles = xcss({ justifyContent: 'space-between', flexDirection: 'row-reverse' }); var actionButtonParentInlineStylesNew = xcss({ justifyContent: 'space-between', flexDirection: 'row-reverse', flexWrap: 'wrap' }); var actionButtonInlineStyles = xcss({ gap: 'space.075' }); var closeButtonInlineStyles = xcss({ marginRight: 'auto' }); var Replace = function Replace(_ref) { var canReplace = _ref.canReplace, initialReplaceText = _ref.replaceText, onReplace = _ref.onReplace, onReplaceAll = _ref.onReplaceAll, onReplaceTextfieldRefSet = _ref.onReplaceTextfieldRefSet, onArrowUp = _ref.onArrowUp, onCancel = _ref.onCancel, count = _ref.count, onFindNext = _ref.onFindNext, onFindPrev = _ref.onFindPrev, dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent, setFindTyped = _ref.setFindTyped, findTyped = _ref.findTyped, focusToolbarButton = _ref.focusToolbarButton, formatMessage = _ref.intl.formatMessage; var _useState = useState(initialReplaceText || ''), _useState2 = _slicedToArray(_useState, 2), replaceText = _useState2[0], setReplaceText = _useState2[1]; var _useState3 = useState(false), _useState4 = _slicedToArray(_useState3, 2), isComposing = _useState4[0], setIsComposing = _useState4[1]; var _useState5 = useState(false), _useState6 = _slicedToArray(_useState5, 2), isHelperMessageVisible = _useState6[0], setIsHelperMessageVisible = _useState6[1]; var _useState7 = useState(false), _useState8 = _slicedToArray(_useState7, 2), fakeSuccessReplacementMessageUpdate = _useState8[0], setFakeSuccessReplacementMessageUpdate = _useState8[1]; var _useState9 = useState(0), _useState0 = _slicedToArray(_useState9, 2), replaceCount = _useState0[0], setReplaceCount = _useState0[1]; var replaceTextfieldRef = useRef(null); var successReplacementMessageRef = useRef(null); var replaceWith = formatMessage(messages.replaceWith); var replaceAll = formatMessage(messages.replaceAll); var findPrevious = formatMessage(messages.findPrevious); var closeFindReplaceDialog = formatMessage(messages.closeFindReplaceDialog); useEffect(function () { onReplaceTextfieldRefSet(replaceTextfieldRef); }, [onReplaceTextfieldRefSet]); useEffect(function () { setReplaceText(initialReplaceText || ''); }, [initialReplaceText]); var skipWhileComposing = function skipWhileComposing(fn) { if (!isComposing) { fn(); } }; var triggerSuccessReplacementMessageUpdate = function triggerSuccessReplacementMessageUpdate(currentReplaceCount) { if (replaceCount === currentReplaceCount) { setFakeSuccessReplacementMessageUpdate(!fakeSuccessReplacementMessageUpdate); } if (successReplacementMessageRef.current) { var ariaLiveRegion = successReplacementMessageRef.current.querySelector('[aria-live="polite"]'); ariaLiveRegion === null || ariaLiveRegion === void 0 || ariaLiveRegion.removeAttribute('aria-live'); ariaLiveRegion === null || ariaLiveRegion === void 0 || ariaLiveRegion.setAttribute('aria-live', 'polite'); } }; var handleReplaceClick = function handleReplaceClick() { return skipWhileComposing(function () { onReplace({ triggerMethod: TRIGGER_METHOD.BUTTON, replaceText: replaceText }); triggerSuccessReplacementMessageUpdate(1); setIsHelperMessageVisible(true); setReplaceCount(1); setFindTyped(false); }); }; var handleReplaceChange = function handleReplaceChange(event) { return skipWhileComposing(function () { updateReplaceValue(event.target.value); }); }; var updateReplaceValue = function updateReplaceValue(text) { if (dispatchAnalyticsEvent) { dispatchAnalyticsEvent({ eventType: EVENT_TYPE.TRACK, action: ACTION.CHANGED_REPLACEMENT_TEXT, actionSubject: ACTION_SUBJECT.FIND_REPLACE_DIALOG }); } setReplaceText(text); }; var handleReplaceKeyDown = function handleReplaceKeyDown(event) { return skipWhileComposing(function () { if (event.key === 'Enter') { onReplace({ triggerMethod: TRIGGER_METHOD.KEYBOARD, replaceText: replaceText }); } else if (event.key === 'ArrowUp') { onArrowUp(); } }); }; var handleReplaceAllClick = function handleReplaceAllClick() { return skipWhileComposing(function () { onReplaceAll({ replaceText: replaceText }); setIsHelperMessageVisible(true); if (count.totalReplaceable && expValEquals('platform_editor_find_and_replace_improvements', 'isEnabled', true)) { triggerSuccessReplacementMessageUpdate(count.totalReplaceable); setReplaceCount(count.totalReplaceable); } else { triggerSuccessReplacementMessageUpdate(count.total); setReplaceCount(count.total); } setFindTyped(false); }); }; var handleCompositionStart = function handleCompositionStart() { setIsComposing(true); }; var handleCompositionEnd = function handleCompositionEnd(event) { setIsComposing(false); // type for React.CompositionEvent doesn't set type for target correctly updateReplaceValue(event.target.value); }; var clearSearch = function clearSearch() { onCancel({ triggerMethod: TRIGGER_METHOD.BUTTON }); focusToolbarButton(); }; var handleFindNextClick = function handleFindNextClick() { if (!isComposing) { onFindNext({ triggerMethod: TRIGGER_METHOD.BUTTON }); } }; var handleFindPrevClick = function handleFindPrevClick() { if (!isComposing) { onFindPrev({ triggerMethod: TRIGGER_METHOD.BUTTON }); } }; var resultsReplace = formatMessage(messages.replaceSuccess, { numberOfMatches: replaceCount }); return /*#__PURE__*/React.createElement(Box, { xcss: replaceContainerStyles }, /*#__PURE__*/React.createElement(Box, { xcss: replaceWithLabelStyle }, /*#__PURE__*/React.createElement(Text, { id: "replace-text-field-label", size: "medium", weight: "bold", color: "color.text.subtle" }, replaceWith)), /*#__PURE__*/React.createElement(Textfield, { name: "replace", "aria-labelledby": "replace-text-field-label", testId: "replace-field", appearance: "standard", defaultValue: replaceText, ref: replaceTextfieldRef, autoComplete: "off", onChange: handleReplaceChange, onKeyDown: handleReplaceKeyDown, onCompositionStart: handleCompositionStart, onCompositionEnd: handleCompositionEnd }), isHelperMessageVisible && !findTyped && /*#__PURE__*/React.createElement("div", { ref: successReplacementMessageRef }, /*#__PURE__*/React.createElement(ValidMessage, { testId: "message-success-replacement" }, fakeSuccessReplacementMessageUpdate ? // @ts-ignore - TS1501 TypeScript 5.9.2 upgrade resultsReplace.replace(/ /, "\xA0") : resultsReplace)), /*#__PURE__*/React.createElement(Box, { xcss: actionButtonContainerStyles }, /*#__PURE__*/React.createElement(Inline, { xcss: expValEquals('platform_editor_find_and_replace_improvements', 'isEnabled', true) ? [actionButtonInlineStyles, actionButtonParentInlineStylesNew] : [actionButtonInlineStyles, actionButtonParentInlineStyles] }, /*#__PURE__*/React.createElement(Inline, { xcss: actionButtonInlineStyles }, /*#__PURE__*/React.createElement(FindReplaceTooltipButton, { title: formatMessage(messages.findNext) // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , icon: function icon(iconProps) { return /*#__PURE__*/React.createElement(ChevronDownIcon, { label: iconProps.label, size: "small" }); }, iconLabel: formatMessage(messages.findNext), keymapDescription: 'Enter', onClick: handleFindNextClick, disabled: count.total <= 1 }), /*#__PURE__*/React.createElement(FindReplaceTooltipButton, { title: findPrevious // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , icon: function icon(iconProps) { return /*#__PURE__*/React.createElement(ChevronUpIcon, { label: iconProps.label, size: "small" }); }, iconLabel: findPrevious, keymapDescription: 'Shift Enter', onClick: handleFindPrevClick, disabled: count.total <= 1 }), /*#__PURE__*/React.createElement(Button, { testId: 'Replace', id: "replace-button", onClick: handleReplaceClick, isDisabled: !canReplace }, formatMessage(messages.replace)), /*#__PURE__*/React.createElement(Button, { appearance: "primary", testId: replaceAll, id: "replaceAll-button", onClick: handleReplaceAllClick, isDisabled: expValEquals('platform_editor_find_and_replace_improvements', 'isEnabled', true) ? count.totalReplaceable === 0 : !canReplace }, replaceAll)), expValEquals('platform_editor_find_and_replace_improvements', 'isEnabled', true) ? /*#__PURE__*/React.createElement(Inline, { xcss: closeButtonInlineStyles }, /*#__PURE__*/React.createElement(Button, { appearance: "subtle", testId: closeFindReplaceDialog, onClick: clearSearch }, closeFindReplaceDialog)) : /*#__PURE__*/React.createElement(Button, { appearance: "subtle", testId: closeFindReplaceDialog, onClick: clearSearch }, closeFindReplaceDialog)))); }; // eslint-disable-next-line @typescript-eslint/ban-types var _default_1 = injectIntl(Replace); export default _default_1;