@intlayer/editor-react 7.0.2-canary.0 → 7.0.2

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 (53) hide show
  1. package/dist/cjs/EditedContentContext.cjs +7 -2
  2. package/dist/cjs/EditedContentContext.cjs.map +1 -1
  3. package/dist/cjs/FocusDictionaryContext copy.cjs +57 -0
  4. package/dist/cjs/FocusDictionaryContext copy.cjs.map +1 -0
  5. package/dist/cjs/FocusDictionaryContext.cjs +4 -1
  6. package/dist/cjs/FocusDictionaryContext.cjs.map +1 -1
  7. package/dist/cjs/FocusDictionaryServerContext.cjs +24 -0
  8. package/dist/cjs/FocusDictionaryServerContext.cjs.map +1 -0
  9. package/dist/cjs/FocusDictionaryUnmergedContext.cjs +102 -0
  10. package/dist/cjs/FocusDictionaryUnmergedContext.cjs.map +1 -0
  11. package/dist/cjs/index.cjs +5 -0
  12. package/dist/cjs/useCrossFrameMessageListener.cjs +6 -1
  13. package/dist/cjs/useCrossFrameMessageListener.cjs.map +1 -1
  14. package/dist/cjs/useEditorLocale.cjs +24 -0
  15. package/dist/cjs/useEditorLocale.cjs.map +1 -0
  16. package/dist/cjs/useFocusUnmergedDictionary.cjs +64 -0
  17. package/dist/cjs/useFocusUnmergedDictionary.cjs.map +1 -0
  18. package/dist/esm/EditedContentContext.mjs +6 -2
  19. package/dist/esm/EditedContentContext.mjs.map +1 -1
  20. package/dist/esm/FocusDictionaryContext copy.mjs +51 -0
  21. package/dist/esm/FocusDictionaryContext copy.mjs.map +1 -0
  22. package/dist/esm/FocusDictionaryContext.mjs +3 -1
  23. package/dist/esm/FocusDictionaryContext.mjs.map +1 -1
  24. package/dist/esm/FocusDictionaryServerContext.mjs +21 -0
  25. package/dist/esm/FocusDictionaryServerContext.mjs.map +1 -0
  26. package/dist/esm/FocusDictionaryUnmergedContext.mjs +93 -0
  27. package/dist/esm/FocusDictionaryUnmergedContext.mjs.map +1 -0
  28. package/dist/esm/index.mjs +3 -1
  29. package/dist/esm/useCrossFrameMessageListener.mjs +6 -1
  30. package/dist/esm/useCrossFrameMessageListener.mjs.map +1 -1
  31. package/dist/esm/useEditorLocale.mjs +21 -0
  32. package/dist/esm/useEditorLocale.mjs.map +1 -0
  33. package/dist/esm/useFocusUnmergedDictionary.mjs +61 -0
  34. package/dist/esm/useFocusUnmergedDictionary.mjs.map +1 -0
  35. package/dist/types/ConfigurationContext.d.ts +2 -2
  36. package/dist/types/EditedContentContext.d.ts.map +1 -1
  37. package/dist/types/EditorEnabledContext.d.ts +2 -2
  38. package/dist/types/FocusDictionaryContext copy.d.ts +23 -0
  39. package/dist/types/FocusDictionaryContext copy.d.ts.map +1 -0
  40. package/dist/types/FocusDictionaryContext.d.ts +6 -3
  41. package/dist/types/FocusDictionaryContext.d.ts.map +1 -1
  42. package/dist/types/FocusDictionaryServerContext.d.ts +9 -0
  43. package/dist/types/FocusDictionaryServerContext.d.ts.map +1 -0
  44. package/dist/types/FocusDictionaryUnmergedContext.d.ts +43 -0
  45. package/dist/types/FocusDictionaryUnmergedContext.d.ts.map +1 -0
  46. package/dist/types/index.d.ts +4 -2
  47. package/dist/types/useCrossFrameMessageListener.d.ts.map +1 -1
  48. package/dist/types/useCrossURLPathState.d.ts +3 -3
  49. package/dist/types/useEditorLocale.d.ts +9 -0
  50. package/dist/types/useEditorLocale.d.ts.map +1 -0
  51. package/dist/types/useFocusUnmergedDictionary.d.ts +13 -0
  52. package/dist/types/useFocusUnmergedDictionary.d.ts.map +1 -0
  53. package/package.json +13 -11
@@ -5,6 +5,7 @@ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
5
5
  const require_useCrossFrameMessageListener = require('./useCrossFrameMessageListener.cjs');
6
6
  const require_useCrossFrameState = require('./useCrossFrameState.cjs');
7
7
  const require_DictionariesRecordContext = require('./DictionariesRecordContext.cjs');
8
+ const require_useEditorLocale = require('./useEditorLocale.cjs');
8
9
  let react = require("react");
9
10
  react = require_rolldown_runtime.__toESM(react);
10
11
  let react_jsx_runtime = require("react/jsx-runtime");
@@ -13,6 +14,8 @@ let __intlayer_editor = require("@intlayer/editor");
13
14
  __intlayer_editor = require_rolldown_runtime.__toESM(__intlayer_editor);
14
15
  let __intlayer_core = require("@intlayer/core");
15
16
  __intlayer_core = require_rolldown_runtime.__toESM(__intlayer_core);
17
+ let __intlayer_types = require("@intlayer/types");
18
+ __intlayer_types = require_rolldown_runtime.__toESM(__intlayer_types);
16
19
 
17
20
  //#region src/EditedContentContext.tsx
18
21
  const EditedContentStateContext = (0, react.createContext)(void 0);
@@ -22,6 +25,7 @@ const EditedContentActionsContext = (0, react.createContext)(void 0);
22
25
  const resolveState = (state, prevState) => typeof state === "function" ? state(prevState) : state;
