@intlayer/editor-react 7.5.0-canary.1 → 7.5.0
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.
- package/dist/cjs/CommunicatorContext.cjs +3 -3
- package/dist/cjs/CommunicatorContext.cjs.map +1 -1
- package/dist/cjs/ConfigurationContext.cjs +2 -2
- package/dist/cjs/ConfigurationContext.cjs.map +1 -1
- package/dist/cjs/DictionariesRecordContext.cjs +2 -2
- package/dist/cjs/DictionariesRecordContext.cjs.map +1 -1
- package/dist/cjs/EditedContentContext.cjs +13 -13
- package/dist/cjs/EditedContentContext.cjs.map +1 -1
- package/dist/cjs/EditorEnabledContext.cjs +4 -4
- package/dist/cjs/EditorEnabledContext.cjs.map +1 -1
- package/dist/cjs/FocusDictionaryContext.cjs +4 -4
- package/dist/cjs/FocusDictionaryContext.cjs.map +1 -1
- package/dist/cjs/index.cjs +3 -3
- package/dist/cjs/useCrossFrameMessageListener.cjs +2 -2
- package/dist/cjs/useCrossFrameMessageListener.cjs.map +1 -1
- package/dist/cjs/useCrossURLPathState.cjs +2 -2
- package/dist/cjs/useCrossURLPathState.cjs.map +1 -1
- package/dist/cjs/useEditorLocale.cjs +3 -3
- package/dist/cjs/useEditorLocale.cjs.map +1 -1
- package/dist/cjs/useFocusUnmergedDictionary.cjs +2 -2
- package/dist/cjs/useFocusUnmergedDictionary.cjs.map +1 -1
- package/dist/cjs/useIframeClickInterceptor.cjs +3 -3
- package/dist/cjs/useIframeClickInterceptor.cjs.map +1 -1
- package/dist/types/ConfigurationContext.d.ts +2 -2
- package/dist/types/EditorEnabledContext.d.ts +2 -2
- package/dist/types/useCrossURLPathState.d.ts +3 -3
- package/dist/types/useEditorLocale.d.ts +2 -2
- package/dist/types/useFocusUnmergedDictionary.d.ts +2 -2
- package/package.json +8 -8
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
4
|
-
let
|
|
5
|
-
|
|
4
|
+
let _intlayer_config_built = require("@intlayer/config/built");
|
|
5
|
+
_intlayer_config_built = require_rolldown_runtime.__toESM(_intlayer_config_built);
|
|
6
6
|
let react = require("react");
|
|
7
7
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
8
|
|
|
9
9
|
//#region src/CommunicatorContext.tsx
|
|
10
10
|
const randomUUID = () => Math.random().toString(36).slice(2);
|
|
11
|
-
const { editor } =
|
|
11
|
+
const { editor } = _intlayer_config_built.default ?? {};
|
|
12
12
|
const CommunicatorContext = (0, react.createContext)({
|
|
13
13
|
postMessage: () => null,
|
|
14
14
|
allowedOrigins: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommunicatorContext.cjs","names":["configuration","CommunicatorProvider: FC<CommunicatorProviderProps>"],"sources":["../../src/CommunicatorContext.tsx"],"sourcesContent":["'use client';\n\nimport configuration from '@intlayer/config/built';\nimport {\n createContext,\n type FC,\n type PropsWithChildren,\n useContext,\n useMemo,\n useRef,\n} from 'react';\n\nconst randomUUID = () => Math.random().toString(36).slice(2);\n\nexport type UseCrossPlatformStateProps = {\n postMessage: typeof window.postMessage;\n allowedOrigins?: string[];\n senderId: string;\n};\n\nconst { editor } = configuration ?? {};\n\nconst CommunicatorContext = createContext<UseCrossPlatformStateProps>({\n postMessage: () => null,\n allowedOrigins: [\n editor?.applicationURL,\n editor?.editorURL,\n editor?.cmsURL,\n ] as string[],\n senderId: '',\n});\n\nexport type CommunicatorProviderProps = PropsWithChildren<\n Omit<UseCrossPlatformStateProps, 'senderId'>\n>;\n\nexport const CommunicatorProvider: FC<CommunicatorProviderProps> = ({\n children,\n allowedOrigins,\n postMessage,\n}) => {\n // Create a stable, unique ID for the lifetime of this app/iframe instance.\n const senderIdRef = useRef(randomUUID());\n\n const value = useMemo(\n () => ({ postMessage, allowedOrigins, senderId: senderIdRef.current }),\n [postMessage, allowedOrigins, senderIdRef.current]\n );\n\n return (\n <CommunicatorContext.Provider value={value}>\n {children}\n </CommunicatorContext.Provider>\n );\n};\n\nexport const useCommunicator = () => useContext(CommunicatorContext);\n"],"mappings":";;;;;;;;;AAYA,MAAM,mBAAmB,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,EAAE;AAQ5D,MAAM,EAAE,WAAWA,
|
|
1
|
+
{"version":3,"file":"CommunicatorContext.cjs","names":["configuration","CommunicatorProvider: FC<CommunicatorProviderProps>"],"sources":["../../src/CommunicatorContext.tsx"],"sourcesContent":["'use client';\n\nimport configuration from '@intlayer/config/built';\nimport {\n createContext,\n type FC,\n type PropsWithChildren,\n useContext,\n useMemo,\n useRef,\n} from 'react';\n\nconst randomUUID = () => Math.random().toString(36).slice(2);\n\nexport type UseCrossPlatformStateProps = {\n postMessage: typeof window.postMessage;\n allowedOrigins?: string[];\n senderId: string;\n};\n\nconst { editor } = configuration ?? {};\n\nconst CommunicatorContext = createContext<UseCrossPlatformStateProps>({\n postMessage: () => null,\n allowedOrigins: [\n editor?.applicationURL,\n editor?.editorURL,\n editor?.cmsURL,\n ] as string[],\n senderId: '',\n});\n\nexport type CommunicatorProviderProps = PropsWithChildren<\n Omit<UseCrossPlatformStateProps, 'senderId'>\n>;\n\nexport const CommunicatorProvider: FC<CommunicatorProviderProps> = ({\n children,\n allowedOrigins,\n postMessage,\n}) => {\n // Create a stable, unique ID for the lifetime of this app/iframe instance.\n const senderIdRef = useRef(randomUUID());\n\n const value = useMemo(\n () => ({ postMessage, allowedOrigins, senderId: senderIdRef.current }),\n [postMessage, allowedOrigins, senderIdRef.current]\n );\n\n return (\n <CommunicatorContext.Provider value={value}>\n {children}\n </CommunicatorContext.Provider>\n );\n};\n\nexport const useCommunicator = () => useContext(CommunicatorContext);\n"],"mappings":";;;;;;;;;AAYA,MAAM,mBAAmB,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,EAAE;AAQ5D,MAAM,EAAE,WAAWA,kCAAiB,EAAE;AAEtC,MAAM,+CAAgE;CACpE,mBAAmB;CACnB,gBAAgB;EACd,QAAQ;EACR,QAAQ;EACR,QAAQ;EACT;CACD,UAAU;CACX,CAAC;AAMF,MAAaC,wBAAuD,EAClE,UACA,gBACA,kBACI;CAEJ,MAAM,gCAAqB,YAAY,CAAC;CAExC,MAAM,kCACG;EAAE;EAAa;EAAgB,UAAU,YAAY;EAAS,GACrE;EAAC;EAAa;EAAgB,YAAY;EAAQ,CACnD;AAED,QACE,2CAAC,oBAAoB;EAAgB;EAClC;GAC4B;;AAInC,MAAa,8CAAmC,oBAAoB"}
|
|
@@ -4,11 +4,11 @@ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
|
4
4
|
const require_useCrossFrameState = require('./useCrossFrameState.cjs');
|
|
5
5
|
let react = require("react");
|
|
6
6
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
|
-
let
|
|
7
|
+
let _intlayer_editor = require("@intlayer/editor");
|
|
8
8
|
|
|
9
9
|
//#region src/ConfigurationContext.tsx
|
|
10
10
|
const ConfigurationStatesContext = (0, react.createContext)(void 0);
|
|
11
|
-
const useConfigurationState = () => require_useCrossFrameState.useCrossFrameState(
|
|
11
|
+
const useConfigurationState = () => require_useCrossFrameState.useCrossFrameState(_intlayer_editor.MessageKey.INTLAYER_CONFIGURATION, void 0, {
|
|
12
12
|
receive: false,
|
|
13
13
|
emit: true
|
|
14
14
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfigurationContext.cjs","names":["useCrossFrameState","MessageKey","ConfigurationProvider: FC<\n PropsWithChildren<ConfigurationProviderProps>\n>"],"sources":["../../src/ConfigurationContext.tsx"],"sourcesContent":["'use client';\n\nimport { MessageKey } from '@intlayer/editor';\nimport type { IntlayerConfig } from '@intlayer/types';\nimport {\n createContext,\n type FC,\n type PropsWithChildren,\n useContext,\n} from 'react';\nimport { useCrossFrameState } from './useCrossFrameState';\n\nconst ConfigurationStatesContext = createContext<IntlayerConfig | undefined>(\n undefined\n);\n\nexport const useConfigurationState = () =>\n useCrossFrameState<IntlayerConfig>(\n MessageKey.INTLAYER_CONFIGURATION,\n undefined,\n {\n receive: false,\n emit: true,\n }\n );\n\nexport type ConfigurationProviderProps = {\n configuration?: IntlayerConfig;\n};\n\nexport const ConfigurationProvider: FC<\n PropsWithChildren<ConfigurationProviderProps>\n> = ({ children, configuration }) => (\n <ConfigurationStatesContext.Provider value={configuration}>\n {children}\n </ConfigurationStatesContext.Provider>\n);\n\nexport const useConfiguration = () => useContext(ConfigurationStatesContext);\n"],"mappings":";;;;;;;;;AAYA,MAAM,sDACJ,OACD;AAED,MAAa,8BACXA,8CACEC,
|
|
1
|
+
{"version":3,"file":"ConfigurationContext.cjs","names":["useCrossFrameState","MessageKey","ConfigurationProvider: FC<\n PropsWithChildren<ConfigurationProviderProps>\n>"],"sources":["../../src/ConfigurationContext.tsx"],"sourcesContent":["'use client';\n\nimport { MessageKey } from '@intlayer/editor';\nimport type { IntlayerConfig } from '@intlayer/types';\nimport {\n createContext,\n type FC,\n type PropsWithChildren,\n useContext,\n} from 'react';\nimport { useCrossFrameState } from './useCrossFrameState';\n\nconst ConfigurationStatesContext = createContext<IntlayerConfig | undefined>(\n undefined\n);\n\nexport const useConfigurationState = () =>\n useCrossFrameState<IntlayerConfig>(\n MessageKey.INTLAYER_CONFIGURATION,\n undefined,\n {\n receive: false,\n emit: true,\n }\n );\n\nexport type ConfigurationProviderProps = {\n configuration?: IntlayerConfig;\n};\n\nexport const ConfigurationProvider: FC<\n PropsWithChildren<ConfigurationProviderProps>\n> = ({ children, configuration }) => (\n <ConfigurationStatesContext.Provider value={configuration}>\n {children}\n </ConfigurationStatesContext.Provider>\n);\n\nexport const useConfiguration = () => useContext(ConfigurationStatesContext);\n"],"mappings":";;;;;;;;;AAYA,MAAM,sDACJ,OACD;AAED,MAAa,8BACXA,8CACEC,4BAAW,wBACX,QACA;CACE,SAAS;CACT,MAAM;CACP,CACF;AAMH,MAAaC,yBAER,EAAE,UAAU,oBACf,2CAAC,2BAA2B;CAAS,OAAO;CACzC;EACmC;AAGxC,MAAa,+CAAoC,2BAA2B"}
|
|
@@ -4,13 +4,13 @@ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
|
4
4
|
const require_useCrossFrameState = require('./useCrossFrameState.cjs');
|
|
5
5
|
let react = require("react");
|
|
6
6
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
|
-
let
|
|
7
|
+
let _intlayer_editor = require("@intlayer/editor");
|
|
8
8
|
|
|
9
9
|
//#region src/DictionariesRecordContext.tsx
|
|
10
10
|
const DictionariesRecordStatesContext = (0, react.createContext)(void 0);
|
|
11
11
|
const DictionariesRecordActionsContext = (0, react.createContext)(void 0);
|
|
12
12
|
const DictionariesRecordProvider = ({ children }) => {
|
|
13
|
-
const [localeDictionaries, setLocaleDictionaries] = require_useCrossFrameState.useCrossFrameState(
|
|
13
|
+
const [localeDictionaries, setLocaleDictionaries] = require_useCrossFrameState.useCrossFrameState(_intlayer_editor.MessageKey.INTLAYER_LOCALE_DICTIONARIES_CHANGED, void 0);
|
|
14
14
|
const stateValue = (0, react.useMemo)(() => ({ localeDictionaries: localeDictionaries ?? {} }), [localeDictionaries]);
|
|
15
15
|
const actionValue = (0, react.useMemo)(() => ({
|
|
16
16
|
setLocaleDictionaries,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DictionariesRecordContext.cjs","names":["DictionariesRecordProvider: FC<PropsWithChildren>","useCrossFrameState","MessageKey"],"sources":["../../src/DictionariesRecordContext.tsx"],"sourcesContent":["'use client';\n\nimport { MessageKey } from '@intlayer/editor';\nimport type { Dictionary, LocalDictionaryId } 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 { useCrossFrameState } from './useCrossFrameState';\n\nexport type DictionaryContent = Record<LocalDictionaryId, Dictionary>;\n\ntype DictionariesRecordStatesContextType = {\n localeDictionaries: DictionaryContent;\n};\ntype DictionariesRecordActionsContextType = {\n setLocaleDictionaries: Dispatch<SetStateAction<DictionaryContent>>;\n setLocaleDictionary: (dictionary: Dictionary) => void;\n};\n\nconst DictionariesRecordStatesContext = createContext<\n DictionariesRecordStatesContextType | undefined\n>(undefined);\nconst DictionariesRecordActionsContext = createContext<\n DictionariesRecordActionsContextType | undefined\n>(undefined);\n\nexport const DictionariesRecordProvider: FC<PropsWithChildren> = ({\n children,\n}) => {\n const [localeDictionaries, setLocaleDictionaries] =\n useCrossFrameState<DictionaryContent>(\n MessageKey.INTLAYER_LOCALE_DICTIONARIES_CHANGED,\n undefined\n );\n\n const stateValue = useMemo(\n () => ({\n localeDictionaries: localeDictionaries ?? {},\n }),\n [localeDictionaries]\n );\n\n const actionValue = useMemo(\n () => ({\n setLocaleDictionaries,\n setLocaleDictionary: (dictionary: Dictionary) => {\n if (!dictionary.localId) return;\n\n setLocaleDictionaries((dictionaries) => ({\n ...dictionaries,\n [dictionary.localId as LocalDictionaryId]: dictionary,\n }));\n },\n }),\n [setLocaleDictionaries]\n );\n\n return (\n <DictionariesRecordStatesContext.Provider value={stateValue}>\n <DictionariesRecordActionsContext.Provider value={actionValue}>\n {children}\n </DictionariesRecordActionsContext.Provider>\n </DictionariesRecordStatesContext.Provider>\n );\n};\n\nexport const useDictionariesRecordActions = () =>\n useContext(DictionariesRecordActionsContext);\n\nexport const useDictionariesRecord = () => {\n const actionsContext = useDictionariesRecordActions();\n const statesContext = useContext(DictionariesRecordStatesContext);\n\n if (!statesContext) {\n throw new Error(\n 'useDictionariesRecordStates must be used within a DictionariesRecordProvider'\n );\n }\n\n return { ...statesContext, ...actionsContext };\n};\n"],"mappings":";;;;;;;;;AAyBA,MAAM,2DAEJ,OAAU;AACZ,MAAM,4DAEJ,OAAU;AAEZ,MAAaA,8BAAqD,EAChE,eACI;CACJ,MAAM,CAAC,oBAAoB,yBACzBC,8CACEC,
|
|
1
|
+
{"version":3,"file":"DictionariesRecordContext.cjs","names":["DictionariesRecordProvider: FC<PropsWithChildren>","useCrossFrameState","MessageKey"],"sources":["../../src/DictionariesRecordContext.tsx"],"sourcesContent":["'use client';\n\nimport { MessageKey } from '@intlayer/editor';\nimport type { Dictionary, LocalDictionaryId } 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 { useCrossFrameState } from './useCrossFrameState';\n\nexport type DictionaryContent = Record<LocalDictionaryId, Dictionary>;\n\ntype DictionariesRecordStatesContextType = {\n localeDictionaries: DictionaryContent;\n};\ntype DictionariesRecordActionsContextType = {\n setLocaleDictionaries: Dispatch<SetStateAction<DictionaryContent>>;\n setLocaleDictionary: (dictionary: Dictionary) => void;\n};\n\nconst DictionariesRecordStatesContext = createContext<\n DictionariesRecordStatesContextType | undefined\n>(undefined);\nconst DictionariesRecordActionsContext = createContext<\n DictionariesRecordActionsContextType | undefined\n>(undefined);\n\nexport const DictionariesRecordProvider: FC<PropsWithChildren> = ({\n children,\n}) => {\n const [localeDictionaries, setLocaleDictionaries] =\n useCrossFrameState<DictionaryContent>(\n MessageKey.INTLAYER_LOCALE_DICTIONARIES_CHANGED,\n undefined\n );\n\n const stateValue = useMemo(\n () => ({\n localeDictionaries: localeDictionaries ?? {},\n }),\n [localeDictionaries]\n );\n\n const actionValue = useMemo(\n () => ({\n setLocaleDictionaries,\n setLocaleDictionary: (dictionary: Dictionary) => {\n if (!dictionary.localId) return;\n\n setLocaleDictionaries((dictionaries) => ({\n ...dictionaries,\n [dictionary.localId as LocalDictionaryId]: dictionary,\n }));\n },\n }),\n [setLocaleDictionaries]\n );\n\n return (\n <DictionariesRecordStatesContext.Provider value={stateValue}>\n <DictionariesRecordActionsContext.Provider value={actionValue}>\n {children}\n </DictionariesRecordActionsContext.Provider>\n </DictionariesRecordStatesContext.Provider>\n );\n};\n\nexport const useDictionariesRecordActions = () =>\n useContext(DictionariesRecordActionsContext);\n\nexport const useDictionariesRecord = () => {\n const actionsContext = useDictionariesRecordActions();\n const statesContext = useContext(DictionariesRecordStatesContext);\n\n if (!statesContext) {\n throw new Error(\n 'useDictionariesRecordStates must be used within a DictionariesRecordProvider'\n );\n }\n\n return { ...statesContext, ...actionsContext };\n};\n"],"mappings":";;;;;;;;;AAyBA,MAAM,2DAEJ,OAAU;AACZ,MAAM,4DAEJ,OAAU;AAEZ,MAAaA,8BAAqD,EAChE,eACI;CACJ,MAAM,CAAC,oBAAoB,yBACzBC,8CACEC,4BAAW,sCACX,OACD;CAEH,MAAM,uCACG,EACL,oBAAoB,sBAAsB,EAAE,EAC7C,GACD,CAAC,mBAAmB,CACrB;CAED,MAAM,wCACG;EACL;EACA,sBAAsB,eAA2B;AAC/C,OAAI,CAAC,WAAW,QAAS;AAEzB,0BAAuB,kBAAkB;IACvC,GAAG;KACF,WAAW,UAA+B;IAC5C,EAAE;;EAEN,GACD,CAAC,sBAAsB,CACxB;AAED,QACE,2CAAC,gCAAgC;EAAS,OAAO;YAC/C,2CAAC,iCAAiC;GAAS,OAAO;GAC/C;IACyC;GACH;;AAI/C,MAAa,2DACA,iCAAiC;AAE9C,MAAa,8BAA8B;CACzC,MAAM,iBAAiB,8BAA8B;CACrD,MAAM,sCAA2B,gCAAgC;AAEjE,KAAI,CAAC,cACH,OAAM,IAAI,MACR,+EACD;AAGH,QAAO;EAAE,GAAG;EAAe,GAAG;EAAgB"}
|
|
@@ -7,20 +7,20 @@ const require_DictionariesRecordContext = require('./DictionariesRecordContext.c
|
|
|
7
7
|
const require_useEditorLocale = require('./useEditorLocale.cjs');
|
|
8
8
|
let react = require("react");
|
|
9
9
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
10
|
-
let
|
|
11
|
-
let
|
|
12
|
-
let
|
|
10
|
+
let _intlayer_editor = require("@intlayer/editor");
|
|
11
|
+
let _intlayer_core = require("@intlayer/core");
|
|
12
|
+
let _intlayer_types = require("@intlayer/types");
|
|
13
13
|
|
|
14
14
|
//#region src/EditedContentContext.tsx
|
|
15
15
|
const EditedContentStateContext = (0, react.createContext)(void 0);
|
|
16
|
-
const usePostEditedContentState = (onEventTriggered) => require_useCrossFrameMessageListener.useCrossFrameMessageListener(`${
|
|
17
|
-
const useGetEditedContentState = (onEventTriggered) => require_useCrossFrameMessageListener.useCrossFrameMessageListener(`${
|
|
16
|
+
const usePostEditedContentState = (onEventTriggered) => require_useCrossFrameMessageListener.useCrossFrameMessageListener(`${_intlayer_editor.MessageKey.INTLAYER_EDITED_CONTENT_CHANGED}/post`, onEventTriggered);
|
|
17
|
+
const useGetEditedContentState = (onEventTriggered) => require_useCrossFrameMessageListener.useCrossFrameMessageListener(`${_intlayer_editor.MessageKey.INTLAYER_EDITED_CONTENT_CHANGED}/get`, onEventTriggered);
|
|
18
18
|
const EditedContentActionsContext = (0, react.createContext)(void 0);
|
|
19
19
|
const resolveState = (state, prevState) => typeof state === "function" ? state(prevState) : state;
|
|
20
20
|
const EditedContentProvider = ({ children }) => {
|
|
21
21
|
const { localeDictionaries } = require_DictionariesRecordContext.useDictionariesRecord();
|
|
22
22
|
const currentLocale = require_useEditorLocale.useEditorLocale();
|
|
23
|
-
const [editedContent, setEditedContentState] = require_useCrossFrameState.useCrossFrameState(
|
|
23
|
+
const [editedContent, setEditedContentState] = require_useCrossFrameState.useCrossFrameState(_intlayer_editor.MessageKey.INTLAYER_EDITED_CONTENT_CHANGED);
|
|
24
24
|
const setEditedDictionary = (newValue) => {
|
|
25
25
|
let updatedDictionaries = resolveState(newValue);
|
|
26
26
|
setEditedContentState((prev) => {
|
|
@@ -55,7 +55,7 @@ const EditedContentProvider = ({ children }) => {
|
|
|
55
55
|
const otherKeyPath = keyPath.slice(0, -1);
|
|
56
56
|
const lastKeyPath = keyPath[keyPath.length - 1];
|
|
57
57
|
let finalKey = lastKeyPath.key;
|
|
58
|
-
while (typeof (0,
|
|
58
|
+
while (typeof (0, _intlayer_core.getContentNodeByKeyPath)(currentContent, newKeyPath) !== "undefined") {
|
|
59
59
|
index++;
|
|
60
60
|
finalKey = index === 0 ? lastKeyPath.key : `${lastKeyPath.key} (${index})`;
|
|
61
61
|
newKeyPath = [...otherKeyPath, {
|
|
@@ -64,7 +64,7 @@ const EditedContentProvider = ({ children }) => {
|
|
|
64
64
|
}];
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
|
-
const updatedContent = (0,
|
|
67
|
+
const updatedContent = (0, _intlayer_core.editDictionaryByKeyPath)(currentContent, newKeyPath, newValue);
|
|
68
68
|
return {
|
|
69
69
|
...prev,
|
|
70
70
|
[localDictionaryId]: {
|
|
@@ -77,7 +77,7 @@ const EditedContentProvider = ({ children }) => {
|
|
|
77
77
|
const renameEditedContent = (localDictionaryId, newKey, keyPath = []) => {
|
|
78
78
|
setEditedContentState((prev) => {
|
|
79
79
|
const originalContent = localeDictionaries[localDictionaryId]?.content;
|
|
80
|
-
const contentWithNewField = (0,
|
|
80
|
+
const contentWithNewField = (0, _intlayer_core.renameContentNodeByKeyPath)(structuredClone(prev?.[localDictionaryId]?.content ?? originalContent), newKey, keyPath);
|
|
81
81
|
return {
|
|
82
82
|
...prev,
|
|
83
83
|
[localDictionaryId]: {
|
|
@@ -90,7 +90,7 @@ const EditedContentProvider = ({ children }) => {
|
|
|
90
90
|
const removeEditedContent = (localDictionaryId, keyPath) => {
|
|
91
91
|
setEditedContentState((prev) => {
|
|
92
92
|
const originalContent = localeDictionaries[localDictionaryId]?.content;
|
|
93
|
-
const restoredContent = (0,
|
|
93
|
+
const restoredContent = (0, _intlayer_core.editDictionaryByKeyPath)(structuredClone(prev?.[localDictionaryId]?.content ?? originalContent), keyPath, (0, _intlayer_core.getContentNodeByKeyPath)(originalContent, keyPath));
|
|
94
94
|
return {
|
|
95
95
|
...prev,
|
|
96
96
|
[localDictionaryId]: {
|
|
@@ -123,11 +123,11 @@ const EditedContentProvider = ({ children }) => {
|
|
|
123
123
|
};
|
|
124
124
|
const getEditedContentValue = (localDictionaryIdOrKey, keyPath) => {
|
|
125
125
|
if (!editedContent) return void 0;
|
|
126
|
-
const filteredKeyPath = keyPath.filter((key) => key.type !==
|
|
127
|
-
if (localDictionaryIdOrKey.includes(":local:") || localDictionaryIdOrKey.includes(":remote:")) return (0,
|
|
126
|
+
const filteredKeyPath = keyPath.filter((key) => key.type !== _intlayer_types.NodeType.Translation);
|
|
127
|
+
if (localDictionaryIdOrKey.includes(":local:") || localDictionaryIdOrKey.includes(":remote:")) return (0, _intlayer_core.getContentNodeByKeyPath)(editedContent?.[localDictionaryIdOrKey]?.content ?? {}, filteredKeyPath, currentLocale);
|
|
128
128
|
const filteredDictionariesLocalId = Object.keys(editedContent).filter((key) => key.startsWith(`${localDictionaryIdOrKey}:`));
|
|
129
129
|
for (const localDictionaryId of filteredDictionariesLocalId) {
|
|
130
|
-
const contentNode = (0,
|
|
130
|
+
const contentNode = (0, _intlayer_core.getContentNodeByKeyPath)(editedContent?.[localDictionaryId]?.content ?? {}, filteredKeyPath, currentLocale);
|
|
131
131
|
if (contentNode) return contentNode;
|
|
132
132
|
}
|
|
133
133
|
};
|
|
@@ -1 +1 @@
|
|
|
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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"}
|
|
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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"}
|
|
@@ -5,13 +5,13 @@ const require_useCrossFrameMessageListener = require('./useCrossFrameMessageList
|
|
|
5
5
|
const require_useCrossFrameState = require('./useCrossFrameState.cjs');
|
|
6
6
|
let react = require("react");
|
|
7
7
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
-
let
|
|
8
|
+
let _intlayer_editor = require("@intlayer/editor");
|
|
9
9
|
|
|
10
10
|
//#region src/EditorEnabledContext.tsx
|
|
11
11
|
const EditorEnabledContext = (0, react.createContext)({ enabled: false });
|
|
12
|
-
const useEditorEnabledState = (options) => require_useCrossFrameState.useCrossFrameState(
|
|
13
|
-
const usePostEditorEnabledState = (onEventTriggered) => require_useCrossFrameMessageListener.useCrossFrameMessageListener(`${
|
|
14
|
-
const useGetEditorEnabledState = (onEventTriggered) => require_useCrossFrameMessageListener.useCrossFrameMessageListener(`${
|
|
12
|
+
const useEditorEnabledState = (options) => require_useCrossFrameState.useCrossFrameState(_intlayer_editor.MessageKey.INTLAYER_EDITOR_ENABLED, false, options);
|
|
13
|
+
const usePostEditorEnabledState = (onEventTriggered) => require_useCrossFrameMessageListener.useCrossFrameMessageListener(`${_intlayer_editor.MessageKey.INTLAYER_EDITOR_ENABLED}/post`, onEventTriggered);
|
|
14
|
+
const useGetEditorEnabledState = (onEventTriggered) => require_useCrossFrameMessageListener.useCrossFrameMessageListener(`${_intlayer_editor.MessageKey.INTLAYER_EDITOR_ENABLED}/get`, onEventTriggered);
|
|
15
15
|
const EditorEnabledProvider = ({ children }) => {
|
|
16
16
|
const [isEnabled] = useEditorEnabledState({
|
|
17
17
|
emit: false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorEnabledContext.cjs","names":["useCrossFrameState","MessageKey","useCrossFrameMessageListener","EditorEnabledProvider: FC<PropsWithChildren>"],"sources":["../../src/EditorEnabledContext.tsx"],"sourcesContent":["'use client';\n\nimport { MessageKey } from '@intlayer/editor';\nimport {\n createContext,\n type FC,\n type PropsWithChildren,\n useContext,\n} from 'react';\nimport { useCrossFrameMessageListener } from './useCrossFrameMessageListener';\nimport {\n type CrossFrameStateOptions,\n useCrossFrameState,\n} from './useCrossFrameState';\n\nexport type EditorEnabledStateProps = {\n enabled: boolean;\n};\n\nconst EditorEnabledContext = createContext<EditorEnabledStateProps>({\n enabled: false,\n});\n\nexport const useEditorEnabledState = (options?: CrossFrameStateOptions) =>\n useCrossFrameState(MessageKey.INTLAYER_EDITOR_ENABLED, false, options);\n\nexport const usePostEditorEnabledState = <S,>(\n onEventTriggered?: (data: S) => void\n) =>\n useCrossFrameMessageListener(\n `${MessageKey.INTLAYER_EDITOR_ENABLED}/post`,\n onEventTriggered\n );\n\nexport const useGetEditorEnabledState = <S,>(\n onEventTriggered?: (data: S) => void\n) =>\n useCrossFrameMessageListener(\n `${MessageKey.INTLAYER_EDITOR_ENABLED}/get`,\n onEventTriggered\n );\n\nexport const EditorEnabledProvider: FC<PropsWithChildren> = ({ children }) => {\n const [isEnabled] = useEditorEnabledState({\n emit: false,\n receive: true,\n });\n\n return (\n <EditorEnabledContext.Provider value={{ enabled: isEnabled }}>\n {children}\n </EditorEnabledContext.Provider>\n );\n};\n\nexport const useEditorEnabled = () => useContext(EditorEnabledContext);\n"],"mappings":";;;;;;;;;;AAmBA,MAAM,gDAA8D,EAClE,SAAS,OACV,CAAC;AAEF,MAAa,yBAAyB,YACpCA,8CAAmBC,
|
|
1
|
+
{"version":3,"file":"EditorEnabledContext.cjs","names":["useCrossFrameState","MessageKey","useCrossFrameMessageListener","EditorEnabledProvider: FC<PropsWithChildren>"],"sources":["../../src/EditorEnabledContext.tsx"],"sourcesContent":["'use client';\n\nimport { MessageKey } from '@intlayer/editor';\nimport {\n createContext,\n type FC,\n type PropsWithChildren,\n useContext,\n} from 'react';\nimport { useCrossFrameMessageListener } from './useCrossFrameMessageListener';\nimport {\n type CrossFrameStateOptions,\n useCrossFrameState,\n} from './useCrossFrameState';\n\nexport type EditorEnabledStateProps = {\n enabled: boolean;\n};\n\nconst EditorEnabledContext = createContext<EditorEnabledStateProps>({\n enabled: false,\n});\n\nexport const useEditorEnabledState = (options?: CrossFrameStateOptions) =>\n useCrossFrameState(MessageKey.INTLAYER_EDITOR_ENABLED, false, options);\n\nexport const usePostEditorEnabledState = <S,>(\n onEventTriggered?: (data: S) => void\n) =>\n useCrossFrameMessageListener(\n `${MessageKey.INTLAYER_EDITOR_ENABLED}/post`,\n onEventTriggered\n );\n\nexport const useGetEditorEnabledState = <S,>(\n onEventTriggered?: (data: S) => void\n) =>\n useCrossFrameMessageListener(\n `${MessageKey.INTLAYER_EDITOR_ENABLED}/get`,\n onEventTriggered\n );\n\nexport const EditorEnabledProvider: FC<PropsWithChildren> = ({ children }) => {\n const [isEnabled] = useEditorEnabledState({\n emit: false,\n receive: true,\n });\n\n return (\n <EditorEnabledContext.Provider value={{ enabled: isEnabled }}>\n {children}\n </EditorEnabledContext.Provider>\n );\n};\n\nexport const useEditorEnabled = () => useContext(EditorEnabledContext);\n"],"mappings":";;;;;;;;;;AAmBA,MAAM,gDAA8D,EAClE,SAAS,OACV,CAAC;AAEF,MAAa,yBAAyB,YACpCA,8CAAmBC,4BAAW,yBAAyB,OAAO,QAAQ;AAExE,MAAa,6BACX,qBAEAC,kEACE,GAAGD,4BAAW,wBAAwB,QACtC,iBACD;AAEH,MAAa,4BACX,qBAEAC,kEACE,GAAGD,4BAAW,wBAAwB,OACtC,iBACD;AAEH,MAAaE,yBAAgD,EAAE,eAAe;CAC5E,MAAM,CAAC,aAAa,sBAAsB;EACxC,MAAM;EACN,SAAS;EACV,CAAC;AAEF,QACE,2CAAC,qBAAqB;EAAS,OAAO,EAAE,SAAS,WAAW;EACzD;GAC6B;;AAIpC,MAAa,+CAAoC,qBAAqB"}
|
|
@@ -4,18 +4,18 @@ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
|
4
4
|
const require_useCrossFrameState = require('./useCrossFrameState.cjs');
|
|
5
5
|
let react = require("react");
|
|
6
6
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
|
-
let
|
|
8
|
-
let
|
|
7
|
+
let _intlayer_editor = require("@intlayer/editor");
|
|
8
|
+
let _intlayer_types = require("@intlayer/types");
|
|
9
9
|
|
|
10
10
|
//#region src/FocusDictionaryContext.tsx
|
|
11
11
|
const FocusDictionaryStateContext = (0, react.createContext)(void 0);
|
|
12
12
|
const FocusDictionaryActionsContext = (0, react.createContext)(void 0);
|
|
13
13
|
const FocusDictionaryProvider = ({ children }) => {
|
|
14
|
-
const [focusedContent, setFocusedContent] = require_useCrossFrameState.useCrossFrameState(
|
|
14
|
+
const [focusedContent, setFocusedContent] = require_useCrossFrameState.useCrossFrameState(_intlayer_editor.MessageKey.INTLAYER_FOCUSED_CONTENT_CHANGED, null);
|
|
15
15
|
const setFocusedContentKeyPath = (keyPath) => {
|
|
16
16
|
setFocusedContent((prev) => {
|
|
17
17
|
if (!prev) return prev;
|
|
18
|
-
const filteredKeyPath = keyPath.filter((key) => key.type !==
|
|
18
|
+
const filteredKeyPath = keyPath.filter((key) => key.type !== _intlayer_types.NodeType.Translation);
|
|
19
19
|
return {
|
|
20
20
|
...prev,
|
|
21
21
|
keyPath: filteredKeyPath
|
|
@@ -1 +1 @@
|
|
|
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,
|
|
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,4BAAW,kCACX,KACD;CAEH,MAAM,4BAA4B,YAAuB;AACvD,qBAAmB,SAAS;AAC1B,OAAI,CAAC,KACH,QAAO;GAIT,MAAM,kBAAkB,QAAQ,QAC7B,QAAQ,IAAI,SAASC,yBAAS,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"}
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -43,10 +43,10 @@ exports.useIframeClickMerger = require_useIframeClickInterceptor.useIframeClickM
|
|
|
43
43
|
exports.usePostEditedContentState = require_EditedContentContext.usePostEditedContentState;
|
|
44
44
|
exports.usePostEditorEnabledState = require_EditorEnabledContext.usePostEditorEnabledState;
|
|
45
45
|
exports.useSetEditorLocale = require_useEditorLocale.useSetEditorLocale;
|
|
46
|
-
var
|
|
47
|
-
Object.keys(
|
|
46
|
+
var _intlayer_editor = require("@intlayer/editor");
|
|
47
|
+
Object.keys(_intlayer_editor).forEach(function (k) {
|
|
48
48
|
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
49
49
|
enumerable: true,
|
|
50
|
-
get: function () { return
|
|
50
|
+
get: function () { return _intlayer_editor[k]; }
|
|
51
51
|
});
|
|
52
52
|
});
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
4
4
|
const require_CommunicatorContext = require('./CommunicatorContext.cjs');
|
|
5
5
|
let react = require("react");
|
|
6
|
-
let
|
|
6
|
+
let _intlayer_editor = require("@intlayer/editor");
|
|
7
7
|
|
|
8
8
|
//#region src/useCrossFrameMessageListener.tsx
|
|
9
9
|
/**
|
|
@@ -43,7 +43,7 @@ const useCrossFrameMessageListener = (key, onEventTriggered, revalidator) => {
|
|
|
43
43
|
void 0,
|
|
44
44
|
"",
|
|
45
45
|
"*"
|
|
46
|
-
].includes(url)).some((url) => (0,
|
|
46
|
+
].includes(url)).some((url) => (0, _intlayer_editor.compareUrls)(url, event.origin)) || allowedOrigins?.includes("*")) onEventTriggered(data);
|
|
47
47
|
};
|
|
48
48
|
window.addEventListener("message", handleMessage);
|
|
49
49
|
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\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,
|
|
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,0CAAoB,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"}
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
4
4
|
const require_useCrossFrameState = require('./useCrossFrameState.cjs');
|
|
5
5
|
let react = require("react");
|
|
6
|
-
let
|
|
6
|
+
let _intlayer_editor = require("@intlayer/editor");
|
|
7
7
|
|
|
8
8
|
//#region src/useCrossURLPathState.tsx
|
|
9
|
-
const useCrossURLPathState = (initialState, options) => require_useCrossFrameState.useCrossFrameState(
|
|
9
|
+
const useCrossURLPathState = (initialState, options) => require_useCrossFrameState.useCrossFrameState(_intlayer_editor.MessageKey.INTLAYER_URL_CHANGE, initialState, options);
|
|
10
10
|
const useCrossURLPathSetter = (initialState) => {
|
|
11
11
|
const states = useCrossURLPathState(initialState, {
|
|
12
12
|
emit: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCrossURLPathState.cjs","names":["useCrossFrameState","MessageKey"],"sources":["../../src/useCrossURLPathState.tsx"],"sourcesContent":["'use client';\n\nimport { MessageKey } from '@intlayer/editor';\nimport { useEffect } from 'react';\nimport {\n type CrossFrameStateOptions,\n useCrossFrameState,\n} from './useCrossFrameState';\n\nexport const useCrossURLPathState = (\n initialState?: string,\n options?: CrossFrameStateOptions\n) => useCrossFrameState(MessageKey.INTLAYER_URL_CHANGE, initialState, options);\n\nexport const useCrossURLPathSetter = (initialState?: string) => {\n const states = useCrossURLPathState(initialState, {\n emit: true,\n receive: false,\n });\n const [_state, setState] = states;\n\n useEffect(() => {\n /**\n * 1) Monkey patch history methods (pushState, replaceState)\n * to dispatch a custom event whenever they are called.\n */\n const originalPushState = history.pushState;\n const originalReplaceState = history.replaceState;\n\n const injectLocationChangeEvent = (method: (...args: any[]) => void) =>\n function (this: typeof history, ...args: [any, string, string?]) {\n method.apply(this, args);\n window.dispatchEvent(new Event('locationchange'));\n };\n\n history.pushState = injectLocationChangeEvent(originalPushState);\n history.replaceState = injectLocationChangeEvent(originalReplaceState);\n\n /**\n * 2) The callback to update our state whenever the URL changes.\n */\n const updateURLState = () => {\n setState(window.location.pathname);\n };\n\n /**\n * 3) Attach event listeners for locationchange, popstate, hashchange.\n * - 'locationchange' is our custom event triggered by push/replaceState overrides.\n * - 'popstate' is fired on back/forward navigation.\n * - 'hashchange' is for URL hash (#) changes.\n * - 'load' is when new page is loaded\n */\n window.addEventListener('locationchange', updateURLState);\n window.addEventListener('popstate', updateURLState);\n window.addEventListener('hashchange', updateURLState);\n window.addEventListener('load', updateURLState);\n\n // Initialize our state immediately on mount\n updateURLState();\n\n /**\n * 4) Cleanup when the component unmounts:\n * - Remove event listeners.\n * - Restore original pushState & replaceState to avoid side effects.\n */\n return () => {\n window.removeEventListener('locationchange', updateURLState);\n window.removeEventListener('popstate', updateURLState);\n window.removeEventListener('hashchange', updateURLState);\n window.removeEventListener('load', updateURLState);\n history.pushState = originalPushState;\n history.replaceState = originalReplaceState;\n };\n }, []);\n\n return states;\n};\n"],"mappings":";;;;;;;;AASA,MAAa,wBACX,cACA,YACGA,8CAAmBC,
|
|
1
|
+
{"version":3,"file":"useCrossURLPathState.cjs","names":["useCrossFrameState","MessageKey"],"sources":["../../src/useCrossURLPathState.tsx"],"sourcesContent":["'use client';\n\nimport { MessageKey } from '@intlayer/editor';\nimport { useEffect } from 'react';\nimport {\n type CrossFrameStateOptions,\n useCrossFrameState,\n} from './useCrossFrameState';\n\nexport const useCrossURLPathState = (\n initialState?: string,\n options?: CrossFrameStateOptions\n) => useCrossFrameState(MessageKey.INTLAYER_URL_CHANGE, initialState, options);\n\nexport const useCrossURLPathSetter = (initialState?: string) => {\n const states = useCrossURLPathState(initialState, {\n emit: true,\n receive: false,\n });\n const [_state, setState] = states;\n\n useEffect(() => {\n /**\n * 1) Monkey patch history methods (pushState, replaceState)\n * to dispatch a custom event whenever they are called.\n */\n const originalPushState = history.pushState;\n const originalReplaceState = history.replaceState;\n\n const injectLocationChangeEvent = (method: (...args: any[]) => void) =>\n function (this: typeof history, ...args: [any, string, string?]) {\n method.apply(this, args);\n window.dispatchEvent(new Event('locationchange'));\n };\n\n history.pushState = injectLocationChangeEvent(originalPushState);\n history.replaceState = injectLocationChangeEvent(originalReplaceState);\n\n /**\n * 2) The callback to update our state whenever the URL changes.\n */\n const updateURLState = () => {\n setState(window.location.pathname);\n };\n\n /**\n * 3) Attach event listeners for locationchange, popstate, hashchange.\n * - 'locationchange' is our custom event triggered by push/replaceState overrides.\n * - 'popstate' is fired on back/forward navigation.\n * - 'hashchange' is for URL hash (#) changes.\n * - 'load' is when new page is loaded\n */\n window.addEventListener('locationchange', updateURLState);\n window.addEventListener('popstate', updateURLState);\n window.addEventListener('hashchange', updateURLState);\n window.addEventListener('load', updateURLState);\n\n // Initialize our state immediately on mount\n updateURLState();\n\n /**\n * 4) Cleanup when the component unmounts:\n * - Remove event listeners.\n * - Restore original pushState & replaceState to avoid side effects.\n */\n return () => {\n window.removeEventListener('locationchange', updateURLState);\n window.removeEventListener('popstate', updateURLState);\n window.removeEventListener('hashchange', updateURLState);\n window.removeEventListener('load', updateURLState);\n history.pushState = originalPushState;\n history.replaceState = originalReplaceState;\n };\n }, []);\n\n return states;\n};\n"],"mappings":";;;;;;;;AASA,MAAa,wBACX,cACA,YACGA,8CAAmBC,4BAAW,qBAAqB,cAAc,QAAQ;AAE9E,MAAa,yBAAyB,iBAA0B;CAC9D,MAAM,SAAS,qBAAqB,cAAc;EAChD,MAAM;EACN,SAAS;EACV,CAAC;CACF,MAAM,CAAC,QAAQ,YAAY;AAE3B,4BAAgB;;;;;EAKd,MAAM,oBAAoB,QAAQ;EAClC,MAAM,uBAAuB,QAAQ;EAErC,MAAM,6BAA6B,WACjC,SAAgC,GAAG,MAA8B;AAC/D,UAAO,MAAM,MAAM,KAAK;AACxB,UAAO,cAAc,IAAI,MAAM,iBAAiB,CAAC;;AAGrD,UAAQ,YAAY,0BAA0B,kBAAkB;AAChE,UAAQ,eAAe,0BAA0B,qBAAqB;;;;EAKtE,MAAM,uBAAuB;AAC3B,YAAS,OAAO,SAAS,SAAS;;;;;;;;;AAUpC,SAAO,iBAAiB,kBAAkB,eAAe;AACzD,SAAO,iBAAiB,YAAY,eAAe;AACnD,SAAO,iBAAiB,cAAc,eAAe;AACrD,SAAO,iBAAiB,QAAQ,eAAe;AAG/C,kBAAgB;;;;;;AAOhB,eAAa;AACX,UAAO,oBAAoB,kBAAkB,eAAe;AAC5D,UAAO,oBAAoB,YAAY,eAAe;AACtD,UAAO,oBAAoB,cAAc,eAAe;AACxD,UAAO,oBAAoB,QAAQ,eAAe;AAClD,WAAQ,YAAY;AACpB,WAAQ,eAAe;;IAExB,EAAE,CAAC;AAEN,QAAO"}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
2
2
|
const require_useCrossFrameState = require('./useCrossFrameState.cjs');
|
|
3
|
-
let
|
|
3
|
+
let _intlayer_editor = require("@intlayer/editor");
|
|
4
4
|
|
|
5
5
|
//#region src/useEditorLocale.tsx
|
|
6
6
|
const useEditorLocale = () => {
|
|
7
|
-
const [currentLocale] = require_useCrossFrameState.useCrossFrameState(
|
|
7
|
+
const [currentLocale] = require_useCrossFrameState.useCrossFrameState(_intlayer_editor.MessageKey.INTLAYER_CURRENT_LOCALE, void 0, {
|
|
8
8
|
receive: true,
|
|
9
9
|
emit: false
|
|
10
10
|
});
|
|
11
11
|
return currentLocale;
|
|
12
12
|
};
|
|
13
13
|
const useSetEditorLocale = () => {
|
|
14
|
-
return require_useCrossFrameState.useCrossFrameState(
|
|
14
|
+
return require_useCrossFrameState.useCrossFrameState(_intlayer_editor.MessageKey.INTLAYER_CURRENT_LOCALE, void 0, {
|
|
15
15
|
receive: true,
|
|
16
16
|
emit: false
|
|
17
17
|
});
|
|
@@ -1 +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,
|
|
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,4BAAW,yBACX,QACA;EACE,SAAS;EACT,MAAM;EACP,CACF;AAED,QAAO;;AAGT,MAAa,2BAA2B;AAUtC,QATyBD,8CACvBC,4BAAW,yBACX,QACA;EACE,SAAS;EACT,MAAM;EACP,CACF"}
|
|
@@ -5,7 +5,7 @@ const require_DictionariesRecordContext = require('./DictionariesRecordContext.c
|
|
|
5
5
|
const require_useEditorLocale = require('./useEditorLocale.cjs');
|
|
6
6
|
const require_FocusDictionaryContext = require('./FocusDictionaryContext.cjs');
|
|
7
7
|
let react = require("react");
|
|
8
|
-
let
|
|
8
|
+
let _intlayer_core = require("@intlayer/core");
|
|
9
9
|
|
|
10
10
|
//#region src/useFocusUnmergedDictionary.tsx
|
|
11
11
|
/**
|
|
@@ -15,7 +15,7 @@ let __intlayer_core = require("@intlayer/core");
|
|
|
15
15
|
*/
|
|
16
16
|
const mergedKeyPathToUnmergedKeyPath = (keyPath, dictionaries, locale) => {
|
|
17
17
|
for (const dictionary of dictionaries) try {
|
|
18
|
-
if ((0,
|
|
18
|
+
if ((0, _intlayer_core.getContentNodeByKeyPath)(dictionary.content, keyPath ?? [], locale)) return {
|
|
19
19
|
keyPath,
|
|
20
20
|
dictionaryLocalId: dictionary.localId
|
|
21
21
|
};
|
|
@@ -1 +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 // 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 try {\n const result = getContentNodeByKeyPath(\n dictionary.content,\n keyPath ?? [],\n locale\n );\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;AAIhC,MAAK,MAAM,cAAc,aACvB,KAAI;AAOF,
|
|
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 // 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 try {\n const result = getContentNodeByKeyPath(\n dictionary.content,\n keyPath ?? [],\n locale\n );\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;AAIhC,MAAK,MAAM,cAAc,aACvB,KAAI;AAOF,kDALE,WAAW,SACX,WAAW,EAAE,EACb,OACD,CAGC,QAAO;GAAE;GAAS,mBAAmB,WAAW;GAAS;SAErD;;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"}
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
4
4
|
const require_useCrossFrameMessageListener = require('./useCrossFrameMessageListener.cjs');
|
|
5
5
|
let react = require("react");
|
|
6
|
-
let
|
|
6
|
+
let _intlayer_editor = require("@intlayer/editor");
|
|
7
7
|
|
|
8
8
|
//#region src/useIframeClickInterceptor.tsx
|
|
9
9
|
const useIframeClickInterceptor = () => {
|
|
10
|
-
const postMessage = require_useCrossFrameMessageListener.useCrossFrameMessageListener(
|
|
10
|
+
const postMessage = require_useCrossFrameMessageListener.useCrossFrameMessageListener(_intlayer_editor.MessageKey.INTLAYER_IFRAME_CLICKED);
|
|
11
11
|
const handlePostMessageEvent = () => {
|
|
12
12
|
postMessage();
|
|
13
13
|
};
|
|
@@ -16,7 +16,7 @@ const useIframeClickInterceptor = () => {
|
|
|
16
16
|
return () => window.removeEventListener("mousedown", handlePostMessageEvent);
|
|
17
17
|
}, [postMessage]);
|
|
18
18
|
};
|
|
19
|
-
const useIframeClickMerger = () => require_useCrossFrameMessageListener.useCrossFrameMessageListener(
|
|
19
|
+
const useIframeClickMerger = () => require_useCrossFrameMessageListener.useCrossFrameMessageListener(_intlayer_editor.MessageKey.INTLAYER_IFRAME_CLICKED, _intlayer_editor.mergeIframeClick);
|
|
20
20
|
|
|
21
21
|
//#endregion
|
|
22
22
|
exports.useIframeClickInterceptor = useIframeClickInterceptor;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useIframeClickInterceptor.cjs","names":["useCrossFrameMessageListener","MessageKey","handlePostMessageEvent: EventListener","mergeIframeClick"],"sources":["../../src/useIframeClickInterceptor.tsx"],"sourcesContent":["'use client';\n\nimport { MessageKey, mergeIframeClick } from '@intlayer/editor';\nimport { useEffect } from 'react';\nimport { useCrossFrameMessageListener } from './useCrossFrameMessageListener';\n\nexport const useIframeClickInterceptor = () => {\n const postMessage = useCrossFrameMessageListener<undefined>(\n MessageKey.INTLAYER_IFRAME_CLICKED\n );\n const handlePostMessageEvent: EventListener = () => {\n postMessage();\n };\n\n useEffect(() => {\n window.addEventListener('mousedown', handlePostMessageEvent);\n\n return () =>\n window.removeEventListener('mousedown', handlePostMessageEvent);\n }, [postMessage]);\n};\n\nexport const useIframeClickMerger = () =>\n useCrossFrameMessageListener<MessageEvent>(\n MessageKey.INTLAYER_IFRAME_CLICKED,\n mergeIframeClick\n );\n"],"mappings":";;;;;;;;AAMA,MAAa,kCAAkC;CAC7C,MAAM,cAAcA,kEAClBC,
|
|
1
|
+
{"version":3,"file":"useIframeClickInterceptor.cjs","names":["useCrossFrameMessageListener","MessageKey","handlePostMessageEvent: EventListener","mergeIframeClick"],"sources":["../../src/useIframeClickInterceptor.tsx"],"sourcesContent":["'use client';\n\nimport { MessageKey, mergeIframeClick } from '@intlayer/editor';\nimport { useEffect } from 'react';\nimport { useCrossFrameMessageListener } from './useCrossFrameMessageListener';\n\nexport const useIframeClickInterceptor = () => {\n const postMessage = useCrossFrameMessageListener<undefined>(\n MessageKey.INTLAYER_IFRAME_CLICKED\n );\n const handlePostMessageEvent: EventListener = () => {\n postMessage();\n };\n\n useEffect(() => {\n window.addEventListener('mousedown', handlePostMessageEvent);\n\n return () =>\n window.removeEventListener('mousedown', handlePostMessageEvent);\n }, [postMessage]);\n};\n\nexport const useIframeClickMerger = () =>\n useCrossFrameMessageListener<MessageEvent>(\n MessageKey.INTLAYER_IFRAME_CLICKED,\n mergeIframeClick\n );\n"],"mappings":";;;;;;;;AAMA,MAAa,kCAAkC;CAC7C,MAAM,cAAcA,kEAClBC,4BAAW,wBACZ;CACD,MAAMC,+BAA8C;AAClD,eAAa;;AAGf,4BAAgB;AACd,SAAO,iBAAiB,aAAa,uBAAuB;AAE5D,eACE,OAAO,oBAAoB,aAAa,uBAAuB;IAChE,CAAC,YAAY,CAAC;;AAGnB,MAAa,6BACXF,kEACEC,4BAAW,yBACXE,kCACD"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react0 from "react";
|
|
2
2
|
import { FC, PropsWithChildren } from "react";
|
|
3
3
|
import { IntlayerConfig } from "@intlayer/types";
|
|
4
4
|
|
|
5
5
|
//#region src/ConfigurationContext.d.ts
|
|
6
|
-
declare const useConfigurationState: () => [IntlayerConfig,
|
|
6
|
+
declare const useConfigurationState: () => [IntlayerConfig, react0.Dispatch<react0.SetStateAction<IntlayerConfig>>, () => void];
|
|
7
7
|
type ConfigurationProviderProps = {
|
|
8
8
|
configuration?: IntlayerConfig;
|
|
9
9
|
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { CrossFrameStateOptions } from "./useCrossFrameState.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react9 from "react";
|
|
3
3
|
import { FC, PropsWithChildren } from "react";
|
|
4
4
|
|
|
5
5
|
//#region src/EditorEnabledContext.d.ts
|
|
6
6
|
type EditorEnabledStateProps = {
|
|
7
7
|
enabled: boolean;
|
|
8
8
|
};
|
|
9
|
-
declare const useEditorEnabledState: (options?: CrossFrameStateOptions) => [boolean,
|
|
9
|
+
declare const useEditorEnabledState: (options?: CrossFrameStateOptions) => [boolean, react9.Dispatch<react9.SetStateAction<boolean>>, () => void];
|
|
10
10
|
declare const usePostEditorEnabledState: <S>(onEventTriggered?: (data: S) => void) => (data?: S) => void;
|
|
11
11
|
declare const useGetEditorEnabledState: <S>(onEventTriggered?: (data: S) => void) => (data?: S) => void;
|
|
12
12
|
declare const EditorEnabledProvider: FC<PropsWithChildren>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { CrossFrameStateOptions } from "./useCrossFrameState.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react1 from "react";
|
|
3
3
|
|
|
4
4
|
//#region src/useCrossURLPathState.d.ts
|
|
5
|
-
declare const useCrossURLPathState: (initialState?: string, options?: CrossFrameStateOptions) => [string,
|
|
6
|
-
declare const useCrossURLPathSetter: (initialState?: string) => [string,
|
|
5
|
+
declare const useCrossURLPathState: (initialState?: string, options?: CrossFrameStateOptions) => [string, react1.Dispatch<react1.SetStateAction<string>>, () => void];
|
|
6
|
+
declare const useCrossURLPathSetter: (initialState?: string) => [string, react1.Dispatch<react1.SetStateAction<string>>, () => void];
|
|
7
7
|
//#endregion
|
|
8
8
|
export { useCrossURLPathSetter, useCrossURLPathState };
|
|
9
9
|
//# sourceMappingURL=useCrossURLPathState.d.ts.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react7 from "react";
|
|
2
2
|
import { Locale } from "@intlayer/types";
|
|
3
3
|
|
|
4
4
|
//#region src/useEditorLocale.d.ts
|
|
5
5
|
declare const useEditorLocale: () => Locale;
|
|
6
|
-
declare const useSetEditorLocale: () => [Locale,
|
|
6
|
+
declare const useSetEditorLocale: () => [Locale, react7.Dispatch<react7.SetStateAction<Locale>>, () => void];
|
|
7
7
|
//#endregion
|
|
8
8
|
export { useEditorLocale, useSetEditorLocale };
|
|
9
9
|
//# sourceMappingURL=useEditorLocale.d.ts.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { FileContent } from "./FocusDictionaryContext.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react5 from "react";
|
|
3
3
|
import { KeyPath } from "@intlayer/types";
|
|
4
4
|
|
|
5
5
|
//#region src/useFocusUnmergedDictionary.d.ts
|
|
6
6
|
declare const useFocusUnmergedDictionary: () => {
|
|
7
7
|
focusedContent: FileContent;
|
|
8
|
-
setFocusedContent:
|
|
8
|
+
setFocusedContent: react5.Dispatch<react5.SetStateAction<FileContent>>;
|
|
9
9
|
setFocusedContentKeyPath: (keyPath: KeyPath[]) => void;
|
|
10
10
|
};
|
|
11
11
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intlayer/editor-react",
|
|
3
|
-
"version": "7.5.0
|
|
3
|
+
"version": "7.5.0",
|
|
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": [
|
|
@@ -71,14 +71,14 @@
|
|
|
71
71
|
"typecheck": "tsc --noEmit --project tsconfig.types.json"
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
|
-
"@intlayer/config": "7.5.0
|
|
75
|
-
"@intlayer/core": "7.5.0
|
|
76
|
-
"@intlayer/editor": "7.5.0
|
|
77
|
-
"@intlayer/types": "7.5.0
|
|
78
|
-
"@intlayer/unmerged-dictionaries-entry": "7.5.0
|
|
74
|
+
"@intlayer/config": "7.5.0",
|
|
75
|
+
"@intlayer/core": "7.5.0",
|
|
76
|
+
"@intlayer/editor": "7.5.0",
|
|
77
|
+
"@intlayer/types": "7.5.0",
|
|
78
|
+
"@intlayer/unmerged-dictionaries-entry": "7.5.0"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
|
-
"@types/node": "25.0.
|
|
81
|
+
"@types/node": "25.0.3",
|
|
82
82
|
"@types/react": ">=16.0.0",
|
|
83
83
|
"@types/react-dom": ">=16.0.0",
|
|
84
84
|
"@utils/ts-config": "1.0.4",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"react": ">=16.0.0",
|
|
88
88
|
"react-dom": ">=16.0.0",
|
|
89
89
|
"rimraf": "6.1.2",
|
|
90
|
-
"tsdown": "0.18.
|
|
90
|
+
"tsdown": "0.18.1",
|
|
91
91
|
"typescript": "5.9.3",
|
|
92
92
|
"vitest": "4.0.16"
|
|
93
93
|
},
|