Skip to content

Commit 6f706d4

Browse files
committed
deploy: cd657c3
1 parent 8c22d57 commit 6f706d4

62 files changed

Lines changed: 550 additions & 300 deletions

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: 78 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ function RemoteFunctions(config = {}) {
2626
const SHARED_STATE = {
2727
__description: "Use this to keep shared state for Live Preview Edit instead of window.*",
2828
_suppressDOMEditDismissal: false,
29-
_suppressDOMEditDismissalTimeout: null
29+
_suppressDOMEditDismissalTimeout: null,
30+
_boxModelHighlightHidden: false
3031
};
3132

3233
let _hoverHighlight;
@@ -190,7 +191,10 @@ function RemoteFunctions(config = {}) {
190191
disableHoverListeners: disableHoverListeners,
191192
enableHoverListeners: enableHoverListeners,
192193
redrawHighlights: redrawHighlights,
193-
redrawEverything: redrawEverything
194+
redrawEverything: redrawEverything,
195+
getTreePath: _getTreePath,
196+
getElementByTreePath: _getElementByTreePath,
197+
getSourceChildren: _instrumentedChildren
194198
};
195199

196200
/**
@@ -446,15 +450,17 @@ function RemoteFunctions(config = {}) {
446450
s.backgroundColor = color;
447451
}
448452

449-
// Padding region
450-
const padColor = COLORS.highlightPadding;
453+
// Padding region. Rects stay in place when hidden, only their fill goes away,
454+
// so nothing has to be rebuilt when they come back.
455+
const boxModelHidden = SHARED_STATE._boxModelHighlightHidden;
456+
const padColor = boxModelHidden ? "transparent" : COLORS.highlightPadding;
451457
setRect(refs.padTop, paddingBox.left, paddingBox.top, paddingBox.width, pt, padColor);
452458
setRect(refs.padBottom, paddingBox.left, contentBox.top + contentBox.height, paddingBox.width, pb, padColor);
453459
setRect(refs.padLeft, paddingBox.left, contentBox.top, pl, contentBox.height, padColor);
454460
setRect(refs.padRight, contentBox.left + contentBox.width, contentBox.top, pr, contentBox.height, padColor);
455461

456462
// Margin region
457-
const margColor = COLORS.highlightMargin;
463+
const margColor = boxModelHidden ? "transparent" : COLORS.highlightMargin;
458464
setRect(refs.marTop, marginBox.left, marginBox.top, marginBox.width, mt, margColor);
459465
setRect(refs.marBottom, marginBox.left, borderBox.top + borderBox.height, marginBox.width, mb, margColor);
460466
setRect(refs.marLeft, marginBox.left, borderBox.top, ml, borderBox.height, margColor);
@@ -1054,6 +1060,25 @@ function RemoteFunctions(config = {}) {
10541060
return results && results[0];
10551061
};
10561062

1063+
// True for elements Phoenix adds to the page itself, like the tool boxes and
1064+
// the highlight overlays. They are not part of the user's source file.
1065+
function _isPhoenixInternalNode(node) {
1066+
return !!node && node.nodeType === Node.ELEMENT_NODE &&
1067+
(node.hasAttribute(GLOBALS.PHCODE_INTERNAL_ATTR) ||
1068+
node.className === GLOBALS.HIGHLIGHT_CLASSNAME);
1069+
}
1070+
1071+
/** The first of the Phoenix elements sitting at the end of `parent`, else null. */
1072+
function _firstTrailingInternalNode(parent) {
1073+
let node = parent.lastChild;
1074+
let first = null;
1075+
while (_isPhoenixInternalNode(node)) {
1076+
first = node;
1077+
node = node.previousSibling;
1078+
}
1079+
return first;
1080+
}
1081+
10571082
/**
10581083
* @private
10591084
* Insert a new child element
@@ -1068,7 +1093,12 @@ function RemoteFunctions(config = {}) {
10681093
if (edit.firstChild) {
10691094
before = targetElement.firstChild;
10701095
} else if (edit.lastChild) {
1071-
after = targetElement.lastChild;
1096+
// Phoenix's tool boxes are the last children of <body>, so appending
1097+
// here would put the new element after them, in the wrong place.
1098+
before = _firstTrailingInternalNode(targetElement);
1099+
if (!before) {
1100+
after = targetElement.lastChild;
1101+
}
10721102
}
10731103

10741104
if (before) {
@@ -1479,6 +1509,9 @@ function RemoteFunctions(config = {}) {
14791509
_pendingHoverRAF = null;
14801510
}
14811511

1512+
// the selection is gone, so a popover can no longer turn the fills back on
1513+
SHARED_STATE._boxModelHighlightHidden = false;
1514+
14821515
// Highlight.clear() removes all overlay divs (outline + margin/padding rects)
14831516
hideHighlight();
14841517

@@ -1492,27 +1525,38 @@ function RemoteFunctions(config = {}) {
14921525
}
14931526
}
14941527

1528+
// Only the children that came from the source file. Phoenix's own elements have
1529+
// no data-brackets-id, and counting them would shift the tree path indexes.
1530+
function _instrumentedChildren(parent) {
1531+
const result = [];
1532+
const children = (parent && parent.children) || [];
1533+
for (let i = 0; i < children.length; i++) {
1534+
if (children[i].hasAttribute(GLOBALS.DATA_BRACKETS_ID_ATTR)) {
1535+
result.push(children[i]);
1536+
}
1537+
}
1538+
return result;
1539+
}
1540+
14951541
/**
14961542
* Compute the tree path of an element as an array of child indices
14971543
* from <html> down. Used to re-locate the element after re-instrumentation
14981544
* when data-brackets-id changes and text matching is ambiguous.
14991545
* E.g. [1, 0, 0, 1] means html > 2nd child > 1st child > 1st child > 2nd child.
1546+
* @return {?Array.<number>} null if the element did not come from the source file.
15001547
*/
15011548
function _getTreePath(element) {
15021549
const path = [];
15031550
let el = element;
15041551
while (el && el.parentElement) {
1505-
const parent = el.parentElement;
1506-
const children = parent.children;
1507-
for (let i = 0; i < children.length; i++) {
1508-
if (children[i] === el) {
1509-
path.unshift(i);
1510-
break;
1511-
}
1552+
const index = _instrumentedChildren(el.parentElement).indexOf(el);
1553+
if (index === -1) {
1554+
return null;
15121555
}
1513-
el = parent;
1556+
path.unshift(index);
1557+
el = el.parentElement;
15141558
}
1515-
return path;
1559+
return path.length ? path : null;
15161560
}
15171561

15181562
/**
@@ -1521,10 +1565,11 @@ function RemoteFunctions(config = {}) {
15211565
function _getElementByTreePath(path) {
15221566
let el = document.documentElement;
15231567
for (let i = 0; i < path.length; i++) {
1524-
if (!el || !el.children || !el.children[path[i]]) {
1568+
const siblings = _instrumentedChildren(el);
1569+
if (!siblings[path[i]]) {
15251570
return null;
15261571
}
1527-
el = el.children[path[i]];
1572+
el = siblings[path[i]];
15281573
}
15291574
return el;
15301575
}
@@ -1727,6 +1772,21 @@ function RemoteFunctions(config = {}) {
17271772
}
17281773
}
17291774

1775+
/**
1776+
* Hide just the margin/padding fills of the selected element highlight, keeping
1777+
* the outline and the selection itself. Used while editing paint properties like
1778+
* background color, where the fills sit on top of what the user is changing.
1779+
* @param {Boolean} hidden
1780+
*/
1781+
function setBoxModelHighlightHidden(hidden) {
1782+
hidden = !!hidden;
1783+
if (SHARED_STATE._boxModelHighlightHidden === hidden) {
1784+
return;
1785+
}
1786+
SHARED_STATE._boxModelHighlightHidden = hidden;
1787+
redrawHighlights();
1788+
}
1789+
17301790
let customReturns = {};
17311791
// only apis that needs to be called from phoenix js layer should be customReturns. APis that are shared within
17321792
// the remote function context only should not be in customReturns and should be in
@@ -1750,6 +1810,7 @@ function RemoteFunctions(config = {}) {
17501810
"getHighlightTrackingElement": getHighlightTrackingElement,
17511811
"getHighlightStyle": getHighlightStyle,
17521812
"setHotCornerHidden": setHotCornerHidden,
1813+
"setBoxModelHighlightHidden": setBoxModelHighlightHidden,
17531814
"clearHoverState": _clearHoverState
17541815
};
17551816

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.15.20"
4141
},
4242
"linting.enabled_by_default": true,
43-
"build_timestamp": "2026-07-28T13:57:19.833Z",
43+
"build_timestamp": "2026-07-31T09:30:19.620Z",
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.2.0-23241",
55+
"version": "5.2.0-23245",
5656
"apiVersion": "5.2.0",
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)