@wordpress/editor
Version:
Enhanced block editor for WordPress posts.
322 lines (320 loc) • 11.6 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// packages/editor/src/components/collab-sidebar/note-thread.js
var note_thread_exports = {};
__export(note_thread_exports, {
NoteThread: () => NoteThread
});
module.exports = __toCommonJS(note_thread_exports);
var import_clsx = __toESM(require("clsx"));
var import_element = require("@wordpress/element");
var import_components = require("@wordpress/components");
var import_ui = require("@wordpress/ui");
var import_compose = require("@wordpress/compose");
var import_i18n = require("@wordpress/i18n");
var import_data = require("@wordpress/data");
var import_dom = require("@wordpress/dom");
var import_block_editor = require("@wordpress/block-editor");
var import_add_note = require("./add-note.cjs");
var import_note = require("./note.cjs");
var import_note_card = require("./note-card.cjs");
var import_note_form = require("./note-form.cjs");
var import_floating_container = require("./floating-container.cjs");
var import_utils = require("./utils.cjs");
var import_store = require("../../store/index.cjs");
var import_lock_unlock = require("../../lock-unlock.cjs");
var import_jsx_runtime = require("react/jsx-runtime");
var { useBlockElement } = (0, import_lock_unlock.unlock)(import_block_editor.privateApis);
function NoteThread({
note,
onEditNote,
onAddReply,
onDeleteNote,
isSelected,
sidebarRef,
floating,
onKeyDown
}) {
const isFloating = !!floating;
const { toggleBlockHighlight, selectBlock, toggleBlockSpotlight } = (0, import_lock_unlock.unlock)(
(0, import_data.useDispatch)(import_block_editor.store)
);
const { selectNote } = (0, import_lock_unlock.unlock)((0, import_data.useDispatch)(import_store.store));
const relatedBlockElement = useBlockElement(note.blockClientId);
const debouncedToggleBlockHighlight = (0, import_compose.useDebounce)(
toggleBlockHighlight,
50
);
const floatingRef = (0, import_element.useRef)(null);
const isKeyboardTabbingRef = (0, import_element.useRef)(false);
const registerThread = floating?.registerThread;
const unregisterThread = floating?.unregisterThread;
(0, import_element.useEffect)(() => {
const floatingEl = floatingRef.current;
if (floatingEl && registerThread) {
registerThread(note.id, relatedBlockElement, floatingEl);
}
return () => unregisterThread?.(note.id);
}, [relatedBlockElement, note.id, registerThread, unregisterThread]);
const onMouseEnter = () => {
debouncedToggleBlockHighlight(note.blockClientId, true);
};
const onMouseLeave = () => {
debouncedToggleBlockHighlight(note.blockClientId, false);
};
const onFocus = () => {
toggleBlockHighlight(note.blockClientId, true);
};
const onBlur = (event) => {
if (!document.hasFocus()) {
return;
}
const isNoteFocused = event.relatedTarget?.closest(
".editor-collab-sidebar-panel__thread"
);
const isDialogFocused = event.relatedTarget?.closest('[role="dialog"]');
const isTabbing = isKeyboardTabbingRef.current;
if (isNoteFocused && !isTabbing) {
return;
}
if (isDialogFocused) {
return;
}
if (isTabbing && event.currentTarget.contains(event.relatedTarget)) {
return;
}
toggleBlockHighlight(note.blockClientId, false);
unselectNote();
};
const handleNoteSelect = () => {
selectNote(note.id);
toggleBlockSpotlight(note.blockClientId, true);
if (!!note.blockClientId) {
selectBlock(note.blockClientId, null);
}
};
const unselectNote = () => {
selectNote(void 0);
toggleBlockSpotlight(note.blockClientId, false);
};
const handleResolve = () => {
onEditNote({ id: note.id, status: "approved" });
unselectNote();
if (isFloating) {
relatedBlockElement?.focus();
} else {
(0, import_utils.focusNoteThread)(note.id, sidebarRef.current);
}
};
const allReplies = note?.reply || [];
const lastReply = allReplies.length > 0 ? allReplies[allReplies.length - 1] : void 0;
const restReplies = allReplies.length > 0 ? allReplies.slice(0, -1) : [];
const noteExcerpt = (0, import_utils.getNoteExcerpt)(
(0, import_dom.__unstableStripHTML)(note.content?.rendered),
10
);
const ariaLabel = !!note.blockClientId ? (0, import_i18n.sprintf)(
// translators: %s: note excerpt
(0, import_i18n.__)("Note: %s"),
noteExcerpt
) : (0, import_i18n.sprintf)(
// translators: %s: note excerpt
(0, import_i18n.__)("Original block deleted. Note: %s"),
noteExcerpt
);
if (isFloating && note.id === "new") {
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_add_note.AddNote,
{
onSubmit: onAddReply,
sidebarRef,
floating: { y: floating.y, ref: floatingRef }
}
);
}
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
import_floating_container.FloatingContainer,
{
floating: isFloating ? { y: floating.y, ref: floatingRef } : void 0,
className: (0, import_clsx.default)("editor-collab-sidebar-panel__thread", {
"is-selected": isSelected
}),
id: `note-thread-${note.id}`,
gap: "md",
onClick: handleNoteSelect,
onMouseEnter,
onMouseLeave,
onFocus,
onBlur,
onKeyUp: (event) => {
if (event.key === "Tab") {
isKeyboardTabbingRef.current = false;
}
},
onKeyDown: (event) => {
if (event.key === "Tab") {
isKeyboardTabbingRef.current = true;
} else {
onKeyDown(event);
}
},
tabIndex: 0,
role: "treeitem",
"aria-label": ariaLabel,
"aria-expanded": isSelected,
children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.Button,
{
className: "editor-collab-sidebar-panel__skip-to-note",
variant: "secondary",
size: "compact",
onClick: () => {
(0, import_utils.focusNoteThread)(note.id, sidebarRef.current, "textarea");
},
children: (0, import_i18n.__)("Add new reply")
}
),
!note.blockClientId && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "editor-collab-sidebar-panel__deleted-block-notice", children: (0, import_i18n.__)("Original block deleted.") }),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_note.Note,
{
note,
isSelected,
onEditNote,
onDeleteNote,
onResolve: handleResolve
}
),
isSelected && allReplies.map((reply) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_note.Note,
{
note: reply,
parentNote: note,
isSelected,
onEditNote,
onDeleteNote
},
reply.id
)),
!isSelected && restReplies.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_ui.Stack,
{
direction: "row",
align: "center",
justify: "space-between",
className: "editor-collab-sidebar-panel__more-reply-separator",
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.Button,
{
size: "compact",
variant: "tertiary",
className: "editor-collab-sidebar-panel__more-reply-button",
onClick: () => {
selectNote(note.id);
(0, import_utils.focusNoteThread)(note.id, sidebarRef.current);
},
children: (0, import_i18n.sprintf)(
// translators: %s: number of replies.
(0, import_i18n._n)(
"%s more reply",
"%s more replies",
restReplies.length
),
restReplies.length
)
}
)
}
),
!isSelected && lastReply && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_note.Note,
{
note: lastReply,
parentNote: note,
isSelected: false,
onEditNote,
onDeleteNote
}
),
isSelected && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_note_card.NoteCard, { role: "treeitem", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_note_form.NoteForm,
{
onSubmit: (inputComment) => {
if ("approved" === note.status) {
onEditNote({
id: note.id,
status: "hold",
content: inputComment
});
} else {
onAddReply({
content: inputComment,
parent: note.id
});
}
},
onCancel: (event) => {
event.stopPropagation();
unselectNote();
(0, import_utils.focusNoteThread)(note.id, sidebarRef.current);
},
labels: {
submit: "approved" === note.status ? (0, import_i18n.__)("Reopen & Reply") : (0, import_i18n.__)("Reply"),
input: (0, import_i18n.sprintf)(
// translators: %1$s: note identifier, %2$s: author name
(0, import_i18n.__)("Reply to note %1$s by %2$s"),
note.id,
note.author_name
)
}
}
) }),
!!note.blockClientId && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.Button,
{
className: "editor-collab-sidebar-panel__skip-to-block",
variant: "secondary",
size: "compact",
onClick: (event) => {
event.stopPropagation();
relatedBlockElement?.focus();
},
children: (0, import_i18n.__)("Back to block")
}
)
]
}
);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
NoteThread
});
//# sourceMappingURL=note-thread.cjs.map