@intlayer/editor 8.4.3 → 8.4.5

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.
Files changed (124) hide show
  1. package/dist/cjs/_virtual/_@oxc-project_runtime@0.115.0/helpers/decorate.cjs +11 -0
  2. package/dist/cjs/_virtual/_rolldown/runtime.cjs +29 -0
  3. package/dist/cjs/compareUrls.cjs +39 -1
  4. package/dist/cjs/compareUrls.cjs.map +1 -1
  5. package/dist/cjs/components/ContentSelector.cjs +168 -1
  6. package/dist/cjs/components/ContentSelector.cjs.map +1 -0
  7. package/dist/cjs/components/ContentSelectorWrapper.cjs +193 -4
  8. package/dist/cjs/components/ContentSelectorWrapper.cjs.map +1 -1
  9. package/dist/cjs/components/EditedContent.cjs +128 -4
  10. package/dist/cjs/components/EditedContent.cjs.map +1 -1
  11. package/dist/cjs/components/IntlayerEditor.cjs +87 -1
  12. package/dist/cjs/components/IntlayerEditor.cjs.map +1 -0
  13. package/dist/cjs/components/index.cjs +14 -1
  14. package/dist/cjs/core/CrossFrameMessenger.cjs +77 -1
  15. package/dist/cjs/core/CrossFrameMessenger.cjs.map +1 -1
  16. package/dist/cjs/core/CrossFrameStateManager.cjs +71 -1
  17. package/dist/cjs/core/CrossFrameStateManager.cjs.map +1 -1
  18. package/dist/cjs/core/EditorStateManager.cjs +258 -1
  19. package/dist/cjs/core/EditorStateManager.cjs.map +1 -1
  20. package/dist/cjs/core/IframeClickInterceptor.cjs +45 -1
  21. package/dist/cjs/core/IframeClickInterceptor.cjs.map +1 -1
  22. package/dist/cjs/core/UrlStateManager.cjs +59 -1
  23. package/dist/cjs/core/UrlStateManager.cjs.map +1 -1
  24. package/dist/cjs/core/globalManager.cjs +82 -1
  25. package/dist/cjs/core/globalManager.cjs.map +1 -1
  26. package/dist/cjs/core/index.cjs +20 -1
  27. package/dist/cjs/core/initEditorClient.cjs +58 -1
  28. package/dist/cjs/core/initEditorClient.cjs.map +1 -0
  29. package/dist/cjs/index.cjs +38 -1
  30. package/dist/cjs/isEnabled.cjs +10 -1
  31. package/dist/cjs/isEnabled.cjs.map +1 -1
  32. package/dist/cjs/mergeIframeClick.cjs +22 -1
  33. package/dist/cjs/mergeIframeClick.cjs.map +1 -1
  34. package/dist/cjs/messageKey.cjs +30 -1
  35. package/dist/cjs/messageKey.cjs.map +1 -1
  36. package/dist/esm/_virtual/_@oxc-project_runtime@0.115.0/helpers/decorate.mjs +10 -0
  37. package/dist/esm/compareUrls.mjs +37 -1
  38. package/dist/esm/compareUrls.mjs.map +1 -1
  39. package/dist/esm/components/ContentSelector.mjs +165 -1
  40. package/dist/esm/components/ContentSelector.mjs.map +1 -0
  41. package/dist/esm/components/ContentSelectorWrapper.mjs +189 -4
  42. package/dist/esm/components/ContentSelectorWrapper.mjs.map +1 -1
  43. package/dist/esm/components/EditedContent.mjs +125 -4
  44. package/dist/esm/components/EditedContent.mjs.map +1 -1
  45. package/dist/esm/components/IntlayerEditor.mjs +84 -1
  46. package/dist/esm/components/IntlayerEditor.mjs.map +1 -0
  47. package/dist/esm/components/index.mjs +6 -1
  48. package/dist/esm/core/CrossFrameMessenger.mjs +76 -1
  49. package/dist/esm/core/CrossFrameMessenger.mjs.map +1 -1
  50. package/dist/esm/core/CrossFrameStateManager.mjs +69 -1
  51. package/dist/esm/core/CrossFrameStateManager.mjs.map +1 -1
  52. package/dist/esm/core/EditorStateManager.mjs +255 -1
  53. package/dist/esm/core/EditorStateManager.mjs.map +1 -1
  54. package/dist/esm/core/IframeClickInterceptor.mjs +44 -1
  55. package/dist/esm/core/IframeClickInterceptor.mjs.map +1 -1
  56. package/dist/esm/core/UrlStateManager.mjs +58 -1
  57. package/dist/esm/core/UrlStateManager.mjs.map +1 -1
  58. package/dist/esm/core/globalManager.mjs +78 -1
  59. package/dist/esm/core/globalManager.mjs.map +1 -1
  60. package/dist/esm/core/index.mjs +9 -1
  61. package/dist/esm/core/initEditorClient.mjs +53 -1
  62. package/dist/esm/core/initEditorClient.mjs.map +1 -0
  63. package/dist/esm/index.mjs +16 -1
  64. package/dist/esm/isEnabled.mjs +7 -1
  65. package/dist/esm/isEnabled.mjs.map +1 -1
  66. package/dist/esm/mergeIframeClick.mjs +20 -1
  67. package/dist/esm/mergeIframeClick.mjs.map +1 -1
  68. package/dist/esm/messageKey.mjs +28 -1
  69. package/dist/esm/messageKey.mjs.map +1 -1
  70. package/dist/types/components/ContentSelector.d.ts +49 -2
  71. package/dist/types/components/ContentSelector.d.ts.map +1 -0
  72. package/dist/types/components/ContentSelectorWrapper.d.ts +49 -2
  73. package/dist/types/components/ContentSelectorWrapper.d.ts.map +1 -0
  74. package/dist/types/components/EditedContent.d.ts +39 -2
  75. package/dist/types/components/EditedContent.d.ts.map +1 -0
  76. package/dist/types/components/IntlayerEditor.d.ts +40 -2
  77. package/dist/types/components/IntlayerEditor.d.ts.map +1 -0
  78. package/dist/types/components/index.d.ts +4 -4
  79. package/dist/types/core/CrossFrameMessenger.d.ts +51 -2
  80. package/dist/types/core/CrossFrameMessenger.d.ts.map +1 -0
  81. package/dist/types/core/CrossFrameStateManager.d.ts +44 -2
  82. package/dist/types/core/CrossFrameStateManager.d.ts.map +1 -0
  83. package/dist/types/core/EditorStateManager.d.ts +73 -2
  84. package/dist/types/core/EditorStateManager.d.ts.map +1 -0
  85. package/dist/types/core/IframeClickInterceptor.d.ts +26 -2
  86. package/dist/types/core/IframeClickInterceptor.d.ts.map +1 -0
  87. package/dist/types/core/UrlStateManager.d.ts +21 -2
  88. package/dist/types/core/UrlStateManager.d.ts.map +1 -0
  89. package/dist/types/core/globalManager.d.ts +39 -2
  90. package/dist/types/core/globalManager.d.ts.map +1 -0
  91. package/dist/types/core/index.d.ts +7 -7
  92. package/dist/types/core/initEditorClient.d.ts +20 -2
  93. package/dist/types/core/initEditorClient.d.ts.map +1 -0
  94. package/dist/types/index.d.ts +11 -11
  95. package/package.json +5 -5
  96. package/dist/cjs/chunk-Bmb41Sf3.cjs +0 -1
  97. package/dist/cjs/components-DWu35JEb.cjs +0 -41
  98. package/dist/cjs/components-DWu35JEb.cjs.map +0 -1
  99. package/dist/cjs/decorate-Bg73f0d3.cjs +0 -1
  100. package/dist/esm/components-RtOXxg9h.mjs +0 -41
  101. package/dist/esm/components-RtOXxg9h.mjs.map +0 -1
  102. package/dist/esm/decorate-BWURH4oJ.mjs +0 -1
  103. package/dist/types/ContentSelector-sIfZu4Dd.d.ts +0 -49
  104. package/dist/types/ContentSelector-sIfZu4Dd.d.ts.map +0 -1
  105. package/dist/types/ContentSelectorWrapper-CID6anMf.d.ts +0 -49
  106. package/dist/types/ContentSelectorWrapper-CID6anMf.d.ts.map +0 -1
  107. package/dist/types/CrossFrameMessenger-CPt3Bu8S.d.ts +0 -51
  108. package/dist/types/CrossFrameMessenger-CPt3Bu8S.d.ts.map +0 -1
  109. package/dist/types/CrossFrameStateManager-CW1DPY_Z.d.ts +0 -44
  110. package/dist/types/CrossFrameStateManager-CW1DPY_Z.d.ts.map +0 -1
  111. package/dist/types/EditedContent-2kq4wk4R.d.ts +0 -39
  112. package/dist/types/EditedContent-2kq4wk4R.d.ts.map +0 -1
  113. package/dist/types/EditorStateManager-Y9j0SYCd.d.ts +0 -73
  114. package/dist/types/EditorStateManager-Y9j0SYCd.d.ts.map +0 -1
  115. package/dist/types/IframeClickInterceptor-Cm89LRcI.d.ts +0 -26
  116. package/dist/types/IframeClickInterceptor-Cm89LRcI.d.ts.map +0 -1
  117. package/dist/types/IntlayerEditor-ePRSIuBI.d.ts +0 -40
  118. package/dist/types/IntlayerEditor-ePRSIuBI.d.ts.map +0 -1
  119. package/dist/types/UrlStateManager-CIOVEeTq.d.ts +0 -21
  120. package/dist/types/UrlStateManager-CIOVEeTq.d.ts.map +0 -1
  121. package/dist/types/globalManager-BD6UaK_1.d.ts +0 -39
  122. package/dist/types/globalManager-BD6UaK_1.d.ts.map +0 -1
  123. package/dist/types/initEditorClient-ovRVUf_n.d.ts +0 -20
  124. package/dist/types/initEditorClient-ovRVUf_n.d.ts.map +0 -1
