@atlaskit/editor-plugin-quick-insert
Version:
Quick insert plugin for @atlaskit/editor-core
214 lines • 9.84 kB
JavaScript
/* RegistryElementBrowser.tsx generated by @compiled/babel-plugin v3.0.2 */
import "./RegistryElementBrowser.compiled.css";
import { ax, ix } from "@compiled/react/runtime";
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useIntl } from 'react-intl';
import IconButton from '@atlaskit/button/icon/button';
import { MENU, RECOMMENDED_SECTION } from '@atlaskit/editor-common/quick-insert/keys';
import { getMenuFooterSectionKey } from '@atlaskit/editor-common/type-ahead-get-menu-footer-section-key';
import { getSectionOverflowItemKey } from '@atlaskit/editor-common/type-ahead-get-section-overflow-item-key';
import Heading from '@atlaskit/heading/heading';
import CrossIcon from '@atlaskit/icon/core/cross';
import ModalBody from '@atlaskit/modal-dialog/modal-body';
import Modal from '@atlaskit/modal-dialog/modal-dialog';
import ModalFooter from '@atlaskit/modal-dialog/modal-footer';
import ModalHeader from '@atlaskit/modal-dialog/modal-header';
import ModalTitle from '@atlaskit/modal-dialog/modal-title';
import ModalTransition from '@atlaskit/modal-dialog/modal-transition';
import { fg } from '@atlaskit/platform-feature-flags/fg';
import Textfield from '@atlaskit/textfield/text-field';
import { createRegistryElementBrowserModel, getInitialRegistryElementBrowserSection, getRegistryElementBrowserItems } from './model';
import { RegistryElementBrowserCategories } from './RegistryElementBrowserCategories';
import { RegistryElementBrowserFooter } from './RegistryElementBrowserFooter';
import { RegistryElementBrowserSearchResults } from './RegistryElementBrowserSearchResults';
const browserGridTemplateColumns = '182px minmax(0, 1fr)';
const categoryColumnGap = `calc(${"var(--ds-space-200, 16px)"} + ${"var(--ds-space-150, 12px)"})`;
const browserLayoutStyles = null;
const headerContentStyles = null;
const headerSearchStyles = null;
const resultsId = 'registry-element-browser-results';
const modalTestId = 'registry-element-browser-modal';
export const RegistryElementBrowser = ({
components,
emptyStateHandler,
defaultSection,
helpUrl,
editorView,
isLoading = false,
isOffline,
isOpen,
onClearSelection,
onClose,
onCloseComplete,
onConfirmInsert,
onSelect
}) => {
var _model$fallbackItems$, _model$fallbackItems;
const {
formatMessage
} = useIntl();
const model = useMemo(() => createRegistryElementBrowserModel(components, {
footerKey: getMenuFooterSectionKey(MENU.key),
overflowKeys: new Set(components.filter(component => component.type === 'menu-section').map(component => getSectionOverflowItemKey(component.key))),
recommendedSectionKey: RECOMMENDED_SECTION.key,
rootKey: MENU.key
}), [components]);
const [query, setQuery] = useState('');
const [section, setSection] = useState(() => getInitialRegistryElementBrowserSection(model, defaultSection));
const [selectedKey, setSelectedKey] = useState();
const searchInputRef = useRef(null);
const wasOpen = useRef(false);
const previousIsOffline = useRef(isOffline);
useEffect(() => {
if (isOpen && !wasOpen.current) {
setQuery('');
setSection(getInitialRegistryElementBrowserSection(model, defaultSection));
// This clears local visual state and the parent-held insertion handler together.
// eslint-disable-next-line @atlassian/perf-linting/no-chain-state-updates
setSelectedKey(undefined);
onClearSelection();
}
wasOpen.current = isOpen;
}, [defaultSection, isOpen, model, onClearSelection]);
const items = useMemo(() => getRegistryElementBrowserItems({
formatMessage,
model,
query,
section
}), [formatMessage, model, query, section]);
const resultCount = items.length || (!isLoading && query.trim() ? (_model$fallbackItems$ = (_model$fallbackItems = model.fallbackItems) === null || _model$fallbackItems === void 0 ? void 0 : _model$fallbackItems.length) !== null && _model$fallbackItems$ !== void 0 ? _model$fallbackItems$ : 0 : 0);
useEffect(() => {
if (previousIsOffline.current !== isOffline) {
setSelectedKey(undefined);
onClearSelection();
}
previousIsOffline.current = isOffline;
}, [isOffline, onClearSelection]);
const onSearchChange = useCallback(event => {
setQuery(event.currentTarget.value);
setSelectedKey(undefined);
onClearSelection();
}, [onClearSelection]);
const onSectionClick = useCallback(event => {
setQuery('');
setSection(event.currentTarget.dataset.section || undefined);
setSelectedKey(undefined);
onClearSelection();
}, [onClearSelection]);
const onClearSearch = useCallback(() => {
var _searchInputRef$curre;
setQuery('');
setSelectedKey(undefined);
onClearSelection();
(_searchInputRef$curre = searchInputRef.current) === null || _searchInputRef$curre === void 0 ? void 0 : _searchInputRef$curre.focus();
}, [onClearSelection]);
const onRegistrySelect = useCallback((key, handler) => {
setSelectedKey(key);
onSelect(handler);
}, [onSelect]);
const onModalOpenComplete = useCallback(node => {
node.style.borderRadius = "var(--ds-radius-large, 8px)";
const footer = node.querySelector(`[data-testid="${modalTestId}--footer"]`);
footer === null || footer === void 0 ? void 0 : footer.style.setProperty('box-sizing', 'border-box');
footer === null || footer === void 0 ? void 0 : footer.style.setProperty('height', '64px');
footer === null || footer === void 0 ? void 0 : footer.style.setProperty('padding-block', "var(--ds-space-200, 16px)");
const scrollableBody = node.querySelector(`[data-testid="${modalTestId}--scrollable"]`);
scrollableBody === null || scrollableBody === void 0 ? void 0 : scrollableBody.style.setProperty('border-block-start', 'none');
scrollableBody === null || scrollableBody === void 0 ? void 0 : scrollableBody.style.setProperty('border-block-end', 'none');
}, []);
const onKeyDown = useCallback(event => {
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
var _resultCollection$que;
const resultCollection = event.currentTarget.ownerDocument.getElementById(resultsId);
const options = Array.from((_resultCollection$que = resultCollection === null || resultCollection === void 0 ? void 0 : resultCollection.querySelectorAll('[role="option"]:not([aria-disabled="true"]):not([disabled])')) !== null && _resultCollection$que !== void 0 ? _resultCollection$que : []);
const currentIndex = options.findIndex(option => option === event.currentTarget.ownerDocument.activeElement);
const nextIndex = event.key === 'ArrowDown' ? currentIndex + 1 : currentIndex - 1;
const nextOption = options.at(nextIndex);
if (nextOption) {
event.preventDefault();
nextOption.focus();
}
return;
}
if (event.key === 'Escape') {
event.preventDefault();
onClose();
return;
}
if (event.key === 'Enter' && selectedKey) {
event.preventDefault();
onConfirmInsert();
}
}, [onClose, onConfirmInsert, selectedKey]);
return /*#__PURE__*/React.createElement(ModalTransition, null, isOpen && /*#__PURE__*/React.createElement(Modal, {
label: formatMessage({
defaultMessage: 'Insert elements',
id: 'editor.quick-insert.title'
}),
height: "664px",
onClose: onClose,
onCloseComplete: onCloseComplete,
onOpenComplete: onModalOpenComplete,
testId: modalTestId,
width: "min(968px, calc(100vw - 32px))"
}, /*#__PURE__*/React.createElement(ModalHeader, null, /*#__PURE__*/React.createElement("div", {
className: ax(["_zulp1fka _1e0c11p5 _yv0e1xuv _1bsb1osq _lk4ji47z"])
}, fg('platform_dst_modal-dialog-use-modal-title') ? /*#__PURE__*/React.createElement(ModalTitle, null, formatMessage({
defaultMessage: 'Insert elements',
id: 'editor.quick-insert.title'
})) : /*#__PURE__*/React.createElement(Heading, {
size: "medium"
}, formatMessage({
defaultMessage: 'Insert elements',
id: 'editor.quick-insert.title'
})), /*#__PURE__*/React.createElement("div", {
className: ax(["_zulp1ejb _4cvr1h6o _1e0c11p5 _yv0ehpfy _1bsb1osq"])
}, /*#__PURE__*/React.createElement(Textfield, {
autoFocus: true,
"aria-controls": resultsId,
"aria-label": formatMessage({
defaultMessage: 'Search elements',
id: 'editor.quick-insert.search'
}),
isCompact: true,
name: "registry-element-browser-search",
onChange: onSearchChange,
onKeyDown: onKeyDown,
ref: searchInputRef,
value: query
}), /*#__PURE__*/React.createElement(IconButton, {
appearance: "subtle",
icon: CrossIcon,
label: formatMessage({
defaultMessage: 'Clear search',
id: 'editor.quick-insert.clear-search'
}),
onClick: onClearSearch,
spacing: "compact"
})))), /*#__PURE__*/React.createElement(ModalBody, null, /*#__PURE__*/React.createElement("div", {
className: ax(["_zulp1fka _1e0c11p5 _yv0e1xuv _lk4ji47z"])
}, /*#__PURE__*/React.createElement(RegistryElementBrowserCategories, {
section: section,
sections: model.sections,
onSectionClick: onSectionClick
}), /*#__PURE__*/React.createElement(RegistryElementBrowserSearchResults, {
editorView: editorView,
emptyStateHandler: emptyStateHandler,
isLoading: isLoading,
isOffline: isOffline,
items: items,
fallbackItems: model.fallbackItems,
query: query,
resultsId: resultsId,
section: section,
selectedKey: selectedKey,
onKeyDown: onKeyDown,
onSelect: onRegistrySelect
}))), /*#__PURE__*/React.createElement(ModalFooter, null, /*#__PURE__*/React.createElement(RegistryElementBrowserFooter, {
helpUrl: helpUrl,
isInsertEnabled: Boolean(selectedKey),
onClose: onClose,
onConfirmInsert: onConfirmInsert,
resultCount: resultCount
}))));
};