Skip to content

Commit 6f43c33

Browse files
committed
deploy: cd657c3
1 parent dcf80e4 commit 6f43c33

94 files changed

Lines changed: 4334 additions & 296 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

LiveDevelopment/BrowserScripts/RemoteFunctions.js

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ function RemoteFunctions(config = {}) {
4242
// we need this so that we can remove click styling from the previous element when a new element is clicked
4343
let previouslySelectedElement = null;
4444
let _selectedFromEditor = false;
45+
// the selected element the `phcode-no-lp-edit` opt-out is lifted for, see _isEditOptedOut
46+
let _editOptOutOverride = null;
4547
// Expose the currently selected element globally for external access
4648
window.__current_ph_lp_selected = null;
4749

@@ -121,6 +123,9 @@ function RemoteFunctions(config = {}) {
121123
* Elements opted out via `phcode-no-lp-edit` (cascades to descendants) or
122124
* `phcode-no-lp-edit-this` (this element only) are also non-inspectable so
123125
* every downstream tool inherits the opt-out automatically.
126+
*
127+
* @param {DOMElement} element
128+
* @param {boolean} [onlyHighlight=false] - If true, bypasses the mode check
124129
*/
125130
function isElementInspectable(element, onlyHighlight = false) {
126131
if(config.mode !== 'edit' && !onlyHighlight) {
@@ -133,13 +138,31 @@ function RemoteFunctions(config = {}) {
133138
// this attribute is used by phoenix internal elements
134139
!element.closest(`[${GLOBALS.PHCODE_INTERNAL_ATTR}]`) &&
135140
!_isInsideHeadTag(element) && // shouldn't be inside the head tag like meta tags and all
136-
!element.closest('.phcode-no-lp-edit') &&
137-
!(element.classList && element.classList.contains('phcode-no-lp-edit-this'))) {
141+
!_isEditOptedOut(element)) {
138142
return true;
139143
}
140144
return false;
141145
}
142146

147+
/**
148+
* `phcode-no-lp-edit` cascades to descendants, `phcode-no-lp-edit-this` covers
149+
* the one element.
150+
*
151+
* The opt-out exists so that a pointer landing on the page is read as the page's
152+
* own business rather than as an edit, and a click still is: handleElementClick
153+
* tests for it before anything else. But an element the editor named outright -
154+
* a row picked in the layers panel - is being edited on purpose and there is
155+
* nothing ambiguous to protect, so while such an element holds the selection
156+
* every tool treats it like any other.
157+
*/
158+
function _isEditOptedOut(element) {
159+
if (element === _editOptOutOverride) {
160+
return false;
161+
}
162+
return !!(element.closest('.phcode-no-lp-edit') ||
163+
(element.classList && element.classList.contains('phcode-no-lp-edit-this')));
164+
}
165+
143166
/**
144167
* This is a checker function for editable elements, it makes sure that the element satisfies all the required check
145168
* - When onlyHighlight is false → config.mode must be 'edit'
@@ -185,6 +208,7 @@ function RemoteFunctions(config = {}) {
185208
isElementVisible: isElementVisible,
186209
screenOffset: screenOffset,
187210
selectElement: selectElement,
211+
sendSelectionToEditor: sendSelectionToEditor,
188212
brieflyDisableHoverListeners: brieflyDisableHoverListeners,
189213
handleElementClick: handleElementClick,
190214
cleanupPreviousElementState: cleanupPreviousElementState,
@@ -668,8 +692,11 @@ function RemoteFunctions(config = {}) {
668692
* @param {boolean} [fromEditor] - If true, this is an editor-cursor-driven selection;
669693
* only lightweight highlights (outline, margin/padding overlay) are shown, not interactive
670694
* UI like control box, spacing handles, or measurements.
695+
* @param {boolean} [ignoreEditOptOut] - Edit this element even though it opted
696+
* out of live preview editing. For selections asked for by name from the
697+
* editor side; holds only while the element stays selected.
671698
*/
672-
function selectElement(element, fromEditor) {
699+
function selectElement(element, fromEditor, ignoreEditOptOut) {
673700
// When a cursor-based highlight re-selects the already-selected element,
674701
// just refresh the highlight overlay without dismissing existing UI panels
675702
// (control box, editor box, element-info). This prevents cursor activity
@@ -685,6 +712,8 @@ function RemoteFunctions(config = {}) {
685712
}
686713

687714
dismissUIAndCleanupState();
715+
// set after the dismissal, which clears the previous selection's exemption
716+
_editOptOutOverride = ignoreEditOptOut ? element : null;
688717
// this should also be there when users are in highlight mode
689718
scrollElementToViewPort(element);
690719

@@ -804,24 +833,36 @@ function RemoteFunctions(config = {}) {
804833
selection.removeAllRanges();
805834
}
806835

807-
// send cursor movement message to editor so cursor jumps to clicked element
808-
if (element.hasAttribute(GLOBALS.DATA_BRACKETS_ID_ATTR) &&
809-
config.syncSourceAndPreview !== false) {
810-
MessageBroker.send({
811-
"tagId": element.getAttribute(GLOBALS.DATA_BRACKETS_ID_ATTR),
812-
"nodeID": element.id,
813-
"nodeClassList": element.classList,
814-
"nodeName": element.nodeName,
815-
"allSelectors": window.getAllInheritedSelectorsInOrder(element),
816-
"contentEditable": element.contentEditable === "true",
817-
"clicked": true
818-
});
819-
}
836+
sendSelectionToEditor(element);
820837

821838
brieflyDisableHoverListeners();
822839
selectElement(element);
823840
}
824841

842+
/**
843+
* Tells the editor which element is now selected, so the cursor jumps to it and
844+
* the css reverse highlight follows. Split out of the click handler because a
845+
* selection can also be asked for from the editor side, which must report itself
846+
* the same way without a pointer gesture ever touching the page.
847+
*
848+
* @param {HTMLElement} element
849+
*/
850+
function sendSelectionToEditor(element) {
851+
if (!element.hasAttribute(GLOBALS.DATA_BRACKETS_ID_ATTR) ||
852+
config.syncSourceAndPreview === false) {
853+
return;
854+
}
855+
MessageBroker.send({
856+
"tagId": element.getAttribute(GLOBALS.DATA_BRACKETS_ID_ATTR),
857+
"nodeID": element.id,
858+
"nodeClassList": element.classList,
859+
"nodeName": element.nodeName,
860+
"allSelectors": window.getAllInheritedSelectorsInOrder(element),
861+
"contentEditable": element.contentEditable === "true",
862+
"clicked": true
863+
});
864+
}
865+
825866
// clear CSS selector highlights
826867
function clearCssSelectorHighlight() {
827868
if (_cssSelectorHighlightTimer) {
@@ -1500,6 +1541,7 @@ function RemoteFunctions(config = {}) {
15001541
previouslySelectedElement = null;
15011542
window.__current_ph_lp_selected = null;
15021543
}
1544+
_editOptOutOverride = null;
15031545

15041546
// Reset hover tracking so the same-element skip doesn't suppress
15051547
// re-highlighting after a full state cleanup (e.g. Escape, dismiss).

LiveDevelopment/MultiBrowserImpl/protocol/LiveDevProtocol.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

appConfig.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ window.AppConfig = {
4040
"ruff": "0.16.5"
4141
},
4242
"linting.enabled_by_default": true,
43-
"build_timestamp": "2026-09-01T10:29:36.836Z",
43+
"build_timestamp": "2026-09-01T15:23:33.790Z",
4444
"googleAnalyticsID": "G-FP5S9BKDSJ",
4545
"googleAnalyticsIDDesktop": "G-D5R1Y6PTS8",
4646
"mixPanelID": "a7e08ffd43c37767c29b13df1d2e6c62",
@@ -52,7 +52,7 @@ window.AppConfig = {
5252
"bugsnagEnv": "staging"
5353
},
5454
"name": "Phoenix Code",
55-
"version": "5.5.3-23366",
55+
"version": "5.5.3-23393",
5656
"apiVersion": "5.5.3",
5757
"homepage": "https://core.ai",
5858
"issues": {

assets/default-project/en.zip

0 Bytes
Binary file not shown.

assets/sample-projects/HTML5.zip

0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.

assets/sample-projects/explore.zip

0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.

brackets.js

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)