@craftile/preview-client 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Craftile Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.cjs ADDED
@@ -0,0 +1,356 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
6
+ class WindowMessenger {
7
+ constructor(targetWindow, targetOrigin = "*") {
8
+ __publicField(this, "handlers", /* @__PURE__ */ new Map());
9
+ __publicField(this, "targetWindow");
10
+ __publicField(this, "targetOrigin");
11
+ __publicField(this, "fallbackHandler");
12
+ this.targetWindow = targetWindow;
13
+ this.targetOrigin = targetOrigin;
14
+ window.addEventListener("message", this.handleMessage.bind(this));
15
+ }
16
+ handleMessage(event) {
17
+ const message = event.data;
18
+ if (!message.type) {
19
+ return;
20
+ }
21
+ const handlers = this.handlers.get(message.type);
22
+ if (handlers) {
23
+ handlers.forEach((handler) => handler(message.payload, event));
24
+ } else if (this.fallbackHandler) {
25
+ this.fallbackHandler(event.data, event);
26
+ }
27
+ }
28
+ send(type, payload) {
29
+ const message = { type, payload };
30
+ this.targetWindow.postMessage(message, this.targetOrigin);
31
+ }
32
+ listen(type, handler) {
33
+ if (!this.handlers.has(type)) {
34
+ this.handlers.set(type, []);
35
+ }
36
+ this.handlers.get(type).push(handler);
37
+ return () => {
38
+ const handlers = this.handlers.get(type);
39
+ if (handlers) {
40
+ const index = handlers.indexOf(handler);
41
+ if (index > -1) {
42
+ handlers.splice(index, 1);
43
+ }
44
+ }
45
+ };
46
+ }
47
+ registerFallbackHandler(handler) {
48
+ this.fallbackHandler = handler;
49
+ }
50
+ }
51
+ function createParentMessenger(targetOrigin = "*") {
52
+ if (window.parent === window) {
53
+ throw new Error("Not inside an iframe");
54
+ }
55
+ return new WindowMessenger(window.parent, targetOrigin);
56
+ }
57
+ class EventBus {
58
+ constructor() {
59
+ __publicField(this, "listeners", /* @__PURE__ */ new Map());
60
+ }
61
+ /**
62
+ * Add an event listener
63
+ *
64
+ * @param event Event name
65
+ * @param listener Event listener function
66
+ *
67
+ * @returns Cleanup function to remove the listener
68
+ */
69
+ on(event, listener) {
70
+ if (!this.listeners.has(event)) {
71
+ this.listeners.set(event, /* @__PURE__ */ new Set());
72
+ }
73
+ this.listeners.get(event).add(listener);
74
+ return () => {
75
+ this.off(event, listener);
76
+ };
77
+ }
78
+ /**
79
+ * Remove an event listener
80
+ *
81
+ * @param event Event name
82
+ * @param listener Event listener function to remove
83
+ */
84
+ off(event, listener) {
85
+ const eventListeners = this.listeners.get(event);
86
+ if (eventListeners) {
87
+ eventListeners.delete(listener);
88
+ if (eventListeners.size === 0) {
89
+ this.listeners.delete(event);
90
+ }
91
+ }
92
+ }
93
+ /**
94
+ * Add a one-time event listener
95
+ *
96
+ * @param event Event name
97
+ * @param listener Event listener function
98
+ */
99
+ once(event, listener) {
100
+ const onceWrapper = (data) => {
101
+ listener(data);
102
+ this.off(event, onceWrapper);
103
+ };
104
+ this.on(event, onceWrapper);
105
+ }
106
+ /**
107
+ * Emit an event
108
+ *
109
+ * @param event Event name
110
+ * @param args Event data (optional, depending on event type)
111
+ */
112
+ emit(event, ...args) {
113
+ const eventListeners = this.listeners.get(event);
114
+ if (eventListeners) {
115
+ const data = args[0];
116
+ eventListeners.forEach((listener) => {
117
+ try {
118
+ listener(data);
119
+ } catch (error) {
120
+ console.error(`Error in event listener for '${String(event)}':`, error);
121
+ }
122
+ });
123
+ }
124
+ }
125
+ /**
126
+ * Remove all listeners for an event, or all listeners if no event specified
127
+ *
128
+ * @param event Optional event name. If not provided, removes all listeners
129
+ */
130
+ removeAllListeners(event) {
131
+ if (event) {
132
+ this.listeners.delete(event);
133
+ } else {
134
+ this.listeners.clear();
135
+ }
136
+ }
137
+ }
138
+ class Inspector {
139
+ constructor(messenger) {
140
+ __publicField(this, "active", true);
141
+ __publicField(this, "messenger");
142
+ __publicField(this, "currentHoveredBlock", null);
143
+ __publicField(this, "currentSelectedBlock", null);
144
+ __publicField(this, "overlayButtonHovered", false);
145
+ __publicField(this, "resizeObserver", null);
146
+ __publicField(this, "mutationObserver", null);
147
+ this.messenger = messenger;
148
+ this.messenger.listen("craftile.inspector.enable", () => this.enable());
149
+ this.messenger.listen("craftile.inspector.disable", () => this.disable());
150
+ this.messenger.listen("craftile.inspector.overlay-button-enter", this.handleOverlayButtonEnter.bind(this));
151
+ this.messenger.listen("craftile.inspector.overlay-button-leave", this.handleOverlayButtonLeave.bind(this));
152
+ window.addEventListener("scroll", this.handleScroll.bind(this), { passive: true });
153
+ this.setupGlobalEventListeners();
154
+ }
155
+ enable() {
156
+ this.active = true;
157
+ document.body.classList.add("craftile-inspector-active");
158
+ }
159
+ disable() {
160
+ this.active = false;
161
+ document.body.classList.remove("craftile-inspector-active");
162
+ this.currentHoveredBlock = null;
163
+ this.currentSelectedBlock = null;
164
+ this.overlayButtonHovered = false;
165
+ }
166
+ handleOverlayButtonEnter() {
167
+ this.overlayButtonHovered = true;
168
+ }
169
+ handleOverlayButtonLeave(_data) {
170
+ this.overlayButtonHovered = false;
171
+ if (!this.currentHoveredBlock) {
172
+ this.messenger.send("craftile.preview.block-leave");
173
+ }
174
+ }
175
+ handleScroll() {
176
+ if (this.currentSelectedBlock) {
177
+ this.sendSelectedBlockPosition();
178
+ }
179
+ if (this.currentHoveredBlock) {
180
+ this.sendHoveredBlockPosition();
181
+ }
182
+ }
183
+ setupGlobalEventListeners() {
184
+ document.addEventListener("mouseover", this.handleGlobalHover.bind(this));
185
+ document.addEventListener("mouseout", this.handleGlobalLeave.bind(this));
186
+ document.addEventListener("click", this.handleGlobalClick.bind(this));
187
+ }
188
+ handleGlobalHover(e) {
189
+ if (!this.active) {
190
+ return;
191
+ }
192
+ const blockElement = e.target.closest("[data-block]");
193
+ if (!blockElement) {
194
+ return;
195
+ }
196
+ e.stopPropagation();
197
+ this.currentHoveredBlock = blockElement;
198
+ this.sendHoveredBlockPosition();
199
+ }
200
+ handleGlobalLeave(e) {
201
+ if (!this.active) {
202
+ return;
203
+ }
204
+ const blockElement = e.target.closest("[data-block]");
205
+ if (!blockElement) {
206
+ return;
207
+ }
208
+ if (!this.overlayButtonHovered) {
209
+ this.currentHoveredBlock = null;
210
+ this.messenger.send("craftile.preview.block-leave");
211
+ }
212
+ }
213
+ handleGlobalClick(e) {
214
+ this.messenger.send("craftile.preview.click");
215
+ if (!this.active) {
216
+ return;
217
+ }
218
+ const blockElement = e.target.closest("[data-block]");
219
+ if (!blockElement) {
220
+ return;
221
+ }
222
+ e.stopPropagation();
223
+ const blockId = blockElement.getAttribute("data-block");
224
+ if (blockId) {
225
+ this.currentSelectedBlock = blockElement;
226
+ this.sendSelectedBlockPosition();
227
+ this.trackSelectedBlock();
228
+ }
229
+ }
230
+ sendHoveredBlockPosition() {
231
+ const position = this.computeElementPositioning(this.currentHoveredBlock);
232
+ this.messenger.send("craftile.preview.block-hover", {
233
+ blockRect: position.rect,
234
+ parentRect: position.parentRect,
235
+ scrollTop: position.scrollTop,
236
+ scrollLeft: position.scrollLeft,
237
+ blockId: this.currentHoveredBlock.dataset.block,
238
+ parentFlexDirection: position.parentFlexDirection
239
+ });
240
+ }
241
+ sendSelectedBlockPosition(updates = false) {
242
+ const position = this.computeElementPositioning(this.currentSelectedBlock);
243
+ this.messenger.send(updates ? "craftile.preview.update-selected-block" : "craftile.preview.block-select", {
244
+ blockRect: position.rect,
245
+ scrollTop: position.scrollTop,
246
+ scrollLeft: position.scrollLeft,
247
+ blockId: this.currentSelectedBlock.dataset.block
248
+ });
249
+ }
250
+ trackSelectedBlock() {
251
+ if (!this.currentSelectedBlock) {
252
+ return;
253
+ }
254
+ if (this.resizeObserver) {
255
+ this.resizeObserver.disconnect();
256
+ this.resizeObserver = null;
257
+ }
258
+ if (this.mutationObserver) {
259
+ this.mutationObserver.disconnect();
260
+ this.mutationObserver = null;
261
+ }
262
+ this.resizeObserver = new ResizeObserver(() => {
263
+ this.sendSelectedBlockPosition(true);
264
+ });
265
+ this.resizeObserver.observe(this.currentSelectedBlock);
266
+ this.mutationObserver = new MutationObserver(() => {
267
+ this.sendSelectedBlockPosition(true);
268
+ });
269
+ this.mutationObserver.observe(this.currentSelectedBlock, {
270
+ attributes: true,
271
+ subtree: false
272
+ });
273
+ let parent = this.currentSelectedBlock.parentElement;
274
+ while (parent) {
275
+ this.mutationObserver.observe(parent, {
276
+ childList: true,
277
+ subtree: false
278
+ });
279
+ if (parent === document.body) {
280
+ break;
281
+ }
282
+ parent = parent.parentElement;
283
+ }
284
+ }
285
+ computeElementPositioning(element) {
286
+ const rect = element.getBoundingClientRect();
287
+ const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
288
+ const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
289
+ const eldestParent = this.findEldestParentBlock(element);
290
+ const parentRect = eldestParent && eldestParent !== element ? eldestParent.getBoundingClientRect() : void 0;
291
+ const parentFlexDirection = this.getElementFlexDirection(element.parentElement);
292
+ return {
293
+ rect,
294
+ parentRect,
295
+ scrollTop,
296
+ scrollLeft,
297
+ parentFlexDirection
298
+ };
299
+ }
300
+ findEldestParentBlock(element) {
301
+ let eldestParent = null;
302
+ let parentElement = element.parentElement;
303
+ while (parentElement && parentElement !== document.body) {
304
+ if (parentElement.hasAttribute("data-block")) {
305
+ eldestParent = parentElement;
306
+ }
307
+ parentElement = parentElement.parentElement;
308
+ }
309
+ return eldestParent;
310
+ }
311
+ getElementFlexDirection(element) {
312
+ if (!element) {
313
+ return "column";
314
+ }
315
+ const style = window.getComputedStyle(element);
316
+ const flexDirection = style.display.includes("flex") ? style.flexDirection : "column";
317
+ return flexDirection === "row" || flexDirection === "row-reverse" ? "row" : "column";
318
+ }
319
+ }
320
+ class PreviewClient extends EventBus {
321
+ constructor() {
322
+ super();
323
+ __publicField(this, "messenger");
324
+ // @ts-ignore
325
+ __publicField(this, "inspector");
326
+ this.messenger = createParentMessenger(window.origin);
327
+ this.inspector = new Inspector(this.messenger);
328
+ this.initialize();
329
+ }
330
+ initialize() {
331
+ window.addEventListener("load", () => {
332
+ this.messenger.send("craftile.preview.ready", {});
333
+ });
334
+ document.addEventListener("DOMContentLoaded", () => {
335
+ this.sendPageData();
336
+ });
337
+ this.messenger.registerFallbackHandler((data) => {
338
+ const { type, payload } = data;
339
+ this.emit(type, payload);
340
+ });
341
+ }
342
+ sendPageData() {
343
+ const pageDataElement = document.getElementById("page-data");
344
+ if (!pageDataElement) {
345
+ return;
346
+ }
347
+ try {
348
+ const pageData = JSON.parse(pageDataElement.textContent || "{}");
349
+ this.messenger.send("craftile.preview.page-data", { pageData });
350
+ } catch (error) {
351
+ console.error("Failed to parse page data:", error);
352
+ }
353
+ }
354
+ }
355
+ exports.PreviewClient = PreviewClient;
356
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../../messenger/src/index.ts","../../event-bus/src/index.ts","../src/inspector.ts","../src/client.ts"],"sourcesContent":["export interface TypedMessage<T = any> {\n type: string;\n payload: T | undefined;\n}\n\nexport class WindowMessenger<Messages extends Record<string, any>> {\n private handlers = new Map<keyof Messages, Function[]>();\n private targetWindow: Window;\n private targetOrigin: string;\n private fallbackHandler?: (data: any, event: MessageEvent) => void;\n\n constructor(targetWindow: Window, targetOrigin: string = '*') {\n this.targetWindow = targetWindow;\n this.targetOrigin = targetOrigin;\n\n window.addEventListener('message', this.handleMessage.bind(this));\n }\n\n private handleMessage(event: MessageEvent) {\n const message = event.data as TypedMessage;\n\n if (!message.type) {\n return;\n }\n\n const handlers = this.handlers.get(message.type);\n\n if (handlers) {\n handlers.forEach((handler) => handler(message.payload, event));\n } else if (this.fallbackHandler) {\n this.fallbackHandler(event.data, event);\n }\n }\n\n send<K extends keyof Messages>(type: K, payload?: Messages[K]): void {\n const message: TypedMessage<Messages[K]> = { type: type as string, payload };\n this.targetWindow.postMessage(message, this.targetOrigin);\n }\n\n listen<K extends keyof Messages>(type: K, handler: (data: Messages[K], event: MessageEvent) => void): () => void {\n if (!this.handlers.has(type)) {\n this.handlers.set(type, []);\n }\n\n this.handlers.get(type)!.push(handler);\n\n return () => {\n const handlers = this.handlers.get(type);\n if (handlers) {\n const index = handlers.indexOf(handler);\n if (index > -1) {\n handlers.splice(index, 1);\n }\n }\n };\n }\n\n registerFallbackHandler(handler: (data: any, event: MessageEvent) => void) {\n this.fallbackHandler = handler;\n }\n}\n\nexport function createIframeMessenger<T extends Record<string, any>>(iframe: HTMLIFrameElement, targetOrigin = '*') {\n return new WindowMessenger<T>(iframe.contentWindow!, targetOrigin);\n}\n\nexport function createParentMessenger<T extends Record<string, any>>(targetOrigin = '*') {\n if (window.parent === window) {\n throw new Error('Not inside an iframe');\n }\n return new WindowMessenger<T>(window.parent, targetOrigin);\n}\n","export type EventListener<T = any> = (data: T) => void;\nexport type EventMap = {\n [event: string]: any;\n};\n\n/**\n * Type-safe EventBus with generic event map support\n *\n * @template T Event map interface that defines the events and their data types\n */\nexport class EventBus<T extends EventMap = EventMap> {\n private listeners: Map<keyof T, Set<EventListener<any>>> = new Map();\n\n /**\n * Add an event listener\n *\n * @param event Event name\n * @param listener Event listener function\n *\n * @returns Cleanup function to remove the listener\n */\n on<K extends keyof T>(event: K, listener: EventListener<T[K]>): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n\n this.listeners.get(event)!.add(listener);\n\n return () => {\n this.off(event, listener);\n };\n }\n\n /**\n * Remove an event listener\n *\n * @param event Event name\n * @param listener Event listener function to remove\n */\n off<K extends keyof T>(event: K, listener: EventListener<T[K]>): void {\n const eventListeners = this.listeners.get(event);\n\n if (eventListeners) {\n eventListeners.delete(listener);\n\n if (eventListeners.size === 0) {\n this.listeners.delete(event);\n }\n }\n }\n\n /**\n * Add a one-time event listener\n *\n * @param event Event name\n * @param listener Event listener function\n */\n once<K extends keyof T>(event: K, listener: EventListener<T[K]>): void {\n const onceWrapper = (data: T[K]) => {\n listener(data);\n this.off(event, onceWrapper);\n };\n\n this.on(event, onceWrapper);\n }\n\n /**\n * Emit an event\n *\n * @param event Event name\n * @param args Event data (optional, depending on event type)\n */\n emit<K extends keyof T>(event: K, ...args: T[K] extends void ? [] : [T[K]]): void {\n const eventListeners = this.listeners.get(event);\n\n if (eventListeners) {\n const data = args[0];\n eventListeners.forEach((listener) => {\n try {\n listener(data);\n } catch (error) {\n console.error(`Error in event listener for '${String(event)}':`, error);\n }\n });\n }\n }\n\n /**\n * Remove all listeners for an event, or all listeners if no event specified\n *\n * @param event Optional event name. If not provided, removes all listeners\n */\n removeAllListeners<K extends keyof T>(event?: K): void {\n if (event) {\n this.listeners.delete(event);\n } else {\n this.listeners.clear();\n }\n }\n}\n","import type { WindowMessenger } from '@craftile/messenger';\nimport type { WindowMessages } from '@craftile/types';\n\nexport class Inspector {\n private active = true;\n private messenger: WindowMessenger<WindowMessages>;\n private currentHoveredBlock: HTMLElement | null = null;\n private currentSelectedBlock: HTMLElement | null = null;\n private overlayButtonHovered = false;\n\n private resizeObserver: ResizeObserver | null = null;\n private mutationObserver: MutationObserver | null = null;\n\n constructor(messenger: WindowMessenger<WindowMessages>) {\n this.messenger = messenger;\n\n this.messenger.listen('craftile.inspector.enable', () => this.enable());\n this.messenger.listen('craftile.inspector.disable', () => this.disable());\n this.messenger.listen('craftile.inspector.overlay-button-enter', this.handleOverlayButtonEnter.bind(this));\n this.messenger.listen('craftile.inspector.overlay-button-leave', this.handleOverlayButtonLeave.bind(this));\n\n window.addEventListener('scroll', this.handleScroll.bind(this), { passive: true });\n this.setupGlobalEventListeners();\n }\n\n enable() {\n this.active = true;\n document.body.classList.add('craftile-inspector-active');\n }\n\n disable() {\n this.active = false;\n document.body.classList.remove('craftile-inspector-active');\n this.currentHoveredBlock = null;\n this.currentSelectedBlock = null;\n this.overlayButtonHovered = false;\n }\n\n private handleOverlayButtonEnter() {\n this.overlayButtonHovered = true;\n }\n\n private handleOverlayButtonLeave(_data: { blockId: string }) {\n this.overlayButtonHovered = false;\n\n if (!this.currentHoveredBlock) {\n this.messenger.send('craftile.preview.block-leave');\n }\n }\n\n private handleScroll() {\n if (this.currentSelectedBlock) {\n this.sendSelectedBlockPosition();\n }\n\n if (this.currentHoveredBlock) {\n this.sendHoveredBlockPosition();\n }\n }\n\n private setupGlobalEventListeners() {\n document.addEventListener('mouseover', this.handleGlobalHover.bind(this));\n document.addEventListener('mouseout', this.handleGlobalLeave.bind(this));\n document.addEventListener('click', this.handleGlobalClick.bind(this));\n }\n\n private handleGlobalHover(e: Event) {\n if (!this.active) {\n return;\n }\n\n const blockElement = (e.target as Element).closest('[data-block]') as HTMLElement;\n\n if (!blockElement) {\n return;\n }\n\n e.stopPropagation();\n this.currentHoveredBlock = blockElement;\n this.sendHoveredBlockPosition();\n }\n\n private handleGlobalLeave(e: Event) {\n if (!this.active) {\n return;\n }\n\n const blockElement = (e.target as Element).closest('[data-block]') as HTMLElement;\n if (!blockElement) {\n return;\n }\n\n // Only clear overlay if button is not being hovered\n if (!this.overlayButtonHovered) {\n this.currentHoveredBlock = null;\n this.messenger.send('craftile.preview.block-leave');\n }\n }\n\n private handleGlobalClick(e: Event) {\n this.messenger.send('craftile.preview.click');\n\n if (!this.active) {\n return;\n }\n\n const blockElement = (e.target as Element).closest('[data-block]') as HTMLElement;\n if (!blockElement) {\n return;\n }\n\n e.stopPropagation();\n\n const blockId = blockElement.getAttribute('data-block');\n\n if (blockId) {\n this.currentSelectedBlock = blockElement;\n this.sendSelectedBlockPosition();\n this.trackSelectedBlock();\n }\n }\n\n private sendHoveredBlockPosition() {\n const position = this.computeElementPositioning(this.currentHoveredBlock!);\n\n this.messenger.send('craftile.preview.block-hover', {\n blockRect: position.rect,\n parentRect: position.parentRect,\n scrollTop: position.scrollTop,\n scrollLeft: position.scrollLeft,\n blockId: this.currentHoveredBlock!.dataset.block as string,\n parentFlexDirection: position.parentFlexDirection,\n });\n }\n\n private sendSelectedBlockPosition(updates: boolean = false) {\n const position = this.computeElementPositioning(this.currentSelectedBlock!);\n this.messenger.send(updates ? 'craftile.preview.update-selected-block' : 'craftile.preview.block-select', {\n blockRect: position.rect,\n scrollTop: position.scrollTop,\n scrollLeft: position.scrollLeft,\n blockId: this.currentSelectedBlock!.dataset.block as string,\n });\n }\n\n private trackSelectedBlock() {\n if (!this.currentSelectedBlock) {\n return;\n }\n\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n\n if (this.mutationObserver) {\n this.mutationObserver.disconnect();\n this.mutationObserver = null;\n }\n\n this.resizeObserver = new ResizeObserver(() => {\n this.sendSelectedBlockPosition(true);\n });\n this.resizeObserver.observe(this.currentSelectedBlock);\n\n this.mutationObserver = new MutationObserver(() => {\n this.sendSelectedBlockPosition(true);\n });\n\n this.mutationObserver.observe(this.currentSelectedBlock, {\n attributes: true,\n subtree: false,\n });\n\n // Also observe parent elements that might affect positioning\n let parent = this.currentSelectedBlock.parentElement;\n while (parent) {\n this.mutationObserver.observe(parent, {\n childList: true,\n subtree: false,\n });\n\n if (parent === document.body) {\n break;\n }\n\n parent = parent.parentElement;\n }\n }\n\n private computeElementPositioning(element: HTMLElement) {\n const rect = element.getBoundingClientRect();\n const scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;\n\n const eldestParent = this.findEldestParentBlock(element);\n const parentRect = eldestParent && eldestParent !== element ? eldestParent.getBoundingClientRect() : undefined;\n const parentFlexDirection = this.getElementFlexDirection(element.parentElement);\n\n return {\n rect,\n parentRect,\n scrollTop,\n scrollLeft,\n parentFlexDirection,\n };\n }\n\n private findEldestParentBlock(element: HTMLElement): HTMLElement | null {\n let eldestParent: HTMLElement | null = null;\n let parentElement = element.parentElement;\n\n while (parentElement && parentElement !== document.body) {\n if (parentElement.hasAttribute('data-block')) {\n eldestParent = parentElement;\n }\n parentElement = parentElement.parentElement;\n }\n\n return eldestParent;\n }\n\n private getElementFlexDirection(element: HTMLElement | null): 'row' | 'column' {\n if (!element) {\n return 'column';\n }\n\n const style = window.getComputedStyle(element);\n const flexDirection = style.display.includes('flex') ? style.flexDirection : 'column';\n\n return flexDirection === 'row' || flexDirection === 'row-reverse' ? 'row' : 'column';\n }\n}\n","import type { WindowMessages } from '@craftile/types';\nimport { createParentMessenger, WindowMessenger } from '@craftile/messenger';\nimport { EventBus } from '@craftile/event-bus';\nimport { Inspector } from './inspector';\n\nexport class PreviewClient extends EventBus {\n private messenger: WindowMessenger<WindowMessages>;\n // @ts-ignore\n private inspector: Inspector;\n\n constructor() {\n super();\n\n this.messenger = createParentMessenger(window.origin);\n this.inspector = new Inspector(this.messenger);\n\n this.initialize();\n }\n\n private initialize() {\n window.addEventListener('load', () => {\n this.messenger.send('craftile.preview.ready', {});\n });\n\n document.addEventListener('DOMContentLoaded', () => {\n this.sendPageData();\n });\n\n this.messenger.registerFallbackHandler((data: any) => {\n const { type, payload } = data;\n this.emit(type, payload);\n });\n }\n\n private sendPageData() {\n const pageDataElement = document.getElementById('page-data');\n\n if (!pageDataElement) {\n return;\n }\n\n try {\n const pageData = JSON.parse(pageDataElement.textContent || '{}');\n this.messenger.send('craftile.preview.page-data', { pageData });\n } catch (error) {\n console.error('Failed to parse page data:', error);\n }\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { EventBus } from '@craftile/event-bus';
2
+
3
+ export declare class PreviewClient extends EventBus {
4
+ private messenger;
5
+ private inspector;
6
+ constructor();
7
+ private initialize;
8
+ private sendPageData;
9
+ }
10
+
11
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,356 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ class WindowMessenger {
5
+ constructor(targetWindow, targetOrigin = "*") {
6
+ __publicField(this, "handlers", /* @__PURE__ */ new Map());
7
+ __publicField(this, "targetWindow");
8
+ __publicField(this, "targetOrigin");
9
+ __publicField(this, "fallbackHandler");
10
+ this.targetWindow = targetWindow;
11
+ this.targetOrigin = targetOrigin;
12
+ window.addEventListener("message", this.handleMessage.bind(this));
13
+ }
14
+ handleMessage(event) {
15
+ const message = event.data;
16
+ if (!message.type) {
17
+ return;
18
+ }
19
+ const handlers = this.handlers.get(message.type);
20
+ if (handlers) {
21
+ handlers.forEach((handler) => handler(message.payload, event));
22
+ } else if (this.fallbackHandler) {
23
+ this.fallbackHandler(event.data, event);
24
+ }
25
+ }
26
+ send(type, payload) {
27
+ const message = { type, payload };
28
+ this.targetWindow.postMessage(message, this.targetOrigin);
29
+ }
30
+ listen(type, handler) {
31
+ if (!this.handlers.has(type)) {
32
+ this.handlers.set(type, []);
33
+ }
34
+ this.handlers.get(type).push(handler);
35
+ return () => {
36
+ const handlers = this.handlers.get(type);
37
+ if (handlers) {
38
+ const index = handlers.indexOf(handler);
39
+ if (index > -1) {
40
+ handlers.splice(index, 1);
41
+ }
42
+ }
43
+ };
44
+ }
45
+ registerFallbackHandler(handler) {
46
+ this.fallbackHandler = handler;
47
+ }
48
+ }
49
+ function createParentMessenger(targetOrigin = "*") {
50
+ if (window.parent === window) {
51
+ throw new Error("Not inside an iframe");
52
+ }
53
+ return new WindowMessenger(window.parent, targetOrigin);
54
+ }
55
+ class EventBus {
56
+ constructor() {
57
+ __publicField(this, "listeners", /* @__PURE__ */ new Map());
58
+ }
59
+ /**
60
+ * Add an event listener
61
+ *
62
+ * @param event Event name
63
+ * @param listener Event listener function
64
+ *
65
+ * @returns Cleanup function to remove the listener
66
+ */
67
+ on(event, listener) {
68
+ if (!this.listeners.has(event)) {
69
+ this.listeners.set(event, /* @__PURE__ */ new Set());
70
+ }
71
+ this.listeners.get(event).add(listener);
72
+ return () => {
73
+ this.off(event, listener);
74
+ };
75
+ }
76
+ /**
77
+ * Remove an event listener
78
+ *
79
+ * @param event Event name
80
+ * @param listener Event listener function to remove
81
+ */
82
+ off(event, listener) {
83
+ const eventListeners = this.listeners.get(event);
84
+ if (eventListeners) {
85
+ eventListeners.delete(listener);
86
+ if (eventListeners.size === 0) {
87
+ this.listeners.delete(event);
88
+ }
89
+ }
90
+ }
91
+ /**
92
+ * Add a one-time event listener
93
+ *
94
+ * @param event Event name
95
+ * @param listener Event listener function
96
+ */
97
+ once(event, listener) {
98
+ const onceWrapper = (data) => {
99
+ listener(data);
100
+ this.off(event, onceWrapper);
101
+ };
102
+ this.on(event, onceWrapper);
103
+ }
104
+ /**
105
+ * Emit an event
106
+ *
107
+ * @param event Event name
108
+ * @param args Event data (optional, depending on event type)
109
+ */
110
+ emit(event, ...args) {
111
+ const eventListeners = this.listeners.get(event);
112
+ if (eventListeners) {
113
+ const data = args[0];
114
+ eventListeners.forEach((listener) => {
115
+ try {
116
+ listener(data);
117
+ } catch (error) {
118
+ console.error(`Error in event listener for '${String(event)}':`, error);
119
+ }
120
+ });
121
+ }
122
+ }
123
+ /**
124
+ * Remove all listeners for an event, or all listeners if no event specified
125
+ *
126
+ * @param event Optional event name. If not provided, removes all listeners
127
+ */
128
+ removeAllListeners(event) {
129
+ if (event) {
130
+ this.listeners.delete(event);
131
+ } else {
132
+ this.listeners.clear();
133
+ }
134
+ }
135
+ }
136
+ class Inspector {
137
+ constructor(messenger) {
138
+ __publicField(this, "active", true);
139
+ __publicField(this, "messenger");
140
+ __publicField(this, "currentHoveredBlock", null);
141
+ __publicField(this, "currentSelectedBlock", null);
142
+ __publicField(this, "overlayButtonHovered", false);
143
+ __publicField(this, "resizeObserver", null);
144
+ __publicField(this, "mutationObserver", null);
145
+ this.messenger = messenger;
146
+ this.messenger.listen("craftile.inspector.enable", () => this.enable());
147
+ this.messenger.listen("craftile.inspector.disable", () => this.disable());
148
+ this.messenger.listen("craftile.inspector.overlay-button-enter", this.handleOverlayButtonEnter.bind(this));
149
+ this.messenger.listen("craftile.inspector.overlay-button-leave", this.handleOverlayButtonLeave.bind(this));
150
+ window.addEventListener("scroll", this.handleScroll.bind(this), { passive: true });
151
+ this.setupGlobalEventListeners();
152
+ }
153
+ enable() {
154
+ this.active = true;
155
+ document.body.classList.add("craftile-inspector-active");
156
+ }
157
+ disable() {
158
+ this.active = false;
159
+ document.body.classList.remove("craftile-inspector-active");
160
+ this.currentHoveredBlock = null;
161
+ this.currentSelectedBlock = null;
162
+ this.overlayButtonHovered = false;
163
+ }
164
+ handleOverlayButtonEnter() {
165
+ this.overlayButtonHovered = true;
166
+ }
167
+ handleOverlayButtonLeave(_data) {
168
+ this.overlayButtonHovered = false;
169
+ if (!this.currentHoveredBlock) {
170
+ this.messenger.send("craftile.preview.block-leave");
171
+ }
172
+ }
173
+ handleScroll() {
174
+ if (this.currentSelectedBlock) {
175
+ this.sendSelectedBlockPosition();
176
+ }
177
+ if (this.currentHoveredBlock) {
178
+ this.sendHoveredBlockPosition();
179
+ }
180
+ }
181
+ setupGlobalEventListeners() {
182
+ document.addEventListener("mouseover", this.handleGlobalHover.bind(this));
183
+ document.addEventListener("mouseout", this.handleGlobalLeave.bind(this));
184
+ document.addEventListener("click", this.handleGlobalClick.bind(this));
185
+ }
186
+ handleGlobalHover(e) {
187
+ if (!this.active) {
188
+ return;
189
+ }
190
+ const blockElement = e.target.closest("[data-block]");
191
+ if (!blockElement) {
192
+ return;
193
+ }
194
+ e.stopPropagation();
195
+ this.currentHoveredBlock = blockElement;
196
+ this.sendHoveredBlockPosition();
197
+ }
198
+ handleGlobalLeave(e) {
199
+ if (!this.active) {
200
+ return;
201
+ }
202
+ const blockElement = e.target.closest("[data-block]");
203
+ if (!blockElement) {
204
+ return;
205
+ }
206
+ if (!this.overlayButtonHovered) {
207
+ this.currentHoveredBlock = null;
208
+ this.messenger.send("craftile.preview.block-leave");
209
+ }
210
+ }
211
+ handleGlobalClick(e) {
212
+ this.messenger.send("craftile.preview.click");
213
+ if (!this.active) {
214
+ return;
215
+ }
216
+ const blockElement = e.target.closest("[data-block]");
217
+ if (!blockElement) {
218
+ return;
219
+ }
220
+ e.stopPropagation();
221
+ const blockId = blockElement.getAttribute("data-block");
222
+ if (blockId) {
223
+ this.currentSelectedBlock = blockElement;
224
+ this.sendSelectedBlockPosition();
225
+ this.trackSelectedBlock();
226
+ }
227
+ }
228
+ sendHoveredBlockPosition() {
229
+ const position = this.computeElementPositioning(this.currentHoveredBlock);
230
+ this.messenger.send("craftile.preview.block-hover", {
231
+ blockRect: position.rect,
232
+ parentRect: position.parentRect,
233
+ scrollTop: position.scrollTop,
234
+ scrollLeft: position.scrollLeft,
235
+ blockId: this.currentHoveredBlock.dataset.block,
236
+ parentFlexDirection: position.parentFlexDirection
237
+ });
238
+ }
239
+ sendSelectedBlockPosition(updates = false) {
240
+ const position = this.computeElementPositioning(this.currentSelectedBlock);
241
+ this.messenger.send(updates ? "craftile.preview.update-selected-block" : "craftile.preview.block-select", {
242
+ blockRect: position.rect,
243
+ scrollTop: position.scrollTop,
244
+ scrollLeft: position.scrollLeft,
245
+ blockId: this.currentSelectedBlock.dataset.block
246
+ });
247
+ }
248
+ trackSelectedBlock() {
249
+ if (!this.currentSelectedBlock) {
250
+ return;
251
+ }
252
+ if (this.resizeObserver) {
253
+ this.resizeObserver.disconnect();
254
+ this.resizeObserver = null;
255
+ }
256
+ if (this.mutationObserver) {
257
+ this.mutationObserver.disconnect();
258
+ this.mutationObserver = null;
259
+ }
260
+ this.resizeObserver = new ResizeObserver(() => {
261
+ this.sendSelectedBlockPosition(true);
262
+ });
263
+ this.resizeObserver.observe(this.currentSelectedBlock);
264
+ this.mutationObserver = new MutationObserver(() => {
265
+ this.sendSelectedBlockPosition(true);
266
+ });
267
+ this.mutationObserver.observe(this.currentSelectedBlock, {
268
+ attributes: true,
269
+ subtree: false
270
+ });
271
+ let parent = this.currentSelectedBlock.parentElement;
272
+ while (parent) {
273
+ this.mutationObserver.observe(parent, {
274
+ childList: true,
275
+ subtree: false
276
+ });
277
+ if (parent === document.body) {
278
+ break;
279
+ }
280
+ parent = parent.parentElement;
281
+ }
282
+ }
283
+ computeElementPositioning(element) {
284
+ const rect = element.getBoundingClientRect();
285
+ const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
286
+ const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
287
+ const eldestParent = this.findEldestParentBlock(element);
288
+ const parentRect = eldestParent && eldestParent !== element ? eldestParent.getBoundingClientRect() : void 0;
289
+ const parentFlexDirection = this.getElementFlexDirection(element.parentElement);
290
+ return {
291
+ rect,
292
+ parentRect,
293
+ scrollTop,
294
+ scrollLeft,
295
+ parentFlexDirection
296
+ };
297
+ }
298
+ findEldestParentBlock(element) {
299
+ let eldestParent = null;
300
+ let parentElement = element.parentElement;
301
+ while (parentElement && parentElement !== document.body) {
302
+ if (parentElement.hasAttribute("data-block")) {
303
+ eldestParent = parentElement;
304
+ }
305
+ parentElement = parentElement.parentElement;
306
+ }
307
+ return eldestParent;
308
+ }
309
+ getElementFlexDirection(element) {
310
+ if (!element) {
311
+ return "column";
312
+ }
313
+ const style = window.getComputedStyle(element);
314
+ const flexDirection = style.display.includes("flex") ? style.flexDirection : "column";
315
+ return flexDirection === "row" || flexDirection === "row-reverse" ? "row" : "column";
316
+ }
317
+ }
318
+ class PreviewClient extends EventBus {
319
+ constructor() {
320
+ super();
321
+ __publicField(this, "messenger");
322
+ // @ts-ignore
323
+ __publicField(this, "inspector");
324
+ this.messenger = createParentMessenger(window.origin);
325
+ this.inspector = new Inspector(this.messenger);
326
+ this.initialize();
327
+ }
328
+ initialize() {
329
+ window.addEventListener("load", () => {
330
+ this.messenger.send("craftile.preview.ready", {});
331
+ });
332
+ document.addEventListener("DOMContentLoaded", () => {
333
+ this.sendPageData();
334
+ });
335
+ this.messenger.registerFallbackHandler((data) => {
336
+ const { type, payload } = data;
337
+ this.emit(type, payload);
338
+ });
339
+ }
340
+ sendPageData() {
341
+ const pageDataElement = document.getElementById("page-data");
342
+ if (!pageDataElement) {
343
+ return;
344
+ }
345
+ try {
346
+ const pageData = JSON.parse(pageDataElement.textContent || "{}");
347
+ this.messenger.send("craftile.preview.page-data", { pageData });
348
+ } catch (error) {
349
+ console.error("Failed to parse page data:", error);
350
+ }
351
+ }
352
+ }
353
+ export {
354
+ PreviewClient
355
+ };
356
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../messenger/src/index.ts","../../event-bus/src/index.ts","../src/inspector.ts","../src/client.ts"],"sourcesContent":["export interface TypedMessage<T = any> {\n type: string;\n payload: T | undefined;\n}\n\nexport class WindowMessenger<Messages extends Record<string, any>> {\n private handlers = new Map<keyof Messages, Function[]>();\n private targetWindow: Window;\n private targetOrigin: string;\n private fallbackHandler?: (data: any, event: MessageEvent) => void;\n\n constructor(targetWindow: Window, targetOrigin: string = '*') {\n this.targetWindow = targetWindow;\n this.targetOrigin = targetOrigin;\n\n window.addEventListener('message', this.handleMessage.bind(this));\n }\n\n private handleMessage(event: MessageEvent) {\n const message = event.data as TypedMessage;\n\n if (!message.type) {\n return;\n }\n\n const handlers = this.handlers.get(message.type);\n\n if (handlers) {\n handlers.forEach((handler) => handler(message.payload, event));\n } else if (this.fallbackHandler) {\n this.fallbackHandler(event.data, event);\n }\n }\n\n send<K extends keyof Messages>(type: K, payload?: Messages[K]): void {\n const message: TypedMessage<Messages[K]> = { type: type as string, payload };\n this.targetWindow.postMessage(message, this.targetOrigin);\n }\n\n listen<K extends keyof Messages>(type: K, handler: (data: Messages[K], event: MessageEvent) => void): () => void {\n if (!this.handlers.has(type)) {\n this.handlers.set(type, []);\n }\n\n this.handlers.get(type)!.push(handler);\n\n return () => {\n const handlers = this.handlers.get(type);\n if (handlers) {\n const index = handlers.indexOf(handler);\n if (index > -1) {\n handlers.splice(index, 1);\n }\n }\n };\n }\n\n registerFallbackHandler(handler: (data: any, event: MessageEvent) => void) {\n this.fallbackHandler = handler;\n }\n}\n\nexport function createIframeMessenger<T extends Record<string, any>>(iframe: HTMLIFrameElement, targetOrigin = '*') {\n return new WindowMessenger<T>(iframe.contentWindow!, targetOrigin);\n}\n\nexport function createParentMessenger<T extends Record<string, any>>(targetOrigin = '*') {\n if (window.parent === window) {\n throw new Error('Not inside an iframe');\n }\n return new WindowMessenger<T>(window.parent, targetOrigin);\n}\n","export type EventListener<T = any> = (data: T) => void;\nexport type EventMap = {\n [event: string]: any;\n};\n\n/**\n * Type-safe EventBus with generic event map support\n *\n * @template T Event map interface that defines the events and their data types\n */\nexport class EventBus<T extends EventMap = EventMap> {\n private listeners: Map<keyof T, Set<EventListener<any>>> = new Map();\n\n /**\n * Add an event listener\n *\n * @param event Event name\n * @param listener Event listener function\n *\n * @returns Cleanup function to remove the listener\n */\n on<K extends keyof T>(event: K, listener: EventListener<T[K]>): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n\n this.listeners.get(event)!.add(listener);\n\n return () => {\n this.off(event, listener);\n };\n }\n\n /**\n * Remove an event listener\n *\n * @param event Event name\n * @param listener Event listener function to remove\n */\n off<K extends keyof T>(event: K, listener: EventListener<T[K]>): void {\n const eventListeners = this.listeners.get(event);\n\n if (eventListeners) {\n eventListeners.delete(listener);\n\n if (eventListeners.size === 0) {\n this.listeners.delete(event);\n }\n }\n }\n\n /**\n * Add a one-time event listener\n *\n * @param event Event name\n * @param listener Event listener function\n */\n once<K extends keyof T>(event: K, listener: EventListener<T[K]>): void {\n const onceWrapper = (data: T[K]) => {\n listener(data);\n this.off(event, onceWrapper);\n };\n\n this.on(event, onceWrapper);\n }\n\n /**\n * Emit an event\n *\n * @param event Event name\n * @param args Event data (optional, depending on event type)\n */\n emit<K extends keyof T>(event: K, ...args: T[K] extends void ? [] : [T[K]]): void {\n const eventListeners = this.listeners.get(event);\n\n if (eventListeners) {\n const data = args[0];\n eventListeners.forEach((listener) => {\n try {\n listener(data);\n } catch (error) {\n console.error(`Error in event listener for '${String(event)}':`, error);\n }\n });\n }\n }\n\n /**\n * Remove all listeners for an event, or all listeners if no event specified\n *\n * @param event Optional event name. If not provided, removes all listeners\n */\n removeAllListeners<K extends keyof T>(event?: K): void {\n if (event) {\n this.listeners.delete(event);\n } else {\n this.listeners.clear();\n }\n }\n}\n","import type { WindowMessenger } from '@craftile/messenger';\nimport type { WindowMessages } from '@craftile/types';\n\nexport class Inspector {\n private active = true;\n private messenger: WindowMessenger<WindowMessages>;\n private currentHoveredBlock: HTMLElement | null = null;\n private currentSelectedBlock: HTMLElement | null = null;\n private overlayButtonHovered = false;\n\n private resizeObserver: ResizeObserver | null = null;\n private mutationObserver: MutationObserver | null = null;\n\n constructor(messenger: WindowMessenger<WindowMessages>) {\n this.messenger = messenger;\n\n this.messenger.listen('craftile.inspector.enable', () => this.enable());\n this.messenger.listen('craftile.inspector.disable', () => this.disable());\n this.messenger.listen('craftile.inspector.overlay-button-enter', this.handleOverlayButtonEnter.bind(this));\n this.messenger.listen('craftile.inspector.overlay-button-leave', this.handleOverlayButtonLeave.bind(this));\n\n window.addEventListener('scroll', this.handleScroll.bind(this), { passive: true });\n this.setupGlobalEventListeners();\n }\n\n enable() {\n this.active = true;\n document.body.classList.add('craftile-inspector-active');\n }\n\n disable() {\n this.active = false;\n document.body.classList.remove('craftile-inspector-active');\n this.currentHoveredBlock = null;\n this.currentSelectedBlock = null;\n this.overlayButtonHovered = false;\n }\n\n private handleOverlayButtonEnter() {\n this.overlayButtonHovered = true;\n }\n\n private handleOverlayButtonLeave(_data: { blockId: string }) {\n this.overlayButtonHovered = false;\n\n if (!this.currentHoveredBlock) {\n this.messenger.send('craftile.preview.block-leave');\n }\n }\n\n private handleScroll() {\n if (this.currentSelectedBlock) {\n this.sendSelectedBlockPosition();\n }\n\n if (this.currentHoveredBlock) {\n this.sendHoveredBlockPosition();\n }\n }\n\n private setupGlobalEventListeners() {\n document.addEventListener('mouseover', this.handleGlobalHover.bind(this));\n document.addEventListener('mouseout', this.handleGlobalLeave.bind(this));\n document.addEventListener('click', this.handleGlobalClick.bind(this));\n }\n\n private handleGlobalHover(e: Event) {\n if (!this.active) {\n return;\n }\n\n const blockElement = (e.target as Element).closest('[data-block]') as HTMLElement;\n\n if (!blockElement) {\n return;\n }\n\n e.stopPropagation();\n this.currentHoveredBlock = blockElement;\n this.sendHoveredBlockPosition();\n }\n\n private handleGlobalLeave(e: Event) {\n if (!this.active) {\n return;\n }\n\n const blockElement = (e.target as Element).closest('[data-block]') as HTMLElement;\n if (!blockElement) {\n return;\n }\n\n // Only clear overlay if button is not being hovered\n if (!this.overlayButtonHovered) {\n this.currentHoveredBlock = null;\n this.messenger.send('craftile.preview.block-leave');\n }\n }\n\n private handleGlobalClick(e: Event) {\n this.messenger.send('craftile.preview.click');\n\n if (!this.active) {\n return;\n }\n\n const blockElement = (e.target as Element).closest('[data-block]') as HTMLElement;\n if (!blockElement) {\n return;\n }\n\n e.stopPropagation();\n\n const blockId = blockElement.getAttribute('data-block');\n\n if (blockId) {\n this.currentSelectedBlock = blockElement;\n this.sendSelectedBlockPosition();\n this.trackSelectedBlock();\n }\n }\n\n private sendHoveredBlockPosition() {\n const position = this.computeElementPositioning(this.currentHoveredBlock!);\n\n this.messenger.send('craftile.preview.block-hover', {\n blockRect: position.rect,\n parentRect: position.parentRect,\n scrollTop: position.scrollTop,\n scrollLeft: position.scrollLeft,\n blockId: this.currentHoveredBlock!.dataset.block as string,\n parentFlexDirection: position.parentFlexDirection,\n });\n }\n\n private sendSelectedBlockPosition(updates: boolean = false) {\n const position = this.computeElementPositioning(this.currentSelectedBlock!);\n this.messenger.send(updates ? 'craftile.preview.update-selected-block' : 'craftile.preview.block-select', {\n blockRect: position.rect,\n scrollTop: position.scrollTop,\n scrollLeft: position.scrollLeft,\n blockId: this.currentSelectedBlock!.dataset.block as string,\n });\n }\n\n private trackSelectedBlock() {\n if (!this.currentSelectedBlock) {\n return;\n }\n\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n\n if (this.mutationObserver) {\n this.mutationObserver.disconnect();\n this.mutationObserver = null;\n }\n\n this.resizeObserver = new ResizeObserver(() => {\n this.sendSelectedBlockPosition(true);\n });\n this.resizeObserver.observe(this.currentSelectedBlock);\n\n this.mutationObserver = new MutationObserver(() => {\n this.sendSelectedBlockPosition(true);\n });\n\n this.mutationObserver.observe(this.currentSelectedBlock, {\n attributes: true,\n subtree: false,\n });\n\n // Also observe parent elements that might affect positioning\n let parent = this.currentSelectedBlock.parentElement;\n while (parent) {\n this.mutationObserver.observe(parent, {\n childList: true,\n subtree: false,\n });\n\n if (parent === document.body) {\n break;\n }\n\n parent = parent.parentElement;\n }\n }\n\n private computeElementPositioning(element: HTMLElement) {\n const rect = element.getBoundingClientRect();\n const scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;\n\n const eldestParent = this.findEldestParentBlock(element);\n const parentRect = eldestParent && eldestParent !== element ? eldestParent.getBoundingClientRect() : undefined;\n const parentFlexDirection = this.getElementFlexDirection(element.parentElement);\n\n return {\n rect,\n parentRect,\n scrollTop,\n scrollLeft,\n parentFlexDirection,\n };\n }\n\n private findEldestParentBlock(element: HTMLElement): HTMLElement | null {\n let eldestParent: HTMLElement | null = null;\n let parentElement = element.parentElement;\n\n while (parentElement && parentElement !== document.body) {\n if (parentElement.hasAttribute('data-block')) {\n eldestParent = parentElement;\n }\n parentElement = parentElement.parentElement;\n }\n\n return eldestParent;\n }\n\n private getElementFlexDirection(element: HTMLElement | null): 'row' | 'column' {\n if (!element) {\n return 'column';\n }\n\n const style = window.getComputedStyle(element);\n const flexDirection = style.display.includes('flex') ? style.flexDirection : 'column';\n\n return flexDirection === 'row' || flexDirection === 'row-reverse' ? 'row' : 'column';\n }\n}\n","import type { WindowMessages } from '@craftile/types';\nimport { createParentMessenger, WindowMessenger } from '@craftile/messenger';\nimport { EventBus } from '@craftile/event-bus';\nimport { Inspector } from './inspector';\n\nexport class PreviewClient extends EventBus {\n private messenger: WindowMessenger<WindowMessages>;\n // @ts-ignore\n private inspector: Inspector;\n\n constructor() {\n super();\n\n this.messenger = createParentMessenger(window.origin);\n this.inspector = new Inspector(this.messenger);\n\n this.initialize();\n }\n\n private initialize() {\n window.addEventListener('load', () => {\n this.messenger.send('craftile.preview.ready', {});\n });\n\n document.addEventListener('DOMContentLoaded', () => {\n this.sendPageData();\n });\n\n this.messenger.registerFallbackHandler((data: any) => {\n const { type, payload } = data;\n this.emit(type, payload);\n });\n }\n\n private sendPageData() {\n const pageDataElement = document.getElementById('page-data');\n\n if (!pageDataElement) {\n return;\n }\n\n try {\n const pageData = JSON.parse(pageDataElement.textContent || '{}');\n this.messenger.send('craftile.preview.page-data', { pageData });\n } catch (error) {\n console.error('Failed to parse page data:', error);\n }\n }\n}\n"],"names":[],"mappings":";;;AAKO,MAAM,gBAAsD;AAAA,EAMjE,YAAY,cAAsB,eAAuB,KAAK;AALtD,wDAAe,IAAA;AACf;AACA;AACA;AAGN,SAAK,eAAe;AACpB,SAAK,eAAe;AAEpB,WAAO,iBAAiB,WAAW,KAAK,cAAc,KAAK,IAAI,CAAC;AAAA,EAClE;AAAA,EAEQ,cAAc,OAAqB;AACzC,UAAM,UAAU,MAAM;AAEtB,QAAI,CAAC,QAAQ,MAAM;AACjB;AAAA,IACF;AAEA,UAAM,WAAW,KAAK,SAAS,IAAI,QAAQ,IAAI;AAE/C,QAAI,UAAU;AACZ,eAAS,QAAQ,CAAC,YAAY,QAAQ,QAAQ,SAAS,KAAK,CAAC;AAAA,IAC/D,WAAW,KAAK,iBAAiB;AAC/B,WAAK,gBAAgB,MAAM,MAAM,KAAK;AAAA,IACxC;AAAA,EACF;AAAA,EAEA,KAA+B,MAAS,SAA6B;AACnE,UAAM,UAAqC,EAAE,MAAsB,QAAA;AACnE,SAAK,aAAa,YAAY,SAAS,KAAK,YAAY;AAAA,EAC1D;AAAA,EAEA,OAAiC,MAAS,SAAuE;AAC/G,QAAI,CAAC,KAAK,SAAS,IAAI,IAAI,GAAG;AAC5B,WAAK,SAAS,IAAI,MAAM,CAAA,CAAE;AAAA,IAC5B;AAEA,SAAK,SAAS,IAAI,IAAI,EAAG,KAAK,OAAO;AAErC,WAAO,MAAM;AACX,YAAM,WAAW,KAAK,SAAS,IAAI,IAAI;AACvC,UAAI,UAAU;AACZ,cAAM,QAAQ,SAAS,QAAQ,OAAO;AACtC,YAAI,QAAQ,IAAI;AACd,mBAAS,OAAO,OAAO,CAAC;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,wBAAwB,SAAmD;AACzE,SAAK,kBAAkB;AAAA,EACzB;AACF;AAMO,SAAS,sBAAqD,eAAe,KAAK;AACvF,MAAI,OAAO,WAAW,QAAQ;AAC5B,UAAM,IAAI,MAAM,sBAAsB;AAAA,EACxC;AACA,SAAO,IAAI,gBAAmB,OAAO,QAAQ,YAAY;AAC3D;AC7DO,MAAM,SAAwC;AAAA,EAA9C;AACG,yDAAuD,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU/D,GAAsB,OAAU,UAA2C;AACzE,QAAI,CAAC,KAAK,UAAU,IAAI,KAAK,GAAG;AAC9B,WAAK,UAAU,IAAI,OAAO,oBAAI,KAAK;AAAA,IACrC;AAEA,SAAK,UAAU,IAAI,KAAK,EAAG,IAAI,QAAQ;AAEvC,WAAO,MAAM;AACX,WAAK,IAAI,OAAO,QAAQ;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAuB,OAAU,UAAqC;AACpE,UAAM,iBAAiB,KAAK,UAAU,IAAI,KAAK;AAE/C,QAAI,gBAAgB;AAClB,qBAAe,OAAO,QAAQ;AAE9B,UAAI,eAAe,SAAS,GAAG;AAC7B,aAAK,UAAU,OAAO,KAAK;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,KAAwB,OAAU,UAAqC;AACrE,UAAM,cAAc,CAAC,SAAe;AAClC,eAAS,IAAI;AACb,WAAK,IAAI,OAAO,WAAW;AAAA,IAC7B;AAEA,SAAK,GAAG,OAAO,WAAW;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,KAAwB,UAAa,MAA6C;AAChF,UAAM,iBAAiB,KAAK,UAAU,IAAI,KAAK;AAE/C,QAAI,gBAAgB;AAClB,YAAM,OAAO,KAAK,CAAC;AACnB,qBAAe,QAAQ,CAAC,aAAa;AACnC,YAAI;AACF,mBAAS,IAAI;AAAA,QACf,SAAS,OAAO;AACd,kBAAQ,MAAM,gCAAgC,OAAO,KAAK,CAAC,MAAM,KAAK;AAAA,QACxE;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,mBAAsC,OAAiB;AACrD,QAAI,OAAO;AACT,WAAK,UAAU,OAAO,KAAK;AAAA,IAC7B,OAAO;AACL,WAAK,UAAU,MAAA;AAAA,IACjB;AAAA,EACF;AACF;AChGO,MAAM,UAAU;AAAA,EAUrB,YAAY,WAA4C;AAThD,kCAAS;AACT;AACA,+CAA0C;AAC1C,gDAA2C;AAC3C,gDAAuB;AAEvB,0CAAwC;AACxC,4CAA4C;AAGlD,SAAK,YAAY;AAEjB,SAAK,UAAU,OAAO,6BAA6B,MAAM,KAAK,QAAQ;AACtE,SAAK,UAAU,OAAO,8BAA8B,MAAM,KAAK,SAAS;AACxE,SAAK,UAAU,OAAO,2CAA2C,KAAK,yBAAyB,KAAK,IAAI,CAAC;AACzG,SAAK,UAAU,OAAO,2CAA2C,KAAK,yBAAyB,KAAK,IAAI,CAAC;AAEzG,WAAO,iBAAiB,UAAU,KAAK,aAAa,KAAK,IAAI,GAAG,EAAE,SAAS,MAAM;AACjF,SAAK,0BAAA;AAAA,EACP;AAAA,EAEA,SAAS;AACP,SAAK,SAAS;AACd,aAAS,KAAK,UAAU,IAAI,2BAA2B;AAAA,EACzD;AAAA,EAEA,UAAU;AACR,SAAK,SAAS;AACd,aAAS,KAAK,UAAU,OAAO,2BAA2B;AAC1D,SAAK,sBAAsB;AAC3B,SAAK,uBAAuB;AAC5B,SAAK,uBAAuB;AAAA,EAC9B;AAAA,EAEQ,2BAA2B;AACjC,SAAK,uBAAuB;AAAA,EAC9B;AAAA,EAEQ,yBAAyB,OAA4B;AAC3D,SAAK,uBAAuB;AAE5B,QAAI,CAAC,KAAK,qBAAqB;AAC7B,WAAK,UAAU,KAAK,8BAA8B;AAAA,IACpD;AAAA,EACF;AAAA,EAEQ,eAAe;AACrB,QAAI,KAAK,sBAAsB;AAC7B,WAAK,0BAAA;AAAA,IACP;AAEA,QAAI,KAAK,qBAAqB;AAC5B,WAAK,yBAAA;AAAA,IACP;AAAA,EACF;AAAA,EAEQ,4BAA4B;AAClC,aAAS,iBAAiB,aAAa,KAAK,kBAAkB,KAAK,IAAI,CAAC;AACxE,aAAS,iBAAiB,YAAY,KAAK,kBAAkB,KAAK,IAAI,CAAC;AACvE,aAAS,iBAAiB,SAAS,KAAK,kBAAkB,KAAK,IAAI,CAAC;AAAA,EACtE;AAAA,EAEQ,kBAAkB,GAAU;AAClC,QAAI,CAAC,KAAK,QAAQ;AAChB;AAAA,IACF;AAEA,UAAM,eAAgB,EAAE,OAAmB,QAAQ,cAAc;AAEjE,QAAI,CAAC,cAAc;AACjB;AAAA,IACF;AAEA,MAAE,gBAAA;AACF,SAAK,sBAAsB;AAC3B,SAAK,yBAAA;AAAA,EACP;AAAA,EAEQ,kBAAkB,GAAU;AAClC,QAAI,CAAC,KAAK,QAAQ;AAChB;AAAA,IACF;AAEA,UAAM,eAAgB,EAAE,OAAmB,QAAQ,cAAc;AACjE,QAAI,CAAC,cAAc;AACjB;AAAA,IACF;AAGA,QAAI,CAAC,KAAK,sBAAsB;AAC9B,WAAK,sBAAsB;AAC3B,WAAK,UAAU,KAAK,8BAA8B;AAAA,IACpD;AAAA,EACF;AAAA,EAEQ,kBAAkB,GAAU;AAClC,SAAK,UAAU,KAAK,wBAAwB;AAE5C,QAAI,CAAC,KAAK,QAAQ;AAChB;AAAA,IACF;AAEA,UAAM,eAAgB,EAAE,OAAmB,QAAQ,cAAc;AACjE,QAAI,CAAC,cAAc;AACjB;AAAA,IACF;AAEA,MAAE,gBAAA;AAEF,UAAM,UAAU,aAAa,aAAa,YAAY;AAEtD,QAAI,SAAS;AACX,WAAK,uBAAuB;AAC5B,WAAK,0BAAA;AACL,WAAK,mBAAA;AAAA,IACP;AAAA,EACF;AAAA,EAEQ,2BAA2B;AACjC,UAAM,WAAW,KAAK,0BAA0B,KAAK,mBAAoB;AAEzE,SAAK,UAAU,KAAK,gCAAgC;AAAA,MAClD,WAAW,SAAS;AAAA,MACpB,YAAY,SAAS;AAAA,MACrB,WAAW,SAAS;AAAA,MACpB,YAAY,SAAS;AAAA,MACrB,SAAS,KAAK,oBAAqB,QAAQ;AAAA,MAC3C,qBAAqB,SAAS;AAAA,IAAA,CAC/B;AAAA,EACH;AAAA,EAEQ,0BAA0B,UAAmB,OAAO;AAC1D,UAAM,WAAW,KAAK,0BAA0B,KAAK,oBAAqB;AAC1E,SAAK,UAAU,KAAK,UAAU,2CAA2C,iCAAiC;AAAA,MACxG,WAAW,SAAS;AAAA,MACpB,WAAW,SAAS;AAAA,MACpB,YAAY,SAAS;AAAA,MACrB,SAAS,KAAK,qBAAsB,QAAQ;AAAA,IAAA,CAC7C;AAAA,EACH;AAAA,EAEQ,qBAAqB;AAC3B,QAAI,CAAC,KAAK,sBAAsB;AAC9B;AAAA,IACF;AAEA,QAAI,KAAK,gBAAgB;AACvB,WAAK,eAAe,WAAA;AACpB,WAAK,iBAAiB;AAAA,IACxB;AAEA,QAAI,KAAK,kBAAkB;AACzB,WAAK,iBAAiB,WAAA;AACtB,WAAK,mBAAmB;AAAA,IAC1B;AAEA,SAAK,iBAAiB,IAAI,eAAe,MAAM;AAC7C,WAAK,0BAA0B,IAAI;AAAA,IACrC,CAAC;AACD,SAAK,eAAe,QAAQ,KAAK,oBAAoB;AAErD,SAAK,mBAAmB,IAAI,iBAAiB,MAAM;AACjD,WAAK,0BAA0B,IAAI;AAAA,IACrC,CAAC;AAED,SAAK,iBAAiB,QAAQ,KAAK,sBAAsB;AAAA,MACvD,YAAY;AAAA,MACZ,SAAS;AAAA,IAAA,CACV;AAGD,QAAI,SAAS,KAAK,qBAAqB;AACvC,WAAO,QAAQ;AACb,WAAK,iBAAiB,QAAQ,QAAQ;AAAA,QACpC,WAAW;AAAA,QACX,SAAS;AAAA,MAAA,CACV;AAED,UAAI,WAAW,SAAS,MAAM;AAC5B;AAAA,MACF;AAEA,eAAS,OAAO;AAAA,IAClB;AAAA,EACF;AAAA,EAEQ,0BAA0B,SAAsB;AACtD,UAAM,OAAO,QAAQ,sBAAA;AACrB,UAAM,YAAY,OAAO,eAAe,SAAS,gBAAgB;AACjE,UAAM,aAAa,OAAO,eAAe,SAAS,gBAAgB;AAElE,UAAM,eAAe,KAAK,sBAAsB,OAAO;AACvD,UAAM,aAAa,gBAAgB,iBAAiB,UAAU,aAAa,0BAA0B;AACrG,UAAM,sBAAsB,KAAK,wBAAwB,QAAQ,aAAa;AAE9E,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEQ,sBAAsB,SAA0C;AACtE,QAAI,eAAmC;AACvC,QAAI,gBAAgB,QAAQ;AAE5B,WAAO,iBAAiB,kBAAkB,SAAS,MAAM;AACvD,UAAI,cAAc,aAAa,YAAY,GAAG;AAC5C,uBAAe;AAAA,MACjB;AACA,sBAAgB,cAAc;AAAA,IAChC;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,wBAAwB,SAA+C;AAC7E,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,OAAO,iBAAiB,OAAO;AAC7C,UAAM,gBAAgB,MAAM,QAAQ,SAAS,MAAM,IAAI,MAAM,gBAAgB;AAE7E,WAAO,kBAAkB,SAAS,kBAAkB,gBAAgB,QAAQ;AAAA,EAC9E;AACF;ACnOO,MAAM,sBAAsB,SAAS;AAAA,EAK1C,cAAc;AACZ,UAAA;AALM;AAEA;AAAA;AAKN,SAAK,YAAY,sBAAsB,OAAO,MAAM;AACpD,SAAK,YAAY,IAAI,UAAU,KAAK,SAAS;AAE7C,SAAK,WAAA;AAAA,EACP;AAAA,EAEQ,aAAa;AACnB,WAAO,iBAAiB,QAAQ,MAAM;AACpC,WAAK,UAAU,KAAK,0BAA0B,CAAA,CAAE;AAAA,IAClD,CAAC;AAED,aAAS,iBAAiB,oBAAoB,MAAM;AAClD,WAAK,aAAA;AAAA,IACP,CAAC;AAED,SAAK,UAAU,wBAAwB,CAAC,SAAc;AACpD,YAAM,EAAE,MAAM,QAAA,IAAY;AAC1B,WAAK,KAAK,MAAM,OAAO;AAAA,IACzB,CAAC;AAAA,EACH;AAAA,EAEQ,eAAe;AACrB,UAAM,kBAAkB,SAAS,eAAe,WAAW;AAE3D,QAAI,CAAC,iBAAiB;AACpB;AAAA,IACF;AAEA,QAAI;AACF,YAAM,WAAW,KAAK,MAAM,gBAAgB,eAAe,IAAI;AAC/D,WAAK,UAAU,KAAK,8BAA8B,EAAE,UAAU;AAAA,IAChE,SAAS,OAAO;AACd,cAAQ,MAAM,8BAA8B,KAAK;AAAA,IACnD;AAAA,EACF;AACF;"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@craftile/preview-client",
3
+ "version": "0.1.0",
4
+ "description": "Browser client for Craftile editor preview iframe functionality",
5
+ "keywords": [
6
+ "craftile",
7
+ "editor",
8
+ "preview",
9
+ "iframe",
10
+ "blocks"
11
+ ],
12
+ "license": "MIT",
13
+ "authors": [
14
+ {
15
+ "name": "Eldo Magan",
16
+ "email": "magan.eldo@gmail.com"
17
+ }
18
+ ],
19
+ "type": "module",
20
+ "main": "dist/index.cjs",
21
+ "module": "dist/index.js",
22
+ "types": "dist/index.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "types": "./dist/index.d.ts",
26
+ "source": "./src/index.ts",
27
+ "import": "./dist/index.js",
28
+ "require": "./dist/index.cjs"
29
+ }
30
+ },
31
+ "files": [
32
+ "dist"
33
+ ],
34
+ "devDependencies": {
35
+ "typescript": "^5.8.4",
36
+ "vite": "^7.0.0",
37
+ "vite-plugin-dts": "^4.3.0",
38
+ "@craftile/event-bus": "0.1.0",
39
+ "@craftile/messenger": "0.1.0",
40
+ "@craftile/types": "0.1.0"
41
+ },
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "git+https://github.com/craftile/editor.git"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "scripts": {
50
+ "dev": "vite build --watch",
51
+ "build": "rm -rf dist && tsc && vite build",
52
+ "preview": "vite preview"
53
+ }
54
+ }