@intlayer/editor 8.7.6 → 8.7.7
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/ContentSelector.cjs +85 -75
- package/dist/cjs/components/ContentSelector.cjs.map +1 -1
- package/dist/cjs/components/ContentSelectorWrapper.cjs +131 -95
- package/dist/cjs/components/ContentSelectorWrapper.cjs.map +1 -1
- package/dist/cjs/components/EditedContent.cjs +74 -49
- package/dist/cjs/components/EditedContent.cjs.map +1 -1
- package/dist/cjs/components/IntlayerEditor.cjs +34 -27
- package/dist/cjs/components/IntlayerEditor.cjs.map +1 -1
- package/dist/cjs/core/CrossFrameMessenger.cjs +6 -3
- package/dist/cjs/core/CrossFrameMessenger.cjs.map +1 -1
- package/dist/cjs/core/CrossFrameStateManager.cjs +5 -1
- package/dist/cjs/core/CrossFrameStateManager.cjs.map +1 -1
- package/dist/cjs/core/EditorStateManager.cjs +14 -3
- package/dist/cjs/core/EditorStateManager.cjs.map +1 -1
- package/dist/cjs/core/IframeClickInterceptor.cjs +3 -2
- package/dist/cjs/core/IframeClickInterceptor.cjs.map +1 -1
- package/dist/cjs/core/UrlStateManager.cjs +4 -3
- package/dist/cjs/core/UrlStateManager.cjs.map +1 -1
- package/dist/cjs/core/globalManager.cjs.map +1 -1
- package/dist/cjs/core/initEditorClient.cjs.map +1 -1
- package/dist/esm/components/ContentSelector.mjs +85 -74
- package/dist/esm/components/ContentSelector.mjs.map +1 -1
- package/dist/esm/components/ContentSelectorWrapper.mjs +131 -95
- package/dist/esm/components/ContentSelectorWrapper.mjs.map +1 -1
- package/dist/esm/components/EditedContent.mjs +74 -49
- package/dist/esm/components/EditedContent.mjs.map +1 -1
- package/dist/esm/components/IntlayerEditor.mjs +34 -26
- package/dist/esm/components/IntlayerEditor.mjs.map +1 -1
- package/dist/esm/core/CrossFrameMessenger.mjs +6 -3
- package/dist/esm/core/CrossFrameMessenger.mjs.map +1 -1
- package/dist/esm/core/CrossFrameStateManager.mjs +5 -1
- package/dist/esm/core/CrossFrameStateManager.mjs.map +1 -1
- package/dist/esm/core/EditorStateManager.mjs +14 -3
- package/dist/esm/core/EditorStateManager.mjs.map +1 -1
- package/dist/esm/core/IframeClickInterceptor.mjs +3 -2
- package/dist/esm/core/IframeClickInterceptor.mjs.map +1 -1
- package/dist/esm/core/UrlStateManager.mjs +4 -3
- package/dist/esm/core/UrlStateManager.mjs.map +1 -1
- package/dist/esm/core/globalManager.mjs.map +1 -1
- package/dist/esm/core/initEditorClient.mjs.map +1 -1
- package/dist/types/components/ContentSelector.d.ts +15 -10
- package/dist/types/components/ContentSelector.d.ts.map +1 -1
- package/dist/types/components/ContentSelectorWrapper.d.ts +22 -12
- package/dist/types/components/ContentSelectorWrapper.d.ts.map +1 -1
- package/dist/types/components/EditedContent.d.ts +21 -10
- package/dist/types/components/EditedContent.d.ts.map +1 -1
- package/dist/types/components/IntlayerEditor.d.ts +16 -10
- package/dist/types/components/IntlayerEditor.d.ts.map +1 -1
- package/package.json +7 -8
- package/dist/cjs/_virtual/_@oxc-project_runtime@0.126.0/helpers/decorate.cjs +0 -11
- package/dist/esm/_virtual/_@oxc-project_runtime@0.126.0/helpers/decorate.mjs +0 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContentSelectorWrapper.mjs","names":[],"sources":["../../../src/components/ContentSelectorWrapper.ts"],"sourcesContent":["import { isSameKeyPath } from '@intlayer/core/utils';\nimport type { ContentNode } from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport type { TypedNodeModel } from '@intlayer/types/nodeType';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { css, html, LitElement } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport type {\n EditorStateManager,\n FileContent,\n} from '../core/EditorStateManager';\nimport {\n getGlobalEditorManager,\n onGlobalEditorManagerChange,\n} from '../core/globalManager';\nimport { MessageKey } from '../messageKey';\n\n/**\n * <intlayer-content-selector-wrapper>\n *\n * Framework-agnostic Lit element that wraps content with the Intlayer editor\n * selection UI. It replaces the per-framework ContentSelectorWrapper components\n * (Vue, Svelte, Solid, Preact).\n *\n * It reads from the global EditorStateManager singleton (set by initEditorClient)\n * and conditionally renders <intlayer-content-selector> around its slot content\n * when the editor is active and the app is running inside an iframe.\n *\n * @attr {string} key-path - JSON-serialized KeyPath[] for this content node\n * @attr {string} dictionary-key - The dictionary key owning this content node\n */\nexport class IntlayerContentSelectorWrapperElement extends LitElement {\n static styles = css`\n :host {\n display: contents;\n }\n `;\n\n @property({ type: String, attribute: 'key-path' }) keyPathJson = '[]';\n @property({ type: String, attribute: 'dictionary-key' }) dictionaryKey = '';\n\n @state() private _editorEnabled = false;\n @state() private _isInIframe = false;\n @state() private _isSelected = false;\n @state() private _editedValue: ContentNode | undefined = undefined;\n\n private _unsubManager: (() => void) | null = null;\n private _unsubEnabled: (() => void) | null = null;\n private _unsubFocused: (() => void) | null = null;\n private _unsubEditedContent: (() => void) | null = null;\n\n connectedCallback(): void {\n super.connectedCallback();\n if (typeof window !== 'undefined') {\n this._isInIframe = window.self !== window.top;\n }\n this._subscribeToManager();\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n this._teardown();\n }\n\n updated(changedProperties: Map<string, unknown>): void {\n if (\n changedProperties.has('keyPathJson') ||\n changedProperties.has('dictionaryKey')\n ) {\n const manager = getGlobalEditorManager();\n if (manager) this._updateEditedValue(manager);\n }\n }\n\n private _teardown(): void {\n this._unsubManager?.();\n this._unsubEnabled?.();\n this._unsubFocused?.();\n this._unsubEditedContent?.();\n this._unsubManager = null;\n this._unsubEnabled = null;\n this._unsubFocused = null;\n this._unsubEditedContent = null;\n }\n\n private _subscribeToManager(): void {\n const manager = getGlobalEditorManager();\n if (manager) {\n this._setupManagerSubscriptions(manager);\n }\n // Keep listening for manager changes (handles stop + re-init cycles)\n this._unsubManager = onGlobalEditorManagerChange((m) => {\n this._unsubEnabled?.();\n this._unsubFocused?.();\n this._unsubEditedContent?.();\n this._unsubEnabled = null;\n this._unsubFocused = null;\n this._unsubEditedContent = null;\n if (m) {\n this._setupManagerSubscriptions(m);\n } else {\n this._editorEnabled = false;\n this._isSelected = false;\n this._editedValue = undefined;\n }\n });\n }\n\n private _setupManagerSubscriptions(manager: EditorStateManager): void {\n this._editorEnabled = manager.editorEnabled.value ?? false;\n this._updateIsSelected(manager.focusedContent.value);\n this._updateEditedValue(manager);\n\n const handleEnabledChange = (e: Event) => {\n this._editorEnabled = (e as CustomEvent<boolean>).detail;\n };\n const handleFocusedChange = (e: Event) => {\n this._updateIsSelected((e as CustomEvent<FileContent | null>).detail);\n };\n const handleEditedContentChange = () => {\n this._updateEditedValue(manager);\n };\n\n manager.editorEnabled.addEventListener('change', handleEnabledChange);\n manager.focusedContent.addEventListener('change', handleFocusedChange);\n manager.editedContent.addEventListener('change', handleEditedContentChange);\n\n this._unsubEnabled = () =>\n manager.editorEnabled.removeEventListener('change', handleEnabledChange);\n this._unsubFocused = () =>\n manager.focusedContent.removeEventListener('change', handleFocusedChange);\n this._unsubEditedContent = () =>\n manager.editedContent.removeEventListener(\n 'change',\n handleEditedContentChange\n );\n }\n\n private _getRawKeyPath(): KeyPath[] {\n try {\n return JSON.parse(this.keyPathJson) as KeyPath[];\n } catch {\n return [];\n }\n }\n\n private _getFilteredKeyPath(): KeyPath[] {\n return this._getRawKeyPath().filter(\n (k) => k.type !== NodeTypes.TRANSLATION\n );\n }\n\n private _updateEditedValue(manager: EditorStateManager): void {\n const filteredKeyPath = this._getFilteredKeyPath();\n if (!this.dictionaryKey || filteredKeyPath.length === 0) {\n this._editedValue = undefined;\n return;\n }\n\n // Node types whose display requires framework-level rendering (markdown,\n // HTML, insertion, file): do not override the slot — the framework handles\n // those. Only plain / translated strings can be substituted here.\n const rawKeyPath = this._getRawKeyPath();\n const lastStepType = rawKeyPath[rawKeyPath.length - 1]?.type;\n if (\n lastStepType === NodeTypes.MARKDOWN ||\n lastStepType === NodeTypes.HTML ||\n lastStepType === NodeTypes.INSERTION ||\n lastStepType === NodeTypes.FILE\n ) {\n this._editedValue = undefined;\n return;\n }\n\n let value = manager.getContentValue(this.dictionaryKey, filteredKeyPath);\n\n // getContentNodeByKeyPath resolves translation nodes only at intermediate\n // steps, not the final leaf. Resolve manually when the returned value is\n // still a translation object (happens when Translation steps are filtered\n // out and the leaf IS the translation object).\n if (\n value !== null &&\n value !== undefined &&\n typeof value === 'object' &&\n value.nodeType === NodeTypes.TRANSLATION\n ) {\n const locale = manager.currentLocale.value as string | undefined;\n // TypedNodeModel<Translation, …> structurally satisfies TypedNode<BaseNode>\n // (both have nodeType), so this narrowing cast is sound.\n const node = value as TypedNodeModel<\n typeof NodeTypes.TRANSLATION,\n Record<string, ContentNode>\n >;\n value = locale ? node[NodeTypes.TRANSLATION][locale] : undefined;\n }\n\n this._editedValue = value;\n }\n\n private _updateIsSelected(\n focusedContent: FileContent | null | undefined\n ): void {\n if (!focusedContent) {\n this._isSelected = false;\n return;\n }\n const keyPath = this._getFilteredKeyPath();\n this._isSelected =\n focusedContent.dictionaryKey === this.dictionaryKey &&\n (focusedContent.keyPath?.length ?? 0) > 0 &&\n isSameKeyPath(focusedContent.keyPath ?? [], keyPath);\n }\n\n private _handlePress(e: Event): void {\n // Stop propagation so nested wrappers don't also fire (composed + bubbles)\n e.stopPropagation();\n const manager = getGlobalEditorManager();\n if (!manager) return;\n manager.focusedContent.set({\n dictionaryKey: this.dictionaryKey,\n keyPath: this._getFilteredKeyPath(),\n });\n }\n\n private _handleHover(e: Event): void {\n e.stopPropagation();\n getGlobalEditorManager()?.messenger.send(\n `${MessageKey.INTLAYER_HOVERED_CONTENT_CHANGED}/post`,\n { dictionaryKey: this.dictionaryKey, keyPath: this._getFilteredKeyPath() }\n );\n }\n\n private _handleUnhover(e: Event): void {\n e.stopPropagation();\n getGlobalEditorManager()?.messenger.send(\n `${MessageKey.INTLAYER_HOVERED_CONTENT_CHANGED}/post`,\n null\n );\n }\n\n render() {\n if (!this._isInIframe || !this._editorEnabled) {\n return html`<slot></slot>`;\n }\n\n const editedValue = this._editedValue;\n const displayedContent =\n typeof editedValue === 'string' ||\n typeof editedValue === 'number' ||\n typeof editedValue === 'boolean'\n ? editedValue\n : html`<slot></slot>`;\n\n return html`\n <intlayer-content-selector\n ?is-selecting=${this._isSelected}\n @intlayer:press=${this._handlePress}\n @intlayer:hover=${this._handleHover}\n @intlayer:unhover=${this._handleUnhover}\n >\n ${displayedContent}\n </intlayer-content-selector>\n `;\n }\n}\n\nexport const defineIntlayerContentSelectorWrapper = (): void => {\n if (typeof customElements === 'undefined') return;\n\n if (!customElements.get('intlayer-content-selector-wrapper')) {\n customElements.define(\n 'intlayer-content-selector-wrapper',\n IntlayerContentSelectorWrapperElement\n );\n }\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ContentSelectorWrapper.mjs","names":["node"],"sources":["../../../src/components/ContentSelectorWrapper.ts"],"sourcesContent":["import { isSameKeyPath } from '@intlayer/core/utils';\n\nimport type { ContentNode } from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport type { TypedNodeModel } from '@intlayer/types/nodeType';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport type {\n EditorStateManager,\n FileContent,\n} from '../core/EditorStateManager';\nimport {\n getGlobalEditorManager,\n onGlobalEditorManagerChange,\n} from '../core/globalManager';\nimport { MessageKey } from '../messageKey';\n\ntype RenderState = 'simple' | 'wrapped-slot' | 'wrapped-text';\n\nconst _HTMLElement =\n typeof HTMLElement !== 'undefined'\n ? HTMLElement\n : (class {} as unknown as typeof HTMLElement);\n\n/**\n * <intlayer-content-selector-wrapper>\n *\n * Framework-agnostic web component that wraps content with the Intlayer editor\n * selection UI. It replaces the per-framework ContentSelectorWrapper components\n * (Vue, Svelte, Solid, Preact).\n *\n * It reads from the global EditorStateManager singleton (set by initEditorClient)\n * and conditionally renders <intlayer-content-selector> around its slot content\n * when the editor is active and the app is running inside an iframe.\n *\n * @attr {string} key-path - JSON-serialized KeyPath[] for this content node\n * @attr {string} dictionary-key - The dictionary key owning this content node\n */\nexport class IntlayerContentSelectorWrapperElement extends _HTMLElement {\n private _keyPathJson = '[]';\n private _dictionaryKey = '';\n private _editorEnabled = false;\n private _isInIframe = false;\n private _isSelected = false;\n private _editedValue: ContentNode | undefined = undefined;\n\n private _renderState: RenderState | null = null;\n private _selector: HTMLElement | null = null;\n\n private _unsubManager: (() => void) | null = null;\n private _unsubEnabled: (() => void) | null = null;\n private _unsubFocused: (() => void) | null = null;\n private _unsubEditedContent: (() => void) | null = null;\n\n static get observedAttributes(): string[] {\n return ['key-path', 'dictionary-key'];\n }\n\n get keyPathJson(): string {\n return this._keyPathJson;\n }\n set keyPathJson(v: string) {\n this._keyPathJson = v;\n const manager = getGlobalEditorManager();\n if (manager) this._updateEditedValue(manager);\n }\n\n get dictionaryKey(): string {\n return this._dictionaryKey;\n }\n set dictionaryKey(v: string) {\n this._dictionaryKey = v;\n const manager = getGlobalEditorManager();\n if (manager) this._updateEditedValue(manager);\n }\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = ':host { display: contents; }';\n shadow.appendChild(style);\n }\n\n attributeChangedCallback(\n name: string,\n _oldVal: string | null,\n newVal: string | null\n ): void {\n if (name === 'key-path') {\n this._keyPathJson = newVal ?? '[]';\n const manager = getGlobalEditorManager();\n if (manager) this._updateEditedValue(manager);\n } else if (name === 'dictionary-key') {\n this._dictionaryKey = newVal ?? '';\n const manager = getGlobalEditorManager();\n if (manager) this._updateEditedValue(manager);\n }\n }\n\n connectedCallback(): void {\n if (typeof window !== 'undefined') {\n this._isInIframe = window.self !== window.top;\n }\n this._subscribeToManager();\n this._render();\n }\n\n disconnectedCallback(): void {\n this._teardown();\n }\n\n private _teardown(): void {\n this._unsubManager?.();\n this._unsubEnabled?.();\n this._unsubFocused?.();\n this._unsubEditedContent?.();\n this._unsubManager = null;\n this._unsubEnabled = null;\n this._unsubFocused = null;\n this._unsubEditedContent = null;\n }\n\n private _getRawKeyPath(): KeyPath[] {\n try {\n return JSON.parse(this._keyPathJson) as KeyPath[];\n } catch {\n return [];\n }\n }\n\n private _getFilteredKeyPath(): KeyPath[] {\n return this._getRawKeyPath().filter(\n (k) => k.type !== NodeTypes.TRANSLATION\n );\n }\n\n private _updateEditedValue(manager: EditorStateManager): void {\n const filteredKeyPath = this._getFilteredKeyPath();\n if (!this._dictionaryKey || filteredKeyPath.length === 0) {\n this._editedValue = undefined;\n this._render();\n return;\n }\n\n // Node types whose display requires framework-level rendering (markdown,\n // HTML, insertion, file): do not override the slot — the framework handles\n // those. Only plain / translated strings can be substituted here.\n const rawKeyPath = this._getRawKeyPath();\n const lastStepType = rawKeyPath[rawKeyPath.length - 1]?.type;\n if (\n lastStepType === NodeTypes.MARKDOWN ||\n lastStepType === NodeTypes.HTML ||\n lastStepType === NodeTypes.INSERTION ||\n lastStepType === NodeTypes.FILE\n ) {\n this._editedValue = undefined;\n this._render();\n return;\n }\n\n let value = manager.getContentValue(this._dictionaryKey, filteredKeyPath);\n\n // getContentNodeByKeyPath resolves translation nodes only at intermediate\n // steps, not the final leaf. Resolve manually when the returned value is\n // still a translation object (happens when Translation steps are filtered\n // out and the leaf IS the translation object).\n if (\n value !== null &&\n value !== undefined &&\n typeof value === 'object' &&\n (value as { nodeType?: unknown }).nodeType === NodeTypes.TRANSLATION\n ) {\n const locale = manager.currentLocale.value as string | undefined;\n // TypedNodeModel<Translation, …> structurally satisfies TypedNode<BaseNode>\n // (both have nodeType), so this narrowing cast is sound.\n const node = value as TypedNodeModel<\n typeof NodeTypes.TRANSLATION,\n Record<string, ContentNode>\n >;\n value = locale ? node[NodeTypes.TRANSLATION][locale] : undefined;\n }\n\n this._editedValue = value;\n this._render();\n }\n\n private _updateIsSelected(\n focusedContent: FileContent | null | undefined\n ): void {\n if (!focusedContent) {\n this._isSelected = false;\n this._updateSelectorAttr();\n return;\n }\n const keyPath = this._getFilteredKeyPath();\n this._isSelected =\n focusedContent.dictionaryKey === this._dictionaryKey &&\n (focusedContent.keyPath?.length ?? 0) > 0 &&\n isSameKeyPath(focusedContent.keyPath ?? [], keyPath);\n this._updateSelectorAttr();\n }\n\n private _updateSelectorAttr(): void {\n if (!this._selector) return;\n if (this._isSelected) {\n this._selector.setAttribute('is-selecting', '');\n } else {\n this._selector.removeAttribute('is-selecting');\n }\n }\n\n private _subscribeToManager(): void {\n const manager = getGlobalEditorManager();\n if (manager) {\n this._setupManagerSubscriptions(manager);\n }\n // Keep listening for manager changes (handles stop + re-init cycles)\n this._unsubManager = onGlobalEditorManagerChange((m) => {\n this._unsubEnabled?.();\n this._unsubFocused?.();\n this._unsubEditedContent?.();\n this._unsubEnabled = null;\n this._unsubFocused = null;\n this._unsubEditedContent = null;\n if (m) {\n this._setupManagerSubscriptions(m);\n } else {\n this._editorEnabled = false;\n this._isSelected = false;\n this._editedValue = undefined;\n this._render();\n }\n });\n }\n\n private _setupManagerSubscriptions(manager: EditorStateManager): void {\n this._editorEnabled = manager.editorEnabled.value ?? false;\n this._updateIsSelected(manager.focusedContent.value);\n this._updateEditedValue(manager);\n\n const handleEnabledChange = (e: Event) => {\n this._editorEnabled = (e as CustomEvent<boolean>).detail;\n this._render();\n };\n const handleFocusedChange = (e: Event) => {\n this._updateIsSelected((e as CustomEvent<FileContent | null>).detail);\n };\n const handleEditedContentChange = () => {\n this._updateEditedValue(manager);\n };\n\n manager.editorEnabled.addEventListener('change', handleEnabledChange);\n manager.focusedContent.addEventListener('change', handleFocusedChange);\n manager.editedContent.addEventListener('change', handleEditedContentChange);\n\n this._unsubEnabled = () =>\n manager.editorEnabled.removeEventListener('change', handleEnabledChange);\n this._unsubFocused = () =>\n manager.focusedContent.removeEventListener('change', handleFocusedChange);\n this._unsubEditedContent = () =>\n manager.editedContent.removeEventListener(\n 'change',\n handleEditedContentChange\n );\n }\n\n private _handlePress(e: Event): void {\n // Stop propagation so nested wrappers don't also fire (composed + bubbles)\n e.stopPropagation();\n const manager = getGlobalEditorManager();\n if (!manager) return;\n manager.focusedContent.set({\n dictionaryKey: this._dictionaryKey,\n keyPath: this._getFilteredKeyPath(),\n });\n }\n\n private _handleHover(e: Event): void {\n e.stopPropagation();\n getGlobalEditorManager()?.messenger.send(\n `${MessageKey.INTLAYER_HOVERED_CONTENT_CHANGED}/post`,\n {\n dictionaryKey: this._dictionaryKey,\n keyPath: this._getFilteredKeyPath(),\n }\n );\n }\n\n private _handleUnhover(e: Event): void {\n e.stopPropagation();\n getGlobalEditorManager()?.messenger.send(\n `${MessageKey.INTLAYER_HOVERED_CONTENT_CHANGED}/post`,\n null\n );\n }\n\n private _render(): void {\n const useWrapper = this._isInIframe && this._editorEnabled;\n const editedValue = this._editedValue;\n const isSimpleValue =\n typeof editedValue === 'string' ||\n typeof editedValue === 'number' ||\n typeof editedValue === 'boolean';\n\n const newState: RenderState = !useWrapper\n ? 'simple'\n : isSimpleValue\n ? 'wrapped-text'\n : 'wrapped-slot';\n\n if (this._renderState !== newState) {\n this._rebuildContent(newState);\n return;\n }\n\n // Structure unchanged — update only dynamic parts\n if (newState !== 'simple' && this._selector) {\n this._updateSelectorAttr();\n if (\n newState === 'wrapped-text' &&\n this._selector.firstChild?.nodeType === Node.TEXT_NODE\n ) {\n (this._selector.firstChild as Text).data = String(editedValue);\n }\n }\n }\n\n private _rebuildContent(state: RenderState): void {\n const shadow = this.shadowRoot!;\n // Remove all nodes except the style element (first child)\n while (shadow.childNodes.length > 1) {\n shadow.removeChild(shadow.lastChild!);\n }\n this._selector = null;\n\n if (state === 'simple') {\n shadow.appendChild(document.createElement('slot'));\n } else {\n const selector = document.createElement('intlayer-content-selector');\n this._selector = selector;\n if (this._isSelected) selector.setAttribute('is-selecting', '');\n selector.addEventListener('intlayer:press', (e) => this._handlePress(e));\n selector.addEventListener('intlayer:hover', (e) => this._handleHover(e));\n selector.addEventListener('intlayer:unhover', (e) =>\n this._handleUnhover(e)\n );\n\n if (state === 'wrapped-text') {\n selector.appendChild(\n document.createTextNode(String(this._editedValue))\n );\n } else {\n selector.appendChild(document.createElement('slot'));\n }\n shadow.appendChild(selector);\n }\n\n this._renderState = state;\n }\n}\n\nexport const defineIntlayerContentSelectorWrapper = (): void => {\n if (typeof customElements === 'undefined') return;\n\n if (!customElements.get('intlayer-content-selector-wrapper')) {\n customElements.define(\n 'intlayer-content-selector-wrapper',\n IntlayerContentSelectorWrapperElement\n );\n }\n};\n"],"mappings":"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"}
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { getGlobalEditorManager, onGlobalEditorManagerChange } from "../core/globalManager.mjs";
|
|
2
|
-
import { __decorate } from "../_virtual/_@oxc-project_runtime@0.126.0/helpers/decorate.mjs";
|
|
3
|
-
import { LitElement, css, html } from "lit";
|
|
4
|
-
import { property, state } from "lit/decorators.js";
|
|
5
2
|
import { getBasePlugins, getContent } from "@intlayer/core/interpreter";
|
|
6
3
|
|
|
7
4
|
//#region src/components/EditedContent.ts
|
|
5
|
+
const _HTMLElement = typeof HTMLElement !== "undefined" ? HTMLElement : class {};
|
|
8
6
|
/**
|
|
9
7
|
* <intlayer-edited-content>
|
|
10
8
|
*
|
|
11
|
-
* Framework-agnostic
|
|
9
|
+
* Framework-agnostic web component that displays edited content from the Intlayer
|
|
12
10
|
* editor. When the editor has an edited value for the given dictionary key and
|
|
13
11
|
* key path, it renders the edited value; otherwise it renders the original
|
|
14
12
|
* content via a slot.
|
|
@@ -19,29 +17,67 @@ import { getBasePlugins, getContent } from "@intlayer/core/interpreter";
|
|
|
19
17
|
* @attr {string} key-path - JSON-serialized KeyPath[] for this content node
|
|
20
18
|
* @attr {string} locale - The current locale string
|
|
21
19
|
*/
|
|
22
|
-
var IntlayerEditedContentElement = class extends
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
20
|
+
var IntlayerEditedContentElement = class extends _HTMLElement {
|
|
21
|
+
_dictionaryKey = "";
|
|
22
|
+
_keyPathJson = "[]";
|
|
23
|
+
_locale = "";
|
|
24
|
+
_editedText = null;
|
|
25
|
+
_unsubManager = null;
|
|
26
|
+
_unsubEditedContent = null;
|
|
27
|
+
_selectorWrapper;
|
|
28
|
+
_slot;
|
|
29
|
+
static get observedAttributes() {
|
|
30
|
+
return [
|
|
31
|
+
"dictionary-key",
|
|
32
|
+
"key-path",
|
|
33
|
+
"locale"
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
get dictionaryKey() {
|
|
37
|
+
return this._dictionaryKey;
|
|
38
|
+
}
|
|
39
|
+
set dictionaryKey(v) {
|
|
40
|
+
this._dictionaryKey = v;
|
|
41
|
+
this._selectorWrapper.setAttribute("dictionary-key", v);
|
|
42
|
+
}
|
|
43
|
+
get keyPathJson() {
|
|
44
|
+
return this._keyPathJson;
|
|
45
|
+
}
|
|
46
|
+
set keyPathJson(v) {
|
|
47
|
+
this._keyPathJson = v;
|
|
48
|
+
this._selectorWrapper.setAttribute("key-path", v);
|
|
49
|
+
}
|
|
50
|
+
get locale() {
|
|
51
|
+
return this._locale;
|
|
31
52
|
}
|
|
32
|
-
|
|
33
|
-
this.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
53
|
+
set locale(v) {
|
|
54
|
+
this._locale = v;
|
|
55
|
+
}
|
|
56
|
+
constructor() {
|
|
57
|
+
super();
|
|
58
|
+
const shadow = this.attachShadow({ mode: "open" });
|
|
59
|
+
const style = document.createElement("style");
|
|
60
|
+
style.textContent = ":host { display: contents; }";
|
|
61
|
+
shadow.appendChild(style);
|
|
62
|
+
this._selectorWrapper = document.createElement("intlayer-content-selector-wrapper");
|
|
63
|
+
this._slot = document.createElement("slot");
|
|
64
|
+
this._selectorWrapper.appendChild(this._slot);
|
|
65
|
+
shadow.appendChild(this._selectorWrapper);
|
|
66
|
+
}
|
|
67
|
+
attributeChangedCallback(name, _oldVal, newVal) {
|
|
68
|
+
const val = newVal ?? "";
|
|
69
|
+
if (name === "dictionary-key") {
|
|
70
|
+
this._dictionaryKey = val;
|
|
71
|
+
this._selectorWrapper.setAttribute("dictionary-key", val);
|
|
72
|
+
} else if (name === "key-path") {
|
|
73
|
+
this._keyPathJson = val || "[]";
|
|
74
|
+
this._selectorWrapper.setAttribute("key-path", this._keyPathJson);
|
|
75
|
+
} else if (name === "locale") this._locale = val;
|
|
38
76
|
}
|
|
39
77
|
connectedCallback() {
|
|
40
|
-
super.connectedCallback();
|
|
41
78
|
this._subscribeToManager();
|
|
42
79
|
}
|
|
43
80
|
disconnectedCallback() {
|
|
44
|
-
super.disconnectedCallback();
|
|
45
81
|
this._teardown();
|
|
46
82
|
}
|
|
47
83
|
_teardown() {
|
|
@@ -52,27 +88,34 @@ var IntlayerEditedContentElement = class extends LitElement {
|
|
|
52
88
|
}
|
|
53
89
|
_getKeyPath() {
|
|
54
90
|
try {
|
|
55
|
-
return JSON.parse(this.
|
|
91
|
+
return JSON.parse(this._keyPathJson);
|
|
56
92
|
} catch {
|
|
57
93
|
return [];
|
|
58
94
|
}
|
|
59
95
|
}
|
|
96
|
+
_render() {
|
|
97
|
+
while (this._selectorWrapper.firstChild) this._selectorWrapper.removeChild(this._selectorWrapper.firstChild);
|
|
98
|
+
if (this._editedText !== null) this._selectorWrapper.appendChild(document.createTextNode(this._editedText));
|
|
99
|
+
else this._selectorWrapper.appendChild(this._slot);
|
|
100
|
+
}
|
|
60
101
|
_resolveEditedText(manager) {
|
|
61
102
|
const keyPath = this._getKeyPath();
|
|
62
|
-
const editedValue = manager.getContentValue(this.
|
|
103
|
+
const editedValue = manager.getContentValue(this._dictionaryKey, keyPath);
|
|
63
104
|
if (editedValue === void 0 || editedValue === null) {
|
|
64
105
|
this._editedText = null;
|
|
106
|
+
this._render();
|
|
65
107
|
return;
|
|
66
108
|
}
|
|
67
109
|
if (typeof editedValue === "string" || typeof editedValue === "number") {
|
|
68
110
|
this._editedText = String(editedValue);
|
|
111
|
+
this._render();
|
|
69
112
|
return;
|
|
70
113
|
}
|
|
71
114
|
if (typeof editedValue === "object") {
|
|
72
|
-
const locale = this.
|
|
115
|
+
const locale = this._locale || void 0;
|
|
73
116
|
const transformed = getContent(editedValue, {
|
|
74
117
|
locale,
|
|
75
|
-
dictionaryKey: this.
|
|
118
|
+
dictionaryKey: this._dictionaryKey,
|
|
76
119
|
keyPath
|
|
77
120
|
}, getBasePlugins(locale));
|
|
78
121
|
if (typeof transformed === "string" || typeof transformed === "number") this._editedText = String(transformed);
|
|
@@ -80,9 +123,11 @@ var IntlayerEditedContentElement = class extends LitElement {
|
|
|
80
123
|
console.error(`[intlayer-edited-content] Incorrect edited content format. Expected string. Value: ${JSON.stringify(transformed)}`);
|
|
81
124
|
this._editedText = null;
|
|
82
125
|
}
|
|
126
|
+
this._render();
|
|
83
127
|
return;
|
|
84
128
|
}
|
|
85
129
|
this._editedText = null;
|
|
130
|
+
this._render();
|
|
86
131
|
}
|
|
87
132
|
_setupManagerSubscriptions(manager) {
|
|
88
133
|
this._resolveEditedText(manager);
|
|
@@ -97,33 +142,13 @@ var IntlayerEditedContentElement = class extends LitElement {
|
|
|
97
142
|
this._unsubEditedContent?.();
|
|
98
143
|
this._unsubEditedContent = null;
|
|
99
144
|
if (m) this._setupManagerSubscriptions(m);
|
|
100
|
-
else
|
|
145
|
+
else {
|
|
146
|
+
this._editedText = null;
|
|
147
|
+
this._render();
|
|
148
|
+
}
|
|
101
149
|
});
|
|
102
150
|
}
|
|
103
|
-
render() {
|
|
104
|
-
return html`
|
|
105
|
-
<intlayer-content-selector-wrapper
|
|
106
|
-
key-path=${this.keyPathJson}
|
|
107
|
-
dictionary-key=${this.dictionaryKey}
|
|
108
|
-
>
|
|
109
|
-
${this._editedText !== null ? this._editedText : html`<slot></slot>`}
|
|
110
|
-
</intlayer-content-selector-wrapper>
|
|
111
|
-
`;
|
|
112
|
-
}
|
|
113
151
|
};
|
|
114
|
-
__decorate([property({
|
|
115
|
-
type: String,
|
|
116
|
-
attribute: "dictionary-key"
|
|
117
|
-
})], IntlayerEditedContentElement.prototype, "dictionaryKey", void 0);
|
|
118
|
-
__decorate([property({
|
|
119
|
-
type: String,
|
|
120
|
-
attribute: "key-path"
|
|
121
|
-
})], IntlayerEditedContentElement.prototype, "keyPathJson", void 0);
|
|
122
|
-
__decorate([property({
|
|
123
|
-
type: String,
|
|
124
|
-
attribute: "locale"
|
|
125
|
-
})], IntlayerEditedContentElement.prototype, "locale", void 0);
|
|
126
|
-
__decorate([state()], IntlayerEditedContentElement.prototype, "_editedText", void 0);
|
|
127
152
|
const defineIntlayerEditedContent = () => {
|
|
128
153
|
if (typeof customElements === "undefined") return;
|
|
129
154
|
if (!customElements.get("intlayer-edited-content")) customElements.define("intlayer-edited-content", IntlayerEditedContentElement);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditedContent.mjs","names":[],"sources":["../../../src/components/EditedContent.ts"],"sourcesContent":["import { getBasePlugins, getContent } from '@intlayer/core/interpreter';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport
|
|
1
|
+
{"version":3,"file":"EditedContent.mjs","names":[],"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,20 +1,18 @@
|
|
|
1
1
|
import { getGlobalEditorManager, onGlobalEditorManagerChange } from "../core/globalManager.mjs";
|
|
2
|
-
import { __decorate } from "../_virtual/_@oxc-project_runtime@0.126.0/helpers/decorate.mjs";
|
|
3
2
|
import { initEditorClient, stopEditorClient } from "../core/initEditorClient.mjs";
|
|
4
|
-
import { LitElement } from "lit";
|
|
5
|
-
import { property } from "lit/decorators.js";
|
|
6
3
|
|
|
7
4
|
//#region src/components/IntlayerEditor.ts
|
|
5
|
+
const _HTMLElement = typeof HTMLElement !== "undefined" ? HTMLElement : class {};
|
|
8
6
|
/**
|
|
9
7
|
* <intlayer-editor>
|
|
10
8
|
*
|
|
11
|
-
* A framework-agnostic
|
|
9
|
+
* A framework-agnostic web component that manages the Intlayer editor singleton
|
|
12
10
|
* lifecycle and keeps the current locale in sync with the EditorStateManager.
|
|
13
11
|
*
|
|
14
12
|
* Drop this element once at the root of your application to activate the editor.
|
|
15
|
-
* It renders no UI
|
|
13
|
+
* It renders no UI.
|
|
16
14
|
*
|
|
17
|
-
* @prop {IntlayerConfig} configuration - The Intlayer config (required; set as property, not attribute)
|
|
15
|
+
* @prop {IntlayerConfig} configuration - The Intlayer config (required; set as JS property, not attribute)
|
|
18
16
|
* @prop {string} locale - The active application locale (attribute/property)
|
|
19
17
|
*
|
|
20
18
|
* @example
|
|
@@ -24,22 +22,38 @@ import { property } from "lit/decorators.js";
|
|
|
24
22
|
* // Vue
|
|
25
23
|
* <intlayer-editor :configuration="config" :locale="currentLocale" />
|
|
26
24
|
*/
|
|
27
|
-
var IntlayerEditorElement = class extends
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
25
|
+
var IntlayerEditorElement = class extends _HTMLElement {
|
|
26
|
+
_configuration = void 0;
|
|
27
|
+
_locale = void 0;
|
|
28
|
+
_initialized = false;
|
|
29
|
+
_unsubManager = null;
|
|
30
|
+
static get observedAttributes() {
|
|
31
|
+
return ["locale"];
|
|
32
|
+
}
|
|
33
|
+
get configuration() {
|
|
34
|
+
return this._configuration;
|
|
35
|
+
}
|
|
36
|
+
set configuration(v) {
|
|
37
|
+
this._configuration = v;
|
|
38
|
+
if (!this._initialized) this._init();
|
|
39
|
+
}
|
|
40
|
+
get locale() {
|
|
41
|
+
return this._locale;
|
|
32
42
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
43
|
+
set locale(v) {
|
|
44
|
+
this._locale = v;
|
|
45
|
+
if (v && this._initialized) this._syncLocale(v);
|
|
46
|
+
}
|
|
47
|
+
attributeChangedCallback(name, _oldVal, newVal) {
|
|
48
|
+
if (name === "locale" && newVal !== null) {
|
|
49
|
+
this._locale = newVal;
|
|
50
|
+
if (this._initialized) this._syncLocale(newVal);
|
|
51
|
+
}
|
|
36
52
|
}
|
|
37
53
|
connectedCallback() {
|
|
38
|
-
super.connectedCallback();
|
|
39
54
|
this._init();
|
|
40
55
|
}
|
|
41
56
|
disconnectedCallback() {
|
|
42
|
-
super.disconnectedCallback();
|
|
43
57
|
this._unsubManager?.();
|
|
44
58
|
this._unsubManager = null;
|
|
45
59
|
if (this._initialized) {
|
|
@@ -47,33 +61,27 @@ var IntlayerEditorElement = class extends LitElement {
|
|
|
47
61
|
this._initialized = false;
|
|
48
62
|
}
|
|
49
63
|
}
|
|
50
|
-
updated(changedProperties) {
|
|
51
|
-
if (changedProperties.has("configuration") && !this._initialized) this._init();
|
|
52
|
-
if (changedProperties.has("locale") && this.locale) this._syncLocale(this.locale);
|
|
53
|
-
}
|
|
54
64
|
_init() {
|
|
55
65
|
if (this._initialized) return;
|
|
56
66
|
initEditorClient();
|
|
57
67
|
this._initialized = true;
|
|
58
|
-
if (this.
|
|
68
|
+
if (this._locale) this._syncLocale(this._locale);
|
|
59
69
|
}
|
|
60
70
|
_syncLocale(locale) {
|
|
61
71
|
const manager = getGlobalEditorManager();
|
|
62
72
|
if (manager) manager.currentLocale.set(locale);
|
|
63
73
|
else {
|
|
64
74
|
this._unsubManager?.();
|
|
65
|
-
this._unsubManager = onGlobalEditorManagerChange((
|
|
66
|
-
if (
|
|
75
|
+
this._unsubManager = onGlobalEditorManagerChange((m) => {
|
|
76
|
+
if (m) {
|
|
67
77
|
this._unsubManager?.();
|
|
68
78
|
this._unsubManager = null;
|
|
69
|
-
|
|
79
|
+
m.currentLocale.set(locale);
|
|
70
80
|
}
|
|
71
81
|
});
|
|
72
82
|
}
|
|
73
83
|
}
|
|
74
84
|
};
|
|
75
|
-
__decorate([property({ attribute: false })], IntlayerEditorElement.prototype, "configuration", void 0);
|
|
76
|
-
__decorate([property({ type: String })], IntlayerEditorElement.prototype, "locale", void 0);
|
|
77
85
|
const defineIntlayerEditorElement = () => {
|
|
78
86
|
if (typeof customElements === "undefined") return;
|
|
79
87
|
if (!customElements.get("intlayer-editor")) customElements.define("intlayer-editor", IntlayerEditorElement);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IntlayerEditor.mjs","names":[],"sources":["../../../src/components/IntlayerEditor.ts"],"sourcesContent":["import type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport {
|
|
1
|
+
{"version":3,"file":"IntlayerEditor.mjs","names":[],"sources":["../../../src/components/IntlayerEditor.ts"],"sourcesContent":["import type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport {\n getGlobalEditorManager,\n onGlobalEditorManagerChange,\n} from '../core/globalManager';\nimport { initEditorClient, stopEditorClient } from '../core/initEditorClient';\n\nconst _HTMLElement =\n typeof HTMLElement !== 'undefined'\n ? HTMLElement\n : (class {} as unknown as typeof HTMLElement);\n\n/**\n * <intlayer-editor>\n *\n * A framework-agnostic web component that manages the Intlayer editor singleton\n * lifecycle and keeps the current locale in sync with the EditorStateManager.\n *\n * Drop this element once at the root of your application to activate the editor.\n * It renders no UI.\n *\n * @prop {IntlayerConfig} configuration - The Intlayer config (required; set as JS property, not attribute)\n * @prop {string} locale - The active application locale (attribute/property)\n *\n * @example\n * // Svelte\n * <intlayer-editor .configuration={config} locale={$locale} />\n *\n * // Vue\n * <intlayer-editor :configuration=\"config\" :locale=\"currentLocale\" />\n */\nexport class IntlayerEditorElement extends _HTMLElement {\n private _configuration: IntlayerConfig | undefined = undefined;\n private _locale: string | undefined = undefined;\n private _initialized = false;\n private _unsubManager: (() => void) | null = null;\n\n static get observedAttributes(): string[] {\n return ['locale'];\n }\n\n get configuration(): IntlayerConfig | undefined {\n return this._configuration;\n }\n set configuration(v: IntlayerConfig | undefined) {\n this._configuration = v;\n if (!this._initialized) this._init();\n }\n\n get locale(): string | undefined {\n return this._locale;\n }\n set locale(v: string | undefined) {\n this._locale = v;\n if (v && this._initialized) this._syncLocale(v);\n }\n\n attributeChangedCallback(\n name: string,\n _oldVal: string | null,\n newVal: string | null\n ): void {\n if (name === 'locale' && newVal !== null) {\n this._locale = newVal;\n if (this._initialized) this._syncLocale(newVal);\n }\n }\n\n connectedCallback(): void {\n this._init();\n }\n\n disconnectedCallback(): void {\n this._unsubManager?.();\n this._unsubManager = null;\n if (this._initialized) {\n stopEditorClient();\n this._initialized = false;\n }\n }\n\n private _init(): void {\n if (this._initialized) return;\n initEditorClient();\n this._initialized = true;\n if (this._locale) this._syncLocale(this._locale);\n }\n\n private _syncLocale(locale: string): void {\n const manager = getGlobalEditorManager();\n if (manager) {\n manager.currentLocale.set(locale as Locale);\n } else {\n // Manager may not be ready yet — wait for it\n this._unsubManager?.();\n this._unsubManager = onGlobalEditorManagerChange((m) => {\n if (m) {\n this._unsubManager?.();\n this._unsubManager = null;\n m.currentLocale.set(locale as Locale);\n }\n });\n }\n }\n}\n\nexport const defineIntlayerEditorElement = (): void => {\n if (typeof customElements === 'undefined') return;\n if (!customElements.get('intlayer-editor')) {\n customElements.define('intlayer-editor', IntlayerEditorElement);\n }\n};\n"],"mappings":";;;;AAQA,MAAM,eACJ,OAAO,gBAAgB,cACnB,cACC,MAAM;;;;;;;;;;;;;;;;;;;;AAqBb,IAAa,wBAAb,cAA2C,aAAa;CACtD,AAAQ,iBAA6C;CACrD,AAAQ,UAA8B;CACtC,AAAQ,eAAe;CACvB,AAAQ,gBAAqC;CAE7C,WAAW,qBAA+B;AACxC,SAAO,CAAC,SAAS;;CAGnB,IAAI,gBAA4C;AAC9C,SAAO,KAAK;;CAEd,IAAI,cAAc,GAA+B;AAC/C,OAAK,iBAAiB;AACtB,MAAI,CAAC,KAAK,aAAc,MAAK,OAAO;;CAGtC,IAAI,SAA6B;AAC/B,SAAO,KAAK;;CAEd,IAAI,OAAO,GAAuB;AAChC,OAAK,UAAU;AACf,MAAI,KAAK,KAAK,aAAc,MAAK,YAAY,EAAE;;CAGjD,yBACE,MACA,SACA,QACM;AACN,MAAI,SAAS,YAAY,WAAW,MAAM;AACxC,QAAK,UAAU;AACf,OAAI,KAAK,aAAc,MAAK,YAAY,OAAO;;;CAInD,oBAA0B;AACxB,OAAK,OAAO;;CAGd,uBAA6B;AAC3B,OAAK,iBAAiB;AACtB,OAAK,gBAAgB;AACrB,MAAI,KAAK,cAAc;AACrB,qBAAkB;AAClB,QAAK,eAAe;;;CAIxB,AAAQ,QAAc;AACpB,MAAI,KAAK,aAAc;AACvB,oBAAkB;AAClB,OAAK,eAAe;AACpB,MAAI,KAAK,QAAS,MAAK,YAAY,KAAK,QAAQ;;CAGlD,AAAQ,YAAY,QAAsB;EACxC,MAAM,UAAU,wBAAwB;AACxC,MAAI,QACF,SAAQ,cAAc,IAAI,OAAiB;OACtC;AAEL,QAAK,iBAAiB;AACtB,QAAK,gBAAgB,6BAA6B,MAAM;AACtD,QAAI,GAAG;AACL,UAAK,iBAAiB;AACtB,UAAK,gBAAgB;AACrB,OAAE,cAAc,IAAI,OAAiB;;KAEvC;;;;AAKR,MAAa,oCAA0C;AACrD,KAAI,OAAO,mBAAmB,YAAa;AAC3C,KAAI,CAAC,eAAe,IAAI,kBAAkB,CACxC,gBAAe,OAAO,mBAAmB,sBAAsB"}
|
|
@@ -10,10 +10,13 @@ const randomUUID = () => Math.random().toString(36).slice(2);
|
|
|
10
10
|
* Replaces CommunicatorContext + useCrossFrameMessageListener across all frameworks.
|
|
11
11
|
*/
|
|
12
12
|
var CrossFrameMessenger = class {
|
|
13
|
+
senderId;
|
|
14
|
+
_config;
|
|
15
|
+
_subscribers = /* @__PURE__ */ new Map();
|
|
16
|
+
_windowHandler = null;
|
|
17
|
+
/** Tracks recently processed messageIds to discard duplicates (same payload sent to multiple origins) */
|
|
18
|
+
_seenMessageIds = /* @__PURE__ */ new Set();
|
|
13
19
|
constructor(config) {
|
|
14
|
-
this._subscribers = /* @__PURE__ */ new Map();
|
|
15
|
-
this._windowHandler = null;
|
|
16
|
-
this._seenMessageIds = /* @__PURE__ */ new Set();
|
|
17
20
|
this._config = config;
|
|
18
21
|
this.senderId = randomUUID();
|
|
19
22
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CrossFrameMessenger.mjs","names":[],"sources":["../../../src/core/CrossFrameMessenger.ts"],"sourcesContent":["import { compareUrls } from '../compareUrls';\n\nconst randomUUID = (): string => Math.random().toString(36).slice(2);\n\nexport type MessagePayload = {\n type: string;\n data?: unknown;\n senderId?: string;\n /** Unique ID per send() call — used to deduplicate when the same payload arrives via multiple target origins */\n messageId?: string;\n};\n\nexport type MessengerConfig = {\n /**\n * Origins allowed to send messages to this instance.\n * Use '*' to allow all origins (not recommended for production).\n */\n allowedOrigins: string[];\n /**\n * Function used to send messages to other frames.\n * Injected so the messenger is agnostic to the frame topology.\n */\n postMessageFn: (payload: MessagePayload, origin: string) => void;\n};\n\ntype MessageHandler<T = unknown> = (data: T, senderId?: string) => void;\n\n/**\n * CrossFrameMessenger manages all cross-frame postMessage communication.\n * It owns a single window message listener and routes incoming messages to\n * type-specific subscribers.\n *\n * Replaces CommunicatorContext + useCrossFrameMessageListener across all frameworks.\n */\nexport class CrossFrameMessenger {\n readonly senderId: string;\n private readonly _config: MessengerConfig;\n private readonly _subscribers = new Map<string, Set<MessageHandler>>();\n\n private _windowHandler: ((event: MessageEvent) => void) | null = null;\n /** Tracks recently processed messageIds to discard duplicates (same payload sent to multiple origins) */\n private readonly _seenMessageIds = new Set<string>();\n\n constructor(config: MessengerConfig) {\n this._config = config;\n this.senderId = randomUUID();\n }\n\n /** Start listening for incoming messages on window. */\n start(): void {\n if (typeof window === 'undefined') return;\n if (this._windowHandler) return;\n this._windowHandler = (event: MessageEvent<MessagePayload>) => {\n this._handleMessage(event);\n };\n window.addEventListener('message', this._windowHandler);\n }\n\n /** Stop listening and clean up. */\n stop(): void {\n if (this._windowHandler) {\n window.removeEventListener('message', this._windowHandler);\n this._windowHandler = null;\n }\n }\n\n /** Send a message payload to all configured target origins. */\n send(type: string, data?: unknown): void {\n const payload: MessagePayload = {\n type,\n data,\n senderId: this.senderId,\n messageId: randomUUID(),\n };\n\n for (const origin of this._config.allowedOrigins) {\n if (origin) {\n this._config.postMessageFn(payload, origin);\n }\n }\n }\n\n /**\n * Subscribe to messages of a given type.\n * Returns an unsubscribe function.\n */\n subscribe<T = unknown>(type: string, handler: MessageHandler<T>): () => void {\n if (!this._subscribers.has(type)) {\n this._subscribers.set(type, new Set());\n }\n this._subscribers.get(type)!.add(handler as MessageHandler);\n return () => {\n this._subscribers.get(type)?.delete(handler as MessageHandler);\n };\n }\n\n private _handleMessage(event: MessageEvent<MessagePayload>): void {\n const payload = event.data;\n if (!payload || typeof payload !== 'object') return;\n\n const { type, data, senderId: msgSenderId, messageId } = payload;\n if (!type || typeof type !== 'string') return;\n\n // Ignore messages originating from this instance\n if (msgSenderId === this.senderId) return;\n\n // Deduplicate: same messageId may arrive multiple times when the sender\n // posts to multiple target origins (one per allowedOrigin)\n if (messageId) {\n if (this._seenMessageIds.has(messageId)) return;\n this._seenMessageIds.add(messageId);\n // Keep the set bounded — clear when it exceeds 200 entries\n if (this._seenMessageIds.size > 200) this._seenMessageIds.clear();\n }\n\n // Validate message origin\n const { allowedOrigins } = this._config;\n const isAllowed =\n !allowedOrigins ||\n allowedOrigins.length === 0 ||\n allowedOrigins.includes('*') ||\n allowedOrigins\n .filter((url) => Boolean(url) && url !== '')\n .some((url) => compareUrls(url, event.origin));\n\n if (!isAllowed) return;\n\n const handlers = this._subscribers.get(type);\n\n if (handlers) {\n for (const handler of handlers) {\n handler(data, msgSenderId);\n }\n }\n }\n}\n"],"mappings":";;;AAEA,MAAM,mBAA2B,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,EAAE;;;;;;;;AAgCpE,IAAa,sBAAb,MAAiC;
|
|
1
|
+
{"version":3,"file":"CrossFrameMessenger.mjs","names":[],"sources":["../../../src/core/CrossFrameMessenger.ts"],"sourcesContent":["import { compareUrls } from '../compareUrls';\n\nconst randomUUID = (): string => Math.random().toString(36).slice(2);\n\nexport type MessagePayload = {\n type: string;\n data?: unknown;\n senderId?: string;\n /** Unique ID per send() call — used to deduplicate when the same payload arrives via multiple target origins */\n messageId?: string;\n};\n\nexport type MessengerConfig = {\n /**\n * Origins allowed to send messages to this instance.\n * Use '*' to allow all origins (not recommended for production).\n */\n allowedOrigins: string[];\n /**\n * Function used to send messages to other frames.\n * Injected so the messenger is agnostic to the frame topology.\n */\n postMessageFn: (payload: MessagePayload, origin: string) => void;\n};\n\ntype MessageHandler<T = unknown> = (data: T, senderId?: string) => void;\n\n/**\n * CrossFrameMessenger manages all cross-frame postMessage communication.\n * It owns a single window message listener and routes incoming messages to\n * type-specific subscribers.\n *\n * Replaces CommunicatorContext + useCrossFrameMessageListener across all frameworks.\n */\nexport class CrossFrameMessenger {\n readonly senderId: string;\n private readonly _config: MessengerConfig;\n private readonly _subscribers = new Map<string, Set<MessageHandler>>();\n\n private _windowHandler: ((event: MessageEvent) => void) | null = null;\n /** Tracks recently processed messageIds to discard duplicates (same payload sent to multiple origins) */\n private readonly _seenMessageIds = new Set<string>();\n\n constructor(config: MessengerConfig) {\n this._config = config;\n this.senderId = randomUUID();\n }\n\n /** Start listening for incoming messages on window. */\n start(): void {\n if (typeof window === 'undefined') return;\n if (this._windowHandler) return;\n this._windowHandler = (event: MessageEvent<MessagePayload>) => {\n this._handleMessage(event);\n };\n window.addEventListener('message', this._windowHandler);\n }\n\n /** Stop listening and clean up. */\n stop(): void {\n if (this._windowHandler) {\n window.removeEventListener('message', this._windowHandler);\n this._windowHandler = null;\n }\n }\n\n /** Send a message payload to all configured target origins. */\n send(type: string, data?: unknown): void {\n const payload: MessagePayload = {\n type,\n data,\n senderId: this.senderId,\n messageId: randomUUID(),\n };\n\n for (const origin of this._config.allowedOrigins) {\n if (origin) {\n this._config.postMessageFn(payload, origin);\n }\n }\n }\n\n /**\n * Subscribe to messages of a given type.\n * Returns an unsubscribe function.\n */\n subscribe<T = unknown>(type: string, handler: MessageHandler<T>): () => void {\n if (!this._subscribers.has(type)) {\n this._subscribers.set(type, new Set());\n }\n this._subscribers.get(type)!.add(handler as MessageHandler);\n return () => {\n this._subscribers.get(type)?.delete(handler as MessageHandler);\n };\n }\n\n private _handleMessage(event: MessageEvent<MessagePayload>): void {\n const payload = event.data;\n if (!payload || typeof payload !== 'object') return;\n\n const { type, data, senderId: msgSenderId, messageId } = payload;\n if (!type || typeof type !== 'string') return;\n\n // Ignore messages originating from this instance\n if (msgSenderId === this.senderId) return;\n\n // Deduplicate: same messageId may arrive multiple times when the sender\n // posts to multiple target origins (one per allowedOrigin)\n if (messageId) {\n if (this._seenMessageIds.has(messageId)) return;\n this._seenMessageIds.add(messageId);\n // Keep the set bounded — clear when it exceeds 200 entries\n if (this._seenMessageIds.size > 200) this._seenMessageIds.clear();\n }\n\n // Validate message origin\n const { allowedOrigins } = this._config;\n const isAllowed =\n !allowedOrigins ||\n allowedOrigins.length === 0 ||\n allowedOrigins.includes('*') ||\n allowedOrigins\n .filter((url) => Boolean(url) && url !== '')\n .some((url) => compareUrls(url, event.origin));\n\n if (!isAllowed) return;\n\n const handlers = this._subscribers.get(type);\n\n if (handlers) {\n for (const handler of handlers) {\n handler(data, msgSenderId);\n }\n }\n }\n}\n"],"mappings":";;;AAEA,MAAM,mBAA2B,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,EAAE;;;;;;;;AAgCpE,IAAa,sBAAb,MAAiC;CAC/B,AAAS;CACT,AAAiB;CACjB,AAAiB,+BAAe,IAAI,KAAkC;CAEtE,AAAQ,iBAAyD;;CAEjE,AAAiB,kCAAkB,IAAI,KAAa;CAEpD,YAAY,QAAyB;AACnC,OAAK,UAAU;AACf,OAAK,WAAW,YAAY;;;CAI9B,QAAc;AACZ,MAAI,OAAO,WAAW,YAAa;AACnC,MAAI,KAAK,eAAgB;AACzB,OAAK,kBAAkB,UAAwC;AAC7D,QAAK,eAAe,MAAM;;AAE5B,SAAO,iBAAiB,WAAW,KAAK,eAAe;;;CAIzD,OAAa;AACX,MAAI,KAAK,gBAAgB;AACvB,UAAO,oBAAoB,WAAW,KAAK,eAAe;AAC1D,QAAK,iBAAiB;;;;CAK1B,KAAK,MAAc,MAAsB;EACvC,MAAM,UAA0B;GAC9B;GACA;GACA,UAAU,KAAK;GACf,WAAW,YAAY;GACxB;AAED,OAAK,MAAM,UAAU,KAAK,QAAQ,eAChC,KAAI,OACF,MAAK,QAAQ,cAAc,SAAS,OAAO;;;;;;CASjD,UAAuB,MAAc,SAAwC;AAC3E,MAAI,CAAC,KAAK,aAAa,IAAI,KAAK,CAC9B,MAAK,aAAa,IAAI,sBAAM,IAAI,KAAK,CAAC;AAExC,OAAK,aAAa,IAAI,KAAK,CAAE,IAAI,QAA0B;AAC3D,eAAa;AACX,QAAK,aAAa,IAAI,KAAK,EAAE,OAAO,QAA0B;;;CAIlE,AAAQ,eAAe,OAA2C;EAChE,MAAM,UAAU,MAAM;AACtB,MAAI,CAAC,WAAW,OAAO,YAAY,SAAU;EAE7C,MAAM,EAAE,MAAM,MAAM,UAAU,aAAa,cAAc;AACzD,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;AAGvC,MAAI,gBAAgB,KAAK,SAAU;AAInC,MAAI,WAAW;AACb,OAAI,KAAK,gBAAgB,IAAI,UAAU,CAAE;AACzC,QAAK,gBAAgB,IAAI,UAAU;AAEnC,OAAI,KAAK,gBAAgB,OAAO,IAAK,MAAK,gBAAgB,OAAO;;EAInE,MAAM,EAAE,mBAAmB,KAAK;AAShC,MAAI,EAPF,CAAC,kBACD,eAAe,WAAW,KAC1B,eAAe,SAAS,IAAI,IAC5B,eACG,QAAQ,QAAQ,QAAQ,IAAI,IAAI,QAAQ,GAAG,CAC3C,MAAM,QAAQ,YAAY,KAAK,MAAM,OAAO,CAAC,EAElC;EAEhB,MAAM,WAAW,KAAK,aAAa,IAAI,KAAK;AAE5C,MAAI,SACF,MAAK,MAAM,WAAW,SACpB,SAAQ,MAAM,YAAY"}
|
|
@@ -12,9 +12,13 @@
|
|
|
12
12
|
* @fires change — CustomEvent<T> dispatched whenever the value changes (local set or received)
|
|
13
13
|
*/
|
|
14
14
|
var CrossFrameStateManager = class extends EventTarget {
|
|
15
|
+
_value;
|
|
16
|
+
_key;
|
|
17
|
+
_messenger;
|
|
18
|
+
_options;
|
|
19
|
+
_unsubscribers = [];
|
|
15
20
|
constructor(key, messenger, options = {}) {
|
|
16
21
|
super();
|
|
17
|
-
this._unsubscribers = [];
|
|
18
22
|
this._key = key;
|
|
19
23
|
this._messenger = messenger;
|
|
20
24
|
this._options = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CrossFrameStateManager.mjs","names":[],"sources":["../../../src/core/CrossFrameStateManager.ts"],"sourcesContent":["import type { CrossFrameMessenger } from './CrossFrameMessenger';\n\nexport type CrossFrameStateOptions = {\n /** Whether to broadcast state changes to other frames. Default: true */\n emit?: boolean;\n /** Whether to listen for state updates from other frames. Default: true */\n receive?: boolean;\n};\n\n/**\n * CrossFrameStateManager synchronizes a single named value across frames using\n * the postMessage API via CrossFrameMessenger.\n *\n * Protocol:\n * `{key}/post` — broadcast a new value\n * `{key}/get` — request the current value from other frames\n *\n * Replaces useCrossFrameState across all frameworks.\n *\n * @fires change — CustomEvent<T> dispatched whenever the value changes (local set or received)\n */\nexport class CrossFrameStateManager<T> extends EventTarget {\n private _value: T | undefined;\n private readonly _key: string;\n private readonly _messenger: CrossFrameMessenger;\n private readonly _options: Required<CrossFrameStateOptions>;\n private readonly _unsubscribers: Array<() => void> = [];\n\n constructor(\n key: string,\n messenger: CrossFrameMessenger,\n options: CrossFrameStateOptions & { initialValue?: T } = {}\n ) {\n super();\n this._key = key;\n this._messenger = messenger;\n this._options = {\n emit: options.emit ?? true,\n receive: options.receive ?? true,\n };\n if (options.initialValue !== undefined) {\n this._value = options.initialValue;\n }\n }\n\n get value(): T | undefined {\n return this._value;\n }\n\n /** Update the value locally and broadcast it to other frames if emit is enabled. */\n set(newValue: T): void {\n this._value = newValue;\n this.dispatchEvent(new CustomEvent<T>('change', { detail: newValue }));\n if (this._options.emit) {\n this._messenger.send(`${this._key}/post`, newValue);\n }\n }\n\n /**\n * Start listening for incoming state updates and responding to /get requests.\n * If receive=true and no initial value is set, sends a /get to request the current value.\n */\n start(): void {\n if (this._options.receive) {\n const unsub = this._messenger.subscribe<T>(\n `${this._key}/post`,\n (data) => {\n this._value = data;\n this.dispatchEvent(new CustomEvent<T>('change', { detail: data }));\n }\n );\n this._unsubscribers.push(unsub);\n }\n\n if (this._options.emit) {\n // Respond to /get requests by broadcasting current value\n const unsub = this._messenger.subscribe(\n `${this._key}/get`,\n (_, originSenderId) => {\n if (originSenderId === this._messenger.senderId) return;\n if (this._value === undefined) return;\n this._messenger.send(`${this._key}/post`, this._value);\n }\n );\n this._unsubscribers.push(unsub);\n }\n\n // If receiving and no initial value, request it from other frames\n if (this._options.receive && this._value === undefined) {\n this._messenger.send(`${this._key}/get`);\n }\n }\n\n /** Stop all listeners. */\n stop(): void {\n for (const unsub of this._unsubscribers) unsub();\n this._unsubscribers.length = 0;\n }\n\n /** Broadcast the current value to all frames (useful after reconnect). */\n postCurrentValue(): void {\n if (this._value !== undefined) {\n this._messenger.send(`${this._key}/post`, this._value);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAqBA,IAAa,yBAAb,cAA+C,YAAY;
|
|
1
|
+
{"version":3,"file":"CrossFrameStateManager.mjs","names":[],"sources":["../../../src/core/CrossFrameStateManager.ts"],"sourcesContent":["import type { CrossFrameMessenger } from './CrossFrameMessenger';\n\nexport type CrossFrameStateOptions = {\n /** Whether to broadcast state changes to other frames. Default: true */\n emit?: boolean;\n /** Whether to listen for state updates from other frames. Default: true */\n receive?: boolean;\n};\n\n/**\n * CrossFrameStateManager synchronizes a single named value across frames using\n * the postMessage API via CrossFrameMessenger.\n *\n * Protocol:\n * `{key}/post` — broadcast a new value\n * `{key}/get` — request the current value from other frames\n *\n * Replaces useCrossFrameState across all frameworks.\n *\n * @fires change — CustomEvent<T> dispatched whenever the value changes (local set or received)\n */\nexport class CrossFrameStateManager<T> extends EventTarget {\n private _value: T | undefined;\n private readonly _key: string;\n private readonly _messenger: CrossFrameMessenger;\n private readonly _options: Required<CrossFrameStateOptions>;\n private readonly _unsubscribers: Array<() => void> = [];\n\n constructor(\n key: string,\n messenger: CrossFrameMessenger,\n options: CrossFrameStateOptions & { initialValue?: T } = {}\n ) {\n super();\n this._key = key;\n this._messenger = messenger;\n this._options = {\n emit: options.emit ?? true,\n receive: options.receive ?? true,\n };\n if (options.initialValue !== undefined) {\n this._value = options.initialValue;\n }\n }\n\n get value(): T | undefined {\n return this._value;\n }\n\n /** Update the value locally and broadcast it to other frames if emit is enabled. */\n set(newValue: T): void {\n this._value = newValue;\n this.dispatchEvent(new CustomEvent<T>('change', { detail: newValue }));\n if (this._options.emit) {\n this._messenger.send(`${this._key}/post`, newValue);\n }\n }\n\n /**\n * Start listening for incoming state updates and responding to /get requests.\n * If receive=true and no initial value is set, sends a /get to request the current value.\n */\n start(): void {\n if (this._options.receive) {\n const unsub = this._messenger.subscribe<T>(\n `${this._key}/post`,\n (data) => {\n this._value = data;\n this.dispatchEvent(new CustomEvent<T>('change', { detail: data }));\n }\n );\n this._unsubscribers.push(unsub);\n }\n\n if (this._options.emit) {\n // Respond to /get requests by broadcasting current value\n const unsub = this._messenger.subscribe(\n `${this._key}/get`,\n (_, originSenderId) => {\n if (originSenderId === this._messenger.senderId) return;\n if (this._value === undefined) return;\n this._messenger.send(`${this._key}/post`, this._value);\n }\n );\n this._unsubscribers.push(unsub);\n }\n\n // If receiving and no initial value, request it from other frames\n if (this._options.receive && this._value === undefined) {\n this._messenger.send(`${this._key}/get`);\n }\n }\n\n /** Stop all listeners. */\n stop(): void {\n for (const unsub of this._unsubscribers) unsub();\n this._unsubscribers.length = 0;\n }\n\n /** Broadcast the current value to all frames (useful after reconnect). */\n postCurrentValue(): void {\n if (this._value !== undefined) {\n this._messenger.send(`${this._key}/post`, this._value);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAqBA,IAAa,yBAAb,cAA+C,YAAY;CACzD,AAAQ;CACR,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAiB,iBAAoC,EAAE;CAEvD,YACE,KACA,WACA,UAAyD,EAAE,EAC3D;AACA,SAAO;AACP,OAAK,OAAO;AACZ,OAAK,aAAa;AAClB,OAAK,WAAW;GACd,MAAM,QAAQ,QAAQ;GACtB,SAAS,QAAQ,WAAW;GAC7B;AACD,MAAI,QAAQ,iBAAiB,OAC3B,MAAK,SAAS,QAAQ;;CAI1B,IAAI,QAAuB;AACzB,SAAO,KAAK;;;CAId,IAAI,UAAmB;AACrB,OAAK,SAAS;AACd,OAAK,cAAc,IAAI,YAAe,UAAU,EAAE,QAAQ,UAAU,CAAC,CAAC;AACtE,MAAI,KAAK,SAAS,KAChB,MAAK,WAAW,KAAK,GAAG,KAAK,KAAK,QAAQ,SAAS;;;;;;CAQvD,QAAc;AACZ,MAAI,KAAK,SAAS,SAAS;GACzB,MAAM,QAAQ,KAAK,WAAW,UAC5B,GAAG,KAAK,KAAK,SACZ,SAAS;AACR,SAAK,SAAS;AACd,SAAK,cAAc,IAAI,YAAe,UAAU,EAAE,QAAQ,MAAM,CAAC,CAAC;KAErE;AACD,QAAK,eAAe,KAAK,MAAM;;AAGjC,MAAI,KAAK,SAAS,MAAM;GAEtB,MAAM,QAAQ,KAAK,WAAW,UAC5B,GAAG,KAAK,KAAK,QACZ,GAAG,mBAAmB;AACrB,QAAI,mBAAmB,KAAK,WAAW,SAAU;AACjD,QAAI,KAAK,WAAW,OAAW;AAC/B,SAAK,WAAW,KAAK,GAAG,KAAK,KAAK,QAAQ,KAAK,OAAO;KAEzD;AACD,QAAK,eAAe,KAAK,MAAM;;AAIjC,MAAI,KAAK,SAAS,WAAW,KAAK,WAAW,OAC3C,MAAK,WAAW,KAAK,GAAG,KAAK,KAAK,MAAM;;;CAK5C,OAAa;AACX,OAAK,MAAM,SAAS,KAAK,eAAgB,QAAO;AAChD,OAAK,eAAe,SAAS;;;CAI/B,mBAAyB;AACvB,MAAI,KAAK,WAAW,OAClB,MAAK,WAAW,KAAK,GAAG,KAAK,KAAK,QAAQ,KAAK,OAAO"}
|
|
@@ -16,10 +16,21 @@ import { editDictionaryByKeyPath, getContentNodeByKeyPath, renameContentNodeByKe
|
|
|
16
16
|
* Solid, Svelte, and Vue integrations.
|
|
17
17
|
*/
|
|
18
18
|
var EditorStateManager = class {
|
|
19
|
+
messenger;
|
|
20
|
+
editorEnabled;
|
|
21
|
+
focusedContent;
|
|
22
|
+
localeDictionaries;
|
|
23
|
+
editedContent;
|
|
24
|
+
configuration;
|
|
25
|
+
currentLocale;
|
|
26
|
+
_urlManager;
|
|
27
|
+
_iframeInterceptor;
|
|
28
|
+
_mode;
|
|
29
|
+
_configuration;
|
|
30
|
+
_unsubAreYouThere = null;
|
|
31
|
+
_unsubActivate = null;
|
|
32
|
+
_unsubClientReady = null;
|
|
19
33
|
constructor(config) {
|
|
20
|
-
this._unsubAreYouThere = null;
|
|
21
|
-
this._unsubActivate = null;
|
|
22
|
-
this._unsubClientReady = null;
|
|
23
34
|
this._mode = config.mode;
|
|
24
35
|
this._configuration = config.configuration;
|
|
25
36
|
this.messenger = new CrossFrameMessenger(config.messenger);
|