@intlayer/editor 8.7.6-canary.0 → 8.7.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/cjs/components/ContentSelector.cjs +85 -75
  2. package/dist/cjs/components/ContentSelector.cjs.map +1 -1
  3. package/dist/cjs/components/ContentSelectorWrapper.cjs +131 -95
  4. package/dist/cjs/components/ContentSelectorWrapper.cjs.map +1 -1
  5. package/dist/cjs/components/EditedContent.cjs +74 -49
  6. package/dist/cjs/components/EditedContent.cjs.map +1 -1
  7. package/dist/cjs/components/IntlayerEditor.cjs +34 -27
  8. package/dist/cjs/components/IntlayerEditor.cjs.map +1 -1
  9. package/dist/cjs/core/CrossFrameMessenger.cjs +6 -3
  10. package/dist/cjs/core/CrossFrameMessenger.cjs.map +1 -1
  11. package/dist/cjs/core/CrossFrameStateManager.cjs +5 -1
  12. package/dist/cjs/core/CrossFrameStateManager.cjs.map +1 -1
  13. package/dist/cjs/core/EditorStateManager.cjs +14 -3
  14. package/dist/cjs/core/EditorStateManager.cjs.map +1 -1
  15. package/dist/cjs/core/IframeClickInterceptor.cjs +3 -2
  16. package/dist/cjs/core/IframeClickInterceptor.cjs.map +1 -1
  17. package/dist/cjs/core/UrlStateManager.cjs +4 -3
  18. package/dist/cjs/core/UrlStateManager.cjs.map +1 -1
  19. package/dist/cjs/core/globalManager.cjs.map +1 -1
  20. package/dist/cjs/core/initEditorClient.cjs.map +1 -1
  21. package/dist/esm/components/ContentSelector.mjs +85 -74
  22. package/dist/esm/components/ContentSelector.mjs.map +1 -1
  23. package/dist/esm/components/ContentSelectorWrapper.mjs +131 -95
  24. package/dist/esm/components/ContentSelectorWrapper.mjs.map +1 -1
  25. package/dist/esm/components/EditedContent.mjs +74 -49
  26. package/dist/esm/components/EditedContent.mjs.map +1 -1
  27. package/dist/esm/components/IntlayerEditor.mjs +34 -26
  28. package/dist/esm/components/IntlayerEditor.mjs.map +1 -1
  29. package/dist/esm/core/CrossFrameMessenger.mjs +6 -3
  30. package/dist/esm/core/CrossFrameMessenger.mjs.map +1 -1
  31. package/dist/esm/core/CrossFrameStateManager.mjs +5 -1
  32. package/dist/esm/core/CrossFrameStateManager.mjs.map +1 -1
  33. package/dist/esm/core/EditorStateManager.mjs +14 -3
  34. package/dist/esm/core/EditorStateManager.mjs.map +1 -1
  35. package/dist/esm/core/IframeClickInterceptor.mjs +3 -2
  36. package/dist/esm/core/IframeClickInterceptor.mjs.map +1 -1
  37. package/dist/esm/core/UrlStateManager.mjs +4 -3
  38. package/dist/esm/core/UrlStateManager.mjs.map +1 -1
  39. package/dist/esm/core/globalManager.mjs.map +1 -1
  40. package/dist/esm/core/initEditorClient.mjs.map +1 -1
  41. package/dist/types/components/ContentSelector.d.ts +15 -10
  42. package/dist/types/components/ContentSelector.d.ts.map +1 -1
  43. package/dist/types/components/ContentSelectorWrapper.d.ts +22 -12
  44. package/dist/types/components/ContentSelectorWrapper.d.ts.map +1 -1
  45. package/dist/types/components/EditedContent.d.ts +21 -10
  46. package/dist/types/components/EditedContent.d.ts.map +1 -1
  47. package/dist/types/components/IntlayerEditor.d.ts +16 -10
  48. package/dist/types/components/IntlayerEditor.d.ts.map +1 -1
  49. package/package.json +7 -8
  50. package/dist/cjs/_virtual/_@oxc-project_runtime@0.126.0/helpers/decorate.cjs +0 -11
  51. package/dist/esm/_virtual/_@oxc-project_runtime@0.126.0/helpers/decorate.mjs +0 -10
@@ -1,22 +1,38 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
- const require_decorate = require('../_virtual/_@oxc-project_runtime@0.126.0/helpers/decorate.cjs');
4
2
  const require_components_ContentSelectorWrapper = require('./ContentSelectorWrapper.cjs');
5
3
  const require_components_EditedContent = require('./EditedContent.cjs');
6
4
  const require_components_IntlayerEditor = require('./IntlayerEditor.cjs');
7
- let lit = require("lit");
8
- let lit_decorators_js = require("lit/decorators.js");
9
5
 
10
6
  //#region src/components/ContentSelector.ts
11
7
  const DEFAULT_PRESS_DURATION = 250;
8
+ const STYLES = `
9
+ :host {
10
+ display: contents;
11
+ }
12
+
13
+ .wrapper {
14
+ display: inline-block;
15
+ cursor: pointer;
16
+ user-select: none;
17
+ border-radius: 0.375rem;
18
+ outline-width: 2px;
19
+ outline-offset: 4px;
20
+ outline-style: solid;
21
+ outline-color: transparent;
22
+ transition: all 100ms 50ms ease-in-out;
23
+ }
24
+
25
+ .wrapper[data-active] {
26
+ outline-color: inherit;
27
+ }
28
+ `;
29
+ const _HTMLElement = typeof HTMLElement !== "undefined" ? HTMLElement : class {};
12
30
  /**
13
31
  * <intlayer-content-selector>
14
32
  *
15
33
  * A framework-agnostic web component that wraps content with Intlayer editor
16
34
  * selection UI (hover outline, long-press to select, click-outside to deselect).
17
35
  *
18
- * Replaces the per-framework ContentSelector components (React, Svelte, Vue, Solid).
19
- *
20
36
  * @fires intlayer:press - Fired after a long press (pressDuration ms). Bubbles.
21
37
  * @fires intlayer:hover - Fired on mouseenter. Bubbles.
22
38
  * @fires intlayer:unhover - Fired on mouseleave / mouseup. Bubbles.
@@ -25,57 +41,80 @@ const DEFAULT_PRESS_DURATION = 250;
25
41
  * @prop {boolean} isSelecting - Whether this element is currently selected (external state)
26
42
  * @prop {number} pressDuration - Long-press threshold in ms. Default: 250
27
43
  */
