@wordpress/editor
Version:
Enhanced block editor for WordPress posts.
8 lines (7 loc) • 21.2 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../../../src/components/collab-sidebar/rich-text-control/index.tsx"],
"sourcesContent": ["import clsx from 'clsx';\nimport type { ReactNode } from 'react';\nimport {\n\tSlotFillProvider,\n\tprivateApis as componentsPrivateApis,\n\t__unstableUseAutocompleteProps as useAutocompleteProps,\n} from '@wordpress/components';\nimport {\n\tuseMergeRefs,\n\tuseRefEffect,\n\t__experimentalUseFocusOutside as useFocusOutside,\n} from '@wordpress/compose';\nimport {\n\tuseInsertionEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from '@wordpress/element';\nimport { withIgnoreIMEEvents } from '@wordpress/keycodes';\nimport {\n\tinsert,\n\tprivateApis as richTextPrivateApis,\n} from '@wordpress/rich-text';\nimport type { EventListenersProps, RichTextValue } from '@wordpress/rich-text';\nimport { unlock } from '../../../lock-unlock';\nimport { getAllowedFormats } from './utils';\nimport FormatEdit from './format-edit';\n\n// The presentational shell: `ContentEditableControl` owns the chrome\n// (`BaseControl` + label and the `contentEditable` element) and has no\n// `@wordpress/rich-text` dependency; the `Validated` wrapper adds the same\n// required/validity treatment the other form controls get. This module is\n// the \"assembly\" that injects the rich-text wiring into it.\nconst { ValidatedContentEditableControl: RichTextControlShell } = unlock(\n\tcomponentsPrivateApis\n);\n\n// `KeyboardShortcutContext` / `InputEventContext` are the same context objects\n// that format types' `RichTextShortcut` / `RichTextInputEvent` read. Format\n// types render those components, so providing these contexts here (below) is\n// what wires their keyboard shortcuts and input events to this field.\n// `shortcutsListener` / `inputEventsListener` dispatch the registered\n// callbacks from the editable element's own events.\nconst {\n\tuseRichText,\n\tKeyboardShortcutContext,\n\tInputEventContext,\n\tshortcutsListener,\n\tinputEventsListener,\n} = unlock( richTextPrivateApis );\n\n// The completer shape isn't exported from `@wordpress/components`, so derive\n// it from the autocomplete hook's own parameter type.\ntype Completer = Parameters<\n\ttypeof useAutocompleteProps\n>[ 0 ][ 'completers' ][ number ];\n\n// Shared empty reference so the default `completers` value is stable across\n// renders and the autocomplete hook doesn't re-run for consumers that don't\n// opt into it.\nconst EMPTY_COMPLETERS: Array< Completer > = [];\n\nexport type RichTextControlProps = {\n\t/**\n\t * Label text for the control.\n\t */\n\tlabel: string;\n\t/**\n\t * The rich text value (HTML string).\n\t */\n\tvalue: string;\n\t/**\n\t * Callback function invoked when the value changes.\n\t */\n\tonChange: ( value: string ) => void;\n\t/**\n\t * Placeholder text displayed when the field is empty.\n\t */\n\tplaceholder?: string;\n\t/**\n\t * Unique identifier for the control.\n\t */\n\tid?: string;\n\t/**\n\t * Block client ID for context (used by format types that need it).\n\t */\n\tclientId?: string;\n\t/**\n\t * Additional class name applied to the contenteditable element.\n\t */\n\tclassName?: string;\n\t/**\n\t * Whether to visually hide the label (still accessible to screen readers).\n\t */\n\thideLabelFromVision?: boolean;\n\t/**\n\t * Help text displayed below the field and linked via `aria-describedby`.\n\t */\n\thelp?: ReactNode;\n\t/**\n\t * Whether the field is non-editable.\n\t */\n\tdisabled?: boolean;\n\t/**\n\t * Whether the field is required.\n\t */\n\trequired?: boolean;\n\t/**\n\t * Label the field as \"optional\" when not `required`, instead of the\n\t * inverse.\n\t */\n\tmarkWhenOptional?: boolean;\n\t/**\n\t * A custom validity message, matching the contract of the `Validated`\n\t * form controls in `@wordpress/components`.\n\t */\n\tcustomValidity?: {\n\t\ttype: 'validating' | 'valid' | 'invalid';\n\t\tmessage?: string;\n\t};\n\t/**\n\t * Array of allowed format types.\n\t */\n\tallowedFormats?: string[];\n\t/**\n\t * Whether to disable all formatting.\n\t */\n\tdisableFormats?: boolean;\n\t/**\n\t * Whether to disable interactive formatting features.\n\t */\n\twithoutInteractiveFormatting?: boolean;\n\t/**\n\t * Whether to preserve whitespace in the content.\n\t */\n\tpreserveWhiteSpace?: boolean;\n\t/**\n\t * Whether to disable line breaks in the content.\n\t */\n\tdisableLineBreaks?: boolean;\n\t/**\n\t * Whether to move focus to the field when it mounts. Off by default; opt\n\t * in for standalone forms where no other code lands focus on the field.\n\t */\n\tfocusOnMount?: boolean;\n\t/**\n\t * Autocompleters to wire to the field (e.g. an `@` mention completer).\n\t * Each is a `WPCompleter` object as consumed by `@wordpress/components`'\n\t * `Autocomplete`. Omit to disable autocomplete.\n\t */\n\tcompleters?: Array< Completer >;\n};\n\n/**\n * Assembles a rich text form field by wiring `@wordpress/rich-text`\n * (`useRichText`, `FormatEdit`, keyboard-shortcut / input-event listeners)\n * into the presentational `ContentEditableControl` shell from\n * `@wordpress/components`.\n *\n * This is the counterpart to the in-canvas `RichText` component from\n * `@wordpress/block-editor`: it exposes a straightforward `value` / `onChange`\n * interface and skips block-editor selection coupling, while still wiring\n * registered format types so familiar keyboard shortcuts (Cmd+B, Cmd+I, Cmd+K)\n * keep working.\n *\n * It lives here, in a package WordPress ships as a script, rather than in\n * `@wordpress/dataviews`: that package is bundled from npm by plugins, so a\n * second copy of `@wordpress/rich-text` — or an `unlock()` against the copy\n * WordPress ships — breaks them (see\n * https://github.com/WordPress/gutenberg/issues/81233). Here\n * `@wordpress/rich-text` is the same `wp.richText` the block editor uses, so\n * the format registry, its store, and its React contexts are shared. A\n * DataForm field can still use it by passing it through a custom `Edit`\n * component.\n */\nexport default function RichTextControl( {\n\tlabel,\n\tvalue: attrValue,\n\tonChange,\n\tplaceholder,\n\tid,\n\tclientId,\n\tclassName,\n\thideLabelFromVision,\n\thelp,\n\tdisabled,\n\trequired,\n\tmarkWhenOptional,\n\tcustomValidity,\n\tallowedFormats,\n\tdisableFormats,\n\twithoutInteractiveFormatting,\n\tpreserveWhiteSpace,\n\tdisableLineBreaks,\n\tfocusOnMount,\n\tcompleters = EMPTY_COMPLETERS,\n}: RichTextControlProps ) {\n\tconst [ selection, setSelection ] = useState< {\n\t\tstart: number | undefined;\n\t\tend: number | undefined;\n\t} >( {\n\t\tstart: undefined,\n\t\tend: undefined,\n\t} );\n\tconst [ isSelected, setIsSelected ] = useState( false );\n\tconst anchorRef = useRef< HTMLElement | undefined >( undefined );\n\tconst inputEvents = useRef( new Set< ( event: Event ) => void >() );\n\tconst keyboardShortcuts = useRef(\n\t\tnew Set< ( event: KeyboardEvent ) => void >()\n\t);\n\n\t// The focus boundary (below) wraps the editable and its format UI. Format\n\t// popovers portal out of it in the DOM but still bubble focus events\n\t// through the React tree, so `useFocusOutside` deselects only once focus\n\t// leaves the field's own UI for good.\n\tconst focusOutside = useFocusOutside( () => setIsSelected( false ) );\n\n\tconst adjustedAllowedFormats = getAllowedFormats( {\n\t\tallowedFormats,\n\t\tdisableFormats,\n\t} );\n\n\tconst {\n\t\tvalue,\n\t\tonChange: onRichTextChange,\n\t\tref: richTextRef,\n\t\tformatTypes,\n\t\tgetValue,\n\t} = useRichText( {\n\t\tvalue: attrValue,\n\t\tonChange,\n\t\tselectionStart: selection.start,\n\t\tselectionEnd: selection.end,\n\t\tonSelectionChange: (\n\t\t\tstart: number | undefined,\n\t\t\tend: number | undefined\n\t\t) => setSelection( { start, end } ),\n\t\t__unstableIsSelected: isSelected,\n\t\tpreserveWhiteSpace: !! preserveWhiteSpace,\n\t\tplaceholder,\n\t\t__unstableDisableFormats: disableFormats,\n\t\tallowedFormats: adjustedAllowedFormats,\n\t\twithoutInteractiveFormatting,\n\t\t__unstableFormatTypeHandlerContext: useMemo(\n\t\t\t() => ( {\n\t\t\t\trichTextIdentifier: id,\n\t\t\t\tblockClientId: clientId,\n\t\t\t} ),\n\t\t\t[ id, clientId ]\n\t\t),\n\t} );\n\n\tfunction onFocus() {\n\t\tanchorRef.current?.focus();\n\t}\n\n\t// Wire registered format keyboard shortcuts (e.g. Cmd+B, Cmd+I, Cmd+K)\n\t// and InputEvent handlers (e.g. native formatBold) to the contenteditable.\n\t// FormatEdit populates these Sets via context; without these listeners the\n\t// callbacks would never fire.\n\tconst eventListenersPropsRef = useRef< EventListenersProps >( {\n\t\tkeyboardShortcuts,\n\t\tinputEvents,\n\t} );\n\n\t// Keep `formatTypes`/`getValue`/`onChange` accessible to the input-rule\n\t// and Enter listeners without retearing them down on every value change.\n\tconst inputRulePropsRef = useRef( {\n\t\tformatTypes,\n\t\tgetValue,\n\t\tonChange: onRichTextChange,\n\t} );\n\tuseInsertionEffect( () => {\n\t\tinputRulePropsRef.current = {\n\t\t\tformatTypes,\n\t\t\tgetValue,\n\t\t\tonChange: onRichTextChange,\n\t\t};\n\t} );\n\n\t/*\n\t * The rich-text hook has no Enter handling of its own. Left to the\n\t * browser, Enter mutates the DOM directly with `<br>` elements (and\n\t * Chrome appends an extra trailing break to keep the caret visible,\n\t * which reads as two new lines). Mirror the block-editor behavior\n\t * instead: prevent the native action and insert the line break into\n\t * the value — or nothing when `disableLineBreaks` is set, matching\n\t * the single-line semantics `aria-multiline` advertises. Presses with\n\t * a meta/ctrl modifier are left to consumers (e.g. a form submitting\n\t * on Cmd+Enter).\n\t */\n\tconst enterRef = useRefEffect< HTMLElement >(\n\t\t( element ) => {\n\t\t\t// A disabled field is not editable; nothing to handle. (Real\n\t\t\t// keyboard input cannot reach it either, since a\n\t\t\t// non-`contentEditable` div is not focusable.)\n\t\t\tif ( disabled ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// During IME composition (e.g. CJK input), Enter confirms the\n\t\t\t// composition rather than requesting a line break, so those\n\t\t\t// presses must reach the browser untouched.\n\t\t\tconst onKeyDown = withIgnoreIMEEvents( ( event: KeyboardEvent ) => {\n\t\t\t\tif (\n\t\t\t\t\tevent.key !== 'Enter' ||\n\t\t\t\t\tevent.defaultPrevented ||\n\t\t\t\t\tevent.metaKey ||\n\t\t\t\t\tevent.ctrlKey\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tevent.preventDefault();\n\t\t\t\tif ( disableLineBreaks ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst { getValue: getCurrentValue, onChange: handleChange } =\n\t\t\t\t\tinputRulePropsRef.current;\n\t\t\t\tconst current: RichTextValue = getCurrentValue();\n\t\t\t\t// Fall back to the end of the content if the selection has\n\t\t\t\t// not been synced into the value yet.\n\t\t\t\thandleChange(\n\t\t\t\t\tinsert(\n\t\t\t\t\t\tcurrent,\n\t\t\t\t\t\t'\\n',\n\t\t\t\t\t\tcurrent.start ?? current.text.length,\n\t\t\t\t\t\tcurrent.end ?? current.text.length\n\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t} );\n\t\t\telement.addEventListener( 'keydown', onKeyDown );\n\t\t\treturn () => element.removeEventListener( 'keydown', onKeyDown );\n\t\t},\n\t\t[ disableLineBreaks, disabled ]\n\t);\n\n\tconst eventListenersRef = useRefEffect< HTMLElement >(\n\t\t( element ) => {\n\t\t\tif ( ! isSelected ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst cleanupShortcuts = shortcutsListener(\n\t\t\t\teventListenersPropsRef\n\t\t\t)( element );\n\t\t\tconst cleanupInputEvents = inputEventsListener(\n\t\t\t\teventListenersPropsRef\n\t\t\t)( element );\n\n\t\t\t// Apply format-level input rules (e.g. `core/code`'s\n\t\t\t// backtick→inline-code transform). Block-transform input rules\n\t\t\t// don't apply to a standalone field.\n\t\t\tfunction onFormatInput( event: Event ) {\n\t\t\t\tif (\n\t\t\t\t\t( event as InputEvent ).inputType !== 'insertText' &&\n\t\t\t\t\tevent.type !== 'compositionend'\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst {\n\t\t\t\t\tformatTypes: types,\n\t\t\t\t\tgetValue: getCurrentValue,\n\t\t\t\t\tonChange: handleChange,\n\t\t\t\t} = inputRulePropsRef.current;\n\t\t\t\tconst current = getCurrentValue();\n\t\t\t\tconst transformed = types.reduce(\n\t\t\t\t\t(\n\t\t\t\t\t\taccumulator: RichTextValue,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t__unstableInputRule,\n\t\t\t\t\t\t}: {\n\t\t\t\t\t\t\t__unstableInputRule?: (\n\t\t\t\t\t\t\t\tvalue: RichTextValue\n\t\t\t\t\t\t\t) => RichTextValue;\n\t\t\t\t\t\t}\n\t\t\t\t\t) =>\n\t\t\t\t\t\t__unstableInputRule\n\t\t\t\t\t\t\t? __unstableInputRule( accumulator )\n\t\t\t\t\t\t\t: accumulator,\n\t\t\t\t\tcurrent\n\t\t\t\t);\n\t\t\t\tif ( transformed !== current ) {\n\t\t\t\t\thandleChange( {\n\t\t\t\t\t\t...transformed,\n\t\t\t\t\t\tactiveFormats: current.activeFormats,\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t\telement.addEventListener( 'input', onFormatInput );\n\t\t\telement.addEventListener( 'compositionend', onFormatInput );\n\n\t\t\treturn () => {\n\t\t\t\tcleanupShortcuts();\n\t\t\t\tcleanupInputEvents();\n\t\t\t\telement.removeEventListener( 'input', onFormatInput );\n\t\t\t\telement.removeEventListener( 'compositionend', onFormatInput );\n\t\t\t};\n\t\t},\n\t\t[ isSelected ]\n\t);\n\n\t/*\n\t * Wire optional autocompleters (e.g. an `@` mention completer) to the\n\t * field. The hook owns the editable element ref it anchors the popover to,\n\t * so we merge its `ref` into the contenteditable below and spread the\n\t * returned props (including the rendered popover as `children`). With no\n\t * `completers` it does no work and renders nothing, keeping the control\n\t * zero-cost for consumers that don't opt in.\n\t */\n\tconst { ref: autocompleteRef, ...autocompleteProps } = useAutocompleteProps(\n\t\t{\n\t\t\tcompleters,\n\t\t\trecord: value,\n\t\t\tonChange: onRichTextChange,\n\t\t\t// This control's completers insert their completion into the value;\n\t\t\t// none replace the whole value, so the required `onReplace` is a\n\t\t\t// no-op here.\n\t\t\tonReplace: () => {},\n\t\t}\n\t);\n\n\t// The shell exposes no focus management of its own (form controls leave\n\t// that to the surrounding region); focus the field on mount here when the\n\t// form opts in.\n\tconst focusOnMountRef = useRefEffect< HTMLElement >(\n\t\t( element ) => {\n\t\t\tif ( focusOnMount && ! disabled ) {\n\t\t\t\telement.focus();\n\t\t\t}\n\t\t},\n\t\t[ focusOnMount, disabled ]\n\t);\n\n\tconst editableRef = useMergeRefs( [\n\t\trichTextRef,\n\t\tanchorRef,\n\t\teventListenersRef,\n\t\tenterRef,\n\t\tfocusOnMountRef,\n\t\tautocompleteRef,\n\t] );\n\n\treturn (\n\t\t// Focus boundary for the field's selection: `onFocus` selects on entry;\n\t\t// the spread `useFocusOutside` handlers deselect once focus leaves.\n\t\t<div\n\t\t\t{ ...focusOutside }\n\t\t\tonFocus={ ( event ) => {\n\t\t\t\tsetIsSelected( true );\n\t\t\t\tfocusOutside.onFocus( event );\n\t\t\t} }\n\t\t>\n\t\t\t{ /*\n\t\t\t * Scopes the format types' `RichText.ToolbarControls.*` fills so\n\t\t\t * they can't reach a surrounding block toolbar.\n\t\t\t */ }\n\t\t\t<SlotFillProvider>\n\t\t\t\t<RichTextControlShell\n\t\t\t\t\tlabel={ label }\n\t\t\t\t\tid={ id }\n\t\t\t\t\tclassName={ clsx( 'editor-rich-text-control', className ) }\n\t\t\t\t\t// The shell draws this while the element is empty, and the\n\t\t\t\t\t// rich-text hook below renders its own placeholder element\n\t\t\t\t\t// once it takes over the contents; either way the attribute\n\t\t\t\t\t// keeps `aria-placeholder` exposed to assistive technology.\n\t\t\t\t\tplaceholder={ placeholder }\n\t\t\t\t\thideLabelFromVision={ hideLabelFromVision }\n\t\t\t\t\thelp={ help }\n\t\t\t\t\tdisabled={ disabled }\n\t\t\t\t\trequired={ required }\n\t\t\t\t\tmarkWhenOptional={ markWhenOptional }\n\t\t\t\t\tcustomValidity={ customValidity }\n\t\t\t\t\t// The shell manages the editable content through the ref; the\n\t\t\t\t\t// plain text only drives its hidden validity delegate.\n\t\t\t\t\tvalue={ value.text }\n\t\t\t\t\taria-multiline={ ! disableLineBreaks }\n\t\t\t\t\t{ ...autocompleteProps }\n\t\t\t\t\tref={ editableRef }\n\t\t\t\t/>\n\t\t\t\t{ /*\n\t\t\t\t * The format assembly mounts only while the field is selected —\n\t\t\t\t * the shell is presentational and knows nothing about selection,\n\t\t\t\t * so this module owns both the state and the gating.\n\t\t\t\t */ }\n\t\t\t\t{ isSelected && ! disabled && (\n\t\t\t\t\t<KeyboardShortcutContext.Provider\n\t\t\t\t\t\tvalue={ keyboardShortcuts }\n\t\t\t\t\t>\n\t\t\t\t\t\t<InputEventContext.Provider value={ inputEvents }>\n\t\t\t\t\t\t\t{ /* Format types gate their inline UIs on `isVisible`. */ }\n\t\t\t\t\t\t\t<FormatEdit\n\t\t\t\t\t\t\t\tvalue={ value }\n\t\t\t\t\t\t\t\tonChange={ onRichTextChange }\n\t\t\t\t\t\t\t\tonFocus={ onFocus }\n\t\t\t\t\t\t\t\tformatTypes={ formatTypes }\n\t\t\t\t\t\t\t\tforwardedRef={ anchorRef }\n\t\t\t\t\t\t\t\tisVisible\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</InputEventContext.Provider>\n\t\t\t\t\t</KeyboardShortcutContext.Provider>\n\t\t\t\t) }\n\t\t\t</SlotFillProvider>\n\t\t</div>\n\t);\n}\n"],
"mappings": "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",
"names": ["componentsPrivateApis", "richTextPrivateApis", "useFocusOutside", "useAutocompleteProps", "clsx", "FormatEdit"]
}