@@ -1,15 +1,200 @@
1
- import{MessageKey as e}from"../messageKey.mjs";import{getGlobalEditorManager as t,onGlobalEditorManagerChange as n}from"../core/globalManager.mjs";import{t as r}from"../decorate-BWURH4oJ.mjs";import{LitElement as i,css as a,html as o}from"lit";import{property as s,state as c}from"lit/decorators.js";import{isSameKeyPath as l}from"@intlayer/core/utils";import{NodeType as u}from"@intlayer/types/nodeType";var d=class extends i{constructor(...e){super(...e),this.keyPathJson=`[]`,this.dictionaryKey=``,this._editorEnabled=!1,this._isInIframe=!1,this._isSelected=!1,this._editedValue=void 0,this._unsubManager=null,this._unsubEnabled=null,this._unsubFocused=null,this._unsubEditedContent=null}static{this.styles=a`
1
+ import { MessageKey } from "../messageKey.mjs";
2
+ import { getGlobalEditorManager, onGlobalEditorManagerChange } from "../core/globalManager.mjs";
3
+ import { __decorate } from "../_virtual/_@oxc-project_runtime@0.115.0/helpers/decorate.mjs";
4
+ import { LitElement, css, html } from "lit";
5
+ import { property, state } from "lit/decorators.js";
6
+ import { isSameKeyPath } from "@intlayer/core/utils";
7
+ import * as NodeTypes from "@intlayer/types/nodeType";
8
+
9
+ //#region src/components/ContentSelectorWrapper.ts
10
+ /**
11
+ * <intlayer-content-selector-wrapper>
12
+ *
13
+ * Framework-agnostic Lit element that wraps content with the Intlayer editor
14
+ * selection UI. It replaces the per-framework ContentSelectorWrapper components
15
+ * (Vue, Svelte, Solid, Preact).
16
+ *
17
+ * It reads from the global EditorStateManager singleton (set by initEditorClient)
18
+ * and conditionally renders <intlayer-content-selector> around its slot content
19
+ * when the editor is active and the app is running inside an iframe.
20
+ *
21
+ * @attr {string} key-path - JSON-serialized KeyPath[] for this content node
22
+ * @attr {string} dictionary-key - The dictionary key owning this content node
23
+ */
24
+ var IntlayerContentSelectorWrapperElement = class extends LitElement {
25
+ constructor(..._args) {
26
+ super(..._args);
27
+ this.keyPathJson = "[]";
28
+ this.dictionaryKey = "";
29
+ this._editorEnabled = false;
30
+ this._isInIframe = false;
31
+ this._isSelected = false;
32
+ this._editedValue = void 0;
33
+ this._unsubManager = null;
34
+ this._unsubEnabled = null;
35
+ this._unsubFocused = null;
36
+ this._unsubEditedContent = null;
37
+ }
38
+ static {
39
+ this.styles = css`
2
40
  :host {
3
41
  display: contents;
4
42
  }
5
- `}connectedCallback(){super.connectedCallback(),typeof window<`u`&&(this._isInIframe=window.self!==window.top),this._subscribeToManager()}disconnectedCallback(){super.disconnectedCallback(),this._teardown()}updated(e){if(e.has(`keyPathJson`)||e.has(`dictionaryKey`)){let e=t();e&&this._updateEditedValue(e)}}_teardown(){this._unsubManager?.(),this._unsubEnabled?.(),this._unsubFocused?.(),this._unsubEditedContent?.(),this._unsubManager=null,this._unsubEnabled=null,this._unsubFocused=null,this._unsubEditedContent=null}_subscribeToManager(){let e=t();e&&this._setupManagerSubscriptions(e),this._unsubManager=n(e=>{this._unsubEnabled?.(),this._unsubFocused?.(),this._unsubEditedContent?.(),this._unsubEnabled=null,this._unsubFocused=null,this._unsubEditedContent=null,e?this._setupManagerSubscriptions(e):(this._editorEnabled=!1,this._isSelected=!1,this._editedValue=void 0)})}_setupManagerSubscriptions(e){this._editorEnabled=e.editorEnabled.value??!1,this._updateIsSelected(e.focusedContent.value),this._updateEditedValue(e);let t=e=>{this._editorEnabled=e.detail},n=e=>{this._updateIsSelected(e.detail)},r=()=>{this._updateEditedValue(e)};e.editorEnabled.addEventListener(`change`,t),e.focusedContent.addEventListener(`change`,n),e.editedContent.addEventListener(`change`,r),this._unsubEnabled=()=>e.editorEnabled.removeEventListener(`change`,t),this._unsubFocused=()=>e.focusedContent.removeEventListener(`change`,n),this._unsubEditedContent=()=>e.editedContent.removeEventListener(`change`,r)}_getRawKeyPath(){try{return JSON.parse(this.keyPathJson)}catch{return[]}}_getFilteredKeyPath(){return this._getRawKeyPath().filter(e=>e.type!==u.Translation)}_updateEditedValue(e){let t=this._getFilteredKeyPath();if(!this.dictionaryKey||t.length===0){this._editedValue=void 0;return}let n=this._getRawKeyPath(),r=n[n.length-1]?.type;if(r===u.Markdown||r===u.HTML||r===u.Insertion||r===u.File){this._editedValue=void 0;return}let i=e.getContentValue(this.dictionaryKey,t);if(typeof i==`object`&&i&&i.nodeType===u.Translation){let t=e.currentLocale.value;i=t?i[u.Translation][t]:void 0}this._editedValue=i}_updateIsSelected(e){if(!e){this._isSelected=!1;return}let t=this._getFilteredKeyPath();this._isSelected=e.dictionaryKey===this.dictionaryKey&&(e.keyPath?.length??0)>0&&l(e.keyPath??[],t)}_handlePress(e){e.stopPropagation();let n=t();n&&n.focusedContent.set({dictionaryKey:this.dictionaryKey,keyPath:this._getFilteredKeyPath()})}_handleHover(n){n.stopPropagation(),t()?.messenger.send(`${e.INTLAYER_HOVERED_CONTENT_CHANGED}/post`,{dictionaryKey:this.dictionaryKey,keyPath:this._getFilteredKeyPath()})}_handleUnhover(n){n.stopPropagation(),t()?.messenger.send(`${e.INTLAYER_HOVERED_CONTENT_CHANGED}/post`,null)}render(){if(!this._isInIframe||!this._editorEnabled)return o`<slot></slot>`;let e=this._editedValue,t=typeof e==`string`||typeof e==`number`||typeof e==`boolean`?e:o`<slot></slot>`;return o`
43
+ `;
44
+ }
45
+ connectedCallback() {
46
+ super.connectedCallback();
47
+ if (typeof window !== "undefined") this._isInIframe = window.self !== window.top;
48
+ this._subscribeToManager();
49
+ }
50
+ disconnectedCallback() {
51
+ super.disconnectedCallback();
52
+ this._teardown();
53
+ }
54
+ updated(changedProperties) {
55
+ if (changedProperties.has("keyPathJson") || changedProperties.has("dictionaryKey")) {
56
+ const manager = getGlobalEditorManager();
57
+ if (manager) this._updateEditedValue(manager);
58
+ }
59
+ }
60
+ _teardown() {
61
+ this._unsubManager?.();
62
+ this._unsubEnabled?.();
63
+ this._unsubFocused?.();
64
+ this._unsubEditedContent?.();
65
+ this._unsubManager = null;
66
+ this._unsubEnabled = null;
67
+ this._unsubFocused = null;
68
+ this._unsubEditedContent = null;
69
+ }
70
+ _subscribeToManager() {
71
+ const manager = getGlobalEditorManager();
72
+ if (manager) this._setupManagerSubscriptions(manager);
73
+ this._unsubManager = onGlobalEditorManagerChange((m) => {
74
+ this._unsubEnabled?.();
75
+ this._unsubFocused?.();
76
+ this._unsubEditedContent?.();
77
+ this._unsubEnabled = null;
78
+ this._unsubFocused = null;
79
+ this._unsubEditedContent = null;
80
+ if (m) this._setupManagerSubscriptions(m);
81
+ else {
82
+ this._editorEnabled = false;
83
+ this._isSelected = false;
84
+ this._editedValue = void 0;
85
+ }
86
+ });
87
+ }
88
+ _setupManagerSubscriptions(manager) {
89
+ this._editorEnabled = manager.editorEnabled.value ?? false;
90
+ this._updateIsSelected(manager.focusedContent.value);
91
+ this._updateEditedValue(manager);
92
+ const handleEnabledChange = (e) => {
93
+ this._editorEnabled = e.detail;
94
+ };
95
+ const handleFocusedChange = (e) => {
96
+ this._updateIsSelected(e.detail);
97
+ };
98
+ const handleEditedContentChange = () => {
99
+ this._updateEditedValue(manager);
100
+ };
101
+ manager.editorEnabled.addEventListener("change", handleEnabledChange);
102
+ manager.focusedContent.addEventListener("change", handleFocusedChange);
103
+ manager.editedContent.addEventListener("change", handleEditedContentChange);
104
+ this._unsubEnabled = () => manager.editorEnabled.removeEventListener("change", handleEnabledChange);
105
+ this._unsubFocused = () => manager.focusedContent.removeEventListener("change", handleFocusedChange);
106
+ this._unsubEditedContent = () => manager.editedContent.removeEventListener("change", handleEditedContentChange);
107
+ }
108
+ _getRawKeyPath() {
109
+ try {
110
+ return JSON.parse(this.keyPathJson);
111
+ } catch {
112
+ return [];
113
+ }
114
+ }
115
+ _getFilteredKeyPath() {
116
+ return this._getRawKeyPath().filter((k) => k.type !== NodeTypes.TRANSLATION);
117
+ }
118
+ _updateEditedValue(manager) {
119
+ const filteredKeyPath = this._getFilteredKeyPath();
120
+ if (!this.dictionaryKey || filteredKeyPath.length === 0) {
121
+ this._editedValue = void 0;
122
+ return;
123
+ }
124
+ const rawKeyPath = this._getRawKeyPath();
125
+ const lastStepType = rawKeyPath[rawKeyPath.length - 1]?.type;
126
+ if (lastStepType === NodeTypes.MARKDOWN || lastStepType === NodeTypes.HTML || lastStepType === NodeTypes.INSERTION || lastStepType === NodeTypes.FILE) {
127
+ this._editedValue = void 0;
128
+ return;
129
+ }
130
+ let value = manager.getContentValue(this.dictionaryKey, filteredKeyPath);
131
+ if (value !== null && value !== void 0 && typeof value === "object" && value.nodeType === NodeTypes.TRANSLATION) {
132
+ const locale = manager.currentLocale.value;
133
+ value = locale ? value[NodeTypes.TRANSLATION][locale] : void 0;
134
+ }
135
+ this._editedValue = value;
136
+ }
137
+ _updateIsSelected(focusedContent) {
138
+ if (!focusedContent) {
139
+ this._isSelected = false;
140
+ return;
141
+ }
142
+ const keyPath = this._getFilteredKeyPath();
143
+ this._isSelected = focusedContent.dictionaryKey === this.dictionaryKey && (focusedContent.keyPath?.length ?? 0) > 0 && isSameKeyPath(focusedContent.keyPath ?? [], keyPath);
144
+ }
145
+ _handlePress(e) {
146
+ e.stopPropagation();
147
+ const manager = getGlobalEditorManager();
148
+ if (!manager) return;
149
+ manager.focusedContent.set({
150
+ dictionaryKey: this.dictionaryKey,
151
+ keyPath: this._getFilteredKeyPath()
152
+ });
153
+ }
154
+ _handleHover(e) {
155
+ e.stopPropagation();
156
+ getGlobalEditorManager()?.messenger.send(`${MessageKey.INTLAYER_HOVERED_CONTENT_CHANGED}/post`, {
157
+ dictionaryKey: this.dictionaryKey,
158
+ keyPath: this._getFilteredKeyPath()
159
+ });
160
+ }
161
+ _handleUnhover(e) {
162
+ e.stopPropagation();
163
+ getGlobalEditorManager()?.messenger.send(`${MessageKey.INTLAYER_HOVERED_CONTENT_CHANGED}/post`, null);
164
+ }
165
+ render() {
166
+ if (!this._isInIframe || !this._editorEnabled) return html`<slot></slot>`;
167
+ const editedValue = this._editedValue;
168
+ const displayedContent = typeof editedValue === "string" || typeof editedValue === "number" || typeof editedValue === "boolean" ? editedValue : html`<slot></slot>`;
169
+ return html`
6
170
  <intlayer-content-selector
7
171
  ?is-selecting=${this._isSelected}
8
172
  @intlayer:press=${this._handlePress}
9
173
  @intlayer:hover=${this._handleHover}
10
174
  @intlayer:unhover=${this._handleUnhover}
11
175
  >
12
- ${t}
176
+ ${displayedContent}
13
177
  </intlayer-content-selector>
14
- `}};r([s({type:String,attribute:`key-path`})],d.prototype,`keyPathJson`,void 0),r([s({type:String,attribute:`dictionary-key`})],d.prototype,`dictionaryKey`,void 0),r([c()],d.prototype,`_editorEnabled`,void 0),r([c()],d.prototype,`_isInIframe`,void 0),r([c()],d.prototype,`_isSelected`,void 0),r([c()],d.prototype,`_editedValue`,void 0);const f=()=>{typeof customElements>`u`||customElements.get(`intlayer-content-selector-wrapper`)||customElements.define(`intlayer-content-selector-wrapper`,d)};export{d as IntlayerContentSelectorWrapperElement,f as defineIntlayerContentSelectorWrapper};
178
+ `;
179
+ }
180
+ };
181
+ __decorate([property({
182
+ type: String,
183
+ attribute: "key-path"
184
+ })], IntlayerContentSelectorWrapperElement.prototype, "keyPathJson", void 0);
185
+ __decorate([property({
186
+ type: String,
187
+ attribute: "dictionary-key"
188
+ })], IntlayerContentSelectorWrapperElement.prototype, "dictionaryKey", void 0);
189
+ __decorate([state()], IntlayerContentSelectorWrapperElement.prototype, "_editorEnabled", void 0);
190
+ __decorate([state()], IntlayerContentSelectorWrapperElement.prototype, "_isInIframe", void 0);
191
+ __decorate([state()], IntlayerContentSelectorWrapperElement.prototype, "_isSelected", void 0);
192
+ __decorate([state()], IntlayerContentSelectorWrapperElement.prototype, "_editedValue", void 0);
193
+ const defineIntlayerContentSelectorWrapper = () => {
194
+ if (typeof customElements === "undefined") return;
195
+ if (!customElements.get("intlayer-content-selector-wrapper")) customElements.define("intlayer-content-selector-wrapper", IntlayerContentSelectorWrapperElement);
196
+ };
197
+
198
+ //#endregion
199
+ export { IntlayerContentSelectorWrapperElement, defineIntlayerContentSelectorWrapper };
15
200
  //# sourceMappingURL=ContentSelectorWrapper.mjs.map
