UNPKG

@wordpress/block-editor

Version:
447 lines (445 loc) 17.2 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/block-editor/src/components/link-control/index.js var link_control_exports = {}; __export(link_control_exports, { DeprecatedExperimentalLinkControl: () => DeprecatedExperimentalLinkControl, default: () => link_control_default }); module.exports = __toCommonJS(link_control_exports); var import_clsx = __toESM(require("clsx")); var import_components = require("@wordpress/components"); var import_i18n = require("@wordpress/i18n"); var import_element = require("@wordpress/element"); var import_compose = require("@wordpress/compose"); var import_dom = require("@wordpress/dom"); var import_keycodes = require("@wordpress/keycodes"); var import_is_shallow_equal = require("@wordpress/is-shallow-equal"); var import_data = require("@wordpress/data"); var import_preferences = require("@wordpress/preferences"); var import_icons = require("@wordpress/icons"); var import_deprecated = __toESM(require("@wordpress/deprecated")); var import_settings_drawer = __toESM(require("./settings-drawer")); var import_search_input = __toESM(require("./search-input")); var import_link_preview = __toESM(require("./link-preview")); var import_settings = __toESM(require("./settings")); var import_use_create_page = __toESM(require("./use-create-page")); var import_use_internal_value = __toESM(require("./use-internal-value")); var import_viewer_slot = require("./viewer-slot"); var import_constants = require("./constants"); var import_jsx_runtime = require("react/jsx-runtime"); var noop = () => { }; var PREFERENCE_SCOPE = "core/block-editor"; var PREFERENCE_KEY = "linkControlSettingsDrawer"; function LinkControl({ searchInputPlaceholder, value, settings = import_constants.DEFAULT_LINK_SETTINGS, onChange = noop, onRemove, onCancel, noDirectEntry = false, showSuggestions = true, showInitialSuggestions, forceIsEditingLink, createSuggestion, withCreateSuggestion, inputValue: propInputValue = "", suggestionsQuery = {}, noURLSuggestion = false, createSuggestionButtonText, hasRichPreviews = false, hasTextControl = false, renderControlBottom = null, handleEntities = false }) { if (withCreateSuggestion === void 0 && createSuggestion) { withCreateSuggestion = true; } const [settingsOpen, setSettingsOpen] = (0, import_element.useState)(false); const { advancedSettingsPreference } = (0, import_data.useSelect)((select) => { const prefsStore = select(import_preferences.store); return { advancedSettingsPreference: prefsStore.get(PREFERENCE_SCOPE, PREFERENCE_KEY) ?? false }; }, []); const { set: setPreference } = (0, import_data.useDispatch)(import_preferences.store); const setSettingsOpenWithPreference = (prefVal) => { if (setPreference) { setPreference(PREFERENCE_SCOPE, PREFERENCE_KEY, prefVal); } setSettingsOpen(prefVal); }; const isSettingsOpen = advancedSettingsPreference || settingsOpen; const isMountingRef = (0, import_element.useRef)(true); const wrapperNode = (0, import_element.useRef)(); const textInputRef = (0, import_element.useRef)(); const searchInputRef = (0, import_element.useRef)(); const entityUrlFallbackRef = (0, import_element.useRef)(); const settingsKeys = settings.map(({ id }) => id); const [ internalControlValue, setInternalControlValue, setInternalURLInputValue, setInternalTextInputValue, createSetInternalSettingValueHandler ] = (0, import_use_internal_value.default)(value); const isEntity = handleEntities && !!internalControlValue?.id; const baseId = (0, import_compose.useInstanceId)(LinkControl, "link-control"); const helpTextId = isEntity ? `${baseId}__help` : null; const valueHasChanges = value && !(0, import_is_shallow_equal.isShallowEqualObjects)(internalControlValue, value); const [isEditingLink, setIsEditingLink] = (0, import_element.useState)( forceIsEditingLink !== void 0 ? forceIsEditingLink : !value || !value.url ); const { createPage, isCreatingPage, errorMessage } = (0, import_use_create_page.default)(createSuggestion); (0, import_element.useEffect)(() => { if (forceIsEditingLink === void 0) { return; } setIsEditingLink(forceIsEditingLink); }, [forceIsEditingLink]); (0, import_element.useEffect)(() => { if (isMountingRef.current) { return; } const nextFocusTarget = import_dom.focus.focusable.find(wrapperNode.current)[0] || wrapperNode.current; nextFocusTarget.focus(); }, [isEditingLink, isCreatingPage]); (0, import_element.useEffect)(() => { isMountingRef.current = false; return () => { isMountingRef.current = true; }; }, []); const hasLinkValue = value?.url?.trim()?.length > 0; const stopEditing = () => { setIsEditingLink(false); }; const handleSelectSuggestion = (updatedValue) => { if (updatedValue?.kind === "taxonomy" && updatedValue?.url) { entityUrlFallbackRef.current = updatedValue.url; } const nonSettingsChanges = Object.keys(updatedValue).reduce( (acc, key) => { if (!settingsKeys.includes(key)) { acc[key] = updatedValue[key]; } return acc; }, {} ); onChange({ ...internalControlValue, ...nonSettingsChanges, // As title is not a setting, it must be manually applied // in such a way as to preserve the users changes over // any "title" value provided by the "suggestion". title: internalControlValue?.title || updatedValue?.title }); stopEditing(); }; const handleSubmit = () => { if (valueHasChanges) { onChange({ ...value, ...internalControlValue, url: currentUrlInputValue }); } stopEditing(); }; const handleSubmitWithEnter = (event) => { const { keyCode } = event; if (keyCode === import_keycodes.ENTER && !currentInputIsEmpty) { event.preventDefault(); handleSubmit(); } }; const resetInternalValues = () => { setInternalControlValue(value); }; const handleCancel = (event) => { event.preventDefault(); event.stopPropagation(); resetInternalValues(); if (hasLinkValue) { stopEditing(); } else { onRemove?.(); } onCancel?.(); }; const [shouldFocusSearchInput, setShouldFocusSearchInput] = (0, import_element.useState)(false); const handleUnlink = () => { const { id, kind, type, ...restValue } = internalControlValue; setInternalControlValue({ ...restValue, id: void 0, kind: void 0, type: void 0, url: void 0 }); setShouldFocusSearchInput(true); }; (0, import_element.useEffect)(() => { if (shouldFocusSearchInput) { searchInputRef.current?.focus(); setShouldFocusSearchInput(false); } }, [shouldFocusSearchInput]); const currentUrlInputValue = propInputValue || internalControlValue?.url || ""; const currentInputIsEmpty = !currentUrlInputValue?.trim()?.length; const shownUnlinkControl = onRemove && value && !isEditingLink && !isCreatingPage; const showActions = isEditingLink && hasLinkValue; const showTextControl = hasLinkValue && hasTextControl; const isEditing = (isEditingLink || !value) && !isCreatingPage; const isDisabled = !valueHasChanges || currentInputIsEmpty; const showSettings = !!settings?.length && isEditingLink && hasLinkValue; const previewValue = (0, import_element.useMemo)(() => { if (value?.kind === "taxonomy" && !value?.url && entityUrlFallbackRef.current) { return { ...value, url: entityUrlFallbackRef.current }; } return value; }, [value]); return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( "div", { tabIndex: -1, ref: wrapperNode, className: "block-editor-link-control", children: [ isCreatingPage && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "block-editor-link-control__loading", children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.Spinner, {}), " ", (0, import_i18n.__)("Creating"), "\u2026" ] }), isEditing && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( "div", { className: (0, import_clsx.default)({ "block-editor-link-control__search-input-wrapper": true, "has-text-control": showTextControl, "has-actions": showActions }), children: [ showTextControl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_components.TextControl, { __nextHasNoMarginBottom: true, ref: textInputRef, className: "block-editor-link-control__field block-editor-link-control__text-content", label: (0, import_i18n.__)("Text"), value: internalControlValue?.title, onChange: setInternalTextInputValue, onKeyDown: handleSubmitWithEnter, __next40pxDefaultSize: true } ), /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_search_input.default, { ref: searchInputRef, currentLink: value, className: "block-editor-link-control__field block-editor-link-control__search-input", placeholder: searchInputPlaceholder, value: currentUrlInputValue, withCreateSuggestion, onCreateSuggestion: createPage, onChange: setInternalURLInputValue, onSelect: handleSelectSuggestion, showInitialSuggestions, allowDirectEntry: !noDirectEntry, showSuggestions, suggestionsQuery, withURLSuggestion: !noURLSuggestion, createSuggestionButtonText, hideLabelFromVision: !showTextControl, isEntity, suffix: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( SearchSuffixControl, { isEntity, showActions, isDisabled, onUnlink: handleUnlink, onSubmit: handleSubmit, helpTextId } ) } ), isEntity && helpTextId && /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "p", { id: helpTextId, className: "block-editor-link-control__help", children: (0, import_i18n.sprintf)( /* translators: %s: entity type (e.g., page, post) */ (0, import_i18n.__)("Synced with the selected %s."), internalControlValue?.type || "item" ) } ) ] } ), errorMessage && /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_components.Notice, { className: "block-editor-link-control__search-error", status: "error", isDismissible: false, children: errorMessage } ) ] }), value && !isEditingLink && !isCreatingPage && /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_link_preview.default, { value: previewValue, onEditClick: () => setIsEditingLink(true), hasRichPreviews, hasUnlinkControl: shownUnlinkControl, onRemove: () => { onRemove(); setIsEditingLink(true); } }, previewValue?.url ), showSettings && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "block-editor-link-control__tools", children: !currentInputIsEmpty && /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_settings_drawer.default, { settingsOpen: isSettingsOpen, setSettingsOpen: setSettingsOpenWithPreference, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_settings.default, { value: internalControlValue, settings, onChange: createSetInternalSettingValueHandler( settingsKeys ) } ) } ) }), showActions && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( import_components.__experimentalHStack, { justify: "right", className: "block-editor-link-control__search-actions", children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_components.Button, { __next40pxDefaultSize: true, variant: "tertiary", onClick: handleCancel, children: (0, import_i18n.__)("Cancel") } ), /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_components.Button, { __next40pxDefaultSize: true, variant: "primary", onClick: isDisabled ? noop : handleSubmit, className: "block-editor-link-control__search-submit", "aria-disabled": isDisabled, children: (0, import_i18n.__)("Apply") } ) ] } ), !isCreatingPage && renderControlBottom && renderControlBottom() ] } ); } function SearchSuffixControl({ isEntity, showActions, isDisabled, onUnlink, onSubmit, helpTextId }) { if (isEntity) { return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_components.Button, { icon: import_icons.linkOff, onClick: onUnlink, "aria-describedby": helpTextId, showTooltip: true, label: (0, import_i18n.__)("Unsync and edit"), __next40pxDefaultSize: true } ); } if (showActions) { return void 0; } return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.__experimentalInputControlSuffixWrapper, { variant: "control", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_components.Button, { onClick: isDisabled ? noop : onSubmit, label: (0, import_i18n.__)("Submit"), icon: import_icons.keyboardReturn, className: "block-editor-link-control__search-submit", "aria-disabled": isDisabled, size: "small" } ) }); } LinkControl.ViewerFill = import_viewer_slot.ViewerFill; LinkControl.DEFAULT_LINK_SETTINGS = import_constants.DEFAULT_LINK_SETTINGS; var DeprecatedExperimentalLinkControl = (props) => { (0, import_deprecated.default)("wp.blockEditor.__experimentalLinkControl", { since: "6.8", alternative: "wp.blockEditor.LinkControl" }); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LinkControl, { ...props }); }; DeprecatedExperimentalLinkControl.ViewerFill = LinkControl.ViewerFill; DeprecatedExperimentalLinkControl.DEFAULT_LINK_SETTINGS = LinkControl.DEFAULT_LINK_SETTINGS; var link_control_default = LinkControl; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { DeprecatedExperimentalLinkControl }); //# sourceMappingURL=index.js.map