@intlayer/editor 8.11.0-canary.0 → 8.11.1

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.
@@ -137,18 +137,30 @@ var IntlayerContentSelectorWrapperElement = class extends _HTMLElement {
137
137
  _scrollIntoViewIfNeeded() {
138
138
  try {
139
139
  let rect;
140
- if (this.childNodes.length > 0) {
140
+ if (this._selector) {
141
+ const innerWrapper = this._selector.shadowRoot?.querySelector(".wrapper");
142
+ if (innerWrapper) {
143
+ const r = innerWrapper.getBoundingClientRect();
144
+ if (r.width > 0 || r.height > 0) rect = r;
145
+ }
146
+ }
147
+ if (!rect && this.childNodes.length > 0) {
141
148
  const range = document.createRange();
142
- range.selectNode(this);
143
- rect = range.getBoundingClientRect();
144
- } else rect = this.getBoundingClientRect();
149
+ range.selectNodeContents(this);
150
+ const r = range.getBoundingClientRect();
151
+ if (r.width > 0 || r.height > 0) rect = r;
152
+ }
153
+ if (!rect) rect = this.getBoundingClientRect();
145
154
  const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
146
155
  const viewportWidth = window.innerWidth || document.documentElement.clientWidth;
147
- if (!(rect.width > 0 && rect.height > 0 && rect.bottom > 0 && rect.right > 0 && rect.top < viewportHeight && rect.left < viewportWidth)) (this.firstElementChild ?? this).scrollIntoView({
148
- behavior: "smooth",
149
- block: "nearest",
150
- inline: "nearest"
151
- });
156
+ if (!(rect.width > 0 && rect.height > 0 && rect.bottom > 0 && rect.right > 0 && rect.top < viewportHeight && rect.left < viewportWidth)) {
157
+ const scrollY = window.scrollY ?? document.documentElement.scrollTop;
158
+ const targetScrollY = rect.top + scrollY - viewportHeight * .25;
159
+ window.scrollTo({
160
+ top: Math.max(0, targetScrollY),
161
+ behavior: "smooth"
162
+ });
163
+ }
152
164
  } catch {}
153
165
  }
154
166
  _updateSelectorAttr() {
@@ -1 +1 @@
1
- {"version":3,"file":"ContentSelectorWrapper.cjs","names":["getGlobalEditorManager","NodeTypes","node","onGlobalEditorManagerChange"],"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 (keyPath) => keyPath.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 const wasSelected = this._isSelected;\n this._isSelected =\n focusedContent.dictionaryKey === this._dictionaryKey &&\n (focusedContent.keyPath?.length ?? 0) > 0 &&\n isSameKeyPath(focusedContent.keyPath ?? [], keyPath);\n this._updateSelectorAttr();\n\n // Scroll into view when this element becomes selected and is not already\n // visible in the iframe viewport. This covers the case where the editor\n // focuses a content block that is off-screen in the client app.\n if (this._isSelected && !wasSelected) {\n this._scrollIntoViewIfNeeded();\n }\n }\n\n private _scrollIntoViewIfNeeded(): void {\n try {\n // this element has display:contents so getBoundingClientRect() returns\n // all zeros. Use a Range over its children to get the real visual bounds.\n let rect: DOMRect;\n if (this.childNodes.length > 0) {\n const range = document.createRange();\n range.selectNode(this);\n rect = range.getBoundingClientRect();\n } else {\n rect = this.getBoundingClientRect();\n }\n\n const viewportHeight =\n window.innerHeight || document.documentElement.clientHeight;\n const viewportWidth =\n window.innerWidth || document.documentElement.clientWidth;\n\n const isVisible =\n rect.width > 0 &&\n rect.height > 0 &&\n rect.bottom > 0 &&\n rect.right > 0 &&\n rect.top < viewportHeight &&\n rect.left < viewportWidth;\n\n if (!isVisible) {\n // Scroll the first real child into view — display:contents hosts have no\n // box of their own and browsers may ignore scrollIntoView on them.\n const scrollTarget =\n (this.firstElementChild as Element | null) ?? this;\n scrollTarget.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n inline: 'nearest',\n });\n }\n } catch {\n // scrollIntoView may not be available in all environments\n }\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
+ {"version":3,"file":"ContentSelectorWrapper.cjs","names":["getGlobalEditorManager","NodeTypes","node","onGlobalEditorManagerChange"],"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 (keyPath) => keyPath.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 const wasSelected = this._isSelected;\n this._isSelected =\n focusedContent.dictionaryKey === this._dictionaryKey &&\n (focusedContent.keyPath?.length ?? 0) > 0 &&\n isSameKeyPath(focusedContent.keyPath ?? [], keyPath);\n this._updateSelectorAttr();\n\n // Scroll into view when this element becomes selected and is not already\n // visible in the iframe viewport. This covers the case where the editor\n // focuses a content block that is off-screen in the client app.\n if (this._isSelected && !wasSelected) {\n this._scrollIntoViewIfNeeded();\n }\n }\n\n private _scrollIntoViewIfNeeded(): void {\n try {\n let rect: DOMRect | undefined;\n\n // Primary: the .wrapper span inside the selector's open shadow DOM has a\n // real CSS box (display:inline-block) for both wrapped-text and wrapped-slot.\n // This is the only reliable source for simple-string nodes where this host's\n // light DOM is empty and this.getBoundingClientRect() returns zeros.\n if (this._selector) {\n const innerWrapper = this._selector.shadowRoot?.querySelector(\n '.wrapper'\n ) as HTMLElement | null;\n if (innerWrapper) {\n const r = innerWrapper.getBoundingClientRect();\n if (r.width > 0 || r.height > 0) rect = r;\n }\n }\n\n // Fallback: range over light-DOM children for wrapped-slot nodes rendered\n // by a framework (React/markdown) before _selector is available.\n if (!rect && this.childNodes.length > 0) {\n const range = document.createRange();\n\n range.selectNodeContents(this);\n\n const r = range.getBoundingClientRect();\n\n if (r.width > 0 || r.height > 0) rect = r;\n }\n\n if (!rect) {\n rect = this.getBoundingClientRect();\n }\n\n const viewportHeight =\n window.innerHeight || document.documentElement.clientHeight;\n const viewportWidth =\n window.innerWidth || document.documentElement.clientWidth;\n\n const isVisible =\n rect.width > 0 &&\n rect.height > 0 &&\n rect.bottom > 0 &&\n rect.right > 0 &&\n rect.top < viewportHeight &&\n rect.left < viewportWidth;\n\n if (!isVisible) {\n // Scroll so the element lands at 25 % from the top of the viewport.\n const scrollY = window.scrollY ?? document.documentElement.scrollTop;\n const targetScrollY = rect.top + scrollY - viewportHeight * 0.25;\n window.scrollTo({\n top: Math.max(0, targetScrollY),\n behavior: 'smooth',\n });\n }\n } catch {\n // scroll APIs may not be available in all environments\n }\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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"}
@@ -134,18 +134,30 @@ var IntlayerContentSelectorWrapperElement = class extends _HTMLElement {
134
134
  _scrollIntoViewIfNeeded() {
135
135
  try {
136
136
  let rect;
137
- if (this.childNodes.length > 0) {
137
+ if (this._selector) {
138
+ const innerWrapper = this._selector.shadowRoot?.querySelector(".wrapper");
139
+ if (innerWrapper) {
140
+ const r = innerWrapper.getBoundingClientRect();
141
+ if (r.width > 0 || r.height > 0) rect = r;
142
+ }
143
+ }
144
+ if (!rect && this.childNodes.length > 0) {
138
145
  const range = document.createRange();
139
- range.selectNode(this);
140
- rect = range.getBoundingClientRect();
141
- } else rect = this.getBoundingClientRect();
146
+ range.selectNodeContents(this);
147
+ const r = range.getBoundingClientRect();
148
+ if (r.width > 0 || r.height > 0) rect = r;
149
+ }
150
+ if (!rect) rect = this.getBoundingClientRect();
142
151
  const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
143
152
  const viewportWidth = window.innerWidth || document.documentElement.clientWidth;
144
- if (!(rect.width > 0 && rect.height > 0 && rect.bottom > 0 && rect.right > 0 && rect.top < viewportHeight && rect.left < viewportWidth)) (this.firstElementChild ?? this).scrollIntoView({
145
- behavior: "smooth",
146
- block: "nearest",
147
- inline: "nearest"
148
- });
153
+ if (!(rect.width > 0 && rect.height > 0 && rect.bottom > 0 && rect.right > 0 && rect.top < viewportHeight && rect.left < viewportWidth)) {
154
+ const scrollY = window.scrollY ?? document.documentElement.scrollTop;
155
+ const targetScrollY = rect.top + scrollY - viewportHeight * .25;
156
+ window.scrollTo({
157
+ top: Math.max(0, targetScrollY),
158
+ behavior: "smooth"
159
+ });
160
+ }
149
161
  } catch {}
150
162
  }
151
163
  _updateSelectorAttr() {
@@ -1 +1 @@
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 (keyPath) => keyPath.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 const wasSelected = this._isSelected;\n this._isSelected =\n focusedContent.dictionaryKey === this._dictionaryKey &&\n (focusedContent.keyPath?.length ?? 0) > 0 &&\n isSameKeyPath(focusedContent.keyPath ?? [], keyPath);\n this._updateSelectorAttr();\n\n // Scroll into view when this element becomes selected and is not already\n // visible in the iframe viewport. This covers the case where the editor\n // focuses a content block that is off-screen in the client app.\n if (this._isSelected && !wasSelected) {\n this._scrollIntoViewIfNeeded();\n }\n }\n\n private _scrollIntoViewIfNeeded(): void {\n try {\n // this element has display:contents so getBoundingClientRect() returns\n // all zeros. Use a Range over its children to get the real visual bounds.\n let rect: DOMRect;\n if (this.childNodes.length > 0) {\n const range = document.createRange();\n range.selectNode(this);\n rect = range.getBoundingClientRect();\n } else {\n rect = this.getBoundingClientRect();\n }\n\n const viewportHeight =\n window.innerHeight || document.documentElement.clientHeight;\n const viewportWidth =\n window.innerWidth || document.documentElement.clientWidth;\n\n const isVisible =\n rect.width > 0 &&\n rect.height > 0 &&\n rect.bottom > 0 &&\n rect.right > 0 &&\n rect.top < viewportHeight &&\n rect.left < viewportWidth;\n\n if (!isVisible) {\n // Scroll the first real child into view — display:contents hosts have no\n // box of their own and browsers may ignore scrollIntoView on them.\n const scrollTarget =\n (this.firstElementChild as Element | null) ?? this;\n scrollTarget.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n inline: 'nearest',\n });\n }\n } catch {\n // scrollIntoView may not be available in all environments\n }\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":";;;;;;AAkBA,MAAM,eACJ,OAAO,gBAAgB,cACnB,cACC,MAAM,CAAC;;;;;;;;;;;;;;;AAgBd,IAAa,wCAAb,cAA2D,aAAa;CACtE,AAAQ,eAAe;CACvB,AAAQ,iBAAiB;CACzB,AAAQ,iBAAiB;CACzB,AAAQ,cAAc;CACtB,AAAQ,cAAc;CACtB,AAAQ,eAAwC;CAEhD,AAAQ,eAAmC;CAC3C,AAAQ,YAAgC;CAExC,AAAQ,gBAAqC;CAC7C,AAAQ,gBAAqC;CAC7C,AAAQ,gBAAqC;CAC7C,AAAQ,sBAA2C;CAEnD,WAAW,qBAA+B;EACxC,OAAO,CAAC,YAAY,gBAAgB;CACtC;CAEA,IAAI,cAAsB;EACxB,OAAO,KAAK;CACd;CACA,IAAI,YAAY,GAAW;EACzB,KAAK,eAAe;EACpB,MAAM,UAAU,uBAAuB;EACvC,IAAI,SAAS,KAAK,mBAAmB,OAAO;CAC9C;CAEA,IAAI,gBAAwB;EAC1B,OAAO,KAAK;CACd;CACA,IAAI,cAAc,GAAW;EAC3B,KAAK,iBAAiB;EACtB,MAAM,UAAU,uBAAuB;EACvC,IAAI,SAAS,KAAK,mBAAmB,OAAO;CAC9C;CAEA,cAAc;EACZ,MAAM;EACN,MAAM,SAAS,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;EACjD,MAAM,QAAQ,SAAS,cAAc,OAAO;EAC5C,MAAM,cAAc;EACpB,OAAO,YAAY,KAAK;CAC1B;CAEA,yBACE,MACA,SACA,QACM;EACN,IAAI,SAAS,YAAY;GACvB,KAAK,eAAe,UAAU;GAC9B,MAAM,UAAU,uBAAuB;GACvC,IAAI,SAAS,KAAK,mBAAmB,OAAO;EAC9C,OAAO,IAAI,SAAS,kBAAkB;GACpC,KAAK,iBAAiB,UAAU;GAChC,MAAM,UAAU,uBAAuB;GACvC,IAAI,SAAS,KAAK,mBAAmB,OAAO;EAC9C;CACF;CAEA,oBAA0B;EACxB,IAAI,OAAO,WAAW,aACpB,KAAK,cAAc,OAAO,SAAS,OAAO;EAE5C,KAAK,oBAAoB;EACzB,KAAK,QAAQ;CACf;CAEA,uBAA6B;EAC3B,KAAK,UAAU;CACjB;CAEA,AAAQ,YAAkB;EACxB,KAAK,gBAAgB;EACrB,KAAK,gBAAgB;EACrB,KAAK,gBAAgB;EACrB,KAAK,sBAAsB;EAC3B,KAAK,gBAAgB;EACrB,KAAK,gBAAgB;EACrB,KAAK,gBAAgB;EACrB,KAAK,sBAAsB;CAC7B;CAEA,AAAQ,iBAA4B;EAClC,IAAI;GACF,OAAO,KAAK,MAAM,KAAK,YAAY;EACrC,QAAQ;GACN,OAAO,CAAC;EACV;CACF;CAEA,AAAQ,sBAAiC;EACvC,OAAO,KAAK,eAAe,EAAE,QAC1B,YAAY,QAAQ,SAAS,UAAU,WAC1C;CACF;CAEA,AAAQ,mBAAmB,SAAmC;EAC5D,MAAM,kBAAkB,KAAK,oBAAoB;EACjD,IAAI,CAAC,KAAK,kBAAkB,gBAAgB,WAAW,GAAG;GACxD,KAAK,eAAe;GACpB,KAAK,QAAQ;GACb;EACF;EAKA,MAAM,aAAa,KAAK,eAAe;EACvC,MAAM,eAAe,WAAW,WAAW,SAAS,IAAI;EACxD,IACE,iBAAiB,UAAU,YAC3B,iBAAiB,UAAU,QAC3B,iBAAiB,UAAU,aAC3B,iBAAiB,UAAU,MAC3B;GACA,KAAK,eAAe;GACpB,KAAK,QAAQ;GACb;EACF;EAEA,IAAI,QAAQ,QAAQ,gBAAgB,KAAK,gBAAgB,eAAe;EAMxE,IACE,UAAU,QACV,UAAU,UACV,OAAO,UAAU,YAChB,MAAiC,aAAa,UAAU,aACzD;GACA,MAAM,SAAS,QAAQ,cAAc;GAOrC,QAAQ,SAASA,MAAK,UAAU,aAAa,UAAU;EACzD;EAEA,KAAK,eAAe;EACpB,KAAK,QAAQ;CACf;CAEA,AAAQ,kBACN,gBACM;EACN,IAAI,CAAC,gBAAgB;GACnB,KAAK,cAAc;GACnB,KAAK,oBAAoB;GACzB;EACF;EACA,MAAM,UAAU,KAAK,oBAAoB;EACzC,MAAM,cAAc,KAAK;EACzB,KAAK,cACH,eAAe,kBAAkB,KAAK,mBACrC,eAAe,SAAS,UAAU,KAAK,KACxC,cAAc,eAAe,WAAW,CAAC,GAAG,OAAO;EACrD,KAAK,oBAAoB;EAKzB,IAAI,KAAK,eAAe,CAAC,aACvB,KAAK,wBAAwB;CAEjC;CAEA,AAAQ,0BAAgC;EACtC,IAAI;GAGF,IAAI;GACJ,IAAI,KAAK,WAAW,SAAS,GAAG;IAC9B,MAAM,QAAQ,SAAS,YAAY;IACnC,MAAM,WAAW,IAAI;IACrB,OAAO,MAAM,sBAAsB;GACrC,OACE,OAAO,KAAK,sBAAsB;GAGpC,MAAM,iBACJ,OAAO,eAAe,SAAS,gBAAgB;GACjD,MAAM,gBACJ,OAAO,cAAc,SAAS,gBAAgB;GAUhD,IAAI,EAPF,KAAK,QAAQ,KACb,KAAK,SAAS,KACd,KAAK,SAAS,KACd,KAAK,QAAQ,KACb,KAAK,MAAM,kBACX,KAAK,OAAO,gBAOZ,CADG,KAAK,qBAAwC,MACnC,eAAe;IAC1B,UAAU;IACV,OAAO;IACP,QAAQ;GACV,CAAC;EAEL,QAAQ,CAER;CACF;CAEA,AAAQ,sBAA4B;EAClC,IAAI,CAAC,KAAK,WAAW;EACrB,IAAI,KAAK,aACP,KAAK,UAAU,aAAa,gBAAgB,EAAE;OAE9C,KAAK,UAAU,gBAAgB,cAAc;CAEjD;CAEA,AAAQ,sBAA4B;EAClC,MAAM,UAAU,uBAAuB;EACvC,IAAI,SACF,KAAK,2BAA2B,OAAO;EAGzC,KAAK,gBAAgB,6BAA6B,MAAM;GACtD,KAAK,gBAAgB;GACrB,KAAK,gBAAgB;GACrB,KAAK,sBAAsB;GAC3B,KAAK,gBAAgB;GACrB,KAAK,gBAAgB;GACrB,KAAK,sBAAsB;GAC3B,IAAI,GACF,KAAK,2BAA2B,CAAC;QAC5B;IACL,KAAK,iBAAiB;IACtB,KAAK,cAAc;IACnB,KAAK,eAAe;IACpB,KAAK,QAAQ;GACf;EACF,CAAC;CACH;CAEA,AAAQ,2BAA2B,SAAmC;EACpE,KAAK,iBAAiB,QAAQ,cAAc,SAAS;EACrD,KAAK,kBAAkB,QAAQ,eAAe,KAAK;EACnD,KAAK,mBAAmB,OAAO;EAE/B,MAAM,uBAAuB,MAAa;GACxC,KAAK,iBAAkB,EAA2B;GAClD,KAAK,QAAQ;EACf;EACA,MAAM,uBAAuB,MAAa;GACxC,KAAK,kBAAmB,EAAsC,MAAM;EACtE;EACA,MAAM,kCAAkC;GACtC,KAAK,mBAAmB,OAAO;EACjC;EAEA,QAAQ,cAAc,iBAAiB,UAAU,mBAAmB;EACpE,QAAQ,eAAe,iBAAiB,UAAU,mBAAmB;EACrE,QAAQ,cAAc,iBAAiB,UAAU,yBAAyB;EAE1E,KAAK,sBACH,QAAQ,cAAc,oBAAoB,UAAU,mBAAmB;EACzE,KAAK,sBACH,QAAQ,eAAe,oBAAoB,UAAU,mBAAmB;EAC1E,KAAK,4BACH,QAAQ,cAAc,oBACpB,UACA,yBACF;CACJ;CAEA,AAAQ,aAAa,GAAgB;EAEnC,EAAE,gBAAgB;EAClB,MAAM,UAAU,uBAAuB;EACvC,IAAI,CAAC,SAAS;EACd,QAAQ,eAAe,IAAI;GACzB,eAAe,KAAK;GACpB,SAAS,KAAK,oBAAoB;EACpC,CAAC;CACH;CAEA,AAAQ,aAAa,GAAgB;EACnC,EAAE,gBAAgB;EAClB,uBAAuB,GAAG,UAAU,KAClC,sCAA+C,QAC/C;GACE,eAAe,KAAK;GACpB,SAAS,KAAK,oBAAoB;EACpC,CACF;CACF;CAEA,AAAQ,eAAe,GAAgB;EACrC,EAAE,gBAAgB;EAClB,uBAAuB,GAAG,UAAU,KAClC,sCAA+C,QAC/C,IACF;CACF;CAEA,AAAQ,UAAgB;EACtB,MAAM,aAAa,KAAK,eAAe,KAAK;EAC5C,MAAM,cAAc,KAAK;EAMzB,MAAM,WAAwB,CAAC,aAC3B,WALF,OAAO,gBAAgB,YACvB,OAAO,gBAAgB,YACvB,OAAO,gBAAgB,YAKnB,iBACA;EAEN,IAAI,KAAK,iBAAiB,UAAU;GAClC,KAAK,gBAAgB,QAAQ;GAC7B;EACF;EAGA,IAAI,aAAa,YAAY,KAAK,WAAW;GAC3C,KAAK,oBAAoB;GACzB,IACE,aAAa,kBACb,KAAK,UAAU,YAAY,aAAa,KAAK,WAE7C,AAAC,KAAK,UAAU,WAAoB,OAAO,OAAO,WAAW;EAEjE;CACF;CAEA,AAAQ,gBAAgB,OAA0B;EAChD,MAAM,SAAS,KAAK;EAEpB,OAAO,OAAO,WAAW,SAAS,GAChC,OAAO,YAAY,OAAO,SAAU;EAEtC,KAAK,YAAY;EAEjB,IAAI,UAAU,UACZ,OAAO,YAAY,SAAS,cAAc,MAAM,CAAC;OAC5C;GACL,MAAM,WAAW,SAAS,cAAc,2BAA2B;GACnE,KAAK,YAAY;GACjB,IAAI,KAAK,aAAa,SAAS,aAAa,gBAAgB,EAAE;GAC9D,SAAS,iBAAiB,mBAAmB,MAAM,KAAK,aAAa,CAAC,CAAC;GACvE,SAAS,iBAAiB,mBAAmB,MAAM,KAAK,aAAa,CAAC,CAAC;GACvE,SAAS,iBAAiB,qBAAqB,MAC7C,KAAK,eAAe,CAAC,CACvB;GAEA,IAAI,UAAU,gBACZ,SAAS,YACP,SAAS,eAAe,OAAO,KAAK,YAAY,CAAC,CACnD;QAEA,SAAS,YAAY,SAAS,cAAc,MAAM,CAAC;GAErD,OAAO,YAAY,QAAQ;EAC7B;EAEA,KAAK,eAAe;CACtB;AACF;AAEA,MAAa,6CAAmD;CAC9D,IAAI,OAAO,mBAAmB,aAAa;CAE3C,IAAI,CAAC,eAAe,IAAI,mCAAmC,GACzD,eAAe,OACb,qCACA,qCACF;AAEJ"}
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 (keyPath) => keyPath.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 const wasSelected = this._isSelected;\n this._isSelected =\n focusedContent.dictionaryKey === this._dictionaryKey &&\n (focusedContent.keyPath?.length ?? 0) > 0 &&\n isSameKeyPath(focusedContent.keyPath ?? [], keyPath);\n this._updateSelectorAttr();\n\n // Scroll into view when this element becomes selected and is not already\n // visible in the iframe viewport. This covers the case where the editor\n // focuses a content block that is off-screen in the client app.\n if (this._isSelected && !wasSelected) {\n this._scrollIntoViewIfNeeded();\n }\n }\n\n private _scrollIntoViewIfNeeded(): void {\n try {\n let rect: DOMRect | undefined;\n\n // Primary: the .wrapper span inside the selector's open shadow DOM has a\n // real CSS box (display:inline-block) for both wrapped-text and wrapped-slot.\n // This is the only reliable source for simple-string nodes where this host's\n // light DOM is empty and this.getBoundingClientRect() returns zeros.\n if (this._selector) {\n const innerWrapper = this._selector.shadowRoot?.querySelector(\n '.wrapper'\n ) as HTMLElement | null;\n if (innerWrapper) {\n const r = innerWrapper.getBoundingClientRect();\n if (r.width > 0 || r.height > 0) rect = r;\n }\n }\n\n // Fallback: range over light-DOM children for wrapped-slot nodes rendered\n // by a framework (React/markdown) before _selector is available.\n if (!rect && this.childNodes.length > 0) {\n const range = document.createRange();\n\n range.selectNodeContents(this);\n\n const r = range.getBoundingClientRect();\n\n if (r.width > 0 || r.height > 0) rect = r;\n }\n\n if (!rect) {\n rect = this.getBoundingClientRect();\n }\n\n const viewportHeight =\n window.innerHeight || document.documentElement.clientHeight;\n const viewportWidth =\n window.innerWidth || document.documentElement.clientWidth;\n\n const isVisible =\n rect.width > 0 &&\n rect.height > 0 &&\n rect.bottom > 0 &&\n rect.right > 0 &&\n rect.top < viewportHeight &&\n rect.left < viewportWidth;\n\n if (!isVisible) {\n // Scroll so the element lands at 25 % from the top of the viewport.\n const scrollY = window.scrollY ?? document.documentElement.scrollTop;\n const targetScrollY = rect.top + scrollY - viewportHeight * 0.25;\n window.scrollTo({\n top: Math.max(0, targetScrollY),\n behavior: 'smooth',\n });\n }\n } catch {\n // scroll APIs may not be available in all environments\n }\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 +1 @@
1
- {"version":3,"file":"ContentSelectorWrapper.d.ts","names":[],"sources":["../../../src/components/ContentSelectorWrapper.ts"],"mappings":";cAkBM,YAAA;EAAA,QAG2C,WAAA;aAAA,WAAA;AAAA;;;;;;;AAgBjD;;;;;;;;cAAa,qCAAA,SAA8C,YAAY;EAAA,QAC7D,YAAA;EAAA,QACA,cAAA;EAAA,QACA,cAAA;EAAA,QACA,WAAA;EAAA,QACA,WAAA;EAAA,QACA,YAAA;EAAA,QAEA,YAAA;EAAA,QACA,SAAA;EAAA,QAEA,aAAA;EAAA,QACA,aAAA;EAAA,QACA,aAAA;EAAA,QACA,mBAAA;EAAA,WAEG,kBAAA,CAAA;EAAA,IAIP,WAAA,CAAA;EAAA,IAGA,WAAA,CAAY,CAAA;EAAA,IAMZ,aAAA,CAAA;EAAA,IAGA,aAAA,CAAc,CAAA;;EAclB,wBAAA,CACE,IAAA,UACA,OAAA,iBACA,MAAA;EAaF,iBAAA,CAAA;EAQA,oBAAA,CAAA;EAAA,QAIQ,SAAA;EAAA,QAWA,cAAA;EAAA,QAQA,mBAAA;EAAA,QAMA,kBAAA;EAAA,QAkDA,iBAAA;EAAA,QAwBA,uBAAA;EAAA,QA0CA,mBAAA;EAAA,QASA,mBAAA;EAAA,QAwBA,0BAAA;EAAA,QA+BA,YAAA;EAAA,QAWA,YAAA;EAAA,QAWA,cAAA;EAAA,QAQA,OAAA;EAAA,QA+BA,eAAA;AAAA;AAAA,cAkCG,oCAAA"}
1
+ {"version":3,"file":"ContentSelectorWrapper.d.ts","names":[],"sources":["../../../src/components/ContentSelectorWrapper.ts"],"mappings":";cAkBM,YAAA;EAAA,QAG2C,WAAA;aAAA,WAAA;AAAA;;;;;;;AAgBjD;;;;;;;;cAAa,qCAAA,SAA8C,YAAY;EAAA,QAC7D,YAAA;EAAA,QACA,cAAA;EAAA,QACA,cAAA;EAAA,QACA,WAAA;EAAA,QACA,WAAA;EAAA,QACA,YAAA;EAAA,QAEA,YAAA;EAAA,QACA,SAAA;EAAA,QAEA,aAAA;EAAA,QACA,aAAA;EAAA,QACA,aAAA;EAAA,QACA,mBAAA;EAAA,WAEG,kBAAA,CAAA;EAAA,IAIP,WAAA,CAAA;EAAA,IAGA,WAAA,CAAY,CAAA;EAAA,IAMZ,aAAA,CAAA;EAAA,IAGA,aAAA,CAAc,CAAA;;EAclB,wBAAA,CACE,IAAA,UACA,OAAA,iBACA,MAAA;EAaF,iBAAA,CAAA;EAQA,oBAAA,CAAA;EAAA,QAIQ,SAAA;EAAA,QAWA,cAAA;EAAA,QAQA,mBAAA;EAAA,QAMA,kBAAA;EAAA,QAkDA,iBAAA;EAAA,QAwBA,uBAAA;EAAA,QA6DA,mBAAA;EAAA,QASA,mBAAA;EAAA,QAwBA,0BAAA;EAAA,QA+BA,YAAA;EAAA,QAWA,YAAA;EAAA,QAWA,cAAA;EAAA,QAQA,OAAA;EAAA,QA+BA,eAAA;AAAA;AAAA,cAkCG,oCAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intlayer/editor",
3
- "version": "8.11.0-canary.0",
3
+ "version": "8.11.1",
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.0-canary.0",
79
- "@intlayer/core": "8.11.0-canary.0",
80
- "@intlayer/types": "8.11.0-canary.0",
81
- "@intlayer/unmerged-dictionaries-entry": "8.11.0-canary.0"
78
+ "@intlayer/config": "8.11.1",
79
+ "@intlayer/core": "8.11.1",
80
+ "@intlayer/types": "8.11.1",
81
+ "@intlayer/unmerged-dictionaries-entry": "8.11.1"
82
82
  },
83
83
  "devDependencies": {
84
84
  "@types/node": "25.9.1",