@intlayer/editor-react 9.6.0 → 9.7.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.
@@ -5,9 +5,13 @@ const require_EditorStateContext = require('./EditorStateContext.cjs');
5
5
  let react = require("react");
6
6
 
7
7
  //#region src/EditedContentContext.tsx
8
+ /**
9
+ * Returns the edited content actions. Memoized on the manager so they can be
10
+ * used as effect dependencies without a compiler.
11
+ */
8
12
  const useEditedContentActions = () => {
9
13
  const manager = require_EditorStateContext.useEditorStateManager();
10
- return {
14
+ return (0, react.useMemo)(() => ({
11
15
  setEditedContentState: (value) => manager?.editedContent.set(value),
12
16
  setEditedDictionary: (dict) => manager?.setEditedDictionary(dict),
13
17
  setEditedContent: (localId, value) => manager?.setEditedContent(localId, value),
@@ -16,7 +20,7 @@ const useEditedContentActions = () => {
16
20
  removeEditedContent: (localId, keyPath) => manager?.removeContent(localId, keyPath),
17
21
  restoreEditedContent: (localId) => manager?.restoreContent(localId),
18
22
  getEditedContentValue: (localIdOrKey, keyPath) => manager?.getContentValue(localIdOrKey, keyPath)
19
- };
23
+ }), [manager]);
20
24
  };
21
25
  const useEditedContent = () => {
22
26
  const manager = require_EditorStateContext.useEditorStateManager();
@@ -1 +1 @@
1
- {"version":3,"file":"EditedContentContext.cjs","names":["useEditorStateManager","useState"],"sources":["../../src/EditedContentContext.tsx"],"sourcesContent":["'use client';\n\nimport type { DictionaryContent } from '@intlayer/editor';\nimport type {\n ContentNode,\n Dictionary,\n LocalDictionaryId,\n} from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport { useEffect, useState } from 'react';\nimport { useEditorStateManager } from './EditorStateContext';\n\nexport type { DictionaryContent } from '@intlayer/editor';\n\ntype EditedContentActionsContextType = {\n setEditedContentState: (editedContent: DictionaryContent) => void;\n setEditedDictionary: (dict: Dictionary) => void;\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 getEditedContentValue: (\n localDictionaryIdOrKey: LocalDictionaryId | Dictionary['key'] | string,\n keyPath: KeyPath[]\n ) => ContentNode | undefined;\n};\n\nexport const useEditedContentActions = (): EditedContentActionsContextType => {\n const manager = useEditorStateManager();\n\n return {\n setEditedContentState: (value: DictionaryContent) =>\n manager?.editedContent.set(value),\n setEditedDictionary: (dict: Dictionary) =>\n manager?.setEditedDictionary(dict),\n setEditedContent: (\n localId: LocalDictionaryId,\n value: Dictionary['content']\n ) => manager?.setEditedContent(localId, value),\n addEditedContent: (localId, value, keyPath, overwrite) =>\n manager?.addContent(localId, value, keyPath, overwrite),\n renameEditedContent: (localId, newKey, keyPath) =>\n manager?.renameContent(localId, newKey, keyPath),\n removeEditedContent: (localId, keyPath) =>\n manager?.removeContent(localId, keyPath),\n restoreEditedContent: (localId) => manager?.restoreContent(localId),\n getEditedContentValue: (localIdOrKey, keyPath) =>\n manager?.getContentValue(localIdOrKey, keyPath),\n };\n};\n\nexport const useEditedContent = () => {\n const manager = useEditorStateManager();\n const [editedContent, setEditedContentState] = useState<\n DictionaryContent | undefined\n >(manager?.editedContent.value);\n\n useEffect(() => {\n if (!manager) return;\n const handler = (e: Event) =>\n setEditedContentState((e as CustomEvent<DictionaryContent>).detail);\n manager.editedContent.addEventListener('change', handler);\n return () => manager.editedContent.removeEventListener('change', handler);\n }, [manager]);\n\n const actions = useEditedContentActions();\n return { editedContent, ...actions };\n};\n"],"mappings":";;;;;;;AA2CA,MAAa,gCAAiE;CAC5E,MAAM,UAAUA,iDAAsB;CAEtC,OAAO;EACL,wBAAwB,UACtB,SAAS,cAAc,IAAI,KAAK;EAClC,sBAAsB,SACpB,SAAS,oBAAoB,IAAI;EACnC,mBACE,SACA,UACG,SAAS,iBAAiB,SAAS,KAAK;EAC7C,mBAAmB,SAAS,OAAO,SAAS,cAC1C,SAAS,WAAW,SAAS,OAAO,SAAS,SAAS;EACxD,sBAAsB,SAAS,QAAQ,YACrC,SAAS,cAAc,SAAS,QAAQ,OAAO;EACjD,sBAAsB,SAAS,YAC7B,SAAS,cAAc,SAAS,OAAO;EACzC,uBAAuB,YAAY,SAAS,eAAe,OAAO;EAClE,wBAAwB,cAAc,YACpC,SAAS,gBAAgB,cAAc,OAAO;CAClD;AACF;AAEA,MAAa,yBAAyB;CACpC,MAAM,UAAUA,iDAAsB;CACtC,MAAM,CAAC,eAAe,6BAAyBC,gBAE7C,SAAS,cAAc,KAAK;CAE9B,2BAAgB;EACd,IAAI,CAAC,SAAS;EACd,MAAM,WAAW,MACf,sBAAuB,EAAqC,MAAM;EACpE,QAAQ,cAAc,iBAAiB,UAAU,OAAO;EACxD,aAAa,QAAQ,cAAc,oBAAoB,UAAU,OAAO;CAC1E,GAAG,CAAC,OAAO,CAAC;CAGZ,OAAO;EAAE;EAAe,GADR,wBACiB;CAAE;AACrC"}
1
+ {"version":3,"file":"EditedContentContext.cjs","names":["useEditorStateManager","useMemo","useState"],"sources":["../../src/EditedContentContext.tsx"],"sourcesContent":["'use client';\n\nimport type { DictionaryContent } from '@intlayer/editor';\nimport type {\n ContentNode,\n Dictionary,\n LocalDictionaryId,\n} from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport { useEffect, useMemo, useState } from 'react';\nimport { useEditorStateManager } from './EditorStateContext';\n\nexport type { DictionaryContent } from '@intlayer/editor';\n\ntype EditedContentActionsContextType = {\n setEditedContentState: (editedContent: DictionaryContent) => void;\n setEditedDictionary: (dict: Dictionary) => void;\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 getEditedContentValue: (\n localDictionaryIdOrKey: LocalDictionaryId | Dictionary['key'] | string,\n keyPath: KeyPath[]\n ) => ContentNode | undefined;\n};\n\n/**\n * Returns the edited content actions. Memoized on the manager so they can be\n * used as effect dependencies without a compiler.\n */\nexport const useEditedContentActions = (): EditedContentActionsContextType => {\n const manager = useEditorStateManager();\n\n return useMemo<EditedContentActionsContextType>(\n () => ({\n setEditedContentState: (value: DictionaryContent) =>\n manager?.editedContent.set(value),\n setEditedDictionary: (dict: Dictionary) =>\n manager?.setEditedDictionary(dict),\n setEditedContent: (\n localId: LocalDictionaryId,\n value: Dictionary['content']\n ) => manager?.setEditedContent(localId, value),\n addEditedContent: (localId, value, keyPath, overwrite) =>\n manager?.addContent(localId, value, keyPath, overwrite),\n renameEditedContent: (localId, newKey, keyPath) =>\n manager?.renameContent(localId, newKey, keyPath),\n removeEditedContent: (localId, keyPath) =>\n manager?.removeContent(localId, keyPath),\n restoreEditedContent: (localId) => manager?.restoreContent(localId),\n getEditedContentValue: (localIdOrKey, keyPath) =>\n manager?.getContentValue(localIdOrKey, keyPath),\n }),\n [manager]\n );\n};\n\nexport const useEditedContent = () => {\n const manager = useEditorStateManager();\n const [editedContent, setEditedContentState] = useState<\n DictionaryContent | undefined\n >(manager?.editedContent.value);\n\n useEffect(() => {\n if (!manager) return;\n const handler = (e: Event) =>\n setEditedContentState((e as CustomEvent<DictionaryContent>).detail);\n manager.editedContent.addEventListener('change', handler);\n return () => manager.editedContent.removeEventListener('change', handler);\n }, [manager]);\n\n const actions = useEditedContentActions();\n return { editedContent, ...actions };\n};\n"],"mappings":";;;;;;;;;;;AA+CA,MAAa,gCAAiE;CAC5E,MAAM,UAAUA,iDAAsB;CAEtC,WAAOC,sBACE;EACL,wBAAwB,UACtB,SAAS,cAAc,IAAI,KAAK;EAClC,sBAAsB,SACpB,SAAS,oBAAoB,IAAI;EACnC,mBACE,SACA,UACG,SAAS,iBAAiB,SAAS,KAAK;EAC7C,mBAAmB,SAAS,OAAO,SAAS,cAC1C,SAAS,WAAW,SAAS,OAAO,SAAS,SAAS;EACxD,sBAAsB,SAAS,QAAQ,YACrC,SAAS,cAAc,SAAS,QAAQ,OAAO;EACjD,sBAAsB,SAAS,YAC7B,SAAS,cAAc,SAAS,OAAO;EACzC,uBAAuB,YAAY,SAAS,eAAe,OAAO;EAClE,wBAAwB,cAAc,YACpC,SAAS,gBAAgB,cAAc,OAAO;CAClD,IACA,CAAC,OAAO,CACV;AACF;AAEA,MAAa,yBAAyB;CACpC,MAAM,UAAUD,iDAAsB;CACtC,MAAM,CAAC,eAAe,6BAAyBE,gBAE7C,SAAS,cAAc,KAAK;CAE9B,2BAAgB;EACd,IAAI,CAAC,SAAS;EACd,MAAM,WAAW,MACf,sBAAuB,EAAqC,MAAM;EACpE,QAAQ,cAAc,iBAAiB,UAAU,OAAO;EACxD,aAAa,QAAQ,cAAc,oBAAoB,UAAU,OAAO;CAC1E,GAAG,CAAC,OAAO,CAAC;CAGZ,OAAO;EAAE;EAAe,GADR,wBACiB;CAAE;AACrC"}
@@ -26,7 +26,7 @@ const useEditorEnabled = () => {
26
26
  */
27
27
  const useEditorPingClient = () => {
28
28
  const manager = require_EditorStateContext.useEditorStateManager();
29
- return () => manager?.pingClient();
29
+ return (0, react.useCallback)(() => manager?.pingClient(), [manager]);
30
30
  };
31
31
 
32
32
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"EditorEnabledContext.cjs","names":["useEditorStateManager","useState"],"sources":["../../src/EditorEnabledContext.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\nimport { useEditorStateManager } from './EditorStateContext';\n\nexport type EditorEnabledStateProps = {\n enabled: boolean;\n};\n\n/**\n * Returns the current editor-enabled state, kept in sync with the shared\n * EditorStateManager. Replaces the old EditorEnabledContext + EditorEnabledProvider.\n */\nexport const useEditorEnabled = (): EditorEnabledStateProps => {\n const manager = useEditorStateManager();\n const [enabled, setEnabled] = useState<boolean>(\n manager?.editorEnabled.value ?? false\n );\n\n useEffect(() => {\n if (!manager) return;\n\n const handler = (e: Event) =>\n setEnabled((e as CustomEvent<boolean>).detail);\n manager.editorEnabled.addEventListener('change', handler);\n return () => manager.editorEnabled.removeEventListener('change', handler);\n }, [manager]);\n\n return { enabled };\n};\n\n/**\n * Returns a function that re-pings the client via ARE_YOU_THERE.\n * Use this as the onClick for an \"Enable Editor\" / reconnect button.\n */\nexport const useEditorPingClient = (): (() => void) => {\n const manager = useEditorStateManager();\n\n return () => manager?.pingClient();\n};\n"],"mappings":";;;;;;;;;;;AAaA,MAAa,yBAAkD;CAC7D,MAAM,UAAUA,iDAAsB;CACtC,MAAM,CAAC,SAAS,kBAAcC,gBAC5B,SAAS,cAAc,SAAS,KAClC;CAEA,2BAAgB;EACd,IAAI,CAAC,SAAS;EAEd,MAAM,WAAW,MACf,WAAY,EAA2B,MAAM;EAC/C,QAAQ,cAAc,iBAAiB,UAAU,OAAO;EACxD,aAAa,QAAQ,cAAc,oBAAoB,UAAU,OAAO;CAC1E,GAAG,CAAC,OAAO,CAAC;CAEZ,OAAO,EAAE,QAAQ;AACnB;;;;;AAMA,MAAa,4BAA0C;CACrD,MAAM,UAAUD,iDAAsB;CAEtC,aAAa,SAAS,WAAW;AACnC"}
1
+ {"version":3,"file":"EditorEnabledContext.cjs","names":["useEditorStateManager","useState","useCallback"],"sources":["../../src/EditorEnabledContext.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useState } from 'react';\nimport { useEditorStateManager } from './EditorStateContext';\n\nexport type EditorEnabledStateProps = {\n enabled: boolean;\n};\n\n/**\n * Returns the current editor-enabled state, kept in sync with the shared\n * EditorStateManager. Replaces the old EditorEnabledContext + EditorEnabledProvider.\n */\nexport const useEditorEnabled = (): EditorEnabledStateProps => {\n const manager = useEditorStateManager();\n const [enabled, setEnabled] = useState<boolean>(\n manager?.editorEnabled.value ?? false\n );\n\n useEffect(() => {\n if (!manager) return;\n\n const handler = (e: Event) =>\n setEnabled((e as CustomEvent<boolean>).detail);\n manager.editorEnabled.addEventListener('change', handler);\n return () => manager.editorEnabled.removeEventListener('change', handler);\n }, [manager]);\n\n return { enabled };\n};\n\n/**\n * Returns a function that re-pings the client via ARE_YOU_THERE.\n * Use this as the onClick for an \"Enable Editor\" / reconnect button.\n */\nexport const useEditorPingClient = (): (() => void) => {\n const manager = useEditorStateManager();\n\n return useCallback(() => manager?.pingClient(), [manager]);\n};\n"],"mappings":";;;;;;;;;;;AAaA,MAAa,yBAAkD;CAC7D,MAAM,UAAUA,iDAAsB;CACtC,MAAM,CAAC,SAAS,kBAAcC,gBAC5B,SAAS,cAAc,SAAS,KAClC;CAEA,2BAAgB;EACd,IAAI,CAAC,SAAS;EAEd,MAAM,WAAW,MACf,WAAY,EAA2B,MAAM;EAC/C,QAAQ,cAAc,iBAAiB,UAAU,OAAO;EACxD,aAAa,QAAQ,cAAc,oBAAoB,UAAU,OAAO;CAC1E,GAAG,CAAC,OAAO,CAAC;CAEZ,OAAO,EAAE,QAAQ;AACnB;;;;;AAMA,MAAa,4BAA0C;CACrD,MAAM,UAAUD,iDAAsB;CAEtC,WAAOE,yBAAkB,SAAS,WAAW,GAAG,CAAC,OAAO,CAAC;AAC3D"}
@@ -11,10 +11,12 @@ const require_EditorEnabledContext = require('./EditorEnabledContext.cjs');
11
11
  const require_EditorProvider = require('./EditorProvider.cjs');
12
12
  const require_FocusDictionaryContext = require('./FocusDictionaryContext.cjs');
13
13
  const require_useFocusUnmergedDictionary = require('./useFocusUnmergedDictionary.cjs');
14
+ const require_useFrameConnectionStatus = require('./useFrameConnectionStatus.cjs');
14
15
  let _intlayer_editor = require("@intlayer/editor");
15
16
 
16
17
  exports.EditorProvider = require_EditorProvider.EditorProvider;
17
18
  exports.EditorStateProvider = require_EditorStateContext.EditorStateProvider;
19
+ exports.FRAME_CONNECTION_TIMEOUT_MS = require_useFrameConnectionStatus.FRAME_CONNECTION_TIMEOUT_MS;
18
20
  Object.defineProperty(exports, 'MessageKey', {
19
21
  enumerable: true,
20
22
  get: function () {
@@ -34,4 +36,5 @@ exports.useEditorLocale = require_useEditorLocale.useEditorLocale;
34
36
  exports.useEditorPingClient = require_EditorEnabledContext.useEditorPingClient;
35
37
  exports.useEditorStateManager = require_EditorStateContext.useEditorStateManager;
36
38
  exports.useFocusDictionary = require_FocusDictionaryContext.useFocusDictionary;
37
- exports.useFocusUnmergedDictionary = require_useFocusUnmergedDictionary.useFocusUnmergedDictionary;
39
+ exports.useFocusUnmergedDictionary = require_useFocusUnmergedDictionary.useFocusUnmergedDictionary;
40
+ exports.useFrameConnectionStatus = require_useFrameConnectionStatus.useFrameConnectionStatus;
@@ -0,0 +1,44 @@
1
+ 'use client';
2
+
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
+ const require_EditorEnabledContext = require('./EditorEnabledContext.cjs');
5
+ let react = require("react");
6
+
7
+ //#region src/useFrameConnectionStatus.ts
8
+ /** Delay after a frame load before an unanswered handshake counts as failed. */
9
+ const FRAME_CONNECTION_TIMEOUT_MS = 5e3;
10
+ /**
11
+ * Detects an application frame that never connects to the editor.
12
+ * A frame blocked by the application's framing policy still fires `load` on
13
+ * an empty error page that the parent cannot inspect, so the missing
14
+ * handshake is the only signal available.
15
+ */
16
+ const useFrameConnectionStatus = (timeoutMs = FRAME_CONNECTION_TIMEOUT_MS) => {
17
+ const { enabled } = require_EditorEnabledContext.useEditorEnabled();
18
+ const [loadCount, setLoadCount] = (0, react.useState)(0);
19
+ const [isTimedOut, setIsTimedOut] = (0, react.useState)(false);
20
+ (0, react.useEffect)(() => {
21
+ if (enabled || loadCount === 0) return;
22
+ const timeout = setTimeout(() => setIsTimedOut(true), timeoutMs);
23
+ return () => clearTimeout(timeout);
24
+ }, [
25
+ enabled,
26
+ loadCount,
27
+ timeoutMs
28
+ ]);
29
+ const handleFrameLoad = (0, react.useCallback)(() => {
30
+ setIsTimedOut(false);
31
+ setLoadCount((count) => count + 1);
32
+ }, []);
33
+ const dismiss = (0, react.useCallback)(() => setIsTimedOut(false), []);
34
+ return {
35
+ isConnectionFailed: isTimedOut && !enabled,
36
+ handleFrameLoad,
37
+ dismiss
38
+ };
39
+ };
40
+
41
+ //#endregion
42
+ exports.FRAME_CONNECTION_TIMEOUT_MS = FRAME_CONNECTION_TIMEOUT_MS;
43
+ exports.useFrameConnectionStatus = useFrameConnectionStatus;
44
+ //# sourceMappingURL=useFrameConnectionStatus.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFrameConnectionStatus.cjs","names":["useEditorEnabled","useState","useCallback"],"sources":["../../src/useFrameConnectionStatus.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useState } from 'react';\nimport { useEditorEnabled } from './EditorEnabledContext';\n\n/** Delay after a frame load before an unanswered handshake counts as failed. */\nexport const FRAME_CONNECTION_TIMEOUT_MS = 5_000;\n\nexport type FrameConnectionStatus = {\n /**\n * The frame loaded but its client never answered the handshake: the page\n * refused to be framed (CSP `frame-ancestors`, `X-Frame-Options`), or it\n * does not run the editor client.\n */\n isConnectionFailed: boolean;\n /** To call on every `load` event of the application frame. */\n handleFrameLoad: () => void;\n /** Hides the failure until the next load. */\n dismiss: () => void;\n};\n\n/**\n * Detects an application frame that never connects to the editor.\n * A frame blocked by the application's framing policy still fires `load` on\n * an empty error page that the parent cannot inspect, so the missing\n * handshake is the only signal available.\n */\nexport const useFrameConnectionStatus = (\n timeoutMs: number = FRAME_CONNECTION_TIMEOUT_MS\n): FrameConnectionStatus => {\n const { enabled } = useEditorEnabled();\n const [loadCount, setLoadCount] = useState(0);\n const [isTimedOut, setIsTimedOut] = useState(false);\n\n useEffect(() => {\n if (enabled || loadCount === 0) return;\n\n const timeout = setTimeout(() => setIsTimedOut(true), timeoutMs);\n\n return () => clearTimeout(timeout);\n }, [enabled, loadCount, timeoutMs]);\n\n const handleFrameLoad = useCallback(() => {\n setIsTimedOut(false);\n setLoadCount((count) => count + 1);\n }, []);\n\n const dismiss = useCallback(() => setIsTimedOut(false), []);\n\n return {\n isConnectionFailed: isTimedOut && !enabled,\n handleFrameLoad,\n dismiss,\n };\n};\n"],"mappings":";;;;;;;;AAMA,MAAa,8BAA8B;;;;;;;AAqB3C,MAAa,4BACX,YAAoB,gCACM;CAC1B,MAAM,EAAE,YAAYA,8CAAiB;CACrC,MAAM,CAAC,WAAW,oBAAgBC,gBAAS,CAAC;CAC5C,MAAM,CAAC,YAAY,qBAAiBA,gBAAS,KAAK;CAElD,2BAAgB;EACd,IAAI,WAAW,cAAc,GAAG;EAEhC,MAAM,UAAU,iBAAiB,cAAc,IAAI,GAAG,SAAS;EAE/D,aAAa,aAAa,OAAO;CACnC,GAAG;EAAC;EAAS;EAAW;CAAS,CAAC;CAElC,MAAM,sBAAkBC,yBAAkB;EACxC,cAAc,KAAK;EACnB,cAAc,UAAU,QAAQ,CAAC;CACnC,GAAG,CAAC,CAAC;CAEL,MAAM,cAAUA,yBAAkB,cAAc,KAAK,GAAG,CAAC,CAAC;CAE1D,OAAO;EACL,oBAAoB,cAAc,CAAC;EACnC;EACA;CACF;AACF"}
@@ -1,12 +1,16 @@
1
1
  'use client';
2
2
 
3
3
  import { useEditorStateManager } from "./EditorStateContext.mjs";
4
- import { useEffect, useState } from "react";
4
+ import { useEffect, useMemo, useState } from "react";
5
5
 
6
6
  //#region src/EditedContentContext.tsx
7
+ /**
8
+ * Returns the edited content actions. Memoized on the manager so they can be
9
+ * used as effect dependencies without a compiler.
10
+ */
7
11
  const useEditedContentActions = () => {
8
12
  const manager = useEditorStateManager();
9
- return {
13
+ return useMemo(() => ({
10
14
  setEditedContentState: (value) => manager?.editedContent.set(value),
11
15
  setEditedDictionary: (dict) => manager?.setEditedDictionary(dict),
12
16
  setEditedContent: (localId, value) => manager?.setEditedContent(localId, value),
@@ -15,7 +19,7 @@ const useEditedContentActions = () => {
15
19
  removeEditedContent: (localId, keyPath) => manager?.removeContent(localId, keyPath),
16
20
  restoreEditedContent: (localId) => manager?.restoreContent(localId),
17
21
  getEditedContentValue: (localIdOrKey, keyPath) => manager?.getContentValue(localIdOrKey, keyPath)
18
- };
22
+ }), [manager]);
19
23
  };
20
24
  const useEditedContent = () => {
21
25
  const manager = useEditorStateManager();
@@ -1 +1 @@
1
- {"version":3,"file":"EditedContentContext.mjs","names":[],"sources":["../../src/EditedContentContext.tsx"],"sourcesContent":["'use client';\n\nimport type { DictionaryContent } from '@intlayer/editor';\nimport type {\n ContentNode,\n Dictionary,\n LocalDictionaryId,\n} from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport { useEffect, useState } from 'react';\nimport { useEditorStateManager } from './EditorStateContext';\n\nexport type { DictionaryContent } from '@intlayer/editor';\n\ntype EditedContentActionsContextType = {\n setEditedContentState: (editedContent: DictionaryContent) => void;\n setEditedDictionary: (dict: Dictionary) => void;\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 getEditedContentValue: (\n localDictionaryIdOrKey: LocalDictionaryId | Dictionary['key'] | string,\n keyPath: KeyPath[]\n ) => ContentNode | undefined;\n};\n\nexport const useEditedContentActions = (): EditedContentActionsContextType => {\n const manager = useEditorStateManager();\n\n return {\n setEditedContentState: (value: DictionaryContent) =>\n manager?.editedContent.set(value),\n setEditedDictionary: (dict: Dictionary) =>\n manager?.setEditedDictionary(dict),\n setEditedContent: (\n localId: LocalDictionaryId,\n value: Dictionary['content']\n ) => manager?.setEditedContent(localId, value),\n addEditedContent: (localId, value, keyPath, overwrite) =>\n manager?.addContent(localId, value, keyPath, overwrite),\n renameEditedContent: (localId, newKey, keyPath) =>\n manager?.renameContent(localId, newKey, keyPath),\n removeEditedContent: (localId, keyPath) =>\n manager?.removeContent(localId, keyPath),\n restoreEditedContent: (localId) => manager?.restoreContent(localId),\n getEditedContentValue: (localIdOrKey, keyPath) =>\n manager?.getContentValue(localIdOrKey, keyPath),\n };\n};\n\nexport const useEditedContent = () => {\n const manager = useEditorStateManager();\n const [editedContent, setEditedContentState] = useState<\n DictionaryContent | undefined\n >(manager?.editedContent.value);\n\n useEffect(() => {\n if (!manager) return;\n const handler = (e: Event) =>\n setEditedContentState((e as CustomEvent<DictionaryContent>).detail);\n manager.editedContent.addEventListener('change', handler);\n return () => manager.editedContent.removeEventListener('change', handler);\n }, [manager]);\n\n const actions = useEditedContentActions();\n return { editedContent, ...actions };\n};\n"],"mappings":";;;;;;AA2CA,MAAa,gCAAiE;CAC5E,MAAM,UAAU,sBAAsB;CAEtC,OAAO;EACL,wBAAwB,UACtB,SAAS,cAAc,IAAI,KAAK;EAClC,sBAAsB,SACpB,SAAS,oBAAoB,IAAI;EACnC,mBACE,SACA,UACG,SAAS,iBAAiB,SAAS,KAAK;EAC7C,mBAAmB,SAAS,OAAO,SAAS,cAC1C,SAAS,WAAW,SAAS,OAAO,SAAS,SAAS;EACxD,sBAAsB,SAAS,QAAQ,YACrC,SAAS,cAAc,SAAS,QAAQ,OAAO;EACjD,sBAAsB,SAAS,YAC7B,SAAS,cAAc,SAAS,OAAO;EACzC,uBAAuB,YAAY,SAAS,eAAe,OAAO;EAClE,wBAAwB,cAAc,YACpC,SAAS,gBAAgB,cAAc,OAAO;CAClD;AACF;AAEA,MAAa,yBAAyB;CACpC,MAAM,UAAU,sBAAsB;CACtC,MAAM,CAAC,eAAe,yBAAyB,SAE7C,SAAS,cAAc,KAAK;CAE9B,gBAAgB;EACd,IAAI,CAAC,SAAS;EACd,MAAM,WAAW,MACf,sBAAuB,EAAqC,MAAM;EACpE,QAAQ,cAAc,iBAAiB,UAAU,OAAO;EACxD,aAAa,QAAQ,cAAc,oBAAoB,UAAU,OAAO;CAC1E,GAAG,CAAC,OAAO,CAAC;CAGZ,OAAO;EAAE;EAAe,GADR,wBACiB;CAAE;AACrC"}
1
+ {"version":3,"file":"EditedContentContext.mjs","names":[],"sources":["../../src/EditedContentContext.tsx"],"sourcesContent":["'use client';\n\nimport type { DictionaryContent } from '@intlayer/editor';\nimport type {\n ContentNode,\n Dictionary,\n LocalDictionaryId,\n} from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport { useEffect, useMemo, useState } from 'react';\nimport { useEditorStateManager } from './EditorStateContext';\n\nexport type { DictionaryContent } from '@intlayer/editor';\n\ntype EditedContentActionsContextType = {\n setEditedContentState: (editedContent: DictionaryContent) => void;\n setEditedDictionary: (dict: Dictionary) => void;\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 getEditedContentValue: (\n localDictionaryIdOrKey: LocalDictionaryId | Dictionary['key'] | string,\n keyPath: KeyPath[]\n ) => ContentNode | undefined;\n};\n\n/**\n * Returns the edited content actions. Memoized on the manager so they can be\n * used as effect dependencies without a compiler.\n */\nexport const useEditedContentActions = (): EditedContentActionsContextType => {\n const manager = useEditorStateManager();\n\n return useMemo<EditedContentActionsContextType>(\n () => ({\n setEditedContentState: (value: DictionaryContent) =>\n manager?.editedContent.set(value),\n setEditedDictionary: (dict: Dictionary) =>\n manager?.setEditedDictionary(dict),\n setEditedContent: (\n localId: LocalDictionaryId,\n value: Dictionary['content']\n ) => manager?.setEditedContent(localId, value),\n addEditedContent: (localId, value, keyPath, overwrite) =>\n manager?.addContent(localId, value, keyPath, overwrite),\n renameEditedContent: (localId, newKey, keyPath) =>\n manager?.renameContent(localId, newKey, keyPath),\n removeEditedContent: (localId, keyPath) =>\n manager?.removeContent(localId, keyPath),\n restoreEditedContent: (localId) => manager?.restoreContent(localId),\n getEditedContentValue: (localIdOrKey, keyPath) =>\n manager?.getContentValue(localIdOrKey, keyPath),\n }),\n [manager]\n );\n};\n\nexport const useEditedContent = () => {\n const manager = useEditorStateManager();\n const [editedContent, setEditedContentState] = useState<\n DictionaryContent | undefined\n >(manager?.editedContent.value);\n\n useEffect(() => {\n if (!manager) return;\n const handler = (e: Event) =>\n setEditedContentState((e as CustomEvent<DictionaryContent>).detail);\n manager.editedContent.addEventListener('change', handler);\n return () => manager.editedContent.removeEventListener('change', handler);\n }, [manager]);\n\n const actions = useEditedContentActions();\n return { editedContent, ...actions };\n};\n"],"mappings":";;;;;;;;;;AA+CA,MAAa,gCAAiE;CAC5E,MAAM,UAAU,sBAAsB;CAEtC,OAAO,eACE;EACL,wBAAwB,UACtB,SAAS,cAAc,IAAI,KAAK;EAClC,sBAAsB,SACpB,SAAS,oBAAoB,IAAI;EACnC,mBACE,SACA,UACG,SAAS,iBAAiB,SAAS,KAAK;EAC7C,mBAAmB,SAAS,OAAO,SAAS,cAC1C,SAAS,WAAW,SAAS,OAAO,SAAS,SAAS;EACxD,sBAAsB,SAAS,QAAQ,YACrC,SAAS,cAAc,SAAS,QAAQ,OAAO;EACjD,sBAAsB,SAAS,YAC7B,SAAS,cAAc,SAAS,OAAO;EACzC,uBAAuB,YAAY,SAAS,eAAe,OAAO;EAClE,wBAAwB,cAAc,YACpC,SAAS,gBAAgB,cAAc,OAAO;CAClD,IACA,CAAC,OAAO,CACV;AACF;AAEA,MAAa,yBAAyB;CACpC,MAAM,UAAU,sBAAsB;CACtC,MAAM,CAAC,eAAe,yBAAyB,SAE7C,SAAS,cAAc,KAAK;CAE9B,gBAAgB;EACd,IAAI,CAAC,SAAS;EACd,MAAM,WAAW,MACf,sBAAuB,EAAqC,MAAM;EACpE,QAAQ,cAAc,iBAAiB,UAAU,OAAO;EACxD,aAAa,QAAQ,cAAc,oBAAoB,UAAU,OAAO;CAC1E,GAAG,CAAC,OAAO,CAAC;CAGZ,OAAO;EAAE;EAAe,GADR,wBACiB;CAAE;AACrC"}
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { useEditorStateManager } from "./EditorStateContext.mjs";
4
- import { useEffect, useState } from "react";
4
+ import { useCallback, useEffect, useState } from "react";
5
5
 
6
6
  //#region src/EditorEnabledContext.tsx
7
7
  /**
@@ -25,7 +25,7 @@ const useEditorEnabled = () => {
25
25
  */
26
26
  const useEditorPingClient = () => {
27
27
  const manager = useEditorStateManager();
28
- return () => manager?.pingClient();
28
+ return useCallback(() => manager?.pingClient(), [manager]);
29
29
  };
30
30
 
31
31
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"EditorEnabledContext.mjs","names":[],"sources":["../../src/EditorEnabledContext.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\nimport { useEditorStateManager } from './EditorStateContext';\n\nexport type EditorEnabledStateProps = {\n enabled: boolean;\n};\n\n/**\n * Returns the current editor-enabled state, kept in sync with the shared\n * EditorStateManager. Replaces the old EditorEnabledContext + EditorEnabledProvider.\n */\nexport const useEditorEnabled = (): EditorEnabledStateProps => {\n const manager = useEditorStateManager();\n const [enabled, setEnabled] = useState<boolean>(\n manager?.editorEnabled.value ?? false\n );\n\n useEffect(() => {\n if (!manager) return;\n\n const handler = (e: Event) =>\n setEnabled((e as CustomEvent<boolean>).detail);\n manager.editorEnabled.addEventListener('change', handler);\n return () => manager.editorEnabled.removeEventListener('change', handler);\n }, [manager]);\n\n return { enabled };\n};\n\n/**\n * Returns a function that re-pings the client via ARE_YOU_THERE.\n * Use this as the onClick for an \"Enable Editor\" / reconnect button.\n */\nexport const useEditorPingClient = (): (() => void) => {\n const manager = useEditorStateManager();\n\n return () => manager?.pingClient();\n};\n"],"mappings":";;;;;;;;;;AAaA,MAAa,yBAAkD;CAC7D,MAAM,UAAU,sBAAsB;CACtC,MAAM,CAAC,SAAS,cAAc,SAC5B,SAAS,cAAc,SAAS,KAClC;CAEA,gBAAgB;EACd,IAAI,CAAC,SAAS;EAEd,MAAM,WAAW,MACf,WAAY,EAA2B,MAAM;EAC/C,QAAQ,cAAc,iBAAiB,UAAU,OAAO;EACxD,aAAa,QAAQ,cAAc,oBAAoB,UAAU,OAAO;CAC1E,GAAG,CAAC,OAAO,CAAC;CAEZ,OAAO,EAAE,QAAQ;AACnB;;;;;AAMA,MAAa,4BAA0C;CACrD,MAAM,UAAU,sBAAsB;CAEtC,aAAa,SAAS,WAAW;AACnC"}
1
+ {"version":3,"file":"EditorEnabledContext.mjs","names":[],"sources":["../../src/EditorEnabledContext.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useState } from 'react';\nimport { useEditorStateManager } from './EditorStateContext';\n\nexport type EditorEnabledStateProps = {\n enabled: boolean;\n};\n\n/**\n * Returns the current editor-enabled state, kept in sync with the shared\n * EditorStateManager. Replaces the old EditorEnabledContext + EditorEnabledProvider.\n */\nexport const useEditorEnabled = (): EditorEnabledStateProps => {\n const manager = useEditorStateManager();\n const [enabled, setEnabled] = useState<boolean>(\n manager?.editorEnabled.value ?? false\n );\n\n useEffect(() => {\n if (!manager) return;\n\n const handler = (e: Event) =>\n setEnabled((e as CustomEvent<boolean>).detail);\n manager.editorEnabled.addEventListener('change', handler);\n return () => manager.editorEnabled.removeEventListener('change', handler);\n }, [manager]);\n\n return { enabled };\n};\n\n/**\n * Returns a function that re-pings the client via ARE_YOU_THERE.\n * Use this as the onClick for an \"Enable Editor\" / reconnect button.\n */\nexport const useEditorPingClient = (): (() => void) => {\n const manager = useEditorStateManager();\n\n return useCallback(() => manager?.pingClient(), [manager]);\n};\n"],"mappings":";;;;;;;;;;AAaA,MAAa,yBAAkD;CAC7D,MAAM,UAAU,sBAAsB;CACtC,MAAM,CAAC,SAAS,cAAc,SAC5B,SAAS,cAAc,SAAS,KAClC;CAEA,gBAAgB;EACd,IAAI,CAAC,SAAS;EAEd,MAAM,WAAW,MACf,WAAY,EAA2B,MAAM;EAC/C,QAAQ,cAAc,iBAAiB,UAAU,OAAO;EACxD,aAAa,QAAQ,cAAc,oBAAoB,UAAU,OAAO;CAC1E,GAAG,CAAC,OAAO,CAAC;CAEZ,OAAO,EAAE,QAAQ;AACnB;;;;;AAMA,MAAa,4BAA0C;CACrD,MAAM,UAAU,sBAAsB;CAEtC,OAAO,kBAAkB,SAAS,WAAW,GAAG,CAAC,OAAO,CAAC;AAC3D"}
@@ -10,6 +10,7 @@ import { useEditorEnabled, useEditorPingClient } from "./EditorEnabledContext.mj
10
10
  import { EditorProvider } from "./EditorProvider.mjs";
11
11
  import { useFocusDictionary } from "./FocusDictionaryContext.mjs";
12
12
  import { useFocusUnmergedDictionary } from "./useFocusUnmergedDictionary.mjs";
13
+ import { FRAME_CONNECTION_TIMEOUT_MS, useFrameConnectionStatus } from "./useFrameConnectionStatus.mjs";
13
14
  import { MessageKey } from "@intlayer/editor";
14
15
 
15
- export { EditorProvider, EditorStateProvider, MessageKey, useConfiguration, useCrossFrameState, useCrossURLPathState, useDictionariesRecord, useDictionariesRecordActions, useEditedContent, useEditedContentActions, useEditedContentPersistence, useEditorEnabled, useEditorLocale, useEditorPingClient, useEditorStateManager, useFocusDictionary, useFocusUnmergedDictionary };
16
+ export { EditorProvider, EditorStateProvider, FRAME_CONNECTION_TIMEOUT_MS, MessageKey, useConfiguration, useCrossFrameState, useCrossURLPathState, useDictionariesRecord, useDictionariesRecordActions, useEditedContent, useEditedContentActions, useEditedContentPersistence, useEditorEnabled, useEditorLocale, useEditorPingClient, useEditorStateManager, useFocusDictionary, useFocusUnmergedDictionary, useFrameConnectionStatus };
@@ -0,0 +1,42 @@
1
+ 'use client';
2
+
3
+ import { useEditorEnabled } from "./EditorEnabledContext.mjs";
4
+ import { useCallback, useEffect, useState } from "react";
5
+
6
+ //#region src/useFrameConnectionStatus.ts
7
+ /** Delay after a frame load before an unanswered handshake counts as failed. */
8
+ const FRAME_CONNECTION_TIMEOUT_MS = 5e3;
9
+ /**
10
+ * Detects an application frame that never connects to the editor.
11
+ * A frame blocked by the application's framing policy still fires `load` on
12
+ * an empty error page that the parent cannot inspect, so the missing
13
+ * handshake is the only signal available.
14
+ */
15
+ const useFrameConnectionStatus = (timeoutMs = FRAME_CONNECTION_TIMEOUT_MS) => {
16
+ const { enabled } = useEditorEnabled();
17
+ const [loadCount, setLoadCount] = useState(0);
18
+ const [isTimedOut, setIsTimedOut] = useState(false);
19
+ useEffect(() => {
20
+ if (enabled || loadCount === 0) return;
21
+ const timeout = setTimeout(() => setIsTimedOut(true), timeoutMs);
22
+ return () => clearTimeout(timeout);
23
+ }, [
24
+ enabled,
25
+ loadCount,
26
+ timeoutMs
27
+ ]);
28
+ const handleFrameLoad = useCallback(() => {
29
+ setIsTimedOut(false);
30
+ setLoadCount((count) => count + 1);
31
+ }, []);
32
+ const dismiss = useCallback(() => setIsTimedOut(false), []);
33
+ return {
34
+ isConnectionFailed: isTimedOut && !enabled,
35
+ handleFrameLoad,
36
+ dismiss
37
+ };
38
+ };
39
+
40
+ //#endregion
41
+ export { FRAME_CONNECTION_TIMEOUT_MS, useFrameConnectionStatus };
42
+ //# sourceMappingURL=useFrameConnectionStatus.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFrameConnectionStatus.mjs","names":[],"sources":["../../src/useFrameConnectionStatus.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useState } from 'react';\nimport { useEditorEnabled } from './EditorEnabledContext';\n\n/** Delay after a frame load before an unanswered handshake counts as failed. */\nexport const FRAME_CONNECTION_TIMEOUT_MS = 5_000;\n\nexport type FrameConnectionStatus = {\n /**\n * The frame loaded but its client never answered the handshake: the page\n * refused to be framed (CSP `frame-ancestors`, `X-Frame-Options`), or it\n * does not run the editor client.\n */\n isConnectionFailed: boolean;\n /** To call on every `load` event of the application frame. */\n handleFrameLoad: () => void;\n /** Hides the failure until the next load. */\n dismiss: () => void;\n};\n\n/**\n * Detects an application frame that never connects to the editor.\n * A frame blocked by the application's framing policy still fires `load` on\n * an empty error page that the parent cannot inspect, so the missing\n * handshake is the only signal available.\n */\nexport const useFrameConnectionStatus = (\n timeoutMs: number = FRAME_CONNECTION_TIMEOUT_MS\n): FrameConnectionStatus => {\n const { enabled } = useEditorEnabled();\n const [loadCount, setLoadCount] = useState(0);\n const [isTimedOut, setIsTimedOut] = useState(false);\n\n useEffect(() => {\n if (enabled || loadCount === 0) return;\n\n const timeout = setTimeout(() => setIsTimedOut(true), timeoutMs);\n\n return () => clearTimeout(timeout);\n }, [enabled, loadCount, timeoutMs]);\n\n const handleFrameLoad = useCallback(() => {\n setIsTimedOut(false);\n setLoadCount((count) => count + 1);\n }, []);\n\n const dismiss = useCallback(() => setIsTimedOut(false), []);\n\n return {\n isConnectionFailed: isTimedOut && !enabled,\n handleFrameLoad,\n dismiss,\n };\n};\n"],"mappings":";;;;;;;AAMA,MAAa,8BAA8B;;;;;;;AAqB3C,MAAa,4BACX,YAAoB,gCACM;CAC1B,MAAM,EAAE,YAAY,iBAAiB;CACrC,MAAM,CAAC,WAAW,gBAAgB,SAAS,CAAC;CAC5C,MAAM,CAAC,YAAY,iBAAiB,SAAS,KAAK;CAElD,gBAAgB;EACd,IAAI,WAAW,cAAc,GAAG;EAEhC,MAAM,UAAU,iBAAiB,cAAc,IAAI,GAAG,SAAS;EAE/D,aAAa,aAAa,OAAO;CACnC,GAAG;EAAC;EAAS;EAAW;CAAS,CAAC;CAElC,MAAM,kBAAkB,kBAAkB;EACxC,cAAc,KAAK;EACnB,cAAc,UAAU,QAAQ,CAAC;CACnC,GAAG,CAAC,CAAC;CAEL,MAAM,UAAU,kBAAkB,cAAc,KAAK,GAAG,CAAC,CAAC;CAE1D,OAAO;EACL,oBAAoB,cAAc,CAAC;EACnC;EACA;CACF;AACF"}
@@ -12,6 +12,10 @@ type EditedContentActionsContextType = {
12
12
  restoreEditedContent: (localDictionaryId: LocalDictionaryId) => void;
13
13
  getEditedContentValue: (localDictionaryIdOrKey: LocalDictionaryId | Dictionary['key'] | string, keyPath: KeyPath[]) => ContentNode | undefined;
14
14
  };
15
+ /**
16
+ * Returns the edited content actions. Memoized on the manager so they can be
17
+ * used as effect dependencies without a compiler.
18
+ */
15
19
  export declare const useEditedContentActions: () => EditedContentActionsContextType;
16
20
  export declare const useEditedContent: () => {
17
21
  setEditedContentState: (editedContent: DictionaryContent$1) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"EditedContentContext.d.ts","names":[],"sources":["../../src/EditedContentContext.tsx"],"mappings":";;;;KAcK;EACH,wBAAwB,eAAe;EACvC,sBAAsB,MAAM;EAC5B,mBACE,mBAAmB,mBACnB,UAAU;EAEZ,mBACE,mBAAmB,mBACnB,UAAU,kBACV,UAAU,WACV;EAEF,sBACE,mBAAmB,mBACnB,QAAQ,gBACR,UAAU;EAEZ,sBACE,mBAAmB,mBACnB,SAAS;EAEX,uBAAuB,mBAAmB;EAC1C,wBACE,wBAAwB,oBAAoB,4BAC5C,SAAS,cACN;;qBAGM,+BAA8B;qBAwB9B;EApDY,wBAAC,eAAe;EAClB,sBAAC,MAAM;EACV,mBAChB,mBAAmB,mBACnB,UAAU;EAEM,mBAChB,mBAAmB,mBACnB,UAAU,kBACV,UAAU,WACV;EAEmB,sBACnB,mBAAmB,mBACnB,QAAQ,gBACR,UAAU;EAES,sBACnB,mBAAmB,mBACnB,SAAS;EAEW,uBAAC,mBAAmB;EACnB,wBACrB,wBAAwB,oBAAoB,4BAC5C,SAAS,cACN"}
1
+ {"version":3,"file":"EditedContentContext.d.ts","names":[],"sources":["../../src/EditedContentContext.tsx"],"mappings":";;;;KAcK;EACH,wBAAwB,eAAe;EACvC,sBAAsB,MAAM;EAC5B,mBACE,mBAAmB,mBACnB,UAAU;EAEZ,mBACE,mBAAmB,mBACnB,UAAU,kBACV,UAAU,WACV;EAEF,sBACE,mBAAmB,mBACnB,QAAQ,gBACR,UAAU;EAEZ,sBACE,mBAAmB,mBACnB,SAAS;EAEX,uBAAuB,mBAAmB;EAC1C,wBACE,wBAAwB,oBAAoB,4BAC5C,SAAS,cACN;;;;;;qBAOM,+BAA8B;qBA2B9B;EA3DY,wBAAC,eAAe;EAClB,sBAAC,MAAM;EACV,mBAChB,mBAAmB,mBACnB,UAAU;EAEM,mBAChB,mBAAmB,mBACnB,UAAU,kBACV,UAAU,WACV;EAEmB,sBACnB,mBAAmB,mBACnB,QAAQ,gBACR,UAAU;EAES,sBACnB,mBAAmB,mBACnB,SAAS;EAEW,uBAAC,mBAAmB;EACnB,wBACrB,wBAAwB,oBAAoB,4BAC5C,SAAS,cACN"}
@@ -10,5 +10,6 @@ import { useCrossURLPathState } from "./useCrossURLPathState.js";
10
10
  import { useEditedContentPersistence } from "./useEditedContentPersistence.js";
11
11
  import { useEditorLocale } from "./useEditorLocale.js";
12
12
  import { useFocusUnmergedDictionary } from "./useFocusUnmergedDictionary.js";
13
+ import { FRAME_CONNECTION_TIMEOUT_MS, FrameConnectionStatus, useFrameConnectionStatus } from "./useFrameConnectionStatus.js";
13
14
  import { MessageKey } from "@intlayer/editor";
14
- export { EditorEnabledStateProps, EditorProvider, EditorProviderProps, EditorStateProvider, type FileContent, FocusDictionaryActions, MessageKey, useConfiguration, useCrossFrameState, useCrossURLPathState, useDictionariesRecord, useDictionariesRecordActions, useEditedContent, useEditedContentActions, useEditedContentPersistence, useEditorEnabled, useEditorLocale, useEditorPingClient, useEditorStateManager, useFocusDictionary, useFocusUnmergedDictionary };
15
+ export { EditorEnabledStateProps, EditorProvider, EditorProviderProps, EditorStateProvider, FRAME_CONNECTION_TIMEOUT_MS, type FileContent, FocusDictionaryActions, FrameConnectionStatus, MessageKey, useConfiguration, useCrossFrameState, useCrossURLPathState, useDictionariesRecord, useDictionariesRecordActions, useEditedContent, useEditedContentActions, useEditedContentPersistence, useEditorEnabled, useEditorLocale, useEditorPingClient, useEditorStateManager, useFocusDictionary, useFocusUnmergedDictionary, useFrameConnectionStatus };
@@ -0,0 +1,24 @@
1
+ //#region src/useFrameConnectionStatus.d.ts
2
+ /** Delay after a frame load before an unanswered handshake counts as failed. */
3
+ export declare const FRAME_CONNECTION_TIMEOUT_MS = 5000;
4
+ export type FrameConnectionStatus = {
5
+ /**
6
+ * The frame loaded but its client never answered the handshake: the page
7
+ * refused to be framed (CSP `frame-ancestors`, `X-Frame-Options`), or it
8
+ * does not run the editor client.
9
+ */
10
+ isConnectionFailed: boolean;
11
+ /** To call on every `load` event of the application frame. */
12
+ handleFrameLoad: () => void;
13
+ /** Hides the failure until the next load. */
14
+ dismiss: () => void;
15
+ };
16
+ /**
17
+ * Detects an application frame that never connects to the editor.
18
+ * A frame blocked by the application's framing policy still fires `load` on
19
+ * an empty error page that the parent cannot inspect, so the missing
20
+ * handshake is the only signal available.
21
+ */
22
+ export declare const useFrameConnectionStatus: (timeoutMs?: number) => FrameConnectionStatus;
23
+ //#endregion
24
+ //# sourceMappingURL=useFrameConnectionStatus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFrameConnectionStatus.d.ts","names":[],"sources":["../../src/useFrameConnectionStatus.ts"],"mappings":";;qBAMa;YAED;;;;;;EAMV;;EAEA;;EAEA;;;;;;;;qBASW,2BAAwB,uBAElC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intlayer/editor-react",
3
- "version": "9.6.0",
3
+ "version": "9.7.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,13 +71,13 @@
71
71
  "typecheck": "tsc --noEmit --project tsconfig.types.json"
72
72
  },
73
73
  "dependencies": {
74
- "@intlayer/config": "9.6.0",
75
- "@intlayer/core": "9.6.0",
76
- "@intlayer/editor": "9.6.0",
77
- "@intlayer/types": "9.6.0"
74
+ "@intlayer/config": "9.7.0",
75
+ "@intlayer/core": "9.7.0",
76
+ "@intlayer/editor": "9.7.0",
77
+ "@intlayer/types": "9.7.0"
78
78
  },
79
79
  "devDependencies": {
80
- "@types/node": "^22",
80
+ "@types/node": "^26",
81
81
  "@types/react": ">=16.0.0",
82
82
  "@types/react-dom": ">=16.0.0",
83
83
  "@utils/ts-config": "1.0.4",