UNPKG

@wordpress/editor

Version:
295 lines (293 loc) 9.68 kB
"use strict"; 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/rich-text-control/index.tsx var rich_text_control_exports = {}; __export(rich_text_control_exports, { default: () => RichTextControl }); module.exports = __toCommonJS(rich_text_control_exports); var import_clsx = __toESM(require("clsx")); var import_components = require("@wordpress/components"); var import_compose = require("@wordpress/compose"); var import_element = require("@wordpress/element"); var import_keycodes = require("@wordpress/keycodes"); var import_rich_text = require("@wordpress/rich-text"); var import_lock_unlock = require("../../../lock-unlock.cjs"); var import_utils = require("./utils.cjs"); var import_format_edit = __toESM(require("./format-edit.cjs")); var import_jsx_runtime = require("react/jsx-runtime"); var { ValidatedContentEditableControl: RichTextControlShell } = (0, import_lock_unlock.unlock)( import_components.privateApis ); var { useRichText, KeyboardShortcutContext, InputEventContext, shortcutsListener, inputEventsListener } = (0, import_lock_unlock.unlock)(import_rich_text.privateApis); var EMPTY_COMPLETERS = []; function RichTextControl({ label, value: attrValue, onChange, placeholder, id, clientId, className, hideLabelFromVision, help, disabled, required, markWhenOptional, customValidity, allowedFormats, disableFormats, withoutInteractiveFormatting, preserveWhiteSpace, disableLineBreaks, focusOnMount, completers = EMPTY_COMPLETERS }) { const [selection, setSelection] = (0, import_element.useState)({ start: void 0, end: void 0 }); const [isSelected, setIsSelected] = (0, import_element.useState)(false); const anchorRef = (0, import_element.useRef)(void 0); const inputEvents = (0, import_element.useRef)(/* @__PURE__ */ new Set()); const keyboardShortcuts = (0, import_element.useRef)( /* @__PURE__ */ new Set() ); const focusOutside = (0, import_compose.__experimentalUseFocusOutside)(() => setIsSelected(false)); const adjustedAllowedFormats = (0, import_utils.getAllowedFormats)({ allowedFormats, disableFormats }); const { value, onChange: onRichTextChange, ref: richTextRef, formatTypes, getValue } = useRichText({ value: attrValue, onChange, selectionStart: selection.start, selectionEnd: selection.end, onSelectionChange: (start, end) => setSelection({ start, end }), __unstableIsSelected: isSelected, preserveWhiteSpace: !!preserveWhiteSpace, placeholder, __unstableDisableFormats: disableFormats, allowedFormats: adjustedAllowedFormats, withoutInteractiveFormatting, __unstableFormatTypeHandlerContext: (0, import_element.useMemo)( () => ({ richTextIdentifier: id, blockClientId: clientId }), [id, clientId] ) }); function onFocus() { anchorRef.current?.focus(); } const eventListenersPropsRef = (0, import_element.useRef)({ keyboardShortcuts, inputEvents }); const inputRulePropsRef = (0, import_element.useRef)({ formatTypes, getValue, onChange: onRichTextChange }); (0, import_element.useInsertionEffect)(() => { inputRulePropsRef.current = { formatTypes, getValue, onChange: onRichTextChange }; }); const enterRef = (0, import_compose.useRefEffect)( (element) => { if (disabled) { return; } const onKeyDown = (0, import_keycodes.withIgnoreIMEEvents)((event) => { if (event.key !== "Enter" || event.defaultPrevented || event.metaKey || event.ctrlKey) { return; } event.preventDefault(); if (disableLineBreaks) { return; } const { getValue: getCurrentValue, onChange: handleChange } = inputRulePropsRef.current; const current = getCurrentValue(); handleChange( (0, import_rich_text.insert)( current, "\n", current.start ?? current.text.length, current.end ?? current.text.length ) ); }); element.addEventListener("keydown", onKeyDown); return () => element.removeEventListener("keydown", onKeyDown); }, [disableLineBreaks, disabled] ); const eventListenersRef = (0, import_compose.useRefEffect)( (element) => { if (!isSelected) { return; } const cleanupShortcuts = shortcutsListener( eventListenersPropsRef )(element); const cleanupInputEvents = inputEventsListener( eventListenersPropsRef )(element); function onFormatInput(event) { if (event.inputType !== "insertText" && event.type !== "compositionend") { return; } const { formatTypes: types, getValue: getCurrentValue, onChange: handleChange } = inputRulePropsRef.current; const current = getCurrentValue(); const transformed = types.reduce( (accumulator, { __unstableInputRule }) => __unstableInputRule ? __unstableInputRule(accumulator) : accumulator, current ); if (transformed !== current) { handleChange({ ...transformed, activeFormats: current.activeFormats }); } } element.addEventListener("input", onFormatInput); element.addEventListener("compositionend", onFormatInput); return () => { cleanupShortcuts(); cleanupInputEvents(); element.removeEventListener("input", onFormatInput); element.removeEventListener("compositionend", onFormatInput); }; }, [isSelected] ); const { ref: autocompleteRef, ...autocompleteProps } = (0, import_components.__unstableUseAutocompleteProps)( { completers, record: value, onChange: onRichTextChange, // This control's completers insert their completion into the value; // none replace the whole value, so the required `onReplace` is a // no-op here. onReplace: () => { } } ); const focusOnMountRef = (0, import_compose.useRefEffect)( (element) => { if (focusOnMount && !disabled) { element.focus(); } }, [focusOnMount, disabled] ); const editableRef = (0, import_compose.useMergeRefs)([ richTextRef, anchorRef, eventListenersRef, enterRef, focusOnMountRef, autocompleteRef ]); return ( // Focus boundary for the field's selection: `onFocus` selects on entry; // the spread `useFocusOutside` handlers deselect once focus leaves. /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "div", { ...focusOutside, onFocus: (event) => { setIsSelected(true); focusOutside.onFocus(event); }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_components.SlotFillProvider, { children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)( RichTextControlShell, { label, id, className: (0, import_clsx.default)("editor-rich-text-control", className), placeholder, hideLabelFromVision, help, disabled, required, markWhenOptional, customValidity, value: value.text, "aria-multiline": !disableLineBreaks, ...autocompleteProps, ref: editableRef } ), isSelected && !disabled && /* @__PURE__ */ (0, import_jsx_runtime.jsx)( KeyboardShortcutContext.Provider, { value: keyboardShortcuts, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InputEventContext.Provider, { value: inputEvents, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_format_edit.default, { value, onChange: onRichTextChange, onFocus, formatTypes, forwardedRef: anchorRef, isVisible: true } ) }) } ) ] }) } ) ); } //# sourceMappingURL=index.cjs.map