chrome-devtools-frontend 1.0.1007846 → 1.0.1008735

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.
@@ -984,7 +984,6 @@ grd_files_debug_sources = [
984
984
  "front_end/panels/elements/components/queryContainer.css.js",
985
985
  "front_end/panels/elements/components/stylePropertyEditor.css.js",
986
986
  "front_end/panels/elements/computedStyleSidebarPane.css.js",
987
- "front_end/panels/elements/computedStyleWidgetTree.css.js",
988
987
  "front_end/panels/elements/domLinkifier.css.js",
989
988
  "front_end/panels/elements/elementStatePaneWidget.css.js",
990
989
  "front_end/panels/elements/elementsPanel.css.js",
@@ -470,8 +470,16 @@ export class ParsedURL {
470
470
  return ParsedURL.substring(url as Platform.DevToolsPath.UrlString, 0, wasmFunctionIndex);
471
471
  }
472
472
 
473
+ private static beginsWithWindowsDriveLetter(url: string): boolean {
474
+ return /^[A-Za-z]:/.test(url);
475
+ }
476
+
477
+ private static beginsWithScheme(url: string): boolean {
478
+ return /^[A-Za-z][A-Za-z0-9+.-]*:/.test(url);
479
+ }
480
+
473
481
  static isRelativeURL(url: string): boolean {
474
- return !(/^[A-Za-z][A-Za-z0-9+.-]*:/.test(url));
482
+ return !this.beginsWithScheme(url) || this.beginsWithWindowsDriveLetter(url);
475
483
  }
476
484
 
477
485
  get displayName(): string {
@@ -1469,9 +1469,6 @@
1469
1469
  "models/issues_manager/DeprecationIssue.ts | rtcpMuxPolicyNegotiate": {
1470
1470
  "message": "The rtcpMuxPolicy option is deprecated and will be removed."
1471
1471
  },
1472
- "models/issues_manager/DeprecationIssue.ts | rtpDataChannel": {
1473
- "message": "RTP data channels are no longer supported. The RtpDataChannels constraint is currently ignored, and may cause an error at a later date."
1474
- },
1475
1472
  "models/issues_manager/DeprecationIssue.ts | sharedArrayBufferConstructedWithoutIsolation": {
1476
1473
  "message": "SharedArrayBuffer will require cross-origin isolation. See https://developer.chrome.com/blog/enabling-shared-array-buffer/ for more details."
1477
1474
  },
@@ -1469,9 +1469,6 @@
1469
1469
  "models/issues_manager/DeprecationIssue.ts | rtcpMuxPolicyNegotiate": {
1470
1470
  "message": "T̂h́ê rtcpMuxPolicy óp̂t́îón̂ íŝ d́êṕr̂éĉát̂éd̂ án̂d́ ŵíl̂ĺ b̂é r̂ém̂óv̂éd̂."
1471
1471
  },
1472
- "models/issues_manager/DeprecationIssue.ts | rtpDataChannel": {
1473
- "message": "RTP data channels âŕê ńô ĺôńĝér̂ śûṕp̂ór̂t́êd́. T̂h́ê RtpDataChannels ćôńŝt́r̂áîńt̂ íŝ ćûŕr̂én̂t́l̂ý îǵn̂ór̂éd̂, án̂d́ m̂áŷ ćâúŝé âń êŕr̂ór̂ át̂ á l̂át̂ér̂ d́ât́ê."
1474
- },
1475
1472
  "models/issues_manager/DeprecationIssue.ts | sharedArrayBufferConstructedWithoutIsolation": {
1476
1473
  "message": "SharedArrayBuffer ŵíl̂ĺ r̂éq̂úîŕê ćr̂óŝś-ôŕîǵîń îśôĺât́îón̂. Śêé ĥt́t̂ṕŝ://d́êv́êĺôṕêŕ.ĉh́r̂óm̂é.ĉóm̂/b́l̂óĝ/én̂áb̂ĺîńĝ-śĥár̂éd̂-ár̂ŕâý-b̂úf̂f́êŕ/ f̂ór̂ ḿôŕê d́êt́âíl̂ś."
1477
1474
  },
@@ -315,7 +315,6 @@ export function registerCommands(inspectorBackend) {
315
315
  'RTCPeerConnectionComplexPlanBSdpUsingDefaultSdpSemantics',
316
316
  RTCPeerConnectionSdpSemanticsPlanB: 'RTCPeerConnectionSdpSemanticsPlanB',
317
317
  RtcpMuxPolicyNegotiate: 'RtcpMuxPolicyNegotiate',
318
- RTPDataChannel: 'RTPDataChannel',
319
318
  SharedArrayBufferConstructedWithoutIsolation: 'SharedArrayBufferConstructedWithoutIsolation',
320
319
  TextToSpeech_DisallowedByAutoplay: 'TextToSpeech_DisallowedByAutoplay',
321
320
  V8SharedArrayBufferConstructedInExtensionWithoutIsolation:
@@ -2380,7 +2379,8 @@ export function registerCommands(inspectorBackend) {
2380
2379
  inspectorBackend.registerEnum(
2381
2380
  'Page.FileChooserOpenedEventMode', {SelectSingle: 'selectSingle', SelectMultiple: 'selectMultiple'});
2382
2381
  inspectorBackend.registerEvent('Page.fileChooserOpened', ['frameId', 'backendNodeId', 'mode']);
2383
- inspectorBackend.registerEvent('Page.frameAttached', ['frameId', 'parentFrameId', 'stack']);
2382
+ inspectorBackend.registerEvent(
2383
+ 'Page.frameAttached', ['frameId', 'parentFrameId', 'stack', 'adScriptId', 'debuggerId']);
2384
2384
  inspectorBackend.registerEvent('Page.frameClearedScheduledNavigation', ['frameId']);
2385
2385
  inspectorBackend.registerEnum('Page.FrameDetachedEventReason', {Remove: 'remove', Swap: 'swap'});
2386
2386
  inspectorBackend.registerEvent('Page.frameDetached', ['frameId', 'reason']);
@@ -1062,7 +1062,6 @@ export namespace Audits {
1062
1062
  'RTCPeerConnectionComplexPlanBSdpUsingDefaultSdpSemantics',
1063
1063
  RTCPeerConnectionSdpSemanticsPlanB = 'RTCPeerConnectionSdpSemanticsPlanB',
1064
1064
  RtcpMuxPolicyNegotiate = 'RtcpMuxPolicyNegotiate',
1065
- RTPDataChannel = 'RTPDataChannel',
1066
1065
  SharedArrayBufferConstructedWithoutIsolation = 'SharedArrayBufferConstructedWithoutIsolation',
1067
1066
  TextToSpeech_DisallowedByAutoplay = 'TextToSpeech_DisallowedByAutoplay',
1068
1067
  V8SharedArrayBufferConstructedInExtensionWithoutIsolation =
@@ -11765,6 +11764,8 @@ export namespace Page {
11765
11764
  * JavaScript stack trace of when frame was attached, only set if frame initiated from script.
11766
11765
  */
11767
11766
  stack?: Runtime.StackTrace;
11767
+ adScriptId?: Runtime.ScriptId;
11768
+ debuggerId?: Runtime.UniqueDebuggerId;
11768
11769
  }
11769
11770
 
11770
11771
  /**
@@ -183,20 +183,20 @@ ElementsTestRunner.computedStyleWidget = function() {
183
183
 
184
184
  ElementsTestRunner.dumpComputedStyle = async function(doNotAutoExpand, printInnerText) {
185
185
  const computed = ElementsTestRunner.computedStyleWidget();
186
- const treeOutline = computed.propertiesOutline;
187
- const children = treeOutline.rootElement().children();
186
+ const treeOutline = computed.propertiesOutline.querySelector('devtools-tree-outline');
187
+ const children = treeOutline.shadowRoot.querySelector('[role="treeitem"]');
188
188
 
189
189
  for (const treeElement of children) {
190
- const property = computed.propertyByTreeElement.get(treeElement);
191
- if (!property || property.name === 'width' || property.name === 'height') {
190
+ const property = treeElement.querySelector('devtools-computed-style-property')?.shadowRoot;
191
+ const propertyName = text(property?.querySelector('.webkit-css-property'));
192
+ const propertyValue = text(property?.querySelector('.value'));
193
+ if (!property || propertyName === 'width' || propertyName === 'height') {
192
194
  continue;
193
195
  }
194
196
 
195
- const propertyName = text(treeElement.title.querySelector('.webkit-css-property'));
196
- const propertyValue = text(treeElement.title.querySelector('.value'));
197
197
  TestRunner.addResult(`${propertyName}: ${propertyValue};`);
198
198
 
199
- if (doNotAutoExpand && !treeElement.expanded) {
199
+ if (doNotAutoExpand && !treeElement.ariaExpanded) {
200
200
  continue;
201
201
  }
202
202
 
@@ -211,7 +211,7 @@ ElementsTestRunner.dumpComputedStyle = async function(doNotAutoExpand, printInne
211
211
  dumpText += text(trace.querySelector('.value'));
212
212
  dumpText += ' - ';
213
213
  dumpText += text(trace.shadowRoot.querySelector('.trace-selector'));
214
- const link = trace.querySelector('[slot="trace-link"]');
214
+ const link = trace.shadowRoot.querySelector('.trace-link');
215
215
 
216
216
  if (link) {
217
217
  dumpText += ' ' + await extractLinkText(link);
@@ -243,16 +243,6 @@ const UIStrings = {
243
243
  * `RTCP MUX` policy.
244
244
  */
245
245
  rtcpMuxPolicyNegotiate: 'The `rtcpMuxPolicy` option is deprecated and will be removed.',
246
- /**
247
- * @description A deprecation warning shown in the DevTools Issues tab.
248
- * It's shown when a video conferencing website attempts to turn on or
249
- * off a feature that has been removed, `RTP data channels`.
250
- * `RTP data channels` are used to send and receive arbitrary data,
251
- * but have been removed in favor of standardized versions of
252
- * `data channels`: `SCTP data channels`.
253
- */
254
- rtpDataChannel:
255
- '`RTP data channels` are no longer supported. The `RtpDataChannels` constraint is currently ignored, and may cause an error at a later date.',
256
246
  /**
257
247
  * @description TODO(crbug.com/1318878): Description needed for translation
258
248
  */
@@ -500,10 +490,6 @@ export class DeprecationIssue extends Issue {
500
490
  feature = 5654810086866944;
501
491
  milestone = 62;
502
492
  break;
503
- case Protocol.Audits.DeprecationIssueType.RTPDataChannel:
504
- messageFunction = i18nLazyString(UIStrings.rtpDataChannel);
505
- milestone = 88;
506
- break;
507
493
  case Protocol.Audits.DeprecationIssueType.SharedArrayBufferConstructedWithoutIsolation:
508
494
  messageFunction = i18nLazyString(UIStrings.sharedArrayBufferConstructedWithoutIsolation);
509
495
  milestone = 106;
@@ -38,9 +38,9 @@ import * as SDK from '../../core/sdk/sdk.js';
38
38
  import * as InlineEditor from '../../ui/legacy/components/inline_editor/inline_editor.js';
39
39
  import * as Components from '../../ui/legacy/components/utils/utils.js';
40
40
  import * as UI from '../../ui/legacy/legacy.js';
41
+
41
42
  import * as ElementsComponents from './components/components.js';
42
43
  import computedStyleSidebarPaneStyles from './computedStyleSidebarPane.css.js';
43
- import computedStyleWidgetTreeStyles from './computedStyleWidgetTree.css.js';
44
44
 
45
45
  import type {ComputedStyle} from './ComputedStyleModel.js';
46
46
  import {ComputedStyleModel, Events} from './ComputedStyleModel.js';
@@ -49,7 +49,9 @@ import {PlatformFontsWidget} from './PlatformFontsWidget.js';
49
49
  import type {Category} from './PropertyNameCategories.js';
50
50
  import {categorizePropertyName, DefaultCategoryOrder} from './PropertyNameCategories.js';
51
51
  import {StylePropertiesSection} from './StylePropertiesSection.js';
52
- import {IdleCallbackManager, StylesSidebarPane, StylesSidebarPropertyRenderer} from './StylesSidebarPane.js';
52
+ import {StylesSidebarPane, StylesSidebarPropertyRenderer} from './StylesSidebarPane.js';
53
+ import * as TreeOutline from '../../ui/components/tree_outline/tree_outline.js';
54
+ import * as LitHtml from '../../ui/lit-html/lit-html.js';
53
55
 
54
56
  const UIStrings = {
55
57
  /**
@@ -92,23 +94,24 @@ const UIStrings = {
92
94
  const str_ = i18n.i18n.registerUIStrings('panels/elements/ComputedStyleWidget.ts', UIStrings);
93
95
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
94
96
 
95
- const createPropertyElement = (node: SDK.DOMModel.DOMNode, propertyName: string, propertyValue: string):
96
- ElementsComponents.ComputedStyleProperty.ComputedStyleProperty => {
97
- const propertyElement = new ElementsComponents.ComputedStyleProperty.ComputedStyleProperty();
98
-
99
- const renderer = new StylesSidebarPropertyRenderer(null, node, propertyName, propertyValue);
100
- renderer.setColorHandler(processColor);
97
+ const createPropertyElement =
98
+ (node: SDK.DOMModel.DOMNode, propertyName: string, propertyValue: string, traceable: boolean, inherited: boolean,
99
+ onNavigateToSource: ((event?: Event) => void)): ElementsComponents.ComputedStyleProperty.ComputedStyleProperty => {
100
+ const propertyElement = new ElementsComponents.ComputedStyleProperty.ComputedStyleProperty();
101
101
 
102
- const propertyNameElement = renderer.renderName();
103
- propertyNameElement.slot = 'property-name';
104
- propertyElement.appendChild(propertyNameElement);
102
+ const renderer = new StylesSidebarPropertyRenderer(null, node, propertyName, propertyValue);
103
+ renderer.setColorHandler(processColor);
105
104
 
106
- const propertyValueElement = renderer.renderValue();
107
- propertyValueElement.slot = 'property-value';
108
- propertyElement.appendChild(propertyValueElement);
105
+ propertyElement.data = {
106
+ propertyNameRenderer: renderer.renderName.bind(renderer),
107
+ propertyValueRenderer: renderer.renderValue.bind(renderer),
108
+ traceable,
109
+ inherited,
110
+ onNavigateToSource,
111
+ };
109
112
 
110
- return propertyElement;
111
- };
113
+ return propertyElement;
114
+ };
112
115
 
113
116
  const createTraceElement =
114
117
  (node: SDK.DOMModel.DOMNode, property: SDK.CSSProperty.CSSProperty, isPropertyOverloaded: boolean,
@@ -123,16 +126,15 @@ const createTraceElement =
123
126
  trace.appendChild(valueElement);
124
127
 
125
128
  const rule = (property.ownerStyle.parentRule as SDK.CSSRule.CSSStyleRule | null);
129
+ let ruleOriginNode;
126
130
  if (rule) {
127
- const linkSpan = document.createElement('span');
128
- linkSpan.appendChild(StylePropertiesSection.createRuleOriginNode(matchedStyles, linkifier, rule));
129
- linkSpan.slot = 'trace-link';
130
- trace.appendChild(linkSpan);
131
+ ruleOriginNode = StylePropertiesSection.createRuleOriginNode(matchedStyles, linkifier, rule);
131
132
  }
132
133
  trace.data = {
133
134
  selector: rule ? rule.selectorText() : 'element.style',
134
135
  active: !isPropertyOverloaded,
135
- onNavigateToSource: (navigateToSource.bind(null, property) as (arg0?: Event|undefined) => void),
136
+ onNavigateToSource: navigateToSource.bind(null, property),
137
+ ruleOriginNode,
136
138
  };
137
139
 
138
140
  return trace;
@@ -154,7 +156,10 @@ const processColor = (text: string): Node => {
154
156
  return swatch;
155
157
  };
156
158
 
157
- const navigateToSource = (cssProperty: SDK.CSSProperty.CSSProperty, event: Event): void => {
159
+ const navigateToSource = (cssProperty: SDK.CSSProperty.CSSProperty, event?: Event): void => {
160
+ if (!event) {
161
+ return;
162
+ }
158
163
  void Common.Revealer.reveal(cssProperty);
159
164
  event.consume(true);
160
165
  };
@@ -171,6 +176,20 @@ const propertySorter = (propA: string, propB: string): number => {
171
176
  return Platform.StringUtilities.compare(canonicalA, canonicalB);
172
177
  };
173
178
 
179
+ type ComputedStyleData = {
180
+ tag: 'property',
181
+ propertyName: string,
182
+ propertyValue: string,
183
+ inherited: boolean,
184
+ }|{
185
+ tag: 'traceElement',
186
+ property: SDK.CSSProperty.CSSProperty,
187
+ rule: SDK.CSSRule.CSSRule | null,
188
+ }|{
189
+ tag: 'category',
190
+ name: string,
191
+ };
192
+
174
193
  export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
175
194
  private computedStyleModel: ComputedStyleModel;
176
195
  private readonly showInheritedComputedStylePropertiesSetting: Common.Settings.Setting<boolean>;
@@ -178,17 +197,11 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
178
197
  input: Element;
179
198
  private filterRegex: RegExp|null;
180
199
  private readonly noMatchesElement: HTMLElement;
181
- private propertiesOutline: UI.TreeOutline.TreeOutlineInShadow;
182
- private readonly propertyByTreeElement: WeakMap<UI.TreeOutline.TreeElement, {
183
- name: string,
184
- value: string,
185
- }>;
186
- private readonly categoryByTreeElement: WeakMap<UI.TreeOutline.TreeElement, Category>;
187
- private readonly expandedProperties: Set<string>;
188
- private readonly expandedGroups: Set<Category>;
189
200
  private readonly linkifier: Components.Linkifier.Linkifier;
190
201
  private readonly imagePreviewPopover: ImagePreviewPopover;
191
- private idleCallbackManager: IdleCallbackManager;
202
+
203
+ #computedStylesTree = new TreeOutline.TreeOutline.TreeOutline<ComputedStyleData>();
204
+ #treeData?: TreeOutline.TreeOutline.TreeOutlineData<ComputedStyleData>;
192
205
 
193
206
  constructor() {
194
207
  super(true);
@@ -223,20 +236,7 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
223
236
  this.noMatchesElement = this.contentElement.createChild('div', 'gray-info-message');
224
237
  this.noMatchesElement.textContent = i18nString(UIStrings.noMatchingProperty);
225
238
 
226
- this.propertiesOutline = new UI.TreeOutline.TreeOutlineInShadow();
227
- this.propertiesOutline.hideOverflow();
228
- this.propertiesOutline.setShowSelectionOnKeyboardFocus(true);
229
- this.propertiesOutline.setFocusable(true);
230
- this.propertiesOutline.element.classList.add('monospace', 'computed-properties');
231
- this.propertiesOutline.addEventListener(UI.TreeOutline.Events.ElementExpanded, this.onTreeElementToggled, this);
232
- this.propertiesOutline.addEventListener(UI.TreeOutline.Events.ElementCollapsed, this.onTreeElementToggled, this);
233
- this.contentElement.appendChild(this.propertiesOutline.element);
234
-
235
- this.propertyByTreeElement = new WeakMap();
236
- this.categoryByTreeElement = new WeakMap();
237
-
238
- this.expandedProperties = new Set();
239
- this.expandedGroups = new Set(DefaultCategoryOrder);
239
+ this.contentElement.appendChild(this.#computedStylesTree);
240
240
 
241
241
  this.linkifier = new Components.Linkifier.Linkifier(_maxLinkLength);
242
242
 
@@ -251,13 +251,12 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
251
251
  const fontsWidget = new PlatformFontsWidget(this.computedStyleModel);
252
252
  fontsWidget.show(this.contentElement);
253
253
 
254
- this.idleCallbackManager = new IdleCallbackManager();
255
254
  Common.Settings.Settings.instance().moduleSetting('colorFormat').addChangeListener(this.update.bind(this));
256
255
  }
257
256
 
258
257
  onResize(): void {
259
258
  const isNarrow = this.contentElement.offsetWidth < 260;
260
- this.propertiesOutline.contentElement.classList.toggle('computed-narrow', isNarrow);
259
+ this.#computedStylesTree.classList.toggle('computed-narrow', isNarrow);
261
260
  }
262
261
 
263
262
  private showInheritedComputedStyleChanged(): void {
@@ -265,25 +264,22 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
265
264
  }
266
265
 
267
266
  update(): void {
268
- if (this.idleCallbackManager) {
269
- this.idleCallbackManager.discard();
270
- }
271
- this.idleCallbackManager = new IdleCallbackManager();
272
267
  super.update();
273
268
  }
274
269
 
275
270
  wasShown(): void {
276
271
  super.wasShown();
277
272
  this.registerCSSFiles([computedStyleSidebarPaneStyles]);
278
- this.propertiesOutline.registerCSSFiles([computedStyleWidgetTreeStyles]);
279
273
  }
280
274
 
281
275
  async doUpdate(): Promise<void> {
282
276
  const [nodeStyles, matchedStyles] =
283
277
  await Promise.all([this.computedStyleModel.fetchComputedStyle(), this.fetchMatchedCascade()]);
278
+ if (!nodeStyles || !matchedStyles) {
279
+ this.noMatchesElement.classList.remove('hidden');
280
+ return;
281
+ }
284
282
  const shouldGroupComputedStyles = this.groupComputedStylesSetting.get();
285
- this.propertiesOutline.contentElement.classList.toggle('grouped-list', shouldGroupComputedStyles);
286
- this.propertiesOutline.contentElement.classList.toggle('alphabetical-list', !shouldGroupComputedStyles);
287
283
  if (shouldGroupComputedStyles) {
288
284
  await this.rebuildGroupedList(nodeStyles, matchedStyles);
289
285
  } else {
@@ -310,15 +306,12 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
310
306
  }
311
307
  }
312
308
 
313
- private async rebuildAlphabeticalList(
314
- nodeStyle: ComputedStyle|null, matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles|null): Promise<void> {
315
- const hadFocus = this.propertiesOutline.element.hasFocus();
309
+ private async rebuildAlphabeticalList(nodeStyle: ComputedStyle, matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles):
310
+ Promise<void> {
316
311
  this.imagePreviewPopover.hide();
317
- this.propertiesOutline.removeChildren();
318
312
  this.linkifier.reset();
319
313
  const cssModel = this.computedStyleModel.cssModel();
320
- if (!nodeStyle || !matchedStyles || !cssModel) {
321
- this.noMatchesElement.classList.remove('hidden');
314
+ if (!cssModel) {
322
315
  return;
323
316
  }
324
317
 
@@ -329,8 +322,7 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
329
322
  const propertyTraces = this.computePropertyTraces(matchedStyles);
330
323
  const nonInheritedProperties = this.computeNonInheritedProperties(matchedStyles);
331
324
  const showInherited = this.showInheritedComputedStylePropertiesSetting.get();
332
- const computedStyleQueue = [];
333
- // filter and preprocess properties to line up in the computed style queue
325
+ const tree: TreeOutline.TreeOutlineUtils.TreeNode<ComputedStyleData>[] = [];
334
326
  for (const propertyName of uniqueProperties) {
335
327
  const propertyValue = nodeStyle.computedStyle.get(propertyName) || '';
336
328
  const canonicalName = SDK.CSSMetadata.cssMetadata().canonicalPropertyName(propertyName);
@@ -344,45 +336,21 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
344
336
  if (propertyName !== canonicalName && propertyValue === nodeStyle.computedStyle.get(canonicalName)) {
345
337
  continue;
346
338
  }
347
- computedStyleQueue.push({propertyName, propertyValue, isInherited});
339
+ tree.push(this.buildTreeNode(propertyTraces, propertyName, propertyValue, isInherited));
348
340
  }
349
341
 
350
- this.propertiesOutline.contentElement.classList.add('render-flash');
351
-
352
- // Render computed style properties in batches via idle callbacks to avoid a
353
- // very long task. The batchSize and timeoutInterval should be tweaked in
354
- // pair. Currently, updating, laying-out, rendering, and painting 20 items
355
- // in every 100ms seems to be a good balance between updating too lazy vs.
356
- // updating too much in one cycle.
357
- const batchSize = 20;
358
- const timeoutInterval = 100;
359
- let timeout = 100;
360
- while (computedStyleQueue.length > 0) {
361
- const currentBatch = computedStyleQueue.splice(0, batchSize);
362
-
363
- this.idleCallbackManager.schedule(() => {
364
- for (const {propertyName, propertyValue, isInherited} of currentBatch) {
365
- const treeElement = this.buildPropertyTreeElement(
366
- propertyTraces, node, (matchedStyles as SDK.CSSMatchedStyles.CSSMatchedStyles), propertyName,
367
- propertyValue, isInherited, hadFocus);
368
- this.propertiesOutline.appendChild(treeElement);
369
- }
370
-
371
- this.filterAlphabeticalList();
372
- }, timeout);
373
-
374
- timeout += timeoutInterval;
375
- }
376
-
377
- await this.idleCallbackManager.awaitDone();
378
- this.propertiesOutline.contentElement.classList.remove('render-flash');
342
+ const defaultRenderer = this.createTreeNodeRenderer(propertyTraces, node, matchedStyles);
343
+ this.#treeData = {
344
+ tree,
345
+ compact: true,
346
+ defaultRenderer,
347
+ };
348
+ this.filterAlphabeticalList();
379
349
  }
380
350
 
381
351
  private async rebuildGroupedList(
382
352
  nodeStyle: ComputedStyle|null, matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles|null): Promise<void> {
383
- const hadFocus = this.propertiesOutline.element.hasFocus();
384
353
  this.imagePreviewPopover.hide();
385
- this.propertiesOutline.removeChildren();
386
354
  this.linkifier.reset();
387
355
  const cssModel = this.computedStyleModel.cssModel();
388
356
  if (!nodeStyle || !matchedStyles || !cssModel) {
@@ -395,8 +363,9 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
395
363
  const nonInheritedProperties = this.computeNonInheritedProperties(matchedStyles);
396
364
  const showInherited = this.showInheritedComputedStylePropertiesSetting.get();
397
365
 
398
- const propertiesByCategory = new Map<Category, UI.TreeOutline.TreeElement[]>();
366
+ const propertiesByCategory = new Map<Category, string[]>();
399
367
 
368
+ const tree: TreeOutline.TreeOutlineUtils.TreeNode<ComputedStyleData>[] = [];
400
369
  for (const [propertyName, propertyValue] of nodeStyle.computedStyle) {
401
370
  const canonicalName = SDK.CSSMetadata.cssMetadata().canonicalPropertyName(propertyName);
402
371
  const isInherited = !nonInheritedProperties.has(canonicalName);
@@ -412,115 +381,109 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
412
381
 
413
382
  const categories = categorizePropertyName(propertyName);
414
383
  for (const category of categories) {
415
- const treeElement = this.buildPropertyTreeElement(
416
- propertyTraces, node, matchedStyles, propertyName, propertyValue, isInherited, hadFocus);
417
384
  if (!propertiesByCategory.has(category)) {
418
385
  propertiesByCategory.set(category, []);
419
386
  }
420
- // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
421
- // @ts-expect-error
422
- propertiesByCategory.get(category).push(treeElement);
387
+ propertiesByCategory.get(category)?.push(propertyName);
423
388
  }
424
389
  }
425
390
 
391
+ this.#computedStylesTree.removeChildren();
426
392
  for (const category of DefaultCategoryOrder) {
427
393
  const properties = propertiesByCategory.get(category);
428
394
  if (properties && properties.length > 0) {
429
- const title = document.createElement('h1');
430
- title.textContent = category;
431
- const group = new UI.TreeOutline.TreeElement(title);
432
- group.listItemElement.classList.add('group-title');
433
- group.toggleOnClick = true;
434
-
435
- for (const property of properties) {
436
- group.appendChild(property);
395
+ const propertyNodes: TreeOutline.TreeOutlineUtils.TreeNode<ComputedStyleData>[] = [];
396
+ for (const propertyName of properties) {
397
+ const propertyValue = nodeStyle.computedStyle.get(propertyName) || '';
398
+ const canonicalName = SDK.CSSMetadata.cssMetadata().canonicalPropertyName(propertyName);
399
+ const isInherited = !nonInheritedProperties.has(canonicalName);
400
+ propertyNodes.push(this.buildTreeNode(propertyTraces, propertyName, propertyValue, isInherited));
437
401
  }
438
-
439
- this.propertiesOutline.appendChild(group);
440
- if (this.expandedGroups.has(category)) {
441
- group.expand();
442
- }
443
-
444
- this.categoryByTreeElement.set(group, category);
402
+ tree.push({id: category, treeNodeData: {tag: 'category', name: category}, children: async () => propertyNodes});
445
403
  }
446
404
  }
405
+ const defaultRenderer = this.createTreeNodeRenderer(propertyTraces, node, matchedStyles);
406
+ this.#treeData = {
407
+ tree,
408
+ compact: true,
409
+ defaultRenderer,
410
+ };
411
+ return this.filterGroupLists();
412
+ }
447
413
 
448
- this.filterGroupLists();
414
+ private buildTraceNode(property: SDK.CSSProperty.CSSProperty):
415
+ TreeOutline.TreeOutlineUtils.TreeNode<ComputedStyleData> {
416
+ const rule = property.ownerStyle.parentRule as SDK.CSSRule.CSSStyleRule;
417
+ return {
418
+ treeNodeData: {
419
+ tag: 'traceElement',
420
+ property,
421
+ rule,
422
+ },
423
+ id: rule.origin + ': ' + rule.styleSheetId + property.range,
424
+ };
449
425
  }
450
426
 
451
- private onTreeElementToggled(event: Common.EventTarget.EventTargetEvent<UI.TreeOutline.TreeElement>): void {
452
- const treeElement = event.data;
453
- const property = this.propertyByTreeElement.get(treeElement);
454
- if (property) {
455
- treeElement.expanded ? this.expandedProperties.add(property.name) : this.expandedProperties.delete(property.name);
456
- } else {
457
- const category = this.categoryByTreeElement.get(treeElement);
458
- if (category) {
459
- treeElement.expanded ? this.expandedGroups.add(category) : this.expandedGroups.delete(category);
427
+ private createTreeNodeRenderer(
428
+ propertyTraces: Map<string, SDK.CSSProperty.CSSProperty[]>,
429
+ domNode: SDK.DOMModel.DOMNode,
430
+ matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles,
431
+ ):
432
+ (node: TreeOutline.TreeOutlineUtils.TreeNode<ComputedStyleData>,
433
+ state: {isExpanded: boolean}) => LitHtml.TemplateResult {
434
+ return node => {
435
+ const data = node.treeNodeData;
436
+ let navigate: (arg0?: Event) => void = () => {};
437
+ if (data.tag === 'property') {
438
+ const trace = propertyTraces.get(data.propertyName);
439
+ const activeProperty = trace?.find(
440
+ property => matchedStyles.propertyState(property) === SDK.CSSMatchedStyles.PropertyState.Active);
441
+ if (activeProperty) {
442
+ navigate = navigateToSource.bind(this, activeProperty);
443
+ }
444
+ const propertyElement = createPropertyElement(
445
+ domNode, data.propertyName, data.propertyValue, propertyTraces.has(data.propertyName), data.inherited,
446
+ navigate);
447
+ if (activeProperty) {
448
+ propertyElement.addEventListener(
449
+ 'contextmenu', this.handleContextMenuEvent.bind(this, matchedStyles, activeProperty));
450
+ }
451
+ return LitHtml.html`${propertyElement}`;
460
452
  }
461
- }
453
+ if (data.tag === 'traceElement') {
454
+ const isPropertyOverloaded =
455
+ matchedStyles.propertyState(data.property) === SDK.CSSMatchedStyles.PropertyState.Overloaded;
456
+ const traceElement =
457
+ createTraceElement(domNode, data.property, isPropertyOverloaded, matchedStyles, this.linkifier);
458
+ traceElement.addEventListener(
459
+ 'contextmenu', this.handleContextMenuEvent.bind(this, matchedStyles, data.property));
460
+ return LitHtml.html`${traceElement}`;
461
+ }
462
+ return LitHtml.html`<span style="cursor: text; color: var(--color-text-secondary);">${data.name}</span>`;
463
+ };
462
464
  }
463
465
 
464
- private buildPropertyTreeElement(
465
- propertyTraces: Map<string, SDK.CSSProperty.CSSProperty[]>, node: SDK.DOMModel.DOMNode,
466
- matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles, propertyName: string, propertyValue: string,
467
- isInherited: boolean, hadFocus: boolean): UI.TreeOutline.TreeElement {
468
- const treeElement = new UI.TreeOutline.TreeElement();
469
- const trace = propertyTraces.get(propertyName);
470
- let navigate: ((arg0?: Event|undefined) => void)|(() => void) = (): void => {};
471
- if (trace) {
472
- const activeProperty =
473
- this.renderPropertyTrace((matchedStyles as SDK.CSSMatchedStyles.CSSMatchedStyles), node, treeElement, trace);
474
- treeElement.setExpandable(true);
475
- treeElement.listItemElement.addEventListener('click', event => {
476
- treeElement.expanded ? treeElement.collapse() : treeElement.expand();
477
- event.consume();
478
- }, false);
479
- navigate = (navigateToSource.bind(this, activeProperty) as (arg0?: Event|undefined) => void);
480
- }
481
-
482
- const propertyElement = createPropertyElement(node, propertyName, propertyValue);
483
- propertyElement.data = {
484
- traceable: propertyTraces.has(propertyName),
466
+ private buildTreeNode(
467
+ propertyTraces: Map<string, SDK.CSSProperty.CSSProperty[]>, propertyName: string, propertyValue: string,
468
+ isInherited: boolean): TreeOutline.TreeOutlineUtils.TreeNode<ComputedStyleData> {
469
+ const treeNodeData: ComputedStyleData = {
470
+ tag: 'property',
471
+ propertyName,
472
+ propertyValue,
485
473
  inherited: isInherited,
486
- onNavigateToSource: navigate,
487
474
  };
488
-
489
- treeElement.title = propertyElement;
490
- this.propertyByTreeElement.set(treeElement, {name: propertyName, value: propertyValue});
491
- if (!this.propertiesOutline.selectedTreeElement) {
492
- treeElement.select(!hadFocus);
493
- }
494
-
495
- if (this.expandedProperties.has(propertyName)) {
496
- treeElement.expand();
497
- }
498
-
499
- return treeElement;
500
- }
501
-
502
- private renderPropertyTrace(
503
- matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles, node: SDK.DOMModel.DOMNode,
504
- rootTreeElement: UI.TreeOutline.TreeElement,
505
- tracedProperties: SDK.CSSProperty.CSSProperty[]): SDK.CSSProperty.CSSProperty {
506
- let activeProperty: SDK.CSSProperty.CSSProperty|null = null;
507
- for (const property of tracedProperties) {
508
- const isPropertyOverloaded =
509
- matchedStyles.propertyState(property) === SDK.CSSMatchedStyles.PropertyState.Overloaded;
510
- if (!isPropertyOverloaded) {
511
- activeProperty = property;
512
- rootTreeElement.listItemElement.addEventListener(
513
- 'contextmenu', this.handleContextMenuEvent.bind(this, matchedStyles, property));
514
- }
515
- const trace = createTraceElement(node, property, isPropertyOverloaded, matchedStyles, this.linkifier);
516
- const traceTreeElement = new UI.TreeOutline.TreeElement();
517
- traceTreeElement.title = trace;
518
- traceTreeElement.listItemElement.addEventListener(
519
- 'contextmenu', this.handleContextMenuEvent.bind(this, matchedStyles, property));
520
- rootTreeElement.appendChild(traceTreeElement);
475
+ const trace = propertyTraces.get(propertyName);
476
+ if (!trace) {
477
+ return {
478
+ treeNodeData,
479
+ id: propertyName,
480
+ };
521
481
  }
522
-
523
- return activeProperty as SDK.CSSProperty.CSSProperty;
482
+ return {
483
+ treeNodeData,
484
+ id: propertyName,
485
+ children: async () => trace.map(this.buildTraceNode),
486
+ };
524
487
  }
525
488
 
526
489
  private handleContextMenuEvent(
@@ -575,56 +538,62 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
575
538
  return result;
576
539
  }
577
540
 
578
- filterComputedStyles(this: ComputedStyleWidget, regex: RegExp|null): void {
541
+ async filterComputedStyles(this: ComputedStyleWidget, regex: RegExp|null): Promise<void> {
579
542
  this.filterRegex = regex;
580
543
  if (this.groupComputedStylesSetting.get()) {
581
- this.filterGroupLists();
582
- } else {
583
- this.filterAlphabeticalList();
544
+ return this.filterGroupLists();
584
545
  }
546
+ return this.filterAlphabeticalList();
585
547
  }
586
548
 
587
- private filterAlphabeticalList(): void {
549
+ private nodeFilter(node: TreeOutline.TreeOutlineUtils.TreeNode<ComputedStyleData>): boolean {
588
550
  const regex = this.filterRegex;
589
- const children = this.propertiesOutline.rootElement().children();
590
- let hasMatch = false;
591
- for (const child of children) {
592
- const property = this.propertyByTreeElement.get(child);
593
- if (!property) {
594
- continue;
595
- }
596
- const matched = !regex || regex.test(property.name) || regex.test(property.value);
597
- child.hidden = !matched;
598
- hasMatch = hasMatch || matched;
551
+ const data = node.treeNodeData;
552
+ if (data.tag === 'property') {
553
+ const matched = !regex || regex.test(data.propertyName) || regex.test(data.propertyValue);
554
+ return matched;
599
555
  }
600
- this.noMatchesElement.classList.toggle('hidden', Boolean(hasMatch));
556
+ return true;
601
557
  }
602
558
 
603
- private filterGroupLists(): void {
604
- const regex = this.filterRegex;
605
- const groups = this.propertiesOutline.rootElement().children();
606
- let hasOverallMatch = false;
607
- let foundFirstGroup = false;
608
- for (const group of groups) {
609
- let hasGroupMatch = false;
610
- const properties = group.children();
611
- for (const propertyTreeElement of properties) {
612
- const property = this.propertyByTreeElement.get(propertyTreeElement);
613
- if (!property) {
614
- continue;
615
- }
616
- const matched = !regex || regex.test(property.name) || regex.test(property.value);
617
- propertyTreeElement.hidden = !matched;
618
- hasOverallMatch = hasOverallMatch || matched;
619
- hasGroupMatch = hasGroupMatch || matched;
559
+ private filterAlphabeticalList(): void {
560
+ if (!this.#treeData) {
561
+ return;
562
+ }
563
+ const tree = this.#treeData.tree.filter(this.nodeFilter.bind(this));
564
+ this.#computedStylesTree.data = {
565
+ tree,
566
+ defaultRenderer: this.#treeData.defaultRenderer,
567
+ compact: this.#treeData.compact,
568
+ };
569
+ this.noMatchesElement.classList.toggle('hidden', Boolean(tree.length));
570
+ }
571
+
572
+ private async filterGroupLists(): Promise<void> {
573
+ if (!this.#treeData) {
574
+ return;
575
+ }
576
+ const tree: TreeOutline.TreeOutlineUtils.TreeNode<ComputedStyleData>[] = [];
577
+ for (const group of this.#treeData.tree) {
578
+ const data = group.treeNodeData;
579
+ if (data.tag !== 'category' || !group.children) {
580
+ continue;
581
+ }
582
+ const properties = await group.children();
583
+ const filteredChildren = properties.filter(this.nodeFilter.bind(this));
584
+ if (filteredChildren.length) {
585
+ tree.push(
586
+ {id: data.name, treeNodeData: {tag: 'category', name: data.name}, children: async () => filteredChildren});
620
587
  }
621
- group.hidden = !hasGroupMatch;
622
- // the first visible group won't have a divider before the group title
623
- group.listItemElement.classList.toggle('first-group', hasGroupMatch && !foundFirstGroup);
624
- foundFirstGroup = foundFirstGroup || hasGroupMatch;
625
588
  }
626
589
 
627
- this.noMatchesElement.classList.toggle('hidden', hasOverallMatch);
590
+ this.#computedStylesTree.data = {
591
+ tree,
592
+ defaultRenderer: this.#treeData.defaultRenderer,
593
+ compact: this.#treeData.compact,
594
+ };
595
+ await this.#computedStylesTree.expandRecursively(0);
596
+ this.noMatchesElement.classList.toggle('hidden', Boolean(tree.length));
628
597
  }
629
598
  }
630
599
 
@@ -918,7 +918,7 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
918
918
  propertyNamePattern = '^' + this.property.name + '$';
919
919
  }
920
920
  const regex = new RegExp(propertyNamePattern, 'i');
921
- computedStyleWidget.filterComputedStyles(regex);
921
+ await computedStyleWidget.filterComputedStyles(regex);
922
922
 
923
923
  const filterInput = (computedStyleWidget.input as HTMLInputElement);
924
924
  filterInput.value = this.property.name;
@@ -9,6 +9,8 @@ import computedStylePropertyStyles from './computedStyleProperty.css.js';
9
9
  const {render, html} = LitHtml;
10
10
 
11
11
  export interface ComputedStylePropertyData {
12
+ propertyNameRenderer: () => Element;
13
+ propertyValueRenderer: () => Element;
12
14
  inherited: boolean;
13
15
  traceable: boolean;
14
16
  onNavigateToSource: (event?: Event) => void;
@@ -18,6 +20,8 @@ export class ComputedStyleProperty extends HTMLElement {
18
20
  static readonly litTagName = LitHtml.literal`devtools-computed-style-property`;
19
21
  readonly #shadow = this.attachShadow({mode: 'open'});
20
22
 
23
+ #propertyNameRenderer?: () => Element = undefined;
24
+ #propertyValueRenderer?: () => Element = undefined;
21
25
  #inherited = false;
22
26
  #traceable = false;
23
27
  #onNavigateToSource: ((event?: Event) => void) = () => {};
@@ -27,6 +31,8 @@ export class ComputedStyleProperty extends HTMLElement {
27
31
  }
28
32
 
29
33
  set data(data: ComputedStylePropertyData) {
34
+ this.#propertyNameRenderer = data.propertyNameRenderer;
35
+ this.#propertyValueRenderer = data.propertyValueRenderer;
30
36
  this.#inherited = data.inherited;
31
37
  this.#traceable = data.traceable;
32
38
  this.#onNavigateToSource = data.onNavigateToSource;
@@ -34,16 +40,22 @@ export class ComputedStyleProperty extends HTMLElement {
34
40
  }
35
41
 
36
42
  #render(): void {
43
+ const propertyNameElement = this.#propertyNameRenderer?.();
44
+ const propertyValueElement = this.#propertyValueRenderer?.();
37
45
  // Disabled until https://crbug.com/1079231 is fixed.
38
46
  // clang-format off
39
47
  render(html`
40
48
  <div class="computed-style-property ${this.#inherited ? 'inherited' : ''}">
41
- <slot name="property-name"></slot>
49
+ <div class="property-name">
50
+ ${propertyNameElement}
51
+ </div>
42
52
  <span class="hidden" aria-hidden="false">: </span>
43
53
  ${this.#traceable ?
44
54
  html`<span class="goto" @click=${this.#onNavigateToSource}></span>` :
45
55
  null}
46
- <slot name="property-value"></slot>
56
+ <div class="property-value">
57
+ ${propertyValueElement}
58
+ </div>
47
59
  <span class="hidden" aria-hidden="false">;</span>
48
60
  </div>
49
61
  `, this.#shadow, {
@@ -12,6 +12,7 @@ export interface ComputedStyleTraceData {
12
12
  selector: string;
13
13
  active: boolean;
14
14
  onNavigateToSource: (event?: Event) => void;
15
+ ruleOriginNode?: Node;
15
16
  }
16
17
 
17
18
  export class ComputedStyleTrace extends HTMLElement {
@@ -21,6 +22,7 @@ export class ComputedStyleTrace extends HTMLElement {
21
22
  #selector = '';
22
23
  #active = false;
23
24
  #onNavigateToSource: ((event?: Event) => void) = () => {};
25
+ #ruleOriginNode?: Node;
24
26
 
25
27
  connectedCallback(): void {
26
28
  this.#shadow.adoptedStyleSheets = [computedStyleTraceStyles];
@@ -30,6 +32,7 @@ export class ComputedStyleTrace extends HTMLElement {
30
32
  this.#selector = data.selector;
31
33
  this.#active = data.active;
32
34
  this.#onNavigateToSource = data.onNavigateToSource;
35
+ this.#ruleOriginNode = data.ruleOriginNode;
33
36
  this.#render();
34
37
  }
35
38
 
@@ -41,7 +44,7 @@ export class ComputedStyleTrace extends HTMLElement {
41
44
  <span class="goto" @click=${this.#onNavigateToSource}></span>
42
45
  <slot name="trace-value" @click=${this.#onNavigateToSource}></slot>
43
46
  <span class="trace-selector">${this.#selector}</span>
44
- <slot name="trace-link"></slot>
47
+ <span class="trace-link">${this.#ruleOriginNode}</span>
45
48
  </div>
46
49
  `, this.#shadow, {
47
50
  host: this,
@@ -14,31 +14,40 @@
14
14
  .computed-style-property {
15
15
  --goto-size: 16px;
16
16
 
17
+ font-family: var(--monospace-font-family);
18
+ font-size: var(--monospace-font-size);
17
19
  min-height: 16px;
18
20
  box-sizing: border-box;
19
21
  padding-top: 2px;
20
22
  white-space: nowrap;
21
23
  }
22
24
 
25
+ .computed-style-property:hover {
26
+ background-color: var(--legacy-focus-bg-color);
27
+ cursor: text;
28
+ }
29
+
23
30
  .computed-style-property.inherited {
24
31
  opacity: 50%;
25
32
  }
26
33
 
27
- slot[name="property-name"],
28
- slot[name="property-value"] {
34
+ .property-name,
35
+ .property-value {
36
+ display: contents;
29
37
  overflow: hidden;
30
38
  text-overflow: ellipsis;
31
39
  }
32
40
 
33
- slot[name="property-name"] {
41
+ .property-name {
34
42
  width: 16em;
35
43
  max-width: 52%;
36
44
  margin-right: calc(var(--goto-size) / 2);
37
45
  display: inline-block;
38
46
  vertical-align: text-top;
47
+ color: var(--webkit-css-property-color, var(--color-syntax-1)); /* stylelint-disable-line plugin/use_theme_colors */ /* See: crbug.com/1152736 for color variable migration. */
39
48
  }
40
49
 
41
- slot[name="property-value"] {
50
+ .property-value {
42
51
  margin-left: 2em;
43
52
  }
44
53
 
@@ -66,8 +75,8 @@ slot[name="property-value"] {
66
75
  white-space: normal;
67
76
  }
68
77
 
69
- :host-context(.computed-narrow) slot[name="property-name"],
70
- :host-context(.computed-narrow) slot[name="property-value"] {
78
+ :host-context(.computed-narrow) .property-name,
79
+ :host-context(.computed-narrow) .property-value {
71
80
  display: inline-block;
72
81
  width: 100%;
73
82
  max-width: 100%;
@@ -12,6 +12,8 @@
12
12
 
13
13
  .computed-style-trace {
14
14
  margin-left: 16px;
15
+ font-family: var(--monospace-font-family);
16
+ font-size: var(--monospace-font-size);
15
17
  }
16
18
 
17
19
  .computed-style-trace:hover {
@@ -38,6 +40,15 @@
38
40
  display: inline-block;
39
41
  }
40
42
 
43
+ .devtools-link {
44
+ --override-text-decoration-color: hsl(0deg 0% 60%);
45
+
46
+ color: var(--color-text-primary);
47
+ text-decoration-color: var(--override-text-decoration-color);
48
+ text-decoration-line: underline;
49
+ cursor: pointer;
50
+ }
51
+
41
52
  .trace-value {
42
53
  margin-left: 16px;
43
54
  }
@@ -53,7 +64,7 @@
53
64
  padding-left: 2em;
54
65
  }
55
66
 
56
- ::slotted([slot="trace-link"]) {
67
+ .trace-link {
57
68
  user-select: none;
58
69
  float: right;
59
70
  padding-left: 1em;
@@ -4,11 +4,6 @@
4
4
  * found in the LICENSE file.
5
5
  */
6
6
 
7
- .computed-properties {
8
- user-select: text;
9
- flex-shrink: 0;
10
- }
11
-
12
7
  .styles-sidebar-pane-toolbar {
13
8
  border-bottom: 1px solid var(--color-details-hairline-light);
14
9
  flex-shrink: 0;
@@ -523,7 +523,7 @@ export const RuntimeSettings: RuntimeSetting[] = [
523
523
  {
524
524
  // This setting is disabled, but we keep it around to show in the UI.
525
525
  setting: Common.Settings.Settings.instance().createSetting(
526
- 'lighthouse.throttling', 'simulated', Common.Settings.SettingStorageType.Synced),
526
+ 'lighthouse.throttling', 'simulate', Common.Settings.SettingStorageType.Synced),
527
527
  title: i18nLazyString(UIStrings.throttlingMethod),
528
528
  // We will disable this when we have a Lantern trace viewer within DevTools.
529
529
  learnMore:
@@ -10,18 +10,20 @@ await FrontendHelpers.initializeGlobalVars();
10
10
 
11
11
  const component = new Elements.ComputedStyleProperty.ComputedStyleProperty();
12
12
 
13
- const propertyName = document.createElement('span');
14
- propertyName.textContent = 'display';
15
- propertyName.slot = 'property-name';
16
- component.appendChild(propertyName);
17
-
18
- const propertyValue = document.createElement('span');
19
- propertyValue.textContent = 'block';
20
- propertyValue.slot = 'property-value';
21
- component.appendChild(propertyValue);
22
-
23
13
  document.getElementById('container')?.appendChild(component);
24
14
  component.data = {
15
+ propertyNameRenderer: () => {
16
+ const propertyName = document.createElement('span');
17
+ propertyName.textContent = 'display';
18
+ propertyName.slot = 'property-name';
19
+ return propertyName;
20
+ },
21
+ propertyValueRenderer: () => {
22
+ const propertyValue = document.createElement('span');
23
+ propertyValue.textContent = 'block';
24
+ propertyValue.slot = 'property-value';
25
+ return propertyValue;
26
+ },
25
27
  inherited: true,
26
28
  traceable: false,
27
29
  onNavigateToSource: (): void => {},
@@ -7,16 +7,6 @@ import * as Elements from '../../../../panels/elements/components/components.js'
7
7
 
8
8
  const component = new Elements.ComputedStyleProperty.ComputedStyleProperty();
9
9
 
10
- const propertyName = document.createElement('span');
11
- propertyName.textContent = 'display';
12
- propertyName.slot = 'property-name';
13
- component.appendChild(propertyName);
14
-
15
- const propertyValue = document.createElement('span');
16
- propertyValue.textContent = 'grid';
17
- propertyValue.slot = 'property-value';
18
- component.appendChild(propertyValue);
19
-
20
10
  const trace = document.createElement('pre');
21
11
  trace.textContent = 'block body (style.css):42';
22
12
  trace.slot = 'property-traces';
@@ -24,6 +14,19 @@ component.appendChild(trace);
24
14
 
25
15
  document.getElementById('container')?.appendChild(component);
26
16
  component.data = {
17
+ propertyNameRenderer: () => {
18
+ const propertyName = document.createElement('span');
19
+ propertyName.textContent = 'display';
20
+ propertyName.slot = 'property-name';
21
+ return propertyName;
22
+ },
23
+ propertyValueRenderer: () => {
24
+ const propertyValue = document.createElement('span');
25
+ propertyValue.textContent = 'grid';
26
+ propertyValue.slot = 'property-value';
27
+
28
+ return propertyValue;
29
+ },
27
30
  inherited: false,
28
31
  traceable: true,
29
32
  onNavigateToSource: (): void => {},
@@ -31,6 +31,7 @@ export interface TreeOutlineData<TreeNodeDataType> {
31
31
  */
32
32
  tree: readonly TreeNode<TreeNodeDataType>[];
33
33
  filter?: (node: TreeNodeDataType) => FilterOption;
34
+ compact?: boolean;
34
35
  }
35
36
 
36
37
  export function defaultRenderer(node: TreeNode<string>): LitHtml.TemplateResult {
@@ -111,6 +112,7 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
111
112
  return LitHtml.html`${String(node.treeNodeData)}`;
112
113
  };
113
114
  #nodeFilter?: ((node: TreeNodeDataType) => FilterOption);
115
+ #compact = false;
114
116
 
115
117
  /**
116
118
  * scheduledRender = render() has been called and scheduled a render.
@@ -155,6 +157,7 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
155
157
  this.#defaultRenderer = data.defaultRenderer;
156
158
  this.#treeData = data.tree;
157
159
  this.#nodeFilter = data.filter;
160
+ this.#compact = data.compact || false;
158
161
 
159
162
  if (!this.#hasRenderedAtLeastOnce) {
160
163
  this.#selectedTreeNode = this.#treeData[0];
@@ -454,6 +457,7 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
454
457
  parent: isExpandableNode(node),
455
458
  selected: this.#isSelectedNode(node),
456
459
  'is-top-level': depth === 0,
460
+ compact: this.#compact,
457
461
  });
458
462
  const ariaExpandedAttribute =
459
463
  LitHtml.Directives.ifDefined(isExpandableNode(node) ? String(nodeIsExpanded) : undefined);
@@ -9,15 +9,21 @@
9
9
  }
10
10
 
11
11
  li {
12
+ border: 2px solid transparent;
12
13
  list-style: none;
13
14
  text-overflow: ellipsis;
14
15
  min-height: 12px;
15
16
  }
16
17
 
18
+ .compact {
19
+ border: 0;
20
+ }
21
+
17
22
  .tree-node-key {
18
23
  white-space: var(--override-key-whitespace-wrapping);
19
24
  /* Override the default |min-width: auto| to avoid overflows of flex items */
20
25
  min-width: 0;
26
+ flex-grow: 1;
21
27
  }
22
28
 
23
29
  .arrow-icon {
@@ -79,7 +85,6 @@ li.is-top-level:last-child {
79
85
  }
80
86
 
81
87
  .arrow-and-key-wrapper {
82
- border: 2px solid transparent;
83
88
  display: flex;
84
89
  align-content: center;
85
90
  align-items: center;
package/package.json CHANGED
@@ -55,5 +55,5 @@
55
55
  "unittest": "scripts/test/run_unittests.py --no-text-coverage",
56
56
  "watch": "vpython third_party/node/node.py --output scripts/watch_build.js"
57
57
  },
58
- "version": "1.0.1007846"
58
+ "version": "1.0.1008735"
59
59
  }
@@ -1,66 +0,0 @@
1
- /*
2
- * Copyright (c) 2017 The Chromium Authors. All rights reserved.
3
- * Use of this source code is governed by a BSD-style license that can be
4
- * found in the LICENSE file.
5
- */
6
-
7
- .alphabetical-list.render-flash {
8
- min-height: 100vh;
9
- }
10
-
11
- .tree-outline,
12
- .tree-outline ol {
13
- padding-left: 0;
14
- }
15
-
16
- .tree-outline li:hover {
17
- background-color: var(--legacy-focus-bg-color);
18
- cursor: text;
19
- }
20
-
21
- .tree-outline li::before {
22
- margin: 0 -1px 0 4px;
23
- }
24
-
25
- .group-title {
26
- /* tree-outline li::before is set to be 16px wide */
27
- padding-right: 16px;
28
- }
29
-
30
- .tree-outline li.group-title:hover {
31
- background-color: transparent;
32
- }
33
-
34
- .group-title > h1 {
35
- margin: 1px 0 0;
36
- padding: 1em 0;
37
- width: 100%;
38
- cursor: text;
39
- color: var(--color-text-secondary);
40
- font-size: 11px;
41
- font-weight: 400;
42
- }
43
-
44
- .group-title:not(.first-group) > h1 {
45
- border-top: 1px solid var(--color-details-hairline);
46
- }
47
-
48
- .group-title + ol.children {
49
- margin-bottom: 1em;
50
- }
51
-
52
- @media (forced-colors: active) {
53
- :host-context(.monospace.computed-properties) .tree-outline li:hover {
54
- forced-color-adjust: none;
55
- background-color: Highlight;
56
- }
57
-
58
- :host-context(.monospace.computed-properties) .tree-outline:not(.hide-selection-when-blurred) li.parent:hover.selected::before,
59
- :host-context(.monospace.computed-properties) .tree-outline-disclosure li.parent:hover::before {
60
- background-color: HighlightText;
61
- }
62
-
63
- :host-context(.monospace.computed-properties) .tree-outline li:hover * {
64
- color: HighlightText;
65
- }
66
- }