diff --git a/docs/API-Reference/view/PanelView.md b/docs/API-Reference/view/PanelView.md
index f2a78088fb..7a4455bcce 100644
--- a/docs/API-Reference/view/PanelView.md
+++ b/docs/API-Reference/view/PanelView.md
@@ -136,7 +136,6 @@ Preference key for persisting the maximize state across reloads.
| id | string | |
| [title] | string | |
| [options] | Object | |
-| [options.iconClass] | string | FontAwesome class string (e.g. "fa-solid fa-terminal"). |
| [options.iconSvg] | string | Path to an SVG icon (e.g. "styles/images/icon.svg"). |
diff --git a/docs/API-Reference/view/WorkspaceManager.md b/docs/API-Reference/view/WorkspaceManager.md
index 539e7ec2c2..2a7f2db812 100644
--- a/docs/API-Reference/view/WorkspaceManager.md
+++ b/docs/API-Reference/view/WorkspaceManager.md
@@ -101,7 +101,7 @@ The panel's size & visibility are automatically saved & restored as a view-state
| $panel | jQueryObject | DOM content to use as the panel. Need not be in the document yet. Must have an id attribute, for use as a preferences key. |
| [minSize] | number | @deprecated No longer used. Pass `undefined`. |
| [title] | string | Display title shown in the bottom panel tab bar. |
-| [options] | Object | Optional settings: - {string} iconClass FontAwesome class string (e.g. "fa-solid fa-terminal"). - {string} iconSvg Path to an SVG icon (e.g. "styles/images/icon.svg"). |
+| [options] | Object | Optional settings: - {string} iconSvg Path to an SVG icon for the panel tab (e.g. "styles/images/icon.svg"). If omitted, a generic default icon is used. |
diff --git a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js
index 0cf6315132..81964e71c5 100644
--- a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js
+++ b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js
@@ -40,6 +40,7 @@ function RemoteFunctions(config = {}) {
// this will store the element that was clicked previously (before the new click)
// we need this so that we can remove click styling from the previous element when a new element is clicked
let previouslySelectedElement = null;
+ let _selectedFromEditor = false;
// Expose the currently selected element globally for external access
window.__current_ph_lp_selected = null;
@@ -496,6 +497,13 @@ function RemoteFunctions(config = {}) {
}
this.elements = [];
+ // Reset the cached selector so that redraw() uses the elements
+ // array instead of re-querying the DOM with a stale selector.
+ // Without this, a selector like [data-brackets-id='3'] persists
+ // after the element is replaced (e.g. tag name change assigns a
+ // new ID), causing redraw() to find zero matches and release
+ // all overlays — making the highlight vanish.
+ this.selector = "";
},
redraw: function () {
@@ -550,8 +558,8 @@ function RemoteFunctions(config = {}) {
}
const element = _lastHoverTarget;
- // Show hover overlay + hover box only for non-selected elements
- if (element && element !== previouslySelectedElement) {
+
+ if (element && (element !== previouslySelectedElement || _selectedFromEditor)) {
_hoverHighlight.add(element);
if (hoverBoxHandler) {
hoverBoxHandler.showHoverBox(element);
@@ -642,6 +650,20 @@ function RemoteFunctions(config = {}) {
* UI like control box, spacing handles, or measurements.
*/
function selectElement(element, fromEditor) {
+ // When a cursor-based highlight re-selects the already-selected element,
+ // just refresh the highlight overlay without dismissing existing UI panels
+ // (control box, editor box, element-info). This prevents cursor activity
+ // after a source edit (e.g., tag name change) from tearing down the
+ // element properties panel and losing its state.
+ if (fromEditor && element === previouslySelectedElement) {
+ if (!_clickHighlight) {
+ _clickHighlight = new Highlight();
+ }
+ _clickHighlight.clear();
+ _clickHighlight.add(element);
+ return;
+ }
+
dismissUIAndCleanupState();
// this should also be there when users are in highlight mode
scrollElementToViewPort(element);
@@ -680,6 +702,7 @@ function RemoteFunctions(config = {}) {
_clickHighlight.add(element);
previouslySelectedElement = element;
+ _selectedFromEditor = fromEditor || false;
window.__current_ph_lp_selected = element;
}
@@ -1315,6 +1338,19 @@ function RemoteFunctions(config = {}) {
}
previouslySelectedElement = freshElement;
window.__current_ph_lp_selected = freshElement;
+ // After element replacement (e.g., tag name change), the old
+ // DOM node is gone. Patch the element reference on any
+ // existing UI boxes so that position() doesn't bail on a
+ // disconnected node and future syncs resolve correctly.
+ // We update references directly rather than calling
+ // handler.updateContent() to avoid side-effects like
+ // re-creating a dismissed control box.
+ if (SHARED_STATE._controlBox) {
+ SHARED_STATE._controlBox.element = freshElement;
+ }
+ if (SHARED_STATE._editorBox) {
+ SHARED_STATE._editorBox.element = freshElement;
+ }
redrawEverything();
}
}
diff --git a/src/LiveDevelopment/LivePreviewConstants.js b/src/LiveDevelopment/LivePreviewConstants.js
index 6eb27d17f4..ecfc9a95db 100644
--- a/src/LiveDevelopment/LivePreviewConstants.js
+++ b/src/LiveDevelopment/LivePreviewConstants.js
@@ -41,6 +41,4 @@ define(function main(require, exports, module) {
exports.HIGHLIGHT_CLICK = "click";
exports.PREFERENCE_SHOW_RULER_LINES = "livePreviewShowMeasurements";
-
- exports.PREFERENCE_LIVE_PREVIEW_SYNC = "livePreviewSyncSourceAndPreview";
});
diff --git a/src/LiveDevelopment/MultiBrowserImpl/documents/LiveDocument.js b/src/LiveDevelopment/MultiBrowserImpl/documents/LiveDocument.js
index 48faddc261..9d5beb6260 100644
--- a/src/LiveDevelopment/MultiBrowserImpl/documents/LiveDocument.js
+++ b/src/LiveDevelopment/MultiBrowserImpl/documents/LiveDocument.js
@@ -192,8 +192,7 @@ define(function (require, exports, module) {
if (!this.editor) {
return;
}
- if(!_disableHighlightOnCursor &&
- PreferencesManager.get(CONSTANTS.PREFERENCE_LIVE_PREVIEW_SYNC) !== false){
+ if(!_disableHighlightOnCursor){
this.updateHighlight();
}
};
diff --git a/src/LiveDevelopment/MultiBrowserImpl/protocol/LiveDevProtocol.js b/src/LiveDevelopment/MultiBrowserImpl/protocol/LiveDevProtocol.js
index 70565d3340..8f0ab12a93 100644
--- a/src/LiveDevelopment/MultiBrowserImpl/protocol/LiveDevProtocol.js
+++ b/src/LiveDevelopment/MultiBrowserImpl/protocol/LiveDevProtocol.js
@@ -240,9 +240,6 @@ define(function (require, exports, module) {
// hilights are enabled only in edit and highlight mode
return;
}
- if(PreferencesManager.get(CONSTANTS.PREFERENCE_LIVE_PREVIEW_SYNC) === false){
- return;
- }
const liveDoc = LiveDevMultiBrowser.getCurrentLiveDoc(),
activeEditor = EditorManager.getActiveEditor(), // this can be an inline editor
activeFullEditor = EditorManager.getCurrentFullEditor();
diff --git a/src/LiveDevelopment/main.js b/src/LiveDevelopment/main.js
index a432affa07..954e4ad96c 100644
--- a/src/LiveDevelopment/main.js
+++ b/src/LiveDevelopment/main.js
@@ -71,6 +71,7 @@ define(function main(require, exports, module) {
elemHighlights: CONSTANTS.HIGHLIGHT_HOVER, // default value, this will get updated when the extension loads
showRulerLines: false, // default value, this will get updated when the extension loads
syncSourceAndPreview: true, // default value, this will get updated when the extension loads
+ imageGalleryAutoOpen: true, // auto-open gallery on first image click per session
isPaidUser: false, // will be updated when we fetch entitlements
isLoggedIn: false, // will be updated when we fetch entitlements
hasLiveEditCapability: false // handled inside _liveEditCapabilityChanged function
@@ -325,13 +326,6 @@ define(function main(require, exports, module) {
MultiBrowserLiveDev.updateConfig(config);
}
- function updateSyncConfig() {
- const prefValue = PreferencesManager.get(CONSTANTS.PREFERENCE_LIVE_PREVIEW_SYNC);
- const config = MultiBrowserLiveDev.getConfig();
- config.syncSourceAndPreview = prefValue !== false;
- MultiBrowserLiveDev.updateConfig(config);
- }
-
EventDispatcher.makeEventDispatcher(exports);
// private api
@@ -355,7 +349,6 @@ define(function main(require, exports, module) {
exports.setLivePreviewTransportBridge = setLivePreviewTransportBridge;
exports.updateElementHighlightConfig = updateElementHighlightConfig;
exports.updateRulerLinesConfig = updateRulerLinesConfig;
- exports.updateSyncConfig = updateSyncConfig;
exports.getConnectionIds = MultiBrowserLiveDev.getConnectionIds;
exports.getLivePreviewDetails = MultiBrowserLiveDev.getLivePreviewDetails;
exports.hideHighlight = MultiBrowserLiveDev.hideHighlight;
diff --git a/src/extensionsIntegrated/Phoenix-live-preview/LivePreviewSettings.js b/src/extensionsIntegrated/Phoenix-live-preview/LivePreviewSettings.js
index 4b79fe124b..8fa32929fd 100644
--- a/src/extensionsIntegrated/Phoenix-live-preview/LivePreviewSettings.js
+++ b/src/extensionsIntegrated/Phoenix-live-preview/LivePreviewSettings.js
@@ -62,8 +62,7 @@ define(function (require, exports, module) {
const SUPPORTED_FRAMEWORKS = {};
SUPPORTED_FRAMEWORKS[FRAMEWORK_DOCUSAURUS] = {configFile: "docusaurus.config.js", hotReloadSupported: true};
- const PREFERENCE_LINK_EDITOR_AND_PREVIEW = "livePreviewSyncSourceAndPreview",
- PREFERENCE_SHOW_LIVE_PREVIEW_PANEL = "livePreviewShowAtStartup",
+ const PREFERENCE_SHOW_LIVE_PREVIEW_PANEL = "livePreviewShowAtStartup",
PREFERENCE_PROJECT_SERVER_ENABLED = "livePreviewUseDevServer",
PREFERENCE_PROJECT_SERVER_URL = "livePreviewServerURL",
PREFERENCE_PROJECT_SERVER_PATH = "livePreviewServerProjectPath",
@@ -123,9 +122,7 @@ define(function (require, exports, module) {
{"settings": currentSettings, "Strings": Strings}));
// Select the correct theme.
- const $linkEditorAndPreviewChk = $template.find("#linkEditorAndPreviewChk"),
- $linkEditorAndPreviewInfo = $template.find("#linkEditorAndPreviewInfo"),
- $livePreviewServerURL = $template.find("#livePreviewServerURL"),
+ const $livePreviewServerURL = $template.find("#livePreviewServerURL"),
$enableCustomServerChk = $template.find("#enableCustomServerChk"),
$showLivePreviewAtStartup = $template.find("#showLivePreviewAtStartupChk"),
$serveRoot = $template.find("#serveRoot"),
@@ -136,13 +133,6 @@ define(function (require, exports, module) {
$frameworkSelect = $template.find("#frameworkSelect");
// Initialize form values from preferences
- $linkEditorAndPreviewChk.prop(
- 'checked', PreferencesManager.get(PREFERENCE_LINK_EDITOR_AND_PREVIEW) !== false
- );
- $linkEditorAndPreviewInfo.on("click", function(e) {
- e.preventDefault();
- Phoenix.app.openURLInDefaultBrowser("https://docs.phcode.dev");
- });
$enableCustomServerChk.prop('checked', PreferencesManager.get(PREFERENCE_PROJECT_SERVER_ENABLED));
$showLivePreviewAtStartup.prop('checked', PreferencesManager.get(PREFERENCE_SHOW_LIVE_PREVIEW_PANEL));
$hotReloadChk.prop('checked', !!PreferencesManager.get(PREFERENCE_PROJECT_SERVER_HOT_RELOAD_SUPPORTED));
@@ -184,7 +174,6 @@ define(function (require, exports, module) {
Metrics.countEvent(Metrics.EVENT_TYPE.LIVE_PREVIEW, "settings", "dialog");
Dialogs.showModalDialogUsingTemplate($template).done(function (id) {
if (id === Dialogs.DIALOG_BTN_OK) {
- PreferencesManager.set(PREFERENCE_LINK_EDITOR_AND_PREVIEW, $linkEditorAndPreviewChk.is(":checked"));
PreferencesManager.set(PREFERENCE_SHOW_LIVE_PREVIEW_PANEL, $showLivePreviewAtStartup.is(":checked"));
_saveProjectPreferences($enableCustomServerChk.is(":checked"), $livePreviewServerURL.val(),
$serveRoot.val(), $hotReloadChk.is(":checked"), $frameworkSelect.val());
diff --git a/src/extensionsIntegrated/Phoenix-live-preview/livePreviewSettings.html b/src/extensionsIntegrated/Phoenix-live-preview/livePreviewSettings.html
index 60d4efc13f..ad3cd9aa89 100644
--- a/src/extensionsIntegrated/Phoenix-live-preview/livePreviewSettings.html
+++ b/src/extensionsIntegrated/Phoenix-live-preview/livePreviewSettings.html
@@ -8,11 +8,6 @@