@primer/react
Version:
An implementation of GitHub's Primer Design System using React
90 lines (83 loc) • 3.79 kB
JavaScript
;
var octiconsReact = require('@primer/octicons-react');
var React = require('react');
var Toolbar = require('./Toolbar.js');
var SelectPanel = require('../../SelectPanel/SelectPanel.js');
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
var React__default = /*#__PURE__*/_interopDefault(React);
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
// SavedRepliesContext is separate from MarkdownEditorContext because the saved replies array is practically guarunteed to change
// on every render. If it was provided in the MarkdownEditorContext, it would cause the whole editor to rerender on every render.
const SavedRepliesContext = /*#__PURE__*/React.createContext(null);
const SavedRepliesButton = () => {
const context = React.useContext(SavedRepliesContext);
React.useImperativeHandle(context === null || context === void 0 ? void 0 : context.ref, () => ({
openMenu: () => {
setOpen(true);
}
}));
const [open, setOpen] = React.useState(false);
React.useEffect(() => setFilter(''), [open]);
const [filter, setFilter] = React.useState('');
// there's not much point in memoizing this since the savedReplies array is likely to change on every render
const items = context === null || context === void 0 ? void 0 : context.savedReplies.filter(({
name
}) => name.toLowerCase().includes(filter.toLowerCase())).map((reply, i) => ({
text: reply.name,
description: reply.content,
descriptionVariant: 'block',
trailingVisual: i < 9 ? `Ctrl + ${i + 1}` : undefined,
sx: {
// hide the leading visual container since we don't use the checkboxes
'& [class*=BaseVisualContainer]:first-child': {
display: 'none'
},
'& [class*=DescriptionContainer]': {
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
maxWidth: '100%'
}
}
}));
const onSelectItem = item => {
setOpen(false);
const reply = context === null || context === void 0 ? void 0 : context.savedReplies.find(({
name
}) => name === (item === null || item === void 0 ? void 0 : item.text));
if (reply) context === null || context === void 0 ? void 0 : context.onSelect(reply);
};
const onKeyDown = event => {
const keyInt = parseInt(event.key, 10);
if (items && event.ctrlKey && !Number.isNaN(keyInt) && keyInt >= 1 && keyInt <= 9) {
event.stopPropagation();
event.preventDefault();
onSelectItem(items[keyInt - 1]);
}
};
return items ? /*#__PURE__*/React__default.default.createElement(SelectPanel.SelectPanel, {
renderAnchor: props => /*#__PURE__*/React__default.default.createElement(Toolbar.ToolbarButton, _extends({}, props, {
icon: octiconsReact.ReplyIcon,
"aria-label": "Add saved reply (Ctrl + .)",
"aria-labelledby": undefined
})),
open: open,
onOpenChange: setOpen,
items: items,
filterValue: filter,
onFilterChange: setFilter,
placeholderText: "Search saved replies",
selected: undefined,
onSelectedChange: selection => {
onSelectItem(Array.isArray(selection) ? selection[0] : selection);
},
overlayProps: {
width: 'small',
maxHeight: 'small',
anchorSide: 'outside-right',
onKeyDown
}
}) : /*#__PURE__*/React__default.default.createElement(React__default.default.Fragment, null);
};
exports.SavedRepliesButton = SavedRepliesButton;
exports.SavedRepliesContext = SavedRepliesContext;