28
- var IntlayerContentSelectorElement = class extends lit.LitElement {
29
- constructor(..._args) {
30
- super(..._args);
31
- this.isSelecting = false;
32
- this.pressDuration = DEFAULT_PRESS_DURATION;
33
- this._isHovered = false;
34
- this._isSelectingState = false;
35
- this._pressTimer = null;
36
- this._clickOutsideHandler = null;
37
- }
38
- static {
39
- this.styles = lit.css`
40
- :host {
41
- display: contents;
42
- }
43
-
44
- .wrapper {
45
- display: inline-block;
46
- cursor: pointer;
47
- user-select: none;
48
- border-radius: 0.375rem;
49
- outline-width: 2px;
50
- outline-offset: 4px;
51
- outline-style: solid;
52
- outline-color: transparent;
53
- transition: all 100ms 50ms ease-in-out;
54
- }
55
-
56
- .wrapper[data-active] {
57
- outline-color: inherit;
58
- }
59
- `;
44
+ var IntlayerContentSelectorElement = class extends _HTMLElement {
45
+ _isSelecting = false;
46
+ _pressDuration = DEFAULT_PRESS_DURATION;
47
+ _isHovered = false;
48
+ _isSelectingState = false;
49
+ _wrapper;
50
+ _pressTimer = null;
51
+ _clickOutsideHandler = null;
52
+ static get observedAttributes() {
53
+ return ["is-selecting", "press-duration"];
54
+ }
55
+ get isSelecting() {
56
+ return this._isSelecting;
57
+ }
58
+ set isSelecting(v) {
59
+ this._isSelecting = v;
60
+ this._updateActiveState();
61
+ }
62
+ get pressDuration() {
63
+ return this._pressDuration;
64
+ }
65
+ set pressDuration(v) {
66
+ this._pressDuration = v;
67
+ }
68
+ constructor() {
69
+ super();
70
+ const shadow = this.attachShadow({ mode: "open" });
71
+ const style = document.createElement("style");
72
+ style.textContent = STYLES;
73
+ shadow.appendChild(style);
74
+ const wrapper = document.createElement("span");
75
+ wrapper.className = "wrapper";
76
+ wrapper.setAttribute("role", "button");
77
+ wrapper.setAttribute("tabindex", "0");
78
+ wrapper.appendChild(document.createElement("slot"));
79
+ shadow.appendChild(wrapper);
80
+ this._wrapper = wrapper;
81
+ wrapper.addEventListener("mousedown", () => this._handleMouseDown());
82
+ wrapper.addEventListener("mouseup", () => this._handleMouseUpOrLeave());
83
+ wrapper.addEventListener("mouseleave", () => this._handleMouseUpOrLeave());
84
+ wrapper.addEventListener("mouseenter", () => this._handleMouseEnter());
85
+ wrapper.addEventListener("click", (e) => this._handleClick(e));
86
+ wrapper.addEventListener("touchstart", () => this._handleMouseDown());
87
+ wrapper.addEventListener("touchend", () => this._handleMouseUpOrLeave());
88
+ wrapper.addEventListener("touchcancel", () => this._handleMouseUpOrLeave());
89
+ wrapper.addEventListener("blur", () => this._handleBlur());
90
+ }
91
+ attributeChangedCallback(name, _oldVal, newVal) {
92
+ if (name === "is-selecting") {
93
+ this._isSelecting = newVal !== null;
94
+ this._updateActiveState();
95
+ } else if (name === "press-duration") this._pressDuration = newVal !== null ? parseInt(newVal, 10) : DEFAULT_PRESS_DURATION;
60
96
  }
61
97
  connectedCallback() {
62
- super.connectedCallback();
63
98
  this._clickOutsideHandler = (e) => {
64
99
  if (!e.composedPath().includes(this)) {
65
100
  this._isSelectingState = false;
66
101
  this._dispatch("intlayer:click-outside");
102
+ this._updateActiveState();
67
103
  }
68
104
  };
69
105
  document.addEventListener("mousedown", this._clickOutsideHandler);
70
106
  }
71
107
  disconnectedCallback() {
72
- super.disconnectedCallback();
73
108
  if (this._clickOutsideHandler) {
74
109
  document.removeEventListener("mousedown", this._clickOutsideHandler);
75
110
  this._clickOutsideHandler = null;
76
111
  }
77
112
  this._clearPressTimer();
78
113
  }
114
+ _updateActiveState() {
115
+ if (this._isSelecting || this._isSelectingState || this._isHovered) this._wrapper.setAttribute("data-active", "");
116
+ else this._wrapper.removeAttribute("data-active");
117
+ }
79
118
  _clearPressTimer() {
80
119
  if (this._pressTimer !== null) {
81
120
  clearTimeout(this._pressTimer);
@@ -92,11 +131,13 @@ var IntlayerContentSelectorElement = class extends lit.LitElement {
92
131
  this._clearPressTimer();
93
132
  this._pressTimer = setTimeout(() => {
94
133
  this._isSelectingState = true;
134
+ this._updateActiveState();
95
135
  this._dispatch("intlayer:press");
96
- }, this.pressDuration);
136
+ }, this._pressDuration);
97
137
  }
98
138
  _handleMouseEnter() {
99
139
  this._isHovered = true;
140
+ this._updateActiveState();
100
141
  this._dispatch("intlayer:hover");
101
142
  }
102
143
  _handleMouseUpOrLeave() {
@@ -105,50 +146,19 @@ var IntlayerContentSelectorElement = class extends lit.LitElement {
105
146
  this._dispatch("intlayer:unhover");
106
147
  }
107
148
  this._clearPressTimer();
149
+ this._updateActiveState();
108
150
  }
109
151
  _handleClick(e) {
110
- if (this.isSelecting || this._isSelectingState) {
152
+ if (this._isSelecting || this._isSelectingState) {
111
153
  e.preventDefault();
112
154
  e.stopPropagation();
113
155
  }
114
156
  }
115
157
  _handleBlur() {
116
158
  this._isSelectingState = false;
117
- }
118
- render() {
119
- return lit.html`
120
- <span
121
- class="wrapper"
122
- ?data-active=${this.isSelecting || this._isSelectingState || this._isHovered}
123
- role="button"
124
- tabindex="0"
125
- @mousedown=${this._handleMouseDown}
126
- @mouseup=${this._handleMouseUpOrLeave}
127
- @mouseleave=${this._handleMouseUpOrLeave}
128
- @mouseenter=${this._handleMouseEnter}
129
- @click=${this._handleClick}
130
- @touchstart=${this._handleMouseDown}
131
- @touchend=${this._handleMouseUpOrLeave}
132
- @touchcancel=${this._handleMouseUpOrLeave}
133
- @blur=${this._handleBlur}
134
- @keyup=${() => {}}
135
- >
136
- <slot></slot>
137
- </span>
138
- `;
159
+ this._updateActiveState();
139
160
  }
140
161
  };
141
- require_decorate.__decorate([(0, lit_decorators_js.property)({
142
- type: Boolean,
143
- attribute: "is-selecting"
144
- })], IntlayerContentSelectorElement.prototype, "isSelecting", void 0);
145
- require_decorate.__decorate([(0, lit_decorators_js.property)({
146
- type: Number,
147
- attribute: "press-duration"
148
- })], IntlayerContentSelectorElement.prototype, "pressDuration", void 0);
149
- require_decorate.__decorate([(0, lit_decorators_js.state)()], IntlayerContentSelectorElement.prototype, "_isHovered", void 0);
150
- require_decorate.__decorate([(0, lit_decorators_js.state)()], IntlayerContentSelectorElement.prototype, "_isSelectingState", void 0);
151
- require_decorate.__decorate([(0, lit_decorators_js.query)(".wrapper")], IntlayerContentSelectorElement.prototype, "_wrapper", void 0);
152
162
  /**
153
163
  * Register all Intlayer custom elements.
154
164
  * Call this once at application startup (inside IntlayerEditorProvider or similar).
@@ -1 +1 @@
1
- {"version":3,"file":"ContentSelector.cjs","names":["LitElement"],"sources":["../../../src/components/ContentSelector.ts"],"sourcesContent":["import { css, html, LitElement } from 'lit';\nimport { property, query, state } from 'lit/decorators.js';\nimport { defineIntlayerContentSelectorWrapper } from './ContentSelectorWrapper';\nimport { defineIntlayerEditedContent } from './EditedContent';\nimport { defineIntlayerEditorElement } from './IntlayerEditor';\n\nconst DEFAULT_PRESS_DURATION = 250;\n\n/**\n * <intlayer-content-selector>\n *\n * A framework-agnostic web component that wraps content with Intlayer editor\n * selection UI (hover outline, long-press to select, click-outside to deselect).\n *\n * Replaces the per-framework ContentSelector components (React, Svelte, Vue, Solid).\n *\n * @fires intlayer:press - Fired after a long press (pressDuration ms). Bubbles.\n * @fires intlayer:hover - Fired on mouseenter. Bubbles.\n * @fires intlayer:unhover - Fired on mouseleave / mouseup. Bubbles.\n * @fires intlayer:click-outside - Fired when a click occurs outside the element. Bubbles.\n *\n * @prop {boolean} isSelecting - Whether this element is currently selected (external state)\n * @prop {number} pressDuration - Long-press threshold in ms. Default: 250\n */\nexport class IntlayerContentSelectorElement extends LitElement {\n static styles = css`\n :host {\n display: contents;\n }\n\n .wrapper {\n display: inline-block;\n cursor: pointer;\n user-select: none;\n border-radius: 0.375rem;\n outline-width: 2px;\n outline-offset: 4px;\n outline-style: solid;\n outline-color: transparent;\n transition: all 100ms 50ms ease-in-out;\n }\n\n .wrapper[data-active] {\n outline-color: inherit;\n }\n `;\n\n @property({ type: Boolean, attribute: 'is-selecting' })\n isSelecting = false;\n\n @property({ type: Number, attribute: 'press-duration' })\n pressDuration = DEFAULT_PRESS_DURATION;\n\n @state() private _isHovered = false;\n @state() private _isSelectingState = false;\n\n @query('.wrapper') private _wrapper!: HTMLSpanElement;\n\n private _pressTimer: ReturnType<typeof setTimeout> | null = null;\n private _clickOutsideHandler: ((e: MouseEvent) => void) | null = null;\n\n connectedCallback(): void {\n super.connectedCallback();\n this._clickOutsideHandler = (e: MouseEvent) => {\n // composedPath() pierces shadow boundaries\n if (!e.composedPath().includes(this)) {\n this._isSelectingState = false;\n this._dispatch('intlayer:click-outside');\n }\n };\n document.addEventListener('mousedown', this._clickOutsideHandler);\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n if (this._clickOutsideHandler) {\n document.removeEventListener('mousedown', this._clickOutsideHandler);\n this._clickOutsideHandler = null;\n }\n this._clearPressTimer();\n }\n\n private _clearPressTimer(): void {\n if (this._pressTimer !== null) {\n clearTimeout(this._pressTimer);\n this._pressTimer = null;\n }\n }\n\n private _dispatch(eventName: string): void {\n this.dispatchEvent(\n new CustomEvent(eventName, { bubbles: true, composed: true })\n );\n }\n\n private _handleMouseDown(): void {\n this._clearPressTimer();\n this._pressTimer = setTimeout(() => {\n this._isSelectingState = true;\n this._dispatch('intlayer:press');\n }, this.pressDuration);\n }\n\n private _handleMouseEnter(): void {\n this._isHovered = true;\n this._dispatch('intlayer:hover');\n }\n\n private _handleMouseUpOrLeave(): void {\n if (this._isHovered) {\n this._isHovered = false;\n this._dispatch('intlayer:unhover');\n }\n this._clearPressTimer();\n }\n\n private _handleClick(e: MouseEvent): void {\n if (this.isSelecting || this._isSelectingState) {\n e.preventDefault();\n e.stopPropagation();\n }\n }\n\n private _handleBlur(): void {\n this._isSelectingState = false;\n }\n\n render() {\n const isActive =\n this.isSelecting || this._isSelectingState || this._isHovered;\n return html`\n <span\n class=\"wrapper\"\n ?data-active=${isActive}\n role=\"button\"\n tabindex=\"0\"\n @mousedown=${this._handleMouseDown}\n @mouseup=${this._handleMouseUpOrLeave}\n @mouseleave=${this._handleMouseUpOrLeave}\n @mouseenter=${this._handleMouseEnter}\n @click=${this._handleClick}\n @touchstart=${this._handleMouseDown}\n @touchend=${this._handleMouseUpOrLeave}\n @touchcancel=${this._handleMouseUpOrLeave}\n @blur=${this._handleBlur}\n @keyup=${() => {}}\n >\n <slot></slot>\n </span>\n `;\n }\n}\n\n/**\n * Register all Intlayer custom elements.\n * Call this once at application startup (inside IntlayerEditorProvider or similar).\n * Safe to call multiple times — only registers elements that are not yet defined.\n */\nexport const defineIntlayerElements = (): void => {\n if (typeof customElements === 'undefined') return;\n if (!customElements.get('intlayer-content-selector')) {\n customElements.define(\n 'intlayer-content-selector',\n IntlayerContentSelectorElement\n );\n }\n defineIntlayerContentSelectorWrapper();\n defineIntlayerEditedContent();\n defineIntlayerEditorElement();\n};\n"],"mappings":";;;;;;;;;;AAMA,MAAM,yBAAyB;;;;;;;;;;;;;;;;;AAkB/B,IAAa,iCAAb,cAAoDA,eAAW;;;qBAwB/C;uBAGE;oBAEc;2BACO;qBAIuB;8BACK;;;gBAlCjD,OAAG;;;;;;;;;;;;;;;;;;;;;;CAoCnB,oBAA0B;AACxB,QAAM,mBAAmB;AACzB,OAAK,wBAAwB,MAAkB;AAE7C,OAAI,CAAC,EAAE,cAAc,CAAC,SAAS,KAAK,EAAE;AACpC,SAAK,oBAAoB;AACzB,SAAK,UAAU,yBAAyB;;;AAG5C,WAAS,iBAAiB,aAAa,KAAK,qBAAqB;;CAGnE,uBAA6B;AAC3B,QAAM,sBAAsB;AAC5B,MAAI,KAAK,sBAAsB;AAC7B,YAAS,oBAAoB,aAAa,KAAK,qBAAqB;AACpE,QAAK,uBAAuB;;AAE9B,OAAK,kBAAkB;;CAGzB,AAAQ,mBAAyB;AAC/B,MAAI,KAAK,gBAAgB,MAAM;AAC7B,gBAAa,KAAK,YAAY;AAC9B,QAAK,cAAc;;;CAIvB,AAAQ,UAAU,WAAyB;AACzC,OAAK,cACH,IAAI,YAAY,WAAW;GAAE,SAAS;GAAM,UAAU;GAAM,CAAC,CAC9D;;CAGH,AAAQ,mBAAyB;AAC/B,OAAK,kBAAkB;AACvB,OAAK,cAAc,iBAAiB;AAClC,QAAK,oBAAoB;AACzB,QAAK,UAAU,iBAAiB;KAC/B,KAAK,cAAc;;CAGxB,AAAQ,oBAA0B;AAChC,OAAK,aAAa;AAClB,OAAK,UAAU,iBAAiB;;CAGlC,AAAQ,wBAA8B;AACpC,MAAI,KAAK,YAAY;AACnB,QAAK,aAAa;AAClB,QAAK,UAAU,mBAAmB;;AAEpC,OAAK,kBAAkB;;CAGzB,AAAQ,aAAa,GAAqB;AACxC,MAAI,KAAK,eAAe,KAAK,mBAAmB;AAC9C,KAAE,gBAAgB;AAClB,KAAE,iBAAiB;;;CAIvB,AAAQ,cAAoB;AAC1B,OAAK,oBAAoB;;CAG3B,SAAS;AAGP,SAAO,QAAI;;;uBADT,KAAK,eAAe,KAAK,qBAAqB,KAAK,WAIzB;;;qBAGX,KAAK,iBAAiB;mBACxB,KAAK,sBAAsB;sBACxB,KAAK,sBAAsB;sBAC3B,KAAK,kBAAkB;iBAC5B,KAAK,aAAa;sBACb,KAAK,iBAAiB;oBACxB,KAAK,sBAAsB;uBACxB,KAAK,sBAAsB;gBAClC,KAAK,YAAY;uBACV,GAAG;;;;;;;6DAlGd;CAAE,MAAM;CAAS,WAAW;CAAgB,CAAC;6DAG7C;CAAE,MAAM;CAAQ,WAAW;CAAkB,CAAC;2DAGhD;2DACA;0DAED,WAAW;;;;;;AAsGpB,MAAa,+BAAqC;AAChD,KAAI,OAAO,mBAAmB,YAAa;AAC3C,KAAI,CAAC,eAAe,IAAI,4BAA4B,CAClD,gBAAe,OACb,6BACA,+BACD;AAEH,iFAAsC;AACtC,+DAA6B;AAC7B,gEAA6B"}
1
+ {"version":3,"file":"ContentSelector.cjs","names":[],"sources":["../../../src/components/ContentSelector.ts"],"sourcesContent":["import { defineIntlayerContentSelectorWrapper } from './ContentSelectorWrapper';\nimport { defineIntlayerEditedContent } from './EditedContent';\nimport { defineIntlayerEditorElement } from './IntlayerEditor';\n\nconst DEFAULT_PRESS_DURATION = 250;\n\nconst STYLES = `\n :host {\n display: contents;\n }\n\n .wrapper {\n display: inline-block;\n cursor: pointer;\n user-select: none;\n border-radius: 0.375rem;\n outline-width: 2px;\n outline-offset: 4px;\n outline-style: solid;\n outline-color: transparent;\n transition: all 100ms 50ms ease-in-out;\n }\n\n .wrapper[data-active] {\n outline-color: inherit;\n }\n`;\n\nconst _HTMLElement =\n typeof HTMLElement !== 'undefined'\n ? HTMLElement\n : (class {} as unknown as typeof HTMLElement);\n\n/**\n * <intlayer-content-selector>\n *\n * A framework-agnostic web component that wraps content with Intlayer editor\n * selection UI (hover outline, long-press to select, click-outside to deselect).\n *\n * @fires intlayer:press - Fired after a long press (pressDuration ms). Bubbles.\n * @fires intlayer:hover - Fired on mouseenter. Bubbles.\n * @fires intlayer:unhover - Fired on mouseleave / mouseup. Bubbles.\n * @fires intlayer:click-outside - Fired when a click occurs outside the element. Bubbles.\n *\n * @prop {boolean} isSelecting - Whether this element is currently selected (external state)\n * @prop {number} pressDuration - Long-press threshold in ms. Default: 250\n */\nexport class IntlayerContentSelectorElement extends _HTMLElement {\n private _isSelecting = false;\n private _pressDuration = DEFAULT_PRESS_DURATION;\n private _isHovered = false;\n private _isSelectingState = false;\n private _wrapper: HTMLSpanElement;\n private _pressTimer: ReturnType<typeof setTimeout> | null = null;\n private _clickOutsideHandler: ((e: MouseEvent) => void) | null = null;\n\n static get observedAttributes(): string[] {\n return ['is-selecting', 'press-duration'];\n }\n\n get isSelecting(): boolean {\n return this._isSelecting;\n }\n set isSelecting(v: boolean) {\n this._isSelecting = v;\n this._updateActiveState();\n }\n\n get pressDuration(): number {\n return this._pressDuration;\n }\n set pressDuration(v: number) {\n this._pressDuration = v;\n }\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = STYLES;\n shadow.appendChild(style);\n\n const wrapper = document.createElement('span');\n wrapper.className = 'wrapper';\n wrapper.setAttribute('role', 'button');\n wrapper.setAttribute('tabindex', '0');\n wrapper.appendChild(document.createElement('slot'));\n shadow.appendChild(wrapper);\n this._wrapper = wrapper;\n\n wrapper.addEventListener('mousedown', () => this._handleMouseDown());\n wrapper.addEventListener('mouseup', () => this._handleMouseUpOrLeave());\n wrapper.addEventListener('mouseleave', () => this._handleMouseUpOrLeave());\n wrapper.addEventListener('mouseenter', () => this._handleMouseEnter());\n wrapper.addEventListener('click', (e) => this._handleClick(e));\n wrapper.addEventListener('touchstart', () => this._handleMouseDown());\n wrapper.addEventListener('touchend', () => this._handleMouseUpOrLeave());\n wrapper.addEventListener('touchcancel', () => this._handleMouseUpOrLeave());\n wrapper.addEventListener('blur', () => this._handleBlur());\n }\n\n attributeChangedCallback(\n name: string,\n _oldVal: string | null,\n newVal: string | null\n ): void {\n if (name === 'is-selecting') {\n this._isSelecting = newVal !== null;\n this._updateActiveState();\n } else if (name === 'press-duration') {\n this._pressDuration =\n newVal !== null ? parseInt(newVal, 10) : DEFAULT_PRESS_DURATION;\n }\n }\n\n connectedCallback(): void {\n this._clickOutsideHandler = (e: MouseEvent) => {\n // composedPath() pierces shadow boundaries\n if (!e.composedPath().includes(this)) {\n this._isSelectingState = false;\n this._dispatch('intlayer:click-outside');\n this._updateActiveState();\n }\n };\n document.addEventListener('mousedown', this._clickOutsideHandler);\n }\n\n disconnectedCallback(): void {\n if (this._clickOutsideHandler) {\n document.removeEventListener('mousedown', this._clickOutsideHandler);\n this._clickOutsideHandler = null;\n }\n this._clearPressTimer();\n }\n\n private _updateActiveState(): void {\n const isActive =\n this._isSelecting || this._isSelectingState || this._isHovered;\n if (isActive) {\n this._wrapper.setAttribute('data-active', '');\n } else {\n this._wrapper.removeAttribute('data-active');\n }\n }\n\n private _clearPressTimer(): void {\n if (this._pressTimer !== null) {\n clearTimeout(this._pressTimer);\n this._pressTimer = null;\n }\n }\n\n private _dispatch(eventName: string): void {\n this.dispatchEvent(\n new CustomEvent(eventName, { bubbles: true, composed: true })\n );\n }\n\n private _handleMouseDown(): void {\n this._clearPressTimer();\n this._pressTimer = setTimeout(() => {\n this._isSelectingState = true;\n this._updateActiveState();\n this._dispatch('intlayer:press');\n }, this._pressDuration);\n }\n\n private _handleMouseEnter(): void {\n this._isHovered = true;\n this._updateActiveState();\n this._dispatch('intlayer:hover');\n }\n\n private _handleMouseUpOrLeave(): void {\n if (this._isHovered) {\n this._isHovered = false;\n this._dispatch('intlayer:unhover');\n }\n this._clearPressTimer();\n this._updateActiveState();\n }\n\n private _handleClick(e: MouseEvent): void {\n if (this._isSelecting || this._isSelectingState) {\n e.preventDefault();\n e.stopPropagation();\n }\n }\n\n private _handleBlur(): void {\n this._isSelectingState = false;\n this._updateActiveState();\n }\n}\n\n/**\n * Register all Intlayer custom elements.\n * Call this once at application startup (inside IntlayerEditorProvider or similar).\n * Safe to call multiple times — only registers elements that are not yet defined.\n */\nexport const defineIntlayerElements = (): void => {\n if (typeof customElements === 'undefined') return;\n if (!customElements.get('intlayer-content-selector')) {\n customElements.define(\n 'intlayer-content-selector',\n IntlayerContentSelectorElement\n );\n }\n defineIntlayerContentSelectorWrapper();\n defineIntlayerEditedContent();\n defineIntlayerEditorElement();\n};\n"],"mappings":"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"}
@@ -2,18 +2,16 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
3
  const require_messageKey = require('../messageKey.cjs');
4
4
  const require_core_globalManager = require('../core/globalManager.cjs');
5
- const require_decorate = require('../_virtual/_@oxc-project_runtime@0.126.0/helpers/decorate.cjs');
6
- let lit = require("lit");
7
- let lit_decorators_js = require("lit/decorators.js");
8
5
  let _intlayer_core_utils = require("@intlayer/core/utils");
9
6
  let _intlayer_types_nodeType = require("@intlayer/types/nodeType");
10
7
  _intlayer_types_nodeType = require_runtime.__toESM(_intlayer_types_nodeType);
11
8
 
12
9
  //#region src/components/ContentSelectorWrapper.ts
10
+ const _HTMLElement = typeof HTMLElement !== "undefined" ? HTMLElement : class {};
13
11
  /**
14
12
  * <intlayer-content-selector-wrapper>
15
13
  *
16
- * Framework-agnostic Lit element that wraps content with the Intlayer editor
14
+ * Framework-agnostic web component that wraps content with the Intlayer editor
17
15
  * selection UI. It replaces the per-framework ContentSelectorWrapper components
18
16
  * (Vue, Svelte, Solid, Preact).
19
17
  *
@@ -24,42 +22,64 @@ _intlayer_types_nodeType = require_runtime.__toESM(_intlayer_types_nodeType);
24
22
  * @attr {string} key-path - JSON-serialized KeyPath[] for this content node
25
23
  * @attr {string} dictionary-key - The dictionary key owning this content node
26
24
  */
27
- var IntlayerContentSelectorWrapperElement = class extends lit.LitElement {
28
- constructor(..._args) {
29
- super(..._args);
30
- this.keyPathJson = "[]";
31
- this.dictionaryKey = "";
32
- this._editorEnabled = false;
33
- this._isInIframe = false;
34
- this._isSelected = false;
35
- this._editedValue = void 0;
36
- this._unsubManager = null;
37
- this._unsubEnabled = null;
38
- this._unsubFocused = null;
39
- this._unsubEditedContent = null;
25
+ var IntlayerContentSelectorWrapperElement = class extends _HTMLElement {
26
+ _keyPathJson = "[]";
27
+ _dictionaryKey = "";
28
+ _editorEnabled = false;
29
+ _isInIframe = false;
30
+ _isSelected = false;
31
+ _editedValue = void 0;
32
+ _renderState = null;
33
+ _selector = null;
34
+ _unsubManager = null;
35
+ _unsubEnabled = null;
36
+ _unsubFocused = null;
37
+ _unsubEditedContent = null;
38
+ static get observedAttributes() {
39
+ return ["key-path", "dictionary-key"];
40
+ }
41
+ get keyPathJson() {
42
+ return this._keyPathJson;
43
+ }
44
+ set keyPathJson(v) {
45
+ this._keyPathJson = v;
46
+ const manager = require_core_globalManager.getGlobalEditorManager();
47
+ if (manager) this._updateEditedValue(manager);
48
+ }
49
+ get dictionaryKey() {
50
+ return this._dictionaryKey;
40
51
  }
41
- static {
42
- this.styles = lit.css`
43
- :host {
44
- display: contents;
45
- }
46
- `;
52
+ set dictionaryKey(v) {
53
+ this._dictionaryKey = v;
54
+ const manager = require_core_globalManager.getGlobalEditorManager();
55
+ if (manager) this._updateEditedValue(manager);
56
+ }
57
+ constructor() {
58
+ super();
59
+ const shadow = this.attachShadow({ mode: "open" });
60
+ const style = document.createElement("style");
61
+ style.textContent = ":host { display: contents; }";
62
+ shadow.appendChild(style);
63
+ }
64
+ attributeChangedCallback(name, _oldVal, newVal) {
65
+ if (name === "key-path") {
66
+ this._keyPathJson = newVal ?? "[]";
67
+ const manager = require_core_globalManager.getGlobalEditorManager();
68
+ if (manager) this._updateEditedValue(manager);
69
+ } else if (name === "dictionary-key") {
70
+ this._dictionaryKey = newVal ?? "";
71
+ const manager = require_core_globalManager.getGlobalEditorManager();
72
+ if (manager) this._updateEditedValue(manager);
73
+ }
47
74
  }
48
75
  connectedCallback() {
49
- super.connectedCallback();
50
76
  if (typeof window !== "undefined") this._isInIframe = window.self !== window.top;
51
77
  this._subscribeToManager();
78
+ this._render();
52
79
  }
53
80
  disconnectedCallback() {
54
- super.disconnectedCallback();
55
81
  this._teardown();
56
82
  }
57
- updated(changedProperties) {
58
- if (changedProperties.has("keyPathJson") || changedProperties.has("dictionaryKey")) {
59
- const manager = require_core_globalManager.getGlobalEditorManager();
60
- if (manager) this._updateEditedValue(manager);
61
- }
62
- }
63
83
  _teardown() {
64
84
  this._unsubManager?.();
65
85
  this._unsubEnabled?.();
@@ -70,6 +90,53 @@ var IntlayerContentSelectorWrapperElement = class extends lit.LitElement {
70
90
  this._unsubFocused = null;
71
91
  this._unsubEditedContent = null;
72
92
  }
93
+ _getRawKeyPath() {
94
+ try {
95
+ return JSON.parse(this._keyPathJson);
96
+ } catch {
97
+ return [];
98
+ }
99
+ }
100
+ _getFilteredKeyPath() {
101
+ return this._getRawKeyPath().filter((k) => k.type !== _intlayer_types_nodeType.TRANSLATION);
102
+ }
103
+ _updateEditedValue(manager) {
104
+ const filteredKeyPath = this._getFilteredKeyPath();
105
+ if (!this._dictionaryKey || filteredKeyPath.length === 0) {
106
+ this._editedValue = void 0;
107
+ this._render();
108
+ return;
109
+ }
110
+ const rawKeyPath = this._getRawKeyPath();
111
+ const lastStepType = rawKeyPath[rawKeyPath.length - 1]?.type;
112
+ if (lastStepType === _intlayer_types_nodeType.MARKDOWN || lastStepType === _intlayer_types_nodeType.HTML || lastStepType === _intlayer_types_nodeType.INSERTION || lastStepType === _intlayer_types_nodeType.FILE) {
113
+ this._editedValue = void 0;
114
+ this._render();
115
+ return;
116
+ }
117
+ let value = manager.getContentValue(this._dictionaryKey, filteredKeyPath);
118
+ if (value !== null && value !== void 0 && typeof value === "object" && value.nodeType === _intlayer_types_nodeType.TRANSLATION) {
119
+ const locale = manager.currentLocale.value;
120
+ value = locale ? value[_intlayer_types_nodeType.TRANSLATION][locale] : void 0;
121
+ }
122
+ this._editedValue = value;
123
+ this._render();
124
+ }
125
+ _updateIsSelected(focusedContent) {
126
+ if (!focusedContent) {
127
+ this._isSelected = false;
128
+ this._updateSelectorAttr();
129
+ return;
130
+ }
131
+ const keyPath = this._getFilteredKeyPath();
132
+ this._isSelected = focusedContent.dictionaryKey === this._dictionaryKey && (focusedContent.keyPath?.length ?? 0) > 0 && (0, _intlayer_core_utils.isSameKeyPath)(focusedContent.keyPath ?? [], keyPath);
133
+ this._updateSelectorAttr();
134
+ }
135
+ _updateSelectorAttr() {
136
+ if (!this._selector) return;
137
+ if (this._isSelected) this._selector.setAttribute("is-selecting", "");
138
+ else this._selector.removeAttribute("is-selecting");
139
+ }
73
140
  _subscribeToManager() {
74
141
  const manager = require_core_globalManager.getGlobalEditorManager();
75
142
  if (manager) this._setupManagerSubscriptions(manager);
@@ -85,6 +152,7 @@ var IntlayerContentSelectorWrapperElement = class extends lit.LitElement {
85
152
  this._editorEnabled = false;
86
153
  this._isSelected = false;
87
154
  this._editedValue = void 0;
155
+ this._render();
88
156
  }
89
157
  });
90
158
  }
@@ -94,6 +162,7 @@ var IntlayerContentSelectorWrapperElement = class extends lit.LitElement {
94
162
  this._updateEditedValue(manager);
95
163
  const handleEnabledChange = (e) => {
96
164
  this._editorEnabled = e.detail;
165
+ this._render();
97
166
  };
98
167
  const handleFocusedChange = (e) => {
99
168
  this._updateIsSelected(e.detail);
@@ -108,56 +177,19 @@ var IntlayerContentSelectorWrapperElement = class extends lit.LitElement {
108
177
  this._unsubFocused = () => manager.focusedContent.removeEventListener("change", handleFocusedChange);
109
178
  this._unsubEditedContent = () => manager.editedContent.removeEventListener("change", handleEditedContentChange);
110
179
  }
111
- _getRawKeyPath() {
112
- try {
113
- return JSON.parse(this.keyPathJson);
114
- } catch {
115
- return [];
116
- }
117
- }
118
- _getFilteredKeyPath() {
119
- return this._getRawKeyPath().filter((k) => k.type !== _intlayer_types_nodeType.TRANSLATION);
120
- }
121
- _updateEditedValue(manager) {
122
- const filteredKeyPath = this._getFilteredKeyPath();
123
- if (!this.dictionaryKey || filteredKeyPath.length === 0) {
124
- this._editedValue = void 0;
125
- return;
126
- }
127
- const rawKeyPath = this._getRawKeyPath();
128
- const lastStepType = rawKeyPath[rawKeyPath.length - 1]?.type;
129
- if (lastStepType === _intlayer_types_nodeType.MARKDOWN || lastStepType === _intlayer_types_nodeType.HTML || lastStepType === _intlayer_types_nodeType.INSERTION || lastStepType === _intlayer_types_nodeType.FILE) {
130
- this._editedValue = void 0;
131
- return;
132
- }
133
- let value = manager.getContentValue(this.dictionaryKey, filteredKeyPath);
134
- if (value !== null && value !== void 0 && typeof value === "object" && value.nodeType === _intlayer_types_nodeType.TRANSLATION) {
135
- const locale = manager.currentLocale.value;
136
- value = locale ? value[_intlayer_types_nodeType.TRANSLATION][locale] : void 0;
137
- }
138
- this._editedValue = value;
139
- }
140
- _updateIsSelected(focusedContent) {
141
- if (!focusedContent) {
142
- this._isSelected = false;
143
- return;
144
- }
145
- const keyPath = this._getFilteredKeyPath();
146
- this._isSelected = focusedContent.dictionaryKey === this.dictionaryKey && (focusedContent.keyPath?.length ?? 0) > 0 && (0, _intlayer_core_utils.isSameKeyPath)(focusedContent.keyPath ?? [], keyPath);
147
- }
148
180
  _handlePress(e) {
149
181
  e.stopPropagation();
150
182
  const manager = require_core_globalManager.getGlobalEditorManager();
151
183
  if (!manager) return;
152
184
  manager.focusedContent.set({
153
- dictionaryKey: this.dictionaryKey,
185
+ dictionaryKey: this._dictionaryKey,
154
186
  keyPath: this._getFilteredKeyPath()
155
187
  });
156
188
  }
157
189
  _handleHover(e) {
158
190
  e.stopPropagation();
159
191
  require_core_globalManager.getGlobalEditorManager()?.messenger.send(`${"INTLAYER_HOVERED_CONTENT_CHANGED"}/post`, {
160
- dictionaryKey: this.dictionaryKey,
192
+ dictionaryKey: this._dictionaryKey,
161
193
  keyPath: this._getFilteredKeyPath()
162
194
  });
163
195
  }
@@ -165,34 +197,38 @@ var IntlayerContentSelectorWrapperElement = class extends lit.LitElement {
165
197
  e.stopPropagation();
166
198
  require_core_globalManager.getGlobalEditorManager()?.messenger.send(`${"INTLAYER_HOVERED_CONTENT_CHANGED"}/post`, null);
167
199
  }
168
- render() {
169
- if (!this._isInIframe || !this._editorEnabled) return lit.html`<slot></slot>`;
200
+ _render() {
201
+ const useWrapper = this._isInIframe && this._editorEnabled;
170
202
  const editedValue = this._editedValue;
171
- const displayedContent = typeof editedValue === "string" || typeof editedValue === "number" || typeof editedValue === "boolean" ? editedValue : lit.html`<slot></slot>`;
172
- return lit.html`
173
- <intlayer-content-selector
174
- ?is-selecting=${this._isSelected}
175
- @intlayer:press=${this._handlePress}
176
- @intlayer:hover=${this._handleHover}
177
- @intlayer:unhover=${this._handleUnhover}
178
- >
179
- ${displayedContent}
180
- </intlayer-content-selector>
181
- `;
203
+ const newState = !useWrapper ? "simple" : typeof editedValue === "string" || typeof editedValue === "number" || typeof editedValue === "boolean" ? "wrapped-text" : "wrapped-slot";
204
+ if (this._renderState !== newState) {
205
+ this._rebuildContent(newState);
206
+ return;
207
+ }
208
+ if (newState !== "simple" && this._selector) {
209
+ this._updateSelectorAttr();
210
+ if (newState === "wrapped-text" && this._selector.firstChild?.nodeType === Node.TEXT_NODE) this._selector.firstChild.data = String(editedValue);
211
+ }
212
+ }
213
+ _rebuildContent(state) {
214
+ const shadow = this.shadowRoot;
215
+ while (shadow.childNodes.length > 1) shadow.removeChild(shadow.lastChild);
216
+ this._selector = null;
217
+ if (state === "simple") shadow.appendChild(document.createElement("slot"));
218
+ else {
219
+ const selector = document.createElement("intlayer-content-selector");
220
+ this._selector = selector;
221
+ if (this._isSelected) selector.setAttribute("is-selecting", "");
222
+ selector.addEventListener("intlayer:press", (e) => this._handlePress(e));
223
+ selector.addEventListener("intlayer:hover", (e) => this._handleHover(e));
224
+ selector.addEventListener("intlayer:unhover", (e) => this._handleUnhover(e));
225
+ if (state === "wrapped-text") selector.appendChild(document.createTextNode(String(this._editedValue)));
226
+ else selector.appendChild(document.createElement("slot"));
227
+ shadow.appendChild(selector);
228
+ }
229
+ this._renderState = state;
182
230
  }
183
231
  };
184
- require_decorate.__decorate([(0, lit_decorators_js.property)({
185
- type: String,
186
- attribute: "key-path"
187
- })], IntlayerContentSelectorWrapperElement.prototype, "keyPathJson", void 0);
188
- require_decorate.__decorate([(0, lit_decorators_js.property)({
189
- type: String,
190
- attribute: "dictionary-key"
191
- })], IntlayerContentSelectorWrapperElement.prototype, "dictionaryKey", void 0);
192
- require_decorate.__decorate([(0, lit_decorators_js.state)()], IntlayerContentSelectorWrapperElement.prototype, "_editorEnabled", void 0);
193
- require_decorate.__decorate([(0, lit_decorators_js.state)()], IntlayerContentSelectorWrapperElement.prototype, "_isInIframe", void 0);
194
- require_decorate.__decorate([(0, lit_decorators_js.state)()], IntlayerContentSelectorWrapperElement.prototype, "_isSelected", void 0);
195
- require_decorate.__decorate([(0, lit_decorators_js.state)()], IntlayerContentSelectorWrapperElement.prototype, "_editedValue", void 0);
196
232
  const defineIntlayerContentSelectorWrapper = () => {
197
233
  if (typeof customElements === "undefined") return;
198
234
  if (!customElements.get("intlayer-content-selector-wrapper")) customElements.define("intlayer-content-selector-wrapper", IntlayerContentSelectorWrapperElement);
@@ -1 +1 @@
1
- {"version":3,"file":"ContentSelectorWrapper.cjs","names":["LitElement","getGlobalEditorManager","onGlobalEditorManagerChange","NodeTypes"],"sources":["../../../src/components/ContentSelectorWrapper.ts"],"sourcesContent":["import { isSameKeyPath } from '@intlayer/core/utils';\nimport type { ContentNode } from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport type { TypedNodeModel } from '@intlayer/types/nodeType';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { css, html, LitElement } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport type {\n EditorStateManager,\n FileContent,\n} from '../core/EditorStateManager';\nimport {\n getGlobalEditorManager,\n onGlobalEditorManagerChange,\n} from '../core/globalManager';\nimport { MessageKey } from '../messageKey';\n\n/**\n * <intlayer-content-selector-wrapper>\n *\n * Framework-agnostic Lit element that wraps content with the Intlayer editor\n * selection UI. It replaces the per-framework ContentSelectorWrapper components\n * (Vue, Svelte, Solid, Preact).\n *\n * It reads from the global EditorStateManager singleton (set by initEditorClient)\n * and conditionally renders <intlayer-content-selector> around its slot content\n * when the editor is active and the app is running inside an iframe.\n *\n * @attr {string} key-path - JSON-serialized KeyPath[] for this content node\n * @attr {string} dictionary-key - The dictionary key owning this content node\n */\nexport class IntlayerContentSelectorWrapperElement extends LitElement {\n static styles = css`\n :host {\n display: contents;\n }\n `;\n\n @property({ type: String, attribute: 'key-path' }) keyPathJson = '[]';\n @property({ type: String, attribute: 'dictionary-key' }) dictionaryKey = '';\n\n @state() private _editorEnabled = false;\n @state() private _isInIframe = false;\n @state() private _isSelected = false;\n @state() private _editedValue: ContentNode | undefined = undefined;\n\n private _unsubManager: (() => void) | null = null;\n private _unsubEnabled: (() => void) | null = null;\n private _unsubFocused: (() => void) | null = null;\n private _unsubEditedContent: (() => void) | null = null;\n\n connectedCallback(): void {\n super.connectedCallback();\n if (typeof window !== 'undefined') {\n this._isInIframe = window.self !== window.top;\n }\n this._subscribeToManager();\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n this._teardown();\n }\n\n updated(changedProperties: Map<string, unknown>): void {\n if (\n changedProperties.has('keyPathJson') ||\n changedProperties.has('dictionaryKey')\n ) {\n const manager = getGlobalEditorManager();\n if (manager) this._updateEditedValue(manager);\n }\n }\n\n private _teardown(): void {\n this._unsubManager?.();\n this._unsubEnabled?.();\n this._unsubFocused?.();\n this._unsubEditedContent?.();\n this._unsubManager = null;\n this._unsubEnabled = null;\n this._unsubFocused = null;\n this._unsubEditedContent = null;\n }\n\n private _subscribeToManager(): void {\n const manager = getGlobalEditorManager();\n if (manager) {\n this._setupManagerSubscriptions(manager);\n }\n // Keep listening for manager changes (handles stop + re-init cycles)\n this._unsubManager = onGlobalEditorManagerChange((m) => {\n this._unsubEnabled?.();\n this._unsubFocused?.();\n this._unsubEditedContent?.();\n this._unsubEnabled = null;\n this._unsubFocused = null;\n this._unsubEditedContent = null;\n if (m) {\n this._setupManagerSubscriptions(m);\n } else {\n this._editorEnabled = false;\n this._isSelected = false;\n this._editedValue = undefined;\n }\n });\n }\n\n private _setupManagerSubscriptions(manager: EditorStateManager): void {\n this._editorEnabled = manager.editorEnabled.value ?? false;\n this._updateIsSelected(manager.focusedContent.value);\n this._updateEditedValue(manager);\n\n const handleEnabledChange = (e: Event) => {\n this._editorEnabled = (e as CustomEvent<boolean>).detail;\n };\n const handleFocusedChange = (e: Event) => {\n this._updateIsSelected((e as CustomEvent<FileContent | null>).detail);\n };\n const handleEditedContentChange = () => {\n this._updateEditedValue(manager);\n };\n\n manager.editorEnabled.addEventListener('change', handleEnabledChange);\n manager.focusedContent.addEventListener('change', handleFocusedChange);\n manager.editedContent.addEventListener('change', handleEditedContentChange);\n\n this._unsubEnabled = () =>\n manager.editorEnabled.removeEventListener('change', handleEnabledChange);\n this._unsubFocused = () =>\n manager.focusedContent.removeEventListener('change', handleFocusedChange);\n this._unsubEditedContent = () =>\n manager.editedContent.removeEventListener(\n 'change',\n handleEditedContentChange\n );\n }\n\n private _getRawKeyPath(): KeyPath[] {\n try {\n return JSON.parse(this.keyPathJson) as KeyPath[];\n } catch {\n return [];\n }\n }\n\n private _getFilteredKeyPath(): KeyPath[] {\n return this._getRawKeyPath().filter(\n (k) => k.type !== NodeTypes.TRANSLATION\n );\n }\n\n private _updateEditedValue(manager: EditorStateManager): void {\n const filteredKeyPath = this._getFilteredKeyPath();\n if (!this.dictionaryKey || filteredKeyPath.length === 0) {\n this._editedValue = undefined;\n return;\n }\n\n // Node types whose display requires framework-level rendering (markdown,\n // HTML, insertion, file): do not override the slot — the framework handles\n // those. Only plain / translated strings can be substituted here.\n const rawKeyPath = this._getRawKeyPath();\n const lastStepType = rawKeyPath[rawKeyPath.length - 1]?.type;\n if (\n lastStepType === NodeTypes.MARKDOWN ||\n lastStepType === NodeTypes.HTML ||\n lastStepType === NodeTypes.INSERTION ||\n lastStepType === NodeTypes.FILE\n ) {\n this._editedValue = undefined;\n return;\n }\n\n let value = manager.getContentValue(this.dictionaryKey, filteredKeyPath);\n\n // getContentNodeByKeyPath resolves translation nodes only at intermediate\n // steps, not the final leaf. Resolve manually when the returned value is\n // still a translation object (happens when Translation steps are filtered\n // out and the leaf IS the translation object).\n if (\n value !== null &&\n value !== undefined &&\n typeof value === 'object' &&\n value.nodeType === NodeTypes.TRANSLATION\n ) {\n const locale = manager.currentLocale.value as string | undefined;\n // TypedNodeModel<Translation, …> structurally satisfies TypedNode<BaseNode>\n // (both have nodeType), so this narrowing cast is sound.\n const node = value as TypedNodeModel<\n typeof NodeTypes.TRANSLATION,\n Record<string, ContentNode>\n >;\n value = locale ? node[NodeTypes.TRANSLATION][locale] : undefined;\n }\n\n this._editedValue = value;\n }\n\n private _updateIsSelected(\n focusedContent: FileContent | null | undefined\n ): void {\n if (!focusedContent) {\n this._isSelected = false;\n return;\n }\n const keyPath = this._getFilteredKeyPath();\n this._isSelected =\n focusedContent.dictionaryKey === this.dictionaryKey &&\n (focusedContent.keyPath?.length ?? 0) > 0 &&\n isSameKeyPath(focusedContent.keyPath ?? [], keyPath);\n }\n\n private _handlePress(e: Event): void {\n // Stop propagation so nested wrappers don't also fire (composed + bubbles)\n e.stopPropagation();\n const manager = getGlobalEditorManager();\n if (!manager) return;\n manager.focusedContent.set({\n dictionaryKey: this.dictionaryKey,\n keyPath: this._getFilteredKeyPath(),\n });\n }\n\n private _handleHover(e: Event): void {\n e.stopPropagation();\n getGlobalEditorManager()?.messenger.send(\n `${MessageKey.INTLAYER_HOVERED_CONTENT_CHANGED}/post`,\n { dictionaryKey: this.dictionaryKey, keyPath: this._getFilteredKeyPath() }\n );\n }\n\n private _handleUnhover(e: Event): void {\n e.stopPropagation();\n getGlobalEditorManager()?.messenger.send(\n `${MessageKey.INTLAYER_HOVERED_CONTENT_CHANGED}/post`,\n null\n );\n }\n\n render() {\n if (!this._isInIframe || !this._editorEnabled) {\n return html`<slot></slot>`;\n }\n\n const editedValue = this._editedValue;\n const displayedContent =\n typeof editedValue === 'string' ||\n typeof editedValue === 'number' ||\n typeof editedValue === 'boolean'\n ? editedValue\n : html`<slot></slot>`;\n\n return html`\n <intlayer-content-selector\n ?is-selecting=${this._isSelected}\n @intlayer:press=${this._handlePress}\n @intlayer:hover=${this._handleHover}\n @intlayer:unhover=${this._handleUnhover}\n >\n ${displayedContent}\n </intlayer-content-selector>\n `;\n }\n}\n\nexport const defineIntlayerContentSelectorWrapper = (): void => {\n if (typeof customElements === 'undefined') return;\n\n if (!customElements.get('intlayer-content-selector-wrapper')) {\n customElements.define(\n 'intlayer-content-selector-wrapper',\n IntlayerContentSelectorWrapperElement\n );\n }\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"ContentSelectorWrapper.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 (k) => k.type !== NodeTypes.TRANSLATION\n );\n }\n\n private _updateEditedValue(manager: EditorStateManager): void {\n const filteredKeyPath = this._getFilteredKeyPath();\n if (!this._dictionaryKey || filteredKeyPath.length === 0) {\n this._editedValue = undefined;\n this._render();\n return;\n }\n\n // Node types whose display requires framework-level rendering (markdown,\n // HTML, insertion, file): do not override the slot — the framework handles\n // those. Only plain / translated strings can be substituted here.\n const rawKeyPath = this._getRawKeyPath();\n const lastStepType = rawKeyPath[rawKeyPath.length - 1]?.type;\n if (\n lastStepType === NodeTypes.MARKDOWN ||\n lastStepType === NodeTypes.HTML ||\n lastStepType === NodeTypes.INSERTION ||\n lastStepType === NodeTypes.FILE\n ) {\n this._editedValue = undefined;\n this._render();\n return;\n }\n\n let value = manager.getContentValue(this._dictionaryKey, filteredKeyPath);\n\n // getContentNodeByKeyPath resolves translation nodes only at intermediate\n // steps, not the final leaf. Resolve manually when the returned value is\n // still a translation object (happens when Translation steps are filtered\n // out and the leaf IS the translation object).\n if (\n value !== null &&\n value !== undefined &&\n typeof value === 'object' &&\n (value as { nodeType?: unknown }).nodeType === NodeTypes.TRANSLATION\n ) {\n const locale = manager.currentLocale.value as string | undefined;\n // TypedNodeModel<Translation, …> structurally satisfies TypedNode<BaseNode>\n // (both have nodeType), so this narrowing cast is sound.\n const node = value as TypedNodeModel<\n typeof NodeTypes.TRANSLATION,\n Record<string, ContentNode>\n >;\n value = locale ? node[NodeTypes.TRANSLATION][locale] : undefined;\n }\n\n this._editedValue = value;\n this._render();\n }\n\n private _updateIsSelected(\n focusedContent: FileContent | null | undefined\n ): void {\n if (!focusedContent) {\n this._isSelected = false;\n this._updateSelectorAttr();\n return;\n }\n const keyPath = this._getFilteredKeyPath();\n this._isSelected =\n focusedContent.dictionaryKey === this._dictionaryKey &&\n (focusedContent.keyPath?.length ?? 0) > 0 &&\n isSameKeyPath(focusedContent.keyPath ?? [], keyPath);\n this._updateSelectorAttr();\n }\n\n private _updateSelectorAttr(): void {\n if (!this._selector) return;\n if (this._isSelected) {\n this._selector.setAttribute('is-selecting', '');\n } else {\n this._selector.removeAttribute('is-selecting');\n }\n }\n\n private _subscribeToManager(): void {\n const manager = getGlobalEditorManager();\n if (manager) {\n this._setupManagerSubscriptions(manager);\n }\n // Keep listening for manager changes (handles stop + re-init cycles)\n this._unsubManager = onGlobalEditorManagerChange((m) => {\n this._unsubEnabled?.();\n this._unsubFocused?.();\n this._unsubEditedContent?.();\n this._unsubEnabled = null;\n this._unsubFocused = null;\n this._unsubEditedContent = null;\n if (m) {\n this._setupManagerSubscriptions(m);\n } else {\n this._editorEnabled = false;\n this._isSelected = false;\n this._editedValue = undefined;\n this._render();\n }\n });\n }\n\n private _setupManagerSubscriptions(manager: EditorStateManager): void {\n this._editorEnabled = manager.editorEnabled.value ?? false;\n this._updateIsSelected(manager.focusedContent.value);\n this._updateEditedValue(manager);\n\n const handleEnabledChange = (e: Event) => {\n this._editorEnabled = (e as CustomEvent<boolean>).detail;\n this._render();\n };\n const handleFocusedChange = (e: Event) => {\n this._updateIsSelected((e as CustomEvent<FileContent | null>).detail);\n };\n const handleEditedContentChange = () => {\n this._updateEditedValue(manager);\n };\n\n manager.editorEnabled.addEventListener('change', handleEnabledChange);\n manager.focusedContent.addEventListener('change', handleFocusedChange);\n manager.editedContent.addEventListener('change', handleEditedContentChange);\n\n this._unsubEnabled = () =>\n manager.editorEnabled.removeEventListener('change', handleEnabledChange);\n this._unsubFocused = () =>\n manager.focusedContent.removeEventListener('change', handleFocusedChange);\n this._unsubEditedContent = () =>\n manager.editedContent.removeEventListener(\n 'change',\n handleEditedContentChange\n );\n }\n\n private _handlePress(e: Event): void {\n // Stop propagation so nested wrappers don't also fire (composed + bubbles)\n e.stopPropagation();\n const manager = getGlobalEditorManager();\n if (!manager) return;\n manager.focusedContent.set({\n dictionaryKey: this._dictionaryKey,\n keyPath: this._getFilteredKeyPath(),\n });\n }\n\n private _handleHover(e: Event): void {\n e.stopPropagation();\n getGlobalEditorManager()?.messenger.send(\n `${MessageKey.INTLAYER_HOVERED_CONTENT_CHANGED}/post`,\n {\n dictionaryKey: this._dictionaryKey,\n keyPath: this._getFilteredKeyPath(),\n }\n );\n }\n\n private _handleUnhover(e: Event): void {\n e.stopPropagation();\n getGlobalEditorManager()?.messenger.send(\n `${MessageKey.INTLAYER_HOVERED_CONTENT_CHANGED}/post`,\n null\n );\n }\n\n private _render(): void {\n const useWrapper = this._isInIframe && this._editorEnabled;\n const editedValue = this._editedValue;\n const isSimpleValue =\n typeof editedValue === 'string' ||\n typeof editedValue === 'number' ||\n typeof editedValue === 'boolean';\n\n const newState: RenderState = !useWrapper\n ? 'simple'\n : isSimpleValue\n ? 'wrapped-text'\n : 'wrapped-slot';\n\n if (this._renderState !== newState) {\n this._rebuildContent(newState);\n return;\n }\n\n // Structure unchanged — update only dynamic parts\n if (newState !== 'simple' && this._selector) {\n this._updateSelectorAttr();\n if (\n newState === 'wrapped-text' &&\n this._selector.firstChild?.nodeType === Node.TEXT_NODE\n ) {\n (this._selector.firstChild as Text).data = String(editedValue);\n }\n }\n }\n\n private _rebuildContent(state: RenderState): void {\n const shadow = this.shadowRoot!;\n // Remove all nodes except the style element (first child)\n while (shadow.childNodes.length > 1) {\n shadow.removeChild(shadow.lastChild!);\n }\n this._selector = null;\n\n if (state === 'simple') {\n shadow.appendChild(document.createElement('slot'));\n } else {\n const selector = document.createElement('intlayer-content-selector');\n this._selector = selector;\n if (this._isSelected) selector.setAttribute('is-selecting', '');\n selector.addEventListener('intlayer:press', (e) => this._handlePress(e));\n selector.addEventListener('intlayer:hover', (e) => this._handleHover(e));\n selector.addEventListener('intlayer:unhover', (e) =>\n this._handleUnhover(e)\n );\n\n if (state === 'wrapped-text') {\n selector.appendChild(\n document.createTextNode(String(this._editedValue))\n );\n } else {\n selector.appendChild(document.createElement('slot'));\n }\n shadow.appendChild(selector);\n }\n\n this._renderState = state;\n }\n}\n\nexport const defineIntlayerContentSelectorWrapper = (): void => {\n if (typeof customElements === 'undefined') return;\n\n if (!customElements.get('intlayer-content-selector-wrapper')) {\n customElements.define(\n 'intlayer-content-selector-wrapper',\n IntlayerContentSelectorWrapperElement\n );\n }\n};\n"],"mappings":"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"}