23
26
  const EditedContentProvider = ({ children }) => {
24
27
  const { localeDictionaries } = require_DictionariesRecordContext.useDictionariesRecord();
28
+ const currentLocale = require_useEditorLocale.useEditorLocale();
25
29
  const [editedContent, setEditedContentState] = require_useCrossFrameState.useCrossFrameState(__intlayer_editor.MessageKey.INTLAYER_EDITED_CONTENT_CHANGED);
26
30
  const setEditedDictionary = (newValue) => {
27
31
  let updatedDictionaries = resolveState(newValue);
@@ -125,10 +129,11 @@ const EditedContentProvider = ({ children }) => {
125
129
  };
126
130
  const getEditedContentValue = (localDictionaryIdOrKey, keyPath) => {
127
131
  if (!editedContent) return void 0;
128
- if (localDictionaryIdOrKey.includes(":local:") || localDictionaryIdOrKey.includes(":remote:")) return (0, __intlayer_core.getContentNodeByKeyPath)(editedContent?.[localDictionaryIdOrKey]?.content ?? {}, keyPath);
132
+ const filteredKeyPath = keyPath.filter((key) => key.type !== __intlayer_types.NodeType.Translation);
133
+ if (localDictionaryIdOrKey.includes(":local:") || localDictionaryIdOrKey.includes(":remote:")) return (0, __intlayer_core.getContentNodeByKeyPath)(editedContent?.[localDictionaryIdOrKey]?.content ?? {}, filteredKeyPath, currentLocale);
129
134
  const filteredDictionariesLocalId = Object.keys(editedContent).filter((key) => key.startsWith(`${localDictionaryIdOrKey}:`));
130
135
  for (const localDictionaryId of filteredDictionariesLocalId) {
131
- const contentNode = (0, __intlayer_core.getContentNodeByKeyPath)(editedContent?.[localDictionaryId]?.content ?? {}, keyPath);
136
+ const contentNode = (0, __intlayer_core.getContentNodeByKeyPath)(editedContent?.[localDictionaryId]?.content ?? {}, filteredKeyPath, currentLocale);
132
137
  if (contentNode) return contentNode;
133
138
  }
134
139
  };
@@ -1 +1 @@
1
- {"version":3,"file":"EditedContentContext.cjs","names":["useCrossFrameMessageListener","MessageKey","EditedContentProvider: FC<PropsWithChildren>","useDictionariesRecord","useCrossFrameState","setEditedDictionary: Dispatch<SetStateAction<Dictionary>>","updatedDictionaries: Dictionary","lastKeyPath: KeyPath"],"sources":["../../src/EditedContentContext.tsx"],"sourcesContent":["'use client';\n\nimport {\n editDictionaryByKeyPath,\n getContentNodeByKeyPath,\n renameContentNodeByKeyPath,\n} from '@intlayer/core';\nimport { MessageKey } from '@intlayer/editor';\nimport type {\n ContentNode,\n Dictionary,\n KeyPath,\n LocalDictionaryId,\n} from '@intlayer/types';\nimport {\n createContext,\n type Dispatch,\n type FC,\n type PropsWithChildren,\n type SetStateAction,\n useContext,\n} from 'react';\nimport {\n type DictionaryContent,\n useDictionariesRecord,\n} from './DictionariesRecordContext';\nimport { useCrossFrameMessageListener } from './useCrossFrameMessageListener';\nimport { useCrossFrameState } from './useCrossFrameState';\n\ntype EditedContentStateContextType = {\n editedContent: Record<LocalDictionaryId, Dictionary> | undefined;\n};\n\nconst EditedContentStateContext = createContext<\n EditedContentStateContextType | undefined\n>(undefined);\n\nexport const usePostEditedContentState = <S,>(\n onEventTriggered?: (data: S) => void\n) =>\n useCrossFrameMessageListener(\n `${MessageKey.INTLAYER_EDITED_CONTENT_CHANGED}/post`,\n onEventTriggered\n );\n\nexport const useGetEditedContentState = <S,>(\n onEventTriggered?: (data: S) => void\n) =>\n useCrossFrameMessageListener(\n `${MessageKey.INTLAYER_EDITED_CONTENT_CHANGED}/get`,\n onEventTriggered\n );\n\ntype EditedContentActionsContextType = {\n setEditedContentState: (editedContent: DictionaryContent) => void;\n setEditedDictionary: Dispatch<SetStateAction<Dictionary>>;\n setEditedContent: (\n localDictionaryId: LocalDictionaryId,\n newValue: Dictionary['content']\n ) => void;\n addEditedContent: (\n localDictionaryId: LocalDictionaryId,\n newValue: ContentNode<any>,\n keyPath?: KeyPath[],\n overwrite?: boolean\n ) => void;\n renameEditedContent: (\n localDictionaryId: LocalDictionaryId,\n newKey: KeyPath['key'],\n keyPath?: KeyPath[]\n ) => void;\n removeEditedContent: (\n localDictionaryId: LocalDictionaryId,\n keyPath: KeyPath[]\n ) => void;\n restoreEditedContent: (localDictionaryId: LocalDictionaryId) => void;\n clearEditedDictionaryContent: (localDictionaryId: LocalDictionaryId) => void;\n clearEditedContent: () => void;\n getEditedContentValue: (\n localDictionaryIdOrKey: LocalDictionaryId | Dictionary['key'] | string,\n keyPath: KeyPath[]\n ) => ContentNode | undefined;\n};\n\nconst EditedContentActionsContext = createContext<\n EditedContentActionsContextType | undefined\n>(undefined);\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 MessageKey.INTLAYER_EDITED_CONTENT_CHANGED\n );\n\n const setEditedDictionary: Dispatch<SetStateAction<Dictionary>> = (\n newValue\n ) => {\n let updatedDictionaries: Dictionary = resolveState(newValue);\n\n setEditedContentState((prev) => {\n if (!updatedDictionaries.localId) {\n console.error('no localId', updatedDictionaries);\n\n return prev;\n }\n\n updatedDictionaries = resolveState(\n newValue,\n prev?.[updatedDictionaries.localId]\n );\n\n return {\n ...prev,\n [updatedDictionaries.localId as LocalDictionaryId]: updatedDictionaries,\n };\n });\n\n return updatedDictionaries;\n };\n\n const setEditedContent = (\n localDictionaryId: LocalDictionaryId,\n newValue: Dictionary['content']\n ) => {\n setEditedContentState((prev) => ({\n ...prev,\n [localDictionaryId]: {\n ...prev?.[localDictionaryId],\n content: newValue,\n },\n }));\n };\n\n const addEditedContent = (\n localDictionaryId: LocalDictionaryId,\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[localDictionaryId]?.content;\n const currentContent = structuredClone(\n prev?.[localDictionaryId]?.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 [localDictionaryId]: {\n ...prev?.[localDictionaryId],\n content: updatedContent as Dictionary['content'],\n },\n };\n });\n };\n\n const renameEditedContent = (\n localDictionaryId: LocalDictionaryId,\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[localDictionaryId]?.content;\n const currentContent = structuredClone(\n prev?.[localDictionaryId]?.content ?? originalContent\n );\n\n const contentWithNewField = renameContentNodeByKeyPath(\n currentContent,\n newKey,\n keyPath\n );\n\n return {\n ...prev,\n [localDictionaryId]: {\n ...prev?.[localDictionaryId],\n content: contentWithNewField as Dictionary['content'],\n },\n };\n });\n };\n\n const removeEditedContent = (\n localDictionaryId: LocalDictionaryId,\n keyPath: KeyPath[]\n ) => {\n setEditedContentState((prev) => {\n // Retrieve the original content as reference\n const originalContent = localeDictionaries[localDictionaryId]?.content;\n const currentContent = structuredClone(\n prev?.[localDictionaryId]?.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 [localDictionaryId]: {\n ...prev?.[localDictionaryId],\n content: restoredContent as Dictionary['content'],\n },\n };\n });\n };\n\n const restoreEditedContent = (localDictionaryId: LocalDictionaryId) => {\n setEditedContentState((prev) => {\n const updated = { ...prev };\n delete updated[localDictionaryId];\n return updated;\n });\n };\n\n const clearEditedDictionaryContent = (\n localDictionaryId: LocalDictionaryId\n ) => {\n setEditedContentState((prev) => {\n const filtered = Object.entries(prev).reduce((acc, [key, value]) => {\n if (key === localDictionaryId) {\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 localDictionaryIdOrKey: LocalDictionaryId | Dictionary['key'] | string,\n keyPath: KeyPath[]\n ): ContentNode | undefined => {\n if (!editedContent) return undefined;\n\n const isDictionaryId =\n localDictionaryIdOrKey.includes(':local:') ||\n localDictionaryIdOrKey.includes(':remote:');\n\n if (isDictionaryId) {\n const currentContent =\n editedContent?.[localDictionaryIdOrKey as LocalDictionaryId]?.content ??\n {};\n\n const contentNode = getContentNodeByKeyPath(currentContent, keyPath);\n\n return contentNode;\n }\n\n const filteredDictionariesLocalId = Object.keys(editedContent).filter(\n (key) => key.startsWith(`${localDictionaryIdOrKey}:`)\n );\n\n for (const localDictionaryId of filteredDictionariesLocalId) {\n const currentContent =\n editedContent?.[localDictionaryId as LocalDictionaryId]?.content ?? {};\n const contentNode = getContentNodeByKeyPath(currentContent, keyPath);\n\n if (contentNode) return contentNode;\n }\n\n return undefined;\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 useContext(EditedContentActionsContext);\n\nexport const useEditedContent = () => {\n const stateContext = useContext(EditedContentStateContext);\n const actionContext = useEditedContentActions();\n\n return { ...stateContext, ...actionContext };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"EditedContentContext.cjs","names":["useCrossFrameMessageListener","MessageKey","EditedContentProvider: FC<PropsWithChildren>","useDictionariesRecord","useEditorLocale","useCrossFrameState","setEditedDictionary: Dispatch<SetStateAction<Dictionary>>","updatedDictionaries: Dictionary","lastKeyPath: KeyPath","NodeType"],"sources":["../../src/EditedContentContext.tsx"],"sourcesContent":["'use client';\n\nimport {\n editDictionaryByKeyPath,\n getContentNodeByKeyPath,\n renameContentNodeByKeyPath,\n} from '@intlayer/core';\nimport { MessageKey } from '@intlayer/editor';\nimport {\n type ContentNode,\n type Dictionary,\n type KeyPath,\n type LocalDictionaryId,\n NodeType,\n} from '@intlayer/types';\nimport {\n createContext,\n type Dispatch,\n type FC,\n type PropsWithChildren,\n type SetStateAction,\n useContext,\n} from 'react';\nimport {\n type DictionaryContent,\n useDictionariesRecord,\n} from './DictionariesRecordContext';\nimport { useCrossFrameMessageListener } from './useCrossFrameMessageListener';\nimport { useCrossFrameState } from './useCrossFrameState';\nimport { useEditorLocale } from './useEditorLocale';\n\ntype EditedContentStateContextType = {\n editedContent: Record<LocalDictionaryId, Dictionary> | undefined;\n};\n\nconst EditedContentStateContext = createContext<\n EditedContentStateContextType | undefined\n>(undefined);\n\nexport const usePostEditedContentState = <S,>(\n onEventTriggered?: (data: S) => void\n) =>\n useCrossFrameMessageListener(\n `${MessageKey.INTLAYER_EDITED_CONTENT_CHANGED}/post`,\n onEventTriggered\n );\n\nexport const useGetEditedContentState = <S,>(\n onEventTriggered?: (data: S) => void\n) =>\n useCrossFrameMessageListener(\n `${MessageKey.INTLAYER_EDITED_CONTENT_CHANGED}/get`,\n onEventTriggered\n );\n\ntype EditedContentActionsContextType = {\n setEditedContentState: (editedContent: DictionaryContent) => void;\n setEditedDictionary: Dispatch<SetStateAction<Dictionary>>;\n setEditedContent: (\n localDictionaryId: LocalDictionaryId,\n newValue: Dictionary['content']\n ) => void;\n addEditedContent: (\n localDictionaryId: LocalDictionaryId,\n newValue: ContentNode<any>,\n keyPath?: KeyPath[],\n overwrite?: boolean\n ) => void;\n renameEditedContent: (\n localDictionaryId: LocalDictionaryId,\n newKey: KeyPath['key'],\n keyPath?: KeyPath[]\n ) => void;\n removeEditedContent: (\n localDictionaryId: LocalDictionaryId,\n keyPath: KeyPath[]\n ) => void;\n restoreEditedContent: (localDictionaryId: LocalDictionaryId) => void;\n clearEditedDictionaryContent: (localDictionaryId: LocalDictionaryId) => void;\n clearEditedContent: () => void;\n getEditedContentValue: (\n localDictionaryIdOrKey: LocalDictionaryId | Dictionary['key'] | string,\n keyPath: KeyPath[]\n ) => ContentNode | undefined;\n};\n\nconst EditedContentActionsContext = createContext<\n EditedContentActionsContextType | undefined\n>(undefined);\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 const currentLocale = useEditorLocale();\n\n const [editedContent, setEditedContentState] =\n useCrossFrameState<DictionaryContent>(\n MessageKey.INTLAYER_EDITED_CONTENT_CHANGED\n );\n\n const setEditedDictionary: Dispatch<SetStateAction<Dictionary>> = (\n newValue\n ) => {\n let updatedDictionaries: Dictionary = resolveState(newValue);\n\n setEditedContentState((prev) => {\n if (!updatedDictionaries.localId) {\n console.error('no localId', updatedDictionaries);\n\n return prev;\n }\n\n updatedDictionaries = resolveState(\n newValue,\n prev?.[updatedDictionaries.localId]\n );\n\n return {\n ...prev,\n [updatedDictionaries.localId as LocalDictionaryId]: updatedDictionaries,\n };\n });\n\n return updatedDictionaries;\n };\n\n const setEditedContent = (\n localDictionaryId: LocalDictionaryId,\n newValue: Dictionary['content']\n ) => {\n setEditedContentState((prev) => ({\n ...prev,\n [localDictionaryId]: {\n ...prev?.[localDictionaryId],\n content: newValue,\n },\n }));\n };\n\n const addEditedContent = (\n localDictionaryId: LocalDictionaryId,\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[localDictionaryId]?.content;\n const currentContent = structuredClone(\n prev?.[localDictionaryId]?.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\n const otherKeyPath = keyPath.slice(0, -1);\n const lastKeyPath: KeyPath = keyPath[keyPath.length - 1];\n\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 [localDictionaryId]: {\n ...prev?.[localDictionaryId],\n content: updatedContent as Dictionary['content'],\n },\n };\n });\n };\n\n const renameEditedContent = (\n localDictionaryId: LocalDictionaryId,\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[localDictionaryId]?.content;\n const currentContent = structuredClone(\n prev?.[localDictionaryId]?.content ?? originalContent\n );\n\n const contentWithNewField = renameContentNodeByKeyPath(\n currentContent,\n newKey,\n keyPath\n );\n\n return {\n ...prev,\n [localDictionaryId]: {\n ...prev?.[localDictionaryId],\n content: contentWithNewField as Dictionary['content'],\n },\n };\n });\n };\n\n const removeEditedContent = (\n localDictionaryId: LocalDictionaryId,\n keyPath: KeyPath[]\n ) => {\n setEditedContentState((prev) => {\n // Retrieve the original content as reference\n const originalContent = localeDictionaries[localDictionaryId]?.content;\n const currentContent = structuredClone(\n prev?.[localDictionaryId]?.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 [localDictionaryId]: {\n ...prev?.[localDictionaryId],\n content: restoredContent as Dictionary['content'],\n },\n };\n });\n };\n\n const restoreEditedContent = (localDictionaryId: LocalDictionaryId) => {\n setEditedContentState((prev) => {\n const updated = { ...prev };\n delete updated[localDictionaryId];\n return updated;\n });\n };\n\n const clearEditedDictionaryContent = (\n localDictionaryId: LocalDictionaryId\n ) => {\n setEditedContentState((prev) => {\n const filtered = Object.entries(prev).reduce((acc, [key, value]) => {\n if (key === localDictionaryId) {\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 localDictionaryIdOrKey: LocalDictionaryId | Dictionary['key'] | string,\n keyPath: KeyPath[]\n ): ContentNode | undefined => {\n if (!editedContent) return undefined;\n\n const filteredKeyPath = keyPath.filter(\n (key) => key.type !== NodeType.Translation\n );\n\n const isDictionaryId =\n localDictionaryIdOrKey.includes(':local:') ||\n localDictionaryIdOrKey.includes(':remote:');\n\n if (isDictionaryId) {\n const currentContent =\n editedContent?.[localDictionaryIdOrKey as LocalDictionaryId]?.content ??\n {};\n\n const contentNode = getContentNodeByKeyPath(\n currentContent,\n filteredKeyPath,\n currentLocale\n );\n\n return contentNode;\n }\n\n const filteredDictionariesLocalId = Object.keys(editedContent).filter(\n (key) => key.startsWith(`${localDictionaryIdOrKey}:`)\n );\n\n for (const localDictionaryId of filteredDictionariesLocalId) {\n const currentContent =\n editedContent?.[localDictionaryId as LocalDictionaryId]?.content ?? {};\n const contentNode = getContentNodeByKeyPath(\n currentContent,\n filteredKeyPath,\n currentLocale\n );\n\n if (contentNode) return contentNode;\n }\n\n return undefined;\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 useContext(EditedContentActionsContext);\n\nexport const useEditedContent = () => {\n const stateContext = useContext(EditedContentStateContext);\n const actionContext = useEditedContentActions();\n\n return { ...stateContext, ...actionContext };\n};\n"],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ 'use client';
2
+
3
+
4
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
5
+ const require_useCrossFrameState = require('./useCrossFrameState.cjs');
6
+ let react = require("react");
7
+ react = require_rolldown_runtime.__toESM(react);
8
+ let react_jsx_runtime = require("react/jsx-runtime");
9
+ react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
10
+ let __intlayer_editor = require("@intlayer/editor");
11
+ __intlayer_editor = require_rolldown_runtime.__toESM(__intlayer_editor);
12
+
13
+ //#region src/FocusDictionaryContext copy.tsx
14
+ const FocusDictionaryStateContext = (0, react.createContext)(void 0);
15
+ const FocusDictionaryActionsContext = (0, react.createContext)(void 0);
16
+ const FocusDictionaryProvider = ({ children }) => {
17
+ const [focusedContent, setFocusedContent] = require_useCrossFrameState.useCrossFrameState(__intlayer_editor.MessageKey.INTLAYER_FOCUSED_CONTENT_CHANGED, null);
18
+ const setFocusedContentKeyPath = (keyPath) => {
19
+ setFocusedContent((prev) => {
20
+ if (!prev) return prev;
21
+ return {
22
+ ...prev,
23
+ keyPath
24
+ };
25
+ });
26
+ };
27
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FocusDictionaryStateContext.Provider, {
28
+ value: { focusedContent },
29
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FocusDictionaryActionsContext.Provider, {
30
+ value: {
31
+ setFocusedContent,
32
+ setFocusedContentKeyPath
33
+ },
34
+ children
35
+ })
36
+ });
37
+ };
38
+ const useFocusDictionaryActions = () => {
39
+ const context = (0, react.useContext)(FocusDictionaryActionsContext);
40
+ if (context === void 0) throw new Error("useFocusDictionaryActions must be used within a FocusDictionaryProvider");
41
+ return context;
42
+ };
43
+ const useFocusDictionary = () => {
44
+ const actionContext = useFocusDictionaryActions();
45
+ const stateContext = (0, react.useContext)(FocusDictionaryStateContext);
46
+ if (stateContext === void 0) throw new Error("useFocusDictionaryState must be used within a FocusDictionaryProvider");
47
+ return {
48
+ ...stateContext,
49
+ ...actionContext
50
+ };
51
+ };
52
+
53
+ //#endregion
54
+ exports.FocusDictionaryProvider = FocusDictionaryProvider;
55
+ exports.useFocusDictionary = useFocusDictionary;
56
+ exports.useFocusDictionaryActions = useFocusDictionaryActions;
57
+ //# sourceMappingURL=FocusDictionaryContext copy.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FocusDictionaryContext copy.cjs","names":["FocusDictionaryProvider: FC<PropsWithChildren>","useCrossFrameState","MessageKey"],"sources":["../../src/FocusDictionaryContext copy.tsx"],"sourcesContent":["'use client';\n\nimport { MessageKey } from '@intlayer/editor';\nimport type { KeyPath } from '@intlayer/types';\nimport {\n createContext,\n type Dispatch,\n type FC,\n type PropsWithChildren,\n type SetStateAction,\n useContext,\n} from 'react';\nimport { useCrossFrameState } from './useCrossFrameState';\n\nexport type FileContent = {\n dictionaryKey: string;\n dictionaryLocalId?: string;\n keyPath?: KeyPath[];\n};\n\ntype FocusDictionaryState = {\n focusedContent: FileContent | null;\n};\n\ntype FocusDictionaryActions = {\n setFocusedContent: Dispatch<SetStateAction<FileContent | null>>;\n setFocusedContentKeyPath: (keyPath: KeyPath[]) => void;\n};\n\nconst FocusDictionaryStateContext = createContext<\n FocusDictionaryState | undefined\n>(undefined);\nconst FocusDictionaryActionsContext = createContext<\n FocusDictionaryActions | undefined\n>(undefined);\n\nexport const FocusDictionaryProvider: FC<PropsWithChildren> = ({\n children,\n}) => {\n const [focusedContent, setFocusedContent] =\n useCrossFrameState<FileContent | null>(\n MessageKey.INTLAYER_FOCUSED_CONTENT_CHANGED,\n null\n );\n\n const setFocusedContentKeyPath = (keyPath: KeyPath[]) => {\n setFocusedContent((prev) => {\n if (!prev) {\n return prev; // nothing to update if there's no focused content\n }\n return { ...prev, keyPath };\n });\n };\n\n return (\n <FocusDictionaryStateContext.Provider value={{ focusedContent }}>\n <FocusDictionaryActionsContext.Provider\n value={{ setFocusedContent, setFocusedContentKeyPath }}\n >\n {children}\n </FocusDictionaryActionsContext.Provider>\n </FocusDictionaryStateContext.Provider>\n );\n};\n\nexport const useFocusDictionaryActions = () => {\n const context = useContext(FocusDictionaryActionsContext);\n if (context === undefined) {\n throw new Error(\n 'useFocusDictionaryActions must be used within a FocusDictionaryProvider'\n );\n }\n return context;\n};\n\nexport const useFocusDictionary = () => {\n const actionContext = useFocusDictionaryActions();\n const stateContext = useContext(FocusDictionaryStateContext);\n\n if (stateContext === undefined) {\n throw new Error(\n 'useFocusDictionaryState must be used within a FocusDictionaryProvider'\n );\n }\n\n return { ...stateContext, ...actionContext };\n};\n"],"mappings":";;;;;;;;;;;;;AA6BA,MAAM,uDAEJ,OAAU;AACZ,MAAM,yDAEJ,OAAU;AAEZ,MAAaA,2BAAkD,EAC7D,eACI;CACJ,MAAM,CAAC,gBAAgB,qBACrBC,8CACEC,6BAAW,kCACX,KACD;CAEH,MAAM,4BAA4B,YAAuB;AACvD,qBAAmB,SAAS;AAC1B,OAAI,CAAC,KACH,QAAO;AAET,UAAO;IAAE,GAAG;IAAM;IAAS;IAC3B;;AAGJ,QACE,2CAAC,4BAA4B;EAAS,OAAO,EAAE,gBAAgB;YAC7D,2CAAC,8BAA8B;GAC7B,OAAO;IAAE;IAAmB;IAA0B;GAErD;IACsC;GACJ;;AAI3C,MAAa,kCAAkC;CAC7C,MAAM,gCAAqB,8BAA8B;AACzD,KAAI,YAAY,OACd,OAAM,IAAI,MACR,0EACD;AAEH,QAAO;;AAGT,MAAa,2BAA2B;CACtC,MAAM,gBAAgB,2BAA2B;CACjD,MAAM,qCAA0B,4BAA4B;AAE5D,KAAI,iBAAiB,OACnB,OAAM,IAAI,MACR,wEACD;AAGH,QAAO;EAAE,GAAG;EAAc,GAAG;EAAe"}
@@ -9,6 +9,8 @@ let react_jsx_runtime = require("react/jsx-runtime");
9
9
  react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
10
10
  let __intlayer_editor = require("@intlayer/editor");
11
11
  __intlayer_editor = require_rolldown_runtime.__toESM(__intlayer_editor);
12
+ let __intlayer_types = require("@intlayer/types");
13
+ __intlayer_types = require_rolldown_runtime.__toESM(__intlayer_types);
12
14
 
13
15
  //#region src/FocusDictionaryContext.tsx
14
16
  const FocusDictionaryStateContext = (0, react.createContext)(void 0);
@@ -18,9 +20,10 @@ const FocusDictionaryProvider = ({ children }) => {
18
20
  const setFocusedContentKeyPath = (keyPath) => {
19
21
  setFocusedContent((prev) => {
20
22
  if (!prev) return prev;
23
+ const filteredKeyPath = keyPath.filter((key) => key.type !== __intlayer_types.NodeType.Translation);
21
24
  return {
22
25
  ...prev,
23
- keyPath
26
+ keyPath: filteredKeyPath
24
27
  };
25
28
  });
26
29
  };
@@ -1 +1 @@
1
- {"version":3,"file":"FocusDictionaryContext.cjs","names":["FocusDictionaryProvider: FC<PropsWithChildren>","useCrossFrameState","MessageKey"],"sources":["../../src/FocusDictionaryContext.tsx"],"sourcesContent":["'use client';\n\nimport { MessageKey } from '@intlayer/editor';\nimport type { KeyPath } from '@intlayer/types';\nimport {\n createContext,\n type Dispatch,\n type FC,\n type PropsWithChildren,\n type SetStateAction,\n useContext,\n} from 'react';\nimport { useCrossFrameState } from './useCrossFrameState';\n\nexport type FileContent = {\n dictionaryKey: string;\n dictionaryLocalId?: string;\n keyPath?: KeyPath[];\n};\n\ntype FocusDictionaryState = {\n focusedContent: FileContent | null;\n};\n\ntype FocusDictionaryActions = {\n setFocusedContent: Dispatch<SetStateAction<FileContent | null>>;\n setFocusedContentKeyPath: (keyPath: KeyPath[]) => void;\n};\n\nconst FocusDictionaryStateContext = createContext<\n FocusDictionaryState | undefined\n>(undefined);\nconst FocusDictionaryActionsContext = createContext<\n FocusDictionaryActions | undefined\n>(undefined);\n\nexport const FocusDictionaryProvider: FC<PropsWithChildren> = ({\n children,\n}) => {\n const [focusedContent, setFocusedContent] =\n useCrossFrameState<FileContent | null>(\n MessageKey.INTLAYER_FOCUSED_CONTENT_CHANGED,\n null\n );\n\n const setFocusedContentKeyPath = (keyPath: KeyPath[]) => {\n setFocusedContent((prev) => {\n if (!prev) {\n return prev; // nothing to update if there's no focused content\n }\n return { ...prev, keyPath };\n });\n };\n\n return (\n <FocusDictionaryStateContext.Provider value={{ focusedContent }}>\n <FocusDictionaryActionsContext.Provider\n value={{ setFocusedContent, setFocusedContentKeyPath }}\n >\n {children}\n </FocusDictionaryActionsContext.Provider>\n </FocusDictionaryStateContext.Provider>\n );\n};\n\nexport const useFocusDictionaryActions = () => {\n const context = useContext(FocusDictionaryActionsContext);\n if (context === undefined) {\n throw new Error(\n 'useFocusDictionaryActions must be used within a FocusDictionaryProvider'\n );\n }\n return context;\n};\n\nexport const useFocusDictionary = () => {\n const actionContext = useFocusDictionaryActions();\n const stateContext = useContext(FocusDictionaryStateContext);\n\n if (stateContext === undefined) {\n throw new Error(\n 'useFocusDictionaryState must be used within a FocusDictionaryProvider'\n );\n }\n\n return { ...stateContext, ...actionContext };\n};\n"],"mappings":";;;;;;;;;;;;;AA6BA,MAAM,uDAEJ,OAAU;AACZ,MAAM,yDAEJ,OAAU;AAEZ,MAAaA,2BAAkD,EAC7D,eACI;CACJ,MAAM,CAAC,gBAAgB,qBACrBC,8CACEC,6BAAW,kCACX,KACD;CAEH,MAAM,4BAA4B,YAAuB;AACvD,qBAAmB,SAAS;AAC1B,OAAI,CAAC,KACH,QAAO;AAET,UAAO;IAAE,GAAG;IAAM;IAAS;IAC3B;;AAGJ,QACE,2CAAC,4BAA4B;EAAS,OAAO,EAAE,gBAAgB;YAC7D,2CAAC,8BAA8B;GAC7B,OAAO;IAAE;IAAmB;IAA0B;GAErD;IACsC;GACJ;;AAI3C,MAAa,kCAAkC;CAC7C,MAAM,gCAAqB,8BAA8B;AACzD,KAAI,YAAY,OACd,OAAM,IAAI,MACR,0EACD;AAEH,QAAO;;AAGT,MAAa,2BAA2B;CACtC,MAAM,gBAAgB,2BAA2B;CACjD,MAAM,qCAA0B,4BAA4B;AAE5D,KAAI,iBAAiB,OACnB,OAAM,IAAI,MACR,wEACD;AAGH,QAAO;EAAE,GAAG;EAAc,GAAG;EAAe"}
1
+ {"version":3,"file":"FocusDictionaryContext.cjs","names":["FocusDictionaryProvider: FC<PropsWithChildren>","useCrossFrameState","MessageKey","NodeType"],"sources":["../../src/FocusDictionaryContext.tsx"],"sourcesContent":["'use client';\n\nimport { MessageKey } from '@intlayer/editor';\nimport {\n type KeyPath,\n type LocalDictionaryId,\n NodeType,\n} from '@intlayer/types';\nimport {\n createContext,\n type Dispatch,\n type FC,\n type PropsWithChildren,\n type SetStateAction,\n useContext,\n} from 'react';\nimport { useCrossFrameState } from './useCrossFrameState';\n\nexport type FileContent = {\n dictionaryKey: string;\n dictionaryLocalId?: LocalDictionaryId;\n keyPath?: KeyPath[];\n};\n\nexport type FocusDictionaryState = {\n focusedContent: FileContent | null;\n};\n\nexport type FocusDictionaryActions = {\n setFocusedContent: Dispatch<SetStateAction<FileContent | null>>;\n setFocusedContentKeyPath: (keyPath: KeyPath[]) => void;\n};\n\nconst FocusDictionaryStateContext = createContext<\n FocusDictionaryState | undefined\n>(undefined);\nconst FocusDictionaryActionsContext = createContext<\n FocusDictionaryActions | undefined\n>(undefined);\n\nexport const FocusDictionaryProvider: FC<PropsWithChildren> = ({\n children,\n}) => {\n const [focusedContent, setFocusedContent] =\n useCrossFrameState<FileContent | null>(\n MessageKey.INTLAYER_FOCUSED_CONTENT_CHANGED,\n null\n );\n\n const setFocusedContentKeyPath = (keyPath: KeyPath[]) => {\n setFocusedContent((prev) => {\n if (!prev) {\n return prev; // nothing to update if there's no focused content\n }\n\n // Remove translation key path if it exists to make it more flexible with optimization client / editor\n const filteredKeyPath = keyPath.filter(\n (key) => key.type !== NodeType.Translation\n );\n\n return {\n ...prev,\n keyPath: filteredKeyPath,\n };\n });\n };\n\n return (\n <FocusDictionaryStateContext.Provider value={{ focusedContent }}>\n <FocusDictionaryActionsContext.Provider\n value={{ setFocusedContent, setFocusedContentKeyPath }}\n >\n {children}\n </FocusDictionaryActionsContext.Provider>\n </FocusDictionaryStateContext.Provider>\n );\n};\n\nexport const useFocusDictionaryActions = () => {\n const context = useContext(FocusDictionaryActionsContext);\n if (context === undefined) {\n throw new Error(\n 'useFocusDictionaryActions must be used within a FocusDictionaryProvider'\n );\n }\n return context;\n};\n\nexport const useFocusDictionary = () => {\n const actionContext = useFocusDictionaryActions();\n const stateContext = useContext(FocusDictionaryStateContext);\n\n if (stateContext === undefined) {\n throw new Error(\n 'useFocusDictionaryState must be used within a FocusDictionaryProvider'\n );\n }\n\n return { ...stateContext, ...actionContext };\n};\n"],"mappings":";;;;;;;;;;;;;;;AAiCA,MAAM,uDAEJ,OAAU;AACZ,MAAM,yDAEJ,OAAU;AAEZ,MAAaA,2BAAkD,EAC7D,eACI;CACJ,MAAM,CAAC,gBAAgB,qBACrBC,8CACEC,6BAAW,kCACX,KACD;CAEH,MAAM,4BAA4B,YAAuB;AACvD,qBAAmB,SAAS;AAC1B,OAAI,CAAC,KACH,QAAO;GAIT,MAAM,kBAAkB,QAAQ,QAC7B,QAAQ,IAAI,SAASC,0BAAS,YAChC;AAED,UAAO;IACL,GAAG;IACH,SAAS;IACV;IACD;;AAGJ,QACE,2CAAC,4BAA4B;EAAS,OAAO,EAAE,gBAAgB;YAC7D,2CAAC,8BAA8B;GAC7B,OAAO;IAAE;IAAmB;IAA0B;GAErD;IACsC;GACJ;;AAI3C,MAAa,kCAAkC;CAC7C,MAAM,gCAAqB,8BAA8B;AACzD,KAAI,YAAY,OACd,OAAM,IAAI,MACR,0EACD;AAEH,QAAO;;AAGT,MAAa,2BAA2B;CACtC,MAAM,gBAAgB,2BAA2B;CACjD,MAAM,qCAA0B,4BAA4B;AAE5D,KAAI,iBAAiB,OACnB,OAAM,IAAI,MACR,wEACD;AAGH,QAAO;EAAE,GAAG;EAAc,GAAG;EAAe"}
@@ -0,0 +1,24 @@
1
+ 'use client';
2
+
3
+
4
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
5
+ const require_FocusDictionaryContext = require('./FocusDictionaryContext.cjs');
6
+ let react = require("react");
7
+ react = require_rolldown_runtime.__toESM(react);
8
+ let __intlayer_types = require("@intlayer/types");
9
+ __intlayer_types = require_rolldown_runtime.__toESM(__intlayer_types);
10
+
11
+ //#region src/FocusDictionaryServerContext.tsx
12
+ const unmergedKeyPathToMergedKeyPath = (keyPath) => {
13
+ if (!keyPath.find((key) => key.type === __intlayer_types.NodeType.Translation)) return keyPath;
14
+ return [keyPath.find((key) => key.type === __intlayer_types.NodeType.Translation), ...keyPath.filter((key) => key.type !== __intlayer_types.NodeType.Translation)];
15
+ };
16
+ const useFocusUnmergedDictionary = () => {
17
+ const [focusedKeyPath, setFocusedKeyPath] = (0, react.useState)([]);
18
+ const { setFocusedContent: setMergedFocusedContent, setFocusedContentKeyPath: setMergedFocusedContentKeyPath, focusedContent: mergedFocusedContent } = require_FocusDictionaryContext.useFocusDictionary();
19
+ return { focusedContent: unmergedKeyPathToMergedKeyPath(focusedKeyPath) };
20
+ };
21
+
22
+ //#endregion
23
+ exports.useFocusUnmergedDictionary = useFocusUnmergedDictionary;
24
+ //# sourceMappingURL=FocusDictionaryServerContext.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FocusDictionaryServerContext.cjs","names":["NodeType","useFocusDictionary"],"sources":["../../src/FocusDictionaryServerContext.tsx"],"sourcesContent":["'use client';\n\nimport { type Dictionary, type KeyPath, NodeType } from '@intlayer/types';\nimport { useState } from 'react';\nimport { useFocusDictionary } from './FocusDictionaryContext';\n\nconst unmergedKeyPathToMergedKeyPath = (keyPath: KeyPath[]): KeyPath[] => {\n if (!keyPath.find((key) => key.type === NodeType.Translation)) return keyPath;\n\n const translationKeyPath = keyPath.find(\n (key) => key.type === NodeType.Translation\n )!;\n const otherKeyPath = keyPath.filter(\n (key) => key.type !== NodeType.Translation\n );\n\n return [translationKeyPath, ...otherKeyPath];\n};\n\nconst mergedKeyPathToUnmergedKeyPath = (\n keyPath: KeyPath[],\n dictionary: Dictionary\n): KeyPath[] => {\n if (!keyPath.find((key) => key.type === NodeType.Translation)) return keyPath;\n\n const translationKeyPath = keyPath.find(\n (key) => key.type === NodeType.Translation\n )!;\n const otherKeyPath = keyPath.filter(\n (key) => key.type !== NodeType.Translation\n );\n\n // it should insert the translation key path at the end and then end -1, end -2, etc.\n const candidates = Object(otherKeyPath.length).map((_, index) =>\n otherKeyPath.slice(0, index + 1)\n );\n\n for (const candidate of candidates) {\n const result = getContentNodeByKeyPath(dictionary.content, candidate);\n\n if (result) {\n return candidate;\n }\n }\n\n return null;\n};\n\nexport const useFocusUnmergedDictionary = () => {\n const [focusedKeyPath, setFocusedKeyPath] = useState<KeyPath[]>([]);\n\n const {\n setFocusedContent: setMergedFocusedContent,\n setFocusedContentKeyPath: setMergedFocusedContentKeyPath,\n focusedContent: mergedFocusedContent,\n } = useFocusDictionary();\n\n const focusedContent = unmergedKeyPathToMergedKeyPath(focusedKeyPath);\n\n return { focusedContent };\n};\n"],"mappings":";;;;;;;;;;;AAMA,MAAM,kCAAkC,YAAkC;AACxE,KAAI,CAAC,QAAQ,MAAM,QAAQ,IAAI,SAASA,0BAAS,YAAY,CAAE,QAAO;AAStE,QAAO,CAPoB,QAAQ,MAChC,QAAQ,IAAI,SAASA,0BAAS,YAChC,EAK2B,GAJP,QAAQ,QAC1B,QAAQ,IAAI,SAASA,0BAAS,YAChC,CAE2C;;AAgC9C,MAAa,mCAAmC;CAC9C,MAAM,CAAC,gBAAgB,yCAAyC,EAAE,CAAC;CAEnE,MAAM,EACJ,mBAAmB,yBACnB,0BAA0B,gCAC1B,gBAAgB,yBACdC,mDAAoB;AAIxB,QAAO,EAAE,gBAFc,+BAA+B,eAAe,EAE5C"}
@@ -0,0 +1,102 @@
1
+ 'use client';
2
+
3
+
4
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
5
+ const require_FocusDictionaryContext = require('./FocusDictionaryContext.cjs');
6
+ let react = require("react");
7
+ react = require_rolldown_runtime.__toESM(react);
8
+ let react_jsx_runtime = require("react/jsx-runtime");
9
+ react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
10
+ let __intlayer_core = require("@intlayer/core");
11
+ __intlayer_core = require_rolldown_runtime.__toESM(__intlayer_core);
12
+ let __intlayer_types = require("@intlayer/types");
13
+ __intlayer_types = require_rolldown_runtime.__toESM(__intlayer_types);
14
+
15
+ //#region src/FocusDictionaryUnmergedContext.tsx
16
+ /**
17
+ * Transforms a keypath from unmerged dictionary format to merged dictionary format.
18
+ * In merged format, translation keys come first.
19
+ *
20
+ * Example:
21
+ * Unmerged: [{ type: 'object', key: 'title' }, { type: 'translation', key: 'fr' }]
22
+ * Merged: [{ type: 'translation', key: 'fr' }, { type: 'object', key: 'title' }]
23
+ */
24
+ const unmergedKeyPathToMergedKeyPath = (keyPath) => {
25
+ if (!keyPath || keyPath.length === 0) return keyPath;
26
+ const translationKeyPath = keyPath.find((key) => key.type === __intlayer_types.NodeType.Translation);
27
+ if (!translationKeyPath) return keyPath;
28
+ return [translationKeyPath, ...keyPath.filter((key) => key.type !== __intlayer_types.NodeType.Translation)];
29
+ };
30
+ /**
31
+ * Transforms a keypath from merged dictionary format to unmerged dictionary format.
32
+ * In unmerged format, translation keys are placed at the appropriate nesting level.
33
+ *
34
+ * Example:
35
+ * Merged: [{ type: 'translation', key: 'fr' }, { type: 'object', key: 'title' }]
36
+ * Unmerged: [{ type: 'object', key: 'title' }, { type: 'translation', key: 'fr' }]
37
+ */
38
+ const mergedKeyPathToUnmergedKeyPath = (keyPath, dictionary) => {
39
+ if (!keyPath || keyPath.length === 0) return keyPath;
40
+ const translationKeyPath = keyPath.find((key) => key.type === __intlayer_types.NodeType.Translation);
41
+ if (!translationKeyPath) return keyPath;
42
+ const otherKeyPaths = keyPath.filter((key) => key.type !== __intlayer_types.NodeType.Translation);
43
+ if (dictionary?.content) for (let i = otherKeyPaths.length; i >= 0; i--) {
44
+ const candidateKeyPath = [
45
+ ...otherKeyPaths.slice(0, i),
46
+ translationKeyPath,
47
+ ...otherKeyPaths.slice(i)
48
+ ];
49
+ try {
50
+ if ((0, __intlayer_core.getContentNodeByKeyPath)(dictionary.content, candidateKeyPath)) return candidateKeyPath;
51
+ } catch {}
52
+ }
53
+ return [...otherKeyPaths, translationKeyPath];
54
+ };
55
+ const FocusDictionaryUnmergedStateContext = (0, react.createContext)(void 0);
56
+ const FocusDictionaryUnmergedActionsContext = (0, react.createContext)(void 0);
57
+ const FocusDictionaryUnmergedProvider = ({ children }) => {
58
+ const { focusedContent, setFocusedContent } = require_FocusDictionaryContext.useFocusDictionary();
59
+ const { setFocusedContentKeyPath: setMergedKeyPath } = require_FocusDictionaryContext.useFocusDictionaryActions();
60
+ const focusedUnmergedKeyPath = (0, react.useMemo)(() => {
61
+ if (!focusedContent?.keyPath) return void 0;
62
+ return focusedContent.keyPath;
63
+ }, [focusedContent?.keyPath]);
64
+ const setFocusedUnmergedKeyPath = (keyPath) => {
65
+ setMergedKeyPath(unmergedKeyPathToMergedKeyPath(keyPath));
66
+ };
67
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FocusDictionaryUnmergedStateContext.Provider, {
68
+ value: {
69
+ focusedContent,
70
+ focusedUnmergedKeyPath
71
+ },
72
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FocusDictionaryUnmergedActionsContext.Provider, {
73
+ value: {
74
+ setFocusedContent,
75
+ setFocusedUnmergedKeyPath
76
+ },
77
+ children
78
+ })
79
+ });
80
+ };
81
+ const useFocusDictionaryUnmergedActions = () => {
82
+ const context = (0, react.useContext)(FocusDictionaryUnmergedActionsContext);
83
+ if (context === void 0) throw new Error("useFocusDictionaryUnmergedActions must be used within a FocusDictionaryUnmergedProvider");
84
+ return context;
85
+ };
86
+ const useFocusDictionaryUnmerged = () => {
87
+ const actionContext = useFocusDictionaryUnmergedActions();
88
+ const stateContext = (0, react.useContext)(FocusDictionaryUnmergedStateContext);
89
+ if (stateContext === void 0) throw new Error("useFocusDictionaryUnmerged must be used within a FocusDictionaryUnmergedProvider");
90
+ return {
91
+ ...stateContext,
92
+ ...actionContext
93
+ };
94
+ };
95
+
96
+ //#endregion
97
+ exports.FocusDictionaryUnmergedProvider = FocusDictionaryUnmergedProvider;
98
+ exports.mergedKeyPathToUnmergedKeyPath = mergedKeyPathToUnmergedKeyPath;
99
+ exports.unmergedKeyPathToMergedKeyPath = unmergedKeyPathToMergedKeyPath;
100
+ exports.useFocusDictionaryUnmerged = useFocusDictionaryUnmerged;
101
+ exports.useFocusDictionaryUnmergedActions = useFocusDictionaryUnmergedActions;
102
+ //# sourceMappingURL=FocusDictionaryUnmergedContext.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FocusDictionaryUnmergedContext.cjs","names":["NodeType","FocusDictionaryUnmergedProvider: FC<PropsWithChildren>","useFocusDictionary","useFocusDictionaryActions"],"sources":["../../src/FocusDictionaryUnmergedContext.tsx"],"sourcesContent":["'use client';\n\nimport { getContentNodeByKeyPath } from '@intlayer/core';\nimport type { Dictionary, KeyPath } from '@intlayer/types';\nimport { NodeType } from '@intlayer/types';\nimport {\n createContext,\n type Dispatch,\n type FC,\n type PropsWithChildren,\n type SetStateAction,\n useContext,\n useMemo,\n} from 'react';\nimport {\n type FileContent,\n useFocusDictionary,\n useFocusDictionaryActions,\n} from './FocusDictionaryContext';\n\n/**\n * Transforms a keypath from unmerged dictionary format to merged dictionary format.\n * In merged format, translation keys come first.\n *\n * Example:\n * Unmerged: [{ type: 'object', key: 'title' }, { type: 'translation', key: 'fr' }]\n * Merged: [{ type: 'translation', key: 'fr' }, { type: 'object', key: 'title' }]\n */\nconst unmergedKeyPathToMergedKeyPath = (keyPath: KeyPath[]): KeyPath[] => {\n if (!keyPath || keyPath.length === 0) return keyPath;\n\n const translationKeyPath = keyPath.find(\n (key) => key.type === NodeType.Translation\n );\n\n // If no translation key, return as is\n if (!translationKeyPath) return keyPath;\n\n const otherKeyPaths = keyPath.filter(\n (key) => key.type !== NodeType.Translation\n );\n\n // Translation key comes first in merged format\n return [translationKeyPath, ...otherKeyPaths];\n};\n\n/**\n * Transforms a keypath from merged dictionary format to unmerged dictionary format.\n * In unmerged format, translation keys are placed at the appropriate nesting level.\n *\n * Example:\n * Merged: [{ type: 'translation', key: 'fr' }, { type: 'object', key: 'title' }]\n * Unmerged: [{ type: 'object', key: 'title' }, { type: 'translation', key: 'fr' }]\n */\nconst mergedKeyPathToUnmergedKeyPath = (\n keyPath: KeyPath[],\n dictionary?: Dictionary\n): KeyPath[] => {\n if (!keyPath || keyPath.length === 0) return keyPath;\n\n const translationKeyPath = keyPath.find(\n (key) => key.type === NodeType.Translation\n );\n\n // If no translation key, return as is\n if (!translationKeyPath) return keyPath;\n\n const otherKeyPaths = keyPath.filter(\n (key) => key.type !== NodeType.Translation\n );\n\n // If we have a dictionary, try to find the correct position for the translation key\n if (dictionary?.content) {\n // Try inserting the translation key at different positions from end to start\n // to find where it should be placed in the unmerged structure\n for (let i = otherKeyPaths.length; i >= 0; i--) {\n const candidateKeyPath = [\n ...otherKeyPaths.slice(0, i),\n translationKeyPath,\n ...otherKeyPaths.slice(i),\n ];\n\n try {\n const result = getContentNodeByKeyPath(\n dictionary.content,\n candidateKeyPath\n );\n if (result) {\n return candidateKeyPath;\n }\n } catch {\n // Continue trying other positions\n }\n }\n }\n\n // Default: translation key at the end (most common unmerged format)\n return [...otherKeyPaths, translationKeyPath];\n};\n\nexport type FocusDictionaryUnmergedState = {\n focusedContent: FileContent | null;\n focusedUnmergedKeyPath: KeyPath[] | undefined;\n};\n\nexport type FocusDictionaryUnmergedActions = {\n setFocusedContent: Dispatch<SetStateAction<FileContent | null>>;\n setFocusedUnmergedKeyPath: (keyPath: KeyPath[]) => void;\n};\n\nconst FocusDictionaryUnmergedStateContext = createContext<\n FocusDictionaryUnmergedState | undefined\n>(undefined);\n\nconst FocusDictionaryUnmergedActionsContext = createContext<\n FocusDictionaryUnmergedActions | undefined\n>(undefined);\n\nexport const FocusDictionaryUnmergedProvider: FC<PropsWithChildren> = ({\n children,\n}) => {\n const { focusedContent, setFocusedContent } = useFocusDictionary();\n const { setFocusedContentKeyPath: setMergedKeyPath } =\n useFocusDictionaryActions();\n\n const focusedUnmergedKeyPath = useMemo(() => {\n if (!focusedContent?.keyPath) return undefined;\n // The focusedContent.keyPath from FocusDictionaryContext is in merged format\n // We don't transform it here because we don't have the dictionary\n // The consumer should use setFocusedUnmergedKeyPath with a dictionary\n return focusedContent.keyPath;\n }, [focusedContent?.keyPath]);\n\n const setFocusedUnmergedKeyPath = (keyPath: KeyPath[]) => {\n // Transform unmerged keypath to merged keypath before setting it\n const mergedKeyPath = unmergedKeyPathToMergedKeyPath(keyPath);\n setMergedKeyPath(mergedKeyPath);\n };\n\n return (\n <FocusDictionaryUnmergedStateContext.Provider\n value={{ focusedContent, focusedUnmergedKeyPath }}\n >\n <FocusDictionaryUnmergedActionsContext.Provider\n value={{ setFocusedContent, setFocusedUnmergedKeyPath }}\n >\n {children}\n </FocusDictionaryUnmergedActionsContext.Provider>\n </FocusDictionaryUnmergedStateContext.Provider>\n );\n};\n\nexport const useFocusDictionaryUnmergedActions = () => {\n const context = useContext(FocusDictionaryUnmergedActionsContext);\n if (context === undefined) {\n throw new Error(\n 'useFocusDictionaryUnmergedActions must be used within a FocusDictionaryUnmergedProvider'\n );\n }\n return context;\n};\n\nexport const useFocusDictionaryUnmerged = () => {\n const actionContext = useFocusDictionaryUnmergedActions();\n const stateContext = useContext(FocusDictionaryUnmergedStateContext);\n\n if (stateContext === undefined) {\n throw new Error(\n 'useFocusDictionaryUnmerged must be used within a FocusDictionaryUnmergedProvider'\n );\n }\n\n return { ...stateContext, ...actionContext };\n};\n\n// Export the mapper functions for use elsewhere\nexport { unmergedKeyPathToMergedKeyPath, mergedKeyPathToUnmergedKeyPath };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA4BA,MAAM,kCAAkC,YAAkC;AACxE,KAAI,CAAC,WAAW,QAAQ,WAAW,EAAG,QAAO;CAE7C,MAAM,qBAAqB,QAAQ,MAChC,QAAQ,IAAI,SAASA,0BAAS,YAChC;AAGD,KAAI,CAAC,mBAAoB,QAAO;AAOhC,QAAO,CAAC,oBAAoB,GALN,QAAQ,QAC3B,QAAQ,IAAI,SAASA,0BAAS,YAChC,CAG4C;;;;;;;;;;AAW/C,MAAM,kCACJ,SACA,eACc;AACd,KAAI,CAAC,WAAW,QAAQ,WAAW,EAAG,QAAO;CAE7C,MAAM,qBAAqB,QAAQ,MAChC,QAAQ,IAAI,SAASA,0BAAS,YAChC;AAGD,KAAI,CAAC,mBAAoB,QAAO;CAEhC,MAAM,gBAAgB,QAAQ,QAC3B,QAAQ,IAAI,SAASA,0BAAS,YAChC;AAGD,KAAI,YAAY,QAGd,MAAK,IAAI,IAAI,cAAc,QAAQ,KAAK,GAAG,KAAK;EAC9C,MAAM,mBAAmB;GACvB,GAAG,cAAc,MAAM,GAAG,EAAE;GAC5B;GACA,GAAG,cAAc,MAAM,EAAE;GAC1B;AAED,MAAI;AAKF,oDAHE,WAAW,SACX,iBACD,CAEC,QAAO;UAEH;;AAOZ,QAAO,CAAC,GAAG,eAAe,mBAAmB;;AAa/C,MAAM,+DAEJ,OAAU;AAEZ,MAAM,iEAEJ,OAAU;AAEZ,MAAaC,mCAA0D,EACrE,eACI;CACJ,MAAM,EAAE,gBAAgB,sBAAsBC,mDAAoB;CAClE,MAAM,EAAE,0BAA0B,qBAChCC,0DAA2B;CAE7B,MAAM,kDAAuC;AAC3C,MAAI,CAAC,gBAAgB,QAAS,QAAO;AAIrC,SAAO,eAAe;IACrB,CAAC,gBAAgB,QAAQ,CAAC;CAE7B,MAAM,6BAA6B,YAAuB;AAGxD,mBADsB,+BAA+B,QAAQ,CAC9B;;AAGjC,QACE,2CAAC,oCAAoC;EACnC,OAAO;GAAE;GAAgB;GAAwB;YAEjD,2CAAC,sCAAsC;GACrC,OAAO;IAAE;IAAmB;IAA2B;GAEtD;IAC8C;GACJ;;AAInD,MAAa,0CAA0C;CACrD,MAAM,gCAAqB,sCAAsC;AACjE,KAAI,YAAY,OACd,OAAM,IAAI,MACR,0FACD;AAEH,QAAO;;AAGT,MAAa,mCAAmC;CAC9C,MAAM,gBAAgB,mCAAmC;CACzD,MAAM,qCAA0B,oCAAoC;AAEpE,KAAI,iBAAiB,OACnB,OAAM,IAAI,MACR,mFACD;AAGH,QAAO;EAAE,GAAG;EAAc,GAAG;EAAe"}
@@ -3,11 +3,13 @@ const require_useCrossFrameMessageListener = require('./useCrossFrameMessageList
3
3
  const require_useCrossFrameState = require('./useCrossFrameState.cjs');
4
4
  const require_ConfigurationContext = require('./ConfigurationContext.cjs');
5
5
  const require_DictionariesRecordContext = require('./DictionariesRecordContext.cjs');
6
+ const require_useEditorLocale = require('./useEditorLocale.cjs');
6
7
  const require_EditedContentContext = require('./EditedContentContext.cjs');
7
8
  const require_EditorEnabledContext = require('./EditorEnabledContext.cjs');
8
9
  const require_FocusDictionaryContext = require('./FocusDictionaryContext.cjs');
9
10
  const require_EditorProvider = require('./EditorProvider.cjs');
10
11
  const require_useCrossURLPathState = require('./useCrossURLPathState.cjs');
12
+ const require_useFocusUnmergedDictionary = require('./useFocusUnmergedDictionary.cjs');
11
13
  const require_useIframeClickInterceptor = require('./useIframeClickInterceptor.cjs');
12
14
 
13
15
  exports.CommunicatorProvider = require_CommunicatorContext.CommunicatorProvider;
@@ -30,14 +32,17 @@ exports.useEditedContent = require_EditedContentContext.useEditedContent;
30
32
  exports.useEditedContentActions = require_EditedContentContext.useEditedContentActions;
31
33
  exports.useEditorEnabled = require_EditorEnabledContext.useEditorEnabled;
32
34
  exports.useEditorEnabledState = require_EditorEnabledContext.useEditorEnabledState;
35
+ exports.useEditorLocale = require_useEditorLocale.useEditorLocale;
33
36
  exports.useFocusDictionary = require_FocusDictionaryContext.useFocusDictionary;
34
37
  exports.useFocusDictionaryActions = require_FocusDictionaryContext.useFocusDictionaryActions;
38
+ exports.useFocusUnmergedDictionary = require_useFocusUnmergedDictionary.useFocusUnmergedDictionary;
35
39
  exports.useGetEditedContentState = require_EditedContentContext.useGetEditedContentState;
36
40
  exports.useGetEditorEnabledState = require_EditorEnabledContext.useGetEditorEnabledState;
37
41
  exports.useIframeClickInterceptor = require_useIframeClickInterceptor.useIframeClickInterceptor;
38
42
  exports.useIframeClickMerger = require_useIframeClickInterceptor.useIframeClickMerger;
39
43
  exports.usePostEditedContentState = require_EditedContentContext.usePostEditedContentState;
40
44
  exports.usePostEditorEnabledState = require_EditorEnabledContext.usePostEditorEnabledState;
45
+ exports.useSetEditorLocale = require_useEditorLocale.useSetEditorLocale;
41
46
  var __intlayer_editor = require("@intlayer/editor");
42
47
  Object.keys(__intlayer_editor).forEach(function (k) {
43
48
  if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
@@ -41,7 +41,12 @@ const useCrossFrameMessageListener = (key, onEventTriggered, revalidator) => {
41
41
  const { type, data, senderId: msgSenderId } = event.data;
42
42
  if (type !== key) return;
43
43
  if (msgSenderId === senderId) return;
44
- if (typeof allowedOrigins === "undefined" || allowedOrigins?.some((url) => (0, __intlayer_editor.compareUrls)(url, event.origin)) || allowedOrigins?.includes("*")) onEventTriggered(data);
44
+ if (typeof allowedOrigins === "undefined" || allowedOrigins?.filter((url) => ![
45
+ null,
46
+ void 0,
47
+ "",
48
+ "*"
49
+ ].includes(url)).some((url) => (0, __intlayer_editor.compareUrls)(url, event.origin)) || allowedOrigins?.includes("*")) onEventTriggered(data);
45
50
  };
46
51
  window.addEventListener("message", handleMessage);
47
52
  return () => window.removeEventListener("message", handleMessage);
@@ -1 +1 @@
1
- {"version":3,"file":"useCrossFrameMessageListener.cjs","names":["useCommunicator","postMessageWrapper: (data?: S) => void"],"sources":["../../src/useCrossFrameMessageListener.tsx"],"sourcesContent":["'use client';\n\nimport { compareUrls, type MessageKey } from '@intlayer/editor';\nimport { useEffect } from 'react';\nimport { useCommunicator } from './CommunicatorContext';\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 key - A unique identifier for the message type to listen for.\n * @param [onEventTriggered] - A callback function triggered when a message\n * @param [revalidator] - A function that re-suscribes the listener. Could be usefull if onEventTriggered depend of some state\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 revalidator?: any\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, revalidator]);\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 = (data) => {\n postMessage({ type: key, data, senderId });\n };\n\n return postMessageWrapper;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBA,MAAa,gCACX,KACA,kBACA,gBACG;CACH,MAAM,EAAE,gBAAgB,aAAa,aAAaA,6CAAiB;AAEnE,4BAAgB;AACd,MAAI,kBAAkB;;;;;;;;;GASpB,MAAM,iBACJ,UACG;IACH,MAAM,EAAE,MAAM,MAAM,UAAU,gBAAgB,MAAM;AAGpD,QAAI,SAAS,IAAK;AAGlB,QAAI,gBAAgB,SAAU;AAG9B,QACE,OAAO,mBAAmB,eAC1B,gBAAgB,MAAM,2CAAoB,KAAK,MAAM,OAAO,CAAC,IAC7D,gBAAgB,SAAS,IAAI,CAG7B,kBAAiB,KAAK;;AAI1B,UAAO,iBAAiB,WAAW,cAAc;AAGjD,gBAAa,OAAO,oBAAoB,WAAW,cAAc;;IAElE;EAAC;EAAgB;EAAa;EAAU;EAAY,CAAC;;;;;;;;;;CAWxD,MAAMC,sBAA0C,SAAS;AACvD,cAAY;GAAE,MAAM;GAAK;GAAM;GAAU,CAAC;;AAG5C,QAAO"}
1
+ {"version":3,"file":"useCrossFrameMessageListener.cjs","names":["useCommunicator","postMessageWrapper: (data?: S) => void"],"sources":["../../src/useCrossFrameMessageListener.tsx"],"sourcesContent":["'use client';\n\nimport { compareUrls, type MessageKey } from '@intlayer/editor';\nimport { useEffect } from 'react';\nimport { useCommunicator } from './CommunicatorContext';\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 key - A unique identifier for the message type to listen for.\n * @param [onEventTriggered] - A callback function triggered when a message\n * @param [revalidator] - A function that re-suscribes the listener. Could be usefull if onEventTriggered depend of some state\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 revalidator?: any\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\n ?.filter((url) => ![null, undefined, '', '*'].includes(url))\n .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, revalidator]);\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 = (data) => {\n postMessage({ type: key, data, senderId });\n };\n\n return postMessageWrapper;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBA,MAAa,gCACX,KACA,kBACA,gBACG;CACH,MAAM,EAAE,gBAAgB,aAAa,aAAaA,6CAAiB;AAEnE,4BAAgB;AACd,MAAI,kBAAkB;;;;;;;;;GASpB,MAAM,iBACJ,UACG;IACH,MAAM,EAAE,MAAM,MAAM,UAAU,gBAAgB,MAAM;AAGpD,QAAI,SAAS,IAAK;AAGlB,QAAI,gBAAgB,SAAU;AAG9B,QACE,OAAO,mBAAmB,eAC1B,gBACI,QAAQ,QAAQ,CAAC;KAAC;KAAM;KAAW;KAAI;KAAI,CAAC,SAAS,IAAI,CAAC,CAC3D,MAAM,2CAAoB,KAAK,MAAM,OAAO,CAAC,IAChD,gBAAgB,SAAS,IAAI,CAG7B,kBAAiB,KAAK;;AAI1B,UAAO,iBAAiB,WAAW,cAAc;AAGjD,gBAAa,OAAO,oBAAoB,WAAW,cAAc;;IAElE;EAAC;EAAgB;EAAa;EAAU;EAAY,CAAC;;;;;;;;;;CAWxD,MAAMC,sBAA0C,SAAS;AACvD,cAAY;GAAE,MAAM;GAAK;GAAM;GAAU,CAAC;;AAG5C,QAAO"}
@@ -0,0 +1,24 @@
1
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
+ const require_useCrossFrameState = require('./useCrossFrameState.cjs');
3
+ let __intlayer_editor = require("@intlayer/editor");
4
+ __intlayer_editor = require_rolldown_runtime.__toESM(__intlayer_editor);
5
+
6
+ //#region src/useEditorLocale.tsx
7
+ const useEditorLocale = () => {
8
+ const [currentLocale] = require_useCrossFrameState.useCrossFrameState(__intlayer_editor.MessageKey.INTLAYER_CURRENT_LOCALE, void 0, {
9
+ receive: true,
10
+ emit: false
11
+ });
12
+ return currentLocale;
13
+ };
14
+ const useSetEditorLocale = () => {
15
+ return require_useCrossFrameState.useCrossFrameState(__intlayer_editor.MessageKey.INTLAYER_CURRENT_LOCALE, void 0, {
16
+ receive: true,
17
+ emit: false
18
+ });
19
+ };
20
+
21
+ //#endregion
22
+ exports.useEditorLocale = useEditorLocale;
23
+ exports.useSetEditorLocale = useSetEditorLocale;
24
+ //# sourceMappingURL=useEditorLocale.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useEditorLocale.cjs","names":["useCrossFrameState","MessageKey"],"sources":["../../src/useEditorLocale.tsx"],"sourcesContent":["import { MessageKey } from '@intlayer/editor';\nimport type { Locale } from '@intlayer/types';\nimport { useCrossFrameState } from './useCrossFrameState';\n\nexport const useEditorLocale = () => {\n const [currentLocale] = useCrossFrameState<Locale>(\n MessageKey.INTLAYER_CURRENT_LOCALE,\n undefined,\n {\n receive: true,\n emit: false,\n }\n );\n\n return currentLocale;\n};\n\nexport const useSetEditorLocale = () => {\n const setCurrentLocale = useCrossFrameState<Locale>(\n MessageKey.INTLAYER_CURRENT_LOCALE,\n undefined,\n {\n receive: true,\n emit: false,\n }\n );\n\n return setCurrentLocale;\n};\n"],"mappings":";;;;;;AAIA,MAAa,wBAAwB;CACnC,MAAM,CAAC,iBAAiBA,8CACtBC,6BAAW,yBACX,QACA;EACE,SAAS;EACT,MAAM;EACP,CACF;AAED,QAAO;;AAGT,MAAa,2BAA2B;AAUtC,QATyBD,8CACvBC,6BAAW,yBACX,QACA;EACE,SAAS;EACT,MAAM;EACP,CACF"}
@@ -0,0 +1,64 @@
1
+ 'use client';
2
+
3
+
4
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
5
+ const require_DictionariesRecordContext = require('./DictionariesRecordContext.cjs');
6
+ const require_useEditorLocale = require('./useEditorLocale.cjs');
7
+ const require_FocusDictionaryContext = require('./FocusDictionaryContext.cjs');
8
+ let react = require("react");
9
+ react = require_rolldown_runtime.__toESM(react);
10
+ let __intlayer_core = require("@intlayer/core");
11
+ __intlayer_core = require_rolldown_runtime.__toESM(__intlayer_core);
12
+
13
+ //#region src/useFocusUnmergedDictionary.tsx
14
+ /**
15
+ * Converts merged keypath format to unmerged format.
16
+ * Merged: [{type: "translation", key: "fr"}, {type: "object", key: "title"}]
17
+ * Unmerged: [{type: "object", key: "title"}, {type: "translation", key: "fr"}]
18
+ */
19
+ const mergedKeyPathToUnmergedKeyPath = (keyPath, dictionaries, locale) => {
20
+ console.log("test2", {
21
+ keyPath,
22
+ dictionaries,
23
+ locale
24
+ });
25
+ for (const dictionary of dictionaries) {
26
+ console.log("test2", { dictionary });
27
+ try {
28
+ const result = (0, __intlayer_core.getContentNodeByKeyPath)(dictionary.content, keyPath ?? [], locale);
29
+ console.log("test2", { result });
30
+ if (result) return {
31
+ keyPath,
32
+ dictionaryLocalId: dictionary.localId
33
+ };
34
+ } catch {}
35
+ }
36
+ };
37
+ const useFocusUnmergedDictionary = () => {
38
+ const { localeDictionaries } = require_DictionariesRecordContext.useDictionariesRecord();
39
+ const currentLocale = require_useEditorLocale.useEditorLocale();
40
+ const { setFocusedContent, setFocusedContentKeyPath, focusedContent: mergedFocusedContent } = require_FocusDictionaryContext.useFocusDictionary();
41
+ return {
42
+ focusedContent: (0, react.useMemo)(() => {
43
+ if (!mergedFocusedContent) return mergedFocusedContent;
44
+ if (!localeDictionaries) return mergedFocusedContent;
45
+ if (mergedFocusedContent.dictionaryLocalId) return mergedFocusedContent;
46
+ const dictionaries = Object.values(localeDictionaries).filter((dictionary) => dictionary.key === mergedFocusedContent.dictionaryKey);
47
+ const unmergedKeyPath = mergedKeyPathToUnmergedKeyPath(mergedFocusedContent.keyPath ?? [], dictionaries, currentLocale);
48
+ return {
49
+ ...mergedFocusedContent,
50
+ ...unmergedKeyPath
51
+ };
52
+ }, [
53
+ mergedFocusedContent,
54
+ localeDictionaries,
55
+ currentLocale
56
+ ]),
57
+ setFocusedContent,
58
+ setFocusedContentKeyPath
59
+ };
60
+ };
61
+
62
+ //#endregion
63
+ exports.useFocusUnmergedDictionary = useFocusUnmergedDictionary;
64
+ //# sourceMappingURL=useFocusUnmergedDictionary.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFocusUnmergedDictionary.cjs","names":["useDictionariesRecord","useEditorLocale","useFocusDictionary"],"sources":["../../src/useFocusUnmergedDictionary.tsx"],"sourcesContent":["'use client';\n\nimport { getContentNodeByKeyPath } from '@intlayer/core';\nimport type {\n Dictionary,\n KeyPath,\n LocalDictionaryId,\n Locale,\n} from '@intlayer/types';\nimport { useMemo } from 'react';\nimport { useDictionariesRecord } from './DictionariesRecordContext';\nimport { type FileContent, useFocusDictionary } from './FocusDictionaryContext';\nimport { useEditorLocale } from './useEditorLocale';\n\ntype UnmergedKeyPath = {\n keyPath: KeyPath[];\n dictionaryLocalId?: LocalDictionaryId;\n};\n\n/**\n * Converts merged keypath format to unmerged format.\n * Merged: [{type: \"translation\", key: \"fr\"}, {type: \"object\", key: \"title\"}]\n * Unmerged: [{type: \"object\", key: \"title\"}, {type: \"translation\", key: \"fr\"}]\n */\nconst mergedKeyPathToUnmergedKeyPath = (\n keyPath: KeyPath[],\n dictionaries: Dictionary[],\n locale: Locale\n): UnmergedKeyPath | undefined => {\n console.log('test2', { keyPath, dictionaries, locale });\n\n // If we have a dictionary, verify the path exists\n // Try to find the correct position for the translation key\n // by checking which path actually exists in the dictionary\n for (const dictionary of dictionaries) {\n console.log('test2', { dictionary });\n try {\n const result = getContentNodeByKeyPath(\n dictionary.content,\n keyPath ?? [],\n locale\n );\n\n console.log('test2', { result });\n\n if (result) {\n return { keyPath, dictionaryLocalId: dictionary.localId };\n }\n } catch {\n // Continue to next candidate\n }\n }\n};\n\nexport const useFocusUnmergedDictionary = () => {\n const { localeDictionaries } = useDictionariesRecord();\n const currentLocale = useEditorLocale();\n const {\n setFocusedContent,\n setFocusedContentKeyPath,\n focusedContent: mergedFocusedContent,\n } = useFocusDictionary();\n\n const focusedContent = useMemo<FileContent | null>(() => {\n if (!mergedFocusedContent) return mergedFocusedContent;\n if (!localeDictionaries) return mergedFocusedContent;\n if (mergedFocusedContent.dictionaryLocalId) return mergedFocusedContent;\n\n const dictionaries = Object.values(localeDictionaries).filter(\n (dictionary) => dictionary.key === mergedFocusedContent.dictionaryKey\n );\n\n const unmergedKeyPath = mergedKeyPathToUnmergedKeyPath(\n mergedFocusedContent.keyPath ?? [],\n dictionaries,\n currentLocale\n );\n\n return {\n ...mergedFocusedContent,\n ...unmergedKeyPath,\n };\n }, [mergedFocusedContent, localeDictionaries, currentLocale]);\n\n return {\n focusedContent,\n setFocusedContent,\n setFocusedContentKeyPath,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAwBA,MAAM,kCACJ,SACA,cACA,WACgC;AAChC,SAAQ,IAAI,SAAS;EAAE;EAAS;EAAc;EAAQ,CAAC;AAKvD,MAAK,MAAM,cAAc,cAAc;AACrC,UAAQ,IAAI,SAAS,EAAE,YAAY,CAAC;AACpC,MAAI;GACF,MAAM,sDACJ,WAAW,SACX,WAAW,EAAE,EACb,OACD;AAED,WAAQ,IAAI,SAAS,EAAE,QAAQ,CAAC;AAEhC,OAAI,OACF,QAAO;IAAE;IAAS,mBAAmB,WAAW;IAAS;UAErD;;;AAMZ,MAAa,mCAAmC;CAC9C,MAAM,EAAE,uBAAuBA,yDAAuB;CACtD,MAAM,gBAAgBC,yCAAiB;CACvC,MAAM,EACJ,mBACA,0BACA,gBAAgB,yBACdC,mDAAoB;AAuBxB,QAAO;EACL,yCAtBuD;AACvD,OAAI,CAAC,qBAAsB,QAAO;AAClC,OAAI,CAAC,mBAAoB,QAAO;AAChC,OAAI,qBAAqB,kBAAmB,QAAO;GAEnD,MAAM,eAAe,OAAO,OAAO,mBAAmB,CAAC,QACpD,eAAe,WAAW,QAAQ,qBAAqB,cACzD;GAED,MAAM,kBAAkB,+BACtB,qBAAqB,WAAW,EAAE,EAClC,cACA,cACD;AAED,UAAO;IACL,GAAG;IACH,GAAG;IACJ;KACA;GAAC;GAAsB;GAAoB;GAAc,CAAC;EAI3D;EACA;EACD"}
@@ -4,10 +4,12 @@
4
4
  import { useCrossFrameMessageListener } from "./useCrossFrameMessageListener.mjs";
5
5
  import { useCrossFrameState } from "./useCrossFrameState.mjs";
6
6
  import { useDictionariesRecord } from "./DictionariesRecordContext.mjs";
7
+ import { useEditorLocale } from "./useEditorLocale.mjs";
7
8
  import { createContext, useContext } from "react";
8
9
  import { jsx } from "react/jsx-runtime";
9
10
  import { MessageKey } from "@intlayer/editor";
10
11
  import { editDictionaryByKeyPath, getContentNodeByKeyPath, renameContentNodeByKeyPath } from "@intlayer/core";
12
+ import { NodeType } from "@intlayer/types";
11
13
 
12
14
  //#region src/EditedContentContext.tsx
13
15
  const EditedContentStateContext = createContext(void 0);
@@ -17,6 +19,7 @@ const EditedContentActionsContext = createContext(void 0);
17
19
  const resolveState = (state, prevState) => typeof state === "function" ? state(prevState) : state;
18
20
  const EditedContentProvider = ({ children }) => {
19
21
  const { localeDictionaries } = useDictionariesRecord();
22
+ const currentLocale = useEditorLocale();
20
23
  const [editedContent, setEditedContentState] = useCrossFrameState(MessageKey.INTLAYER_EDITED_CONTENT_CHANGED);
21
24
  const setEditedDictionary = (newValue) => {
22
25
  let updatedDictionaries = resolveState(newValue);
@@ -120,10 +123,11 @@ const EditedContentProvider = ({ children }) => {
120
123
  };
121
124
  const getEditedContentValue = (localDictionaryIdOrKey, keyPath) => {
122
125
  if (!editedContent) return void 0;
123
- if (localDictionaryIdOrKey.includes(":local:") || localDictionaryIdOrKey.includes(":remote:")) return getContentNodeByKeyPath(editedContent?.[localDictionaryIdOrKey]?.content ?? {}, keyPath);
126
+ const filteredKeyPath = keyPath.filter((key) => key.type !== NodeType.Translation);
127
+ if (localDictionaryIdOrKey.includes(":local:") || localDictionaryIdOrKey.includes(":remote:")) return getContentNodeByKeyPath(editedContent?.[localDictionaryIdOrKey]?.content ?? {}, filteredKeyPath, currentLocale);
124
128
  const filteredDictionariesLocalId = Object.keys(editedContent).filter((key) => key.startsWith(`${localDictionaryIdOrKey}:`));
125
129
  for (const localDictionaryId of filteredDictionariesLocalId) {
126
- const contentNode = getContentNodeByKeyPath(editedContent?.[localDictionaryId]?.content ?? {}, keyPath);
130
+ const contentNode = getContentNodeByKeyPath(editedContent?.[localDictionaryId]?.content ?? {}, filteredKeyPath, currentLocale);
127
131
  if (contentNode) return contentNode;
128
132
  }
129
133
  };