@intlayer/editor 8.11.0 → 8.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/EditedContent.cjs +0 -1
- package/dist/cjs/components/EditedContent.cjs.map +1 -1
- package/dist/cjs/core/EditorStateManager.cjs.map +1 -1
- package/dist/cjs/core/initEditorClient.cjs +1 -3
- package/dist/cjs/core/initEditorClient.cjs.map +1 -1
- package/dist/cjs/isEnabled.cjs +0 -1
- package/dist/cjs/isEnabled.cjs.map +1 -1
- package/dist/esm/core/EditorStateManager.mjs.map +1 -1
- package/dist/esm/core/initEditorClient.mjs +2 -2
- package/dist/esm/core/initEditorClient.mjs.map +1 -1
- package/dist/types/core/EditorStateManager.d.ts +3 -2
- package/dist/types/core/EditorStateManager.d.ts.map +1 -1
- package/package.json +6 -6
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
3
2
|
const require_core_globalManager = require('../core/globalManager.cjs');
|
|
4
3
|
let _intlayer_core_interpreter = require("@intlayer/core/interpreter");
|
|
5
4
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditedContent.cjs","names":["getGlobalEditorManager","onGlobalEditorManagerChange"],"sources":["../../../src/components/EditedContent.ts"],"sourcesContent":["import { getBasePlugins, getContent } from '@intlayer/core/interpreter';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport type { EditorStateManager } from '../core/EditorStateManager';\nimport {\n getGlobalEditorManager,\n onGlobalEditorManagerChange,\n} from '../core/globalManager';\n\nconst _HTMLElement =\n typeof HTMLElement !== 'undefined'\n ? HTMLElement\n : (class {} as unknown as typeof HTMLElement);\n\n/**\n * <intlayer-edited-content>\n *\n * Framework-agnostic web component that displays edited content from the Intlayer\n * editor. When the editor has an edited value for the given dictionary key and\n * key path, it renders the edited value; otherwise it renders the original\n * content via a slot.\n *\n * Always wraps content in <intlayer-content-selector-wrapper> for selection UI.\n *\n * @attr {string} dictionary-key - The dictionary key owning this content node\n * @attr {string} key-path - JSON-serialized KeyPath[] for this content node\n * @attr {string} locale - The current locale string\n */\nexport class IntlayerEditedContentElement extends _HTMLElement {\n private _dictionaryKey = '';\n private _keyPathJson = '[]';\n private _locale = '';\n private _editedText: string | null = null;\n\n private _unsubManager: (() => void) | null = null;\n private _unsubEditedContent: (() => void) | null = null;\n\n private _selectorWrapper: HTMLElement;\n private _slot: HTMLSlotElement;\n\n static get observedAttributes(): string[] {\n return ['dictionary-key', 'key-path', 'locale'];\n }\n\n get dictionaryKey(): string {\n return this._dictionaryKey;\n }\n set dictionaryKey(v: string) {\n this._dictionaryKey = v;\n this._selectorWrapper.setAttribute('dictionary-key', v);\n }\n\n get keyPathJson(): string {\n return this._keyPathJson;\n }\n set keyPathJson(v: string) {\n this._keyPathJson = v;\n this._selectorWrapper.setAttribute('key-path', v);\n }\n\n get locale(): string {\n return this._locale;\n }\n set locale(v: string) {\n this._locale = v;\n }\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = ':host { display: contents; }';\n shadow.appendChild(style);\n\n this._selectorWrapper = document.createElement(\n 'intlayer-content-selector-wrapper'\n );\n this._slot = document.createElement('slot') as HTMLSlotElement;\n this._selectorWrapper.appendChild(this._slot);\n shadow.appendChild(this._selectorWrapper);\n }\n\n attributeChangedCallback(\n name: string,\n _oldVal: string | null,\n newVal: string | null\n ): void {\n const val = newVal ?? '';\n if (name === 'dictionary-key') {\n this._dictionaryKey = val;\n this._selectorWrapper.setAttribute('dictionary-key', val);\n } else if (name === 'key-path') {\n this._keyPathJson = val || '[]';\n this._selectorWrapper.setAttribute('key-path', this._keyPathJson);\n } else if (name === 'locale') {\n this._locale = val;\n }\n }\n\n connectedCallback(): void {\n this._subscribeToManager();\n }\n\n disconnectedCallback(): void {\n this._teardown();\n }\n\n private _teardown(): void {\n this._unsubManager?.();\n this._unsubEditedContent?.();\n this._unsubManager = null;\n this._unsubEditedContent = null;\n }\n\n private _getKeyPath(): KeyPath[] {\n try {\n return JSON.parse(this._keyPathJson);\n } catch {\n return [];\n }\n }\n\n private _render(): void {\n while (this._selectorWrapper.firstChild) {\n this._selectorWrapper.removeChild(this._selectorWrapper.firstChild);\n }\n if (this._editedText !== null) {\n this._selectorWrapper.appendChild(\n document.createTextNode(this._editedText)\n );\n } else {\n this._selectorWrapper.appendChild(this._slot);\n }\n }\n\n private _resolveEditedText(manager: EditorStateManager): void {\n const keyPath = this._getKeyPath();\n const editedValue = manager.getContentValue(this._dictionaryKey, keyPath);\n\n if (editedValue === undefined || editedValue === null) {\n this._editedText = null;\n this._render();\n return;\n }\n\n if (typeof editedValue === 'string' || typeof editedValue === 'number') {\n this._editedText = String(editedValue);\n this._render();\n return;\n }\n\n if (typeof editedValue === 'object') {\n const locale = this._locale || undefined;\n const transformed = getContent(\n editedValue,\n {\n locale: locale as any,\n dictionaryKey: this._dictionaryKey,\n keyPath,\n },\n getBasePlugins(locale)\n );\n if (typeof transformed === 'string' || typeof transformed === 'number') {\n this._editedText = String(transformed);\n } else {\n console.error(\n `[intlayer-edited-content] Incorrect edited content format. Expected string. Value: ${JSON.stringify(transformed)}`\n );\n this._editedText = null;\n }\n this._render();\n return;\n }\n\n this._editedText = null;\n this._render();\n }\n\n private _setupManagerSubscriptions(manager: EditorStateManager): void {\n this._resolveEditedText(manager);\n\n const handleChange = () => this._resolveEditedText(manager);\n manager.editedContent.addEventListener('change', handleChange);\n\n this._unsubEditedContent = () =>\n manager.editedContent.removeEventListener('change', handleChange);\n }\n\n private _subscribeToManager(): void {\n const manager = getGlobalEditorManager();\n if (manager) {\n this._setupManagerSubscriptions(manager);\n }\n\n this._unsubManager = onGlobalEditorManagerChange((m) => {\n this._unsubEditedContent?.();\n this._unsubEditedContent = null;\n if (m) {\n this._setupManagerSubscriptions(m);\n } else {\n this._editedText = null;\n this._render();\n }\n });\n }\n}\n\nexport const defineIntlayerEditedContent = (): void => {\n if (typeof customElements === 'undefined') return;\n\n if (!customElements.get('intlayer-edited-content')) {\n customElements.define(\n 'intlayer-edited-content',\n IntlayerEditedContentElement\n );\n }\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"EditedContent.cjs","names":["getGlobalEditorManager","onGlobalEditorManagerChange"],"sources":["../../../src/components/EditedContent.ts"],"sourcesContent":["import { getBasePlugins, getContent } from '@intlayer/core/interpreter';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport type { EditorStateManager } from '../core/EditorStateManager';\nimport {\n getGlobalEditorManager,\n onGlobalEditorManagerChange,\n} from '../core/globalManager';\n\nconst _HTMLElement =\n typeof HTMLElement !== 'undefined'\n ? HTMLElement\n : (class {} as unknown as typeof HTMLElement);\n\n/**\n * <intlayer-edited-content>\n *\n * Framework-agnostic web component that displays edited content from the Intlayer\n * editor. When the editor has an edited value for the given dictionary key and\n * key path, it renders the edited value; otherwise it renders the original\n * content via a slot.\n *\n * Always wraps content in <intlayer-content-selector-wrapper> for selection UI.\n *\n * @attr {string} dictionary-key - The dictionary key owning this content node\n * @attr {string} key-path - JSON-serialized KeyPath[] for this content node\n * @attr {string} locale - The current locale string\n */\nexport class IntlayerEditedContentElement extends _HTMLElement {\n private _dictionaryKey = '';\n private _keyPathJson = '[]';\n private _locale = '';\n private _editedText: string | null = null;\n\n private _unsubManager: (() => void) | null = null;\n private _unsubEditedContent: (() => void) | null = null;\n\n private _selectorWrapper: HTMLElement;\n private _slot: HTMLSlotElement;\n\n static get observedAttributes(): string[] {\n return ['dictionary-key', 'key-path', 'locale'];\n }\n\n get dictionaryKey(): string {\n return this._dictionaryKey;\n }\n set dictionaryKey(v: string) {\n this._dictionaryKey = v;\n this._selectorWrapper.setAttribute('dictionary-key', v);\n }\n\n get keyPathJson(): string {\n return this._keyPathJson;\n }\n set keyPathJson(v: string) {\n this._keyPathJson = v;\n this._selectorWrapper.setAttribute('key-path', v);\n }\n\n get locale(): string {\n return this._locale;\n }\n set locale(v: string) {\n this._locale = v;\n }\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = ':host { display: contents; }';\n shadow.appendChild(style);\n\n this._selectorWrapper = document.createElement(\n 'intlayer-content-selector-wrapper'\n );\n this._slot = document.createElement('slot') as HTMLSlotElement;\n this._selectorWrapper.appendChild(this._slot);\n shadow.appendChild(this._selectorWrapper);\n }\n\n attributeChangedCallback(\n name: string,\n _oldVal: string | null,\n newVal: string | null\n ): void {\n const val = newVal ?? '';\n if (name === 'dictionary-key') {\n this._dictionaryKey = val;\n this._selectorWrapper.setAttribute('dictionary-key', val);\n } else if (name === 'key-path') {\n this._keyPathJson = val || '[]';\n this._selectorWrapper.setAttribute('key-path', this._keyPathJson);\n } else if (name === 'locale') {\n this._locale = val;\n }\n }\n\n connectedCallback(): void {\n this._subscribeToManager();\n }\n\n disconnectedCallback(): void {\n this._teardown();\n }\n\n private _teardown(): void {\n this._unsubManager?.();\n this._unsubEditedContent?.();\n this._unsubManager = null;\n this._unsubEditedContent = null;\n }\n\n private _getKeyPath(): KeyPath[] {\n try {\n return JSON.parse(this._keyPathJson);\n } catch {\n return [];\n }\n }\n\n private _render(): void {\n while (this._selectorWrapper.firstChild) {\n this._selectorWrapper.removeChild(this._selectorWrapper.firstChild);\n }\n if (this._editedText !== null) {\n this._selectorWrapper.appendChild(\n document.createTextNode(this._editedText)\n );\n } else {\n this._selectorWrapper.appendChild(this._slot);\n }\n }\n\n private _resolveEditedText(manager: EditorStateManager): void {\n const keyPath = this._getKeyPath();\n const editedValue = manager.getContentValue(this._dictionaryKey, keyPath);\n\n if (editedValue === undefined || editedValue === null) {\n this._editedText = null;\n this._render();\n return;\n }\n\n if (typeof editedValue === 'string' || typeof editedValue === 'number') {\n this._editedText = String(editedValue);\n this._render();\n return;\n }\n\n if (typeof editedValue === 'object') {\n const locale = this._locale || undefined;\n const transformed = getContent(\n editedValue,\n {\n locale: locale as any,\n dictionaryKey: this._dictionaryKey,\n keyPath,\n },\n getBasePlugins(locale)\n );\n if (typeof transformed === 'string' || typeof transformed === 'number') {\n this._editedText = String(transformed);\n } else {\n console.error(\n `[intlayer-edited-content] Incorrect edited content format. Expected string. Value: ${JSON.stringify(transformed)}`\n );\n this._editedText = null;\n }\n this._render();\n return;\n }\n\n this._editedText = null;\n this._render();\n }\n\n private _setupManagerSubscriptions(manager: EditorStateManager): void {\n this._resolveEditedText(manager);\n\n const handleChange = () => this._resolveEditedText(manager);\n manager.editedContent.addEventListener('change', handleChange);\n\n this._unsubEditedContent = () =>\n manager.editedContent.removeEventListener('change', handleChange);\n }\n\n private _subscribeToManager(): void {\n const manager = getGlobalEditorManager();\n if (manager) {\n this._setupManagerSubscriptions(manager);\n }\n\n this._unsubManager = onGlobalEditorManagerChange((m) => {\n this._unsubEditedContent?.();\n this._unsubEditedContent = null;\n if (m) {\n this._setupManagerSubscriptions(m);\n } else {\n this._editedText = null;\n this._render();\n }\n });\n }\n}\n\nexport const defineIntlayerEditedContent = (): void => {\n if (typeof customElements === 'undefined') return;\n\n if (!customElements.get('intlayer-edited-content')) {\n customElements.define(\n 'intlayer-edited-content',\n IntlayerEditedContentElement\n );\n }\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorStateManager.cjs","names":["CrossFrameMessenger","CrossFrameStateManager","UrlStateManager","IframeClickInterceptor","NodeTypes","subscribeToGlobalEditedContent","getGlobalEditedContent","subscribeToGlobalFocusedContent","getGlobalFocusedContent"],"sources":["../../../src/core/EditorStateManager.ts"],"sourcesContent":["import {\n editDictionaryByKeyPath,\n getContentNodeByKeyPath,\n renameContentNodeByKeyPath,\n} from '@intlayer/core/dictionaryManipulator';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type {\n ContentNode,\n Dictionary,\n LocalDictionaryId,\n} from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { MessageKey } from '../messageKey';\nimport {\n CrossFrameMessenger,\n type MessengerConfig,\n} from './CrossFrameMessenger';\nimport { CrossFrameStateManager } from './CrossFrameStateManager';\nimport {\n getGlobalEditedContent,\n setGlobalEditedContent,\n subscribeToGlobalEditedContent,\n} from './editedContentBus';\nimport {\n getGlobalFocusedContent,\n setGlobalFocusedContent,\n subscribeToGlobalFocusedContent,\n} from './focusedContentBus';\nimport { IframeClickInterceptor } from './IframeClickInterceptor';\nimport { UrlStateManager } from './UrlStateManager';\n\nexport type DictionaryContent = Record<LocalDictionaryId, Dictionary>;\n\nexport type FileContent = {\n dictionaryKey: string;\n dictionaryLocalId?: LocalDictionaryId;\n keyPath?: KeyPath[];\n};\n\nexport type EditorStateManagerConfig = {\n /** 'client' = the app running inside the iframe; 'editor' = the editor wrapping the app */\n mode: 'editor' | 'client';\n /** Cross-frame messaging configuration */\n messenger: MessengerConfig;\n /** Optional initial Intlayer configuration to broadcast */\n configuration?: IntlayerConfig;\n};\n\n/**\n * EditorStateManager is the single entry point for all Intlayer editor state.\n * It is framework-agnostic: instantiate one instance at the root of the application\n * and subscribe to its EventTarget-based events from any framework adapter.\n *\n * Replaces all context providers, hooks and store files across React, Preact,\n * Solid, Svelte, and Vue integrations.\n */\nexport class EditorStateManager {\n readonly messenger: CrossFrameMessenger;\n readonly editorEnabled: CrossFrameStateManager<boolean>;\n readonly focusedContent: CrossFrameStateManager<FileContent | null>;\n readonly localeDictionaries: CrossFrameStateManager<DictionaryContent>;\n readonly editedContent: CrossFrameStateManager<DictionaryContent>;\n readonly configuration: CrossFrameStateManager<IntlayerConfig>;\n readonly currentLocale: CrossFrameStateManager<Locale | undefined>;\n readonly displayedDictionaryKeys: CrossFrameStateManager<string[]>;\n\n private readonly _urlManager: UrlStateManager;\n private readonly _iframeInterceptor: IframeClickInterceptor;\n private readonly _mode: 'editor' | 'client';\n private readonly _configuration: IntlayerConfig | undefined;\n\n // Client-mode handshake subscribers\n private _unsubAreYouThere: (() => void) | null = null;\n private _unsubActivate: (() => void) | null = null;\n // Editor-mode handshake subscriber\n private _unsubClientReady: (() => void) | null = null;\n\n // Client-mode displayed-keys tracking\n private _displayedKeysObserver: MutationObserver | null = null;\n private _displayedKeysTimer: ReturnType<typeof setTimeout> | null = null;\n private _displayedKeysListeners: Array<[string, EventListener]> = [];\n\n // Global editedContent bus sync\n private _editedContentFromBus = false;\n private _unsubGlobalEditedContent: (() => void) | null = null;\n private _editedContentBusHandler: ((e: Event) => void) | null = null;\n\n // Global focusedContent bus sync\n private _focusedContentFromBus = false;\n private _unsubGlobalFocusedContent: (() => void) | null = null;\n private _focusedContentBusHandler: ((e: Event) => void) | null = null;\n\n constructor(config: EditorStateManagerConfig) {\n this._mode = config.mode;\n this._configuration = config.configuration;\n\n this.messenger = new CrossFrameMessenger(config.messenger);\n\n this.editorEnabled = new CrossFrameStateManager<boolean>(\n MessageKey.INTLAYER_EDITOR_ENABLED,\n this.messenger,\n { emit: false, receive: true, initialValue: false }\n );\n\n this.focusedContent = new CrossFrameStateManager<FileContent | null>(\n MessageKey.INTLAYER_FOCUSED_CONTENT_CHANGED,\n this.messenger,\n { emit: true, receive: true, initialValue: null }\n );\n\n this.localeDictionaries = new CrossFrameStateManager<DictionaryContent>(\n MessageKey.INTLAYER_LOCALE_DICTIONARIES_CHANGED,\n this.messenger\n );\n\n this.editedContent = new CrossFrameStateManager<DictionaryContent>(\n MessageKey.INTLAYER_EDITED_CONTENT_CHANGED,\n this.messenger\n );\n\n this.configuration = new CrossFrameStateManager<IntlayerConfig>(\n MessageKey.INTLAYER_CONFIGURATION,\n this.messenger,\n {\n emit: true,\n receive: false,\n ...(config.configuration ? { initialValue: config.configuration } : {}),\n }\n );\n\n // Client emits its locale to the editor; editor receives it.\n this.currentLocale = new CrossFrameStateManager<Locale>(\n MessageKey.INTLAYER_CURRENT_LOCALE,\n this.messenger,\n {\n emit: config.mode === 'client',\n receive: config.mode === 'editor',\n }\n );\n\n // Client emits displayed dictionary keys; editor receives them.\n this.displayedDictionaryKeys = new CrossFrameStateManager<string[]>(\n MessageKey.INTLAYER_DISPLAYED_DICTIONARY_KEYS,\n this.messenger,\n {\n emit: config.mode === 'client',\n receive: config.mode === 'editor',\n initialValue: [],\n }\n );\n\n this._urlManager = new UrlStateManager(this.messenger);\n this._iframeInterceptor = new IframeClickInterceptor(this.messenger);\n }\n\n start(): void {\n this.messenger.start();\n this.editorEnabled.start();\n this.focusedContent.start();\n this.localeDictionaries.start();\n this.editedContent.start();\n this.configuration.start();\n this.currentLocale.start();\n this.displayedDictionaryKeys.start();\n this._startEditedContentBusSync();\n this._startFocusedContentBusSync();\n\n if (this._mode === 'client') {\n this._urlManager.start();\n this._iframeInterceptor.startInterceptor();\n this._loadDictionaries();\n this._startDisplayedDictionariesTracking();\n // Request current edited content from the editor\n this.messenger.send(`${MessageKey.INTLAYER_EDITED_CONTENT_CHANGED}/get`);\n // Activation handshake: only participate if editor.enabled !== false\n if (this._configuration?.editor?.enabled !== false) {\n this._setupActivationHandshake();\n }\n } else {\n this._iframeInterceptor.startMerger();\n this._setupEditorHandshake();\n }\n }\n\n stop(): void {\n this._unsubAreYouThere?.();\n this._unsubActivate?.();\n this._unsubClientReady?.();\n this._unsubAreYouThere = null;\n this._unsubActivate = null;\n this._unsubClientReady = null;\n this.messenger.stop();\n this.editorEnabled.stop();\n this.focusedContent.stop();\n this.localeDictionaries.stop();\n this.editedContent.stop();\n this.configuration.stop();\n this.currentLocale.stop();\n this.displayedDictionaryKeys.stop();\n this._stopDisplayedDictionariesTracking();\n this._stopEditedContentBusSync();\n this._stopFocusedContentBusSync();\n this._urlManager.stop();\n this._iframeInterceptor.stopInterceptor();\n this._iframeInterceptor.stopMerger();\n }\n\n // ─── Handshake helpers ───────────────────────────────────────────────────────\n\n /**\n * EDITOR mode: re-send ARE_YOU_THERE to attempt re-connection with the client.\n * Call this when the user clicks \"Enable Editor\" or when the iframe reloads.\n */\n pingClient(): void {\n if (this._mode !== 'editor') return;\n\n this.messenger.send(MessageKey.INTLAYER_ARE_YOU_THERE);\n }\n\n // ─── Focus helpers ──────────────────────────────────────────────────────────\n\n setFocusedContentKeyPath(keyPath: KeyPath[]): void {\n const filtered = keyPath.filter(\n (key) => key.type !== NodeTypes.TRANSLATION\n );\n const prev = this.focusedContent.value;\n\n if (!prev) return;\n\n this.focusedContent.set({ ...prev, keyPath: filtered });\n }\n\n // ─── Dictionary record helpers ───────────────────────────────────────────\n\n setLocaleDictionary(dictionary: Dictionary): void {\n if (!dictionary.localId) return;\n const current = this.localeDictionaries.value ?? {};\n\n this.localeDictionaries.set({\n ...current,\n [dictionary.localId as LocalDictionaryId]: dictionary,\n });\n }\n\n // ─── Edited content helpers ───────────────────────────────────────────────\n\n setEditedDictionary(newDict: Dictionary): void {\n if (!newDict.localId) {\n console.error('setEditedDictionary: missing localId', newDict);\n return;\n }\n const current = this.editedContent.value ?? {};\n\n this.editedContent.set({\n ...current,\n [newDict.localId as LocalDictionaryId]: newDict,\n });\n }\n\n setEditedContent(\n localDictionaryId: LocalDictionaryId,\n newValue: Dictionary['content']\n ): void {\n const current = this.editedContent.value ?? {};\n\n this.editedContent.set({\n ...current,\n [localDictionaryId]: {\n ...current[localDictionaryId],\n content: newValue,\n },\n });\n }\n\n addContent(\n localDictionaryId: LocalDictionaryId,\n newValue: ContentNode,\n keyPath: KeyPath[] = [],\n overwrite = true\n ): void {\n const current = this.editedContent.value ?? {};\n const localeDicts = this.localeDictionaries.value ?? {};\n\n const originalContent = localeDicts[localDictionaryId]?.content;\n const currentContent = structuredClone(\n current[localDictionaryId]?.content ?? originalContent\n );\n\n let newKeyPath = keyPath;\n if (!overwrite) {\n let index = 0;\n\n const otherKeyPath = keyPath.slice(0, -1);\n const lastKeyPath = keyPath[keyPath.length - 1];\n\n let finalKey = lastKeyPath.key;\n\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 this.editedContent.set({\n ...current,\n [localDictionaryId]: {\n ...current[localDictionaryId],\n content: updatedContent as Dictionary['content'],\n },\n });\n }\n\n renameContent(\n localDictionaryId: LocalDictionaryId,\n newKey: KeyPath['key'],\n keyPath: KeyPath[] = []\n ): void {\n const current = this.editedContent.value ?? {};\n const localeDicts = this.localeDictionaries.value ?? {};\n const originalContent = localeDicts[localDictionaryId]?.content;\n const currentContent = structuredClone(\n current[localDictionaryId]?.content ?? originalContent\n );\n const updated = renameContentNodeByKeyPath(currentContent, newKey, keyPath);\n\n this.editedContent.set({\n ...current,\n [localDictionaryId]: {\n ...current[localDictionaryId],\n content: updated as Dictionary['content'],\n },\n });\n }\n\n removeContent(\n localDictionaryId: LocalDictionaryId,\n keyPath: KeyPath[]\n ): void {\n const current = this.editedContent.value ?? {};\n const localeDicts = this.localeDictionaries.value ?? {};\n const originalContent = localeDicts[localDictionaryId]?.content;\n const currentContent = structuredClone(\n current[localDictionaryId]?.content ?? originalContent\n );\n const initialContent = getContentNodeByKeyPath(originalContent, keyPath);\n const restored = editDictionaryByKeyPath(\n currentContent,\n keyPath,\n initialContent\n );\n\n this.editedContent.set({\n ...current,\n [localDictionaryId]: {\n ...current[localDictionaryId],\n content: restored as Dictionary['content'],\n },\n });\n }\n\n restoreContent(localDictionaryId: LocalDictionaryId): void {\n const current = this.editedContent.value ?? {};\n const updated = { ...current };\n\n delete updated[localDictionaryId];\n\n this.editedContent.set(updated);\n }\n\n clearContent(localDictionaryId: LocalDictionaryId): void {\n const current = this.editedContent.value ?? {};\n const filtered = { ...current };\n\n delete filtered[localDictionaryId];\n\n this.editedContent.set(filtered);\n }\n\n clearAllContent(): void {\n this.editedContent.set({});\n }\n\n getContentValue(\n localDictionaryIdOrKey: LocalDictionaryId | string,\n keyPath: KeyPath[]\n ): ContentNode | undefined {\n const edited = this.editedContent.value;\n if (!edited) return undefined;\n\n const filteredKeyPath = keyPath.filter(\n (key) => key.type !== NodeTypes.TRANSLATION\n );\n\n // Only use edited content entries whose localId is known to this client.\n // This prevents stale edits from other apps (different framework demos) from\n // being applied when the editor sends back its stored editedContent.\n const localeDicts = this.localeDictionaries.value;\n\n const isDictionaryId =\n localDictionaryIdOrKey.includes(':local:') ||\n localDictionaryIdOrKey.includes(':remote:');\n\n if (isDictionaryId) {\n // If localeDictionaries is loaded, verify this localId belongs to us\n if (localeDicts && !(localDictionaryIdOrKey in localeDicts)) {\n return undefined;\n }\n const content =\n edited[localDictionaryIdOrKey as LocalDictionaryId]?.content ?? {};\n\n return getContentNodeByKeyPath(\n content,\n filteredKeyPath,\n this.currentLocale.value\n );\n }\n\n const matchingIds = Object.keys(edited).filter(\n (key) =>\n key.startsWith(`${localDictionaryIdOrKey}:`) &&\n // If localeDictionaries is loaded, only include known localIds\n (!localeDicts || key in localeDicts)\n );\n\n for (const localId of matchingIds) {\n const content = edited[localId as LocalDictionaryId]?.content ?? {};\n const node = getContentNodeByKeyPath(\n content,\n filteredKeyPath,\n this.currentLocale.value\n );\n if (node) return node;\n }\n\n return undefined;\n }\n\n // ─── Global editedContent bus sync ───────────────────────────────────────\n\n private _startEditedContentBusSync(): void {\n // Push local changes to the global bus (loop-guarded)\n this._editedContentBusHandler = (e: Event) => {\n if (this._editedContentFromBus) return;\n const content = (e as CustomEvent<DictionaryContent>).detail;\n setGlobalEditedContent(content, this.messenger.senderId);\n };\n this.editedContent.addEventListener(\n 'change',\n this._editedContentBusHandler\n );\n\n // Receive bus changes from other managers\n this._unsubGlobalEditedContent = subscribeToGlobalEditedContent(\n (content, sourceId) => {\n if (sourceId === this.messenger.senderId) return;\n this._editedContentFromBus = true;\n this.editedContent.set(content);\n this._editedContentFromBus = false;\n }\n );\n\n // Seed local value from the bus if bus already has content\n const existing = getGlobalEditedContent();\n if (Object.keys(existing).length > 0) {\n this._editedContentFromBus = true;\n this.editedContent.set(existing);\n this._editedContentFromBus = false;\n }\n }\n\n private _stopEditedContentBusSync(): void {\n if (this._editedContentBusHandler) {\n this.editedContent.removeEventListener(\n 'change',\n this._editedContentBusHandler\n );\n this._editedContentBusHandler = null;\n }\n this._unsubGlobalEditedContent?.();\n this._unsubGlobalEditedContent = null;\n }\n\n // ─── Global focusedContent bus sync ──────────────────────────────────────\n\n private _startFocusedContentBusSync(): void {\n this._focusedContentBusHandler = (e: Event) => {\n if (this._focusedContentFromBus) return;\n const content = (e as CustomEvent<FileContent | null>).detail;\n setGlobalFocusedContent(content, this.messenger.senderId);\n };\n this.focusedContent.addEventListener(\n 'change',\n this._focusedContentBusHandler\n );\n\n this._unsubGlobalFocusedContent = subscribeToGlobalFocusedContent(\n (content, sourceId) => {\n if (sourceId === this.messenger.senderId) return;\n this._focusedContentFromBus = true;\n this.focusedContent.set(content);\n this._focusedContentFromBus = false;\n }\n );\n\n const existing = getGlobalFocusedContent();\n if (existing !== undefined) {\n this._focusedContentFromBus = true;\n this.focusedContent.set(existing);\n this._focusedContentFromBus = false;\n }\n }\n\n private _stopFocusedContentBusSync(): void {\n if (this._focusedContentBusHandler) {\n this.focusedContent.removeEventListener(\n 'change',\n this._focusedContentBusHandler\n );\n this._focusedContentBusHandler = null;\n }\n this._unsubGlobalFocusedContent?.();\n this._unsubGlobalFocusedContent = null;\n }\n\n // ─── Displayed dictionaries tracking (client mode only) ──────────────────\n\n private _scanDisplayedDictionaryKeys(): void {\n if (typeof document === 'undefined') return;\n const elements = document.querySelectorAll(\n 'intlayer-content-selector-wrapper[dictionary-key]'\n );\n const keys = Array.from(\n new Set(\n Array.from(elements)\n .map((el) => el.getAttribute('dictionary-key') ?? '')\n .filter(Boolean)\n )\n );\n this.displayedDictionaryKeys.set(keys);\n }\n\n private _startDisplayedDictionariesTracking(): void {\n if (\n typeof document === 'undefined' ||\n typeof MutationObserver === 'undefined'\n )\n return;\n\n const schedule = () => {\n if (this._displayedKeysTimer) clearTimeout(this._displayedKeysTimer);\n this._displayedKeysTimer = setTimeout(\n () => this._scanDisplayedDictionaryKeys(),\n 100\n );\n };\n\n this._displayedKeysObserver = new MutationObserver(schedule);\n this._displayedKeysObserver.observe(document.body, {\n childList: true,\n subtree: true,\n });\n\n for (const evt of ['locationchange', 'popstate'] as const) {\n const listener = schedule as EventListener;\n window.addEventListener(evt, listener);\n this._displayedKeysListeners.push([evt, listener]);\n }\n\n this._scanDisplayedDictionaryKeys();\n }\n\n private _stopDisplayedDictionariesTracking(): void {\n this._displayedKeysObserver?.disconnect();\n this._displayedKeysObserver = null;\n if (this._displayedKeysTimer) {\n clearTimeout(this._displayedKeysTimer);\n this._displayedKeysTimer = null;\n }\n for (const [evt, listener] of this._displayedKeysListeners) {\n window.removeEventListener(evt, listener);\n }\n this._displayedKeysListeners = [];\n }\n\n // ─── Handshake helpers ───────────────────────────────────────────────────────\n\n /**\n * EDITOR mode: listen for CLIENT_READY and respond with EDITOR_ACTIVATE.\n * Also pings the client immediately in case it loaded before the editor.\n */\n private _setupEditorHandshake(): void {\n // When the client announces it is ready, activate it\n this._unsubClientReady = this.messenger.subscribe(\n MessageKey.INTLAYER_CLIENT_READY,\n () => {\n this.editorEnabled.set(true);\n this.messenger.send(MessageKey.INTLAYER_EDITOR_ACTIVATE);\n }\n );\n\n // Ping any already-running client (covers editor-opens-after-client scenario)\n this.messenger.send(MessageKey.INTLAYER_ARE_YOU_THERE);\n }\n\n private _setupActivationHandshake(): void {\n // Announce to the editor that the client is ready\n this.messenger.send(MessageKey.INTLAYER_CLIENT_READY);\n\n // Respond to \"are you there?\" pings from the editor\n this._unsubAreYouThere = this.messenger.subscribe(\n MessageKey.INTLAYER_ARE_YOU_THERE,\n () => {\n this.messenger.send(MessageKey.INTLAYER_CLIENT_READY);\n }\n );\n\n // When the editor activates us, enable the selector and broadcast state\n this._unsubActivate = this.messenger.subscribe(\n MessageKey.INTLAYER_EDITOR_ACTIVATE,\n () => {\n this.editorEnabled.set(true);\n this._broadcastData();\n }\n );\n }\n\n private _broadcastData(): void {\n const configVal = this.configuration.value;\n\n if (configVal) {\n this.messenger.send(\n `${MessageKey.INTLAYER_CONFIGURATION}/post`,\n configVal\n );\n }\n const localeVal = this.currentLocale.value;\n\n if (localeVal) {\n this.messenger.send(\n `${MessageKey.INTLAYER_CURRENT_LOCALE}/post`,\n localeVal\n );\n }\n const dicts = this.localeDictionaries.value;\n\n if (dicts) {\n this.messenger.send(\n `${MessageKey.INTLAYER_LOCALE_DICTIONARIES_CHANGED}/post`,\n dicts\n );\n }\n }\n\n private async _loadDictionaries(): Promise<void> {\n try {\n const mod = await import('@intlayer/unmerged-dictionaries-entry');\n const unmergedDictionaries = mod.getUnmergedDictionaries();\n const dictionariesList = Object.fromEntries(\n Object.values(unmergedDictionaries)\n .flat()\n .map((dictionary) => [dictionary.localId, dictionary])\n ) as DictionaryContent;\n\n this.localeDictionaries.set(dictionariesList);\n\n // If the editor already activated us before dictionaries finished loading,\n // re-broadcast now so the editor receives the dictionaries.\n if (this.editorEnabled.value) {\n this._broadcastData();\n }\n } catch (e) {\n // Dynamic entry not available (expected in editor mode or when not configured)\n console.warn('[intlayer] Failed to load unmerged dictionaries:', e);\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EditorStateManager.cjs","names":["CrossFrameMessenger","CrossFrameStateManager","UrlStateManager","IframeClickInterceptor","NodeTypes","subscribeToGlobalEditedContent","getGlobalEditedContent","subscribeToGlobalFocusedContent","getGlobalFocusedContent"],"sources":["../../../src/core/EditorStateManager.ts"],"sourcesContent":["import {\n editDictionaryByKeyPath,\n getContentNodeByKeyPath,\n renameContentNodeByKeyPath,\n} from '@intlayer/core/dictionaryManipulator';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type {\n ContentNode,\n Dictionary,\n LocalDictionaryId,\n} from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { MessageKey } from '../messageKey';\nimport {\n CrossFrameMessenger,\n type MessengerConfig,\n} from './CrossFrameMessenger';\nimport { CrossFrameStateManager } from './CrossFrameStateManager';\nimport {\n getGlobalEditedContent,\n setGlobalEditedContent,\n subscribeToGlobalEditedContent,\n} from './editedContentBus';\nimport {\n getGlobalFocusedContent,\n setGlobalFocusedContent,\n subscribeToGlobalFocusedContent,\n} from './focusedContentBus';\nimport { IframeClickInterceptor } from './IframeClickInterceptor';\nimport { UrlStateManager } from './UrlStateManager';\n\nexport type DictionaryContent = Record<LocalDictionaryId, Dictionary>;\n\ntype EditorConfig = Pick<IntlayerConfig, 'editor'>;\n\nexport type FileContent = {\n dictionaryKey: string;\n dictionaryLocalId?: LocalDictionaryId;\n keyPath?: KeyPath[];\n};\n\nexport type EditorStateManagerConfig = {\n /** 'client' = the app running inside the iframe; 'editor' = the editor wrapping the app */\n mode: 'editor' | 'client';\n /** Cross-frame messaging configuration */\n messenger: MessengerConfig;\n /** Optional initial Intlayer configuration to broadcast */\n configuration?: EditorConfig;\n};\n\n/**\n * EditorStateManager is the single entry point for all Intlayer editor state.\n * It is framework-agnostic: instantiate one instance at the root of the application\n * and subscribe to its EventTarget-based events from any framework adapter.\n *\n * Replaces all context providers, hooks and store files across React, Preact,\n * Solid, Svelte, and Vue integrations.\n */\nexport class EditorStateManager {\n readonly messenger: CrossFrameMessenger;\n readonly editorEnabled: CrossFrameStateManager<boolean>;\n readonly focusedContent: CrossFrameStateManager<FileContent | null>;\n readonly localeDictionaries: CrossFrameStateManager<DictionaryContent>;\n readonly editedContent: CrossFrameStateManager<DictionaryContent>;\n readonly configuration: CrossFrameStateManager<EditorConfig>;\n readonly currentLocale: CrossFrameStateManager<Locale | undefined>;\n readonly displayedDictionaryKeys: CrossFrameStateManager<string[]>;\n\n private readonly _urlManager: UrlStateManager;\n private readonly _iframeInterceptor: IframeClickInterceptor;\n private readonly _mode: 'editor' | 'client';\n private readonly _configuration: EditorConfig | undefined;\n\n // Client-mode handshake subscribers\n private _unsubAreYouThere: (() => void) | null = null;\n private _unsubActivate: (() => void) | null = null;\n // Editor-mode handshake subscriber\n private _unsubClientReady: (() => void) | null = null;\n\n // Client-mode displayed-keys tracking\n private _displayedKeysObserver: MutationObserver | null = null;\n private _displayedKeysTimer: ReturnType<typeof setTimeout> | null = null;\n private _displayedKeysListeners: Array<[string, EventListener]> = [];\n\n // Global editedContent bus sync\n private _editedContentFromBus = false;\n private _unsubGlobalEditedContent: (() => void) | null = null;\n private _editedContentBusHandler: ((e: Event) => void) | null = null;\n\n // Global focusedContent bus sync\n private _focusedContentFromBus = false;\n private _unsubGlobalFocusedContent: (() => void) | null = null;\n private _focusedContentBusHandler: ((e: Event) => void) | null = null;\n\n constructor(config: EditorStateManagerConfig) {\n this._mode = config.mode;\n this._configuration = config.configuration;\n\n this.messenger = new CrossFrameMessenger(config.messenger);\n\n this.editorEnabled = new CrossFrameStateManager<boolean>(\n MessageKey.INTLAYER_EDITOR_ENABLED,\n this.messenger,\n { emit: false, receive: true, initialValue: false }\n );\n\n this.focusedContent = new CrossFrameStateManager<FileContent | null>(\n MessageKey.INTLAYER_FOCUSED_CONTENT_CHANGED,\n this.messenger,\n { emit: true, receive: true, initialValue: null }\n );\n\n this.localeDictionaries = new CrossFrameStateManager<DictionaryContent>(\n MessageKey.INTLAYER_LOCALE_DICTIONARIES_CHANGED,\n this.messenger\n );\n\n this.editedContent = new CrossFrameStateManager<DictionaryContent>(\n MessageKey.INTLAYER_EDITED_CONTENT_CHANGED,\n this.messenger\n );\n\n this.configuration = new CrossFrameStateManager<EditorConfig>(\n MessageKey.INTLAYER_CONFIGURATION,\n this.messenger,\n {\n emit: true,\n receive: false,\n ...(config.configuration ? { initialValue: config.configuration } : {}),\n }\n );\n\n // Client emits its locale to the editor; editor receives it.\n this.currentLocale = new CrossFrameStateManager<Locale>(\n MessageKey.INTLAYER_CURRENT_LOCALE,\n this.messenger,\n {\n emit: config.mode === 'client',\n receive: config.mode === 'editor',\n }\n );\n\n // Client emits displayed dictionary keys; editor receives them.\n this.displayedDictionaryKeys = new CrossFrameStateManager<string[]>(\n MessageKey.INTLAYER_DISPLAYED_DICTIONARY_KEYS,\n this.messenger,\n {\n emit: config.mode === 'client',\n receive: config.mode === 'editor',\n initialValue: [],\n }\n );\n\n this._urlManager = new UrlStateManager(this.messenger);\n this._iframeInterceptor = new IframeClickInterceptor(this.messenger);\n }\n\n start(): void {\n this.messenger.start();\n this.editorEnabled.start();\n this.focusedContent.start();\n this.localeDictionaries.start();\n this.editedContent.start();\n this.configuration.start();\n this.currentLocale.start();\n this.displayedDictionaryKeys.start();\n this._startEditedContentBusSync();\n this._startFocusedContentBusSync();\n\n if (this._mode === 'client') {\n this._urlManager.start();\n this._iframeInterceptor.startInterceptor();\n this._loadDictionaries();\n this._startDisplayedDictionariesTracking();\n // Request current edited content from the editor\n this.messenger.send(`${MessageKey.INTLAYER_EDITED_CONTENT_CHANGED}/get`);\n // Activation handshake: only participate if editor.enabled !== false\n if (this._configuration?.editor?.enabled !== false) {\n this._setupActivationHandshake();\n }\n } else {\n this._iframeInterceptor.startMerger();\n this._setupEditorHandshake();\n }\n }\n\n stop(): void {\n this._unsubAreYouThere?.();\n this._unsubActivate?.();\n this._unsubClientReady?.();\n this._unsubAreYouThere = null;\n this._unsubActivate = null;\n this._unsubClientReady = null;\n this.messenger.stop();\n this.editorEnabled.stop();\n this.focusedContent.stop();\n this.localeDictionaries.stop();\n this.editedContent.stop();\n this.configuration.stop();\n this.currentLocale.stop();\n this.displayedDictionaryKeys.stop();\n this._stopDisplayedDictionariesTracking();\n this._stopEditedContentBusSync();\n this._stopFocusedContentBusSync();\n this._urlManager.stop();\n this._iframeInterceptor.stopInterceptor();\n this._iframeInterceptor.stopMerger();\n }\n\n // ─── Handshake helpers ───────────────────────────────────────────────────────\n\n /**\n * EDITOR mode: re-send ARE_YOU_THERE to attempt re-connection with the client.\n * Call this when the user clicks \"Enable Editor\" or when the iframe reloads.\n */\n pingClient(): void {\n if (this._mode !== 'editor') return;\n\n this.messenger.send(MessageKey.INTLAYER_ARE_YOU_THERE);\n }\n\n // ─── Focus helpers ──────────────────────────────────────────────────────────\n\n setFocusedContentKeyPath(keyPath: KeyPath[]): void {\n const filtered = keyPath.filter(\n (key) => key.type !== NodeTypes.TRANSLATION\n );\n const prev = this.focusedContent.value;\n\n if (!prev) return;\n\n this.focusedContent.set({ ...prev, keyPath: filtered });\n }\n\n // ─── Dictionary record helpers ───────────────────────────────────────────\n\n setLocaleDictionary(dictionary: Dictionary): void {\n if (!dictionary.localId) return;\n const current = this.localeDictionaries.value ?? {};\n\n this.localeDictionaries.set({\n ...current,\n [dictionary.localId as LocalDictionaryId]: dictionary,\n });\n }\n\n // ─── Edited content helpers ───────────────────────────────────────────────\n\n setEditedDictionary(newDict: Dictionary): void {\n if (!newDict.localId) {\n console.error('setEditedDictionary: missing localId', newDict);\n return;\n }\n const current = this.editedContent.value ?? {};\n\n this.editedContent.set({\n ...current,\n [newDict.localId as LocalDictionaryId]: newDict,\n });\n }\n\n setEditedContent(\n localDictionaryId: LocalDictionaryId,\n newValue: Dictionary['content']\n ): void {\n const current = this.editedContent.value ?? {};\n\n this.editedContent.set({\n ...current,\n [localDictionaryId]: {\n ...current[localDictionaryId],\n content: newValue,\n },\n });\n }\n\n addContent(\n localDictionaryId: LocalDictionaryId,\n newValue: ContentNode,\n keyPath: KeyPath[] = [],\n overwrite = true\n ): void {\n const current = this.editedContent.value ?? {};\n const localeDicts = this.localeDictionaries.value ?? {};\n\n const originalContent = localeDicts[localDictionaryId]?.content;\n const currentContent = structuredClone(\n current[localDictionaryId]?.content ?? originalContent\n );\n\n let newKeyPath = keyPath;\n if (!overwrite) {\n let index = 0;\n\n const otherKeyPath = keyPath.slice(0, -1);\n const lastKeyPath = keyPath[keyPath.length - 1];\n\n let finalKey = lastKeyPath.key;\n\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 this.editedContent.set({\n ...current,\n [localDictionaryId]: {\n ...current[localDictionaryId],\n content: updatedContent as Dictionary['content'],\n },\n });\n }\n\n renameContent(\n localDictionaryId: LocalDictionaryId,\n newKey: KeyPath['key'],\n keyPath: KeyPath[] = []\n ): void {\n const current = this.editedContent.value ?? {};\n const localeDicts = this.localeDictionaries.value ?? {};\n const originalContent = localeDicts[localDictionaryId]?.content;\n const currentContent = structuredClone(\n current[localDictionaryId]?.content ?? originalContent\n );\n const updated = renameContentNodeByKeyPath(currentContent, newKey, keyPath);\n\n this.editedContent.set({\n ...current,\n [localDictionaryId]: {\n ...current[localDictionaryId],\n content: updated as Dictionary['content'],\n },\n });\n }\n\n removeContent(\n localDictionaryId: LocalDictionaryId,\n keyPath: KeyPath[]\n ): void {\n const current = this.editedContent.value ?? {};\n const localeDicts = this.localeDictionaries.value ?? {};\n const originalContent = localeDicts[localDictionaryId]?.content;\n const currentContent = structuredClone(\n current[localDictionaryId]?.content ?? originalContent\n );\n const initialContent = getContentNodeByKeyPath(originalContent, keyPath);\n const restored = editDictionaryByKeyPath(\n currentContent,\n keyPath,\n initialContent\n );\n\n this.editedContent.set({\n ...current,\n [localDictionaryId]: {\n ...current[localDictionaryId],\n content: restored as Dictionary['content'],\n },\n });\n }\n\n restoreContent(localDictionaryId: LocalDictionaryId): void {\n const current = this.editedContent.value ?? {};\n const updated = { ...current };\n\n delete updated[localDictionaryId];\n\n this.editedContent.set(updated);\n }\n\n clearContent(localDictionaryId: LocalDictionaryId): void {\n const current = this.editedContent.value ?? {};\n const filtered = { ...current };\n\n delete filtered[localDictionaryId];\n\n this.editedContent.set(filtered);\n }\n\n clearAllContent(): void {\n this.editedContent.set({});\n }\n\n getContentValue(\n localDictionaryIdOrKey: LocalDictionaryId | string,\n keyPath: KeyPath[]\n ): ContentNode | undefined {\n const edited = this.editedContent.value;\n if (!edited) return undefined;\n\n const filteredKeyPath = keyPath.filter(\n (key) => key.type !== NodeTypes.TRANSLATION\n );\n\n // Only use edited content entries whose localId is known to this client.\n // This prevents stale edits from other apps (different framework demos) from\n // being applied when the editor sends back its stored editedContent.\n const localeDicts = this.localeDictionaries.value;\n\n const isDictionaryId =\n localDictionaryIdOrKey.includes(':local:') ||\n localDictionaryIdOrKey.includes(':remote:');\n\n if (isDictionaryId) {\n // If localeDictionaries is loaded, verify this localId belongs to us\n if (localeDicts && !(localDictionaryIdOrKey in localeDicts)) {\n return undefined;\n }\n const content =\n edited[localDictionaryIdOrKey as LocalDictionaryId]?.content ?? {};\n\n return getContentNodeByKeyPath(\n content,\n filteredKeyPath,\n this.currentLocale.value\n );\n }\n\n const matchingIds = Object.keys(edited).filter(\n (key) =>\n key.startsWith(`${localDictionaryIdOrKey}:`) &&\n // If localeDictionaries is loaded, only include known localIds\n (!localeDicts || key in localeDicts)\n );\n\n for (const localId of matchingIds) {\n const content = edited[localId as LocalDictionaryId]?.content ?? {};\n const node = getContentNodeByKeyPath(\n content,\n filteredKeyPath,\n this.currentLocale.value\n );\n if (node) return node;\n }\n\n return undefined;\n }\n\n // ─── Global editedContent bus sync ───────────────────────────────────────\n\n private _startEditedContentBusSync(): void {\n // Push local changes to the global bus (loop-guarded)\n this._editedContentBusHandler = (e: Event) => {\n if (this._editedContentFromBus) return;\n const content = (e as CustomEvent<DictionaryContent>).detail;\n setGlobalEditedContent(content, this.messenger.senderId);\n };\n this.editedContent.addEventListener(\n 'change',\n this._editedContentBusHandler\n );\n\n // Receive bus changes from other managers\n this._unsubGlobalEditedContent = subscribeToGlobalEditedContent(\n (content, sourceId) => {\n if (sourceId === this.messenger.senderId) return;\n this._editedContentFromBus = true;\n this.editedContent.set(content);\n this._editedContentFromBus = false;\n }\n );\n\n // Seed local value from the bus if bus already has content\n const existing = getGlobalEditedContent();\n if (Object.keys(existing).length > 0) {\n this._editedContentFromBus = true;\n this.editedContent.set(existing);\n this._editedContentFromBus = false;\n }\n }\n\n private _stopEditedContentBusSync(): void {\n if (this._editedContentBusHandler) {\n this.editedContent.removeEventListener(\n 'change',\n this._editedContentBusHandler\n );\n this._editedContentBusHandler = null;\n }\n this._unsubGlobalEditedContent?.();\n this._unsubGlobalEditedContent = null;\n }\n\n // ─── Global focusedContent bus sync ──────────────────────────────────────\n\n private _startFocusedContentBusSync(): void {\n this._focusedContentBusHandler = (e: Event) => {\n if (this._focusedContentFromBus) return;\n const content = (e as CustomEvent<FileContent | null>).detail;\n setGlobalFocusedContent(content, this.messenger.senderId);\n };\n this.focusedContent.addEventListener(\n 'change',\n this._focusedContentBusHandler\n );\n\n this._unsubGlobalFocusedContent = subscribeToGlobalFocusedContent(\n (content, sourceId) => {\n if (sourceId === this.messenger.senderId) return;\n this._focusedContentFromBus = true;\n this.focusedContent.set(content);\n this._focusedContentFromBus = false;\n }\n );\n\n const existing = getGlobalFocusedContent();\n if (existing !== undefined) {\n this._focusedContentFromBus = true;\n this.focusedContent.set(existing);\n this._focusedContentFromBus = false;\n }\n }\n\n private _stopFocusedContentBusSync(): void {\n if (this._focusedContentBusHandler) {\n this.focusedContent.removeEventListener(\n 'change',\n this._focusedContentBusHandler\n );\n this._focusedContentBusHandler = null;\n }\n this._unsubGlobalFocusedContent?.();\n this._unsubGlobalFocusedContent = null;\n }\n\n // ─── Displayed dictionaries tracking (client mode only) ──────────────────\n\n private _scanDisplayedDictionaryKeys(): void {\n if (typeof document === 'undefined') return;\n const elements = document.querySelectorAll(\n 'intlayer-content-selector-wrapper[dictionary-key]'\n );\n const keys = Array.from(\n new Set(\n Array.from(elements)\n .map((el) => el.getAttribute('dictionary-key') ?? '')\n .filter(Boolean)\n )\n );\n this.displayedDictionaryKeys.set(keys);\n }\n\n private _startDisplayedDictionariesTracking(): void {\n if (\n typeof document === 'undefined' ||\n typeof MutationObserver === 'undefined'\n )\n return;\n\n const schedule = () => {\n if (this._displayedKeysTimer) clearTimeout(this._displayedKeysTimer);\n this._displayedKeysTimer = setTimeout(\n () => this._scanDisplayedDictionaryKeys(),\n 100\n );\n };\n\n this._displayedKeysObserver = new MutationObserver(schedule);\n this._displayedKeysObserver.observe(document.body, {\n childList: true,\n subtree: true,\n });\n\n for (const evt of ['locationchange', 'popstate'] as const) {\n const listener = schedule as EventListener;\n window.addEventListener(evt, listener);\n this._displayedKeysListeners.push([evt, listener]);\n }\n\n this._scanDisplayedDictionaryKeys();\n }\n\n private _stopDisplayedDictionariesTracking(): void {\n this._displayedKeysObserver?.disconnect();\n this._displayedKeysObserver = null;\n if (this._displayedKeysTimer) {\n clearTimeout(this._displayedKeysTimer);\n this._displayedKeysTimer = null;\n }\n for (const [evt, listener] of this._displayedKeysListeners) {\n window.removeEventListener(evt, listener);\n }\n this._displayedKeysListeners = [];\n }\n\n // ─── Handshake helpers ───────────────────────────────────────────────────────\n\n /**\n * EDITOR mode: listen for CLIENT_READY and respond with EDITOR_ACTIVATE.\n * Also pings the client immediately in case it loaded before the editor.\n */\n private _setupEditorHandshake(): void {\n // When the client announces it is ready, activate it\n this._unsubClientReady = this.messenger.subscribe(\n MessageKey.INTLAYER_CLIENT_READY,\n () => {\n this.editorEnabled.set(true);\n this.messenger.send(MessageKey.INTLAYER_EDITOR_ACTIVATE);\n }\n );\n\n // Ping any already-running client (covers editor-opens-after-client scenario)\n this.messenger.send(MessageKey.INTLAYER_ARE_YOU_THERE);\n }\n\n private _setupActivationHandshake(): void {\n // Announce to the editor that the client is ready\n this.messenger.send(MessageKey.INTLAYER_CLIENT_READY);\n\n // Respond to \"are you there?\" pings from the editor\n this._unsubAreYouThere = this.messenger.subscribe(\n MessageKey.INTLAYER_ARE_YOU_THERE,\n () => {\n this.messenger.send(MessageKey.INTLAYER_CLIENT_READY);\n }\n );\n\n // When the editor activates us, enable the selector and broadcast state\n this._unsubActivate = this.messenger.subscribe(\n MessageKey.INTLAYER_EDITOR_ACTIVATE,\n () => {\n this.editorEnabled.set(true);\n this._broadcastData();\n }\n );\n }\n\n private _broadcastData(): void {\n const configVal = this.configuration.value;\n\n if (configVal) {\n this.messenger.send(\n `${MessageKey.INTLAYER_CONFIGURATION}/post`,\n configVal\n );\n }\n const localeVal = this.currentLocale.value;\n\n if (localeVal) {\n this.messenger.send(\n `${MessageKey.INTLAYER_CURRENT_LOCALE}/post`,\n localeVal\n );\n }\n const dicts = this.localeDictionaries.value;\n\n if (dicts) {\n this.messenger.send(\n `${MessageKey.INTLAYER_LOCALE_DICTIONARIES_CHANGED}/post`,\n dicts\n );\n }\n }\n\n private async _loadDictionaries(): Promise<void> {\n try {\n const mod = await import('@intlayer/unmerged-dictionaries-entry');\n const unmergedDictionaries = mod.getUnmergedDictionaries();\n const dictionariesList = Object.fromEntries(\n Object.values(unmergedDictionaries)\n .flat()\n .map((dictionary) => [dictionary.localId, dictionary])\n ) as DictionaryContent;\n\n this.localeDictionaries.set(dictionariesList);\n\n // If the editor already activated us before dictionaries finished loading,\n // re-broadcast now so the editor receives the dictionaries.\n if (this.editorEnabled.value) {\n this._broadcastData();\n }\n } catch (e) {\n // Dynamic entry not available (expected in editor mode or when not configured)\n console.warn('[intlayer] Failed to load unmerged dictionaries:', e);\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
3
2
|
const require_core_globalManager = require('./globalManager.cjs');
|
|
4
3
|
const require_core_EditorStateManager = require('./EditorStateManager.cjs');
|
|
5
4
|
const require_components_ContentSelector = require('../components/ContentSelector.cjs');
|
|
6
5
|
let _intlayer_config_built = require("@intlayer/config/built");
|
|
7
|
-
_intlayer_config_built = require_runtime.__toESM(_intlayer_config_built);
|
|
8
6
|
|
|
9
7
|
//#region src/core/initEditorClient.ts
|
|
10
8
|
const buildClientMessengerConfig = () => {
|
|
@@ -32,7 +30,7 @@ const initEditorClient = () => {
|
|
|
32
30
|
const manager = new require_core_EditorStateManager.EditorStateManager({
|
|
33
31
|
mode: "client",
|
|
34
32
|
messenger: buildClientMessengerConfig(),
|
|
35
|
-
configuration: _intlayer_config_built.
|
|
33
|
+
configuration: { editor: _intlayer_config_built.editor }
|
|
36
34
|
});
|
|
37
35
|
require_core_globalManager.setGlobalEditorManager(manager);
|
|
38
36
|
require_components_ContentSelector.defineIntlayerElements();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initEditorClient.cjs","names":["editor","getGlobalEditorManager","EditorStateManager"],"sources":["../../../src/core/initEditorClient.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"initEditorClient.cjs","names":["editor","getGlobalEditorManager","EditorStateManager"],"sources":["../../../src/core/initEditorClient.ts"],"sourcesContent":["import { editor, internationalization } from '@intlayer/config/built';\nimport { defineIntlayerElements } from '../components';\nimport type { MessengerConfig } from './CrossFrameMessenger';\nimport { EditorStateManager } from './EditorStateManager';\nimport {\n getGlobalEditorManager,\n setGlobalEditorManager,\n} from './globalManager';\n\nexport const buildClientMessengerConfig = (): MessengerConfig => {\n return {\n allowedOrigins: [editor?.editorURL, editor?.cmsURL].filter(\n Boolean\n ) as string[],\n postMessageFn: (payload: unknown, origin: string) => {\n if (typeof window === 'undefined') return;\n\n const isInIframe = window.self !== window.top;\n\n if (!isInIframe) return;\n window.parent?.postMessage(payload, origin);\n },\n };\n};\n\n/** Reference count — tracks how many providers have called initEditorClient. */\nlet _clientRefCount = 0;\n\n/**\n * Initialize the Intlayer editor client singleton.\n * Safe to call multiple times — returns the existing manager if already initialized.\n * Increments a reference counter so nested providers don't destroy the manager\n * prematurely when the inner provider unmounts.\n */\nexport const initEditorClient = (): EditorStateManager => {\n _clientRefCount++;\n\n const existing = getGlobalEditorManager();\n if (existing) return existing;\n\n const manager = new EditorStateManager({\n mode: 'client',\n messenger: buildClientMessengerConfig(),\n configuration: { editor },\n });\n\n setGlobalEditorManager(manager);\n defineIntlayerElements();\n manager.start();\n\n return manager;\n};\n\n/**\n * Decrement the reference count and stop the global editor client singleton\n * only when the last provider unmounts.\n */\nexport const stopEditorClient = (): void => {\n _clientRefCount = Math.max(0, _clientRefCount - 1);\n\n if (_clientRefCount > 0) return;\n\n const manager = getGlobalEditorManager();\n manager?.stop();\n setGlobalEditorManager(null);\n};\n"],"mappings":";;;;;;;AASA,MAAa,mCAAoD;CAC/D,OAAO;EACL,gBAAgB,CAACA,+BAAQ,WAAWA,+BAAQ,MAAM,EAAE,OAClD,OACF;EACA,gBAAgB,SAAkB,WAAmB;GACnD,IAAI,OAAO,WAAW,aAAa;GAInC,IAAI,EAFe,OAAO,SAAS,OAAO,MAEzB;GACjB,OAAO,QAAQ,YAAY,SAAS,MAAM;EAC5C;CACF;AACF;;AAGA,IAAI,kBAAkB;;;;;;;AAQtB,MAAa,yBAA6C;CACxD;CAEA,MAAM,WAAWC,kDAAuB;CACxC,IAAI,UAAU,OAAO;CAErB,MAAM,UAAU,IAAIC,mDAAmB;EACrC,MAAM;EACN,WAAW,2BAA2B;EACtC,eAAe,EAAE,sCAAO;CAC1B,CAAC;CAED,kDAAuB,OAAO;CAC9B,0DAAuB;CACvB,QAAQ,MAAM;CAEd,OAAO;AACT;;;;;AAMA,MAAa,yBAA+B;CAC1C,kBAAkB,KAAK,IAAI,GAAG,kBAAkB,CAAC;CAEjD,IAAI,kBAAkB,GAAG;CAGzB,AADgBD,kDACV,GAAG,KAAK;CACd,kDAAuB,IAAI;AAC7B"}
|
package/dist/cjs/isEnabled.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"isEnabled.cjs","names":["editor"],"sources":["../../src/isEnabled.ts"],"sourcesContent":["import { editor } from '@intlayer/config/built';\n\nconst TREE_SHAKE_EDITOR = process.env['INTLAYER_EDITOR_ENABLED'] === 'false';\n\nexport const isEnabled =\n !TREE_SHAKE_EDITOR && // Allow purging a build time using bundler + env var\n editor?.enabled && // Editor enabled in config\n typeof window !== 'undefined' && // Client side\n window.self !== window.top; // Is in iframe\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"isEnabled.cjs","names":["editor"],"sources":["../../src/isEnabled.ts"],"sourcesContent":["import { editor } from '@intlayer/config/built';\n\nconst TREE_SHAKE_EDITOR = process.env['INTLAYER_EDITOR_ENABLED'] === 'false';\n\nexport const isEnabled =\n !TREE_SHAKE_EDITOR && // Allow purging a build time using bundler + env var\n editor?.enabled && // Editor enabled in config\n typeof window !== 'undefined' && // Client side\n window.self !== window.top; // Is in iframe\n"],"mappings":";;;;AAEA,MAAM,oBAAoB,QAAQ,IAAI,+BAA+B;AAErE,MAAa,YACX,CAAC,qBACDA,+BAAQ,WACR,OAAO,WAAW,eAClB,OAAO,SAAS,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorStateManager.mjs","names":[],"sources":["../../../src/core/EditorStateManager.ts"],"sourcesContent":["import {\n editDictionaryByKeyPath,\n getContentNodeByKeyPath,\n renameContentNodeByKeyPath,\n} from '@intlayer/core/dictionaryManipulator';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type {\n ContentNode,\n Dictionary,\n LocalDictionaryId,\n} from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { MessageKey } from '../messageKey';\nimport {\n CrossFrameMessenger,\n type MessengerConfig,\n} from './CrossFrameMessenger';\nimport { CrossFrameStateManager } from './CrossFrameStateManager';\nimport {\n getGlobalEditedContent,\n setGlobalEditedContent,\n subscribeToGlobalEditedContent,\n} from './editedContentBus';\nimport {\n getGlobalFocusedContent,\n setGlobalFocusedContent,\n subscribeToGlobalFocusedContent,\n} from './focusedContentBus';\nimport { IframeClickInterceptor } from './IframeClickInterceptor';\nimport { UrlStateManager } from './UrlStateManager';\n\nexport type DictionaryContent = Record<LocalDictionaryId, Dictionary>;\n\nexport type FileContent = {\n dictionaryKey: string;\n dictionaryLocalId?: LocalDictionaryId;\n keyPath?: KeyPath[];\n};\n\nexport type EditorStateManagerConfig = {\n /** 'client' = the app running inside the iframe; 'editor' = the editor wrapping the app */\n mode: 'editor' | 'client';\n /** Cross-frame messaging configuration */\n messenger: MessengerConfig;\n /** Optional initial Intlayer configuration to broadcast */\n configuration?: IntlayerConfig;\n};\n\n/**\n * EditorStateManager is the single entry point for all Intlayer editor state.\n * It is framework-agnostic: instantiate one instance at the root of the application\n * and subscribe to its EventTarget-based events from any framework adapter.\n *\n * Replaces all context providers, hooks and store files across React, Preact,\n * Solid, Svelte, and Vue integrations.\n */\nexport class EditorStateManager {\n readonly messenger: CrossFrameMessenger;\n readonly editorEnabled: CrossFrameStateManager<boolean>;\n readonly focusedContent: CrossFrameStateManager<FileContent | null>;\n readonly localeDictionaries: CrossFrameStateManager<DictionaryContent>;\n readonly editedContent: CrossFrameStateManager<DictionaryContent>;\n readonly configuration: CrossFrameStateManager<IntlayerConfig>;\n readonly currentLocale: CrossFrameStateManager<Locale | undefined>;\n readonly displayedDictionaryKeys: CrossFrameStateManager<string[]>;\n\n private readonly _urlManager: UrlStateManager;\n private readonly _iframeInterceptor: IframeClickInterceptor;\n private readonly _mode: 'editor' | 'client';\n private readonly _configuration: IntlayerConfig | undefined;\n\n // Client-mode handshake subscribers\n private _unsubAreYouThere: (() => void) | null = null;\n private _unsubActivate: (() => void) | null = null;\n // Editor-mode handshake subscriber\n private _unsubClientReady: (() => void) | null = null;\n\n // Client-mode displayed-keys tracking\n private _displayedKeysObserver: MutationObserver | null = null;\n private _displayedKeysTimer: ReturnType<typeof setTimeout> | null = null;\n private _displayedKeysListeners: Array<[string, EventListener]> = [];\n\n // Global editedContent bus sync\n private _editedContentFromBus = false;\n private _unsubGlobalEditedContent: (() => void) | null = null;\n private _editedContentBusHandler: ((e: Event) => void) | null = null;\n\n // Global focusedContent bus sync\n private _focusedContentFromBus = false;\n private _unsubGlobalFocusedContent: (() => void) | null = null;\n private _focusedContentBusHandler: ((e: Event) => void) | null = null;\n\n constructor(config: EditorStateManagerConfig) {\n this._mode = config.mode;\n this._configuration = config.configuration;\n\n this.messenger = new CrossFrameMessenger(config.messenger);\n\n this.editorEnabled = new CrossFrameStateManager<boolean>(\n MessageKey.INTLAYER_EDITOR_ENABLED,\n this.messenger,\n { emit: false, receive: true, initialValue: false }\n );\n\n this.focusedContent = new CrossFrameStateManager<FileContent | null>(\n MessageKey.INTLAYER_FOCUSED_CONTENT_CHANGED,\n this.messenger,\n { emit: true, receive: true, initialValue: null }\n );\n\n this.localeDictionaries = new CrossFrameStateManager<DictionaryContent>(\n MessageKey.INTLAYER_LOCALE_DICTIONARIES_CHANGED,\n this.messenger\n );\n\n this.editedContent = new CrossFrameStateManager<DictionaryContent>(\n MessageKey.INTLAYER_EDITED_CONTENT_CHANGED,\n this.messenger\n );\n\n this.configuration = new CrossFrameStateManager<IntlayerConfig>(\n MessageKey.INTLAYER_CONFIGURATION,\n this.messenger,\n {\n emit: true,\n receive: false,\n ...(config.configuration ? { initialValue: config.configuration } : {}),\n }\n );\n\n // Client emits its locale to the editor; editor receives it.\n this.currentLocale = new CrossFrameStateManager<Locale>(\n MessageKey.INTLAYER_CURRENT_LOCALE,\n this.messenger,\n {\n emit: config.mode === 'client',\n receive: config.mode === 'editor',\n }\n );\n\n // Client emits displayed dictionary keys; editor receives them.\n this.displayedDictionaryKeys = new CrossFrameStateManager<string[]>(\n MessageKey.INTLAYER_DISPLAYED_DICTIONARY_KEYS,\n this.messenger,\n {\n emit: config.mode === 'client',\n receive: config.mode === 'editor',\n initialValue: [],\n }\n );\n\n this._urlManager = new UrlStateManager(this.messenger);\n this._iframeInterceptor = new IframeClickInterceptor(this.messenger);\n }\n\n start(): void {\n this.messenger.start();\n this.editorEnabled.start();\n this.focusedContent.start();\n this.localeDictionaries.start();\n this.editedContent.start();\n this.configuration.start();\n this.currentLocale.start();\n this.displayedDictionaryKeys.start();\n this._startEditedContentBusSync();\n this._startFocusedContentBusSync();\n\n if (this._mode === 'client') {\n this._urlManager.start();\n this._iframeInterceptor.startInterceptor();\n this._loadDictionaries();\n this._startDisplayedDictionariesTracking();\n // Request current edited content from the editor\n this.messenger.send(`${MessageKey.INTLAYER_EDITED_CONTENT_CHANGED}/get`);\n // Activation handshake: only participate if editor.enabled !== false\n if (this._configuration?.editor?.enabled !== false) {\n this._setupActivationHandshake();\n }\n } else {\n this._iframeInterceptor.startMerger();\n this._setupEditorHandshake();\n }\n }\n\n stop(): void {\n this._unsubAreYouThere?.();\n this._unsubActivate?.();\n this._unsubClientReady?.();\n this._unsubAreYouThere = null;\n this._unsubActivate = null;\n this._unsubClientReady = null;\n this.messenger.stop();\n this.editorEnabled.stop();\n this.focusedContent.stop();\n this.localeDictionaries.stop();\n this.editedContent.stop();\n this.configuration.stop();\n this.currentLocale.stop();\n this.displayedDictionaryKeys.stop();\n this._stopDisplayedDictionariesTracking();\n this._stopEditedContentBusSync();\n this._stopFocusedContentBusSync();\n this._urlManager.stop();\n this._iframeInterceptor.stopInterceptor();\n this._iframeInterceptor.stopMerger();\n }\n\n // ─── Handshake helpers ───────────────────────────────────────────────────────\n\n /**\n * EDITOR mode: re-send ARE_YOU_THERE to attempt re-connection with the client.\n * Call this when the user clicks \"Enable Editor\" or when the iframe reloads.\n */\n pingClient(): void {\n if (this._mode !== 'editor') return;\n\n this.messenger.send(MessageKey.INTLAYER_ARE_YOU_THERE);\n }\n\n // ─── Focus helpers ──────────────────────────────────────────────────────────\n\n setFocusedContentKeyPath(keyPath: KeyPath[]): void {\n const filtered = keyPath.filter(\n (key) => key.type !== NodeTypes.TRANSLATION\n );\n const prev = this.focusedContent.value;\n\n if (!prev) return;\n\n this.focusedContent.set({ ...prev, keyPath: filtered });\n }\n\n // ─── Dictionary record helpers ───────────────────────────────────────────\n\n setLocaleDictionary(dictionary: Dictionary): void {\n if (!dictionary.localId) return;\n const current = this.localeDictionaries.value ?? {};\n\n this.localeDictionaries.set({\n ...current,\n [dictionary.localId as LocalDictionaryId]: dictionary,\n });\n }\n\n // ─── Edited content helpers ───────────────────────────────────────────────\n\n setEditedDictionary(newDict: Dictionary): void {\n if (!newDict.localId) {\n console.error('setEditedDictionary: missing localId', newDict);\n return;\n }\n const current = this.editedContent.value ?? {};\n\n this.editedContent.set({\n ...current,\n [newDict.localId as LocalDictionaryId]: newDict,\n });\n }\n\n setEditedContent(\n localDictionaryId: LocalDictionaryId,\n newValue: Dictionary['content']\n ): void {\n const current = this.editedContent.value ?? {};\n\n this.editedContent.set({\n ...current,\n [localDictionaryId]: {\n ...current[localDictionaryId],\n content: newValue,\n },\n });\n }\n\n addContent(\n localDictionaryId: LocalDictionaryId,\n newValue: ContentNode,\n keyPath: KeyPath[] = [],\n overwrite = true\n ): void {\n const current = this.editedContent.value ?? {};\n const localeDicts = this.localeDictionaries.value ?? {};\n\n const originalContent = localeDicts[localDictionaryId]?.content;\n const currentContent = structuredClone(\n current[localDictionaryId]?.content ?? originalContent\n );\n\n let newKeyPath = keyPath;\n if (!overwrite) {\n let index = 0;\n\n const otherKeyPath = keyPath.slice(0, -1);\n const lastKeyPath = keyPath[keyPath.length - 1];\n\n let finalKey = lastKeyPath.key;\n\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 this.editedContent.set({\n ...current,\n [localDictionaryId]: {\n ...current[localDictionaryId],\n content: updatedContent as Dictionary['content'],\n },\n });\n }\n\n renameContent(\n localDictionaryId: LocalDictionaryId,\n newKey: KeyPath['key'],\n keyPath: KeyPath[] = []\n ): void {\n const current = this.editedContent.value ?? {};\n const localeDicts = this.localeDictionaries.value ?? {};\n const originalContent = localeDicts[localDictionaryId]?.content;\n const currentContent = structuredClone(\n current[localDictionaryId]?.content ?? originalContent\n );\n const updated = renameContentNodeByKeyPath(currentContent, newKey, keyPath);\n\n this.editedContent.set({\n ...current,\n [localDictionaryId]: {\n ...current[localDictionaryId],\n content: updated as Dictionary['content'],\n },\n });\n }\n\n removeContent(\n localDictionaryId: LocalDictionaryId,\n keyPath: KeyPath[]\n ): void {\n const current = this.editedContent.value ?? {};\n const localeDicts = this.localeDictionaries.value ?? {};\n const originalContent = localeDicts[localDictionaryId]?.content;\n const currentContent = structuredClone(\n current[localDictionaryId]?.content ?? originalContent\n );\n const initialContent = getContentNodeByKeyPath(originalContent, keyPath);\n const restored = editDictionaryByKeyPath(\n currentContent,\n keyPath,\n initialContent\n );\n\n this.editedContent.set({\n ...current,\n [localDictionaryId]: {\n ...current[localDictionaryId],\n content: restored as Dictionary['content'],\n },\n });\n }\n\n restoreContent(localDictionaryId: LocalDictionaryId): void {\n const current = this.editedContent.value ?? {};\n const updated = { ...current };\n\n delete updated[localDictionaryId];\n\n this.editedContent.set(updated);\n }\n\n clearContent(localDictionaryId: LocalDictionaryId): void {\n const current = this.editedContent.value ?? {};\n const filtered = { ...current };\n\n delete filtered[localDictionaryId];\n\n this.editedContent.set(filtered);\n }\n\n clearAllContent(): void {\n this.editedContent.set({});\n }\n\n getContentValue(\n localDictionaryIdOrKey: LocalDictionaryId | string,\n keyPath: KeyPath[]\n ): ContentNode | undefined {\n const edited = this.editedContent.value;\n if (!edited) return undefined;\n\n const filteredKeyPath = keyPath.filter(\n (key) => key.type !== NodeTypes.TRANSLATION\n );\n\n // Only use edited content entries whose localId is known to this client.\n // This prevents stale edits from other apps (different framework demos) from\n // being applied when the editor sends back its stored editedContent.\n const localeDicts = this.localeDictionaries.value;\n\n const isDictionaryId =\n localDictionaryIdOrKey.includes(':local:') ||\n localDictionaryIdOrKey.includes(':remote:');\n\n if (isDictionaryId) {\n // If localeDictionaries is loaded, verify this localId belongs to us\n if (localeDicts && !(localDictionaryIdOrKey in localeDicts)) {\n return undefined;\n }\n const content =\n edited[localDictionaryIdOrKey as LocalDictionaryId]?.content ?? {};\n\n return getContentNodeByKeyPath(\n content,\n filteredKeyPath,\n this.currentLocale.value\n );\n }\n\n const matchingIds = Object.keys(edited).filter(\n (key) =>\n key.startsWith(`${localDictionaryIdOrKey}:`) &&\n // If localeDictionaries is loaded, only include known localIds\n (!localeDicts || key in localeDicts)\n );\n\n for (const localId of matchingIds) {\n const content = edited[localId as LocalDictionaryId]?.content ?? {};\n const node = getContentNodeByKeyPath(\n content,\n filteredKeyPath,\n this.currentLocale.value\n );\n if (node) return node;\n }\n\n return undefined;\n }\n\n // ─── Global editedContent bus sync ───────────────────────────────────────\n\n private _startEditedContentBusSync(): void {\n // Push local changes to the global bus (loop-guarded)\n this._editedContentBusHandler = (e: Event) => {\n if (this._editedContentFromBus) return;\n const content = (e as CustomEvent<DictionaryContent>).detail;\n setGlobalEditedContent(content, this.messenger.senderId);\n };\n this.editedContent.addEventListener(\n 'change',\n this._editedContentBusHandler\n );\n\n // Receive bus changes from other managers\n this._unsubGlobalEditedContent = subscribeToGlobalEditedContent(\n (content, sourceId) => {\n if (sourceId === this.messenger.senderId) return;\n this._editedContentFromBus = true;\n this.editedContent.set(content);\n this._editedContentFromBus = false;\n }\n );\n\n // Seed local value from the bus if bus already has content\n const existing = getGlobalEditedContent();\n if (Object.keys(existing).length > 0) {\n this._editedContentFromBus = true;\n this.editedContent.set(existing);\n this._editedContentFromBus = false;\n }\n }\n\n private _stopEditedContentBusSync(): void {\n if (this._editedContentBusHandler) {\n this.editedContent.removeEventListener(\n 'change',\n this._editedContentBusHandler\n );\n this._editedContentBusHandler = null;\n }\n this._unsubGlobalEditedContent?.();\n this._unsubGlobalEditedContent = null;\n }\n\n // ─── Global focusedContent bus sync ──────────────────────────────────────\n\n private _startFocusedContentBusSync(): void {\n this._focusedContentBusHandler = (e: Event) => {\n if (this._focusedContentFromBus) return;\n const content = (e as CustomEvent<FileContent | null>).detail;\n setGlobalFocusedContent(content, this.messenger.senderId);\n };\n this.focusedContent.addEventListener(\n 'change',\n this._focusedContentBusHandler\n );\n\n this._unsubGlobalFocusedContent = subscribeToGlobalFocusedContent(\n (content, sourceId) => {\n if (sourceId === this.messenger.senderId) return;\n this._focusedContentFromBus = true;\n this.focusedContent.set(content);\n this._focusedContentFromBus = false;\n }\n );\n\n const existing = getGlobalFocusedContent();\n if (existing !== undefined) {\n this._focusedContentFromBus = true;\n this.focusedContent.set(existing);\n this._focusedContentFromBus = false;\n }\n }\n\n private _stopFocusedContentBusSync(): void {\n if (this._focusedContentBusHandler) {\n this.focusedContent.removeEventListener(\n 'change',\n this._focusedContentBusHandler\n );\n this._focusedContentBusHandler = null;\n }\n this._unsubGlobalFocusedContent?.();\n this._unsubGlobalFocusedContent = null;\n }\n\n // ─── Displayed dictionaries tracking (client mode only) ──────────────────\n\n private _scanDisplayedDictionaryKeys(): void {\n if (typeof document === 'undefined') return;\n const elements = document.querySelectorAll(\n 'intlayer-content-selector-wrapper[dictionary-key]'\n );\n const keys = Array.from(\n new Set(\n Array.from(elements)\n .map((el) => el.getAttribute('dictionary-key') ?? '')\n .filter(Boolean)\n )\n );\n this.displayedDictionaryKeys.set(keys);\n }\n\n private _startDisplayedDictionariesTracking(): void {\n if (\n typeof document === 'undefined' ||\n typeof MutationObserver === 'undefined'\n )\n return;\n\n const schedule = () => {\n if (this._displayedKeysTimer) clearTimeout(this._displayedKeysTimer);\n this._displayedKeysTimer = setTimeout(\n () => this._scanDisplayedDictionaryKeys(),\n 100\n );\n };\n\n this._displayedKeysObserver = new MutationObserver(schedule);\n this._displayedKeysObserver.observe(document.body, {\n childList: true,\n subtree: true,\n });\n\n for (const evt of ['locationchange', 'popstate'] as const) {\n const listener = schedule as EventListener;\n window.addEventListener(evt, listener);\n this._displayedKeysListeners.push([evt, listener]);\n }\n\n this._scanDisplayedDictionaryKeys();\n }\n\n private _stopDisplayedDictionariesTracking(): void {\n this._displayedKeysObserver?.disconnect();\n this._displayedKeysObserver = null;\n if (this._displayedKeysTimer) {\n clearTimeout(this._displayedKeysTimer);\n this._displayedKeysTimer = null;\n }\n for (const [evt, listener] of this._displayedKeysListeners) {\n window.removeEventListener(evt, listener);\n }\n this._displayedKeysListeners = [];\n }\n\n // ─── Handshake helpers ───────────────────────────────────────────────────────\n\n /**\n * EDITOR mode: listen for CLIENT_READY and respond with EDITOR_ACTIVATE.\n * Also pings the client immediately in case it loaded before the editor.\n */\n private _setupEditorHandshake(): void {\n // When the client announces it is ready, activate it\n this._unsubClientReady = this.messenger.subscribe(\n MessageKey.INTLAYER_CLIENT_READY,\n () => {\n this.editorEnabled.set(true);\n this.messenger.send(MessageKey.INTLAYER_EDITOR_ACTIVATE);\n }\n );\n\n // Ping any already-running client (covers editor-opens-after-client scenario)\n this.messenger.send(MessageKey.INTLAYER_ARE_YOU_THERE);\n }\n\n private _setupActivationHandshake(): void {\n // Announce to the editor that the client is ready\n this.messenger.send(MessageKey.INTLAYER_CLIENT_READY);\n\n // Respond to \"are you there?\" pings from the editor\n this._unsubAreYouThere = this.messenger.subscribe(\n MessageKey.INTLAYER_ARE_YOU_THERE,\n () => {\n this.messenger.send(MessageKey.INTLAYER_CLIENT_READY);\n }\n );\n\n // When the editor activates us, enable the selector and broadcast state\n this._unsubActivate = this.messenger.subscribe(\n MessageKey.INTLAYER_EDITOR_ACTIVATE,\n () => {\n this.editorEnabled.set(true);\n this._broadcastData();\n }\n );\n }\n\n private _broadcastData(): void {\n const configVal = this.configuration.value;\n\n if (configVal) {\n this.messenger.send(\n `${MessageKey.INTLAYER_CONFIGURATION}/post`,\n configVal\n );\n }\n const localeVal = this.currentLocale.value;\n\n if (localeVal) {\n this.messenger.send(\n `${MessageKey.INTLAYER_CURRENT_LOCALE}/post`,\n localeVal\n );\n }\n const dicts = this.localeDictionaries.value;\n\n if (dicts) {\n this.messenger.send(\n `${MessageKey.INTLAYER_LOCALE_DICTIONARIES_CHANGED}/post`,\n dicts\n );\n }\n }\n\n private async _loadDictionaries(): Promise<void> {\n try {\n const mod = await import('@intlayer/unmerged-dictionaries-entry');\n const unmergedDictionaries = mod.getUnmergedDictionaries();\n const dictionariesList = Object.fromEntries(\n Object.values(unmergedDictionaries)\n .flat()\n .map((dictionary) => [dictionary.localId, dictionary])\n ) as DictionaryContent;\n\n this.localeDictionaries.set(dictionariesList);\n\n // If the editor already activated us before dictionaries finished loading,\n // re-broadcast now so the editor receives the dictionaries.\n if (this.editorEnabled.value) {\n this._broadcastData();\n }\n } catch (e) {\n // Dynamic entry not available (expected in editor mode or when not configured)\n console.warn('[intlayer] Failed to load unmerged dictionaries:', e);\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EditorStateManager.mjs","names":[],"sources":["../../../src/core/EditorStateManager.ts"],"sourcesContent":["import {\n editDictionaryByKeyPath,\n getContentNodeByKeyPath,\n renameContentNodeByKeyPath,\n} from '@intlayer/core/dictionaryManipulator';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type {\n ContentNode,\n Dictionary,\n LocalDictionaryId,\n} from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { MessageKey } from '../messageKey';\nimport {\n CrossFrameMessenger,\n type MessengerConfig,\n} from './CrossFrameMessenger';\nimport { CrossFrameStateManager } from './CrossFrameStateManager';\nimport {\n getGlobalEditedContent,\n setGlobalEditedContent,\n subscribeToGlobalEditedContent,\n} from './editedContentBus';\nimport {\n getGlobalFocusedContent,\n setGlobalFocusedContent,\n subscribeToGlobalFocusedContent,\n} from './focusedContentBus';\nimport { IframeClickInterceptor } from './IframeClickInterceptor';\nimport { UrlStateManager } from './UrlStateManager';\n\nexport type DictionaryContent = Record<LocalDictionaryId, Dictionary>;\n\ntype EditorConfig = Pick<IntlayerConfig, 'editor'>;\n\nexport type FileContent = {\n dictionaryKey: string;\n dictionaryLocalId?: LocalDictionaryId;\n keyPath?: KeyPath[];\n};\n\nexport type EditorStateManagerConfig = {\n /** 'client' = the app running inside the iframe; 'editor' = the editor wrapping the app */\n mode: 'editor' | 'client';\n /** Cross-frame messaging configuration */\n messenger: MessengerConfig;\n /** Optional initial Intlayer configuration to broadcast */\n configuration?: EditorConfig;\n};\n\n/**\n * EditorStateManager is the single entry point for all Intlayer editor state.\n * It is framework-agnostic: instantiate one instance at the root of the application\n * and subscribe to its EventTarget-based events from any framework adapter.\n *\n * Replaces all context providers, hooks and store files across React, Preact,\n * Solid, Svelte, and Vue integrations.\n */\nexport class EditorStateManager {\n readonly messenger: CrossFrameMessenger;\n readonly editorEnabled: CrossFrameStateManager<boolean>;\n readonly focusedContent: CrossFrameStateManager<FileContent | null>;\n readonly localeDictionaries: CrossFrameStateManager<DictionaryContent>;\n readonly editedContent: CrossFrameStateManager<DictionaryContent>;\n readonly configuration: CrossFrameStateManager<EditorConfig>;\n readonly currentLocale: CrossFrameStateManager<Locale | undefined>;\n readonly displayedDictionaryKeys: CrossFrameStateManager<string[]>;\n\n private readonly _urlManager: UrlStateManager;\n private readonly _iframeInterceptor: IframeClickInterceptor;\n private readonly _mode: 'editor' | 'client';\n private readonly _configuration: EditorConfig | undefined;\n\n // Client-mode handshake subscribers\n private _unsubAreYouThere: (() => void) | null = null;\n private _unsubActivate: (() => void) | null = null;\n // Editor-mode handshake subscriber\n private _unsubClientReady: (() => void) | null = null;\n\n // Client-mode displayed-keys tracking\n private _displayedKeysObserver: MutationObserver | null = null;\n private _displayedKeysTimer: ReturnType<typeof setTimeout> | null = null;\n private _displayedKeysListeners: Array<[string, EventListener]> = [];\n\n // Global editedContent bus sync\n private _editedContentFromBus = false;\n private _unsubGlobalEditedContent: (() => void) | null = null;\n private _editedContentBusHandler: ((e: Event) => void) | null = null;\n\n // Global focusedContent bus sync\n private _focusedContentFromBus = false;\n private _unsubGlobalFocusedContent: (() => void) | null = null;\n private _focusedContentBusHandler: ((e: Event) => void) | null = null;\n\n constructor(config: EditorStateManagerConfig) {\n this._mode = config.mode;\n this._configuration = config.configuration;\n\n this.messenger = new CrossFrameMessenger(config.messenger);\n\n this.editorEnabled = new CrossFrameStateManager<boolean>(\n MessageKey.INTLAYER_EDITOR_ENABLED,\n this.messenger,\n { emit: false, receive: true, initialValue: false }\n );\n\n this.focusedContent = new CrossFrameStateManager<FileContent | null>(\n MessageKey.INTLAYER_FOCUSED_CONTENT_CHANGED,\n this.messenger,\n { emit: true, receive: true, initialValue: null }\n );\n\n this.localeDictionaries = new CrossFrameStateManager<DictionaryContent>(\n MessageKey.INTLAYER_LOCALE_DICTIONARIES_CHANGED,\n this.messenger\n );\n\n this.editedContent = new CrossFrameStateManager<DictionaryContent>(\n MessageKey.INTLAYER_EDITED_CONTENT_CHANGED,\n this.messenger\n );\n\n this.configuration = new CrossFrameStateManager<EditorConfig>(\n MessageKey.INTLAYER_CONFIGURATION,\n this.messenger,\n {\n emit: true,\n receive: false,\n ...(config.configuration ? { initialValue: config.configuration } : {}),\n }\n );\n\n // Client emits its locale to the editor; editor receives it.\n this.currentLocale = new CrossFrameStateManager<Locale>(\n MessageKey.INTLAYER_CURRENT_LOCALE,\n this.messenger,\n {\n emit: config.mode === 'client',\n receive: config.mode === 'editor',\n }\n );\n\n // Client emits displayed dictionary keys; editor receives them.\n this.displayedDictionaryKeys = new CrossFrameStateManager<string[]>(\n MessageKey.INTLAYER_DISPLAYED_DICTIONARY_KEYS,\n this.messenger,\n {\n emit: config.mode === 'client',\n receive: config.mode === 'editor',\n initialValue: [],\n }\n );\n\n this._urlManager = new UrlStateManager(this.messenger);\n this._iframeInterceptor = new IframeClickInterceptor(this.messenger);\n }\n\n start(): void {\n this.messenger.start();\n this.editorEnabled.start();\n this.focusedContent.start();\n this.localeDictionaries.start();\n this.editedContent.start();\n this.configuration.start();\n this.currentLocale.start();\n this.displayedDictionaryKeys.start();\n this._startEditedContentBusSync();\n this._startFocusedContentBusSync();\n\n if (this._mode === 'client') {\n this._urlManager.start();\n this._iframeInterceptor.startInterceptor();\n this._loadDictionaries();\n this._startDisplayedDictionariesTracking();\n // Request current edited content from the editor\n this.messenger.send(`${MessageKey.INTLAYER_EDITED_CONTENT_CHANGED}/get`);\n // Activation handshake: only participate if editor.enabled !== false\n if (this._configuration?.editor?.enabled !== false) {\n this._setupActivationHandshake();\n }\n } else {\n this._iframeInterceptor.startMerger();\n this._setupEditorHandshake();\n }\n }\n\n stop(): void {\n this._unsubAreYouThere?.();\n this._unsubActivate?.();\n this._unsubClientReady?.();\n this._unsubAreYouThere = null;\n this._unsubActivate = null;\n this._unsubClientReady = null;\n this.messenger.stop();\n this.editorEnabled.stop();\n this.focusedContent.stop();\n this.localeDictionaries.stop();\n this.editedContent.stop();\n this.configuration.stop();\n this.currentLocale.stop();\n this.displayedDictionaryKeys.stop();\n this._stopDisplayedDictionariesTracking();\n this._stopEditedContentBusSync();\n this._stopFocusedContentBusSync();\n this._urlManager.stop();\n this._iframeInterceptor.stopInterceptor();\n this._iframeInterceptor.stopMerger();\n }\n\n // ─── Handshake helpers ───────────────────────────────────────────────────────\n\n /**\n * EDITOR mode: re-send ARE_YOU_THERE to attempt re-connection with the client.\n * Call this when the user clicks \"Enable Editor\" or when the iframe reloads.\n */\n pingClient(): void {\n if (this._mode !== 'editor') return;\n\n this.messenger.send(MessageKey.INTLAYER_ARE_YOU_THERE);\n }\n\n // ─── Focus helpers ──────────────────────────────────────────────────────────\n\n setFocusedContentKeyPath(keyPath: KeyPath[]): void {\n const filtered = keyPath.filter(\n (key) => key.type !== NodeTypes.TRANSLATION\n );\n const prev = this.focusedContent.value;\n\n if (!prev) return;\n\n this.focusedContent.set({ ...prev, keyPath: filtered });\n }\n\n // ─── Dictionary record helpers ───────────────────────────────────────────\n\n setLocaleDictionary(dictionary: Dictionary): void {\n if (!dictionary.localId) return;\n const current = this.localeDictionaries.value ?? {};\n\n this.localeDictionaries.set({\n ...current,\n [dictionary.localId as LocalDictionaryId]: dictionary,\n });\n }\n\n // ─── Edited content helpers ───────────────────────────────────────────────\n\n setEditedDictionary(newDict: Dictionary): void {\n if (!newDict.localId) {\n console.error('setEditedDictionary: missing localId', newDict);\n return;\n }\n const current = this.editedContent.value ?? {};\n\n this.editedContent.set({\n ...current,\n [newDict.localId as LocalDictionaryId]: newDict,\n });\n }\n\n setEditedContent(\n localDictionaryId: LocalDictionaryId,\n newValue: Dictionary['content']\n ): void {\n const current = this.editedContent.value ?? {};\n\n this.editedContent.set({\n ...current,\n [localDictionaryId]: {\n ...current[localDictionaryId],\n content: newValue,\n },\n });\n }\n\n addContent(\n localDictionaryId: LocalDictionaryId,\n newValue: ContentNode,\n keyPath: KeyPath[] = [],\n overwrite = true\n ): void {\n const current = this.editedContent.value ?? {};\n const localeDicts = this.localeDictionaries.value ?? {};\n\n const originalContent = localeDicts[localDictionaryId]?.content;\n const currentContent = structuredClone(\n current[localDictionaryId]?.content ?? originalContent\n );\n\n let newKeyPath = keyPath;\n if (!overwrite) {\n let index = 0;\n\n const otherKeyPath = keyPath.slice(0, -1);\n const lastKeyPath = keyPath[keyPath.length - 1];\n\n let finalKey = lastKeyPath.key;\n\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 this.editedContent.set({\n ...current,\n [localDictionaryId]: {\n ...current[localDictionaryId],\n content: updatedContent as Dictionary['content'],\n },\n });\n }\n\n renameContent(\n localDictionaryId: LocalDictionaryId,\n newKey: KeyPath['key'],\n keyPath: KeyPath[] = []\n ): void {\n const current = this.editedContent.value ?? {};\n const localeDicts = this.localeDictionaries.value ?? {};\n const originalContent = localeDicts[localDictionaryId]?.content;\n const currentContent = structuredClone(\n current[localDictionaryId]?.content ?? originalContent\n );\n const updated = renameContentNodeByKeyPath(currentContent, newKey, keyPath);\n\n this.editedContent.set({\n ...current,\n [localDictionaryId]: {\n ...current[localDictionaryId],\n content: updated as Dictionary['content'],\n },\n });\n }\n\n removeContent(\n localDictionaryId: LocalDictionaryId,\n keyPath: KeyPath[]\n ): void {\n const current = this.editedContent.value ?? {};\n const localeDicts = this.localeDictionaries.value ?? {};\n const originalContent = localeDicts[localDictionaryId]?.content;\n const currentContent = structuredClone(\n current[localDictionaryId]?.content ?? originalContent\n );\n const initialContent = getContentNodeByKeyPath(originalContent, keyPath);\n const restored = editDictionaryByKeyPath(\n currentContent,\n keyPath,\n initialContent\n );\n\n this.editedContent.set({\n ...current,\n [localDictionaryId]: {\n ...current[localDictionaryId],\n content: restored as Dictionary['content'],\n },\n });\n }\n\n restoreContent(localDictionaryId: LocalDictionaryId): void {\n const current = this.editedContent.value ?? {};\n const updated = { ...current };\n\n delete updated[localDictionaryId];\n\n this.editedContent.set(updated);\n }\n\n clearContent(localDictionaryId: LocalDictionaryId): void {\n const current = this.editedContent.value ?? {};\n const filtered = { ...current };\n\n delete filtered[localDictionaryId];\n\n this.editedContent.set(filtered);\n }\n\n clearAllContent(): void {\n this.editedContent.set({});\n }\n\n getContentValue(\n localDictionaryIdOrKey: LocalDictionaryId | string,\n keyPath: KeyPath[]\n ): ContentNode | undefined {\n const edited = this.editedContent.value;\n if (!edited) return undefined;\n\n const filteredKeyPath = keyPath.filter(\n (key) => key.type !== NodeTypes.TRANSLATION\n );\n\n // Only use edited content entries whose localId is known to this client.\n // This prevents stale edits from other apps (different framework demos) from\n // being applied when the editor sends back its stored editedContent.\n const localeDicts = this.localeDictionaries.value;\n\n const isDictionaryId =\n localDictionaryIdOrKey.includes(':local:') ||\n localDictionaryIdOrKey.includes(':remote:');\n\n if (isDictionaryId) {\n // If localeDictionaries is loaded, verify this localId belongs to us\n if (localeDicts && !(localDictionaryIdOrKey in localeDicts)) {\n return undefined;\n }\n const content =\n edited[localDictionaryIdOrKey as LocalDictionaryId]?.content ?? {};\n\n return getContentNodeByKeyPath(\n content,\n filteredKeyPath,\n this.currentLocale.value\n );\n }\n\n const matchingIds = Object.keys(edited).filter(\n (key) =>\n key.startsWith(`${localDictionaryIdOrKey}:`) &&\n // If localeDictionaries is loaded, only include known localIds\n (!localeDicts || key in localeDicts)\n );\n\n for (const localId of matchingIds) {\n const content = edited[localId as LocalDictionaryId]?.content ?? {};\n const node = getContentNodeByKeyPath(\n content,\n filteredKeyPath,\n this.currentLocale.value\n );\n if (node) return node;\n }\n\n return undefined;\n }\n\n // ─── Global editedContent bus sync ───────────────────────────────────────\n\n private _startEditedContentBusSync(): void {\n // Push local changes to the global bus (loop-guarded)\n this._editedContentBusHandler = (e: Event) => {\n if (this._editedContentFromBus) return;\n const content = (e as CustomEvent<DictionaryContent>).detail;\n setGlobalEditedContent(content, this.messenger.senderId);\n };\n this.editedContent.addEventListener(\n 'change',\n this._editedContentBusHandler\n );\n\n // Receive bus changes from other managers\n this._unsubGlobalEditedContent = subscribeToGlobalEditedContent(\n (content, sourceId) => {\n if (sourceId === this.messenger.senderId) return;\n this._editedContentFromBus = true;\n this.editedContent.set(content);\n this._editedContentFromBus = false;\n }\n );\n\n // Seed local value from the bus if bus already has content\n const existing = getGlobalEditedContent();\n if (Object.keys(existing).length > 0) {\n this._editedContentFromBus = true;\n this.editedContent.set(existing);\n this._editedContentFromBus = false;\n }\n }\n\n private _stopEditedContentBusSync(): void {\n if (this._editedContentBusHandler) {\n this.editedContent.removeEventListener(\n 'change',\n this._editedContentBusHandler\n );\n this._editedContentBusHandler = null;\n }\n this._unsubGlobalEditedContent?.();\n this._unsubGlobalEditedContent = null;\n }\n\n // ─── Global focusedContent bus sync ──────────────────────────────────────\n\n private _startFocusedContentBusSync(): void {\n this._focusedContentBusHandler = (e: Event) => {\n if (this._focusedContentFromBus) return;\n const content = (e as CustomEvent<FileContent | null>).detail;\n setGlobalFocusedContent(content, this.messenger.senderId);\n };\n this.focusedContent.addEventListener(\n 'change',\n this._focusedContentBusHandler\n );\n\n this._unsubGlobalFocusedContent = subscribeToGlobalFocusedContent(\n (content, sourceId) => {\n if (sourceId === this.messenger.senderId) return;\n this._focusedContentFromBus = true;\n this.focusedContent.set(content);\n this._focusedContentFromBus = false;\n }\n );\n\n const existing = getGlobalFocusedContent();\n if (existing !== undefined) {\n this._focusedContentFromBus = true;\n this.focusedContent.set(existing);\n this._focusedContentFromBus = false;\n }\n }\n\n private _stopFocusedContentBusSync(): void {\n if (this._focusedContentBusHandler) {\n this.focusedContent.removeEventListener(\n 'change',\n this._focusedContentBusHandler\n );\n this._focusedContentBusHandler = null;\n }\n this._unsubGlobalFocusedContent?.();\n this._unsubGlobalFocusedContent = null;\n }\n\n // ─── Displayed dictionaries tracking (client mode only) ──────────────────\n\n private _scanDisplayedDictionaryKeys(): void {\n if (typeof document === 'undefined') return;\n const elements = document.querySelectorAll(\n 'intlayer-content-selector-wrapper[dictionary-key]'\n );\n const keys = Array.from(\n new Set(\n Array.from(elements)\n .map((el) => el.getAttribute('dictionary-key') ?? '')\n .filter(Boolean)\n )\n );\n this.displayedDictionaryKeys.set(keys);\n }\n\n private _startDisplayedDictionariesTracking(): void {\n if (\n typeof document === 'undefined' ||\n typeof MutationObserver === 'undefined'\n )\n return;\n\n const schedule = () => {\n if (this._displayedKeysTimer) clearTimeout(this._displayedKeysTimer);\n this._displayedKeysTimer = setTimeout(\n () => this._scanDisplayedDictionaryKeys(),\n 100\n );\n };\n\n this._displayedKeysObserver = new MutationObserver(schedule);\n this._displayedKeysObserver.observe(document.body, {\n childList: true,\n subtree: true,\n });\n\n for (const evt of ['locationchange', 'popstate'] as const) {\n const listener = schedule as EventListener;\n window.addEventListener(evt, listener);\n this._displayedKeysListeners.push([evt, listener]);\n }\n\n this._scanDisplayedDictionaryKeys();\n }\n\n private _stopDisplayedDictionariesTracking(): void {\n this._displayedKeysObserver?.disconnect();\n this._displayedKeysObserver = null;\n if (this._displayedKeysTimer) {\n clearTimeout(this._displayedKeysTimer);\n this._displayedKeysTimer = null;\n }\n for (const [evt, listener] of this._displayedKeysListeners) {\n window.removeEventListener(evt, listener);\n }\n this._displayedKeysListeners = [];\n }\n\n // ─── Handshake helpers ───────────────────────────────────────────────────────\n\n /**\n * EDITOR mode: listen for CLIENT_READY and respond with EDITOR_ACTIVATE.\n * Also pings the client immediately in case it loaded before the editor.\n */\n private _setupEditorHandshake(): void {\n // When the client announces it is ready, activate it\n this._unsubClientReady = this.messenger.subscribe(\n MessageKey.INTLAYER_CLIENT_READY,\n () => {\n this.editorEnabled.set(true);\n this.messenger.send(MessageKey.INTLAYER_EDITOR_ACTIVATE);\n }\n );\n\n // Ping any already-running client (covers editor-opens-after-client scenario)\n this.messenger.send(MessageKey.INTLAYER_ARE_YOU_THERE);\n }\n\n private _setupActivationHandshake(): void {\n // Announce to the editor that the client is ready\n this.messenger.send(MessageKey.INTLAYER_CLIENT_READY);\n\n // Respond to \"are you there?\" pings from the editor\n this._unsubAreYouThere = this.messenger.subscribe(\n MessageKey.INTLAYER_ARE_YOU_THERE,\n () => {\n this.messenger.send(MessageKey.INTLAYER_CLIENT_READY);\n }\n );\n\n // When the editor activates us, enable the selector and broadcast state\n this._unsubActivate = this.messenger.subscribe(\n MessageKey.INTLAYER_EDITOR_ACTIVATE,\n () => {\n this.editorEnabled.set(true);\n this._broadcastData();\n }\n );\n }\n\n private _broadcastData(): void {\n const configVal = this.configuration.value;\n\n if (configVal) {\n this.messenger.send(\n `${MessageKey.INTLAYER_CONFIGURATION}/post`,\n configVal\n );\n }\n const localeVal = this.currentLocale.value;\n\n if (localeVal) {\n this.messenger.send(\n `${MessageKey.INTLAYER_CURRENT_LOCALE}/post`,\n localeVal\n );\n }\n const dicts = this.localeDictionaries.value;\n\n if (dicts) {\n this.messenger.send(\n `${MessageKey.INTLAYER_LOCALE_DICTIONARIES_CHANGED}/post`,\n dicts\n );\n }\n }\n\n private async _loadDictionaries(): Promise<void> {\n try {\n const mod = await import('@intlayer/unmerged-dictionaries-entry');\n const unmergedDictionaries = mod.getUnmergedDictionaries();\n const dictionariesList = Object.fromEntries(\n Object.values(unmergedDictionaries)\n .flat()\n .map((dictionary) => [dictionary.localId, dictionary])\n ) as DictionaryContent;\n\n this.localeDictionaries.set(dictionariesList);\n\n // If the editor already activated us before dictionaries finished loading,\n // re-broadcast now so the editor receives the dictionaries.\n if (this.editorEnabled.value) {\n this._broadcastData();\n }\n } catch (e) {\n // Dynamic entry not available (expected in editor mode or when not configured)\n console.warn('[intlayer] Failed to load unmerged dictionaries:', e);\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getGlobalEditorManager, setGlobalEditorManager } from "./globalManager.mjs";
|
|
2
2
|
import { EditorStateManager } from "./EditorStateManager.mjs";
|
|
3
3
|
import { defineIntlayerElements } from "../components/ContentSelector.mjs";
|
|
4
|
-
import
|
|
4
|
+
import { editor } from "@intlayer/config/built";
|
|
5
5
|
|
|
6
6
|
//#region src/core/initEditorClient.ts
|
|
7
7
|
const buildClientMessengerConfig = () => {
|
|
@@ -29,7 +29,7 @@ const initEditorClient = () => {
|
|
|
29
29
|
const manager = new EditorStateManager({
|
|
30
30
|
mode: "client",
|
|
31
31
|
messenger: buildClientMessengerConfig(),
|
|
32
|
-
configuration
|
|
32
|
+
configuration: { editor }
|
|
33
33
|
});
|
|
34
34
|
setGlobalEditorManager(manager);
|
|
35
35
|
defineIntlayerElements();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initEditorClient.mjs","names":[],"sources":["../../../src/core/initEditorClient.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"initEditorClient.mjs","names":[],"sources":["../../../src/core/initEditorClient.ts"],"sourcesContent":["import { editor, internationalization } from '@intlayer/config/built';\nimport { defineIntlayerElements } from '../components';\nimport type { MessengerConfig } from './CrossFrameMessenger';\nimport { EditorStateManager } from './EditorStateManager';\nimport {\n getGlobalEditorManager,\n setGlobalEditorManager,\n} from './globalManager';\n\nexport const buildClientMessengerConfig = (): MessengerConfig => {\n return {\n allowedOrigins: [editor?.editorURL, editor?.cmsURL].filter(\n Boolean\n ) as string[],\n postMessageFn: (payload: unknown, origin: string) => {\n if (typeof window === 'undefined') return;\n\n const isInIframe = window.self !== window.top;\n\n if (!isInIframe) return;\n window.parent?.postMessage(payload, origin);\n },\n };\n};\n\n/** Reference count — tracks how many providers have called initEditorClient. */\nlet _clientRefCount = 0;\n\n/**\n * Initialize the Intlayer editor client singleton.\n * Safe to call multiple times — returns the existing manager if already initialized.\n * Increments a reference counter so nested providers don't destroy the manager\n * prematurely when the inner provider unmounts.\n */\nexport const initEditorClient = (): EditorStateManager => {\n _clientRefCount++;\n\n const existing = getGlobalEditorManager();\n if (existing) return existing;\n\n const manager = new EditorStateManager({\n mode: 'client',\n messenger: buildClientMessengerConfig(),\n configuration: { editor },\n });\n\n setGlobalEditorManager(manager);\n defineIntlayerElements();\n manager.start();\n\n return manager;\n};\n\n/**\n * Decrement the reference count and stop the global editor client singleton\n * only when the last provider unmounts.\n */\nexport const stopEditorClient = (): void => {\n _clientRefCount = Math.max(0, _clientRefCount - 1);\n\n if (_clientRefCount > 0) return;\n\n const manager = getGlobalEditorManager();\n manager?.stop();\n setGlobalEditorManager(null);\n};\n"],"mappings":";;;;;;AASA,MAAa,mCAAoD;CAC/D,OAAO;EACL,gBAAgB,CAAC,QAAQ,WAAW,QAAQ,MAAM,EAAE,OAClD,OACF;EACA,gBAAgB,SAAkB,WAAmB;GACnD,IAAI,OAAO,WAAW,aAAa;GAInC,IAAI,EAFe,OAAO,SAAS,OAAO,MAEzB;GACjB,OAAO,QAAQ,YAAY,SAAS,MAAM;EAC5C;CACF;AACF;;AAGA,IAAI,kBAAkB;;;;;;;AAQtB,MAAa,yBAA6C;CACxD;CAEA,MAAM,WAAW,uBAAuB;CACxC,IAAI,UAAU,OAAO;CAErB,MAAM,UAAU,IAAI,mBAAmB;EACrC,MAAM;EACN,WAAW,2BAA2B;EACtC,eAAe,EAAE,OAAO;CAC1B,CAAC;CAED,uBAAuB,OAAO;CAC9B,uBAAuB;CACvB,QAAQ,MAAM;CAEd,OAAO;AACT;;;;;AAMA,MAAa,yBAA+B;CAC1C,kBAAkB,KAAK,IAAI,GAAG,kBAAkB,CAAC;CAEjD,IAAI,kBAAkB,GAAG;CAGzB,AADgB,uBACV,GAAG,KAAK;CACd,uBAAuB,IAAI;AAC7B"}
|
|
@@ -7,6 +7,7 @@ import { KeyPath } from "@intlayer/types/keyPath";
|
|
|
7
7
|
|
|
8
8
|
//#region src/core/EditorStateManager.d.ts
|
|
9
9
|
type DictionaryContent = Record<LocalDictionaryId, Dictionary>;
|
|
10
|
+
type EditorConfig = Pick<IntlayerConfig, 'editor'>;
|
|
10
11
|
type FileContent = {
|
|
11
12
|
dictionaryKey: string;
|
|
12
13
|
dictionaryLocalId?: LocalDictionaryId;
|
|
@@ -15,7 +16,7 @@ type FileContent = {
|
|
|
15
16
|
type EditorStateManagerConfig = {
|
|
16
17
|
/** 'client' = the app running inside the iframe; 'editor' = the editor wrapping the app */mode: 'editor' | 'client'; /** Cross-frame messaging configuration */
|
|
17
18
|
messenger: MessengerConfig; /** Optional initial Intlayer configuration to broadcast */
|
|
18
|
-
configuration?:
|
|
19
|
+
configuration?: EditorConfig;
|
|
19
20
|
};
|
|
20
21
|
/**
|
|
21
22
|
* EditorStateManager is the single entry point for all Intlayer editor state.
|
|
@@ -31,7 +32,7 @@ declare class EditorStateManager {
|
|
|
31
32
|
readonly focusedContent: CrossFrameStateManager<FileContent | null>;
|
|
32
33
|
readonly localeDictionaries: CrossFrameStateManager<DictionaryContent>;
|
|
33
34
|
readonly editedContent: CrossFrameStateManager<DictionaryContent>;
|
|
34
|
-
readonly configuration: CrossFrameStateManager<
|
|
35
|
+
readonly configuration: CrossFrameStateManager<EditorConfig>;
|
|
35
36
|
readonly currentLocale: CrossFrameStateManager<Locale | undefined>;
|
|
36
37
|
readonly displayedDictionaryKeys: CrossFrameStateManager<string[]>;
|
|
37
38
|
private readonly _urlManager;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorStateManager.d.ts","names":[],"sources":["../../../src/core/EditorStateManager.ts"],"mappings":";;;;;;;;KAiCY,iBAAA,GAAoB,MAAA,CAAO,iBAAA,EAAmB,UAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"EditorStateManager.d.ts","names":[],"sources":["../../../src/core/EditorStateManager.ts"],"mappings":";;;;;;;;KAiCY,iBAAA,GAAoB,MAAA,CAAO,iBAAA,EAAmB,UAAA;AAAA,KAErD,YAAA,GAAe,IAAI,CAAC,cAAA;AAAA,KAEb,WAAA;EACV,aAAA;EACA,iBAAA,GAAoB,iBAAA;EACpB,OAAA,GAAU,OAAO;AAAA;AAAA,KAGP,wBAAA;EAV0B,2FAYpC,IAAA,uBAZ8B;EAc9B,SAAA,EAAW,eAAA,EAd6C;EAgBxD,aAAA,GAAgB,YAAY;AAAA;AAhBwC;;;;AAE/B;AAEvC;;;AAJsE,cA2BzD,kBAAA;EAAA,SACF,SAAA,EAAW,mBAAA;EAAA,SACX,aAAA,EAAe,sBAAA;EAAA,SACf,cAAA,EAAgB,sBAAA,CAAuB,WAAA;EAAA,SACvC,kBAAA,EAAoB,sBAAA,CAAuB,iBAAA;EAAA,SAC3C,aAAA,EAAe,sBAAA,CAAuB,iBAAA;EAAA,SACtC,aAAA,EAAe,sBAAA,CAAuB,YAAA;EAAA,SACtC,aAAA,EAAe,sBAAA,CAAuB,MAAA;EAAA,SACtC,uBAAA,EAAyB,sBAAA;EAAA,iBAEjB,WAAA;EAAA,iBACA,kBAAA;EAAA,iBACA,KAAA;EAAA,iBACA,cAAA;EAAA,QAGT,iBAAA;EAAA,QACA,cAAA;EAAA,QAEA,iBAAA;EAAA,QAGA,sBAAA;EAAA,QACA,mBAAA;EAAA,QACA,uBAAA;EAAA,QAGA,qBAAA;EAAA,QACA,yBAAA;EAAA,QACA,wBAAA;EAAA,QAGA,sBAAA;EAAA,QACA,0BAAA;EAAA,QACA,yBAAA;cAEI,MAAA,EAAQ,wBAAA;EA+DpB,KAAA,CAAA;EA6BA,IAAA,CAAA;EA3H+C;;;;EAwJ/C,UAAA,CAAA;EAQA,wBAAA,CAAyB,OAAA,EAAS,OAAA;EAalC,mBAAA,CAAoB,UAAA,EAAY,UAAA;EAYhC,mBAAA,CAAoB,OAAA,EAAS,UAAA;EAa7B,gBAAA,CACE,iBAAA,EAAmB,iBAAA,EACnB,QAAA,EAAU,UAAA;EAaZ,UAAA,CACE,iBAAA,EAAmB,iBAAA,EACnB,QAAA,EAAU,WAAA,EACV,OAAA,GAAS,OAAA,IACT,SAAA;EAgDF,aAAA,CACE,iBAAA,EAAmB,iBAAA,EACnB,MAAA,EAAQ,OAAA,SACR,OAAA,GAAS,OAAA;EAmBX,aAAA,CACE,iBAAA,EAAmB,iBAAA,EACnB,OAAA,EAAS,OAAA;EAwBX,cAAA,CAAe,iBAAA,EAAmB,iBAAA;EASlC,YAAA,CAAa,iBAAA,EAAmB,iBAAA;EAShC,eAAA,CAAA;EAIA,eAAA,CACE,sBAAA,EAAwB,iBAAA,WACxB,OAAA,EAAS,OAAA,KACR,WAAA;EAAA,QAsDK,0BAAA;EAAA,QA+BA,yBAAA;EAAA,QAcA,2BAAA;EAAA,QA4BA,0BAAA;EAAA,QAcA,4BAAA;EAAA,QAeA,mCAAA;EAAA,QA8BA,kCAAA;EA5LkB;;;;EAAA,QA+MlB,qBAAA;EAAA,QAcA,yBAAA;EAAA,QAsBA,cAAA;EAAA,QA2BM,iBAAA;AAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intlayer/editor",
|
|
3
|
-
"version": "8.11.
|
|
3
|
+
"version": "8.11.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Provides the utilities to interface the application with the Intlayer editor and manipulate dictionaries",
|
|
6
6
|
"keywords": [
|
|
@@ -75,10 +75,10 @@
|
|
|
75
75
|
"typecheck": "tsc --noEmit --project tsconfig.types.json"
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@intlayer/config": "8.11.
|
|
79
|
-
"@intlayer/core": "8.11.
|
|
80
|
-
"@intlayer/types": "8.11.
|
|
81
|
-
"@intlayer/unmerged-dictionaries-entry": "8.11.
|
|
78
|
+
"@intlayer/config": "8.11.2",
|
|
79
|
+
"@intlayer/core": "8.11.2",
|
|
80
|
+
"@intlayer/types": "8.11.2",
|
|
81
|
+
"@intlayer/unmerged-dictionaries-entry": "8.11.2"
|
|
82
82
|
},
|
|
83
83
|
"devDependencies": {
|
|
84
84
|
"@types/node": "25.9.1",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"@utils/ts-config-types": "1.0.4",
|
|
87
87
|
"@utils/tsdown-config": "1.0.4",
|
|
88
88
|
"rimraf": "6.1.3",
|
|
89
|
-
"tsdown": "0.22.
|
|
89
|
+
"tsdown": "0.22.1",
|
|
90
90
|
"typescript": "6.0.3",
|
|
91
91
|
"vitest": "4.1.7"
|
|
92
92
|
},
|