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 @@

{{Strings.LIVE_DEV_SETTINGS_TITLE}}

-
- - - -
diff --git a/src/extensionsIntegrated/Phoenix-live-preview/main.js b/src/extensionsIntegrated/Phoenix-live-preview/main.js index 43ef8b6947..3129acb45e 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/main.js +++ b/src/extensionsIntegrated/Phoenix-live-preview/main.js @@ -115,12 +115,6 @@ define(function (require, exports, module) { description: Strings.LIVE_DEV_SETTINGS_SHOW_RULER_LINES_PREFERENCE }); - // live preview link editor and preview preference - const PREFERENCE_LIVE_PREVIEW_SYNC = CONSTANTS.PREFERENCE_LIVE_PREVIEW_SYNC; - PreferencesManager.definePreference(PREFERENCE_LIVE_PREVIEW_SYNC, "boolean", true, { - description: Strings.LIVE_DEV_SETTINGS_LINK_EDITOR_AND_PREVIEW_PREFERENCE - }); - const LIVE_PREVIEW_PANEL_ID = "live-preview-panel"; const LIVE_PREVIEW_IFRAME_ID = "panel-live-preview-frame"; const MDVIEWR_IFRAME_ID = "panel-md-preview-frame"; @@ -1474,14 +1468,9 @@ define(function (require, exports, module) { PreferencesManager.on("change", PREFERENCE_SHOW_RULER_LINES, function() { LiveDevelopment.updateRulerLinesConfig(); }); - PreferencesManager.on("change", PREFERENCE_LIVE_PREVIEW_SYNC, function() { - LiveDevelopment.updateSyncConfig(); - }); - - // Initialize element highlight, ruler lines, and sync config on startup + // Initialize element highlight and ruler lines config on startup LiveDevelopment.updateElementHighlightConfig(); LiveDevelopment.updateRulerLinesConfig(); - LiveDevelopment.updateSyncConfig(); LiveDevelopment.openLivePreview(); LiveDevelopment.on(LiveDevelopment.EVENT_OPEN_PREVIEW_URL, _openLivePreviewURL); diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index d868d37d6c..3c6b44f115 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -185,6 +185,8 @@ define({ "LIVE_DEV_SETTINGS_SHOW_RULER_LINES_PREFERENCE": "Show measurements when elements are selected in live preview. Defaults to 'false'", "LIVE_DEV_TOOLBOX_SELECT_PARENT": "Select Parent", "LIVE_DEV_TOOLBOX_EDIT_TEXT": "Edit Text", + "LIVE_DEV_TOOLBOX_DOUBLE_CLICK_HINT": "Double-click", + "LIVE_DEV_TOOLBOX_EDIT_ELEMENT_PROPS": "Edit Element Properties", "LIVE_DEV_TOOLBOX_EDIT_HYPERLINK": "Edit Hyperlink", "LIVE_DEV_HYPERLINK_NO_HREF": "No href set", "LIVE_DEV_HYPERLINK_OPEN_LINK": "Open this link", @@ -272,12 +274,13 @@ define({ "LIVE_DEV_FORMAT_MORE": "More formatting", "LIVE_DEV_ELEMENT_PROPS_TITLE": "Element Properties", "LIVE_DEV_ELEMENT_PROPS_TAG": "Tag", + "LIVE_DEV_ELEMENT_PROPS_VOID_ERROR": "<{0}> is self-closing and cannot have content", "LIVE_DEV_ELEMENT_PROPS_SIZE": "Size", "LIVE_DEV_ELEMENT_PROPS_CLASS": "Class", "LIVE_DEV_ELEMENT_PROPS_ID": "ID", "LIVE_DEV_ELEMENT_PROPS_HREF": "Link", "LIVE_DEV_ELEMENT_PROPS_ADD_CLASS": "+ add class", - "LIVE_DEV_ELEMENT_PROPS_SEARCH_TAGS": "Search tags\u2026", + "LIVE_DEV_ELEMENT_PROPS_SEARCH_TAGS": "Tag Suggestions", "LIVE_DEV_ELEMENT_PROPS_COMPUTED": "Computed:", "LIVE_DEV_ELEMENT_PROPS_USE_CUSTOM": "Use \u201c{0}\u201d", "LIVE_DEV_ELEMENT_PROPS_ATTRIBUTES": "Attributes", @@ -285,6 +288,7 @@ define({ "LIVE_DEV_ELEMENT_PROPS_ATTR_NAME": "name", "LIVE_DEV_ELEMENT_PROPS_ATTR_VALUE": "value", "LIVE_DEV_ELEMENT_PROPS_LOADING": "Loading", + "LIVE_DEV_ELEMENT_PROPS_NO_CLASSES": "No classes", "LIVE_DEV_ELEMENT_PROPS_NO_ATTRIBUTES": "No attributes", "LIVE_DEV_ELEMENT_PROPS_RESETTING": "Resetting", "LIVE_DEV_CB_EXCEEDED_CLASSES": "+{0} more", @@ -440,8 +444,9 @@ define({ "LIVE_DEV_HB_HEADER": "Header", "LIVE_DEV_HB_FOOTER": "Footer", "LIVE_DEV_HB_NAVIGATION": "Navigation", - "LIVE_DEV_HB_SIDEBAR": "Sidebar", + "LIVE_DEV_HB_SIDEBAR": "Aside", "LIVE_DEV_HB_MAIN": "Main", + "LIVE_DEV_HB_ADDRESS": "Address", "LIVE_DEV_HB_IMAGE": "Image", "LIVE_DEV_HB_VIDEO": "Video", "LIVE_DEV_HB_AUDIO": "Audio", @@ -544,8 +549,6 @@ define({ "LIVE_PREVIEW_MODE_EDIT": "Edit Mode", "LIVE_PREVIEW_EDIT_HIGHLIGHT_ON": "Inspect Element on Hover", "LIVE_PREVIEW_SHOW_RULER_LINES": "Show Measurements", - "LIVE_PREVIEW_LINK_EDITOR_AND_PREVIEW": "Link Editor and Preview", - "LIVE_DEV_SETTINGS_LINK_EDITOR_AND_PREVIEW_PREFERENCE": "Link editor cursor with live preview element highlighting. When enabled, moving the cursor in the editor highlights the corresponding element in the live preview, and clicking an element in the live preview jumps the cursor to its source code. Defaults to 'true'", "LIVE_PREVIEW_MODE_PREFERENCE": "'{0}' shows only the webpage, '{1}' connects the webpage to your code - click on elements to jump to their code and vice versa, '{2}' provides highlighting along with advanced element manipulation", "LIVE_PREVIEW_CONFIGURE_MODES": "Configure Live Preview Modes", diff --git a/tracking-repos.json b/tracking-repos.json index d9ea48c809..7eab94bfac 100644 --- a/tracking-repos.json +++ b/tracking-repos.json @@ -1,5 +1,5 @@ { "phoenixPro": { - "commitID": "9bf998b2c6c137a9bfdd2b715975a28fb8311b7e" + "commitID": "227551b263c5d4ea5233e3920639bc5aa493b321" } }