UNPKG

@sklinet/strapi-plugin-tinymce

Version:

Strapi custom field with a customized build of TinyMCE richtext editor.

144 lines (143 loc) 6.02 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const jsxRuntime = require("react/jsx-runtime"); const react = require("react"); const designSystem = require("@strapi/design-system"); const icons = require("@strapi/icons"); const tinymceReact = require("@tinymce/tinymce-react"); const index = require("./index-CoQue_YS.js"); const settings = require("./settings-DJU7OoOr.js"); const admin = require("@strapi/strapi/admin"); const prefixFileUrlWithBackendUrl = (path, url = process.env.STRAPI_ADMIN_BACKEND_URL || process.env.BACKEND_URL || "http://localhost:1337") => { if (path?.startsWith("http")) { return path; } if (url) { return url + path; } else { return path; } }; const TinyEditor = ({ onChange, name, value, disabled, disableMediaLibrary }) => { const { get, post } = admin.useFetchClient(); const [pluginConfig, setPluginConfig] = react.useState(null); const [apiKey, setApiKey] = react.useState(""); const [loading, setLoading] = react.useState(true); prefixFileUrlWithBackendUrl("/api/upload", pluginConfig?.data?.defaultAdminDomain || ""); react.useEffect(() => { const getApiKey = async () => { const data = await settings.taskRequests.getSettings(); if (data) { return setApiKey(data.data.apiKey); } }; const getPluginConfig = async () => { const editor = await get(`/${index.PLUGIN_ID}/config/editor`); if (editor) { setPluginConfig(editor); } }; getApiKey().then(() => { setLoading(false); }); getPluginConfig(); }, []); const imageUploadHandler = react.useCallback( async (blobInfo) => { const data = new FormData(); data.append("files", blobInfo.blob(), blobInfo.filename()); try { const res = await post(`/${index.PLUGIN_ID}/uploadImage`, data); return res.data.location; } catch (error) { console.error("Image upload failed:", error); throw error; } }, [post] ); return !loading && pluginConfig?.data ? /* @__PURE__ */ jsxRuntime.jsx( tinymceReact.Editor, { apiKey: apiKey || "", tinymceScriptSrc: pluginConfig?.data?.tinymceSrc || void 0, value, tagName: name, onEditorChange: (editorContent) => { onChange({ target: { name, value: editorContent } }); }, init: { ...!disableMediaLibrary && { images_upload_handler: imageUploadHandler }, ...disableMediaLibrary && { paste_data_images: false }, ...pluginConfig?.data?.editorConfig } } ) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, {}); }; const MediaLib = ({ isOpen, onChange, onToggle }) => { const mediaLibraryDialog = admin.useStrapiApp("mediaLibrary", (state) => state.components); const MediaDialog = mediaLibraryDialog["media-library"]; const handleSelectAssets = (files) => { const formattedFiles = files.map((f) => ({ alt: f.alternativeText || f.name, url: prefixFileUrlWithBackendUrl(f.url), mime: f.mime })); if (onChange) onChange(formattedFiles); }; if (!isOpen) { return null; } return /* @__PURE__ */ jsxRuntime.jsx(MediaDialog, { onClose: onToggle, onSelectAssets: handleSelectAssets }); }; const Wysiwyg = ({ name, onChange, value, label, disabled, error, required, hint, attribute }) => { const localized = Boolean(attribute?.pluginOptions?.i18n?.localized || false); const disableMediaLibrary = Boolean(attribute?.options?.disableMediaLibrary || false); const [mediaLibVisible, setMediaLibVisible] = react.useState(false); const handleToggleMediaLib = () => setMediaLibVisible((prev) => !prev); const handleChangeAssets = (assets) => { let newValue = value ? value : ""; assets.map((asset) => { if (asset.mime.includes("image")) { const imgTag = `<p><img src="${asset.url}" alt="${asset.alt}"></img></p>`; newValue = `${newValue}${imgTag}`; } if (asset.mime.includes("video")) { const videoTag = `<video><source src="${asset.url}" alt="${asset.alt}"</source></video>`; newValue = `${newValue}${videoTag}`; } }); onChange({ target: { name, value: newValue } }); handleToggleMediaLib(); }; return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [ label && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { paddingBottom: 1, children: [ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral800", children: label }), required && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", textColor: "danger600", children: "*" }), localized && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { paddingLeft: 1, children: /* @__PURE__ */ jsxRuntime.jsx(icons.Earth, { width: 12, height: 12 }) }) ] }), !disableMediaLibrary && /* @__PURE__ */ jsxRuntime.jsx( designSystem.Button, { startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Image, {}), variant: "secondary", fullWidth: true, onClick: handleToggleMediaLib, children: "Media library" } ), /* @__PURE__ */ jsxRuntime.jsx(TinyEditor, { disabled: Boolean(disabled), name, onChange, value, disableMediaLibrary }), (error || hint) && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 1, children: error ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "danger600", children: error }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: hint }) }) ] }), /* @__PURE__ */ jsxRuntime.jsx( MediaLib, { isOpen: mediaLibVisible, onChange: handleChangeAssets, onToggle: handleToggleMediaLib } ) ] }); }; exports.default = Wysiwyg;