@@ -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 { NodeType, type TypedNodeModel } 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((k) => k.type !== NodeType.Translation);\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 === NodeType.Markdown ||\n lastStepType === NodeType.HTML ||\n lastStepType === NodeType.Insertion ||\n lastStepType === NodeType.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 === NodeType.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 NodeType.Translation,\n Record<string, ContentNode>\n >;\n value = locale ? node[NodeType.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":"qZA8BA,IAAa,EAAb,cAA2D,CAAW,gDAOH,wBACQ,uBAEvC,oBACH,oBACA,qBAC0B,IAAA,sBAEZ,wBACA,wBACA,8BACM,wBAjBnC,CAAG;;;;IAmBnB,mBAA0B,CACxB,MAAM,mBAAmB,CACrB,OAAO,OAAW,MACpB,KAAK,YAAc,OAAO,OAAS,OAAO,KAE5C,KAAK,qBAAqB,CAG5B,sBAA6B,CAC3B,MAAM,sBAAsB,CAC5B,KAAK,WAAW,CAGlB,QAAQ,EAA+C,CACrD,GACE,EAAkB,IAAI,cAAc,EACpC,EAAkB,IAAI,gBAAgB,CACtC,CACA,IAAM,EAAU,GAAwB,CACpC,GAAS,KAAK,mBAAmB,EAAQ,EAIjD,WAA0B,CACxB,KAAK,iBAAiB,CACtB,KAAK,iBAAiB,CACtB,KAAK,iBAAiB,CACtB,KAAK,uBAAuB,CAC5B,KAAK,cAAgB,KACrB,KAAK,cAAgB,KACrB,KAAK,cAAgB,KACrB,KAAK,oBAAsB,KAG7B,qBAAoC,CAClC,IAAM,EAAU,GAAwB,CACpC,GACF,KAAK,2BAA2B,EAAQ,CAG1C,KAAK,cAAgB,EAA6B,GAAM,CACtD,KAAK,iBAAiB,CACtB,KAAK,iBAAiB,CACtB,KAAK,uBAAuB,CAC5B,KAAK,cAAgB,KACrB,KAAK,cAAgB,KACrB,KAAK,oBAAsB,KACvB,EACF,KAAK,2BAA2B,EAAE,EAElC,KAAK,eAAiB,GACtB,KAAK,YAAc,GACnB,KAAK,aAAe,IAAA,KAEtB,CAGJ,2BAAmC,EAAmC,CACpE,KAAK,eAAiB,EAAQ,cAAc,OAAS,GACrD,KAAK,kBAAkB,EAAQ,eAAe,MAAM,CACpD,KAAK,mBAAmB,EAAQ,CAEhC,IAAM,EAAuB,GAAa,CACxC,KAAK,eAAkB,EAA2B,QAE9C,EAAuB,GAAa,CACxC,KAAK,kBAAmB,EAAsC,OAAO,EAEjE,MAAkC,CACtC,KAAK,mBAAmB,EAAQ,EAGlC,EAAQ,cAAc,iBAAiB,SAAU,EAAoB,CACrE,EAAQ,eAAe,iBAAiB,SAAU,EAAoB,CACtE,EAAQ,cAAc,iBAAiB,SAAU,EAA0B,CAE3E,KAAK,kBACH,EAAQ,cAAc,oBAAoB,SAAU,EAAoB,CAC1E,KAAK,kBACH,EAAQ,eAAe,oBAAoB,SAAU,EAAoB,CAC3E,KAAK,wBACH,EAAQ,cAAc,oBACpB,SACA,EACD,CAGL,gBAAoC,CAClC,GAAI,CACF,OAAO,KAAK,MAAM,KAAK,YAAY,MAC7B,CACN,MAAO,EAAE,EAIb,qBAAyC,CACvC,OAAO,KAAK,gBAAgB,CAAC,OAAQ,GAAM,EAAE,OAAS,EAAS,YAAY,CAG7E,mBAA2B,EAAmC,CAC5D,IAAM,EAAkB,KAAK,qBAAqB,CAClD,GAAI,CAAC,KAAK,eAAiB,EAAgB,SAAW,EAAG,CACvD,KAAK,aAAe,IAAA,GACpB,OAMF,IAAM,EAAa,KAAK,gBAAgB,CAClC,EAAe,EAAW,EAAW,OAAS,IAAI,KACxD,GACE,IAAiB,EAAS,UAC1B,IAAiB,EAAS,MAC1B,IAAiB,EAAS,WAC1B,IAAiB,EAAS,KAC1B,CACA,KAAK,aAAe,IAAA,GACpB,OAGF,IAAI,EAAQ,EAAQ,gBAAgB,KAAK,cAAe,EAAgB,CAMxE,GAGE,OAAO,GAAU,UAFjB,GAGA,EAAM,WAAa,EAAS,YAC5B,CACA,IAAM,EAAS,EAAQ,cAAc,MAOrC,EAAQ,EAJK,EAIS,EAAS,aAAa,GAAU,IAAA,GAGxD,KAAK,aAAe,EAGtB,kBACE,EACM,CACN,GAAI,CAAC,EAAgB,CACnB,KAAK,YAAc,GACnB,OAEF,IAAM,EAAU,KAAK,qBAAqB,CAC1C,KAAK,YACH,EAAe,gBAAkB,KAAK,gBACrC,EAAe,SAAS,QAAU,GAAK,GACxC,EAAc,EAAe,SAAW,EAAE,CAAE,EAAQ,CAGxD,aAAqB,EAAgB,CAEnC,EAAE,iBAAiB,CACnB,IAAM,EAAU,GAAwB,CACnC,GACL,EAAQ,eAAe,IAAI,CACzB,cAAe,KAAK,cACpB,QAAS,KAAK,qBAAqB,CACpC,CAAC,CAGJ,aAAqB,EAAgB,CACnC,EAAE,iBAAiB,CACnB,GAAwB,EAAE,UAAU,KAClC,GAAG,EAAW,iCAAiC,OAC/C,CAAE,cAAe,KAAK,cAAe,QAAS,KAAK,qBAAqB,CAAE,CAC3E,CAGH,eAAuB,EAAgB,CACrC,EAAE,iBAAiB,CACnB,GAAwB,EAAE,UAAU,KAClC,GAAG,EAAW,iCAAiC,OAC/C,KACD,CAGH,QAAS,CACP,GAAI,CAAC,KAAK,aAAe,CAAC,KAAK,eAC7B,MAAO,EAAI,gBAGb,IAAM,EAAc,KAAK,aACnB,EACJ,OAAO,GAAgB,UACvB,OAAO,GAAgB,UACvB,OAAO,GAAgB,UACnB,EACA,CAAI,gBAEV,MAAO,EAAI;;wBAES,KAAK,YAAY;0BACf,KAAK,aAAa;0BAClB,KAAK,aAAa;4BAChB,KAAK,eAAe;;UAEtC,EAAiB;;WA5NxB,EAAS,CAAE,KAAM,OAAQ,UAAW,WAAY,CAAC,CAAA,CAAA,EAAA,UAAA,cAAA,IAAA,GAAA,IACjD,EAAS,CAAE,KAAM,OAAQ,UAAW,iBAAkB,CAAC,CAAA,CAAA,EAAA,UAAA,gBAAA,IAAA,GAAA,IAEvD,GAAO,CAAA,CAAA,EAAA,UAAA,iBAAA,IAAA,GAAA,IACP,GAAO,CAAA,CAAA,EAAA,UAAA,cAAA,IAAA,GAAA,IACP,GAAO,CAAA,CAAA,EAAA,UAAA,cAAA,IAAA,GAAA,IACP,GAAO,CAAA,CAAA,EAAA,UAAA,eAAA,IAAA,GAAA,CA4NV,MAAa,MAAmD,CAC1D,OAAO,eAAmB,KAEzB,eAAe,IAAI,oCAAoC,EAC1D,eAAe,OACb,oCACA,EACD"}
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,13 +1,134 @@
1
- import{getGlobalEditorManager as e,onGlobalEditorManagerChange as t}from"../core/globalManager.mjs";import{t as n}from"../decorate-BWURH4oJ.mjs";import{LitElement as r,css as i,html as a}from"lit";import{property as o,state as s}from"lit/decorators.js";import{getBasePlugins as c,getContent as l}from"@intlayer/core/interpreter";var u=class extends r{constructor(...e){super(...e),this.dictionaryKey=``,this.keyPathJson=`[]`,this.locale=``,this._editedText=null,this._unsubManager=null,this._unsubEditedContent=null}static{this.styles=i`
1
+ import { getGlobalEditorManager, onGlobalEditorManagerChange } from "../core/globalManager.mjs";
2
+ import { __decorate } from "../_virtual/_@oxc-project_runtime@0.115.0/helpers/decorate.mjs";
3
+ import { LitElement, css, html } from "lit";
4
+ import { property, state } from "lit/decorators.js";
5
+ import { getBasePlugins, getContent } from "@intlayer/core/interpreter";
6
+
7
+ //#region src/components/EditedContent.ts
8
+ /**
9
+ * <intlayer-edited-content>
10
+ *
11
+ * Framework-agnostic Lit element that displays edited content from the Intlayer
12
+ * editor. When the editor has an edited value for the given dictionary key and
13
+ * key path, it renders the edited value; otherwise it renders the original
14
+ * content via a slot.
15
+ *
16
+ * Always wraps content in <intlayer-content-selector-wrapper> for selection UI.
17
+ *
18
+ * @attr {string} dictionary-key - The dictionary key owning this content node
19
+ * @attr {string} key-path - JSON-serialized KeyPath[] for this content node
20
+ * @attr {string} locale - The current locale string
21
+ */
22
+ var IntlayerEditedContentElement = class extends LitElement {
23
+ constructor(..._args) {
24
+ super(..._args);
25
+ this.dictionaryKey = "";
26
+ this.keyPathJson = "[]";
27
+ this.locale = "";
28
+ this._editedText = null;
29
+ this._unsubManager = null;
30
+ this._unsubEditedContent = null;
31
+ }
32
+ static {
33
+ this.styles = css`
2
34
  :host {
3
35
  display: contents;
4
36
  }
5
- `}connectedCallback(){super.connectedCallback(),this._subscribeToManager()}disconnectedCallback(){super.disconnectedCallback(),this._teardown()}_teardown(){this._unsubManager?.(),this._unsubEditedContent?.(),this._unsubManager=null,this._unsubEditedContent=null}_getKeyPath(){try{return JSON.parse(this.keyPathJson)}catch{return[]}}_resolveEditedText(e){let t=this._getKeyPath(),n=e.getContentValue(this.dictionaryKey,t);if(n==null){this._editedText=null;return}if(typeof n==`string`||typeof n==`number`){this._editedText=String(n);return}if(typeof n==`object`){let e=this.locale||void 0,r=l(n,{locale:e,dictionaryKey:this.dictionaryKey,keyPath:t},c(e));typeof r==`string`||typeof r==`number`?this._editedText=String(r):(console.error(`[intlayer-edited-content] Incorrect edited content format. Expected string. Value: ${JSON.stringify(r)}`),this._editedText=null);return}this._editedText=null}_setupManagerSubscriptions(e){this._resolveEditedText(e);let t=()=>this._resolveEditedText(e);e.editedContent.addEventListener(`change`,t),this._unsubEditedContent=()=>e.editedContent.removeEventListener(`change`,t)}_subscribeToManager(){let n=e();n&&this._setupManagerSubscriptions(n),this._unsubManager=t(e=>{this._unsubEditedContent?.(),this._unsubEditedContent=null,e?this._setupManagerSubscriptions(e):this._editedText=null})}render(){return a`
37
+ `;
38
+ }
39
+ connectedCallback() {
40
+ super.connectedCallback();
41
+ this._subscribeToManager();
42
+ }
43
+ disconnectedCallback() {
44
+ super.disconnectedCallback();
45
+ this._teardown();
46
+ }
47
+ _teardown() {
48
+ this._unsubManager?.();
49
+ this._unsubEditedContent?.();
50
+ this._unsubManager = null;
51
+ this._unsubEditedContent = null;
52
+ }
53
+ _getKeyPath() {
54
+ try {
55
+ return JSON.parse(this.keyPathJson);
56
+ } catch {
57
+ return [];
58
+ }
59
+ }
60
+ _resolveEditedText(manager) {
61
+ const keyPath = this._getKeyPath();
62
+ const editedValue = manager.getContentValue(this.dictionaryKey, keyPath);
63
+ if (editedValue === void 0 || editedValue === null) {
64
+ this._editedText = null;
65
+ return;
66
+ }
67
+ if (typeof editedValue === "string" || typeof editedValue === "number") {
68
+ this._editedText = String(editedValue);
69
+ return;
70
+ }
71
+ if (typeof editedValue === "object") {
72
+ const locale = this.locale || void 0;
73
+ const transformed = getContent(editedValue, {
74
+ locale,
75
+ dictionaryKey: this.dictionaryKey,
76
+ keyPath
77
+ }, getBasePlugins(locale));
78
+ if (typeof transformed === "string" || typeof transformed === "number") this._editedText = String(transformed);
79
+ else {
80
+ console.error(`[intlayer-edited-content] Incorrect edited content format. Expected string. Value: ${JSON.stringify(transformed)}`);
81
+ this._editedText = null;
82
+ }
83
+ return;
84
+ }
85
+ this._editedText = null;
86
+ }
87
+ _setupManagerSubscriptions(manager) {
88
+ this._resolveEditedText(manager);
89
+ const handleChange = () => this._resolveEditedText(manager);
90
+ manager.editedContent.addEventListener("change", handleChange);
91
+ this._unsubEditedContent = () => manager.editedContent.removeEventListener("change", handleChange);
92
+ }
93
+ _subscribeToManager() {
94
+ const manager = getGlobalEditorManager();
95
+ if (manager) this._setupManagerSubscriptions(manager);
96
+ this._unsubManager = onGlobalEditorManagerChange((m) => {
97
+ this._unsubEditedContent?.();
98
+ this._unsubEditedContent = null;
99
+ if (m) this._setupManagerSubscriptions(m);
100
+ else this._editedText = null;
101
+ });
102
+ }
103
+ render() {
104
+ return html`
6
105
  <intlayer-content-selector-wrapper
7
106
  key-path=${this.keyPathJson}
8
107
  dictionary-key=${this.dictionaryKey}
9
108
  >
10
- ${this._editedText===null?a`<slot></slot>`:this._editedText}
109
+ ${this._editedText !== null ? this._editedText : html`<slot></slot>`}
11
110
  </intlayer-content-selector-wrapper>
12
- `}};n([o({type:String,attribute:`dictionary-key`})],u.prototype,`dictionaryKey`,void 0),n([o({type:String,attribute:`key-path`})],u.prototype,`keyPathJson`,void 0),n([o({type:String,attribute:`locale`})],u.prototype,`locale`,void 0),n([s()],u.prototype,`_editedText`,void 0);const d=()=>{typeof customElements>`u`||customElements.get(`intlayer-edited-content`)||customElements.define(`intlayer-edited-content`,u)};export{u as IntlayerEditedContentElement,d as defineIntlayerEditedContent};
111
+ `;
112
+ }
113
+ };
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
+ const defineIntlayerEditedContent = () => {
128
+ if (typeof customElements === "undefined") return;
129
+ if (!customElements.get("intlayer-edited-content")) customElements.define("intlayer-edited-content", IntlayerEditedContentElement);
130
+ };
131
+
132
+ //#endregion
133
+ export { IntlayerEditedContentElement, defineIntlayerEditedContent };
13
134
  //# sourceMappingURL=EditedContent.mjs.map
@@ -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 { css, html, LitElement } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport type { EditorStateManager } from '../core/EditorStateManager';\nimport {\n getGlobalEditorManager,\n onGlobalEditorManagerChange,\n} from '../core/globalManager';\n\n/**\n * <intlayer-edited-content>\n *\n * Framework-agnostic Lit element 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 LitElement {\n static styles = css`\n :host {\n display: contents;\n }\n `;\n\n @property({ type: String, attribute: 'dictionary-key' }) dictionaryKey = '';\n @property({ type: String, attribute: 'key-path' }) keyPathJson = '[]';\n @property({ type: String, attribute: 'locale' }) locale = '';\n\n @state() private _editedText: string | null = null;\n\n private _unsubManager: (() => void) | null = null;\n private _unsubEditedContent: (() => void) | null = null;\n\n connectedCallback(): void {\n super.connectedCallback();\n this._subscribeToManager();\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\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 _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 return;\n }\n\n if (typeof editedValue === 'string' || typeof editedValue === 'number') {\n this._editedText = String(editedValue);\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 as any)\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 return;\n }\n\n this._editedText = null;\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 }\n });\n }\n\n render() {\n return html`\n <intlayer-content-selector-wrapper\n key-path=${this.keyPathJson}\n dictionary-key=${this.dictionaryKey}\n >\n ${this._editedText !== null ? this._editedText : html`<slot></slot>`}\n </intlayer-content-selector-wrapper>\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":"yUAwBA,IAAa,EAAb,cAAkD,CAAW,kDAOc,oBACR,iBACP,oBAEZ,wBAED,8BACM,wBAbnC,CAAG;;;;IAenB,mBAA0B,CACxB,MAAM,mBAAmB,CACzB,KAAK,qBAAqB,CAG5B,sBAA6B,CAC3B,MAAM,sBAAsB,CAC5B,KAAK,WAAW,CAGlB,WAA0B,CACxB,KAAK,iBAAiB,CACtB,KAAK,uBAAuB,CAC5B,KAAK,cAAgB,KACrB,KAAK,oBAAsB,KAG7B,aAAiC,CAC/B,GAAI,CACF,OAAO,KAAK,MAAM,KAAK,YAAY,MAC7B,CACN,MAAO,EAAE,EAIb,mBAA2B,EAAmC,CAC5D,IAAM,EAAU,KAAK,aAAa,CAC5B,EAAc,EAAQ,gBAAgB,KAAK,cAAe,EAAQ,CAExE,GAAI,GAA6C,KAAM,CACrD,KAAK,YAAc,KACnB,OAGF,GAAI,OAAO,GAAgB,UAAY,OAAO,GAAgB,SAAU,CACtE,KAAK,YAAc,OAAO,EAAY,CACtC,OAGF,GAAI,OAAO,GAAgB,SAAU,CACnC,IAAM,EAAS,KAAK,QAAU,IAAA,GACxB,EAAc,EAClB,EACA,CACU,SACR,cAAe,KAAK,cACpB,UACD,CACD,EAAe,EAAc,CAC9B,CACG,OAAO,GAAgB,UAAY,OAAO,GAAgB,SAC5D,KAAK,YAAc,OAAO,EAAY,EAEtC,QAAQ,MACN,sFAAsF,KAAK,UAAU,EAAY,GAClH,CACD,KAAK,YAAc,MAErB,OAGF,KAAK,YAAc,KAGrB,2BAAmC,EAAmC,CACpE,KAAK,mBAAmB,EAAQ,CAEhC,IAAM,MAAqB,KAAK,mBAAmB,EAAQ,CAC3D,EAAQ,cAAc,iBAAiB,SAAU,EAAa,CAE9D,KAAK,wBACH,EAAQ,cAAc,oBAAoB,SAAU,EAAa,CAGrE,qBAAoC,CAClC,IAAM,EAAU,GAAwB,CACpC,GACF,KAAK,2BAA2B,EAAQ,CAG1C,KAAK,cAAgB,EAA6B,GAAM,CACtD,KAAK,uBAAuB,CAC5B,KAAK,oBAAsB,KACvB,EACF,KAAK,2BAA2B,EAAE,CAElC,KAAK,YAAc,MAErB,CAGJ,QAAS,CACP,MAAO,EAAI;;mBAEI,KAAK,YAAY;yBACX,KAAK,cAAc;;UAElC,KAAK,cAAgB,KAA0B,CAAI,gBAAvB,KAAK,YAAkC;;WA1G1E,EAAS,CAAE,KAAM,OAAQ,UAAW,iBAAkB,CAAC,CAAA,CAAA,EAAA,UAAA,gBAAA,IAAA,GAAA,IACvD,EAAS,CAAE,KAAM,OAAQ,UAAW,WAAY,CAAC,CAAA,CAAA,EAAA,UAAA,cAAA,IAAA,GAAA,IACjD,EAAS,CAAE,KAAM,OAAQ,UAAW,SAAU,CAAC,CAAA,CAAA,EAAA,UAAA,SAAA,IAAA,GAAA,IAE/C,GAAO,CAAA,CAAA,EAAA,UAAA,cAAA,IAAA,GAAA,CA4GV,MAAa,MAA0C,CACjD,OAAO,eAAmB,KAEzB,eAAe,IAAI,0BAA0B,EAChD,eAAe,OACb,0BACA,EACD"}
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 { css, html, LitElement } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport type { EditorStateManager } from '../core/EditorStateManager';\nimport {\n getGlobalEditorManager,\n onGlobalEditorManagerChange,\n} from '../core/globalManager';\n\n/**\n * <intlayer-edited-content>\n *\n * Framework-agnostic Lit element 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 LitElement {\n static styles = css`\n :host {\n display: contents;\n }\n `;\n\n @property({ type: String, attribute: 'dictionary-key' }) dictionaryKey = '';\n @property({ type: String, attribute: 'key-path' }) keyPathJson = '[]';\n @property({ type: String, attribute: 'locale' }) locale = '';\n\n @state() private _editedText: string | null = null;\n\n private _unsubManager: (() => void) | null = null;\n private _unsubEditedContent: (() => void) | null = null;\n\n connectedCallback(): void {\n super.connectedCallback();\n this._subscribeToManager();\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\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 _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 return;\n }\n\n if (typeof editedValue === 'string' || typeof editedValue === 'number') {\n this._editedText = String(editedValue);\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 as any)\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 return;\n }\n\n this._editedText = null;\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 }\n });\n }\n\n render() {\n return html`\n <intlayer-content-selector-wrapper\n key-path=${this.keyPathJson}\n dictionary-key=${this.dictionaryKey}\n >\n ${this._editedText !== null ? this._editedText : html`<slot></slot>`}\n </intlayer-content-selector-wrapper>\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":";;;;;;;;;;;;;;;;;;;;;AAwBA,IAAa,+BAAb,cAAkD,WAAW;;;uBAOc;qBACR;gBACP;qBAEZ;uBAED;6BACM;;;gBAbnC,GAAG;;;;;;CAenB,oBAA0B;AACxB,QAAM,mBAAmB;AACzB,OAAK,qBAAqB;;CAG5B,uBAA6B;AAC3B,QAAM,sBAAsB;AAC5B,OAAK,WAAW;;CAGlB,AAAQ,YAAkB;AACxB,OAAK,iBAAiB;AACtB,OAAK,uBAAuB;AAC5B,OAAK,gBAAgB;AACrB,OAAK,sBAAsB;;CAG7B,AAAQ,cAAyB;AAC/B,MAAI;AACF,UAAO,KAAK,MAAM,KAAK,YAAY;UAC7B;AACN,UAAO,EAAE;;;CAIb,AAAQ,mBAAmB,SAAmC;EAC5D,MAAM,UAAU,KAAK,aAAa;EAClC,MAAM,cAAc,QAAQ,gBAAgB,KAAK,eAAe,QAAQ;AAExE,MAAI,gBAAgB,UAAa,gBAAgB,MAAM;AACrD,QAAK,cAAc;AACnB;;AAGF,MAAI,OAAO,gBAAgB,YAAY,OAAO,gBAAgB,UAAU;AACtE,QAAK,cAAc,OAAO,YAAY;AACtC;;AAGF,MAAI,OAAO,gBAAgB,UAAU;GACnC,MAAM,SAAS,KAAK,UAAU;GAC9B,MAAM,cAAc,WAClB,aACA;IACU;IACR,eAAe,KAAK;IACpB;IACD,EACD,eAAe,OAAc,CAC9B;AACD,OAAI,OAAO,gBAAgB,YAAY,OAAO,gBAAgB,SAC5D,MAAK,cAAc,OAAO,YAAY;QACjC;AACL,YAAQ,MACN,sFAAsF,KAAK,UAAU,YAAY,GAClH;AACD,SAAK,cAAc;;AAErB;;AAGF,OAAK,cAAc;;CAGrB,AAAQ,2BAA2B,SAAmC;AACpE,OAAK,mBAAmB,QAAQ;EAEhC,MAAM,qBAAqB,KAAK,mBAAmB,QAAQ;AAC3D,UAAQ,cAAc,iBAAiB,UAAU,aAAa;AAE9D,OAAK,4BACH,QAAQ,cAAc,oBAAoB,UAAU,aAAa;;CAGrE,AAAQ,sBAA4B;EAClC,MAAM,UAAU,wBAAwB;AACxC,MAAI,QACF,MAAK,2BAA2B,QAAQ;AAG1C,OAAK,gBAAgB,6BAA6B,MAAM;AACtD,QAAK,uBAAuB;AAC5B,QAAK,sBAAsB;AAC3B,OAAI,EACF,MAAK,2BAA2B,EAAE;OAElC,MAAK,cAAc;IAErB;;CAGJ,SAAS;AACP,SAAO,IAAI;;mBAEI,KAAK,YAAY;yBACX,KAAK,cAAc;;UAElC,KAAK,gBAAgB,OAAO,KAAK,cAAc,IAAI,gBAAgB;;;;;YA1G1E,SAAS;CAAE,MAAM;CAAQ,WAAW;CAAkB,CAAC;YACvD,SAAS;CAAE,MAAM;CAAQ,WAAW;CAAY,CAAC;YACjD,SAAS;CAAE,MAAM;CAAQ,WAAW;CAAU,CAAC;YAE/C,OAAO;AA4GV,MAAa,oCAA0C;AACrD,KAAI,OAAO,mBAAmB,YAAa;AAE3C,KAAI,CAAC,eAAe,IAAI,0BAA0B,CAChD,gBAAe,OACb,2BACA,6BACD"}
@@ -1 +1,84 @@
1
- import{i as e,r as t}from"../components-RtOXxg9h.mjs";export{t as IntlayerEditorElement,e as defineIntlayerEditorElement};
1
+ import { getGlobalEditorManager, onGlobalEditorManagerChange } from "../core/globalManager.mjs";
2
+ import { __decorate } from "../_virtual/_@oxc-project_runtime@0.115.0/helpers/decorate.mjs";
3
+ import { initEditorClient, stopEditorClient } from "../core/initEditorClient.mjs";
4
+ import { LitElement } from "lit";
5
+ import { property } from "lit/decorators.js";
6
+
7
+ //#region src/components/IntlayerEditor.ts
8
+ /**
9
+ * <intlayer-editor>
10
+ *
11
+ * A framework-agnostic Lit element that manages the Intlayer editor singleton
12
+ * lifecycle and keeps the current locale in sync with the EditorStateManager.
13
+ *
14
+ * Drop this element once at the root of your application to activate the editor.
15
+ * It renders no UI (display: contents, empty shadow root).
16
+ *
17
+ * @prop {IntlayerConfig} configuration - The Intlayer config (required; set as property, not attribute)
18
+ * @prop {string} locale - The active application locale (attribute/property)
19
+ *
20
+ * @example
21
+ * // Svelte
22
+ * <intlayer-editor .configuration={config} locale={$locale} />
23
+ *
24
+ * // Vue
25
+ * <intlayer-editor :configuration="config" :locale="currentLocale" />
26
+ */
27
+ var IntlayerEditorElement = class extends LitElement {
28
+ constructor(..._args) {
29
+ super(..._args);
30
+ this._initialized = false;
31
+ this._unsubManager = null;
32
+ }
33
+ /** No visible UI — render nothing into the shadow root */
34
+ createRenderRoot() {
35
+ return this;
36
+ }
37
+ connectedCallback() {
38
+ super.connectedCallback();
39
+ this._init();
40
+ }
41
+ disconnectedCallback() {
42
+ super.disconnectedCallback();
43
+ this._unsubManager?.();
44
+ this._unsubManager = null;
45
+ if (this._initialized) {
46
+ stopEditorClient();
47
+ this._initialized = false;
48
+ }
49
+ }
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
+ _init() {
55
+ if (this._initialized) return;
56
+ initEditorClient();
57
+ this._initialized = true;
58
+ if (this.locale) this._syncLocale(this.locale);
59
+ }
60
+ _syncLocale(locale) {
61
+ const manager = getGlobalEditorManager();
62
+ if (manager) manager.currentLocale.set(locale);
63
+ else {
64
+ this._unsubManager?.();
65
+ this._unsubManager = onGlobalEditorManagerChange((manager) => {
66
+ if (manager) {
67
+ this._unsubManager?.();
68
+ this._unsubManager = null;
69
+ manager.currentLocale.set(locale);
70
+ }
71
+ });
72
+ }
73
+ }
74
+ };
75
+ __decorate([property({ attribute: false })], IntlayerEditorElement.prototype, "configuration", void 0);
76
+ __decorate([property({ type: String })], IntlayerEditorElement.prototype, "locale", void 0);
77
+ const defineIntlayerEditorElement = () => {
78
+ if (typeof customElements === "undefined") return;
79
+ if (!customElements.get("intlayer-editor")) customElements.define("intlayer-editor", IntlayerEditorElement);
80
+ };
81
+
82
+ //#endregion
83
+ export { IntlayerEditorElement, defineIntlayerEditorElement };
84
+ //# sourceMappingURL=IntlayerEditor.mjs.map
@@ -0,0 +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 { LitElement } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport {\n getGlobalEditorManager,\n onGlobalEditorManagerChange,\n} from '../core/globalManager';\nimport { initEditorClient, stopEditorClient } from '../core/initEditorClient';\n\n/**\n * <intlayer-editor>\n *\n * A framework-agnostic Lit element 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 (display: contents, empty shadow root).\n *\n * @prop {IntlayerConfig} configuration - The Intlayer config (required; set as 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 LitElement {\n /** No visible UI — render nothing into the shadow root */\n createRenderRoot(): this {\n return this;\n }\n\n @property({ attribute: false }) configuration?: IntlayerConfig;\n\n @property({ type: String }) locale?: string;\n\n private _initialized = false;\n private _unsubManager: (() => void) | null = null;\n\n connectedCallback(): void {\n super.connectedCallback();\n this._init();\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n this._unsubManager?.();\n this._unsubManager = null;\n\n if (this._initialized) {\n stopEditorClient();\n this._initialized = false;\n }\n }\n\n updated(changedProperties: Map<string | symbol, unknown>): void {\n if (changedProperties.has('configuration') && !this._initialized) {\n this._init();\n }\n\n if (changedProperties.has('locale') && this.locale) {\n this._syncLocale(this.locale);\n }\n }\n\n private _init(): void {\n if (this._initialized) return;\n\n initEditorClient();\n\n this._initialized = true;\n\n // Sync locale immediately after init if it is already set\n if (this.locale) {\n this._syncLocale(this.locale);\n }\n }\n\n private _syncLocale(locale: string): void {\n const manager = getGlobalEditorManager();\n\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((manager) => {\n if (manager) {\n this._unsubManager?.();\n this._unsubManager = null;\n\n manager.currentLocale.set(locale as Locale);\n }\n });\n }\n }\n}\n\nexport const defineIntlayerEditorElement = (): void => {\n if (typeof customElements === 'undefined') return;\n\n if (!customElements.get('intlayer-editor')) {\n customElements.define('intlayer-editor', IntlayerEditorElement);\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,IAAa,wBAAb,cAA2C,WAAW;;;sBAU7B;uBACsB;;;CAT7C,mBAAyB;AACvB,SAAO;;CAUT,oBAA0B;AACxB,QAAM,mBAAmB;AACzB,OAAK,OAAO;;CAGd,uBAA6B;AAC3B,QAAM,sBAAsB;AAC5B,OAAK,iBAAiB;AACtB,OAAK,gBAAgB;AAErB,MAAI,KAAK,cAAc;AACrB,qBAAkB;AAClB,QAAK,eAAe;;;CAIxB,QAAQ,mBAAwD;AAC9D,MAAI,kBAAkB,IAAI,gBAAgB,IAAI,CAAC,KAAK,aAClD,MAAK,OAAO;AAGd,MAAI,kBAAkB,IAAI,SAAS,IAAI,KAAK,OAC1C,MAAK,YAAY,KAAK,OAAO;;CAIjC,AAAQ,QAAc;AACpB,MAAI,KAAK,aAAc;AAEvB,oBAAkB;AAElB,OAAK,eAAe;AAGpB,MAAI,KAAK,OACP,MAAK,YAAY,KAAK,OAAO;;CAIjC,AAAQ,YAAY,QAAsB;EACxC,MAAM,UAAU,wBAAwB;AAExC,MAAI,QACF,SAAQ,cAAc,IAAI,OAAiB;OACtC;AAEL,QAAK,iBAAiB;AACtB,QAAK,gBAAgB,6BAA6B,YAAY;AAC5D,QAAI,SAAS;AACX,UAAK,iBAAiB;AACtB,UAAK,gBAAgB;AAErB,aAAQ,cAAc,IAAI,OAAiB;;KAE7C;;;;YA7DL,SAAS,EAAE,WAAW,OAAO,CAAC;YAE9B,SAAS,EAAE,MAAM,QAAQ,CAAC;AAgE7B,MAAa,oCAA0C;AACrD,KAAI,OAAO,mBAAmB,YAAa;AAE3C,KAAI,CAAC,eAAe,IAAI,kBAAkB,CACxC,gBAAe,OAAO,mBAAmB,sBAAsB"}
@@ -1 +1,6 @@
1
- import{IntlayerContentSelectorWrapperElement as e,defineIntlayerContentSelectorWrapper as t}from"./ContentSelectorWrapper.mjs";import{IntlayerEditedContentElement as n,defineIntlayerEditedContent as r}from"./EditedContent.mjs";import{i,n as a,r as o,t as s}from"../components-RtOXxg9h.mjs";export{s as IntlayerContentSelectorElement,e as IntlayerContentSelectorWrapperElement,n as IntlayerEditedContentElement,o as IntlayerEditorElement,t as defineIntlayerContentSelectorWrapper,r as defineIntlayerEditedContent,i as defineIntlayerEditorElement,a as defineIntlayerElements};
1
+ import { IntlayerContentSelectorWrapperElement, defineIntlayerContentSelectorWrapper } from "./ContentSelectorWrapper.mjs";
2
+ import { IntlayerEditedContentElement, defineIntlayerEditedContent } from "./EditedContent.mjs";
3
+ import { IntlayerEditorElement, defineIntlayerEditorElement } from "./IntlayerEditor.mjs";
4
+ import { IntlayerContentSelectorElement, defineIntlayerElements } from "./ContentSelector.mjs";
5
+
6
+ export { IntlayerContentSelectorElement, IntlayerContentSelectorWrapperElement, IntlayerEditedContentElement, IntlayerEditorElement, defineIntlayerContentSelectorWrapper, defineIntlayerEditedContent, defineIntlayerEditorElement, defineIntlayerElements };
@@ -1,2 +1,77 @@
1
- import{compareUrls as e}from"../compareUrls.mjs";const t=()=>Math.random().toString(36).slice(2);var n=class{constructor(e){this._subscribers=new Map,this._windowHandler=null,this._seenMessageIds=new Set,this._config=e,this.senderId=t()}start(){typeof window>`u`||this._windowHandler||(this._windowHandler=e=>{this._handleMessage(e)},window.addEventListener(`message`,this._windowHandler))}stop(){this._windowHandler&&=(window.removeEventListener(`message`,this._windowHandler),null)}send(e,n){let r={type:e,data:n,senderId:this.senderId,messageId:t()};for(let e of this._config.allowedOrigins)e&&this._config.postMessageFn(r,e)}subscribe(e,t){return this._subscribers.has(e)||this._subscribers.set(e,new Set),this._subscribers.get(e).add(t),()=>{this._subscribers.get(e)?.delete(t)}}_handleMessage(t){let n=t.data;if(!n||typeof n!=`object`)return;let{type:r,data:i,senderId:a,messageId:o}=n;if(!r||typeof r!=`string`||a===this.senderId)return;if(o){if(this._seenMessageIds.has(o))return;this._seenMessageIds.add(o),this._seenMessageIds.size>200&&this._seenMessageIds.clear()}let{allowedOrigins:s}=this._config;if(!(!s||s.length===0||s.includes(`*`)||s.filter(e=>!!e&&e!==``).some(n=>e(n,t.origin))))return;let c=this._subscribers.get(r);if(c)for(let e of c)e(i,a)}};export{n as CrossFrameMessenger};
1
+ import { compareUrls } from "../compareUrls.mjs";
2
+
3
+ //#region src/core/CrossFrameMessenger.ts
4
+ const randomUUID = () => Math.random().toString(36).slice(2);
5
+ /**
6
+ * CrossFrameMessenger manages all cross-frame postMessage communication.
7
+ * It owns a single window message listener and routes incoming messages to
8
+ * type-specific subscribers.
9
+ *
10
+ * Replaces CommunicatorContext + useCrossFrameMessageListener across all frameworks.
11
+ */
12
+ var CrossFrameMessenger = class {
13
+ constructor(config) {
14
+ this._subscribers = /* @__PURE__ */ new Map();
15
+ this._windowHandler = null;
16
+ this._seenMessageIds = /* @__PURE__ */ new Set();
17
+ this._config = config;
18
+ this.senderId = randomUUID();
19
+ }
20
+ /** Start listening for incoming messages on window. */
21
+ start() {
22
+ if (typeof window === "undefined") return;
23
+ if (this._windowHandler) return;
24
+ this._windowHandler = (event) => {
25
+ this._handleMessage(event);
26
+ };
27
+ window.addEventListener("message", this._windowHandler);
28
+ }
29
+ /** Stop listening and clean up. */
30
+ stop() {
31
+ if (this._windowHandler) {
32
+ window.removeEventListener("message", this._windowHandler);
33
+ this._windowHandler = null;
34
+ }
35
+ }
36
+ /** Send a message payload to all configured target origins. */
37
+ send(type, data) {
38
+ const payload = {
39
+ type,
40
+ data,
41
+ senderId: this.senderId,
42
+ messageId: randomUUID()
43
+ };
44
+ for (const origin of this._config.allowedOrigins) if (origin) this._config.postMessageFn(payload, origin);
45
+ }
46
+ /**
47
+ * Subscribe to messages of a given type.
48
+ * Returns an unsubscribe function.
49
+ */
50
+ subscribe(type, handler) {
51
+ if (!this._subscribers.has(type)) this._subscribers.set(type, /* @__PURE__ */ new Set());
52
+ this._subscribers.get(type).add(handler);
53
+ return () => {
54
+ this._subscribers.get(type)?.delete(handler);
55
+ };
56
+ }
57
+ _handleMessage(event) {
58
+ const payload = event.data;
59
+ if (!payload || typeof payload !== "object") return;
60
+ const { type, data, senderId: msgSenderId, messageId } = payload;
61
+ if (!type || typeof type !== "string") return;
62
+ if (msgSenderId === this.senderId) return;
63
+ if (messageId) {
64
+ if (this._seenMessageIds.has(messageId)) return;
65
+ this._seenMessageIds.add(messageId);
66
+ if (this._seenMessageIds.size > 200) this._seenMessageIds.clear();
67
+ }
68
+ const { allowedOrigins } = this._config;
69
+ if (!(!allowedOrigins || allowedOrigins.length === 0 || allowedOrigins.includes("*") || allowedOrigins.filter((url) => Boolean(url) && url !== "").some((url) => compareUrls(url, event.origin)))) return;
70
+ const handlers = this._subscribers.get(type);
71
+ if (handlers) for (const handler of handlers) handler(data, msgSenderId);
72
+ }
73
+ };
74
+
75
+ //#endregion
76
+ export { CrossFrameMessenger };
2
77
  //# sourceMappingURL=CrossFrameMessenger.mjs.map