@intlayer/editor-react 5.1.3 → 5.1.5

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.
@@ -37,12 +37,27 @@ const useEditedContentState = () => (0, import_useCrossFrameState.useCrossFrameS
37
37
  void 0,
38
38
  { emit: true, receive: false }
39
39
  );
40
+ const resolveState = (state, prevState) => typeof state === "function" ? state(prevState) : state;
40
41
  const EditedContentProvider = ({ children }) => {
41
42
  const { localeDictionaries } = (0, import_DictionariesRecordContext.useDictionariesRecord)();
42
43
  const [editedContent, setEditedContentState] = (0, import_useCrossFrameState.useCrossFrameState)(
43
44
  "INTLAYER_EDITED_CONTENT_CHANGED",
44
45
  void 0
45
46
  );
47
+ const setEditedDictionary = (newValue) => {
48
+ let updatedDictionaries = resolveState(newValue);
49
+ setEditedContentState((prev) => {
50
+ updatedDictionaries = resolveState(
51
+ newValue,
52
+ prev?.[updatedDictionaries.key]
53
+ );
54
+ return {
55
+ ...prev,
56
+ [updatedDictionaries.key]: updatedDictionaries
57
+ };
58
+ });
59
+ return updatedDictionaries;
60
+ };
46
61
  const setEditedContent = (dictionaryKey, newValue) => {
47
62
  setEditedContentState((prev) => ({
48
63
  ...prev,
@@ -164,6 +179,7 @@ const EditedContentProvider = ({ children }) => {
164
179
  {
165
180
  value: {
166
181
  setEditedContentState,
182
+ setEditedDictionary,
167
183
  setEditedContent,
168
184
  addEditedContent,
169
185
  renameEditedContent,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/EditedContentContext.tsx"],"sourcesContent":["'use client';\n\nimport {\n type Dictionary,\n type ContentNode,\n type KeyPath,\n editDictionaryByKeyPath,\n getContentNodeByKeyPath,\n renameContentNodeByKeyPath,\n} from '@intlayer/core';\nimport {\n createContext,\n useContext,\n type FC,\n type PropsWithChildren,\n} from 'react';\nimport {\n useDictionariesRecord,\n type DictionaryContent,\n} from './DictionariesRecordContext';\nimport { useCrossFrameState } from './useCrossFrameState';\n\ntype EditedContentStateContextType = {\n editedContent: Record<Dictionary['key'], Dictionary> | undefined;\n};\n\nconst EditedContentStateContext = createContext<\n EditedContentStateContextType | undefined\n>(undefined);\n\ntype EditedContentActionsContextType = {\n setEditedContentState: (\n editedContent: Record<Dictionary['key'], Dictionary>\n ) => void;\n setEditedContent: (\n dictionaryKey: Dictionary['key'],\n newValue: Dictionary['content']\n ) => void;\n addEditedContent: (\n dictionaryKey: Dictionary['key'],\n newValue: ContentNode<any>,\n keyPath?: KeyPath[],\n overwrite?: boolean\n ) => void;\n renameEditedContent: (\n dictionaryKey: Dictionary['key'],\n newKey: KeyPath['key'],\n keyPath?: KeyPath[]\n ) => void;\n removeEditedContent: (\n dictionaryKey: Dictionary['key'],\n keyPath: KeyPath[]\n ) => void;\n restoreEditedContent: (dictionaryKey: Dictionary['key']) => void;\n clearEditedDictionaryContent: (dictionaryKey: Dictionary['key']) => void;\n clearEditedContent: () => void;\n getEditedContentValue: (\n dictionaryKey: Dictionary['key'],\n keyPath: KeyPath[]\n ) => ContentNode | undefined;\n};\n\nconst EditedContentActionsContext = createContext<\n EditedContentActionsContextType | undefined\n>(undefined);\n\nexport const useEditedContentState = () =>\n useCrossFrameState<DictionaryContent>(\n 'INTLAYER_EDITED_CONTENT_CHANGED',\n undefined,\n { emit: true, receive: false }\n );\n\nexport const EditedContentProvider: FC<PropsWithChildren> = ({ children }) => {\n const { localeDictionaries } = useDictionariesRecord();\n\n const [editedContent, setEditedContentState] =\n useCrossFrameState<DictionaryContent>(\n 'INTLAYER_EDITED_CONTENT_CHANGED',\n undefined\n );\n\n const setEditedContent = (\n dictionaryKey: Dictionary['key'],\n newValue: Dictionary['content']\n ) => {\n setEditedContentState((prev) => ({\n ...prev,\n [dictionaryKey]: {\n ...prev?.[dictionaryKey],\n content: newValue,\n },\n }));\n };\n\n const addEditedContent = (\n dictionaryKey: Dictionary['key'],\n newValue: ContentNode,\n keyPath: KeyPath[] = [],\n overwrite: boolean = true\n ) => {\n setEditedContentState((prev) => {\n // Get the starting content: edited version if available, otherwise a deep copy of the original\n const originalContent = localeDictionaries[dictionaryKey]?.content;\n const currentContent = structuredClone(\n prev?.[dictionaryKey]?.content ?? originalContent\n );\n\n let newKeyPath = keyPath;\n if (!overwrite) {\n // Find a unique key based on the keyPath provided\n let index = 0;\n const otherKeyPath = keyPath.slice(0, -1);\n const lastKeyPath: KeyPath = keyPath[keyPath.length - 1];\n let finalKey = lastKeyPath.key;\n\n // Loop until we find a key that does not exist\n while (\n typeof getContentNodeByKeyPath(currentContent, newKeyPath) !==\n 'undefined'\n ) {\n index++;\n finalKey =\n index === 0 ? lastKeyPath.key : `${lastKeyPath.key} (${index})`;\n newKeyPath = [\n ...otherKeyPath,\n { ...lastKeyPath, key: finalKey } as KeyPath,\n ];\n }\n }\n\n const updatedContent = editDictionaryByKeyPath(\n currentContent,\n newKeyPath,\n newValue\n );\n\n return {\n ...prev,\n [dictionaryKey]: {\n ...prev?.[dictionaryKey],\n content: updatedContent as Dictionary['content'],\n },\n };\n });\n };\n\n const renameEditedContent = (\n dictionaryKey: Dictionary['key'],\n newKey: KeyPath['key'],\n keyPath: KeyPath[] = []\n ) => {\n setEditedContentState((prev) => {\n // Retrieve the base content: use edited version if available, otherwise deep copy of original\n const originalContent = localeDictionaries[dictionaryKey]?.content;\n const currentContent = structuredClone(\n prev?.[dictionaryKey]?.content ?? originalContent\n );\n\n const contentWithNewField = renameContentNodeByKeyPath(\n currentContent,\n newKey,\n keyPath\n );\n\n return {\n ...prev,\n [dictionaryKey]: {\n ...prev?.[dictionaryKey],\n content: contentWithNewField as Dictionary['content'],\n },\n };\n });\n };\n\n const removeEditedContent = (\n dictionaryKey: Dictionary['key'],\n keyPath: KeyPath[]\n ) => {\n setEditedContentState((prev) => {\n // Retrieve the original content as reference\n const originalContent = localeDictionaries[dictionaryKey]?.content;\n const currentContent = structuredClone(\n prev?.[dictionaryKey]?.content ?? originalContent\n );\n\n // Get the initial value from the original dictionary content\n const initialContent = getContentNodeByKeyPath(originalContent, keyPath);\n\n // Restore the value at the given keyPath\n const restoredContent = editDictionaryByKeyPath(\n currentContent,\n keyPath,\n initialContent\n );\n\n return {\n ...prev,\n [dictionaryKey]: {\n ...prev?.[dictionaryKey],\n content: restoredContent as Dictionary['content'],\n },\n };\n });\n };\n\n const restoreEditedContent = (dictionaryKey: Dictionary['key']) => {\n setEditedContentState((prev) => {\n const updated = { ...prev };\n delete updated[dictionaryKey];\n return updated;\n });\n };\n\n const clearEditedDictionaryContent = (dictionaryKey: Dictionary['key']) => {\n setEditedContentState((prev) => {\n const filtered = Object.entries(prev).reduce((acc, [key, value]) => {\n if (key === dictionaryKey) {\n return acc;\n }\n return { ...acc, [key]: value };\n }, {} as DictionaryContent);\n return filtered;\n });\n };\n\n const clearEditedContent = () => {\n setEditedContentState({});\n };\n\n const getEditedContentValue = (\n dictionaryKey: Dictionary['key'],\n keyPath: KeyPath[]\n ): ContentNode | undefined => {\n const currentContent = editedContent?.[dictionaryKey]?.content ?? {};\n return getContentNodeByKeyPath(currentContent, keyPath);\n };\n\n return (\n <EditedContentStateContext.Provider\n value={{\n editedContent,\n }}\n >\n <EditedContentActionsContext.Provider\n value={{\n setEditedContentState,\n setEditedContent,\n addEditedContent,\n renameEditedContent,\n removeEditedContent,\n restoreEditedContent,\n clearEditedDictionaryContent,\n clearEditedContent,\n getEditedContentValue,\n }}\n >\n {children}\n </EditedContentActionsContext.Provider>\n </EditedContentStateContext.Provider>\n );\n};\n\nexport const useEditedContentActions = () => {\n const context = useContext(EditedContentActionsContext);\n\n if (!context) {\n throw new Error(\n 'useEditedContent must be used within an EditedContentProvider'\n );\n }\n\n return context;\n};\n\nexport const useEditedContent = () => {\n const stateContext = useContext(EditedContentStateContext);\n const actionContext = useEditedContentActions();\n\n if (!stateContext) {\n throw new Error(\n 'useEditedContent must be used within an EditedContentProvider'\n );\n }\n\n return { ...stateContext, ...actionContext };\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/EditedContentContext.tsx"],"sourcesContent":["'use client';\n\nimport {\n type Dictionary,\n type ContentNode,\n type KeyPath,\n editDictionaryByKeyPath,\n getContentNodeByKeyPath,\n renameContentNodeByKeyPath,\n} from '@intlayer/core';\nimport {\n type Dispatch,\n createContext,\n useContext,\n type SetStateAction,\n type FC,\n type PropsWithChildren,\n} from 'react';\nimport {\n useDictionariesRecord,\n type DictionaryContent,\n} from './DictionariesRecordContext';\nimport { useCrossFrameState } from './useCrossFrameState';\n\ntype EditedContentStateContextType = {\n editedContent: Record<Dictionary['key'], Dictionary> | undefined;\n};\n\nconst EditedContentStateContext = createContext<\n EditedContentStateContextType | undefined\n>(undefined);\n\ntype EditedContentActionsContextType = {\n setEditedContentState: (\n editedContent: Record<Dictionary['key'], Dictionary>\n ) => void;\n setEditedDictionary: Dispatch<SetStateAction<Dictionary>>;\n setEditedContent: (\n dictionaryKey: Dictionary['key'],\n newValue: Dictionary['content']\n ) => void;\n addEditedContent: (\n dictionaryKey: Dictionary['key'],\n newValue: ContentNode<any>,\n keyPath?: KeyPath[],\n overwrite?: boolean\n ) => void;\n renameEditedContent: (\n dictionaryKey: Dictionary['key'],\n newKey: KeyPath['key'],\n keyPath?: KeyPath[]\n ) => void;\n removeEditedContent: (\n dictionaryKey: Dictionary['key'],\n keyPath: KeyPath[]\n ) => void;\n restoreEditedContent: (dictionaryKey: Dictionary['key']) => void;\n clearEditedDictionaryContent: (dictionaryKey: Dictionary['key']) => void;\n clearEditedContent: () => void;\n getEditedContentValue: (\n dictionaryKey: Dictionary['key'],\n keyPath: KeyPath[]\n ) => ContentNode | undefined;\n};\n\nconst EditedContentActionsContext = createContext<\n EditedContentActionsContextType | undefined\n>(undefined);\n\nexport const useEditedContentState = () =>\n useCrossFrameState<DictionaryContent>(\n 'INTLAYER_EDITED_CONTENT_CHANGED',\n undefined,\n { emit: true, receive: false }\n );\n\nconst resolveState = <S,>(state?: SetStateAction<S>, prevState?: S): S =>\n typeof state === 'function'\n ? (state as (prevState?: S) => S)(prevState)\n : (state as S);\n\nexport const EditedContentProvider: FC<PropsWithChildren> = ({ children }) => {\n const { localeDictionaries } = useDictionariesRecord();\n\n const [editedContent, setEditedContentState] =\n useCrossFrameState<DictionaryContent>(\n 'INTLAYER_EDITED_CONTENT_CHANGED',\n undefined\n );\n\n const setEditedDictionary: Dispatch<SetStateAction<Dictionary>> = (\n newValue\n ) => {\n let updatedDictionaries: Dictionary = resolveState(newValue);\n\n setEditedContentState((prev) => {\n updatedDictionaries = resolveState(\n newValue,\n prev?.[updatedDictionaries.key]\n );\n\n return {\n ...prev,\n [updatedDictionaries.key]: updatedDictionaries,\n };\n });\n\n return updatedDictionaries;\n };\n\n const setEditedContent = (\n dictionaryKey: Dictionary['key'],\n newValue: Dictionary['content']\n ) => {\n setEditedContentState((prev) => ({\n ...prev,\n [dictionaryKey]: {\n ...prev?.[dictionaryKey],\n content: newValue,\n },\n }));\n };\n\n const addEditedContent = (\n dictionaryKey: Dictionary['key'],\n newValue: ContentNode,\n keyPath: KeyPath[] = [],\n overwrite: boolean = true\n ) => {\n setEditedContentState((prev) => {\n // Get the starting content: edited version if available, otherwise a deep copy of the original\n const originalContent = localeDictionaries[dictionaryKey]?.content;\n const currentContent = structuredClone(\n prev?.[dictionaryKey]?.content ?? originalContent\n );\n\n let newKeyPath = keyPath;\n if (!overwrite) {\n // Find a unique key based on the keyPath provided\n let index = 0;\n const otherKeyPath = keyPath.slice(0, -1);\n const lastKeyPath: KeyPath = keyPath[keyPath.length - 1];\n let finalKey = lastKeyPath.key;\n\n // Loop until we find a key that does not exist\n while (\n typeof getContentNodeByKeyPath(currentContent, newKeyPath) !==\n 'undefined'\n ) {\n index++;\n finalKey =\n index === 0 ? lastKeyPath.key : `${lastKeyPath.key} (${index})`;\n newKeyPath = [\n ...otherKeyPath,\n { ...lastKeyPath, key: finalKey } as KeyPath,\n ];\n }\n }\n\n const updatedContent = editDictionaryByKeyPath(\n currentContent,\n newKeyPath,\n newValue\n );\n\n return {\n ...prev,\n [dictionaryKey]: {\n ...prev?.[dictionaryKey],\n content: updatedContent as Dictionary['content'],\n },\n };\n });\n };\n\n const renameEditedContent = (\n dictionaryKey: Dictionary['key'],\n newKey: KeyPath['key'],\n keyPath: KeyPath[] = []\n ) => {\n setEditedContentState((prev) => {\n // Retrieve the base content: use edited version if available, otherwise deep copy of original\n const originalContent = localeDictionaries[dictionaryKey]?.content;\n const currentContent = structuredClone(\n prev?.[dictionaryKey]?.content ?? originalContent\n );\n\n const contentWithNewField = renameContentNodeByKeyPath(\n currentContent,\n newKey,\n keyPath\n );\n\n return {\n ...prev,\n [dictionaryKey]: {\n ...prev?.[dictionaryKey],\n content: contentWithNewField as Dictionary['content'],\n },\n };\n });\n };\n\n const removeEditedContent = (\n dictionaryKey: Dictionary['key'],\n keyPath: KeyPath[]\n ) => {\n setEditedContentState((prev) => {\n // Retrieve the original content as reference\n const originalContent = localeDictionaries[dictionaryKey]?.content;\n const currentContent = structuredClone(\n prev?.[dictionaryKey]?.content ?? originalContent\n );\n\n // Get the initial value from the original dictionary content\n const initialContent = getContentNodeByKeyPath(originalContent, keyPath);\n\n // Restore the value at the given keyPath\n const restoredContent = editDictionaryByKeyPath(\n currentContent,\n keyPath,\n initialContent\n );\n\n return {\n ...prev,\n [dictionaryKey]: {\n ...prev?.[dictionaryKey],\n content: restoredContent as Dictionary['content'],\n },\n };\n });\n };\n\n const restoreEditedContent = (dictionaryKey: Dictionary['key']) => {\n setEditedContentState((prev) => {\n const updated = { ...prev };\n delete updated[dictionaryKey];\n return updated;\n });\n };\n\n const clearEditedDictionaryContent = (dictionaryKey: Dictionary['key']) => {\n setEditedContentState((prev) => {\n const filtered = Object.entries(prev).reduce((acc, [key, value]) => {\n if (key === dictionaryKey) {\n return acc;\n }\n return { ...acc, [key]: value };\n }, {} as DictionaryContent);\n return filtered;\n });\n };\n\n const clearEditedContent = () => {\n setEditedContentState({});\n };\n\n const getEditedContentValue = (\n dictionaryKey: Dictionary['key'],\n keyPath: KeyPath[]\n ): ContentNode | undefined => {\n const currentContent = editedContent?.[dictionaryKey]?.content ?? {};\n return getContentNodeByKeyPath(currentContent, keyPath);\n };\n\n return (\n <EditedContentStateContext.Provider\n value={{\n editedContent,\n }}\n >\n <EditedContentActionsContext.Provider\n value={{\n setEditedContentState,\n setEditedDictionary,\n setEditedContent,\n addEditedContent,\n renameEditedContent,\n removeEditedContent,\n restoreEditedContent,\n clearEditedDictionaryContent,\n clearEditedContent,\n getEditedContentValue,\n }}\n >\n {children}\n </EditedContentActionsContext.Provider>\n </EditedContentStateContext.Provider>\n );\n};\n\nexport const useEditedContentActions = () => {\n const context = useContext(EditedContentActionsContext);\n\n if (!context) {\n throw new Error(\n 'useEditedContent must be used within an EditedContentProvider'\n );\n }\n\n return context;\n};\n\nexport const useEditedContent = () => {\n const stateContext = useContext(EditedContentStateContext);\n const actionContext = useEditedContentActions();\n\n if (!stateContext) {\n throw new Error(\n 'useEditedContent must be used within an EditedContentProvider'\n );\n }\n\n return { ...stateContext, ...actionContext };\n};\n"],"mappings":"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","names":[]}
@@ -24,6 +24,24 @@ __export(useCrossFrameMessageListener_exports, {
24
24
  module.exports = __toCommonJS(useCrossFrameMessageListener_exports);
25
25
  var import_react = require("react");
26
26
  var import_CommunicatorContext = require('./CommunicatorContext.cjs');
27
+ const compareUrls = (url1, url2) => {
28
+ try {
29
+ const parsedUrl1 = new URL(url1);
30
+ const parsedUrl2 = new URL(url2);
31
+ if (parsedUrl1.protocol !== parsedUrl2.protocol || parsedUrl1.hostname !== parsedUrl2.hostname || parsedUrl1.port !== parsedUrl2.port) {
32
+ return false;
33
+ }
34
+ const path1 = parsedUrl1.pathname.replace(/\/$/, "");
35
+ const path2 = parsedUrl2.pathname.replace(/\/$/, "");
36
+ if (path1 !== "" && path2 !== "" && path1 !== path2) {
37
+ return false;
38
+ }
39
+ return true;
40
+ } catch (error) {
41
+ console.error("Invalid URL(s)", error);
42
+ return false;
43
+ }
44
+ };
27
45
  const useCrossFrameMessageListener = (key, onEventTriggered) => {
28
46
  const { allowedOrigins, postMessage, senderId } = (0, import_CommunicatorContext.useCommunicator)();
29
47
  (0, import_react.useEffect)(() => {
@@ -32,7 +50,7 @@ const useCrossFrameMessageListener = (key, onEventTriggered) => {
32
50
  const { type, data, senderId: msgSenderId } = event.data;
33
51
  if (type !== key) return;
34
52
  if (msgSenderId === senderId) return;
35
- if (typeof allowedOrigins === "undefined" || allowedOrigins?.includes(event.origin) || allowedOrigins?.includes("*")) {
53
+ if (typeof allowedOrigins === "undefined" || allowedOrigins?.some((url) => compareUrls(url, event.origin)) || allowedOrigins?.includes("*")) {
36
54
  onEventTriggered(data);
37
55
  }
38
56
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/useCrossFrameMessageListener.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo } from 'react';\nimport { useCommunicator } from './CommunicatorContext';\nimport { type MessageKey } from './messageKey';\n\n/**\n * useCrossFrameMessageListener\n *\n * This React hook listens for messages sent via the `postMessage` API and triggers a callback\n * whenever a message of the specified type (`key`) is received. It is useful for synchronizing\n * state or events across different windows, iframes, or contexts.\n *\n * @template S - The type of the data payload in the message.\n * @param {`${MessageKey}` | `${MessageKey}/post` | `${MessageKey}/get`} key - A unique identifier for the message type to listen for.\n * @param {(data: S) => void} [onEventTriggered] - A callback function triggered when a message\n * with the specified key is received. The callback receives the message data as its argument.\n *\n * @returns {{ postMessage: (data: S) => void }} An object containing a `postMessage` function\n * that allows broadcasting messages with the specified key and data.\n */\nexport const useCrossFrameMessageListener = <S,>(\n key: `${MessageKey}` | `${MessageKey}/post` | `${MessageKey}/get`,\n onEventTriggered?: (data: S) => void\n) => {\n const { allowedOrigins, postMessage, senderId } = useCommunicator();\n\n useEffect(() => {\n if (onEventTriggered) {\n /**\n * Message handler to process incoming messages.\n *\n * - **Message Filtering:** Ensures only messages with the specified `key` are processed.\n * - **Origin Validation:** Checks that the origin of the message is within the allowed origins.\n *\n * @param {MessageEvent<{ type: string; data: S }>} event - The incoming message event object.\n */\n const handleMessage = (\n event: MessageEvent<{ type: string; data: S; senderId: string }>\n ) => {\n const { type, data, senderId: msgSenderId } = event.data;\n\n // Ignore messages that do not match the current key\n if (type !== key) return;\n\n // Ignore messages from myself\n if (msgSenderId === senderId) return;\n\n // Check if the message origin is allowed\n if (\n typeof allowedOrigins === 'undefined' ||\n allowedOrigins?.includes(event.origin) ||\n allowedOrigins?.includes('*')\n ) {\n // Update the local state with the received data\n onEventTriggered(data);\n }\n };\n\n window.addEventListener('message', handleMessage);\n\n // Clean up the event listener on unmount\n return () => window.removeEventListener('message', handleMessage);\n }\n }, [allowedOrigins, postMessage, senderId]);\n\n /**\n * A wrapper function around the `postMessage` function to broadcast messages efficiently.\n *\n * - **Encapsulation:** Ensures the `postMessage` function is scoped to the provided key.\n * - **Ease of Use:** Simplifies broadcasting messages with consistent type and format.\n *\n * @param {S} data - The data payload to include in the message.\n * @returns {void}\n */\n const postMessageWrapper: (data: S) => void = useCallback(\n (data) => {\n postMessage({ type: key, data, senderId });\n },\n [postMessage, key, senderId]\n );\n\n return useMemo(() => postMessageWrapper, [postMessageWrapper]);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,mBAAgD;AAChD,iCAAgC;AAkBzB,MAAM,+BAA+B,CAC1C,KACA,qBACG;AACH,QAAM,EAAE,gBAAgB,aAAa,SAAS,QAAI,4CAAgB;AAElE,8BAAU,MAAM;AACd,QAAI,kBAAkB;AASpB,YAAM,gBAAgB,CACpB,UACG;AACH,cAAM,EAAE,MAAM,MAAM,UAAU,YAAY,IAAI,MAAM;AAGpD,YAAI,SAAS,IAAK;AAGlB,YAAI,gBAAgB,SAAU;AAG9B,YACE,OAAO,mBAAmB,eAC1B,gBAAgB,SAAS,MAAM,MAAM,KACrC,gBAAgB,SAAS,GAAG,GAC5B;AAEA,2BAAiB,IAAI;AAAA,QACvB;AAAA,MACF;AAEA,aAAO,iBAAiB,WAAW,aAAa;AAGhD,aAAO,MAAM,OAAO,oBAAoB,WAAW,aAAa;AAAA,IAClE;AAAA,EACF,GAAG,CAAC,gBAAgB,aAAa,QAAQ,CAAC;AAW1C,QAAM,yBAAwC;AAAA,IAC5C,CAAC,SAAS;AACR,kBAAY,EAAE,MAAM,KAAK,MAAM,SAAS,CAAC;AAAA,IAC3C;AAAA,IACA,CAAC,aAAa,KAAK,QAAQ;AAAA,EAC7B;AAEA,aAAO,sBAAQ,MAAM,oBAAoB,CAAC,kBAAkB,CAAC;AAC/D;","names":[]}
1
+ {"version":3,"sources":["../../src/useCrossFrameMessageListener.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo } from 'react';\nimport { useCommunicator } from './CommunicatorContext';\nimport { type MessageKey } from './messageKey';\n\n/**\n * Compare two URLs for equality.\n * This function is used to determine if a message originates from the same origin.\n *\n * ```js\n * // Example usage\n * console.log(compareUrls(\"http://localhost:5173/\", \"http://localhost:5173\")); // true\n * console.log(compareUrls(\"http://localhost:5173\", \"http://localhost:5173?myParam=true\")); // true\n * console.log(compareUrls(\"http://localhost:5173/subpath\", \"http://localhost:5173\")); // true\n * console.log(compareUrls(\"http://localhost:5172\", \"http://localhost:5173\")); // false\n * ```\n *\n * @param url1 - The first URL to compare.\n * @param url2 - The second URL to compare.\n * @returns Whether the two URLs are equal.\n */\nconst compareUrls = (url1: string, url2: string): boolean => {\n try {\n const parsedUrl1 = new URL(url1);\n const parsedUrl2 = new URL(url2);\n\n // Compare protocol, hostname, and port\n if (\n parsedUrl1.protocol !== parsedUrl2.protocol ||\n parsedUrl1.hostname !== parsedUrl2.hostname ||\n parsedUrl1.port !== parsedUrl2.port\n ) {\n return false;\n }\n\n // One URL should not have a subpath while the other does\n const path1 = parsedUrl1.pathname.replace(/\\/$/, ''); // Remove trailing slash\n const path2 = parsedUrl2.pathname.replace(/\\/$/, '');\n\n if (path1 !== '' && path2 !== '' && path1 !== path2) {\n return false;\n }\n\n return true;\n } catch (error) {\n console.error('Invalid URL(s)', error);\n return false;\n }\n};\n\n/**\n * useCrossFrameMessageListener\n *\n * This React hook listens for messages sent via the `postMessage` API and triggers a callback\n * whenever a message of the specified type (`key`) is received. It is useful for synchronizing\n * state or events across different windows, iframes, or contexts.\n *\n * @template S - The type of the data payload in the message.\n * @param {`${MessageKey}` | `${MessageKey}/post` | `${MessageKey}/get`} key - A unique identifier for the message type to listen for.\n * @param {(data: S) => void} [onEventTriggered] - A callback function triggered when a message\n * with the specified key is received. The callback receives the message data as its argument.\n *\n * @returns {{ postMessage: (data: S) => void }} An object containing a `postMessage` function\n * that allows broadcasting messages with the specified key and data.\n */\nexport const useCrossFrameMessageListener = <S,>(\n key: `${MessageKey}` | `${MessageKey}/post` | `${MessageKey}/get`,\n onEventTriggered?: (data: S) => void\n) => {\n const { allowedOrigins, postMessage, senderId } = useCommunicator();\n\n useEffect(() => {\n if (onEventTriggered) {\n /**\n * Message handler to process incoming messages.\n *\n * - **Message Filtering:** Ensures only messages with the specified `key` are processed.\n * - **Origin Validation:** Checks that the origin of the message is within the allowed origins.\n *\n * @param {MessageEvent<{ type: string; data: S }>} event - The incoming message event object.\n */\n const handleMessage = (\n event: MessageEvent<{ type: string; data: S; senderId: string }>\n ) => {\n const { type, data, senderId: msgSenderId } = event.data;\n\n // Ignore messages that do not match the current key\n if (type !== key) return;\n\n // Ignore messages from myself\n if (msgSenderId === senderId) return;\n\n // Check if the message origin is allowed\n if (\n typeof allowedOrigins === 'undefined' ||\n allowedOrigins?.some((url) => compareUrls(url, event.origin)) ||\n allowedOrigins?.includes('*')\n ) {\n // Update the local state with the received data\n onEventTriggered(data);\n }\n };\n\n window.addEventListener('message', handleMessage);\n\n // Clean up the event listener on unmount\n return () => window.removeEventListener('message', handleMessage);\n }\n }, [allowedOrigins, postMessage, senderId]);\n\n /**\n * A wrapper function around the `postMessage` function to broadcast messages efficiently.\n *\n * - **Encapsulation:** Ensures the `postMessage` function is scoped to the provided key.\n * - **Ease of Use:** Simplifies broadcasting messages with consistent type and format.\n *\n * @param {S} data - The data payload to include in the message.\n * @returns {void}\n */\n const postMessageWrapper: (data: S) => void = useCallback(\n (data) => {\n postMessage({ type: key, data, senderId });\n },\n [postMessage, key, senderId]\n );\n\n return useMemo(() => postMessageWrapper, [postMessageWrapper]);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,mBAAgD;AAChD,iCAAgC;AAmBhC,MAAM,cAAc,CAAC,MAAc,SAA0B;AAC3D,MAAI;AACF,UAAM,aAAa,IAAI,IAAI,IAAI;AAC/B,UAAM,aAAa,IAAI,IAAI,IAAI;AAG/B,QACE,WAAW,aAAa,WAAW,YACnC,WAAW,aAAa,WAAW,YACnC,WAAW,SAAS,WAAW,MAC/B;AACA,aAAO;AAAA,IACT;AAGA,UAAM,QAAQ,WAAW,SAAS,QAAQ,OAAO,EAAE;AACnD,UAAM,QAAQ,WAAW,SAAS,QAAQ,OAAO,EAAE;AAEnD,QAAI,UAAU,MAAM,UAAU,MAAM,UAAU,OAAO;AACnD,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,kBAAkB,KAAK;AACrC,WAAO;AAAA,EACT;AACF;AAiBO,MAAM,+BAA+B,CAC1C,KACA,qBACG;AACH,QAAM,EAAE,gBAAgB,aAAa,SAAS,QAAI,4CAAgB;AAElE,8BAAU,MAAM;AACd,QAAI,kBAAkB;AASpB,YAAM,gBAAgB,CACpB,UACG;AACH,cAAM,EAAE,MAAM,MAAM,UAAU,YAAY,IAAI,MAAM;AAGpD,YAAI,SAAS,IAAK;AAGlB,YAAI,gBAAgB,SAAU;AAG9B,YACE,OAAO,mBAAmB,eAC1B,gBAAgB,KAAK,CAAC,QAAQ,YAAY,KAAK,MAAM,MAAM,CAAC,KAC5D,gBAAgB,SAAS,GAAG,GAC5B;AAEA,2BAAiB,IAAI;AAAA,QACvB;AAAA,MACF;AAEA,aAAO,iBAAiB,WAAW,aAAa;AAGhD,aAAO,MAAM,OAAO,oBAAoB,WAAW,aAAa;AAAA,IAClE;AAAA,EACF,GAAG,CAAC,gBAAgB,aAAa,QAAQ,CAAC;AAW1C,QAAM,yBAAwC;AAAA,IAC5C,CAAC,SAAS;AACR,kBAAY,EAAE,MAAM,KAAK,MAAM,SAAS,CAAC;AAAA,IAC3C;AAAA,IACA,CAAC,aAAa,KAAK,QAAQ;AAAA,EAC7B;AAEA,aAAO,sBAAQ,MAAM,oBAAoB,CAAC,kBAAkB,CAAC;AAC/D;","names":[]}
@@ -20,12 +20,27 @@ const useEditedContentState = () => useCrossFrameState(
20
20
  void 0,
21
21
  { emit: true, receive: false }
22
22
  );
23
+ const resolveState = (state, prevState) => typeof state === "function" ? state(prevState) : state;
23
24
  const EditedContentProvider = ({ children }) => {
24
25
  const { localeDictionaries } = useDictionariesRecord();
25
26
  const [editedContent, setEditedContentState] = useCrossFrameState(
26
27
  "INTLAYER_EDITED_CONTENT_CHANGED",
27
28
  void 0
28
29
  );
30
+ const setEditedDictionary = (newValue) => {
31
+ let updatedDictionaries = resolveState(newValue);
32
+ setEditedContentState((prev) => {
33
+ updatedDictionaries = resolveState(
34
+ newValue,
35
+ prev?.[updatedDictionaries.key]
36
+ );
37
+ return {
38
+ ...prev,
39
+ [updatedDictionaries.key]: updatedDictionaries
40
+ };
41
+ });
42
+ return updatedDictionaries;
43
+ };
29
44
  const setEditedContent = (dictionaryKey, newValue) => {
30
45
  setEditedContentState((prev) => ({
31
46
  ...prev,
@@ -147,6 +162,7 @@ const EditedContentProvider = ({ children }) => {
147
162
  {
148
163
  value: {
149
164
  setEditedContentState,
165
+ setEditedDictionary,
150
166
  setEditedContent,
151
167
  addEditedContent,
152
168
  renameEditedContent,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/EditedContentContext.tsx"],"sourcesContent":["'use client';\n\nimport {\n type Dictionary,\n type ContentNode,\n type KeyPath,\n editDictionaryByKeyPath,\n getContentNodeByKeyPath,\n renameContentNodeByKeyPath,\n} from '@intlayer/core';\nimport {\n createContext,\n useContext,\n type FC,\n type PropsWithChildren,\n} from 'react';\nimport {\n useDictionariesRecord,\n type DictionaryContent,\n} from './DictionariesRecordContext';\nimport { useCrossFrameState } from './useCrossFrameState';\n\ntype EditedContentStateContextType = {\n editedContent: Record<Dictionary['key'], Dictionary> | undefined;\n};\n\nconst EditedContentStateContext = createContext<\n EditedContentStateContextType | undefined\n>(undefined);\n\ntype EditedContentActionsContextType = {\n setEditedContentState: (\n editedContent: Record<Dictionary['key'], Dictionary>\n ) => void;\n setEditedContent: (\n dictionaryKey: Dictionary['key'],\n newValue: Dictionary['content']\n ) => void;\n addEditedContent: (\n dictionaryKey: Dictionary['key'],\n newValue: ContentNode<any>,\n keyPath?: KeyPath[],\n overwrite?: boolean\n ) => void;\n renameEditedContent: (\n dictionaryKey: Dictionary['key'],\n newKey: KeyPath['key'],\n keyPath?: KeyPath[]\n ) => void;\n removeEditedContent: (\n dictionaryKey: Dictionary['key'],\n keyPath: KeyPath[]\n ) => void;\n restoreEditedContent: (dictionaryKey: Dictionary['key']) => void;\n clearEditedDictionaryContent: (dictionaryKey: Dictionary['key']) => void;\n clearEditedContent: () => void;\n getEditedContentValue: (\n dictionaryKey: Dictionary['key'],\n keyPath: KeyPath[]\n ) => ContentNode | undefined;\n};\n\nconst EditedContentActionsContext = createContext<\n EditedContentActionsContextType | undefined\n>(undefined);\n\nexport const useEditedContentState = () =>\n useCrossFrameState<DictionaryContent>(\n 'INTLAYER_EDITED_CONTENT_CHANGED',\n undefined,\n { emit: true, receive: false }\n );\n\nexport const EditedContentProvider: FC<PropsWithChildren> = ({ children }) => {\n const { localeDictionaries } = useDictionariesRecord();\n\n const [editedContent, setEditedContentState] =\n useCrossFrameState<DictionaryContent>(\n 'INTLAYER_EDITED_CONTENT_CHANGED',\n undefined\n );\n\n const setEditedContent = (\n dictionaryKey: Dictionary['key'],\n newValue: Dictionary['content']\n ) => {\n setEditedContentState((prev) => ({\n ...prev,\n [dictionaryKey]: {\n ...prev?.[dictionaryKey],\n content: newValue,\n },\n }));\n };\n\n const addEditedContent = (\n dictionaryKey: Dictionary['key'],\n newValue: ContentNode,\n keyPath: KeyPath[] = [],\n overwrite: boolean = true\n ) => {\n setEditedContentState((prev) => {\n // Get the starting content: edited version if available, otherwise a deep copy of the original\n const originalContent = localeDictionaries[dictionaryKey]?.content;\n const currentContent = structuredClone(\n prev?.[dictionaryKey]?.content ?? originalContent\n );\n\n let newKeyPath = keyPath;\n if (!overwrite) {\n // Find a unique key based on the keyPath provided\n let index = 0;\n const otherKeyPath = keyPath.slice(0, -1);\n const lastKeyPath: KeyPath = keyPath[keyPath.length - 1];\n let finalKey = lastKeyPath.key;\n\n // Loop until we find a key that does not exist\n while (\n typeof getContentNodeByKeyPath(currentContent, newKeyPath) !==\n 'undefined'\n ) {\n index++;\n finalKey =\n index === 0 ? lastKeyPath.key : `${lastKeyPath.key} (${index})`;\n newKeyPath = [\n ...otherKeyPath,\n { ...lastKeyPath, key: finalKey } as KeyPath,\n ];\n }\n }\n\n const updatedContent = editDictionaryByKeyPath(\n currentContent,\n newKeyPath,\n newValue\n );\n\n return {\n ...prev,\n [dictionaryKey]: {\n ...prev?.[dictionaryKey],\n content: updatedContent as Dictionary['content'],\n },\n };\n });\n };\n\n const renameEditedContent = (\n dictionaryKey: Dictionary['key'],\n newKey: KeyPath['key'],\n keyPath: KeyPath[] = []\n ) => {\n setEditedContentState((prev) => {\n // Retrieve the base content: use edited version if available, otherwise deep copy of original\n const originalContent = localeDictionaries[dictionaryKey]?.content;\n const currentContent = structuredClone(\n prev?.[dictionaryKey]?.content ?? originalContent\n );\n\n const contentWithNewField = renameContentNodeByKeyPath(\n currentContent,\n newKey,\n keyPath\n );\n\n return {\n ...prev,\n [dictionaryKey]: {\n ...prev?.[dictionaryKey],\n content: contentWithNewField as Dictionary['content'],\n },\n };\n });\n };\n\n const removeEditedContent = (\n dictionaryKey: Dictionary['key'],\n keyPath: KeyPath[]\n ) => {\n setEditedContentState((prev) => {\n // Retrieve the original content as reference\n const originalContent = localeDictionaries[dictionaryKey]?.content;\n const currentContent = structuredClone(\n prev?.[dictionaryKey]?.content ?? originalContent\n );\n\n // Get the initial value from the original dictionary content\n const initialContent = getContentNodeByKeyPath(originalContent, keyPath);\n\n // Restore the value at the given keyPath\n const restoredContent = editDictionaryByKeyPath(\n currentContent,\n keyPath,\n initialContent\n );\n\n return {\n ...prev,\n [dictionaryKey]: {\n ...prev?.[dictionaryKey],\n content: restoredContent as Dictionary['content'],\n },\n };\n });\n };\n\n const restoreEditedContent = (dictionaryKey: Dictionary['key']) => {\n setEditedContentState((prev) => {\n const updated = { ...prev };\n delete updated[dictionaryKey];\n return updated;\n });\n };\n\n const clearEditedDictionaryContent = (dictionaryKey: Dictionary['key']) => {\n setEditedContentState((prev) => {\n const filtered = Object.entries(prev).reduce((acc, [key, value]) => {\n if (key === dictionaryKey) {\n return acc;\n }\n return { ...acc, [key]: value };\n }, {} as DictionaryContent);\n return filtered;\n });\n };\n\n const clearEditedContent = () => {\n setEditedContentState({});\n };\n\n const getEditedContentValue = (\n dictionaryKey: Dictionary['key'],\n keyPath: KeyPath[]\n ): ContentNode | undefined => {\n const currentContent = editedContent?.[dictionaryKey]?.content ?? {};\n return getContentNodeByKeyPath(currentContent, keyPath);\n };\n\n return (\n <EditedContentStateContext.Provider\n value={{\n editedContent,\n }}\n >\n <EditedContentActionsContext.Provider\n value={{\n setEditedContentState,\n setEditedContent,\n addEditedContent,\n renameEditedContent,\n removeEditedContent,\n restoreEditedContent,\n clearEditedDictionaryContent,\n clearEditedContent,\n getEditedContentValue,\n }}\n >\n {children}\n </EditedContentActionsContext.Provider>\n </EditedContentStateContext.Provider>\n );\n};\n\nexport const useEditedContentActions = () => {\n const context = useContext(EditedContentActionsContext);\n\n if (!context) {\n throw new Error(\n 'useEditedContent must be used within an EditedContentProvider'\n );\n }\n\n return context;\n};\n\nexport const useEditedContent = () => {\n const stateContext = useContext(EditedContentStateContext);\n const actionContext = useEditedContentActions();\n\n if (!stateContext) {\n throw new Error(\n 'useEditedContent must be used within an EditedContentProvider'\n );\n }\n\n return { ...stateContext, ...actionContext };\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/EditedContentContext.tsx"],"sourcesContent":["'use client';\n\nimport {\n type Dictionary,\n type ContentNode,\n type KeyPath,\n editDictionaryByKeyPath,\n getContentNodeByKeyPath,\n renameContentNodeByKeyPath,\n} from '@intlayer/core';\nimport {\n type Dispatch,\n createContext,\n useContext,\n type SetStateAction,\n type FC,\n type PropsWithChildren,\n} from 'react';\nimport {\n useDictionariesRecord,\n type DictionaryContent,\n} from './DictionariesRecordContext';\nimport { useCrossFrameState } from './useCrossFrameState';\n\ntype EditedContentStateContextType = {\n editedContent: Record<Dictionary['key'], Dictionary> | undefined;\n};\n\nconst EditedContentStateContext = createContext<\n EditedContentStateContextType | undefined\n>(undefined);\n\ntype EditedContentActionsContextType = {\n setEditedContentState: (\n editedContent: Record<Dictionary['key'], Dictionary>\n ) => void;\n setEditedDictionary: Dispatch<SetStateAction<Dictionary>>;\n setEditedContent: (\n dictionaryKey: Dictionary['key'],\n newValue: Dictionary['content']\n ) => void;\n addEditedContent: (\n dictionaryKey: Dictionary['key'],\n newValue: ContentNode<any>,\n keyPath?: KeyPath[],\n overwrite?: boolean\n ) => void;\n renameEditedContent: (\n dictionaryKey: Dictionary['key'],\n newKey: KeyPath['key'],\n keyPath?: KeyPath[]\n ) => void;\n removeEditedContent: (\n dictionaryKey: Dictionary['key'],\n keyPath: KeyPath[]\n ) => void;\n restoreEditedContent: (dictionaryKey: Dictionary['key']) => void;\n clearEditedDictionaryContent: (dictionaryKey: Dictionary['key']) => void;\n clearEditedContent: () => void;\n getEditedContentValue: (\n dictionaryKey: Dictionary['key'],\n keyPath: KeyPath[]\n ) => ContentNode | undefined;\n};\n\nconst EditedContentActionsContext = createContext<\n EditedContentActionsContextType | undefined\n>(undefined);\n\nexport const useEditedContentState = () =>\n useCrossFrameState<DictionaryContent>(\n 'INTLAYER_EDITED_CONTENT_CHANGED',\n undefined,\n { emit: true, receive: false }\n );\n\nconst resolveState = <S,>(state?: SetStateAction<S>, prevState?: S): S =>\n typeof state === 'function'\n ? (state as (prevState?: S) => S)(prevState)\n : (state as S);\n\nexport const EditedContentProvider: FC<PropsWithChildren> = ({ children }) => {\n const { localeDictionaries } = useDictionariesRecord();\n\n const [editedContent, setEditedContentState] =\n useCrossFrameState<DictionaryContent>(\n 'INTLAYER_EDITED_CONTENT_CHANGED',\n undefined\n );\n\n const setEditedDictionary: Dispatch<SetStateAction<Dictionary>> = (\n newValue\n ) => {\n let updatedDictionaries: Dictionary = resolveState(newValue);\n\n setEditedContentState((prev) => {\n updatedDictionaries = resolveState(\n newValue,\n prev?.[updatedDictionaries.key]\n );\n\n return {\n ...prev,\n [updatedDictionaries.key]: updatedDictionaries,\n };\n });\n\n return updatedDictionaries;\n };\n\n const setEditedContent = (\n dictionaryKey: Dictionary['key'],\n newValue: Dictionary['content']\n ) => {\n setEditedContentState((prev) => ({\n ...prev,\n [dictionaryKey]: {\n ...prev?.[dictionaryKey],\n content: newValue,\n },\n }));\n };\n\n const addEditedContent = (\n dictionaryKey: Dictionary['key'],\n newValue: ContentNode,\n keyPath: KeyPath[] = [],\n overwrite: boolean = true\n ) => {\n setEditedContentState((prev) => {\n // Get the starting content: edited version if available, otherwise a deep copy of the original\n const originalContent = localeDictionaries[dictionaryKey]?.content;\n const currentContent = structuredClone(\n prev?.[dictionaryKey]?.content ?? originalContent\n );\n\n let newKeyPath = keyPath;\n if (!overwrite) {\n // Find a unique key based on the keyPath provided\n let index = 0;\n const otherKeyPath = keyPath.slice(0, -1);\n const lastKeyPath: KeyPath = keyPath[keyPath.length - 1];\n let finalKey = lastKeyPath.key;\n\n // Loop until we find a key that does not exist\n while (\n typeof getContentNodeByKeyPath(currentContent, newKeyPath) !==\n 'undefined'\n ) {\n index++;\n finalKey =\n index === 0 ? lastKeyPath.key : `${lastKeyPath.key} (${index})`;\n newKeyPath = [\n ...otherKeyPath,\n { ...lastKeyPath, key: finalKey } as KeyPath,\n ];\n }\n }\n\n const updatedContent = editDictionaryByKeyPath(\n currentContent,\n newKeyPath,\n newValue\n );\n\n return {\n ...prev,\n [dictionaryKey]: {\n ...prev?.[dictionaryKey],\n content: updatedContent as Dictionary['content'],\n },\n };\n });\n };\n\n const renameEditedContent = (\n dictionaryKey: Dictionary['key'],\n newKey: KeyPath['key'],\n keyPath: KeyPath[] = []\n ) => {\n setEditedContentState((prev) => {\n // Retrieve the base content: use edited version if available, otherwise deep copy of original\n const originalContent = localeDictionaries[dictionaryKey]?.content;\n const currentContent = structuredClone(\n prev?.[dictionaryKey]?.content ?? originalContent\n );\n\n const contentWithNewField = renameContentNodeByKeyPath(\n currentContent,\n newKey,\n keyPath\n );\n\n return {\n ...prev,\n [dictionaryKey]: {\n ...prev?.[dictionaryKey],\n content: contentWithNewField as Dictionary['content'],\n },\n };\n });\n };\n\n const removeEditedContent = (\n dictionaryKey: Dictionary['key'],\n keyPath: KeyPath[]\n ) => {\n setEditedContentState((prev) => {\n // Retrieve the original content as reference\n const originalContent = localeDictionaries[dictionaryKey]?.content;\n const currentContent = structuredClone(\n prev?.[dictionaryKey]?.content ?? originalContent\n );\n\n // Get the initial value from the original dictionary content\n const initialContent = getContentNodeByKeyPath(originalContent, keyPath);\n\n // Restore the value at the given keyPath\n const restoredContent = editDictionaryByKeyPath(\n currentContent,\n keyPath,\n initialContent\n );\n\n return {\n ...prev,\n [dictionaryKey]: {\n ...prev?.[dictionaryKey],\n content: restoredContent as Dictionary['content'],\n },\n };\n });\n };\n\n const restoreEditedContent = (dictionaryKey: Dictionary['key']) => {\n setEditedContentState((prev) => {\n const updated = { ...prev };\n delete updated[dictionaryKey];\n return updated;\n });\n };\n\n const clearEditedDictionaryContent = (dictionaryKey: Dictionary['key']) => {\n setEditedContentState((prev) => {\n const filtered = Object.entries(prev).reduce((acc, [key, value]) => {\n if (key === dictionaryKey) {\n return acc;\n }\n return { ...acc, [key]: value };\n }, {} as DictionaryContent);\n return filtered;\n });\n };\n\n const clearEditedContent = () => {\n setEditedContentState({});\n };\n\n const getEditedContentValue = (\n dictionaryKey: Dictionary['key'],\n keyPath: KeyPath[]\n ): ContentNode | undefined => {\n const currentContent = editedContent?.[dictionaryKey]?.content ?? {};\n return getContentNodeByKeyPath(currentContent, keyPath);\n };\n\n return (\n <EditedContentStateContext.Provider\n value={{\n editedContent,\n }}\n >\n <EditedContentActionsContext.Provider\n value={{\n setEditedContentState,\n setEditedDictionary,\n setEditedContent,\n addEditedContent,\n renameEditedContent,\n removeEditedContent,\n restoreEditedContent,\n clearEditedDictionaryContent,\n clearEditedContent,\n getEditedContentValue,\n }}\n >\n {children}\n </EditedContentActionsContext.Provider>\n </EditedContentStateContext.Provider>\n );\n};\n\nexport const useEditedContentActions = () => {\n const context = useContext(EditedContentActionsContext);\n\n if (!context) {\n throw new Error(\n 'useEditedContent must be used within an EditedContentProvider'\n );\n }\n\n return context;\n};\n\nexport const useEditedContent = () => {\n const stateContext = useContext(EditedContentStateContext);\n const actionContext = useEditedContentActions();\n\n if (!stateContext) {\n throw new Error(\n 'useEditedContent must be used within an EditedContentProvider'\n );\n }\n\n return { ...stateContext, ...actionContext };\n};\n"],"mappings":"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","names":[]}
@@ -1,6 +1,24 @@
1
1
  "use client";
2
2
  import { useCallback, useEffect, useMemo } from "react";
3
3
  import { useCommunicator } from "./CommunicatorContext.mjs";
4
+ const compareUrls = (url1, url2) => {
5
+ try {
6
+ const parsedUrl1 = new URL(url1);
7
+ const parsedUrl2 = new URL(url2);
8
+ if (parsedUrl1.protocol !== parsedUrl2.protocol || parsedUrl1.hostname !== parsedUrl2.hostname || parsedUrl1.port !== parsedUrl2.port) {
9
+ return false;
10
+ }
11
+ const path1 = parsedUrl1.pathname.replace(/\/$/, "");
12
+ const path2 = parsedUrl2.pathname.replace(/\/$/, "");
13
+ if (path1 !== "" && path2 !== "" && path1 !== path2) {
14
+ return false;
15
+ }
16
+ return true;
17
+ } catch (error) {
18
+ console.error("Invalid URL(s)", error);
19
+ return false;
20
+ }
21
+ };
4
22
  const useCrossFrameMessageListener = (key, onEventTriggered) => {
5
23
  const { allowedOrigins, postMessage, senderId } = useCommunicator();
6
24
  useEffect(() => {
@@ -9,7 +27,7 @@ const useCrossFrameMessageListener = (key, onEventTriggered) => {
9
27
  const { type, data, senderId: msgSenderId } = event.data;
10
28
  if (type !== key) return;
11
29
  if (msgSenderId === senderId) return;
12
- if (typeof allowedOrigins === "undefined" || allowedOrigins?.includes(event.origin) || allowedOrigins?.includes("*")) {
30
+ if (typeof allowedOrigins === "undefined" || allowedOrigins?.some((url) => compareUrls(url, event.origin)) || allowedOrigins?.includes("*")) {
13
31
  onEventTriggered(data);
14
32
  }
15
33
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/useCrossFrameMessageListener.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo } from 'react';\nimport { useCommunicator } from './CommunicatorContext';\nimport { type MessageKey } from './messageKey';\n\n/**\n * useCrossFrameMessageListener\n *\n * This React hook listens for messages sent via the `postMessage` API and triggers a callback\n * whenever a message of the specified type (`key`) is received. It is useful for synchronizing\n * state or events across different windows, iframes, or contexts.\n *\n * @template S - The type of the data payload in the message.\n * @param {`${MessageKey}` | `${MessageKey}/post` | `${MessageKey}/get`} key - A unique identifier for the message type to listen for.\n * @param {(data: S) => void} [onEventTriggered] - A callback function triggered when a message\n * with the specified key is received. The callback receives the message data as its argument.\n *\n * @returns {{ postMessage: (data: S) => void }} An object containing a `postMessage` function\n * that allows broadcasting messages with the specified key and data.\n */\nexport const useCrossFrameMessageListener = <S,>(\n key: `${MessageKey}` | `${MessageKey}/post` | `${MessageKey}/get`,\n onEventTriggered?: (data: S) => void\n) => {\n const { allowedOrigins, postMessage, senderId } = useCommunicator();\n\n useEffect(() => {\n if (onEventTriggered) {\n /**\n * Message handler to process incoming messages.\n *\n * - **Message Filtering:** Ensures only messages with the specified `key` are processed.\n * - **Origin Validation:** Checks that the origin of the message is within the allowed origins.\n *\n * @param {MessageEvent<{ type: string; data: S }>} event - The incoming message event object.\n */\n const handleMessage = (\n event: MessageEvent<{ type: string; data: S; senderId: string }>\n ) => {\n const { type, data, senderId: msgSenderId } = event.data;\n\n // Ignore messages that do not match the current key\n if (type !== key) return;\n\n // Ignore messages from myself\n if (msgSenderId === senderId) return;\n\n // Check if the message origin is allowed\n if (\n typeof allowedOrigins === 'undefined' ||\n allowedOrigins?.includes(event.origin) ||\n allowedOrigins?.includes('*')\n ) {\n // Update the local state with the received data\n onEventTriggered(data);\n }\n };\n\n window.addEventListener('message', handleMessage);\n\n // Clean up the event listener on unmount\n return () => window.removeEventListener('message', handleMessage);\n }\n }, [allowedOrigins, postMessage, senderId]);\n\n /**\n * A wrapper function around the `postMessage` function to broadcast messages efficiently.\n *\n * - **Encapsulation:** Ensures the `postMessage` function is scoped to the provided key.\n * - **Ease of Use:** Simplifies broadcasting messages with consistent type and format.\n *\n * @param {S} data - The data payload to include in the message.\n * @returns {void}\n */\n const postMessageWrapper: (data: S) => void = useCallback(\n (data) => {\n postMessage({ type: key, data, senderId });\n },\n [postMessage, key, senderId]\n );\n\n return useMemo(() => postMessageWrapper, [postMessageWrapper]);\n};\n"],"mappings":";AAEA,SAAS,aAAa,WAAW,eAAe;AAChD,SAAS,uBAAuB;AAkBzB,MAAM,+BAA+B,CAC1C,KACA,qBACG;AACH,QAAM,EAAE,gBAAgB,aAAa,SAAS,IAAI,gBAAgB;AAElE,YAAU,MAAM;AACd,QAAI,kBAAkB;AASpB,YAAM,gBAAgB,CACpB,UACG;AACH,cAAM,EAAE,MAAM,MAAM,UAAU,YAAY,IAAI,MAAM;AAGpD,YAAI,SAAS,IAAK;AAGlB,YAAI,gBAAgB,SAAU;AAG9B,YACE,OAAO,mBAAmB,eAC1B,gBAAgB,SAAS,MAAM,MAAM,KACrC,gBAAgB,SAAS,GAAG,GAC5B;AAEA,2BAAiB,IAAI;AAAA,QACvB;AAAA,MACF;AAEA,aAAO,iBAAiB,WAAW,aAAa;AAGhD,aAAO,MAAM,OAAO,oBAAoB,WAAW,aAAa;AAAA,IAClE;AAAA,EACF,GAAG,CAAC,gBAAgB,aAAa,QAAQ,CAAC;AAW1C,QAAM,qBAAwC;AAAA,IAC5C,CAAC,SAAS;AACR,kBAAY,EAAE,MAAM,KAAK,MAAM,SAAS,CAAC;AAAA,IAC3C;AAAA,IACA,CAAC,aAAa,KAAK,QAAQ;AAAA,EAC7B;AAEA,SAAO,QAAQ,MAAM,oBAAoB,CAAC,kBAAkB,CAAC;AAC/D;","names":[]}
1
+ {"version":3,"sources":["../../src/useCrossFrameMessageListener.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo } from 'react';\nimport { useCommunicator } from './CommunicatorContext';\nimport { type MessageKey } from './messageKey';\n\n/**\n * Compare two URLs for equality.\n * This function is used to determine if a message originates from the same origin.\n *\n * ```js\n * // Example usage\n * console.log(compareUrls(\"http://localhost:5173/\", \"http://localhost:5173\")); // true\n * console.log(compareUrls(\"http://localhost:5173\", \"http://localhost:5173?myParam=true\")); // true\n * console.log(compareUrls(\"http://localhost:5173/subpath\", \"http://localhost:5173\")); // true\n * console.log(compareUrls(\"http://localhost:5172\", \"http://localhost:5173\")); // false\n * ```\n *\n * @param url1 - The first URL to compare.\n * @param url2 - The second URL to compare.\n * @returns Whether the two URLs are equal.\n */\nconst compareUrls = (url1: string, url2: string): boolean => {\n try {\n const parsedUrl1 = new URL(url1);\n const parsedUrl2 = new URL(url2);\n\n // Compare protocol, hostname, and port\n if (\n parsedUrl1.protocol !== parsedUrl2.protocol ||\n parsedUrl1.hostname !== parsedUrl2.hostname ||\n parsedUrl1.port !== parsedUrl2.port\n ) {\n return false;\n }\n\n // One URL should not have a subpath while the other does\n const path1 = parsedUrl1.pathname.replace(/\\/$/, ''); // Remove trailing slash\n const path2 = parsedUrl2.pathname.replace(/\\/$/, '');\n\n if (path1 !== '' && path2 !== '' && path1 !== path2) {\n return false;\n }\n\n return true;\n } catch (error) {\n console.error('Invalid URL(s)', error);\n return false;\n }\n};\n\n/**\n * useCrossFrameMessageListener\n *\n * This React hook listens for messages sent via the `postMessage` API and triggers a callback\n * whenever a message of the specified type (`key`) is received. It is useful for synchronizing\n * state or events across different windows, iframes, or contexts.\n *\n * @template S - The type of the data payload in the message.\n * @param {`${MessageKey}` | `${MessageKey}/post` | `${MessageKey}/get`} key - A unique identifier for the message type to listen for.\n * @param {(data: S) => void} [onEventTriggered] - A callback function triggered when a message\n * with the specified key is received. The callback receives the message data as its argument.\n *\n * @returns {{ postMessage: (data: S) => void }} An object containing a `postMessage` function\n * that allows broadcasting messages with the specified key and data.\n */\nexport const useCrossFrameMessageListener = <S,>(\n key: `${MessageKey}` | `${MessageKey}/post` | `${MessageKey}/get`,\n onEventTriggered?: (data: S) => void\n) => {\n const { allowedOrigins, postMessage, senderId } = useCommunicator();\n\n useEffect(() => {\n if (onEventTriggered) {\n /**\n * Message handler to process incoming messages.\n *\n * - **Message Filtering:** Ensures only messages with the specified `key` are processed.\n * - **Origin Validation:** Checks that the origin of the message is within the allowed origins.\n *\n * @param {MessageEvent<{ type: string; data: S }>} event - The incoming message event object.\n */\n const handleMessage = (\n event: MessageEvent<{ type: string; data: S; senderId: string }>\n ) => {\n const { type, data, senderId: msgSenderId } = event.data;\n\n // Ignore messages that do not match the current key\n if (type !== key) return;\n\n // Ignore messages from myself\n if (msgSenderId === senderId) return;\n\n // Check if the message origin is allowed\n if (\n typeof allowedOrigins === 'undefined' ||\n allowedOrigins?.some((url) => compareUrls(url, event.origin)) ||\n allowedOrigins?.includes('*')\n ) {\n // Update the local state with the received data\n onEventTriggered(data);\n }\n };\n\n window.addEventListener('message', handleMessage);\n\n // Clean up the event listener on unmount\n return () => window.removeEventListener('message', handleMessage);\n }\n }, [allowedOrigins, postMessage, senderId]);\n\n /**\n * A wrapper function around the `postMessage` function to broadcast messages efficiently.\n *\n * - **Encapsulation:** Ensures the `postMessage` function is scoped to the provided key.\n * - **Ease of Use:** Simplifies broadcasting messages with consistent type and format.\n *\n * @param {S} data - The data payload to include in the message.\n * @returns {void}\n */\n const postMessageWrapper: (data: S) => void = useCallback(\n (data) => {\n postMessage({ type: key, data, senderId });\n },\n [postMessage, key, senderId]\n );\n\n return useMemo(() => postMessageWrapper, [postMessageWrapper]);\n};\n"],"mappings":";AAEA,SAAS,aAAa,WAAW,eAAe;AAChD,SAAS,uBAAuB;AAmBhC,MAAM,cAAc,CAAC,MAAc,SAA0B;AAC3D,MAAI;AACF,UAAM,aAAa,IAAI,IAAI,IAAI;AAC/B,UAAM,aAAa,IAAI,IAAI,IAAI;AAG/B,QACE,WAAW,aAAa,WAAW,YACnC,WAAW,aAAa,WAAW,YACnC,WAAW,SAAS,WAAW,MAC/B;AACA,aAAO;AAAA,IACT;AAGA,UAAM,QAAQ,WAAW,SAAS,QAAQ,OAAO,EAAE;AACnD,UAAM,QAAQ,WAAW,SAAS,QAAQ,OAAO,EAAE;AAEnD,QAAI,UAAU,MAAM,UAAU,MAAM,UAAU,OAAO;AACnD,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,kBAAkB,KAAK;AACrC,WAAO;AAAA,EACT;AACF;AAiBO,MAAM,+BAA+B,CAC1C,KACA,qBACG;AACH,QAAM,EAAE,gBAAgB,aAAa,SAAS,IAAI,gBAAgB;AAElE,YAAU,MAAM;AACd,QAAI,kBAAkB;AASpB,YAAM,gBAAgB,CACpB,UACG;AACH,cAAM,EAAE,MAAM,MAAM,UAAU,YAAY,IAAI,MAAM;AAGpD,YAAI,SAAS,IAAK;AAGlB,YAAI,gBAAgB,SAAU;AAG9B,YACE,OAAO,mBAAmB,eAC1B,gBAAgB,KAAK,CAAC,QAAQ,YAAY,KAAK,MAAM,MAAM,CAAC,KAC5D,gBAAgB,SAAS,GAAG,GAC5B;AAEA,2BAAiB,IAAI;AAAA,QACvB;AAAA,MACF;AAEA,aAAO,iBAAiB,WAAW,aAAa;AAGhD,aAAO,MAAM,OAAO,oBAAoB,WAAW,aAAa;AAAA,IAClE;AAAA,EACF,GAAG,CAAC,gBAAgB,aAAa,QAAQ,CAAC;AAW1C,QAAM,qBAAwC;AAAA,IAC5C,CAAC,SAAS;AACR,kBAAY,EAAE,MAAM,KAAK,MAAM,SAAS,CAAC;AAAA,IAC3C;AAAA,IACA,CAAC,aAAa,KAAK,QAAQ;AAAA,EAC7B;AAEA,SAAO,QAAQ,MAAM,oBAAoB,CAAC,kBAAkB,CAAC;AAC/D;","names":[]}
@@ -1,8 +1,9 @@
1
1
  import { type Dictionary, type ContentNode, type KeyPath } from '@intlayer/core';
2
- import { type FC, type PropsWithChildren } from 'react';
2
+ import { type Dispatch, type SetStateAction, type FC, type PropsWithChildren } from 'react';
3
3
  import { type DictionaryContent } from './DictionariesRecordContext';
4
4
  type EditedContentActionsContextType = {
5
5
  setEditedContentState: (editedContent: Record<Dictionary['key'], Dictionary>) => void;
6
+ setEditedDictionary: Dispatch<SetStateAction<Dictionary>>;
6
7
  setEditedContent: (dictionaryKey: Dictionary['key'], newValue: Dictionary['content']) => void;
7
8
  addEditedContent: (dictionaryKey: Dictionary['key'], newValue: ContentNode<any>, keyPath?: KeyPath[], overwrite?: boolean) => void;
8
9
  renameEditedContent: (dictionaryKey: Dictionary['key'], newKey: KeyPath['key'], keyPath?: KeyPath[]) => void;
@@ -12,11 +13,12 @@ type EditedContentActionsContextType = {
12
13
  clearEditedContent: () => void;
13
14
  getEditedContentValue: (dictionaryKey: Dictionary['key'], keyPath: KeyPath[]) => ContentNode | undefined;
14
15
  };
15
- export declare const useEditedContentState: () => [DictionaryContent, import("react").Dispatch<import("react").SetStateAction<DictionaryContent>>];
16
+ export declare const useEditedContentState: () => [DictionaryContent, Dispatch<SetStateAction<DictionaryContent>>];
16
17
  export declare const EditedContentProvider: FC<PropsWithChildren>;
17
18
  export declare const useEditedContentActions: () => EditedContentActionsContextType;
18
19
  export declare const useEditedContent: () => {
19
20
  setEditedContentState: (editedContent: Record<Dictionary["key"], Dictionary>) => void;
21
+ setEditedDictionary: Dispatch<SetStateAction<Dictionary>>;
20
22
  setEditedContent: (dictionaryKey: Dictionary["key"], newValue: Dictionary["content"]) => void;
21
23
  addEditedContent: (dictionaryKey: Dictionary["key"], newValue: ContentNode<any>, keyPath?: KeyPath[], overwrite?: boolean) => void;
22
24
  renameEditedContent: (dictionaryKey: Dictionary["key"], newKey: KeyPath["key"], keyPath?: KeyPath[]) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"EditedContentContext.d.ts","sourceRoot":"","sources":["../../src/EditedContentContext.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EditedContentContext.d.ts","sourceRoot":"","sources":["../../src/EditedContentContext.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useCrossFrameMessageListener.d.ts","sourceRoot":"","sources":["../../src/useCrossFrameMessageListener.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,4BAA4B,GAAI,CAAC,OACvC,GAAG,UAAU,EAAE,GAAG,GAAG,UAAU,OAAO,GAAG,GAAG,UAAU,MAAM,qBAC9C,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,YAoDH,CAAC,KAAK,IAQxC,CAAC"}
1
+ {"version":3,"file":"useCrossFrameMessageListener.d.ts","sourceRoot":"","sources":["../../src/useCrossFrameMessageListener.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AA+C/C;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,4BAA4B,GAAI,CAAC,OACvC,GAAG,UAAU,EAAE,GAAG,GAAG,UAAU,OAAO,GAAG,GAAG,UAAU,MAAM,qBAC9C,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,YAoDH,CAAC,KAAK,IAQxC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intlayer/editor-react",
3
- "version": "5.1.3",
3
+ "version": "5.1.5",
4
4
  "private": false,
5
5
  "description": "Provides the states, contexts, hooks and components to interact with the Intlayer editor for a React application",
6
6
  "keywords": [
@@ -52,9 +52,9 @@
52
52
  ],
53
53
  "dependencies": {
54
54
  "uuid": "^11.0.5",
55
- "@intlayer/config": "5.1.3",
56
- "@intlayer/core": "5.1.3",
57
- "@intlayer/editor": "5.1.3"
55
+ "@intlayer/config": "5.1.5",
56
+ "@intlayer/core": "5.1.5",
57
+ "@intlayer/editor": "5.1.5"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@types/node": "^22.10.6",
@@ -68,17 +68,17 @@
68
68
  "tsc-alias": "^1.8.10",
69
69
  "tsup": "^8.3.5",
70
70
  "typescript": "^5.7.3",
71
- "@utils/ts-config": "1.0.4",
72
71
  "@utils/eslint-config": "1.0.4",
72
+ "@utils/ts-config": "1.0.4",
73
73
  "@utils/ts-config-types": "1.0.4",
74
74
  "@utils/tsup-config": "1.0.4"
75
75
  },
76
76
  "peerDependencies": {
77
77
  "react": ">=16.0.0",
78
78
  "react-dom": ">=16.0.0",
79
- "@intlayer/editor": "5.1.3",
80
- "@intlayer/config": "5.1.3",
81
- "@intlayer/core": "5.1.3"
79
+ "@intlayer/config": "5.1.5",
80
+ "@intlayer/editor": "5.1.5",
81
+ "@intlayer/core": "5.1.5"
82
82
  },
83
83
  "engines": {
84
84
  "node": ">=14.18"