magic-editor-x 1.4.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/dist/_chunks/{App-ByYQ99dO.js → App-DImBvISP.js} +59 -59
  2. package/dist/_chunks/{App-C8q91Ico.mjs → App-iNfbV7cz.mjs} +32 -32
  3. package/dist/_chunks/{CustomBlocksPage-rLRB05j0.mjs → CustomBlocksPage-COPOZ2-_.mjs} +2 -1
  4. package/dist/_chunks/{CustomBlocksPage-BkmF2iOQ.js → CustomBlocksPage-Cj-0TTUs.js} +14 -13
  5. package/dist/_chunks/{LicensePage-Bdn7zWU2.js → LicensePage-CmvILX9m.js} +43 -43
  6. package/dist/_chunks/{LicensePage-DR_Cwyfw.mjs → LicensePage-gLRoo8WJ.mjs} +38 -38
  7. package/dist/_chunks/{LiveCollaborationPanel-BUHIq0CQ.js → LiveCollaborationPanel-BFybu8h0.js} +7 -7
  8. package/dist/_chunks/{LiveCollaborationPanel-0tplv17N.mjs → LiveCollaborationPanel-CVgl4IyR.mjs} +3 -3
  9. package/dist/_chunks/{Settings-FfpVHlpw.mjs → Settings-ButYcfrm.mjs} +82 -82
  10. package/dist/_chunks/Settings-BzGqgrxD.js +440 -0
  11. package/dist/_chunks/{getTranslation-DOJ3x1SL.js → getTranslation-BADoesEn.js} +19120 -12315
  12. package/dist/_chunks/{getTranslation-Bk8tKbUs.mjs → getTranslation-D3h3Z3gU.mjs} +18708 -11903
  13. package/dist/_chunks/index-BXBnwuRw.js +2158 -0
  14. package/dist/_chunks/index-BvEdg518.mjs +2159 -0
  15. package/dist/_chunks/{index-DzixAi6O.js → index-DDFAuQNT.js} +360 -180
  16. package/dist/_chunks/{index-zOiCW1bZ.mjs → index-DEi6nwfM.mjs} +215 -35
  17. package/dist/_chunks/{tools-uudZx91W.mjs → tools-BXzd0lx5.mjs} +3 -3
  18. package/dist/_chunks/{tools-BSMn5LLQ.js → tools-Q0uwDS9E.js} +10 -10
  19. package/dist/admin/index.js +1 -1
  20. package/dist/admin/index.mjs +2 -2
  21. package/dist/server/index.js +142 -135
  22. package/dist/server/index.mjs +142 -135
  23. package/package.json +7 -7
  24. package/dist/_chunks/Settings-B5mffA2O.js +0 -440
  25. package/dist/_chunks/index-C5DuaTDl.js +0 -2550
  26. package/dist/_chunks/index-DkpTkVe7.mjs +0 -2551
@@ -1,14 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
- const React = require("react");
5
- const getTranslation = require("./getTranslation-DOJ3x1SL.js");
4
+ const m = require("react");
5
+ const getTranslation = require("./getTranslation-BADoesEn.js");
6
6
  const styled = require("styled-components");
7
7
  const outline = require("@heroicons/react/24/outline");
8
8
  const EditorJS = require("@editorjs/editorjs");
9
- const tools = require("./tools-BSMn5LLQ.js");
9
+ const tools = require("./tools-Q0uwDS9E.js");
10
10
  const admin = require("@strapi/strapi/admin");
11
- const index = require("./index-C5DuaTDl.js");
11
+ const index = require("./index-BXBnwuRw.js");
12
12
  const socket_ioClient = require("socket.io-client");
13
13
  const Y = require("yjs");
14
14
  const yIndexeddb = require("y-indexeddb");
@@ -31,7 +31,7 @@ function _interopNamespace(e) {
31
31
  n.default = e;
32
32
  return Object.freeze(n);
33
33
  }
34
- const React__default = /* @__PURE__ */ _interopDefault(React);
34
+ const m__default = /* @__PURE__ */ _interopDefault(m);
35
35
  const styled__default = /* @__PURE__ */ _interopDefault(styled);
36
36
  const EditorJS__default = /* @__PURE__ */ _interopDefault(EditorJS);
37
37
  const Y__namespace = /* @__PURE__ */ _interopNamespace(Y);
