@wordpress/block-editor
Version:
447 lines (445 loc) • 17.2 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/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