chrome-devtools-frontend 1.0.1596535 → 1.0.1597448
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.
- package/agents/prompts/ui-widgets.md +7 -8
- package/docs/ui_engineering.md +10 -11
- package/front_end/core/host/InspectorFrontendHostAPI.ts +1 -0
- package/front_end/core/host/UserMetrics.ts +12 -0
- package/front_end/core/root/Runtime.ts +5 -0
- package/front_end/core/sdk/CPUThrottlingManager.ts +9 -12
- package/front_end/core/sdk/PageResourceLoader.ts +22 -1
- package/front_end/devtools_compatibility.js +2 -1
- package/front_end/models/ai_assistance/AiConversation.ts +5 -0
- package/front_end/models/ai_assistance/agents/AiAgent.ts +4 -0
- package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +24 -0
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +289 -12
- package/front_end/models/greendev/Prototypes.ts +7 -1
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +35 -33
- package/front_end/panels/ai_assistance/PatchWidget.ts +6 -6
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +3 -28
- package/front_end/panels/ai_assistance/components/ChatView.ts +6 -11
- package/front_end/panels/ai_assistance/components/StylingAgentMarkdownRenderer.ts +200 -0
- package/front_end/panels/ai_assistance/components/chatMessage.css +0 -8
- package/front_end/panels/application/ServiceWorkerCacheViews.ts +1 -1
- package/front_end/panels/common/ExtensionServer.ts +15 -0
- package/front_end/panels/elements/ElementsTreeElement.ts +55 -47
- package/front_end/panels/elements/ElementsTreeOutline.ts +149 -28
- package/front_end/panels/lighthouse/LighthousePanel.ts +8 -0
- package/front_end/panels/settings/SettingsScreen.ts +3 -2
- package/front_end/ui/legacy/UIUtils.ts +5 -5
- package/front_end/ui/legacy/Widget.ts +33 -2
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- package/package.json +1 -1
|
@@ -25,6 +25,7 @@ const {
|
|
|
25
25
|
repeat,
|
|
26
26
|
classMap,
|
|
27
27
|
} = Directives;
|
|
28
|
+
const {widget} = UI.Widget;
|
|
28
29
|
|
|
29
30
|
/*
|
|
30
31
|
* Strings that don't need to be translated at this time.
|
|
@@ -67,9 +68,8 @@ export interface Props {
|
|
|
67
68
|
messages: Message[];
|
|
68
69
|
context: AiAssistanceModel.AiAgent.ConversationContext<unknown>|null;
|
|
69
70
|
isContextSelected: boolean;
|
|
70
|
-
isLoading: boolean;
|
|
71
71
|
canShowFeedbackForm: boolean;
|
|
72
|
-
|
|
72
|
+
isLoading: boolean;
|
|
73
73
|
conversationType: AiAssistanceModel.AiHistoryStorage.ConversationType;
|
|
74
74
|
isReadOnly: boolean;
|
|
75
75
|
blockedByCrossOrigin: boolean;
|
|
@@ -91,7 +91,6 @@ export interface Props {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
interface ChatWidgetInput extends Props {
|
|
94
|
-
accountGivenName: string;
|
|
95
94
|
handleScroll: (ev: Event) => void;
|
|
96
95
|
handleSuggestionClick: (title: string) => void;
|
|
97
96
|
handleMessageContainerRef: (el: Element|undefined) => void;
|
|
@@ -116,12 +115,11 @@ const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
116
115
|
${input.messages.length > 0 ? html`
|
|
117
116
|
<div class="messages-container" ${ref(input.handleMessageContainerRef)}>
|
|
118
117
|
${repeat(input.messages, message =>
|
|
119
|
-
|
|
118
|
+
widget(ChatMessage, {
|
|
120
119
|
message,
|
|
121
120
|
isLoading: input.isLoading && input.messages.at(-1) === message,
|
|
122
121
|
isReadOnly: input.isReadOnly,
|
|
123
122
|
canShowFeedbackForm: input.canShowFeedbackForm,
|
|
124
|
-
userInfo: input.userInfo,
|
|
125
123
|
markdownRenderer: input.markdownRenderer,
|
|
126
124
|
isLastMessage: input.messages.at(-1) === message,
|
|
127
125
|
onSuggestionClick: input.handleSuggestionClick,
|
|
@@ -130,14 +128,12 @@ const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
130
128
|
walkthrough: {
|
|
131
129
|
...input.walkthrough,
|
|
132
130
|
}
|
|
133
|
-
})
|
|
131
|
+
})
|
|
134
132
|
)}
|
|
135
|
-
${input.isLoading ? nothing :
|
|
136
|
-
.widgetConfig=${UI.Widget.widgetConfig(PatchWidget, {
|
|
133
|
+
${input.isLoading ? nothing : widget(PatchWidget, {
|
|
137
134
|
changeSummary: input.changeSummary ?? '',
|
|
138
135
|
changeManager: input.changeManager,
|
|
139
136
|
})}
|
|
140
|
-
></devtools-widget>`}
|
|
141
137
|
</div>
|
|
142
138
|
` : html`
|
|
143
139
|
<div class="empty-state-container">
|
|
@@ -149,7 +145,7 @@ const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
149
145
|
</div>
|
|
150
146
|
${AiAssistanceModel.AiUtils.isGeminiBranding() ?
|
|
151
147
|
html`
|
|
152
|
-
<h1 class='greeting'>Hello
|
|
148
|
+
<h1 class='greeting'>Hello</h1>
|
|
153
149
|
<p class='cta'>${lockedString(UIStringsNotTranslate.emptyStateTextGemini)}</p>
|
|
154
150
|
` : html`<h1>${lockedString(UIStringsNotTranslate.emptyStateText)}</h1>`
|
|
155
151
|
}
|
|
@@ -354,7 +350,6 @@ export class ChatView extends HTMLElement {
|
|
|
354
350
|
this.#view(
|
|
355
351
|
{
|
|
356
352
|
...this.#props,
|
|
357
|
-
accountGivenName: this.#props.userInfo.accountGivenName ?? '',
|
|
358
353
|
handleScroll: this.#handleScroll,
|
|
359
354
|
handleSuggestionClick: this.#handleSuggestionClick,
|
|
360
355
|
handleMessageContainerRef: this.#handleMessageContainerRef,
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// Copyright 2026 The Chromium Authors
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
import * as SDK from '../../../core/sdk/sdk.js';
|
|
6
|
+
import type * as Protocol from '../../../generated/protocol.js';
|
|
7
|
+
import * as Marked from '../../../third_party/marked/marked.js';
|
|
8
|
+
import type * as MarkdownView from '../../../ui/components/markdown_view/MarkdownView.js';
|
|
9
|
+
import * as Lit from '../../../ui/lit/lit.js';
|
|
10
|
+
import * as PanelsCommon from '../../common/common.js';
|
|
11
|
+
|
|
12
|
+
import {MarkdownRendererWithCodeBlock} from './MarkdownRendererWithCodeBlock.js';
|
|
13
|
+
|
|
14
|
+
const {html} = Lit.StaticHtml;
|
|
15
|
+
const {ref, createRef} = Lit.Directives;
|
|
16
|
+
|
|
17
|
+
export class StylingAgentMarkdownRenderer extends MarkdownRendererWithCodeBlock {
|
|
18
|
+
constructor(
|
|
19
|
+
private mainFrameId = '',
|
|
20
|
+
) {
|
|
21
|
+
super();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#renderTableFromJson(data: Array<Record<string, string>>): Lit.LitTemplate|null {
|
|
25
|
+
if (!Array.isArray(data) || data.length === 0 || typeof data[0] !== 'object' || data[0] === null) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const headers = Object.keys(data[0]);
|
|
30
|
+
const requiredKeys = ['Problem', 'Element', 'NodeId', 'Details'];
|
|
31
|
+
if (!requiredKeys.every(key => headers.includes(key))) {
|
|
32
|
+
return null; // Not the expected JSON structure
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const problemIndex = headers.indexOf('Problem');
|
|
36
|
+
if (problemIndex > -1) {
|
|
37
|
+
const problemHeader = headers.splice(problemIndex, 1);
|
|
38
|
+
headers.unshift(...problemHeader);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return html`
|
|
42
|
+
<table style="width: 100%;">
|
|
43
|
+
<thead>
|
|
44
|
+
<tr>
|
|
45
|
+
${headers.map(header => html`<th style="text-align: left;">${header === 'NodeId' ? '' : header}</th>`)}
|
|
46
|
+
</tr>
|
|
47
|
+
</thead>
|
|
48
|
+
<tbody>
|
|
49
|
+
${data.flatMap(row => {
|
|
50
|
+
return html`
|
|
51
|
+
<tr>
|
|
52
|
+
${headers.map(header => {
|
|
53
|
+
if (header === 'NodeId') {
|
|
54
|
+
return html`<td>${this.#renderLinkifiedText(row[header])}</td>`;
|
|
55
|
+
}
|
|
56
|
+
if (header === 'Details') {
|
|
57
|
+
// eslint-disable-next-line @devtools/no-a-tags-in-lit
|
|
58
|
+
return html`<td><a href="#" @click=${this.#toggleDetailsRow}>Details</a></td>`;
|
|
59
|
+
}
|
|
60
|
+
return html`<td>${row[header]}</td>`;
|
|
61
|
+
})}
|
|
62
|
+
</tr>
|
|
63
|
+
<tr class="details-row" style="display: none;">
|
|
64
|
+
<td colspan=${headers.length} style="background-color: #f0f0f0; padding: 1em;">
|
|
65
|
+
<devtools-markdown-view .data=${{
|
|
66
|
+
tokens: Marked.Marked.lexer(row['Details']),
|
|
67
|
+
renderer: new StylingAgentMarkdownRenderer(this.mainFrameId),
|
|
68
|
+
} as MarkdownView.MarkdownViewData}></devtools-markdown-view>
|
|
69
|
+
</td>
|
|
70
|
+
</tr>
|
|
71
|
+
`;
|
|
72
|
+
})}
|
|
73
|
+
</tbody>
|
|
74
|
+
</table>
|
|
75
|
+
<br><div>To investigate these problems, please click one of the provided links (above), to set as context, and ask me further questions about the problem.</div>
|
|
76
|
+
`;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
override templateForToken(token: Marked.Marked.MarkedToken): Lit.LitTemplate|null {
|
|
80
|
+
if (token.type === 'code') {
|
|
81
|
+
try {
|
|
82
|
+
const data = JSON.parse(token.text);
|
|
83
|
+
const table = this.#renderTableFromJson(data);
|
|
84
|
+
if (table) {
|
|
85
|
+
return table;
|
|
86
|
+
}
|
|
87
|
+
} catch {
|
|
88
|
+
// Not a JSON object, fallback to default rendering.
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (token.type === 'link' && token.href.startsWith('#')) {
|
|
93
|
+
let nodeId = undefined;
|
|
94
|
+
if (token.href.startsWith('#node-')) {
|
|
95
|
+
nodeId = Number(token.href.replace('#node-', '')) as Protocol.DOM.BackendNodeId;
|
|
96
|
+
} else if (token.href.startsWith('#')) {
|
|
97
|
+
// So often does it ignore requests to prepend nodes with node-, frustratingly.
|
|
98
|
+
nodeId = Number(token.href.replace('#', '')) as Protocol.DOM.BackendNodeId;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (nodeId) {
|
|
102
|
+
const templateRef = createRef();
|
|
103
|
+
void this.#linkifyNode(nodeId, token.text).then(node => {
|
|
104
|
+
if (!templateRef.value || !node) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
templateRef.value.textContent = '';
|
|
109
|
+
templateRef.value.append(node);
|
|
110
|
+
});
|
|
111
|
+
return html`<span ${ref(templateRef)}>${token.text}</span>`;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return super.templateForToken(token);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
#toggleDetailsRow(e: Event): void {
|
|
119
|
+
e.preventDefault();
|
|
120
|
+
const link = e.target as HTMLAnchorElement;
|
|
121
|
+
const currentRow = link.closest('tr');
|
|
122
|
+
if (!currentRow) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const detailsRow = currentRow.nextElementSibling as HTMLTableRowElement | null;
|
|
126
|
+
if (detailsRow?.classList.contains('details-row')) {
|
|
127
|
+
if (detailsRow.style.display === 'none') {
|
|
128
|
+
detailsRow.style.display = 'table-row';
|
|
129
|
+
link.textContent = 'Hide';
|
|
130
|
+
} else {
|
|
131
|
+
detailsRow.style.display = 'none';
|
|
132
|
+
link.textContent = 'Details';
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
#renderLinkifiedText(text: string): Lit.LitTemplate {
|
|
138
|
+
if (text.indexOf(',') === -1) {
|
|
139
|
+
const nodeId = Number(text) as Protocol.DOM.BackendNodeId;
|
|
140
|
+
if (isNaN(nodeId)) {
|
|
141
|
+
// Not a number, return as is.
|
|
142
|
+
return html`${text}`;
|
|
143
|
+
}
|
|
144
|
+
return this.#renderSingleLink(nodeId);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Check for comma separated list.
|
|
148
|
+
const nodeIdsStr = text.split(',').map(s => s.trim()).filter(Boolean);
|
|
149
|
+
return html`${nodeIdsStr.map(idStr => {
|
|
150
|
+
const nodeId = Number(idStr) as Protocol.DOM.BackendNodeId;
|
|
151
|
+
if (isNaN(nodeId)) {
|
|
152
|
+
return html`<div>${idStr}</div>`;
|
|
153
|
+
}
|
|
154
|
+
return html`<div>${this.#renderSingleLink(nodeId)}</div>`;
|
|
155
|
+
})}`;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
#renderSingleLink(nodeId: Protocol.DOM.BackendNodeId): Lit.LitTemplate {
|
|
159
|
+
const label = `link`;
|
|
160
|
+
const templateRef = createRef();
|
|
161
|
+
void this.#linkifyNode(nodeId, label).then(node => {
|
|
162
|
+
if (!templateRef.value) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
templateRef.value.textContent = '';
|
|
166
|
+
if (node) {
|
|
167
|
+
templateRef.value.append(node);
|
|
168
|
+
} else {
|
|
169
|
+
// Fallback to plain text if linkification fails
|
|
170
|
+
templateRef.value.append(document.createTextNode(label));
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
// Placeholder for async link
|
|
174
|
+
return html`<span ${ref(templateRef)}>${label}</span>`;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async #linkifyNode(backendNodeId: Protocol.DOM.BackendNodeId, label: string): Promise<Node|undefined> {
|
|
178
|
+
if (backendNodeId === undefined) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
|
|
183
|
+
const domModel = target?.model(SDK.DOMModel.DOMModel);
|
|
184
|
+
if (!domModel) {
|
|
185
|
+
return undefined;
|
|
186
|
+
}
|
|
187
|
+
const domNodesMap = await domModel.pushNodesByBackendIdsToFrontend(new Set([backendNodeId]));
|
|
188
|
+
const node = domNodesMap?.get(backendNodeId);
|
|
189
|
+
if (!node) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (node.frameId() !== this.mainFrameId) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const linkedNode = PanelsCommon.DOMLinkifier.Linkifier.instance().linkify(node, {textContent: label});
|
|
198
|
+
return linkedNode;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
@@ -143,14 +143,6 @@
|
|
|
143
143
|
gap: var(--sys-size-4);
|
|
144
144
|
font: var(--sys-typescale-body4-bold);
|
|
145
145
|
|
|
146
|
-
img {
|
|
147
|
-
border: 0;
|
|
148
|
-
border-radius: var(--sys-shape-corner-full);
|
|
149
|
-
display: block;
|
|
150
|
-
height: var(--sys-size-9);
|
|
151
|
-
width: var(--sys-size-9);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
146
|
h2 {
|
|
155
147
|
font: var(--sys-typescale-body4-bold);
|
|
156
148
|
}
|
|
@@ -178,7 +178,7 @@ export class ServiceWorkerCacheView extends UI.View.SimpleView {
|
|
|
178
178
|
this.dataGrid = this.createDataGrid();
|
|
179
179
|
const dataGridWidget = this.dataGrid.asWidget();
|
|
180
180
|
this.splitWidget.setSidebarWidget(dataGridWidget);
|
|
181
|
-
dataGridWidget.setMinimumSize(0,
|
|
181
|
+
dataGridWidget.setMinimumSize(0, 100);
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
override wasShown(): void {
|
|
@@ -1574,6 +1574,21 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
1574
1574
|
return this.status.E_FAILED('Permission denied');
|
|
1575
1575
|
}
|
|
1576
1576
|
|
|
1577
|
+
try {
|
|
1578
|
+
const parsedUrl = new URL(frame.url);
|
|
1579
|
+
let targetType = Host.UserMetrics.ExtensionEvalTarget.WEB_PAGE;
|
|
1580
|
+
if (parsedUrl.protocol === 'chrome-extension:') {
|
|
1581
|
+
if (parsedUrl.origin === securityOrigin) {
|
|
1582
|
+
targetType = Host.UserMetrics.ExtensionEvalTarget.SAME_EXTENSION;
|
|
1583
|
+
} else {
|
|
1584
|
+
targetType = Host.UserMetrics.ExtensionEvalTarget.OTHER_EXTENSION;
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
Host.userMetrics.extensionEvalTarget(targetType);
|
|
1588
|
+
} catch {
|
|
1589
|
+
// Ignore invalid URLs.
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1577
1592
|
void context
|
|
1578
1593
|
.evaluate(
|
|
1579
1594
|
{
|
|
@@ -284,8 +284,8 @@ const UIStrings = {
|
|
|
284
284
|
*/
|
|
285
285
|
startAChat: 'Start a chat',
|
|
286
286
|
/**
|
|
287
|
-
|
|
288
|
-
|
|
287
|
+
* @description Label of an adorner next to the html node in the Elements panel.
|
|
288
|
+
*/
|
|
289
289
|
viewSourceCode: 'View source code',
|
|
290
290
|
/**
|
|
291
291
|
* @description Context menu item in Elements panel to assess visibility of an element via AI.
|
|
@@ -436,7 +436,6 @@ export interface ViewInput {
|
|
|
436
436
|
showAiButton: boolean;
|
|
437
437
|
aiButtonTitle?: string;
|
|
438
438
|
onAiButtonClick: (e: Event) => void;
|
|
439
|
-
|
|
440
439
|
decorations: Decoration[];
|
|
441
440
|
descendantDecorations: Decoration[];
|
|
442
441
|
decorationsTooltip: string;
|
|
@@ -806,16 +805,13 @@ function renderAttribute(
|
|
|
806
805
|
|
|
807
806
|
// clang-format off
|
|
808
807
|
return html`<span class="webkit-html-attribute" jslog=${jslog}><span class="webkit-html-attribute-name"
|
|
809
|
-
${animateOn(Boolean(updateRecord?.isAttributeModified(name) && !hasText), DOM_UPDATE_ANIMATION_CLASS_NAME)} ${
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
animateOn(
|
|
813
|
-
Boolean(updateRecord?.isAttributeModified(name) && hasText),
|
|
814
|
-
DOM_UPDATE_ANIMATION_CLASS_NAME)} ${valueRelationRefDirective} ${withEntitiesRef}>
|
|
808
|
+
${animateOn(Boolean(updateRecord?.isAttributeModified(name) && !hasText), DOM_UPDATE_ANIMATION_CLASS_NAME)} ${relationRefDirective}>${name}</span>${hasText ? html`=\u200B"<span class="webkit-html-attribute-value" ${animateOn(
|
|
809
|
+
Boolean(updateRecord?.isAttributeModified(name) && hasText),
|
|
810
|
+
DOM_UPDATE_ANIMATION_CLASS_NAME)} ${valueRelationRefDirective} ${withEntitiesRef}>
|
|
815
811
|
${valueType === ValueType.SRC ? renderLinkifiedValue(value, node) : nothing}
|
|
816
812
|
${valueType === ValueType.SRCSET ? renderLinkifiedSrcset(Common.Srcset.parseSrcset(value), node) : nothing}
|
|
817
813
|
</span>"` :
|
|
818
|
-
|
|
814
|
+
nothing}</span>`;
|
|
819
815
|
// clang-format on
|
|
820
816
|
}
|
|
821
817
|
|
|
@@ -868,15 +864,15 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
868
864
|
render(html`
|
|
869
865
|
<div ${ref(el => { output.contentElement = el as HTMLElement; })}>
|
|
870
866
|
${input.node ? html`<span class="highlight">${renderTitle(
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
867
|
+
input.node,
|
|
868
|
+
input.isClosingTag,
|
|
869
|
+
input.expanded,
|
|
870
|
+
input.isExpandable,
|
|
871
|
+
input.isXMLMimeType,
|
|
872
|
+
input.updateRecord,
|
|
873
|
+
input.onHighlightSearchResults,
|
|
874
|
+
input.onExpand,
|
|
875
|
+
)}</span>` : nothing}
|
|
880
876
|
${input.isHovered || input.isSelected ? html`
|
|
881
877
|
<div class="selection fill" style=${`margin-left: ${-input.indent}px`}></div>
|
|
882
878
|
` : nothing}
|
|
@@ -913,7 +909,7 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
913
909
|
toggleable=true
|
|
914
910
|
tabindex=0
|
|
915
911
|
.name=${ElementsComponents.AdornerManager.RegisteredAdorners.CONTAINER}
|
|
916
|
-
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.CONTAINER).track({click: true})}
|
|
912
|
+
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.CONTAINER).track({ click: true })}
|
|
917
913
|
active=${input.containerAdornerActive}
|
|
918
914
|
aria-label=${input.containerAdornerActive ? i18nString(UIStrings.enableContainer) : i18nString(UIStrings.disableContainer)}
|
|
919
915
|
@click=${input.onContainerAdornerClick}
|
|
@@ -930,7 +926,7 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
930
926
|
toggleable=true
|
|
931
927
|
tabindex=0
|
|
932
928
|
.name=${ElementsComponents.AdornerManager.RegisteredAdorners.FLEX}
|
|
933
|
-
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.FLEX).track({click: true})}
|
|
929
|
+
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.FLEX).track({ click: true })}
|
|
934
930
|
active=${input.flexAdornerActive}
|
|
935
931
|
aria-label=${input.flexAdornerActive ? i18nString(UIStrings.disableFlexMode) : i18nString(UIStrings.enableFlexMode)}
|
|
936
932
|
@click=${input.onFlexAdornerClick}
|
|
@@ -944,7 +940,7 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
944
940
|
toggleable=true
|
|
945
941
|
tabindex=0
|
|
946
942
|
.name=${input.isSubgrid ? ElementsComponents.AdornerManager.RegisteredAdorners.SUBGRID : ElementsComponents.AdornerManager.RegisteredAdorners.GRID}
|
|
947
|
-
jslog=${VisualLogging.adorner(input.isSubgrid ? ElementsComponents.AdornerManager.RegisteredAdorners.SUBGRID : ElementsComponents.AdornerManager.RegisteredAdorners.GRID).track({click: true})}
|
|
943
|
+
jslog=${VisualLogging.adorner(input.isSubgrid ? ElementsComponents.AdornerManager.RegisteredAdorners.SUBGRID : ElementsComponents.AdornerManager.RegisteredAdorners.GRID).track({ click: true })}
|
|
948
944
|
active=${input.gridAdornerActive}
|
|
949
945
|
aria-label=${input.gridAdornerActive ? i18nString(UIStrings.disableGridMode) : i18nString(UIStrings.enableGridMode)}
|
|
950
946
|
@click=${input.onGridAdornerClick}
|
|
@@ -958,7 +954,7 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
958
954
|
toggleable=true
|
|
959
955
|
tabindex=0
|
|
960
956
|
.name=${ElementsComponents.AdornerManager.RegisteredAdorners.GRID_LANES}
|
|
961
|
-
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.GRID_LANES).track({click: true})}
|
|
957
|
+
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.GRID_LANES).track({ click: true })}
|
|
962
958
|
active=${input.gridAdornerActive}
|
|
963
959
|
aria-label=${input.gridAdornerActive ? i18nString(UIStrings.disableGridLanesMode) : i18nString(UIStrings.enableGridLanesMode)}
|
|
964
960
|
@click=${input.onGridAdornerClick}
|
|
@@ -971,7 +967,7 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
971
967
|
role=button
|
|
972
968
|
tabindex=0
|
|
973
969
|
.name=${ElementsComponents.AdornerManager.RegisteredAdorners.MEDIA}
|
|
974
|
-
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.MEDIA).track({click: true})}
|
|
970
|
+
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.MEDIA).track({ click: true })}
|
|
975
971
|
aria-label=${i18nString(UIStrings.openMediaPanel)}
|
|
976
972
|
@click=${input.onMediaAdornerClick}
|
|
977
973
|
@keydown=${handleAdornerKeydown(input.onMediaAdornerClick)}
|
|
@@ -986,7 +982,7 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
986
982
|
toggleable=true
|
|
987
983
|
tabindex=0
|
|
988
984
|
.name=${ElementsComponents.AdornerManager.RegisteredAdorners.POPOVER}
|
|
989
|
-
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.POPOVER).track({click: true})}
|
|
985
|
+
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.POPOVER).track({ click: true })}
|
|
990
986
|
active=${input.popoverAdornerActive}
|
|
991
987
|
aria-label=${input.popoverAdornerActive ? i18nString(UIStrings.stopForceOpenPopover) : i18nString(UIStrings.forceOpenPopover)}
|
|
992
988
|
@click=${input.onPopoverAdornerClick}
|
|
@@ -999,7 +995,7 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
999
995
|
role=button
|
|
1000
996
|
tabindex=0
|
|
1001
997
|
.name=${ElementsComponents.AdornerManager.RegisteredAdorners.TOP_LAYER}
|
|
1002
|
-
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.TOP_LAYER).track({click: true})}
|
|
998
|
+
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.TOP_LAYER).track({ click: true })}
|
|
1003
999
|
aria-label=${i18nString(UIStrings.reveal)}
|
|
1004
1000
|
@click=${input.onTopLayerAdornerClick}
|
|
1005
1001
|
@keydown=${handleAdornerKeydown(input.onTopLayerAdornerClick)}
|
|
@@ -1011,7 +1007,7 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
1011
1007
|
${input.showStartingStyleAdorner ? html`<devtools-adorner
|
|
1012
1008
|
class="starting-style"
|
|
1013
1009
|
.name=${ElementsComponents.AdornerManager.RegisteredAdorners.STARTING_STYLE}
|
|
1014
|
-
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.STARTING_STYLE).track({click: true})}
|
|
1010
|
+
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.STARTING_STYLE).track({ click: true })}
|
|
1015
1011
|
active=${input.startingStyleAdornerActive}
|
|
1016
1012
|
toggleable=true
|
|
1017
1013
|
aria-label=${input.startingStyleAdornerActive ? i18nString(UIStrings.disableStartingStyle) : i18nString(UIStrings.enableStartingStyle)}
|
|
@@ -1023,7 +1019,7 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
1023
1019
|
${input.showScrollAdorner ? html`<devtools-adorner
|
|
1024
1020
|
class="scroll"
|
|
1025
1021
|
.name=${ElementsComponents.AdornerManager.RegisteredAdorners.SCROLL}
|
|
1026
|
-
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.SCROLL).track({click: true})}
|
|
1022
|
+
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.SCROLL).track({ click: true })}
|
|
1027
1023
|
aria-label=${i18nString(UIStrings.elementHasScrollableOverflow)}
|
|
1028
1024
|
${adornerRef()}>
|
|
1029
1025
|
<span>${ElementsComponents.AdornerManager.RegisteredAdorners.SCROLL}</span>
|
|
@@ -1033,7 +1029,7 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
1033
1029
|
role=button
|
|
1034
1030
|
tabindex=0
|
|
1035
1031
|
.name=${ElementsComponents.AdornerManager.RegisteredAdorners.SLOT}
|
|
1036
|
-
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.SLOT).track({click: true})}
|
|
1032
|
+
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.SLOT).track({ click: true })}
|
|
1037
1033
|
@click=${input.onSlotAdornerClick}
|
|
1038
1034
|
@mousedown=${(e: Event) => e.stopPropagation()}
|
|
1039
1035
|
${adornerRef()}>
|
|
@@ -1045,7 +1041,7 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
1045
1041
|
${input.showScrollSnapAdorner ? html`<devtools-adorner
|
|
1046
1042
|
class="scroll-snap"
|
|
1047
1043
|
.name=${ElementsComponents.AdornerManager.RegisteredAdorners.SCROLL_SNAP}
|
|
1048
|
-
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.SCROLL_SNAP).track({click: true})}
|
|
1044
|
+
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.SCROLL_SNAP).track({ click: true })}
|
|
1049
1045
|
active=${input.scrollSnapAdornerActive}
|
|
1050
1046
|
toggleable=true
|
|
1051
1047
|
aria-label=${input.scrollSnapAdornerActive ? i18nString(UIStrings.disableScrollSnap) : i18nString(UIStrings.enableScrollSnap)}
|
|
@@ -1056,7 +1052,7 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
1056
1052
|
</devtools-adorner>` : nothing}
|
|
1057
1053
|
</div>`: nothing}
|
|
1058
1054
|
${input.isSelected ? html`
|
|
1059
|
-
<span class="selected-hint" title=${i18nString(UIStrings.useSInTheConsoleToReferToThis, {PH1: '$0'})} aria-hidden="true"></span>
|
|
1055
|
+
<span class="selected-hint" title=${i18nString(UIStrings.useSInTheConsoleToReferToThis, { PH1: '$0' })} aria-hidden="true"></span>
|
|
1060
1056
|
` : nothing}
|
|
1061
1057
|
${input.showAiButton ? html`
|
|
1062
1058
|
<span class="ai-button-container">
|
|
@@ -1261,7 +1257,8 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1261
1257
|
showSlotAdorner: Boolean(this.nodeInternal.assignedSlot) && !this.isClosingTag(),
|
|
1262
1258
|
showStartingStyleAdorner: this.nodeInternal.affectedByStartingStyles() && !this.isClosingTag(),
|
|
1263
1259
|
startingStyleAdornerActive: this.#startingStyleAdornerActive,
|
|
1264
|
-
onStartingStyleAdornerClick:
|
|
1260
|
+
onStartingStyleAdornerClick:
|
|
1261
|
+
this.treeOutline?.disableEdits ? () => {} : (event: Event) => this.#onStartingStyleAdornerClick(event),
|
|
1265
1262
|
onSlotAdornerClick: () => {
|
|
1266
1263
|
if (this.nodeInternal.assignedSlot) {
|
|
1267
1264
|
const deferredNode = this.nodeInternal.assignedSlot.deferredNode;
|
|
@@ -1271,25 +1268,32 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1271
1268
|
}
|
|
1272
1269
|
},
|
|
1273
1270
|
topLayerIndex: this.node().topLayerIndex(),
|
|
1274
|
-
onViewSourceAdornerClick: this.revealHTMLInSources.bind(this),
|
|
1271
|
+
onViewSourceAdornerClick: this.treeOutline?.disableEdits ? () => {} : this.revealHTMLInSources.bind(this),
|
|
1275
1272
|
onGutterClick: this.showContextMenu.bind(this),
|
|
1276
|
-
onContainerAdornerClick:
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1273
|
+
onContainerAdornerClick:
|
|
1274
|
+
this.treeOutline?.disableEdits ? () => {} : (event: Event) => this.#onContainerAdornerClick(event),
|
|
1275
|
+
onFlexAdornerClick: this.treeOutline?.disableEdits ? () => {} :
|
|
1276
|
+
(event: Event) => this.#onFlexAdornerClick(event),
|
|
1277
|
+
onGridAdornerClick: this.treeOutline?.disableEdits ? () => {} :
|
|
1278
|
+
(event: Event) => this.#onGridAdornerClick(event),
|
|
1279
|
+
onMediaAdornerClick: this.treeOutline?.disableEdits ? () => {} :
|
|
1280
|
+
(event: Event) => this.#onMediaAdornerClick(event),
|
|
1281
|
+
onPopoverAdornerClick: this.treeOutline?.disableEdits ? () => {} :
|
|
1282
|
+
(event: Event) => this.#onPopoverAdornerClick(event),
|
|
1283
|
+
onScrollSnapAdornerClick:
|
|
1284
|
+
this.treeOutline?.disableEdits ? () => {} : (event: Event) => this.#onScrollSnapAdornerClick(event),
|
|
1285
|
+
onTopLayerAdornerClick: this.treeOutline?.disableEdits ? () => {} :
|
|
1286
|
+
() => {
|
|
1287
|
+
if (!this.treeOutline) {
|
|
1288
|
+
return;
|
|
1289
|
+
}
|
|
1290
|
+
this.treeOutline.revealInTopLayer(this.node());
|
|
1291
|
+
},
|
|
1288
1292
|
isHovered: this.#hovered,
|
|
1289
1293
|
isSelected: this.selected,
|
|
1290
1294
|
showAiButton: Boolean(this.#hovered || this.selected) && this.node().nodeType() === Node.ELEMENT_NODE &&
|
|
1291
|
-
|
|
1292
|
-
aiButtonTitle:
|
|
1295
|
+
this.isAiButtonEnabled() && (this.treeOutline as ElementsTreeOutline)?.showAIButton,
|
|
1296
|
+
aiButtonTitle: this.isAiButtonEnabled() ?
|
|
1293
1297
|
UI.ActionRegistry.ActionRegistry.instance().getAction('freestyler.elements-floating-button').title() :
|
|
1294
1298
|
undefined,
|
|
1295
1299
|
onAiButtonClick: (ev: Event) => {
|
|
@@ -1893,6 +1897,10 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1893
1897
|
{jslogContext: 'scroll-into-view'});
|
|
1894
1898
|
}
|
|
1895
1899
|
|
|
1900
|
+
private isAiButtonEnabled(): boolean {
|
|
1901
|
+
return UI.ActionRegistry.ActionRegistry.instance().hasAction('freestyler.elements-floating-button');
|
|
1902
|
+
}
|
|
1903
|
+
|
|
1896
1904
|
async populateTextContextMenu(contextMenu: UI.ContextMenu.ContextMenu, textNode: Element): Promise<void> {
|
|
1897
1905
|
if (!this.editing) {
|
|
1898
1906
|
contextMenu.editSection().appendItem(
|