chrome-devtools-frontend 1.0.1018017 → 1.0.1019017

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.
@@ -933,6 +933,7 @@ grd_files_debug_sources = [
933
933
  "front_end/panels/developer_resources/developerResourcesView.css.js",
934
934
  "front_end/panels/elements/AccessibilityTreeUtils.js",
935
935
  "front_end/panels/elements/AccessibilityTreeView.js",
936
+ "front_end/panels/elements/CSSRuleValidator.js",
936
937
  "front_end/panels/elements/ClassesPaneWidget.js",
937
938
  "front_end/panels/elements/ColorSwatchPopoverIcon.js",
938
939
  "front_end/panels/elements/ComputedStyleModel.js",
@@ -3209,6 +3209,9 @@
3209
3209
  "panels/application/components/PermissionsPolicySection.ts | showDetails": {
3210
3210
  "message": "Show details"
3211
3211
  },
3212
+ "panels/application/components/ProtocolHandlersView.ts | dropdownLabel": {
3213
+ "message": "Select protocol handler"
3214
+ },
3212
3215
  "panels/application/components/ProtocolHandlersView.ts | manifest": {
3213
3216
  "message": "manifest"
3214
3217
  },
@@ -3227,6 +3230,9 @@
3227
3230
  "panels/application/components/ProtocolHandlersView.ts | testProtocol": {
3228
3231
  "message": "Test protocol"
3229
3232
  },
3233
+ "panels/application/components/ProtocolHandlersView.ts | textboxLabel": {
3234
+ "message": "Query parameter or endpoint for protocol handler"
3235
+ },
3230
3236
  "panels/application/components/ReportsGrid.ts | destination": {
3231
3237
  "message": "Destination"
3232
3238
  },
@@ -4682,6 +4688,12 @@
4682
4688
  "panels/elements/ComputedStyleWidget.ts | showAll": {
4683
4689
  "message": "Show all"
4684
4690
  },
4691
+ "panels/elements/CSSRuleValidator.ts | alignContentRuleOnNoWrapFlex": {
4692
+ "message": "This element has flex-wrap: nowrap rule, therefore 'align-content' has no effect."
4693
+ },
4694
+ "panels/elements/CSSRuleValidator.ts | notFlexItemHint": {
4695
+ "message": "Parent of this element is not flex container, therefore {PH1} property has no effect."
4696
+ },
4685
4697
  "panels/elements/DOMLinkifier.ts | node": {
4686
4698
  "message": "<node>"
4687
4699
  },
@@ -3209,6 +3209,9 @@
3209
3209
  "panels/application/components/PermissionsPolicySection.ts | showDetails": {
3210
3210
  "message": "Ŝh́ôẃ d̂ét̂áîĺŝ"
3211
3211
  },
3212
+ "panels/application/components/ProtocolHandlersView.ts | dropdownLabel": {
3213
+ "message": "Ŝél̂éĉt́ p̂ŕôt́ôćôĺ ĥán̂d́l̂ér̂"
3214
+ },
3212
3215
  "panels/application/components/ProtocolHandlersView.ts | manifest": {
3213
3216
  "message": "m̂án̂íf̂éŝt́"
3214
3217
  },
@@ -3227,6 +3230,9 @@
3227
3230
  "panels/application/components/ProtocolHandlersView.ts | testProtocol": {
3228
3231
  "message": "T̂éŝt́ p̂ŕôt́ôćôĺ"
3229
3232
  },
3233
+ "panels/application/components/ProtocolHandlersView.ts | textboxLabel": {
3234
+ "message": "Q̂úêŕŷ ṕâŕâḿêt́êŕ ôŕ êńd̂ṕôín̂t́ f̂ór̂ ṕr̂ót̂óĉól̂ h́âńd̂ĺêŕ"
3235
+ },
3230
3236
  "panels/application/components/ReportsGrid.ts | destination": {
3231
3237
  "message": "D̂éŝt́îńât́îón̂"
3232
3238
  },
@@ -4682,6 +4688,12 @@
4682
4688
  "panels/elements/ComputedStyleWidget.ts | showAll": {
4683
4689
  "message": "Ŝh́ôẃ âĺl̂"
4684
4690
  },
4691
+ "panels/elements/CSSRuleValidator.ts | alignContentRuleOnNoWrapFlex": {
4692
+ "message": "T̂h́îś êĺêḿêńt̂ h́âś f̂ĺêx́-ŵŕâṕ: n̂óŵŕâṕ r̂úl̂é, t̂h́êŕêf́ôŕê 'ál̂íĝń-ĉón̂t́êńt̂' h́âś n̂ó êf́f̂éĉt́."
4693
+ },
4694
+ "panels/elements/CSSRuleValidator.ts | notFlexItemHint": {
4695
+ "message": "P̂ár̂én̂t́ ôf́ t̂h́îś êĺêḿêńt̂ íŝ ńôt́ f̂ĺêx́ ĉón̂t́âín̂ér̂, t́ĥér̂éf̂ór̂é {PH1} p̂ŕôṕêŕt̂ý ĥáŝ ńô éf̂f́êćt̂."
4696
+ },
4685
4697
  "panels/elements/DOMLinkifier.ts | node": {
4686
4698
  "message": "<n̂ód̂é>"
4687
4699
  },
@@ -319,12 +319,16 @@ export class DOMStorageModel extends SDK.SDKModel.SDKModel<EventTypes> {
319
319
  }
320
320
  }