@@ -780,11 +780,11 @@ const MediaLibComponent = ({
780
780
  allowedTypes = ["images", "files", "videos", "audios"],
781
781
  multiple = true
782
782
  }) => {
783
- const [isLoading, setIsLoading] = React.useState(true);
784
- const [retryCount, setRetryCount] = React.useState(0);
783
+ const [isLoading, setIsLoading] = m.useState(true);
784
+ const [retryCount, setRetryCount] = m.useState(0);
785
785
  const components = admin.useStrapiApp("MediaLibComponent", (state) => state.components);
786
786
  const MediaLibraryDialog = components?.["media-library"];
787
- React.useEffect(() => {
787
+ m.useEffect(() => {
788
788
  if (isOpen && !MediaLibraryDialog && retryCount < 5) {
789
789
  const timer = setTimeout(() => {
790
790
  setRetryCount((prev) => prev + 1);
@@ -793,13 +793,13 @@ const MediaLibComponent = ({
793
793
  }
794
794
  setIsLoading(false);
795
795
  }, [isOpen, MediaLibraryDialog, retryCount]);
796
- React.useEffect(() => {
796
+ m.useEffect(() => {
797
797
  if (!isOpen) {
798
798
  setRetryCount(0);
799
799
  setIsLoading(true);
800
800
  }
801
801
  }, [isOpen]);
802
- React.useEffect(() => {
802
+ m.useEffect(() => {
803
803
  if (isOpen) {
804
804
  console.log("[Magic Editor X] MediaLib opened");
805
805
  console.log("[Magic Editor X] Available components:", Object.keys(components || {}));
@@ -807,7 +807,7 @@ const MediaLibComponent = ({
807
807
  console.log("[Magic Editor X] Retry count:", retryCount);
808
808
  }
809
809
  }, [isOpen, components, MediaLibraryDialog, retryCount]);
810
- const handleSelectAssets = React.useCallback((files) => {
810
+ const handleSelectAssets = m.useCallback((files) => {
811
811
  console.log("[Magic Editor X] Selected assets:", files);
812
812
  if (!files || files.length === 0) {
813
813
  onToggle();
@@ -829,7 +829,7 @@ const MediaLibComponent = ({
829
829
  console.log("[Magic Editor X] Formatted files:", formattedFiles);
830
830
  onChange(formattedFiles);
831
831
  }, [onChange, onToggle]);
832
- const handleClose = React.useCallback(() => {
832
+ const handleClose = m.useCallback(() => {
833
833
  console.log("[Magic Editor X] MediaLib closing");
834
834
  onToggle();
835
835
  }, [onToggle]);
@@ -994,7 +994,7 @@ const MediaLibComponent = ({
994
994
  }
995
995
  ) });
996
996
  };
997
- class MediaLibErrorBoundary extends React__default.default.Component {
997
+ class MediaLibErrorBoundary extends m__default.default.Component {
998
998
  constructor(props) {
999
999
  super(props);
1000
1000
  this.state = { hasError: false, error: null };
@@ -1268,20 +1268,20 @@ const useMagicCollaboration = ({
1268
1268
  const { get, post } = admin.useFetchClient();
1269
1269
  const authContext = admin.useAuth("useMagicCollaboration", (state) => state);
1270
1270
  const user = authContext?.user || null;
1271
- const [status, setStatus] = React.useState(enabled ? "idle" : "disabled");
1272
- const [error, setError] = React.useState(null);
1273
- const [peers, setPeers] = React.useState([]);
1274
- const [awareness, setAwareness] = React.useState({});
1275
- const [collabRole, setCollabRole] = React.useState(null);
1276
- const [canEdit, setCanEdit] = React.useState(null);
1277
- const socketRef = React.useRef(null);
1278
- const persistenceRef = React.useRef(null);
1279
- const bootstrappedRef = React.useRef(false);
1280
- const onRemoteUpdateRef = React.useRef(onRemoteUpdate);
1281
- React.useEffect(() => {
1271
+ const [status, setStatus] = m.useState(enabled ? "idle" : "disabled");
1272
+ const [error, setError] = m.useState(null);
1273
+ const [peers, setPeers] = m.useState([]);
1274
+ const [awareness, setAwareness] = m.useState({});
1275
+ const [collabRole, setCollabRole] = m.useState(null);
1276
+ const [canEdit, setCanEdit] = m.useState(null);
1277
+ const socketRef = m.useRef(null);
1278
+ const persistenceRef = m.useRef(null);
1279
+ const bootstrappedRef = m.useRef(false);
1280
+ const onRemoteUpdateRef = m.useRef(onRemoteUpdate);
1281
+ m.useEffect(() => {
1282
1282
  onRemoteUpdateRef.current = onRemoteUpdate;
1283
1283
  }, [onRemoteUpdate]);
1284
- const { doc, blocksMap, textMap, metaMap } = React.useMemo(() => {
1284
+ const { doc, blocksMap, textMap, metaMap } = m.useMemo(() => {
1285
1285
  const yDoc = new Y__namespace.Doc();
1286
1286
  return {
1287
1287
  doc: yDoc,
@@ -1293,7 +1293,7 @@ const useMagicCollaboration = ({
1293
1293
  // Document metadata (time, blockOrder)
1294
1294
  };
1295
1295
  }, [roomId]);
1296
- const getBlockText = React.useCallback((blockId) => {
1296
+ const getBlockText = m.useCallback((blockId) => {
1297
1297
  if (!blockId) return null;
1298
1298
  let ytext = textMap.get(blockId);
1299
1299
  if (!ytext) {
@@ -1302,7 +1302,7 @@ const useMagicCollaboration = ({
1302
1302
  }
1303
1303
  return ytext;
1304
1304
  }, [textMap]);
1305
- const setBlockText = React.useCallback((blockId, html) => {
1305
+ const setBlockText = m.useCallback((blockId, html) => {
1306
1306
  if (!blockId) return;
1307
1307
  const ytext = getBlockText(blockId);
1308
1308
  if (!ytext) return;
@@ -1316,18 +1316,18 @@ const useMagicCollaboration = ({
1316
1316
  }
1317
1317
  }, "local");
1318
1318
  }, [doc, getBlockText]);
1319
- const getBlockTextHtml = React.useCallback((blockId) => {
1319
+ const getBlockTextHtml = m.useCallback((blockId) => {
1320
1320
  if (!blockId) return "";
1321
1321
  const ytext = textMap.get(blockId);
1322
1322
  if (!ytext) return "";
1323
1323
  return deltaToHtml(ytext.toDelta());
1324
1324
  }, [textMap]);
1325
- React.useEffect(() => {
1325
+ m.useEffect(() => {
1326
1326
  return () => {
1327
1327
  doc.destroy();
1328
1328
  };
1329
1329
  }, [doc]);
1330
- React.useEffect(() => {
1330
+ m.useEffect(() => {
1331
1331
  bootstrappedRef.current = false;
1332
1332
  setPeers([]);
1333
1333
  setAwareness({});
@@ -1342,7 +1342,7 @@ const useMagicCollaboration = ({
1342
1342
  }
1343
1343
  };
1344
1344
  }, [roomId]);
1345
- React.useEffect(() => {
1345
+ m.useEffect(() => {
1346
1346
  if (!enabled) return void 0;
1347
1347
  const cleanupInterval = setInterval(() => {
1348
1348
  const now = Date.now();
@@ -1361,14 +1361,14 @@ const useMagicCollaboration = ({
1361
1361
  }, 1e4);
1362
1362
  return () => clearInterval(cleanupInterval);
1363
1363
  }, [enabled]);
1364
- React.useEffect(() => {
1364
+ m.useEffect(() => {
1365
1365
  if (!enabled) {
1366
1366
  setStatus("disabled");
1367
1367
  } else if (status === "disabled") {
1368
1368
  setStatus("idle");
1369
1369
  }
1370
1370
  }, [enabled, status]);
1371
- React.useEffect(() => {
1371
+ m.useEffect(() => {
1372
1372
  if (!enabled || !roomId) {
1373
1373
  return void 0;
1374
1374
  }
@@ -1376,7 +1376,7 @@ const useMagicCollaboration = ({
1376
1376
  console.log("[Magic Collab] [READY] Client ready, waiting for server sync...");
1377
1377
  return void 0;
1378
1378
  }, [enabled, roomId]);
1379
- React.useEffect(() => {
1379
+ m.useEffect(() => {
1380
1380
  if (!enabled || !roomId || !doc) {
1381
1381
  return void 0;
1382
1382
  }
@@ -1402,11 +1402,11 @@ const useMagicCollaboration = ({
1402
1402
  }
1403
1403
  };
1404
1404
  }, [enabled, roomId, doc]);
1405
- const initialValueRef = React.useRef(initialValue);
1406
- React.useEffect(() => {
1405
+ const initialValueRef = m.useRef(initialValue);
1406
+ m.useEffect(() => {
1407
1407
  initialValueRef.current = initialValue;
1408
1408
  }, [initialValue]);
1409
- React.useEffect(() => {
1409
+ m.useEffect(() => {
1410
1410
  if (!enabled || !roomId || !user) {
1411
1411
  return void 0;
1412
1412
  }
@@ -1583,7 +1583,7 @@ const useMagicCollaboration = ({
1583
1583
  setPeers([]);
1584
1584
  };
1585
1585
  }, [enabled, post, fieldName, roomId, user]);
1586
- React.useEffect(() => {
1586
+ m.useEffect(() => {
1587
1587
  if (!enabled) {
1588
1588
  console.log("[Magic Collab] [SKIP] Update handler not registered (disabled)");
1589
1589
  return void 0;
@@ -1611,12 +1611,12 @@ const useMagicCollaboration = ({
1611
1611
  doc.off("update", handler);
1612
1612
  };
1613
1613
  }, [doc, enabled]);
1614
- const emitAwareness = React.useCallback((payload) => {
1614
+ const emitAwareness = m.useCallback((payload) => {
1615
1615
  if (socketRef.current?.connected) {
1616
1616
  socketRef.current.emit("collab:awareness", payload);
1617
1617
  }
1618
1618
  }, []);
1619
- const localUserColor = React.useMemo(() => {
1619
+ const localUserColor = m.useMemo(() => {
1620
1620
  return user ? getUserColor(user.id) : CURSOR_COLORS[0];
1621
1621
  }, [user]);
1622
1622
  return {
@@ -1658,15 +1658,15 @@ const useMagicCollaboration = ({
1658
1658
  };
1659
1659
  const useLicense = () => {
1660
1660
  const { get } = admin.useFetchClient();
1661
- const [isPremium, setIsPremium] = React.useState(false);
1662
- const [isAdvanced, setIsAdvanced] = React.useState(false);
1663
- const [isEnterprise, setIsEnterprise] = React.useState(false);
1664
- const [tier, setTier] = React.useState("free");
1665
- const [loading, setLoading] = React.useState(true);
1666
- const [error, setError] = React.useState(null);
1667
- const [licenseData, setLicenseData] = React.useState(null);
1668
- const [limits, setLimits] = React.useState(null);
1669
- React.useEffect(() => {
1661
+ const [isPremium, setIsPremium] = m.useState(false);
1662
+ const [isAdvanced, setIsAdvanced] = m.useState(false);
1663
+ const [isEnterprise, setIsEnterprise] = m.useState(false);
1664
+ const [tier, setTier] = m.useState("free");
1665
+ const [loading, setLoading] = m.useState(true);
1666
+ const [error, setError] = m.useState(null);
1667
+ const [licenseData, setLicenseData] = m.useState(null);
1668
+ const [limits, setLimits] = m.useState(null);
1669
+ m.useEffect(() => {
1670
1670
  let mounted = true;
1671
1671
  const fetchLicense = async () => {
1672
1672
  if (mounted) {
@@ -1787,13 +1787,13 @@ const useLicense = () => {
1787
1787
  };
1788
1788
  };
1789
1789
  const useAIActions = ({ licenseKey, editorInstanceRef, isReady, onNoCredits }) => {
1790
- const apiClientRef = React__default.default.useRef(null);
1791
- React__default.default.useEffect(() => {
1790
+ const apiClientRef = m__default.default.useRef(null);
1791
+ m__default.default.useEffect(() => {
1792
1792
  if (licenseKey && !apiClientRef.current) {
1793
1793
  apiClientRef.current = new tools.MagicEditorAPI(licenseKey);
1794
1794
  }
1795
1795
  }, [licenseKey]);
1796
- const replaceText = React.useCallback((range, newText) => {
1796
+ const replaceText = m.useCallback((range, newText) => {
1797
1797
  if (!range) return false;
1798
1798
  try {
1799
1799
  const selection = window.getSelection();
@@ -1812,7 +1812,7 @@ const useAIActions = ({ licenseKey, editorInstanceRef, isReady, onNoCredits }) =
1812
1812
  return false;
1813
1813
  }
1814
1814
  }, [editorInstanceRef, isReady]);
1815
- const appendText = React.useCallback((range, additionalText) => {
1815
+ const appendText = m.useCallback((range, additionalText) => {
1816
1816
  if (!range) return false;
1817
1817
  try {
1818
1818
  const selection = window.getSelection();
@@ -1833,7 +1833,7 @@ const useAIActions = ({ licenseKey, editorInstanceRef, isReady, onNoCredits }) =
1833
1833
  return false;
1834
1834
  }
1835
1835
  }, [editorInstanceRef, isReady]);
1836
- const handleAIAction = React.useCallback(async (action, options, { text, range }) => {
1836
+ const handleAIAction = m.useCallback(async (action, options, { text, range }) => {
1837
1837
  if (!apiClientRef.current || !text) return;
1838
1838
  const originalText = text;
1839
1839
  const langNames = { en: "Englisch", de: "Deutsch", fr: "Französisch", es: "Spanisch" };
@@ -1943,14 +1943,14 @@ const useAIActions = ({ licenseKey, editorInstanceRef, isReady, onNoCredits }) =
1943
1943
  };
1944
1944
  const useWebtoolsLinks = () => {
1945
1945
  const getPlugin = admin.useStrapiApp("WebtoolsLinks", (state) => state.getPlugin);
1946
- const linksPlugin = React.useMemo(() => {
1946
+ const linksPlugin = m.useMemo(() => {
1947
1947
  try {
1948
1948
  return getPlugin?.("webtools-addon-links");
1949
1949
  } catch (e) {
1950
1950
  return null;
1951
1951
  }
1952
1952
  }, [getPlugin]);
1953
- const isAvailable = React.useMemo(() => {
1953
+ const isAvailable = m.useMemo(() => {
1954
1954
  const available = !!linksPlugin?.apis?.openLinkPicker;
1955
1955
  if (typeof window !== "undefined" && !window.__WEBTOOLS_LINKS_CHECKED__) {
1956
1956
  window.__WEBTOOLS_LINKS_CHECKED__ = true;
@@ -1962,7 +1962,7 @@ const useWebtoolsLinks = () => {
1962
1962
  }
1963
1963
  return available;
1964
1964
  }, [linksPlugin]);
1965
- const openLinkPicker = React.useCallback(async ({ initialHref = "", initialText = "" } = {}) => {
1965
+ const openLinkPicker = m.useCallback(async ({ initialHref = "", initialText = "" } = {}) => {
1966
1966
  if (!linksPlugin?.apis?.openLinkPicker) {
1967
1967
  console.warn("[Magic Editor X] Webtools Link Picker not available");
1968
1968
  return null;
@@ -2002,10 +2002,10 @@ const apiBase = "/magic-editor-x";
2002
2002
  const useVersionHistory = () => {
2003
2003
  const { get, post } = admin.useFetchClient();
2004
2004
  const { tier } = useLicense();
2005
- const [snapshots, setSnapshots] = React.useState([]);
2006
- const [loading, setLoading] = React.useState(false);
2007
- const [error, setError] = React.useState(null);
2008
- const fetchSnapshots = React.useCallback(
2005
+ const [snapshots, setSnapshots] = m.useState([]);
2006
+ const [loading, setLoading] = m.useState(false);
2007
+ const [error, setError] = m.useState(null);
2008
+ const fetchSnapshots = m.useCallback(
2009
2009
  async (roomId) => {
2010
2010
  if (!roomId) return;
2011
2011
  setLoading(true);
@@ -2021,7 +2021,7 @@ const useVersionHistory = () => {
2021
2021
  },
2022
2022
  [get]
2023
2023
  );
2024
- const restoreSnapshot = React.useCallback(
2024
+ const restoreSnapshot = m.useCallback(
2025
2025
  async (documentId, roomId) => {
2026
2026
  if (!documentId) return;
2027
2027
  setLoading(true);
@@ -2038,7 +2038,7 @@ const useVersionHistory = () => {
2038
2038
  },
2039
2039
  [get]
2040
2040
  );
2041
- const createSnapshot = React.useCallback(
2041
+ const createSnapshot = m.useCallback(
2042
2042
  async ({ roomId, contentType, entryId, fieldName, content }) => {
2043
2043
  if (!roomId || !contentType || !entryId || !fieldName) return;
2044
2044
  setLoading(true);
@@ -2343,6 +2343,9 @@ function createSimpleBlock(config) {
2343
2343
  this.data[field.name] = input.value;
2344
2344
  });
2345
2345
  break;
2346
+ case "image":
2347
+ input = this._createImageField(field);
2348
+ break;
2346
2349
  default:
2347
2350
  input = document.createElement("input");
2348
2351
  input.type = field.type || "text";
@@ -2365,6 +2368,146 @@ function createSimpleBlock(config) {
2365
2368
  container.appendChild(input);
2366
2369
  return container;
2367
2370
  }
2371
+ /**
2372
+ * Create image field with Media Library integration
2373
+ * @param {object} field - Field configuration
2374
+ * @returns {HTMLElement}
2375
+ */
2376
+ _createImageField(field) {
2377
+ const wrapper = document.createElement("div");
2378
+ wrapper.style.cssText = `
2379
+ border: 2px dashed #e2e8f0;
2380
+ border-radius: 8px;
2381
+ padding: 16px;
2382
+ text-align: center;
2383
+ background: #fafbfc;
2384
+ transition: all 0.2s ease;
2385
+ `;
2386
+ const preview = document.createElement("div");
2387
+ preview.className = "image-preview";
2388
+ preview.style.cssText = `
2389
+ margin-bottom: 12px;
2390
+ min-height: 60px;
2391
+ display: flex;
2392
+ align-items: center;
2393
+ justify-content: center;
2394
+ `;
2395
+ const img = document.createElement("img");
2396
+ img.style.cssText = `
2397
+ max-width: 100%;
2398
+ max-height: 150px;
2399
+ border-radius: 6px;
2400
+ display: none;
2401
+ `;
2402
+ const placeholder = document.createElement("div");
2403
+ placeholder.innerHTML = `
2404
+ <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="#94a3b8" stroke-width="1.5">
2405
+ <rect x="3" y="3" width="18" height="18" rx="2"/>
2406
+ <circle cx="8.5" cy="8.5" r="1.5"/>
2407
+ <path d="M21 15l-5-5L5 21"/>
2408
+ </svg>
2409
+ <p style="margin: 8px 0 0; color: #94a3b8; font-size: 13px;">No image selected</p>
2410
+ `;
2411
+ placeholder.style.cssText = "text-align: center;";
2412
+ preview.appendChild(img);
2413
+ preview.appendChild(placeholder);
2414
+ const updatePreview = (url) => {
2415
+ if (url) {
2416
+ img.src = url;
2417
+ img.style.display = "block";
2418
+ placeholder.style.display = "none";
2419
+ wrapper.style.borderStyle = "solid";
2420
+ wrapper.style.borderColor = "#c4b5fd";
2421
+ } else {
2422
+ img.style.display = "none";
2423
+ placeholder.style.display = "block";
2424
+ wrapper.style.borderStyle = "dashed";
2425
+ wrapper.style.borderColor = "#e2e8f0";
2426
+ }
2427
+ };
2428
+ const currentValue = this.data[field.name];
2429
+ if (currentValue && typeof currentValue === "object") {
2430
+ updatePreview(currentValue.url);
2431
+ } else if (typeof currentValue === "string" && currentValue) {
2432
+ updatePreview(currentValue);
2433
+ }
2434
+ const buttons = document.createElement("div");
2435
+ buttons.style.cssText = "display: flex; gap: 8px; justify-content: center;";
2436
+ const selectBtn = document.createElement("button");
2437
+ selectBtn.type = "button";
2438
+ selectBtn.textContent = "Select Image";
2439
+ selectBtn.style.cssText = `
2440
+ padding: 8px 16px;
2441
+ background: linear-gradient(135deg, #7c3aed 0%, #6d28d9 100%);
2442
+ color: white;
2443
+ border: none;
2444
+ border-radius: 6px;
2445
+ font-size: 13px;
2446
+ font-weight: 600;
2447
+ cursor: pointer;
2448
+ transition: all 0.2s ease;
2449
+ `;
2450
+ selectBtn.addEventListener("mouseenter", () => {
2451
+ selectBtn.style.transform = "translateY(-1px)";
2452
+ selectBtn.style.boxShadow = "0 4px 12px rgba(124, 58, 237, 0.35)";
2453
+ });
2454
+ selectBtn.addEventListener("mouseleave", () => {
2455
+ selectBtn.style.transform = "translateY(0)";
2456
+ selectBtn.style.boxShadow = "none";
2457
+ });
2458
+ const removeBtn = document.createElement("button");
2459
+ removeBtn.type = "button";
2460
+ removeBtn.textContent = "Remove";
2461
+ removeBtn.style.cssText = `
2462
+ padding: 8px 16px;
2463
+ background: transparent;
2464
+ color: #ef4444;
2465
+ border: 1px solid #fecaca;
2466
+ border-radius: 6px;
2467
+ font-size: 13px;
2468
+ font-weight: 600;
2469
+ cursor: pointer;
2470
+ transition: all 0.2s ease;
2471
+ display: ${this.data[field.name] ? "inline-block" : "none"};
2472
+ `;
2473
+ removeBtn.addEventListener("click", () => {
2474
+ this.data[field.name] = null;
2475
+ updatePreview(null);
2476
+ removeBtn.style.display = "none";
2477
+ });
2478
+ selectBtn.addEventListener("click", () => {
2479
+ if (this.readOnly) return;
2480
+ const callbackId = `image_field_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
2481
+ window.__MAGIC_EDITOR_IMAGE_CALLBACKS__ = window.__MAGIC_EDITOR_IMAGE_CALLBACKS__ || {};
2482
+ window.__MAGIC_EDITOR_IMAGE_CALLBACKS__[callbackId] = (files) => {
2483
+ if (files && files.length > 0) {
2484
+ const file = files[0];
2485
+ const imageData = {
2486
+ url: file.url,
2487
+ alt: file.alt || file.name || "",
2488
+ width: file.width,
2489
+ height: file.height,
2490
+ id: file.id,
2491
+ documentId: file.documentId
2492
+ };
2493
+ this.data[field.name] = imageData;
2494
+ updatePreview(imageData.url);
2495
+ removeBtn.style.display = "inline-block";
2496
+ }
2497
+ delete window.__MAGIC_EDITOR_IMAGE_CALLBACKS__[callbackId];
2498
+ };
2499
+ window.dispatchEvent(new CustomEvent("magic-editor-open-media-lib", {
2500
+ detail: { callbackId, fieldName: field.name, allowedTypes: ["images"] }
2501
+ }));
2502
+ });
2503
+ buttons.appendChild(selectBtn);
2504
+ buttons.appendChild(removeBtn);
2505
+ wrapper.appendChild(preview);
2506
+ if (!this.readOnly) {
2507
+ wrapper.appendChild(buttons);
2508
+ }
2509
+ return wrapper;
2510
+ }
2368
2511
  /**
2369
2512
  * Escape HTML special characters
2370
2513
  * @param {string} text - Text to escape
@@ -2418,11 +2561,11 @@ function createBlockClasses(blockConfigs) {
2418
2561
  }
2419
2562
  function useCustomBlocks() {
2420
2563
  const { get } = admin.useFetchClient();
2421
- const [customBlocks, setCustomBlocks] = React.useState([]);
2422
- const [isLoading, setIsLoading] = React.useState(true);
2423
- const [error, setError] = React.useState(null);
2424
- const [lastFetched, setLastFetched] = React.useState(null);
2425
- const fetchCustomBlocks = React.useCallback(async () => {
2564
+ const [customBlocks, setCustomBlocks] = m.useState([]);
2565
+ const [isLoading, setIsLoading] = m.useState(true);
2566
+ const [error, setError] = m.useState(null);
2567
+ const [lastFetched, setLastFetched] = m.useState(null);
2568
+ const fetchCustomBlocks = m.useCallback(async () => {
2426
2569
  try {
2427
2570
  setIsLoading(true);
2428
2571
  setError(null);
@@ -2441,10 +2584,10 @@ function useCustomBlocks() {
2441
2584
  setIsLoading(false);
2442
2585
  }
2443
2586
  }, [get]);
2444
- const refresh = React.useCallback(() => {
2587
+ const refresh = m.useCallback(() => {
2445
2588
  return fetchCustomBlocks();
2446
2589
  }, [fetchCustomBlocks]);
2447
- React.useEffect(() => {
2590
+ m.useEffect(() => {
2448
2591
  fetchCustomBlocks();
2449
2592
  }, [fetchCustomBlocks]);
2450
2593
  return {
@@ -2696,14 +2839,14 @@ const SparklesIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "24",
2696
2839
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M17 19h4" })
2697
2840
  ] });
2698
2841
  const AIAssistantPopup = ({ selectedText, licenseKey, onClose, onApply }) => {
2699
- const [activeType, setActiveType] = React.useState(null);
2700
- const [isLoading, setIsLoading] = React.useState(false);
2701
- const [result, setResult] = React.useState(null);
2702
- const [error, setError] = React.useState(null);
2703
- const [credits, setCredits] = React.useState(0);
2704
- const [usage, setUsage] = React.useState(null);
2705
- const [apiClient, setApiClient] = React.useState(null);
2706
- React.useEffect(() => {
2842
+ const [activeType, setActiveType] = m.useState(null);
2843
+ const [isLoading, setIsLoading] = m.useState(false);
2844
+ const [result, setResult] = m.useState(null);
2845
+ const [error, setError] = m.useState(null);
2846
+ const [credits, setCredits] = m.useState(0);
2847
+ const [usage, setUsage] = m.useState(null);
2848
+ const [apiClient, setApiClient] = m.useState(null);
2849
+ m.useEffect(() => {
2707
2850
  if (licenseKey) {
2708
2851
  const client = new tools.MagicEditorAPI(licenseKey);
2709
2852
  setApiClient(client);
@@ -2715,7 +2858,7 @@ const AIAssistantPopup = ({ selectedText, licenseKey, onClose, onApply }) => {
2715
2858
  });
2716
2859
  }
2717
2860
  }, [licenseKey]);
2718
- const handleCorrection = React.useCallback(async (type) => {
2861
+ const handleCorrection = m.useCallback(async (type) => {
2719
2862
  if (!apiClient || !selectedText) return;
2720
2863
  setActiveType(type);
2721
2864
  setIsLoading(true);
@@ -2745,7 +2888,7 @@ const AIAssistantPopup = ({ selectedText, licenseKey, onClose, onApply }) => {
2745
2888
  setIsLoading(false);
2746
2889
  }
2747
2890
  }, [apiClient, selectedText]);
2748
- const handleApply = React.useCallback(() => {
2891
+ const handleApply = m.useCallback(() => {
2749
2892
  if (result?.corrected) {
2750
2893
  onApply(result.corrected);
2751
2894
  }
@@ -2755,7 +2898,7 @@ const AIAssistantPopup = ({ selectedText, licenseKey, onClose, onApply }) => {
2755
2898
  onClose();
2756
2899
  }
2757
2900
  };
2758
- React.useEffect(() => {
2901
+ m.useEffect(() => {
2759
2902
  const handleKeyDown = (e) => {
2760
2903
  if (e.key === "Escape") {
2761
2904
  onClose();
@@ -2864,7 +3007,7 @@ const AIAssistantPopup = ({ selectedText, licenseKey, onClose, onApply }) => {
2864
3007
  ] })
2865
3008
  ] }) });
2866
3009
  };
2867
- const PanelWrapper = styled__default.default(getTranslation.Box)`
3010
+ const PanelWrapper = styled__default.default(getTranslation.R)`
2868
3011
  width: 320px;
2869
3012
  background: ${({ theme }) => theme.colors.neutral0};
2870
3013
  border: 1px solid ${({ theme }) => theme.colors.neutral150};
@@ -2874,25 +3017,25 @@ const PanelWrapper = styled__default.default(getTranslation.Box)`
2874
3017
  flex-direction: column;
2875
3018
  max-height: 70vh;
2876
3019
  `;
2877
- const Header$1 = styled__default.default(getTranslation.Flex)`
3020
+ const Header$1 = styled__default.default(getTranslation.T)`
2878
3021
  padding: 12px 16px;
2879
3022
  border-bottom: 1px solid ${({ theme }) => theme.colors.neutral150};
2880
3023
  `;
2881
- const Content$1 = styled__default.default(getTranslation.Box)`
3024
+ const Content$1 = styled__default.default(getTranslation.R)`
2882
3025
  padding: 12px 16px;
2883
3026
  overflow-y: auto;
2884
3027
  `;
2885
- const Item = styled__default.default(getTranslation.Box)`
3028
+ const Item = styled__default.default(getTranslation.R)`
2886
3029
  padding: 10px 12px;
2887
3030
  border: 1px solid ${({ theme }) => theme.colors.neutral150};
2888
3031
  border-radius: 6px;
2889
3032
  margin-bottom: 10px;
2890
3033
  `;
2891
- const Meta = styled__default.default(getTranslation.Typography)`
3034
+ const Meta = styled__default.default(getTranslation.I)`
2892
3035
  color: ${({ theme }) => theme.colors.neutral500};
2893
3036
  font-size: 12px;
2894
3037
  `;
2895
- const PremiumBadge = styled__default.default(getTranslation.Box)`
3038
+ const PremiumBadge = styled__default.default(getTranslation.R)`
2896
3039
  background: ${({ theme }) => theme.colors.primary100};
2897
3040
  color: ${({ theme }) => theme.colors.primary600};
2898
3041
  border-radius: 6px;
@@ -2941,33 +3084,33 @@ const VersionHistoryPanel = ({
2941
3084
  );
2942
3085
  return /* @__PURE__ */ jsxRuntime.jsxs(PanelWrapper, { "data-testid": "version-history-panel", children: [
2943
3086
  /* @__PURE__ */ jsxRuntime.jsxs(Header$1, { justifyContent: "space-between", alignItems: "center", children: [
2944
- /* @__PURE__ */ jsxRuntime.jsxs(getTranslation.Flex, { gap: 8, alignItems: "center", children: [
3087
+ /* @__PURE__ */ jsxRuntime.jsxs(getTranslation.T, { gap: 8, alignItems: "center", children: [
2945
3088
  /* @__PURE__ */ jsxRuntime.jsx(outline.ClockIcon, { width: 18 }),
2946
- /* @__PURE__ */ jsxRuntime.jsx(getTranslation.Typography, { fontWeight: "bold", children: t("versionHistory.title", "Version History") })
3089
+ /* @__PURE__ */ jsxRuntime.jsx(getTranslation.I, { fontWeight: "bold", children: t("versionHistory.title", "Version History") })
2947
3090
  ] }),
2948
- /* @__PURE__ */ jsxRuntime.jsx(getTranslation.Button, { size: "S", variant: "tertiary", onClick: onClose, children: t("versionHistory.close", "Close") })
3091
+ /* @__PURE__ */ jsxRuntime.jsx(getTranslation.zn, { size: "S", variant: "tertiary", onClick: onClose, children: t("versionHistory.close", "Close") })
2949
3092
  ] }),
2950
3093
  /* @__PURE__ */ jsxRuntime.jsxs(Content$1, { children: [
2951
- loading && /* @__PURE__ */ jsxRuntime.jsx(getTranslation.Typography, { children: t("versionHistory.loading", "Loading versions...") }),
2952
- error && /* @__PURE__ */ jsxRuntime.jsx(getTranslation.Typography, { textColor: "danger600", children: error }),
2953
- !loading && !error && snapshots.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(getTranslation.Typography, { children: t("versionHistory.noSnapshots", "No versions saved yet") }),
3094
+ loading && /* @__PURE__ */ jsxRuntime.jsx(getTranslation.I, { children: t("versionHistory.loading", "Loading versions...") }),
3095
+ error && /* @__PURE__ */ jsxRuntime.jsx(getTranslation.I, { textColor: "danger600", children: error }),
3096
+ !loading && !error && snapshots.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(getTranslation.I, { children: t("versionHistory.noSnapshots", "No versions saved yet") }),
2954
3097
  !loading && !error && snapshots.map((snap) => /* @__PURE__ */ jsxRuntime.jsxs(Item, { children: [
2955
- /* @__PURE__ */ jsxRuntime.jsxs(getTranslation.Flex, { justifyContent: "space-between", alignItems: "center", children: [
2956
- /* @__PURE__ */ jsxRuntime.jsxs(getTranslation.Typography, { fontWeight: "bold", children: [
3098
+ /* @__PURE__ */ jsxRuntime.jsxs(getTranslation.T, { justifyContent: "space-between", alignItems: "center", children: [
3099
+ /* @__PURE__ */ jsxRuntime.jsxs(getTranslation.I, { fontWeight: "bold", children: [
2957
3100
  t("versionHistory.version", "Version"),
2958
3101
  " ",
2959
3102
  snap.version
2960
3103
  ] }),
2961
- /* @__PURE__ */ jsxRuntime.jsx(getTranslation.Typography, { variant: "pi", children: formatDate(snap.createdAt) })
3104
+ /* @__PURE__ */ jsxRuntime.jsx(getTranslation.I, { variant: "pi", children: formatDate(snap.createdAt) })
2962
3105
  ] }),
2963
3106
  /* @__PURE__ */ jsxRuntime.jsxs(Meta, { children: [
2964
3107
  t("versionHistory.createdBy", "By"),
2965
3108
  " ",
2966
3109
  snap.createdBy?.firstname ? `${snap.createdBy.firstname} ${snap.createdBy.lastname || ""}`.trim() : "—"
2967
3110
  ] }),
2968
- /* @__PURE__ */ jsxRuntime.jsx(getTranslation.Divider, { marginTop: 2, marginBottom: 2 }),
2969
- canRestore ? /* @__PURE__ */ jsxRuntime.jsx(getTranslation.Flex, { gap: 8, children: /* @__PURE__ */ jsxRuntime.jsx(
2970
- getTranslation.Button,
3111
+ /* @__PURE__ */ jsxRuntime.jsx(getTranslation.bl, { marginTop: 2, marginBottom: 2 }),
3112
+ canRestore ? /* @__PURE__ */ jsxRuntime.jsx(getTranslation.T, { gap: 8, children: /* @__PURE__ */ jsxRuntime.jsx(
3113
+ getTranslation.zn,
2971
3114
  {
2972
3115
  size: "S",
2973
3116
  variant: "secondary",
@@ -2979,9 +3122,9 @@ const VersionHistoryPanel = ({
2979
3122
  t("versionHistory.premiumOnly", "Premium feature")
2980
3123
  ] })
2981
3124
  ] }, snap.documentId || snap.id)),
2982
- /* @__PURE__ */ jsxRuntime.jsx(getTranslation.Divider, { marginTop: 4, marginBottom: 4 }),
2983
- canRestore ? /* @__PURE__ */ jsxRuntime.jsx(getTranslation.Button, { size: "S", fullWidth: true, variant: "default", onClick: onCreate, disabled: loading, children: t("versionHistory.create", "Create Snapshot") }) : /* @__PURE__ */ jsxRuntime.jsxs(getTranslation.Box, { children: [
2984
- /* @__PURE__ */ jsxRuntime.jsx(getTranslation.Button, { size: "S", fullWidth: true, variant: "default", disabled: true, children: t("versionHistory.create", "Create Snapshot") }),
3125
+ /* @__PURE__ */ jsxRuntime.jsx(getTranslation.bl, { marginTop: 4, marginBottom: 4 }),
3126
+ canRestore ? /* @__PURE__ */ jsxRuntime.jsx(getTranslation.zn, { size: "S", fullWidth: true, variant: "default", onClick: onCreate, disabled: loading, children: t("versionHistory.create", "Create Snapshot") }) : /* @__PURE__ */ jsxRuntime.jsxs(getTranslation.R, { children: [
3127
+ /* @__PURE__ */ jsxRuntime.jsx(getTranslation.zn, { size: "S", fullWidth: true, variant: "default", disabled: true, children: t("versionHistory.create", "Create Snapshot") }),
2985
3128
  /* @__PURE__ */ jsxRuntime.jsxs(PremiumBadge, { style: { marginTop: "8px", width: "100%", justifyContent: "center" }, children: [
2986
3129
  /* @__PURE__ */ jsxRuntime.jsx(outline.ExclamationTriangleIcon, { width: 16 }),
2987
3130
  t("versionHistory.premiumOnly", "Premium feature")
@@ -5170,7 +5313,7 @@ const getPeerName = (user = {}) => {
5170
5313
  }
5171
5314
  return user.email?.split("@")[0] || "Anonymous";
5172
5315
  };
5173
- const Editor = React.forwardRef(({
5316
+ const Editor = m.forwardRef(({
5174
5317
  name,
5175
5318
  value,
5176
5319
  onChange,
@@ -5189,14 +5332,14 @@ const Editor = React.forwardRef(({
5189
5332
  const { licenseData, tier: licenseTier } = useLicense();
5190
5333
  const { isAvailable: isWebtoolsAvailable, openLinkPicker: webtoolsOpenLinkPicker } = useWebtoolsLinks();
5191
5334
  const { customBlocks, isLoading: isLoadingCustomBlocks } = useCustomBlocks();
5192
- const editorRef = React.useRef(null);
5193
- const editorInstanceRef = React.useRef(null);
5194
- const containerRef = React.useRef(null);
5195
- const webtoolsSelectionRef = React.useRef({ text: "", range: null, blockIndex: -1, existingAnchor: null, existingHref: "" });
5196
- const isReadyRef = React.useRef(false);
5197
- const [isReady, setIsReady] = React.useState(false);
5198
- const [showCreditsModal, setShowCreditsModal] = React.useState(false);
5199
- const [creditsUpgradeInfo, setCreditsUpgradeInfo] = React.useState(null);
5335
+ const editorRef = m.useRef(null);
5336
+ const editorInstanceRef = m.useRef(null);
5337
+ const containerRef = m.useRef(null);
5338
+ const webtoolsSelectionRef = m.useRef({ text: "", range: null, blockIndex: -1, existingAnchor: null, existingHref: "" });
5339
+ const isReadyRef = m.useRef(false);
5340
+ const [isReady, setIsReady] = m.useState(false);
5341
+ const [showCreditsModal, setShowCreditsModal] = m.useState(false);
5342
+ const [creditsUpgradeInfo, setCreditsUpgradeInfo] = m.useState(null);
5200
5343
  const { handleAIAction } = useAIActions({
5201
5344
  licenseKey: licenseData?.licenseKey,
5202
5345
  editorInstanceRef,
@@ -5206,7 +5349,7 @@ const Editor = React.forwardRef(({
5206
5349
  setShowCreditsModal(true);
5207
5350
  }
5208
5351
  });
5209
- React.useEffect(() => {
5352
+ m.useEffect(() => {
5210
5353
  if (licenseData?.licenseKey) {
5211
5354
  window.__MAGIC_EDITOR_LICENSE_KEY__ = licenseData.licenseKey;
5212
5355
  }
@@ -5214,22 +5357,22 @@ const Editor = React.forwardRef(({
5214
5357
  delete window.__MAGIC_EDITOR_LICENSE_KEY__;
5215
5358
  };
5216
5359
  }, [licenseData?.licenseKey]);
5217
- const [blocksCount, setBlocksCount] = React.useState(0);
5218
- const [wordCount, setWordCount] = React.useState(0);
5219
- const [charCount, setCharCount] = React.useState(0);
5220
- const [isFocused, setIsFocused] = React.useState(false);
5221
- const [isFullscreen, setIsFullscreen] = React.useState(false);
5222
- const [editorHeight, setEditorHeight] = React.useState(400);
5223
- const [mediaLibBlockIndex, setMediaLibBlockIndex] = React.useState(-1);
5224
- const [isMediaLibOpen, setIsMediaLibOpen] = React.useState(false);
5225
- const [showAIPopup, setShowAIPopup] = React.useState(false);
5226
- const [showAIToolbar, setShowAIToolbar] = React.useState(false);
5227
- const [aiToolbarPosition, setAIToolbarPosition] = React.useState({ top: 0, left: 0 });
5228
- const [aiSelectedText, setAISelectedText] = React.useState("");
5229
- const aiSelectionRangeRef = React.useRef(null);
5230
- const [aiLoading, setAILoading] = React.useState(false);
5231
- const [showVersionHistory, setShowVersionHistory] = React.useState(false);
5232
- React.useEffect(() => {
5360
+ const [blocksCount, setBlocksCount] = m.useState(0);
5361
+ const [wordCount, setWordCount] = m.useState(0);
5362
+ const [charCount, setCharCount] = m.useState(0);
5363
+ const [isFocused, setIsFocused] = m.useState(false);
5364
+ const [isFullscreen, setIsFullscreen] = m.useState(false);
5365
+ const [editorHeight, setEditorHeight] = m.useState(400);
5366
+ const [mediaLibBlockIndex, setMediaLibBlockIndex] = m.useState(-1);
5367
+ const [isMediaLibOpen, setIsMediaLibOpen] = m.useState(false);
5368
+ const [showAIPopup, setShowAIPopup] = m.useState(false);
5369
+ const [showAIToolbar, setShowAIToolbar] = m.useState(false);
5370
+ const [aiToolbarPosition, setAIToolbarPosition] = m.useState({ top: 0, left: 0 });
5371
+ const [aiSelectedText, setAISelectedText] = m.useState("");
5372
+ const aiSelectionRangeRef = m.useRef(null);
5373
+ const [aiLoading, setAILoading] = m.useState(false);
5374
+ const [showVersionHistory, setShowVersionHistory] = m.useState(false);
5375
+ m.useEffect(() => {
5233
5376
  if (!isWebtoolsAvailable || !editorRef.current) return;
5234
5377
  const updateWebtoolsSelection = () => {
5235
5378
  const selection = window.getSelection();
@@ -5273,13 +5416,13 @@ const Editor = React.forwardRef(({
5273
5416
  document.removeEventListener("selectionchange", updateWebtoolsSelection);
5274
5417
  };
5275
5418
  }, [isWebtoolsAvailable, isReady]);
5276
- const serializedInitialValue = React.useMemo(() => {
5419
+ const serializedInitialValue = m.useMemo(() => {
5277
5420
  if (!value) {
5278
5421
  return "";
5279
5422
  }
5280
5423
  return typeof value === "string" ? value : JSON.stringify(value);
5281
5424
  }, [value]);
5282
- const serializeForCompare = React.useCallback((payload) => {
5425
+ const serializeForCompare = m.useCallback((payload) => {
5283
5426
  if (!payload) return "";
5284
5427
  try {
5285
5428
  const dataObj = typeof payload === "string" ? JSON.parse(payload) : payload;
@@ -5294,9 +5437,9 @@ const Editor = React.forwardRef(({
5294
5437
  return "";
5295
5438
  }
5296
5439
  }, []);
5297
- const collabRoomId = React.useMemo(() => buildRoomId(name), [name]);
5440
+ const collabRoomId = m.useMemo(() => buildRoomId(name), [name]);
5298
5441
  const collabEnabled = (attribute?.options?.collaboration?.enabled ?? true) && !disabled;
5299
- const renderFromYDocRef = React.useRef(null);
5442
+ const renderFromYDocRef = m.useRef(null);
5300
5443
  const {
5301
5444
  doc: yDoc,
5302
5445
  blocksMap: yBlocksMap,
@@ -5333,8 +5476,8 @@ const Editor = React.forwardRef(({
5333
5476
  }
5334
5477
  }
5335
5478
  });
5336
- const yTextBindingsRef = React.useRef(/* @__PURE__ */ new Map());
5337
- const bindBlockToYText = React.useCallback((blockId, element) => {
5479
+ const yTextBindingsRef = m.useRef(/* @__PURE__ */ new Map());
5480
+ const bindBlockToYText = m.useCallback((blockId, element) => {
5338
5481
  if (!collabEnabled || !blockId || !element || !yTextMap) return;
5339
5482
  if (yTextBindingsRef.current.has(blockId)) {
5340
5483
  const existing = yTextBindingsRef.current.get(blockId);
@@ -5409,7 +5552,7 @@ const Editor = React.forwardRef(({
5409
5552
  });
5410
5553
  console.log("[Magic Editor X] [CHAR-SYNC] Bound block to Y.Text:", blockId);
5411
5554
  }, [collabEnabled, yTextMap, yDoc, getBlockText, collabHtmlToDelta, collabDeltaToHtml]);
5412
- const unbindBlockFromYText = React.useCallback((blockId) => {
5555
+ const unbindBlockFromYText = m.useCallback((blockId) => {
5413
5556
  const binding = yTextBindingsRef.current.get(blockId);
5414
5557
  if (!binding) return;
5415
5558
  binding.ytext.unobserve(binding.ytextObserver);
@@ -5417,7 +5560,7 @@ const Editor = React.forwardRef(({
5417
5560
  yTextBindingsRef.current.delete(blockId);
5418
5561
  console.log("[Magic Editor X] [CHAR-SYNC] Unbound block from Y.Text:", blockId);
5419
5562
  }, []);
5420
- const bindAllBlocksToYText = React.useCallback(() => {
5563
+ const bindAllBlocksToYText = m.useCallback(() => {
5421
5564
  if (!collabEnabled || !editorInstanceRef.current || !yTextMap) return;
5422
5565
  const editor = editorInstanceRef.current;
5423
5566
  if (!editor.blocks || typeof editor.blocks.getBlocksCount !== "function") return;
@@ -5445,8 +5588,8 @@ const Editor = React.forwardRef(({
5445
5588
  }
5446
5589
  }
5447
5590
  }, [collabEnabled, yTextMap, getBlockText, setBlockText, bindBlockToYText]);
5448
- const blockObserverRef = React.useRef(null);
5449
- React.useEffect(() => {
5591
+ const blockObserverRef = m.useRef(null);
5592
+ m.useEffect(() => {
5450
5593
  if (!collabEnabled || !editorRef.current || !yTextMap) return;
5451
5594
  const observer = new MutationObserver((mutations) => {
5452
5595
  let hasNewBlocks = false;
@@ -5477,7 +5620,7 @@ const Editor = React.forwardRef(({
5477
5620
  blockObserverRef.current = null;
5478
5621
  };
5479
5622
  }, [collabEnabled, yTextMap, bindAllBlocksToYText]);
5480
- React.useEffect(() => {
5623
+ m.useEffect(() => {
5481
5624
  return () => {
5482
5625
  yTextBindingsRef.current.forEach((binding, blockId) => {
5483
5626
  binding.ytext.unobserve(binding.ytextObserver);
@@ -5494,12 +5637,12 @@ const Editor = React.forwardRef(({
5494
5637
  restoreSnapshot,
5495
5638
  createSnapshot
5496
5639
  } = useVersionHistory();
5497
- React.useEffect(() => {
5640
+ m.useEffect(() => {
5498
5641
  if (showVersionHistory && collabRoomId) {
5499
5642
  fetchSnapshots(collabRoomId);
5500
5643
  }
5501
5644
  }, [showVersionHistory, collabRoomId, fetchSnapshots]);
5502
- React.useMemo(() => {
5645
+ m.useMemo(() => {
5503
5646
  switch (collabRole) {
5504
5647
  case "viewer":
5505
5648
  return { icon: "V", text: "Viewer", color: "#3b82f6" };
@@ -5511,7 +5654,7 @@ const Editor = React.forwardRef(({
5511
5654
  return null;
5512
5655
  }
5513
5656
  }, [collabRole]);
5514
- React.useMemo(() => {
5657
+ m.useMemo(() => {
5515
5658
  switch (collabStatus) {
5516
5659
  case "connected":
5517
5660
  if (collabRole === "viewer") {
@@ -5535,15 +5678,15 @@ const Editor = React.forwardRef(({
5535
5678
  return "Bereit";
5536
5679
  }
5537
5680
  }, [collabStatus, collabRole]);
5538
- React.useMemo(() => collabPeers.slice(0, 3), [collabPeers]);
5539
- const activeEditors = React.useMemo(() => {
5681
+ m.useMemo(() => collabPeers.slice(0, 3), [collabPeers]);
5682
+ const activeEditors = m.useMemo(() => {
5540
5683
  return Object.values(collabAwareness || {}).filter(
5541
5684
  (entry) => entry?.user && Date.now() - entry.lastUpdate < 3e4
5542
5685
  );
5543
5686
  }, [collabAwareness]);
5544
- const lastCursorUpdateRef = React.useRef(0);
5545
- const lastEmittedPositionRef = React.useRef(null);
5546
- const getAbsoluteOffset = React.useCallback((container, node, offset) => {
5687
+ const lastCursorUpdateRef = m.useRef(0);
5688
+ const lastEmittedPositionRef = m.useRef(null);
5689
+ const getAbsoluteOffset = m.useCallback((container, node, offset) => {
5547
5690
  if (!container || !node) return 0;
5548
5691
  let absoluteOffset = 0;
5549
5692
  const walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT, null, false);
@@ -5557,7 +5700,7 @@ const Editor = React.forwardRef(({
5557
5700
  }
5558
5701
  return absoluteOffset + offset;
5559
5702
  }, []);
5560
- const emitCursorPosition = React.useCallback(() => {
5703
+ const emitCursorPosition = m.useCallback(() => {
5561
5704
  if (!collabEnabled || !emitAwareness || collabStatus !== "connected") {
5562
5705
  return;
5563
5706
  }
@@ -5607,7 +5750,7 @@ const Editor = React.forwardRef(({
5607
5750
  } catch (err) {
5608
5751
  }
5609
5752
  }, [collabEnabled, emitAwareness, collabStatus, getAbsoluteOffset]);
5610
- React.useEffect(() => {
5753
+ m.useEffect(() => {
5611
5754
  if (!collabEnabled || !editorRef.current) {
5612
5755
  return void 0;
5613
5756
  }
@@ -5647,7 +5790,7 @@ const Editor = React.forwardRef(({
5647
5790
  }
5648
5791
  };
5649
5792
  }, [collabEnabled, emitCursorPosition]);
5650
- const findTextPosition = React.useCallback((container, targetOffset) => {
5793
+ const findTextPosition = m.useCallback((container, targetOffset) => {
5651
5794
  if (!container || targetOffset === null || targetOffset === void 0) {
5652
5795
  return null;
5653
5796
  }
@@ -5677,8 +5820,8 @@ const Editor = React.forwardRef(({
5677
5820
  }
5678
5821
  return null;
5679
5822
  }, []);
5680
- React.useRef(null);
5681
- React.useEffect(() => {
5823
+ m.useRef(null);
5824
+ m.useEffect(() => {
5682
5825
  if (!collabEnabled || !editorRef.current || !isReady) {
5683
5826
  return void 0;
5684
5827
  }
@@ -5788,7 +5931,7 @@ const Editor = React.forwardRef(({
5788
5931
  cursors?.forEach((el) => el.remove());
5789
5932
  };
5790
5933
  }, [collabEnabled, activeEditors, isReady, findTextPosition]);
5791
- React.useEffect(() => {
5934
+ m.useEffect(() => {
5792
5935
  const state = {
5793
5936
  status: collabStatus,
5794
5937
  peers: collabPeers,
@@ -5805,13 +5948,13 @@ const Editor = React.forwardRef(({
5805
5948
  }));
5806
5949
  };
5807
5950
  }, [collabStatus, collabPeers, collabError]);
5808
- const isApplyingRemoteRef = React.useRef(false);
5809
- const pendingRenderRef = React.useRef(null);
5810
- const lastSerializedValueRef = React.useRef(serializeForCompare(serializedInitialValue || null));
5811
- React.useEffect(() => {
5951
+ const isApplyingRemoteRef = m.useRef(false);
5952
+ const pendingRenderRef = m.useRef(null);
5953
+ const lastSerializedValueRef = m.useRef(serializeForCompare(serializedInitialValue || null));
5954
+ m.useEffect(() => {
5812
5955
  lastSerializedValueRef.current = serializeForCompare(serializedInitialValue || null);
5813
5956
  }, [serializedInitialValue, serializeForCompare]);
5814
- const calculateStats = React.useCallback((data) => {
5957
+ const calculateStats = m.useCallback((data) => {
5815
5958
  if (!data?.blocks) {
5816
5959
  setWordCount(0);
5817
5960
  setCharCount(0);
@@ -5831,7 +5974,7 @@ const Editor = React.forwardRef(({
5831
5974
  setCharCount(plainText.length);
5832
5975
  setWordCount(plainText.split(/\s+/).filter((w) => w.length > 0).length);
5833
5976
  }, []);
5834
- const renderFromYDoc = React.useCallback(async () => {
5977
+ const renderFromYDoc = m.useCallback(async () => {
5835
5978
  if (!collabEnabled || !yBlocksMap || !yDoc) {
5836
5979
  return;
5837
5980
  }
@@ -5946,10 +6089,10 @@ const Editor = React.forwardRef(({
5946
6089
  isApplyingRemoteRef.current = false;
5947
6090
  }
5948
6091
  }, [collabEnabled, yBlocksMap, yDoc, yMetaMap]);
5949
- React.useEffect(() => {
6092
+ m.useEffect(() => {
5950
6093
  renderFromYDocRef.current = renderFromYDoc;
5951
6094
  }, [renderFromYDoc]);
5952
- const pushLocalToCollab = React.useCallback((payload) => {
6095
+ const pushLocalToCollab = m.useCallback((payload) => {
5953
6096
  console.log("[Magic Editor X] [PUSH] pushLocalToCollab called, enabled:", collabEnabled, "yDoc:", !!yDoc, "yBlocksMap:", !!yBlocksMap);
5954
6097
  if (!collabEnabled || !yDoc || !yBlocksMap) {
5955
6098
  console.log("[Magic Editor X] [SKIP] Skipping push - not enabled or missing yDoc/yBlocksMap");
@@ -5994,20 +6137,20 @@ const Editor = React.forwardRef(({
5994
6137
  console.error("[Magic Editor X] Failed to push local update", error2);
5995
6138
  }
5996
6139
  }, [collabEnabled, yDoc, yBlocksMap, yMetaMap]);
5997
- const pushLocalToCollabRef = React.useRef(pushLocalToCollab);
5998
- React.useEffect(() => {
6140
+ const pushLocalToCollabRef = m.useRef(pushLocalToCollab);
6141
+ m.useEffect(() => {
5999
6142
  pushLocalToCollabRef.current = pushLocalToCollab;
6000
6143
  }, [pushLocalToCollab]);
6001
6144
  const customPlaceholder = attribute?.options?.placeholder || placeholder || "Start writing your amazing content...";
6002
6145
  attribute?.options?.minHeight || 400;
6003
- const mediaLibToggleFunc = React.useCallback(
6146
+ const mediaLibToggleFunc = m.useCallback(
6004
6147
  getToggleFunc({
6005
6148
  openStateSetter: setIsMediaLibOpen,
6006
6149
  indexStateSetter: setMediaLibBlockIndex
6007
6150
  }),
6008
6151
  []
6009
6152
  );
6010
- const handleMediaLibChange = React.useCallback(
6153
+ const handleMediaLibChange = m.useCallback(
6011
6154
  (data) => {
6012
6155
  changeFunc({
6013
6156
  indexStateSetter: setMediaLibBlockIndex,
@@ -6019,7 +6162,38 @@ const Editor = React.forwardRef(({
6019
6162
  },
6020
6163
  [mediaLibBlockIndex, mediaLibToggleFunc]
6021
6164
  );
6022
- const toggleFullscreen = React.useCallback(() => {
6165
+ const [customBlockImageCallback, setCustomBlockImageCallback] = m.useState(null);
6166
+ const handleCustomBlockMediaLibChange = m.useCallback((data) => {
6167
+ if (customBlockImageCallback && window.__MAGIC_EDITOR_IMAGE_CALLBACKS__) {
6168
+ const callback = window.__MAGIC_EDITOR_IMAGE_CALLBACKS__[customBlockImageCallback];
6169
+ if (callback) {
6170
+ const formattedData = data.map((file) => ({
6171
+ url: file.url,
6172
+ alt: file.alt || file.name || "",
6173
+ width: file.width,
6174
+ height: file.height,
6175
+ id: file.id,
6176
+ documentId: file.documentId,
6177
+ name: file.name
6178
+ }));
6179
+ callback(formattedData);
6180
+ }
6181
+ }
6182
+ setCustomBlockImageCallback(null);
6183
+ setIsMediaLibOpen(false);
6184
+ }, [customBlockImageCallback]);
6185
+ m.useEffect(() => {
6186
+ const handleOpenMediaLib = (event) => {
6187
+ const { callbackId, allowedTypes } = event.detail || {};
6188
+ if (callbackId) {
6189
+ setCustomBlockImageCallback(callbackId);
6190
+ setIsMediaLibOpen(true);
6191
+ }
6192
+ };
6193
+ window.addEventListener("magic-editor-open-media-lib", handleOpenMediaLib);
6194
+ return () => window.removeEventListener("magic-editor-open-media-lib", handleOpenMediaLib);
6195
+ }, []);
6196
+ const toggleFullscreen = m.useCallback(() => {
6023
6197
  setIsFullscreen((prev) => {
6024
6198
  if (!prev) {
6025
6199
  document.body.classList.add("editor-fullscreen");
@@ -6029,7 +6203,7 @@ const Editor = React.forwardRef(({
6029
6203
  return !prev;
6030
6204
  });
6031
6205
  }, []);
6032
- React.useEffect(() => {
6206
+ m.useEffect(() => {
6033
6207
  const handleKeyDown = (e) => {
6034
6208
  if (e.key === "Escape" && isFullscreen) {
6035
6209
  toggleFullscreen();
@@ -6041,7 +6215,7 @@ const Editor = React.forwardRef(({
6041
6215
  window.addEventListener("keydown", handleKeyDown);
6042
6216
  return () => window.removeEventListener("keydown", handleKeyDown);
6043
6217
  }, [isFullscreen, toggleFullscreen]);
6044
- const handleAIAssistant = React.useCallback(() => {
6218
+ const handleAIAssistant = m.useCallback(() => {
6045
6219
  const selection = window.getSelection();
6046
6220
  let text = selection?.toString().trim();
6047
6221
  if (!text && editorInstanceRef.current && isReady) {
@@ -6082,7 +6256,7 @@ const Editor = React.forwardRef(({
6082
6256
  setAISelectedText(text);
6083
6257
  setShowAIToolbar(true);
6084
6258
  }, [isReady]);
6085
- const handleInsertBlock = React.useCallback((blockType) => {
6259
+ const handleInsertBlock = m.useCallback((blockType) => {
6086
6260
  if (!editorInstanceRef.current || !isReady) return;
6087
6261
  if (blockType === "mediaLib") {
6088
6262
  if (collabEnabled && collabCanEdit === false) {
@@ -6102,7 +6276,7 @@ const Editor = React.forwardRef(({
6102
6276
  editor.blocks.insert(blockType, {}, {}, lastIndex, true);
6103
6277
  editor.caret.setToBlock(lastIndex);
6104
6278
  }, [isReady, collabEnabled, collabCanEdit]);
6105
- const handleClear = React.useCallback(async () => {
6279
+ const handleClear = m.useCallback(async () => {
6106
6280
  if (!editorInstanceRef.current || !isReady) return;
6107
6281
  if (window.confirm("Clear all content? This cannot be undone.")) {
6108
6282
  await editorInstanceRef.current.clear();
@@ -6115,12 +6289,12 @@ const Editor = React.forwardRef(({
6115
6289
  setCharCount(0);
6116
6290
  }
6117
6291
  }, [isReady, name, onChange, pushLocalToCollab]);
6118
- const handleCopy = React.useCallback(async () => {
6292
+ const handleCopy = m.useCallback(async () => {
6119
6293
  if (!editorInstanceRef.current || !isReady) return;
6120
6294
  const data = await editorInstanceRef.current.save();
6121
6295
  await navigator.clipboard.writeText(JSON.stringify(data, null, 2));
6122
6296
  }, [isReady]);
6123
- React.useEffect(() => {
6297
+ m.useEffect(() => {
6124
6298
  if (isLoadingCustomBlocks) {
6125
6299
  console.log("[Magic Editor X] Waiting for custom blocks to load...");
6126
6300
  return;
@@ -6317,7 +6491,7 @@ const Editor = React.forwardRef(({
6317
6491
  document.body.classList.remove("editor-fullscreen");
6318
6492
  };
6319
6493
  }, [isLoadingCustomBlocks, customBlocks]);
6320
- React.useEffect(() => {
6494
+ m.useEffect(() => {
6321
6495
  const editor = editorInstanceRef.current;
6322
6496
  if (!editor || !isReady) return;
6323
6497
  const shouldBeReadOnly = disabled || collabEnabled && collabCanEdit === false;
@@ -6355,11 +6529,11 @@ const Editor = React.forwardRef(({
6355
6529
  { icon: outline.ExclamationTriangleIcon, label: "Warning", block: "warning" },
6356
6530
  { icon: outline.MinusIcon, label: "Divider", block: "delimiter" }
6357
6531
  ];
6358
- return /* @__PURE__ */ jsxRuntime.jsxs(getTranslation.Field.Root, { name, id: name, error, required, hint, children: [
6532
+ return /* @__PURE__ */ jsxRuntime.jsxs(getTranslation.Hm.Root, { name, id: name, error, required, hint, children: [
6359
6533
  /* @__PURE__ */ jsxRuntime.jsx(FullscreenGlobalStyle, {}),
6360
6534
  /* @__PURE__ */ jsxRuntime.jsx(EditorJSGlobalStyles, {}),
6361
6535
  /* @__PURE__ */ jsxRuntime.jsx(tools.AIToast, {}),
6362
- label && !isFullscreen && /* @__PURE__ */ jsxRuntime.jsx(getTranslation.Field.Label, { action: labelAction, children: label }),
6536
+ label && !isFullscreen && /* @__PURE__ */ jsxRuntime.jsx(getTranslation.Hm.Label, { action: labelAction, children: label }),
6363
6537
  /* @__PURE__ */ jsxRuntime.jsx(
6364
6538
  EditorContainer,
6365
6539
  {
@@ -6573,7 +6747,7 @@ const Editor = React.forwardRef(({
6573
6747
  onBlur: () => setIsFocused(false),
6574
6748
  children: [
6575
6749
  !isReady && /* @__PURE__ */ jsxRuntime.jsxs(LoadingOverlay, { children: [
6576
- /* @__PURE__ */ jsxRuntime.jsx(getTranslation.Loader, { small: true }),
6750
+ /* @__PURE__ */ jsxRuntime.jsx(getTranslation.Vd, { small: true }),
6577
6751
  /* @__PURE__ */ jsxRuntime.jsx(LoadingText, { children: "Initializing editor..." })
6578
6752
  ] }),
6579
6753
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -6658,15 +6832,21 @@ const Editor = React.forwardRef(({
6658
6832
  }
6659
6833
  ),
6660
6834
  !isFullscreen && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6661
- /* @__PURE__ */ jsxRuntime.jsx(getTranslation.Field.Hint, {}),
6662
- /* @__PURE__ */ jsxRuntime.jsx(getTranslation.Field.Error, {})
6835
+ /* @__PURE__ */ jsxRuntime.jsx(getTranslation.Hm.Hint, {}),
6836
+ /* @__PURE__ */ jsxRuntime.jsx(getTranslation.Hm.Error, {})
6663
6837
  ] }),
6664
6838
  /* @__PURE__ */ jsxRuntime.jsx(
6665
6839
  MediaLibComponent,
6666
6840
  {
6667
6841
  isOpen: isMediaLibOpen,
6668
- onChange: handleMediaLibChange,
6669
- onToggle: mediaLibToggleFunc
6842
+ onChange: customBlockImageCallback ? handleCustomBlockMediaLibChange : handleMediaLibChange,
6843
+ onToggle: () => {
6844
+ if (customBlockImageCallback) {
6845
+ setCustomBlockImageCallback(null);
6846
+ }
6847
+ mediaLibToggleFunc();
6848
+ },
6849
+ multiple: !customBlockImageCallback
6670
6850
  }
6671
6851
  ),
6672
6852
  showAIToolbar && /* @__PURE__ */ jsxRuntime.jsx(