@salesforce/ui-bundle 10.0.0 → 10.2.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.
@@ -1,830 +0,0 @@
1
- /**
2
- * Design Mode Interactions (Bundled)
3
- *
4
- * This file is auto-generated by esbuild from the modular design mode interactions files.
5
- * Do not edit this file directly - edit the modules in src/design/interactions/
6
- */
7
- (function () {
8
-
9
- "use strict";
10
- (() => {
11
- var __defProp = Object.defineProperty;
12
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
14
-
15
- // src/design/interactions/utils/sourceUtils.ts
16
- function parseOptionalInt(value) {
17
- if (value === null || value === void 0 || value === "") {
18
- return null;
19
- }
20
- const parsed = Number.parseInt(String(value), 10);
21
- return Number.isFinite(parsed) ? parsed : null;
22
- }
23
- function parseSourceFileAttribute(value) {
24
- const match = /^(.*):(\d+):(\d+)$/.exec(value);
25
- if (!match) {
26
- return { fileName: value, lineNumber: null, columnNumber: null };
27
- }
28
- return {
29
- fileName: match[1] ?? value,
30
- lineNumber: parseOptionalInt(match[2]),
31
- columnNumber: parseOptionalInt(match[3])
32
- };
33
- }
34
- function getSourceFromDataAttributes(element) {
35
- if (!element) {
36
- return null;
37
- }
38
- const source = element.getAttribute("data-source-file") || null;
39
- if (!source) {
40
- return null;
41
- }
42
- return parseSourceFileAttribute(source);
43
- }
44
- function findElementsBySourceLocation(location) {
45
- const results = [];
46
- const elements = document.querySelectorAll("[data-source-file]");
47
- for (const el of elements) {
48
- const elSource = getSourceFromDataAttributes(el);
49
- if (elSource && elSource.fileName === location.fileName && elSource.lineNumber === location.lineNumber && elSource.columnNumber === location.columnNumber) {
50
- results.push(el);
51
- }
52
- }
53
- return results;
54
- }
55
- function parseSourceLocation(sl) {
56
- if (!sl || typeof sl !== "object") return void 0;
57
- const obj = sl;
58
- return {
59
- fileName: String(obj.sourceFile ?? ""),
60
- lineNumber: typeof obj.lineNumber === "number" ? obj.lineNumber : null,
61
- columnNumber: typeof obj.columnNumber === "number" ? obj.columnNumber : null
62
- };
63
- }
64
- function getLabelFromSource(element) {
65
- if (!element) {
66
- return "";
67
- }
68
- const source = element.getAttribute("data-source-file");
69
- if (!source) {
70
- return element.tagName ? element.tagName.toLowerCase() : "";
71
- }
72
- const { fileName } = parseSourceFileAttribute(source);
73
- const parts = fileName.split(/[/\\]/);
74
- const baseName = parts[parts.length - 1] || fileName;
75
- console.log("baseName", baseName);
76
- return baseName;
77
- }
78
-
79
- // src/design/interactions/editableManager.ts
80
- var TEXT_TAGS = ["H1", "H2", "H3", "H4", "H5", "H6", "P", "SPAN", "A", "BUTTON", "LABEL"];
81
- var EditableManager = class {
82
- constructor(communicationManager) {
83
- __publicField(this, "communicationManager");
84
- __publicField(this, "boundHandleBlur");
85
- __publicField(this, "boundHandleKeydown");
86
- __publicField(this, "boundHandleInput");
87
- __publicField(this, "editableGroup");
88
- this.communicationManager = communicationManager;
89
- this.boundHandleBlur = this._handleBlur.bind(this);
90
- this.boundHandleKeydown = this._handleKeydown.bind(this);
91
- this.boundHandleInput = this._handleInput.bind(this);
92
- this.editableGroup = [];
93
- }
94
- makeEditableIfText(element) {
95
- if (!this._isTextElement(element)) {
96
- return;
97
- }
98
- const source = getSourceFromDataAttributes(element);
99
- const siblings = source ? findElementsBySourceLocation(source) : [];
100
- const others = siblings.filter((el) => el !== element);
101
- this.editableGroup = [element, ...others];
102
- for (const el of this.editableGroup) {
103
- el.dataset.originalText = el.textContent ?? "";
104
- }
105
- element.contentEditable = "true";
106
- element.addEventListener("blur", this.boundHandleBlur);
107
- element.addEventListener("keydown", this.boundHandleKeydown);
108
- element.addEventListener("input", this.boundHandleInput);
109
- }
110
- removeEditable(element) {
111
- if (element.contentEditable === "true") {
112
- element.contentEditable = "false";
113
- }
114
- element.removeEventListener("blur", this.boundHandleBlur);
115
- element.removeEventListener("keydown", this.boundHandleKeydown);
116
- element.removeEventListener("input", this.boundHandleInput);
117
- for (const el of this.editableGroup) {
118
- delete el.dataset.originalText;
119
- }
120
- this.editableGroup = [];
121
- }
122
- _isTextElement(element) {
123
- return TEXT_TAGS.includes(element.tagName) && (element.textContent ?? "").trim().length > 0 && element.dataset.textType === "static";
124
- }
125
- _handleInput(e) {
126
- const primary = e.target;
127
- const text = primary.textContent ?? "";
128
- for (let i = 1; i < this.editableGroup.length; i++) {
129
- this.editableGroup[i].textContent = text;
130
- }
131
- }
132
- _handleBlur(e) {
133
- const element = e.target;
134
- const newText = element.textContent ?? "";
135
- const originalText = element.dataset.originalText ?? "";
136
- if (newText !== originalText) {
137
- for (const el of this.editableGroup) {
138
- el.dataset.originalText = newText;
139
- }
140
- if (this.communicationManager) {
141
- this.communicationManager.notifyTextChange(element, originalText, newText);
142
- }
143
- }
144
- this.removeEditable(element);
145
- }
146
- _handleKeydown(e) {
147
- const element = e.target;
148
- if (e.key === "Enter" && !e.shiftKey) {
149
- e.preventDefault();
150
- element.blur();
151
- }
152
- if (e.key === "Escape") {
153
- for (const el of this.editableGroup) {
154
- if (el.dataset.originalText) {
155
- el.textContent = el.dataset.originalText;
156
- }
157
- }
158
- element.blur();
159
- }
160
- }
161
- };
162
-
163
- // src/design/interactions/utils/cssUtils.ts
164
- function getElementStyles(element) {
165
- if (!element) return {};
166
- const computed = window.getComputedStyle(element);
167
- const inlineStyle = element.style;
168
- const prop = (name, fallback) => ({
169
- inline: inlineStyle[name] || (fallback ? inlineStyle[fallback] : "") || "",
170
- computed: (fallback ? computed[fallback] : computed[name]) || ""
171
- });
172
- const box = (shorthand, top, right, bottom, left) => {
173
- let inlineValue = inlineStyle[shorthand] || "";
174
- if (!inlineValue) {
175
- const iT = inlineStyle[top] || "", iR = inlineStyle[right] || "", iB = inlineStyle[bottom] || "", iL = inlineStyle[left] || "";
176
- if (iT || iR || iB || iL) {
177
- inlineValue = `${iT || "0px"} ${iR || "0px"} ${iB || "0px"} ${iL || "0px"}`;
178
- }
179
- }
180
- return {
181
- inline: inlineValue,
182
- computed: `${computed[top] || ""} ${computed[right] || ""} ${computed[bottom] || ""} ${computed[left] || ""}`
183
- };
184
- };
185
- return {
186
- width: prop("width"),
187
- minWidth: prop("minWidth"),
188
- maxWidth: prop("maxWidth"),
189
- height: prop("height"),
190
- minHeight: prop("minHeight"),
191
- maxHeight: prop("maxHeight"),
192
- overflow: prop("overflow"),
193
- padding: box("padding", "paddingTop", "paddingRight", "paddingBottom", "paddingLeft"),
194
- margin: box("margin", "marginTop", "marginRight", "marginBottom", "marginLeft"),
195
- backgroundColor: prop("backgroundColor"),
196
- borderWidth: box(
197
- "borderWidth",
198
- "borderTopWidth",
199
- "borderRightWidth",
200
- "borderBottomWidth",
201
- "borderLeftWidth"
202
- ),
203
- borderStyle: prop("borderStyle", "borderTopStyle"),
204
- borderColor: prop("borderColor", "borderTopColor"),
205
- borderRadius: box(
206
- "borderRadius",
207
- "borderTopLeftRadius",
208
- "borderTopRightRadius",
209
- "borderBottomRightRadius",
210
- "borderBottomLeftRadius"
211
- ),
212
- color: prop("color"),
213
- fontFamily: prop("fontFamily"),
214
- fontSize: prop("fontSize"),
215
- fontWeight: prop("fontWeight"),
216
- fontStyle: prop("fontStyle"),
217
- lineHeight: prop("lineHeight"),
218
- letterSpacing: prop("letterSpacing"),
219
- textAlign: prop("textAlign"),
220
- textDecoration: prop("textDecoration", "textDecorationLine"),
221
- textTransform: prop("textTransform")
222
- };
223
- }
224
-
225
- // src/design/interactions/communicationManager.ts
226
- function getMediaInfo(element) {
227
- switch (element.tagName) {
228
- case "IMG": {
229
- const img = element;
230
- return {
231
- tag: "img",
232
- src: img.getAttribute("src") ?? "",
233
- alt: img.getAttribute("alt") ?? "",
234
- width: img.getAttribute("width") ?? "",
235
- height: img.getAttribute("height") ?? ""
236
- };
237
- }
238
- default:
239
- return void 0;
240
- }
241
- }
242
- var CommunicationManager = class {
243
- constructor() {
244
- }
245
- /**
246
- * Notify the extension about a selected component
247
- * @param element - The selected element
248
- */
249
- notifyComponentSelected(element) {
250
- const label = getLabelFromSource(element);
251
- const wasSelected = element.classList.contains("design-mode-selected");
252
- if (wasSelected) {
253
- element.classList.remove("design-mode-selected");
254
- }
255
- const styles = getElementStyles(element);
256
- if (wasSelected) {
257
- element.classList.add("design-mode-selected");
258
- }
259
- const debugSource = getSourceFromDataAttributes(element);
260
- const textType = element.dataset?.textType ?? "none";
261
- const hasNonEditableText = TEXT_TAGS.includes(element.tagName) && (textType === "dynamic" || textType === "mixed");
262
- const media = getMediaInfo(element);
263
- try {
264
- if (window.parent !== window) {
265
- window.parent.postMessage(
266
- {
267
- type: "component-selected",
268
- component: {
269
- name: label,
270
- tagName: element.tagName,
271
- styles: {
272
- ...styles
273
- },
274
- debugSource,
275
- hasNonEditableText,
276
- ...media ? { media } : {}
277
- }
278
- },
279
- "*"
280
- );
281
- }
282
- } catch (error) {
283
- console.log("Could not notify extension:", error);
284
- }
285
- window.selectedComponentInfo = {
286
- name: label,
287
- element,
288
- tagName: element.tagName
289
- };
290
- }
291
- /**
292
- * Notify the extension about a text change
293
- * @param element - The element that changed
294
- * @param originalText - The original text
295
- * @param newText - The new text
296
- */
297
- notifyTextChange(element, originalText, newText) {
298
- const label = getLabelFromSource(element);
299
- const debugSource = getSourceFromDataAttributes(element);
300
- try {
301
- if (window.parent !== window) {
302
- window.parent.postMessage(
303
- {
304
- type: "text-changed",
305
- change: {
306
- componentName: label,
307
- tagName: element.tagName,
308
- originalText,
309
- newText,
310
- debugSource
311
- }
312
- },
313
- "*"
314
- );
315
- }
316
- } catch (error) {
317
- console.log("Could not notify extension about text change:", error);
318
- }
319
- }
320
- /**
321
- * Notify the parent window that interactions initialization is complete
322
- */
323
- notifyInitializationComplete() {
324
- try {
325
- if (typeof window !== "undefined" && window.parent && window.parent !== window) {
326
- window.parent.postMessage(
327
- {
328
- type: "interactions-initialized"
329
- },
330
- "*"
331
- );
332
- }
333
- } catch (error) {
334
- const err = error;
335
- console.warn("Could not send initialization message to parent:", err.message);
336
- }
337
- }
338
- };
339
-
340
- // src/design/interactions/componentMatcher.ts
341
- var ComponentMatcher = class {
342
- constructor(options = {}) {
343
- __publicField(this, "allowlist");
344
- this.allowlist = options.allowlist ?? [];
345
- }
346
- /**
347
- * Check whether an element contains compile-time source metadata attributes.
348
- * @param element - The element to check
349
- * @returns True if the data-source-file attribute is present
350
- */
351
- hasSourceMetadata(element) {
352
- if (!element) {
353
- return false;
354
- }
355
- return element.hasAttribute("data-source-file");
356
- }
357
- matchesList(element, selectors) {
358
- return selectors.some((selector) => element.matches(selector));
359
- }
360
- /**
361
- * Checks if a label represents a component name (not a fallback like tag name, ID, or text content)
362
- * @param label - The label to check
363
- * @param tagName - The element's tag name (lowercase)
364
- * @returns True if the label is a component name
365
- */
366
- isComponentNameLabel(label, tagName) {
367
- return label !== tagName && !label.includes("#") && !label.includes("(") && !label.includes('"');
368
- }
369
- /**
370
- * Check if an element is highlightable.
371
- * @param element - The element to check
372
- * @returns True if the element should be highlighted
373
- */
374
- isHighlightableElement(element) {
375
- if (!element || element === document.body || element === document.documentElement) {
376
- return false;
377
- }
378
- if (!this.hasSourceMetadata(element)) {
379
- return false;
380
- }
381
- if (this.allowlist.length > 0) {
382
- return this.matchesList(element, this.allowlist);
383
- }
384
- return true;
385
- }
386
- /**
387
- * Find the nearest highlightable element by walking up the DOM tree
388
- * @param target - The target element
389
- * @returns The highlightable element or null
390
- */
391
- findHighlightableElement(target) {
392
- if (!target || target === document.body || target === document.documentElement) {
393
- return null;
394
- }
395
- const closest = typeof target.closest === "function" ? target.closest("[data-source-file]") : null;
396
- if (closest && closest !== document.body && closest !== document.documentElement && this.isHighlightableElement(closest)) {
397
- return closest;
398
- }
399
- let current = target;
400
- while (current && current !== document.body && current !== document.documentElement) {
401
- if (this.isHighlightableElement(current)) {
402
- return current;
403
- }
404
- current = current.parentElement;
405
- }
406
- return null;
407
- }
408
- };
409
-
410
- // src/design/interactions/eventHandlers.ts
411
- var EventHandlers = class {
412
- constructor(isInteractionsActive, componentMatcher, styleManager, editableManager, communicationManager) {
413
- __publicField(this, "isInteractionsActive");
414
- __publicField(this, "componentMatcher");
415
- __publicField(this, "styleManager");
416
- __publicField(this, "editableManager");
417
- __publicField(this, "communicationManager");
418
- __publicField(this, "currentHighlightedElements");
419
- __publicField(this, "selectedElement");
420
- __publicField(this, "selectedElements");
421
- this.isInteractionsActive = isInteractionsActive;
422
- this.componentMatcher = componentMatcher;
423
- this.styleManager = styleManager;
424
- this.editableManager = editableManager;
425
- this.communicationManager = communicationManager;
426
- this.currentHighlightedElements = [];
427
- this.selectedElement = null;
428
- this.selectedElements = [];
429
- this.handleMouseOver = this.handleMouseOver.bind(this);
430
- this.handleMouseLeave = this.handleMouseLeave.bind(this);
431
- this.handleClick = this.handleClick.bind(this);
432
- }
433
- _findHighlightableElement(target) {
434
- return this.componentMatcher.findHighlightableElement(target);
435
- }
436
- handleMouseOver(e) {
437
- if (!this.isInteractionsActive()) {
438
- return;
439
- }
440
- e.stopPropagation();
441
- const target = e.target;
442
- if (target.nodeType !== 1 || target.tagName === "HTML" || target.tagName === "BODY") {
443
- return;
444
- }
445
- const element = this._findHighlightableElement(target);
446
- if (!element) {
447
- return;
448
- }
449
- if (this.currentHighlightedElements.includes(element) || this.selectedElement && this.selectedElement === element) {
450
- return;
451
- }
452
- if (this.currentHighlightedElements.length > 0 && !this.currentHighlightedElements[0].classList.contains("design-mode-selected")) {
453
- this.styleManager.unhighlightElements(this.currentHighlightedElements);
454
- this.currentHighlightedElements = [];
455
- }
456
- const allElements = findElementsBySourceLocation(getSourceFromDataAttributes(element));
457
- this.styleManager.highlightElements(allElements);
458
- this.currentHighlightedElements = allElements;
459
- }
460
- handleMouseLeave() {
461
- if (!this.isInteractionsActive()) {
462
- return;
463
- }
464
- if (this.currentHighlightedElements.length > 0 && !this.currentHighlightedElements[0].classList.contains("design-mode-selected")) {
465
- this.styleManager.unhighlightElements(this.currentHighlightedElements);
466
- this.currentHighlightedElements = [];
467
- }
468
- }
469
- handleClick(e) {
470
- if (!this.isInteractionsActive()) {
471
- return;
472
- }
473
- e.preventDefault();
474
- e.stopPropagation();
475
- const target = e.target;
476
- if (target.nodeType !== 1 || target.tagName === "HTML" || target.tagName === "BODY") {
477
- return;
478
- }
479
- const element = this._findHighlightableElement(target);
480
- if (!element) {
481
- return;
482
- }
483
- if (this.selectedElement && this.selectedElement === element) {
484
- return;
485
- }
486
- if (this.selectedElement) {
487
- this.styleManager.deselectElements(this.selectedElements);
488
- this.editableManager.removeEditable(this.selectedElement);
489
- }
490
- if (this.currentHighlightedElements.length > 0) {
491
- this.styleManager.unhighlightElements(this.currentHighlightedElements);
492
- this.currentHighlightedElements = [];
493
- }
494
- this.selectedElement = element;
495
- const allElements = findElementsBySourceLocation(getSourceFromDataAttributes(element));
496
- this.selectedElements = allElements;
497
- this.styleManager.selectElements(allElements);
498
- this.editableManager.makeEditableIfText(element);
499
- this.communicationManager.notifyComponentSelected(element);
500
- }
501
- clearAll() {
502
- if (this.currentHighlightedElements.length > 0) {
503
- this.styleManager.unhighlightElements(this.currentHighlightedElements);
504
- this.currentHighlightedElements = [];
505
- }
506
- if (this.selectedElement) {
507
- this.styleManager.deselectElements(this.selectedElements);
508
- this.editableManager.removeEditable(this.selectedElement);
509
- this.selectedElement = null;
510
- this.selectedElements = [];
511
- }
512
- }
513
- getSelectedElement() {
514
- return this.selectedElement;
515
- }
516
- };
517
-
518
- // src/design/interactions/styleManager.ts
519
- var StyleManager = class {
520
- constructor() {
521
- __publicField(this, "styleId");
522
- __publicField(this, "stylesAdded");
523
- this.styleId = "design-mode-styles";
524
- this.stylesAdded = false;
525
- }
526
- /**
527
- * Add CSS styles for highlighting to the document
528
- */
529
- addHighlightStyles() {
530
- if (this.stylesAdded) {
531
- return;
532
- }
533
- const style = document.createElement("style");
534
- style.id = this.styleId;
535
- style.textContent = this._getStyles();
536
- document.head.appendChild(style);
537
- this.stylesAdded = true;
538
- }
539
- /**
540
- * Remove highlight styles from the document
541
- */
542
- removeHighlightStyles() {
543
- const style = document.getElementById(this.styleId);
544
- if (style) {
545
- style.remove();
546
- this.stylesAdded = false;
547
- }
548
- }
549
- /**
550
- * Get the CSS styles for highlighting
551
- * @private
552
- * @returns CSS styles
553
- */
554
- _getStyles() {
555
- return `
556
- .design-mode-highlight {
557
- outline: 4px dashed #007acc !important;
558
- outline-offset: -4px !important;
559
- transition: all 0.2s ease !important;
560
- position: relative !important;
561
- cursor: pointer !important;
562
- }
563
- .design-mode-selected {
564
- outline: 5px dashed #ff6b35 !important;
565
- outline-offset: -5px !important;
566
- position: relative !important;
567
- }
568
- `;
569
- }
570
- /**
571
- * Apply highlight class to one or more elements
572
- * @param elements - The elements to highlight
573
- */
574
- highlightElements(elements) {
575
- for (const el of elements) {
576
- el.classList.add("design-mode-highlight");
577
- }
578
- }
579
- /**
580
- * Remove highlight class from one or more elements
581
- * @param elements - The elements to unhighlight
582
- */
583
- unhighlightElements(elements) {
584
- for (const el of elements) {
585
- el.classList.remove("design-mode-highlight");
586
- }
587
- }
588
- /**
589
- * Apply selected class to one or more elements
590
- * @param elements - The elements to select
591
- */
592
- selectElements(elements) {
593
- for (const el of elements) {
594
- el.classList.add("design-mode-selected");
595
- }
596
- }
597
- /**
598
- * Remove selected class from one or more elements
599
- * @param elements - The elements to deselect
600
- */
601
- deselectElements(elements) {
602
- for (const el of elements) {
603
- el.classList.remove("design-mode-selected");
604
- }
605
- }
606
- };
607
-
608
- // src/design/interactions/interactionsController.ts
609
- var mediaAppliers = {
610
- img: (el, attrs) => {
611
- const img = el;
612
- if (attrs.src !== void 0) img.setAttribute("src", attrs.src);
613
- if (attrs.alt !== void 0) img.setAttribute("alt", attrs.alt);
614
- if (attrs.width !== void 0) {
615
- if (attrs.width === "") img.removeAttribute("width");
616
- else img.setAttribute("width", attrs.width);
617
- }
618
- if (attrs.height !== void 0) {
619
- if (attrs.height === "") img.removeAttribute("height");
620
- else img.setAttribute("height", attrs.height);
621
- }
622
- }
623
- };
624
- var InteractionsController = class {
625
- constructor(enabled = true) {
626
- __publicField(this, "enabled");
627
- __publicField(this, "isActive");
628
- __publicField(this, "componentMatcher");
629
- __publicField(this, "styleManager");
630
- __publicField(this, "communicationManager");
631
- __publicField(this, "editableManager");
632
- __publicField(this, "eventHandlers");
633
- this.enabled = enabled;
634
- this.isActive = false;
635
- this.componentMatcher = new ComponentMatcher({
636
- allowlist: [
637
- "div",
638
- "p",
639
- "span",
640
- "h1",
641
- "h2",
642
- "h3",
643
- "h4",
644
- "h5",
645
- "h6",
646
- "a",
647
- "button",
648
- "input",
649
- "select",
650
- "textarea",
651
- "label",
652
- "section",
653
- "article",
654
- "main",
655
- "aside",
656
- "header",
657
- "footer",
658
- "nav",
659
- "figure",
660
- "figcaption",
661
- "ul",
662
- "ol",
663
- "li",
664
- "table",
665
- "tr",
666
- "td",
667
- "th",
668
- "blockquote",
669
- "img"
670
- ]
671
- });
672
- this.styleManager = new StyleManager();
673
- this.communicationManager = new CommunicationManager();
674
- this.editableManager = new EditableManager(this.communicationManager);
675
- this.eventHandlers = new EventHandlers(
676
- () => this.isActive,
677
- this.componentMatcher,
678
- this.styleManager,
679
- this.editableManager,
680
- this.communicationManager
681
- );
682
- }
683
- /**
684
- * Initialize the design mode interactions
685
- */
686
- initialize() {
687
- if (!this.enabled) {
688
- console.log("Design Mode Interactions disabled");
689
- return;
690
- }
691
- console.log("Initializing Design Mode Interactions...");
692
- this.styleManager.addHighlightStyles();
693
- document.addEventListener("mouseover", this.eventHandlers.handleMouseOver);
694
- document.addEventListener("mouseleave", this.eventHandlers.handleMouseLeave);
695
- document.addEventListener("click", this.eventHandlers.handleClick, true);
696
- console.log("Design Mode Interactions initialized!");
697
- this.communicationManager.notifyInitializationComplete();
698
- }
699
- /**
700
- * Enable the design mode interactions
701
- */
702
- enable() {
703
- this.isActive = true;
704
- console.log("Design Mode Interactions enabled");
705
- }
706
- /**
707
- * Disable the design mode interactions
708
- */
709
- disable() {
710
- this.isActive = false;
711
- this.eventHandlers.clearAll();
712
- console.log("Design Mode Interactions disabled");
713
- }
714
- resolveTargets(sourceLocation) {
715
- let location = sourceLocation ?? null;
716
- if (!location?.fileName) {
717
- const selectedElement = this.eventHandlers.getSelectedElement();
718
- location = getSourceFromDataAttributes(selectedElement);
719
- }
720
- return location ? findElementsBySourceLocation(location) : [];
721
- }
722
- /**
723
- * Apply a style change to all elements at the given source location.
724
- * When sourceLocation is provided (undo/redo), it is used directly.
725
- * Otherwise the source location is read from the currently selected element.
726
- */
727
- applyStyleChange(property, value, sourceLocation) {
728
- for (const el of this.resolveTargets(sourceLocation)) {
729
- el.style[property] = value;
730
- }
731
- }
732
- applyTextChange(text, sourceLocation) {
733
- for (const el of this.resolveTargets(sourceLocation)) {
734
- el.textContent = text;
735
- }
736
- }
737
- /**
738
- * Apply attribute changes to all elements at the given source location whose
739
- * `tagName` matches `tag` (case-insensitive). Per-tag appliers declare which
740
- * attributes are valid and how empty-string values are handled (e.g. for
741
- * `img`, an empty `width`/`height` clears the attribute).
742
- *
743
- * No-op if the tag has no registered applier. When `sourceLocation` is
744
- * omitted (live edit), the source is read from the currently selected
745
- * element; when provided (undo/redo replay), it is used directly.
746
- *
747
- * To support a new tag, add an entry to {@link mediaAppliers}.
748
- *
749
- * @param tag - The HTML tag the change targets (e.g. `"img"`).
750
- * @param attributes - Sparse map of attribute names to their new string values; `undefined` values are skipped.
751
- * @param sourceLocation - Explicit source location for undo/redo; falls back to the selected element when omitted.
752
- */
753
- applyMediaChange(tag, attributes, sourceLocation) {
754
- const applier = mediaAppliers[tag.toLowerCase()];
755
- if (!applier) return;
756
- const tagNameUpper = tag.toUpperCase();
757
- for (const el of this.resolveTargets(sourceLocation)) {
758
- if (el.tagName !== tagNameUpper) continue;
759
- applier(el, attributes);
760
- }
761
- }
762
- /**
763
- * Cleanup and remove event listeners
764
- */
765
- destroy() {
766
- document.removeEventListener("mouseover", this.eventHandlers.handleMouseOver);
767
- document.removeEventListener("mouseleave", this.eventHandlers.handleMouseLeave);
768
- document.removeEventListener("click", this.eventHandlers.handleClick, true);
769
- this.styleManager.removeHighlightStyles();
770
- this.eventHandlers.clearAll();
771
- }
772
- };
773
-
774
- // src/design/interactions/index.ts
775
- var interactions = new InteractionsController(true);
776
- if (typeof document !== "undefined") {
777
- if (document.readyState === "loading") {
778
- document.addEventListener("DOMContentLoaded", () => {
779
- interactions.initialize();
780
- });
781
- } else {
782
- interactions.initialize();
783
- }
784
- }
785
- if (typeof window !== "undefined") {
786
- window.enableInteractions = function() {
787
- interactions.enable();
788
- };
789
- window.disableInteractions = function() {
790
- interactions.disable();
791
- };
792
- window.addEventListener("message", function(event) {
793
- const data = event.data;
794
- const typed = data && typeof data === "object" ? data : null;
795
- if (typed && typed.type === "style-change") {
796
- interactions.applyStyleChange(
797
- String(typed.property ?? ""),
798
- String(typed.value ?? ""),
799
- parseSourceLocation(typed.sourceLocation)
800
- );
801
- }
802
- if (typed && typed.type === "text-change") {
803
- interactions.applyTextChange(
804
- String(typed.text ?? ""),
805
- parseSourceLocation(typed.sourceLocation)
806
- );
807
- }
808
- if (typed && typed.type === "media-change") {
809
- const tag = typeof typed.tag === "string" ? typed.tag : "";
810
- const rawAttributes = typed.attributes && typeof typed.attributes === "object" ? typed.attributes : {};
811
- const attributes = {};
812
- for (const [key, raw] of Object.entries(rawAttributes)) {
813
- attributes[key] = raw === void 0 ? void 0 : String(raw);
814
- }
815
- if (tag) {
816
- interactions.applyMediaChange(tag, attributes, parseSourceLocation(typed.sourceLocation));
817
- }
818
- }
819
- if (typed && typed.type === "enable-interactions") {
820
- window.enableInteractions?.();
821
- }
822
- if (typed && typed.type === "disable-interactions") {
823
- window.disableInteractions?.();
824
- }
825
- });
826
- }
827
- })();
828
-
829
- })();
830
-