321
321
 
322
- private storageKey(securityOrigin: string, storageKey: string, isLocalStorage: boolean): string {
322
+ private storageKey(securityOrigin: string|undefined, storageKey: string|undefined, isLocalStorage: boolean): string {
323
323
  // TODO(crbug.com/1313434) Prioritize storageKey once everything is ready
324
+ console.assert(Boolean(securityOrigin) || Boolean(storageKey));
324
325
  if (securityOrigin) {
325
326
  return JSON.stringify(DOMStorage.storageIdWithSecurityOrigin(securityOrigin, isLocalStorage));
326
327
  }
327
- return JSON.stringify(DOMStorage.storageIdWithStorageKey(storageKey, isLocalStorage));
328
+ if (storageKey) {
329
+ return JSON.stringify(DOMStorage.storageIdWithStorageKey(storageKey, isLocalStorage));
330
+ }
331
+ throw new Error('Either securityOrigin or storageKey is required');
328
332
  }
329
333
 
330
334
  private keyForSecurityOrigin(securityOrigin: string, isLocalStorage: boolean): string {
@@ -375,7 +379,8 @@ export class DOMStorageModel extends SDK.SDKModel.SDKModel<EventTypes> {
375
379
  }
376
380
 
377
381
  storageForId(storageId: Protocol.DOMStorage.StorageId): DOMStorage {
378
- return this.storagesInternal[JSON.stringify(storageId)];
382
+ return this
383
+ .storagesInternal[this.storageKey(storageId.securityOrigin, storageId.storageKey, storageId.isLocalStorage)];
379
384
  }
380
385
 
381
386
  storages(): DOMStorage[] {
@@ -48,6 +48,14 @@ const UIStrings = {
48
48
  *@description Text for test protocol button
49
49
  */
50
50
  testProtocol: 'Test protocol',
51
+ /**
52
+ * @description Aria text for screen reader to announce they can select a protocol handler in the dropdown
53
+ */
54
+ dropdownLabel: 'Select protocol handler',
55
+ /**
56
+ * @description Aria text for screen reader to announce they can enter query parameters or endpoints into the textbox
57
+ */
58
+ textboxLabel: 'Query parameter or endpoint for protocol handler',
51
59
  };
52
60
 
53
61
  const str_ = i18n.i18n.registerUIStrings('panels/application/components/ProtocolHandlersView.ts', UIStrings);
@@ -121,11 +129,12 @@ export class ProtocolHandlersView extends HTMLElement {
121
129
  .map(p => LitHtml.html`<option value=${p.protocol}>${p.protocol}://</option>`);
122
130
  return LitHtml.html`
123
131
  <div class="protocol-handlers-row">
124
- <select class="chrome-select protocol-select" @change=${this.#handleProtocolSelect}>
132
+ <select class="chrome-select protocol-select" @change=${this.#handleProtocolSelect} aria-label=${
133
+ i18nString(UIStrings.dropdownLabel)}>
125
134
  ${protocolOptions}
126
135
  </select>
127
136
  <input .value=${this.#queryInputState} class="devtools-text-input" type="text" @change=${
128
- this.#handleQueryInputChange}/>
137
+ this.#handleQueryInputChange} aria-label=${i18nString(UIStrings.textboxLabel)}/>
129
138
  <${Buttons.Button.Button.litTagName} .variant=${Buttons.Button.Variant.PRIMARY} @click=${
130
139
  this.#handleTestProtocolClick}>
131
140
  ${i18nString(UIStrings.testProtocol)}
@@ -0,0 +1,100 @@
1
+ // Copyright 2022 The Chromium Authors. All rights reserved.
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 i18n from '../../core/i18n/i18n.js';
6
+
7
+ const UIStrings = {
8
+ /**
9
+ *@description Hint for Align-content rule where element also has flex-wrap nowrap rule.
10
+ */
11
+ alignContentRuleOnNoWrapFlex: 'This element has flex-wrap: nowrap rule, therefore \'align-content\' has no effect.',
12
+ /**
13
+ *@description Hint for element that does not have effect if parent container is not flex.
14
+ *@example {flex} PH1
15
+ */
16
+ notFlexItemHint: 'Parent of this element is not flex container, therefore {PH1} property has no effect.',
17
+ };
18
+ const str_ = i18n.i18n.registerUIStrings('panels/elements/CSSRuleValidator.ts', UIStrings);
19
+ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
20
+
21
+ export abstract class CSSRuleValidator {
22
+ readonly #affectedProperties: string[];
23
+
24
+ constructor(affectedProperties: string[]) {
25
+ this.#affectedProperties = affectedProperties;
26
+ }
27
+
28
+ abstract isRuleValid(computedStyles: Map<String, String>|null, parentsComputedStyles?: Map<String, String>|null):
29
+ boolean;
30
+
31
+ getAffectedProperties(): string[] {
32
+ return this.#affectedProperties;
33
+ }
34
+
35
+ abstract getHintMessage(propertyName: string): string;
36
+ }
37
+
38
+ export class AlignContentValidator extends CSSRuleValidator {
39
+ constructor() {
40
+ super(['align-content']);
41
+ }
42
+
43
+ isRuleValid(computedStyles: Map<String, String>|null): boolean {
44
+ if (computedStyles === null || computedStyles === undefined) {
45
+ return true;
46
+ }
47
+ const display = computedStyles.get('display');
48
+ if (display !== 'flex' && display !== 'inline-flex') {
49
+ return true;
50
+ }
51
+ return computedStyles.get('flex-wrap') !== 'nowrap';
52
+ }
53
+
54
+ getHintMessage(): string {
55
+ return i18nString(UIStrings.alignContentRuleOnNoWrapFlex);
56
+ }
57
+ }
58
+
59
+ export class FlexItemValidator extends CSSRuleValidator {
60
+ constructor() {
61
+ super(['flex', 'flex-basis', 'flex-grow', 'flex-shrink']);
62
+ }
63
+
64
+ isRuleValid(computedStyles: Map<String, String>|null, parentsComputedStyles: Map<String, String>|null): boolean {
65
+ if (computedStyles === null || computedStyles === undefined || parentsComputedStyles === null ||
66
+ parentsComputedStyles === undefined) {
67
+ return true;
68
+ }
69
+ const parentDisplay = parentsComputedStyles.get('display');
70
+ return parentDisplay === 'flex' || parentDisplay === 'inline-flex';
71
+ }
72
+
73
+ getHintMessage(property: string): string {
74
+ return i18nString(UIStrings.notFlexItemHint, {
75
+ 'PH1': property,
76
+ });
77
+ }
78
+ }
79
+
80
+ const setupCSSRulesValidators = (): Map<String, CSSRuleValidator[]> => {
81
+ const validators = [new AlignContentValidator(), new FlexItemValidator()];
82
+
83
+ const validatorsMap = new Map<String, CSSRuleValidator[]>();
84
+ for (const validator of validators) {
85
+ const affectedProperties = validator.getAffectedProperties();
86
+
87
+ for (const affectedProperty of affectedProperties) {
88
+ let propertyValidators = validatorsMap.get(affectedProperty);
89
+ if (propertyValidators === undefined) {
90
+ propertyValidators = [];
91
+ }
92
+ propertyValidators.push(validator);
93
+
94
+ validatorsMap.set(affectedProperty, propertyValidators);
95
+ }
96
+ }
97
+ return validatorsMap;
98
+ };
99
+
100
+ export const cssRuleValidatorsMap: Map<String, CSSRuleValidator[]> = setupCSSRulesValidators();
@@ -121,6 +121,8 @@ export class StylePropertiesSection {
121
121
  protected parentPane: StylesSidebarPane;
122
122
  styleInternal: SDK.CSSStyleDeclaration.CSSStyleDeclaration;
123
123
  readonly matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles;
124
+ private computedStyles: Map<string, string>|null;
125
+ private parentsComputedStyles: Map<string, string>|null;
124
126
  editable: boolean;
125
127
  private hoverTimer: number|null;
126
128
  private willCauseCancelEditing: boolean;
@@ -152,11 +154,14 @@ export class StylePropertiesSection {
152
154
 
153
155
  constructor(
154
156
  parentPane: StylesSidebarPane, matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles,
155
- style: SDK.CSSStyleDeclaration.CSSStyleDeclaration, sectionIdx: number) {
157
+ style: SDK.CSSStyleDeclaration.CSSStyleDeclaration, sectionIdx: number, computedStyles: Map<string, string>|null,
158
+ parentsComputedStyles: Map<string, string>|null) {
156
159
  this.parentPane = parentPane;
157
160
  this.sectionIdx = sectionIdx;
158
161
  this.styleInternal = style;
159
162
  this.matchedStyles = matchedStyles;
163
+ this.computedStyles = computedStyles;
164
+ this.parentsComputedStyles = parentsComputedStyles;
160
165
  this.editable = Boolean(style.styleSheetId && style.range);
161
166
  this.hoverTimer = null;
162
167
  this.willCauseCancelEditing = false;
@@ -932,6 +937,8 @@ export class StylePropertiesSection {
932
937
  }
933
938
  const item = new StylePropertyTreeElement(
934
939
  this.parentPane, this.matchedStyles, property, isShorthand, inherited, overloaded, false);
940
+ item.setComputedStyles(this.computedStyles);
941
+ item.setParentsComputedStyles(this.parentsComputedStyles);
935
942
  this.propertiesTreeOutline.appendChild(item);
936
943
  }
937
944
 
@@ -1449,7 +1456,7 @@ export class BlankStylePropertiesSection extends StylePropertiesSection {
1449
1456
  insertAfterStyle: SDK.CSSStyleDeclaration.CSSStyleDeclaration, sectionIdx: number) {
1450
1457
  const cssModel = (stylesPane.cssModel() as SDK.CSSModel.CSSModel);
1451
1458
  const rule = SDK.CSSRule.CSSStyleRule.createDummyRule(cssModel, defaultSelectorText);
1452
- super(stylesPane, matchedStyles, rule.style, sectionIdx);
1459
+ super(stylesPane, matchedStyles, rule.style, sectionIdx, null, null);
1453
1460
  this.normal = false;
1454
1461
  this.ruleLocation = ruleLocation;
1455
1462
  this.styleSheetId = styleSheetId;
@@ -1553,7 +1560,7 @@ export class KeyframePropertiesSection extends StylePropertiesSection {
1553
1560
  constructor(
1554
1561
  stylesPane: StylesSidebarPane, matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles,
1555
1562
  style: SDK.CSSStyleDeclaration.CSSStyleDeclaration, sectionIdx: number) {
1556
- super(stylesPane, matchedStyles, style, sectionIdx);
1563
+ super(stylesPane, matchedStyles, style, sectionIdx, null, null);
1557
1564
  this.selectorElement.className = 'keyframe-key';
1558
1565
  }
1559
1566
 
@@ -21,6 +21,7 @@ import {StyleEditorWidget} from './StyleEditorWidget.js';
21
21
  import type {StylePropertiesSection} from './StylePropertiesSection.js';
22
22
  import {CSSPropertyPrompt, StylesSidebarPane, StylesSidebarPropertyRenderer} from './StylesSidebarPane.js';
23
23
  import {getCssDeclarationAsJavascriptProperty} from './StylePropertyUtils.js';
24
+ import {cssRuleValidatorsMap} from './CSSRuleValidator.js';
24
25
 
25
26
  const FlexboxEditor = ElementsComponents.StylePropertyEditor.FlexboxEditor;
26
27
  const GridEditor = ElementsComponents.StylePropertyEditor.GridEditor;
@@ -120,6 +121,8 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
120
121
  private hasBeenEditedIncrementally: boolean;
121
122
  private prompt: CSSPropertyPrompt|null;
122
123
  private lastComputedValue: string|null;
124
+ private computedStyles: Map<string, string>|null = null;
125
+ private parentsComputedStyles: Map<string, string>|null = null;
123
126
  private contextForTest!: Context|undefined;
124
127
  #propertyTextFromSource: string;
125
128
 
@@ -179,6 +182,14 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
179
182
  this.updateState();
180
183
  }
181
184
 
185
+ setComputedStyles(computedStyles: Map<string, string>|null): void {
186
+ this.computedStyles = computedStyles;
187
+ }
188
+
189
+ setParentsComputedStyles(parentsComputedStyles: Map<string, string>|null): void {
190
+ this.parentsComputedStyles = parentsComputedStyles;
191
+ }
192
+
182
193
  get name(): string {
183
194
  return this.property.name;
184
195
  }
@@ -568,6 +579,8 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
568
579
  const item = new StylePropertyTreeElement(
569
580
  this.parentPaneInternal, this.matchedStylesInternal, longhandProperties[i], false, inherited, overloaded,
570
581
  false);
582
+ item.setComputedStyles(this.computedStyles);
583
+ item.setParentsComputedStyles(this.parentsComputedStyles);
571
584
  this.appendChild(item);
572
585
  }
573
586
  }
@@ -702,6 +715,17 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
702
715
  }
703
716
  }
704
717
 
718
+ const hintMessage = this.getHintMessage(this.computedStyles, this.parentsComputedStyles);
719
+ if (hintMessage !== null) {
720
+ const hintIcon = UI.Icon.Icon.create('mediumicon-info', 'hint');
721
+ const hintPopover =
722
+ new UI.PopoverHelper.PopoverHelper(hintIcon, event => this.handleHintPopoverRequest(hintMessage, event));
723
+ hintPopover.setHasPadding(true);
724
+ hintPopover.setTimeout(0, 100);
725
+
726
+ this.listItemElement.append(hintIcon);
727
+ }
728
+
705
729
  if (!this.property.parsedOk) {
706
730
  // Avoid having longhands under an invalid shorthand.
707
731
  this.listItemElement.classList.add('not-parsed-ok');
@@ -793,6 +817,41 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
793
817
  StylesSidebarPane.createExclamationMark(this.property, warnings.join(' ')), this.listItemElement.firstChild);
794
818
  }
795
819
 
820
+ private getHintMessage(computedStyles: Map<string, string>|null, parentComputedStyles: Map<string, string>|null):
821
+ string|null {
822
+ const propertyName = this.property.name;
823
+
824
+ if (!Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.CSS_AUTHORING_HINTS) ||
825
+ !cssRuleValidatorsMap.has(propertyName)) {
826
+ return null;
827
+ }
828
+
829
+ for (const validator of cssRuleValidatorsMap.get(propertyName) || []) {
830
+ if (!validator.isRuleValid(computedStyles, parentComputedStyles)) {
831
+ return validator.getHintMessage(propertyName);
832
+ }
833
+ }
834
+
835
+ return null;
836
+ }
837
+
838
+ private handleHintPopoverRequest(hintMessageContent: string, event: Event): UI.PopoverHelper.PopoverRequest|null {
839
+ const link = event.composedPath()[0];
840
+ Platform.DCHECK(() => link instanceof Element, 'Link is not an instance of Element');
841
+
842
+ return {
843
+ box: (link as Element).boxInWindow(),
844
+ show: async(popover: UI.GlassPane.GlassPane): Promise<boolean> => {
845
+ const node = this.node();
846
+ if (!node) {
847
+ return false;
848
+ }
849
+ popover.contentElement.insertAdjacentHTML('beforeend', hintMessageContent);
850
+ return true;
851
+ },
852
+ };
853
+ }
854
+
796
855
  private mouseUp(event: MouseEvent): void {
797
856
  const activeTreeElement = parentMap.get(this.parentPaneInternal);
798
857
  parentMap.delete(this.parentPaneInternal);
@@ -583,8 +583,16 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
583
583
  }, 200 /* only spin for loading time > 200ms to avoid unpleasant render flashes */);
584
584
  }
585
585
 
586
+ const node = this.node();
587
+ // TODO: Fetch the parent node id using CDP command
588
+ const parentNode = node ? node.parentNode : null;
589
+
590
+ const [computedStyles, parentsComputedStyles] =
591
+ await Promise.all([this.fetchComputedStylesFor(node), this.fetchComputedStylesFor(parentNode)]);
592
+
586
593
  const matchedStyles = await this.fetchMatchedCascade();
587
- await this.innerRebuildUpdate(matchedStyles);
594
+
595
+ await this.innerRebuildUpdate(matchedStyles, computedStyles, parentsComputedStyles);
588
596
  if (!this.initialUpdateCompleted) {
589
597
  this.initialUpdateCompleted = true;
590
598
  this.appendToolbarItem(this.createRenderingShortcuts());
@@ -599,6 +607,13 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
599
607
  this.dispatchEventToListeners(Events.StylesUpdateCompleted, {hasMatchedStyles: this.hasMatchedStyles});
600
608
  }
601
609
 
610
+ private async fetchComputedStylesFor(node: SDK.DOMModel.DOMNode|null): Promise<Map<string, string>|null> {
611
+ if (!node) {
612
+ return null;
613
+ }
614
+ return await node.domModel().cssModel().getComputedStyle(node.id);
615
+ }
616
+
602
617
  onResize(): void {
603
618
  void this.resizeThrottler.schedule(this.innerResize.bind(this));
604
619
  }
@@ -718,7 +733,9 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
718
733
  }
719
734
  }
720
735
 
721
- private async innerRebuildUpdate(matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles|null): Promise<void> {
736
+ private async innerRebuildUpdate(
737
+ matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles|null, computedStyles: Map<string, string>|null,
738
+ parentsComputedStyles: Map<string, string>|null): Promise<void> {
722
739
  // ElementsSidebarPane's throttler schedules this method. Usually,
723
740
  // rebuild is suppressed while editing (see onCSSModelChanged()), but we need a
724
741
  // 'force' flag since the currently running throttler process cannot be canceled.
@@ -742,8 +759,8 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
742
759
  return;
743
760
  }
744
761
 
745
- this.sectionBlocks =
746
- await this.rebuildSectionsForMatchedStyleRules((matchedStyles as SDK.CSSMatchedStyles.CSSMatchedStyles));
762
+ this.sectionBlocks = await this.rebuildSectionsForMatchedStyleRules(
763
+ (matchedStyles as SDK.CSSMatchedStyles.CSSMatchedStyles), computedStyles, parentsComputedStyles);
747
764
 
748
765
  // Style sections maybe re-created when flexbox editor is activated.
749
766
  // With the following code we re-bind the flexbox editor to the new
@@ -814,8 +831,9 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
814
831
  // For sniffing in tests.
815
832
  }
816
833
 
817
- private async rebuildSectionsForMatchedStyleRules(matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles):
818
- Promise<SectionBlock[]> {
834
+ private async rebuildSectionsForMatchedStyleRules(
835
+ matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles, computedStyles: Map<string, string>|null,
836
+ parentsComputedStyles: Map<string, string>|null): Promise<SectionBlock[]> {
819
837
  if (this.idleCallbackManager) {
820
838
  this.idleCallbackManager.discard();
821
839
  }
@@ -872,7 +890,8 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
872
890
  const lastBlock = blocks[blocks.length - 1];
873
891
  if (lastBlock) {
874
892
  this.idleCallbackManager.schedule(() => {
875
- const section = new StylePropertiesSection(this, matchedStyles, style, sectionIdx);
893
+ const section =
894
+ new StylePropertiesSection(this, matchedStyles, style, sectionIdx, computedStyles, parentsComputedStyles);
876
895
  sectionIdx++;
877
896
  lastBlock.sections.push(section);
878
897
  });
@@ -941,7 +960,8 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
941
960
  addLayerSeparator(style);
942
961
  const lastBlock = blocks[blocks.length - 1];
943
962
  this.idleCallbackManager.schedule(() => {
944
- const section = new HighlightPseudoStylePropertiesSection(this, matchedStyles, style, sectionIdx);
963
+ const section = new HighlightPseudoStylePropertiesSection(
964
+ this, matchedStyles, style, sectionIdx, computedStyles, parentsComputedStyles);
945
965
  sectionIdx++;
946
966
  lastBlock.sections.push(section);
947
967
  });
@@ -22,6 +22,7 @@ import './StylePropertyHighlighter.js';
22
22
  import './StylesSidebarPane.js';
23
23
  import './StylePropertyTreeElement.js';
24
24
  import './ComputedStyleWidget.js';
25
+ import './CSSRuleValidator.js';
25
26
  import './ElementsPanel.js';
26
27
  import './ClassesPaneWidget.js';
27
28
  import './ElementStatePaneWidget.js';
@@ -32,6 +33,7 @@ import * as ClassesPaneWidget from './ClassesPaneWidget.js';
32
33
  import * as ColorSwatchPopoverIcon from './ColorSwatchPopoverIcon.js';
33
34
  import * as ComputedStyleModel from './ComputedStyleModel.js';
34
35
  import * as ComputedStyleWidget from './ComputedStyleWidget.js';
36
+ import * as CSSRuleValidator from './CSSRuleValidator.js';
35
37
  import * as DOMLinkifier from './DOMLinkifier.js';
36
38
  import * as DOMPath from './DOMPath.js';
37
39
  import * as ElementsPanel from './ElementsPanel.js';
@@ -62,6 +64,7 @@ export {
62
64
  ColorSwatchPopoverIcon,
63
65
  ComputedStyleModel,
64
66
  ComputedStyleWidget,
67
+ CSSRuleValidator,
65
68
  DOMLinkifier,
66
69
  DOMPath,
67
70
  ElementsPanel,
@@ -155,6 +155,16 @@ ol.expanded {
155
155
  transform: scale(0.9);
156
156
  }
157
157
 
158
+ .hint {
159
+ position: absolute;
160
+ top: 0;
161
+ bottom: 0;
162
+ margin: auto;
163
+ display: inline-block;
164
+ cursor: pointer;
165
+ transform: scale(0.9);
166
+ }
167
+
158
168
  .has-ignorable-error {
159
169
  color: var(--color-text-disabled);
160
170
  }
@@ -16,3 +16,7 @@
16
16
  .data-grid .event-display-table-basic-text-table-entry {
17
17
  line-height: 26px;
18
18
  }
19
+
20
+ .event-display-table-contents-json-wrapper > .json-view {
21
+ overflow: visible;
22
+ }
@@ -67,11 +67,18 @@ export class PreviewToggle extends HTMLElement {
67
67
 
68
68
  #render(): void {
69
69
  const checked = Root.Runtime.experiments.isEnabled(this.#experiment);
70
+ const hasLink = Boolean(this.#feedbackURL) || Boolean(this.#learnMoreURL);
71
+
72
+ const containerClasses = LitHtml.Directives.classMap({
73
+ 'container': true,
74
+ 'has-link': hasLink,
75
+ });
76
+
70
77
  // Disabled until https://crbug.com/1079231 is fixed.
71
78
  // clang-format off
72
79
  render(
73
80
  html`
74
- <div class="container">
81
+ <div class=${containerClasses}>
75
82
  <div class="checkbox-line">
76
83
  <label class="experiment-preview">
77
84
  <input type="checkbox" ?checked=${checked} @change=${this.#checkboxChanged} aria-label=${this.#name}/>
@@ -33,6 +33,12 @@
33
33
  padding: 4px;
34
34
  }
35
35
 
36
+ .container.has-link {
37
+ /* For x-link outline not to paint over the helper text
38
+ we need to have 2 * <padding>px additional line height */
39
+ line-height: calc(1em + 8px);
40
+ }
41
+
36
42
  .x-link {
37
43
  color: var(--color-primary);
38
44
  text-decoration-line: underline;
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.1018017"
58
+ "version": "1.0.1019017"
59
59
  }