chrome-devtools-frontend 1.0.1581449 → 1.0.1581708

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.
Files changed (54) hide show
  1. package/agents/prompts/merging-devtools-module.md +144 -0
  2. package/agents/prompts/ui-widgets.md +351 -0
  3. package/agents/prompts/verification.md +2 -1
  4. package/docs/contributing/README.md +5 -6
  5. package/docs/contributing/changes.md +1 -2
  6. package/docs/styleguide/ux/README.md +1 -1
  7. package/front_end/core/sdk/OverlayModel.ts +4 -2
  8. package/front_end/core/sdk/StorageKeyManager.ts +6 -1
  9. package/front_end/core/sdk/Target.ts +4 -2
  10. package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +22 -16
  11. package/front_end/entrypoints/greendev_floaty/floaty.css +41 -1
  12. package/front_end/entrypoints/greendev_floaty/floaty.html +8 -1
  13. package/front_end/entrypoints/greendev_floaty/greendev_floaty.ts +4 -4
  14. package/front_end/entrypoints/node_app/app/NodeMain.ts +19 -1
  15. package/front_end/entrypoints/node_app/node_app.ts +34 -0
  16. package/front_end/models/ai_assistance/AiConversation.ts +10 -0
  17. package/front_end/models/ai_assistance/agents/AiAgent.ts +2 -0
  18. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +22 -0
  19. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +71 -1
  20. package/front_end/models/computed_style/ComputedStyleModel.ts +26 -0
  21. package/front_end/models/issues_manager/CookieIssue.ts +0 -28
  22. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +87 -6
  23. package/front_end/panels/ai_assistance/components/ChatInput.ts +1 -1
  24. package/front_end/panels/application/ApplicationPanelSidebar.ts +13 -11
  25. package/front_end/panels/application/DOMStorageModel.ts +1 -1
  26. package/front_end/panels/application/ResourcesPanel.ts +10 -5
  27. package/front_end/panels/common/AiCodeCompletionTeaser.ts +13 -3
  28. package/front_end/panels/common/aiCodeCompletionTeaser.css +6 -0
  29. package/front_end/panels/console_counters/WarningErrorCounter.ts +16 -10
  30. package/front_end/panels/elements/ComputedStyleWidget.ts +55 -37
  31. package/front_end/panels/elements/PlatformFontsWidget.ts +23 -10
  32. package/front_end/panels/greendev/GreenDevPanel.css +42 -1
  33. package/front_end/panels/greendev/GreenDevPanel.ts +30 -1
  34. package/front_end/panels/network/RequestInitiatorView.ts +8 -11
  35. package/front_end/panels/network/RequestTimingView.ts +1 -1
  36. package/front_end/panels/settings/KeybindsSettingsTab.ts +4 -3
  37. package/front_end/panels/sources/OutlineQuickOpen.ts +19 -0
  38. package/front_end/panels/timeline/TimelinePanel.ts +25 -0
  39. package/front_end/third_party/lighthouse/README.chromium +2 -2
  40. package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +145 -144
  41. package/front_end/third_party/lighthouse/report/bundle.js +12 -5
  42. package/front_end/third_party/lighthouse/report-assets/report-generator.mjs +2 -2
  43. package/front_end/ui/legacy/ListControl.ts +28 -1
  44. package/front_end/ui/legacy/Treeoutline.ts +1 -1
  45. package/front_end/ui/legacy/UIUtils.ts +17 -7
  46. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +4 -2
  47. package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
  48. package/inspector_overlay/main.ts +18 -3
  49. package/inspector_overlay/tool_green_dev_anchors.css +54 -0
  50. package/inspector_overlay/tool_green_dev_anchors.ts +164 -0
  51. package/inspector_overlay/tool_persistent.ts +14 -0
  52. package/package.json +1 -1
  53. package/docs/contributing/design.md +0 -166
  54. package/docs/design_guidelines.md +0 -1
@@ -282,6 +282,26 @@ export class ListControl<T> {
282
282
  return false;
283
283
  }
284
284
 
285
+ selectFirstItem(center?: boolean): boolean {
286
+ const index = this.findFirstSelectable(0, +1, false);
287
+ if (index !== -1) {
288
+ this.scrollIntoView(index, center);
289
+ this.select(index);
290
+ return true;
291
+ }
292
+ return false;
293
+ }
294
+
295
+ selectLastItem(center?: boolean): boolean {
296
+ const index = this.findFirstSelectable(this.model.length - 1, -1, false);
297
+ if (index !== -1) {
298
+ this.scrollIntoView(index, center);
299
+ this.select(index);
300
+ return true;
301
+ }
302
+ return false;
303
+ }
304
+
285
305
  private scrollIntoView(index: number, center?: boolean): void {
286
306
  if (this.mode === ListMode.NonViewport) {
287
307
  this.elementAtIndex(index).scrollIntoViewIfNeeded(Boolean(center));
@@ -328,6 +348,12 @@ export class ListControl<T> {
328
348
  case 'PageDown':
329
349
  selected = this.selectItemNextPage(false);
330
350
  break;
351
+ case 'Home':
352
+ selected = this.selectFirstItem();
353
+ break;
354
+ case 'End':
355
+ selected = this.selectLastItem();
356
+ break;
331
357
  }
332
358
  if (selected) {
333
359
  event.consume(true);
@@ -364,7 +390,8 @@ export class ListControl<T> {
364
390
  element = this.delegate.createElementForItem(item);
365
391
  if (!element.hasAttribute('jslog')) {
366
392
  element.setAttribute(
367
- 'jslog', `${VisualLogging.item().track({click: true, keydown: 'ArrowUp|ArrowDown|PageUp|PageDown'})}`);
393
+ 'jslog',
394
+ `${VisualLogging.item().track({click: true, keydown: 'ArrowUp|ArrowDown|PageUp|PageDown|Home|End'})}`);
368
395
  }
369
396
  this.itemToElement.set(item, element);
370
397
  this.updateElementARIA(element, index);
@@ -1566,7 +1566,7 @@ class TreeViewTreeElement extends TreeElement {
1566
1566
  this.listItemElement.classList.add(className);
1567
1567
  this.#clonedClasses.add(className);
1568
1568
  }
1569
- InterceptBindingDirective.attachEventListeners(this.configElement, this.listItemElement);
1569
+ InterceptBindingDirective.setEventListeners(this.configElement, this.listItemElement);
1570
1570
 
1571
1571
  for (const child of this.configElement.childNodes) {
1572
1572
  if (child instanceof HTMLUListElement && child.role === 'group') {
@@ -1970,6 +1970,7 @@ export function bindToAction(actionName: string): ReturnType<typeof Directives.r
1970
1970
  type BindingEventListener = (arg: any) => any;
1971
1971
  export class InterceptBindingDirective extends Lit.Directive.Directive {
1972
1972
  static readonly #interceptedBindings = new WeakMap<Element, Map<string, BindingEventListener>>();
1973
+ static readonly #attachedBindings = new WeakMap<Element, Map<string, BindingEventListener>>();
1973
1974
 
1974
1975
  override update(part: Lit.Directive.Part, [listener]: [BindingEventListener]): unknown {
1975
1976
  if (part.type !== Lit.Directive.PartType.EVENT) {
@@ -1990,13 +1991,22 @@ export class InterceptBindingDirective extends Lit.Directive.Directive {
1990
1991
  return undefined;
1991
1992
  }
1992
1993
 
1993
- static attachEventListeners(templateElement: Element, renderedElement: Element): void {
1994
- const eventListeners = InterceptBindingDirective.#interceptedBindings.get(templateElement);
1995
- if (!eventListeners) {
1996
- return;
1994
+ static setEventListeners(templateElement: Element, renderedElement: Element): void {
1995
+ const attachedListeners = InterceptBindingDirective.#attachedBindings.get(renderedElement);
1996
+ if (attachedListeners) {
1997
+ for (const [name, listener] of attachedListeners) {
1998
+ renderedElement.removeEventListener(name, listener);
1999
+ }
1997
2000
  }
1998
- for (const [name, listener] of eventListeners) {
1999
- renderedElement.addEventListener(name, listener);
2001
+
2002
+ const newListeners = InterceptBindingDirective.#interceptedBindings.get(templateElement);
2003
+ if (newListeners?.size) {
2004
+ for (const [name, listener] of newListeners) {
2005
+ renderedElement.addEventListener(name, listener);
2006
+ }
2007
+ InterceptBindingDirective.#attachedBindings.set(renderedElement, new Map(newListeners));
2008
+ } else {
2009
+ InterceptBindingDirective.#attachedBindings.delete(renderedElement);
2000
2010
  }
2001
2011
  }
2002
2012
  }
@@ -2029,7 +2039,7 @@ export class HTMLElementWithLightDOMTemplate extends HTMLElement {
2029
2039
  clone.appendChild(HTMLElementWithLightDOMTemplate.cloneNode(child));
2030
2040
  }
2031
2041
  if (node instanceof Element && clone instanceof Element) {
2032
- InterceptBindingDirective.attachEventListeners(node, clone);
2042
+ InterceptBindingDirective.setEventListeners(node, clone);
2033
2043
  }
2034
2044
  return clone;
2035
2045
  }
@@ -353,8 +353,6 @@ export class StackTracePreviewContent extends UI.Widget.Widget {
353
353
  this.#table = this.contentElement.createChild('table', 'stack-preview-container');
354
354
  this.#table.classList.toggle('width-constrained', this.#options.widthConstrained ?? false);
355
355
 
356
- this.#stackTrace?.addEventListener(StackTrace.StackTrace.Events.UPDATED, this.performUpdate.bind(this));
357
-
358
356
  this.performUpdate();
359
357
  }
360
358
 
@@ -407,7 +405,11 @@ export class StackTracePreviewContent extends UI.Widget.Widget {
407
405
  }
408
406
 
409
407
  set stackTrace(stackTrace: StackTrace.StackTrace.StackTrace) {
408
+ if (this.#stackTrace) {
409
+ this.#stackTrace.removeEventListener(StackTrace.StackTrace.Events.UPDATED, this.requestUpdate, this);
410
+ }
410
411
  this.#stackTrace = stackTrace;
412
+ this.#stackTrace.addEventListener(StackTrace.StackTrace.Events.UPDATED, this.requestUpdate, this);
411
413
  this.requestUpdate();
412
414
  }
413
415
 
@@ -923,12 +923,14 @@ export const knownContextValues = new Set([
923
923
  'content-type',
924
924
  'content-visibility',
925
925
  'context',
926
+ 'context-added',
926
927
  'context-change-drjones-file',
927
928
  'context-change-drjones-network-request',
928
929
  'context-change-drjones-performance',
929
930
  'context-change-freestyler',
930
931
  'context-change-none',
931
932
  'context-change-performance-insight',
933
+ 'context-removed',
932
934
  'context3',
933
935
  'contextmenu',
934
936
  'continue',
@@ -7,6 +7,13 @@ import commonStyle from './common.css';
7
7
  import {adoptStyleSheet} from './common.js';
8
8
  import {gridStyle} from './highlight_grid_common.js';
9
9
  // @ts-expect-error Importing CSS is handled in Rollup.
10
+ import greenDevAnchorsStyle from './tool_green_dev_anchors.css';
11
+ import {
12
+ type GreenDevAnchorsDispatchMessage,
13
+ GreenDevAnchorsOverlay,
14
+ type GreenDevAnchorsToolMessage
15
+ } from './tool_green_dev_anchors.js';
16
+ // @ts-expect-error Importing CSS is handled in Rollup.
10
17
  import highlightGridStyle from './tool_grid.css';
11
18
  // @ts-expect-error Importing CSS is handled in Rollup.
12
19
  import highlightStyle from './tool_highlight.css';
@@ -29,7 +36,9 @@ import {WindowControlsOverlay} from './tool_window_controls.js';
29
36
  declare global {
30
37
  interface Window {
31
38
  // eslint-disable-next-line @typescript-eslint/naming-convention
32
- InspectorOverlayHost: {send(data: PausedToolMessage|PersistentToolMessage|ScreenshotToolMessage|string): void};
39
+ InspectorOverlayHost: {
40
+ send(data: PausedToolMessage|PersistentToolMessage|ScreenshotToolMessage|GreenDevAnchorsToolMessage|string): void,
41
+ };
33
42
  }
34
43
  }
35
44
 
@@ -39,14 +48,18 @@ const gridStyleSheet = new CSSStyleSheet();
39
48
  gridStyleSheet.replaceSync(gridStyle);
40
49
 
41
50
  const highlightOverlay = new HighlightOverlay(window, [highlightStyle, gridStyleSheet]);
42
- const persistentOverlay = new PersistentOverlay(window, [highlightGridStyle, gridStyleSheet]);
51
+ const persistentOverlay = new PersistentOverlay(window, [highlightGridStyle, greenDevAnchorsStyle, gridStyleSheet]);
43
52
  const pausedOverlay = new PausedOverlay(window, pausedStyle);
44
53
  const screenshotOverlay = new ScreenshotOverlay(window, screenshotStyle);
54
+ const greenDevAnchorsOverlay = new GreenDevAnchorsOverlay(window, greenDevAnchorsStyle);
45
55
  const sourceOrderOverlay = new SourceOrderOverlay(window, sourceOrderStyle);
46
56
  const viewportSizeOverlay = new ViewportSizeOverlay(window);
47
57
  const windowControlsOverlay = new WindowControlsOverlay(window, [wcoStyle]);
48
58
 
59
+ persistentOverlay.setGreenDevAnchorsOverlay(greenDevAnchorsOverlay);
60
+
49
61
  interface Overlays {
62
+ greenDevFloaty: GreenDevAnchorsOverlay;
50
63
  highlight: HighlightOverlay;
51
64
  persistent: PersistentOverlay;
52
65
  paused: PausedOverlay;
@@ -60,6 +73,7 @@ type PlatformName = string;
60
73
 
61
74
  // Key in this object is the name the backend refers to a particular overlay by.
62
75
  const overlays: Overlays = {
76
+ greenDevFloaty: greenDevAnchorsOverlay,
63
77
  highlight: highlightOverlay,
64
78
  persistent: persistentOverlay,
65
79
  paused: pausedOverlay,
@@ -76,6 +90,7 @@ interface MessageLookup {
76
90
  setOverlay: keyof Overlays;
77
91
  setPlatform: PlatformName;
78
92
  drawingFinished: '';
93
+ update: GreenDevAnchorsDispatchMessage;
79
94
  }
80
95
 
81
96
  const dispatch = <K extends keyof MessageLookup>(message: [a: K, b: MessageLookup[K]]) => {
@@ -93,7 +108,7 @@ const dispatch = <K extends keyof MessageLookup>(message: [a: K, b: MessageLooku
93
108
  currentOverlay.install();
94
109
  }
95
110
  } else if (functionName === 'setPlatform') {
96
- platformName = message[1];
111
+ platformName = message[1] as PlatformName;
97
112
  } else if (functionName === 'drawingFinished') {
98
113
  // TODO The logic needs to be added here once the backend starts sending this event.
99
114
  } else {
@@ -0,0 +1,54 @@
1
+ /*
2
+ * Copyright 2026 The Chromium Authors
3
+ * Use of this source code is governed by a BSD-style license that can be
4
+ * found in the LICENSE file.
5
+ */
6
+ /* eslint-disable color-named, plugin/use_theme_colors */
7
+
8
+ :root {
9
+ --gemini-logo: url("data:image/svg+xml,%0A%3Csvg%20fill%3D%22none%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2065%2065%22%3E%3Cmask%20id%3D%22maskme%22%20style%3D%22mask-type%3Aalpha%22%20maskUnits%3D%22userSpaceOnUse%22%20x%3D%220%22%20y%3D%220%22%20width%3D%2265%22%20height%3D%2265%22%3E%3Cpath%20d%3D%22M32.447%200c.68%200%201.273.465%201.439%201.125a38.904%2038.904%200%20001.999%205.905c2.152%205%205.105%209.376%208.854%2013.125%203.751%203.75%208.126%206.703%2013.125%208.855a38.98%2038.98%200%20005.906%201.999c.66.166%201.124.758%201.124%201.438%200%20.68-.464%201.273-1.125%201.439a38.902%2038.902%200%2000-5.905%201.999c-5%202.152-9.375%205.105-13.125%208.854-3.749%203.751-6.702%208.126-8.854%2013.125a38.973%2038.973%200%2000-2%205.906%201.485%201.485%200%2001-1.438%201.124c-.68%200-1.272-.464-1.438-1.125a38.913%2038.913%200%2000-2-5.905c-2.151-5-5.103-9.375-8.854-13.125-3.75-3.749-8.125-6.702-13.125-8.854a38.973%2038.973%200%2000-5.905-2A1.485%201.485%200%20010%2032.448c0-.68.465-1.272%201.125-1.438a38.903%2038.903%200%20005.905-2c5-2.151%209.376-5.104%2013.125-8.854%203.75-3.749%206.703-8.125%208.855-13.125a38.972%2038.972%200%20001.999-5.905A1.485%201.485%200%200132.447%200z%22%20fill%3D%22%23000%22/%3E%3Cpath%20d%3D%22M32.447%200c.68%200%201.273.465%201.439%201.125a38.904%2038.904%200%20001.999%205.905c2.152%205%205.105%209.376%208.854%2013.125%203.751%203.75%208.126%206.703%2013.125%208.855a38.98%2038.98%200%20005.906%201.999c.66.166%201.124.758%201.124%201.438%200%20.68-.464%201.273-1.125%201.439a38.902%2038.902%200%2000-5.905%201.999c-5%202.152-9.375%205.105-13.125%208.854-3.749%203.751-6.702%208.126-8.854%2013.125a38.973%2038.973%200%2000-2%205.906%201.485%201.485%200%2001-1.438%201.124c-.68%200-1.272-.464-1.438-1.125a38.913%2038.913%200%2000-2-5.905c-2.151-5-5.103-9.375-8.854-13.125-3.75-3.749-8.125-6.702-13.125-8.854a38.973%2038.973%200%2000-5.905-2A1.485%201.485%200%20010%2032.448c0-.68.465-1.272%201.125-1.438a38.903%2038.903%200%20005.905-2c5-2.151%209.376-5.104%2013.125-8.854%203.75-3.749%206.703-8.125%208.855-13.125a38.972%2038.972%200%20001.999-5.905A1.485%201.485%200%200132.447%200z%22%20fill%3D%22%23000%22/%3E%3C/mask%3E%3Cg%20mask%3D%22url(%23maskme)%22%3E%3Cpath%20fill%3D%22%234285F4%22%20d%3D%22M0%200h38.235L65%2027.66%2065%2065H0z%22/%3E%3Cpath%20fill%3D%22%23EA4335%22%20d%3D%22M26.765%200H65v38.235z%22/%3E%3Cpath%20fill%3D%22%2334A853%22%20d%3D%22M0%2026.765H38.235V65H0z%22/%3E%3Cpath%20fill%3D%22%23FBBC04%22%20d%3D%22M27.66%2065L65%2038.235V65z%22/%3E%3C/g%3E%3C/svg%3E");
10
+ --open-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6' /%3E%3Cpolyline points='15 3 21 3 21 9' /%3E%3Cline x1='10' y1='14' x2='21' y2='3' /%3E%3C/svg%3E");
11
+ }
12
+
13
+ #green-dev-anchors-container {
14
+ position: absolute;
15
+ top: 0;
16
+ left: 0;
17
+ width: 100%;
18
+ height: 100%;
19
+ z-index: 1000;
20
+ pointer-events: none;
21
+ }
22
+
23
+ .green-dev-anchor-minimal {
24
+ position: absolute;
25
+ width: 70px;
26
+ height: 40px;
27
+ background-color: #fff;
28
+ border-radius: 12px;
29
+ box-shadow: 0 4px 8px rgb(0 0 0 / 20%);
30
+ pointer-events: auto;
31
+ z-index: 1001;
32
+ display: flex;
33
+ align-items: center;
34
+ justify-content: center;
35
+ padding: 0 5px;
36
+ cursor: pointer;
37
+ }
38
+
39
+ .green-dev-anchor-icon-gemini {
40
+ width: 24px;
41
+ height: 24px;
42
+ background-image: var(--gemini-logo);
43
+ background-size: cover;
44
+ background-repeat: no-repeat;
45
+ margin-right: 5px;
46
+ }
47
+
48
+ .green-dev-anchor-icon-open {
49
+ width: 20px;
50
+ height: 20px;
51
+ background-image: var(--open-icon);
52
+ background-size: cover;
53
+ background-repeat: no-repeat;
54
+ }
@@ -0,0 +1,164 @@
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 {Overlay} from './common.js';
6
+
7
+ export interface GreenDevAnchorsHighlight {
8
+ nodeId: number;
9
+ x: number;
10
+ y: number;
11
+ }
12
+
13
+ export type GreenDevAnchorsToolMessage = {
14
+ highlightType: 'greenDevFloaty',
15
+ command: 'setInputValue',
16
+ nodeId: number,
17
+ value: string,
18
+ }|{
19
+ highlightType: 'greenDevFloaty',
20
+ command: 'debugMessage',
21
+ message: string,
22
+ }|{
23
+ highlightType: 'greenDevFloaty',
24
+ command: 'openDevTools',
25
+ nodeId: number,
26
+ }|{
27
+ highlightType: 'greenDevFloaty',
28
+ command: 'restoreFloaty',
29
+ nodeId: number,
30
+ };
31
+
32
+ function consoleLog(message: string) {
33
+ window.InspectorOverlayHost.send({highlightType: 'greenDevFloaty', command: 'debugMessage', message});
34
+ }
35
+
36
+ export interface GreenDevAnchorsDispatchMessage {
37
+ nodeId: number;
38
+ value: string;
39
+ }
40
+
41
+ export class GreenDevAnchorsOverlay extends Overlay {
42
+ #anchorsContainer!: HTMLElement;
43
+ #anchorsByNodeId = new Map<number, HTMLElement>();
44
+
45
+ override install() {
46
+ consoleLog('GreenDevAnchorsOverlay.install() called');
47
+
48
+ this.document.body.classList.add('fill');
49
+
50
+ const canvas = this.document.createElement('canvas');
51
+ canvas.id = 'canvas';
52
+ canvas.classList.add('fill');
53
+ canvas.style.pointerEvents = 'none';
54
+ this.document.body.append(canvas);
55
+
56
+ const anchorsContainer = this.document.createElement('div');
57
+ anchorsContainer.id = 'green-dev-anchors-container';
58
+ this.document.body.append(anchorsContainer);
59
+ this.#anchorsContainer = anchorsContainer;
60
+
61
+ this.setCanvas(canvas);
62
+ super.install();
63
+ }
64
+
65
+ override uninstall() {
66
+ consoleLog('GreenDevAnchorsOverlay.uninstall() called');
67
+
68
+ this.document.body.classList.remove('fill');
69
+ if (this.#anchorsContainer && this.#anchorsContainer.parentElement) {
70
+ this.#anchorsContainer.parentElement.removeChild(this.#anchorsContainer);
71
+ }
72
+ // Clear the map as the elements are removed from DOM.
73
+ this.#anchorsByNodeId.clear();
74
+ super.uninstall();
75
+ }
76
+
77
+ drawGreenDevAnchors(highlights: GreenDevAnchorsHighlight[]) {
78
+ if (this.#anchorsContainer && !this.#anchorsContainer.isConnected) {
79
+ // The container was removed from the DOM (likely by PersistentOverlay.uninstall cleaning up),
80
+ // but this overlay still thinks it's installed. We need to re-install to restore the DOM.
81
+ try {
82
+ this.uninstall();
83
+ } catch (e) {
84
+ console.error('Error during uninstall in drawGreenDevAnchors:', e);
85
+ }
86
+ this.install();
87
+ }
88
+
89
+ const newAnchorsByNodeId = new Map<number, HTMLElement>();
90
+
91
+ for (const highlight of highlights) {
92
+ const {x, y, nodeId} = highlight;
93
+ let anchor = this.#anchorsByNodeId.get(nodeId);
94
+
95
+ if (anchor) {
96
+ anchor.style.left = `${x}px`;
97
+ anchor.style.top = `${y}px`;
98
+ // Remove from the old map so only anchors that need to be deleted remain.
99
+ this.#anchorsByNodeId.delete(nodeId);
100
+ } else {
101
+ const newAnchor = this.drawGreenDevAnchor(highlight);
102
+ if (!newAnchor) {
103
+ continue;
104
+ }
105
+ anchor = newAnchor;
106
+ anchor.style.left = `${x}px`;
107
+ anchor.style.top = `${y}px`;
108
+ this.#anchorsContainer.append(anchor);
109
+ }
110
+ newAnchorsByNodeId.set(nodeId, anchor);
111
+ }
112
+
113
+ // Remove any anchors that were not present in the new highlights list.
114
+ for (const anchor of this.#anchorsByNodeId.values()) {
115
+ anchor.remove();
116
+ }
117
+
118
+ this.#anchorsByNodeId = newAnchorsByNodeId;
119
+ }
120
+
121
+ private drawGreenDevAnchor(highlight: GreenDevAnchorsHighlight): HTMLElement {
122
+ const {nodeId} = highlight;
123
+ const anchor = this.document.createElement('div');
124
+ anchor.classList.add('green-dev-anchor-minimal');
125
+
126
+ const geminiIcon = this.document.createElement('div');
127
+ geminiIcon.classList.add('green-dev-anchor-icon-gemini');
128
+ anchor.append(geminiIcon);
129
+
130
+ const openIcon = this.document.createElement('div');
131
+ openIcon.classList.add('green-dev-anchor-icon-open');
132
+ anchor.append(openIcon);
133
+
134
+ const onEvent = (event: MouseEvent) => {
135
+ event.stopPropagation();
136
+ event.preventDefault();
137
+ };
138
+
139
+ openIcon.addEventListener('mousedown', onEvent);
140
+ openIcon.addEventListener('mouseup', onEvent);
141
+ openIcon.addEventListener('mousemove', onEvent);
142
+ openIcon.addEventListener('mouseenter', onEvent);
143
+ openIcon.addEventListener('mouseleave', onEvent);
144
+ openIcon.addEventListener('click', (event: MouseEvent) => {
145
+ onEvent(event);
146
+ window.InspectorOverlayHost.send({highlightType: 'greenDevFloaty', command: 'openDevTools', nodeId});
147
+ });
148
+
149
+ anchor.addEventListener('mousedown', onEvent);
150
+ anchor.addEventListener('mouseup', onEvent);
151
+ anchor.addEventListener('mousemove', onEvent);
152
+ anchor.addEventListener('mouseenter', onEvent);
153
+ anchor.addEventListener('mouseleave', onEvent);
154
+ anchor.addEventListener('click', (event: MouseEvent) => {
155
+ if (event.target !== anchor && !anchor.contains(event.target as Node)) {
156
+ return;
157
+ }
158
+ onEvent(event);
159
+ window.InspectorOverlayHost.send({highlightType: 'greenDevFloaty', command: 'restoreFloaty', nodeId});
160
+ });
161
+
162
+ return anchor;
163
+ }
164
+ }
@@ -9,6 +9,7 @@ import {drawLayoutFlexContainerHighlight, type FlexContainerHighlight} from './h
9
9
  import {drawLayoutGridHighlight, type GridHighlight} from './highlight_grid_common.js';
10
10
  import {drawIsolatedElementHighlight, type IsolatedElementHighlight} from './highlight_isolated_element.js';
11
11
  import {drawScrollSnapHighlight, type ScrollSnapHighlight} from './highlight_scroll_snap.js';
12
+ import type {GreenDevAnchorsHighlight, GreenDevAnchorsOverlay} from './tool_green_dev_anchors.js';
12
13
 
13
14
  export interface PersistentToolMessage {
14
15
  highlightType: string;
@@ -65,11 +66,17 @@ export class PersistentOverlay extends Overlay {
65
66
  initialHeight: number,
66
67
  }>();
67
68
  private dragHandler?: DragResizeHandler;
69
+ private greenDevAnchorsOverlay?: GreenDevAnchorsOverlay;
70
+
71
+ setGreenDevAnchorsOverlay(greenDevAnchorsOverlay: GreenDevAnchorsOverlay) {
72
+ this.greenDevAnchorsOverlay = greenDevAnchorsOverlay;
73
+ }
68
74
 
69
75
  override reset(data: ResetData) {
70
76
  super.reset(data);
71
77
  this.gridLabelState.gridLayerCounter = 0;
72
78
  this.gridLabels.innerHTML = '';
79
+ this.greenDevAnchorsOverlay?.reset(data);
73
80
  }
74
81
 
75
82
  renderGridMarkup() {
@@ -129,6 +136,13 @@ export class PersistentOverlay extends Overlay {
129
136
  this.context.restore();
130
137
  }
131
138
 
139
+ drawGreenDevFloatyAnchors(highlights: GreenDevAnchorsHighlight[]) {
140
+ if (this.greenDevAnchorsOverlay && !this.greenDevAnchorsOverlay.installed) {
141
+ this.greenDevAnchorsOverlay.install();
142
+ }
143
+ this.greenDevAnchorsOverlay?.drawGreenDevAnchors(highlights);
144
+ }
145
+
132
146
  drawIsolatedElementHighlight(highlight: IsolatedElementHighlight) {
133
147
  if (!this.dragHandler) {
134
148
  this.dragHandler = new DragResizeHandler(this.document, makeDraggableDelegate(this));
package/package.json CHANGED
@@ -105,5 +105,5 @@
105
105
  "flat-cache": "6.1.12"
106
106
  }
107
107
  },
108
- "version": "1.0.1581449"
108
+ "version": "1.0.1581708"
109
109
  }
@@ -1,166 +0,0 @@
1
- # Design Documents
2
-
3
- **TL;DR**: This document outlines the development process for Chromium DevTools,
4
- in particular the established culture and processes around design artifacts.
5
-
6
- [TOC]
7
-
8
- ## Writing a design document
9
-
10
- Any non-trivial technical effort that will significantly impact Chromium DevTools
11
- should have a design doc ([template](https://goo.gle/devtools-design-doc-template)),
12
- sometimes also referred to as _bluedoc_. Specifically, we require design docs
13
- (DDs) in the following cases:
14
-
15
- 1. When writing code that will have a large impact on DevTools as a whole, e.g.
16
- when you are changing behavior of a critical component like the Console or
17
- Sources panel.
18
- 1. When beginning a large technical undertaking that should be documented for
19
- historical reasons (>1 person-month of work can be used as a general
20
- guideline).
21
-
22
- *** promo
23
- **Tip (Googlers):**
24
- For smaller scale changes or when you are not sure yet whether any of the
25
- criteria above will apply, but you still want to have it written up and
26
- discussed, you can start with a Design Proposal
27
- ([template](http://go/chrome-devtools-greendoc-template)).
28
- These should always be Google internal.
29
- ***
30
-
31
- Public design docs have to live in the
32
- [Design Documents](https://drive.google.com/drive/folders/1JbUthATfybvMQR3yAHC4J0P7n6oftYNq)
33
- folder of the shared public
34
- [Chromium DevTools](http://go/chrome-devtools/team-resources#chromium-devtools-shared-drive) team drive,
35
- which automatically makes them commentable for
36
- [contributors@chromium.org](mailto:contributors@chromium.org) and
37
- [devtools-dev@chromium.org](mailto:devtools-dev@chromium.org). And they need to
38
- be send to
39
- [devtools-dev+design@chromium.org](mailto:devtools-dev+design@chromium.org).
40
-
41
- Google internal design docs have to live in the
42
- [Design Documents (internal)](http://go/chrome-devtools:design-internal-drive)
43
- folder of the shared internal
44
- [Chrome DevTools](http://go/chrome-devtools/team-resources#chrome-devtools-shared-drive) team drive, and
45
- should be sent to
46
- [chrome-devtools@google.com](mailto:chrome-devtools@google.com).
47
-
48
- *** note
49
- **IMPORTANT (Googlers):** Every design document (whether public or internal) must be editable
50
- by [chrome-devtools-staff@google.com](mailto:chrome-devtools-staff@google.com) and
51
- must have a `go/chrome-devtools:<project-name>-design` go/ link pointing to it
52
- (even for publicly visible documents).
53
- ***
54
-
55
- Follow the steps in the
56
- [Chrome DevTools Design Review Guidelines](#Review-Guidelines)
57
- to proceed with your design document and get it reviewed and approved.
58
-
59
- ## Review Guidelines
60
-
61
- When contributing to Chrome DevTools, please follow the process explained in this document. This is to reach a clear agreement on proposals, while involving all relevant stakeholders and decision makers.
62
-
63
- This process puts the IC in charge, but also requires Chrome DevTools' leaders to help the IC navigate the decision process. It includes an escalation path in case of disagreement. The overhead of this process should be proportionate to the scope of the proposal.
64
-
65
- **Important:**
66
-
67
- 1. Assume good intentions.
68
- 1. Be kind and civilized.
69
- 1. Be pragmatic.
70
-
71
- ![DevTools Design Process](./images/design-guidelines.png)
72
-
73
- ### Roles
74
-
75
- #### Individual Contributor (IC)
76
-
77
- _LGTM_: N/A
78
-
79
- This person is the creator of the feature and the creator of the design documentation.
80
-
81
- #### Technical Lead (TL)
82
-
83
- _LGTM_: Required. May delegate.
84
-
85
- The Chrome DevTools TL is Danil Somsikov (dsv@chromium.org). The TL ensures architectural consistency and good coverage by the right set of LGTM providers, and is required to sign off on the design. They may however explicitly delegate to other LGTM providers.
86
-
87
- In the absence of the TL, an EnReOw can act in their stead.
88
-
89
- #### LGTM provider
90
-
91
- _LGTM_: Required. May delegate.
92
-
93
- This is a person that is required to give LGTM. These are usually ICs with significant knowledge about the areas in question.
94
-
95
- #### Reviewer
96
-
97
- _LGTM_: Not required.
98
-
99
- This is somebody who reviews and comments on the proposal. Their input should be considered, although their LGTM is not required.
100
-
101
- #### The Eng Review Owners (EnReOw)
102
-
103
- _LGTM_: Not required. However, LGTM or non-LGTM is binding.
104
-
105
- Stuck proposals can be escalated to the [ENG_REVIEW_OWNERS](https://cs.chromium.org/chromium/src/third_party/devtools-frontend/src/config/owner/ENG_REVIEW_OWNERS). Potential use cases of such an escalation:
106
-
107
- - An LGTM provider is non-responsive.
108
- - No consensus on the design can be reached.
109
-
110
- The EnReOw can overrule non-LGTMs or LGTMs.
111
-
112
- ### Detailed workflow
113
-
114
- 1. IC shares the document with LGTM providers and reviewers according to the roles listed above.
115
- 1. LGTM providers may add more LGTM providers to remove themselves as LGTM providers.
116
- 1. LGTM providers and reviewers review the design document and add feedback.
117
- 1. IC incorporates feedback and iterates on their design document.
118
- 1. Optional: the design doc is shared publicly with devtools-dev+design@chromium.org (make sure to give comment access to contributors@chromium.org, but untick the "Notify" checkbox).
119
- 1. IC collects LGTMs by addressing feedback. Iterate if necessary.
120
- 1. Once all required LGTMs have been collected, proceed with implementation.
121
- 1. On disagreement that cannot be resolved or unreasonable delays, escalate to EnReOw.
122
- 1. Implement and iterate on CLs with code owners. We expect the implementation to take place on the public repository's main branch. Note that a series of small incremental changes has a higher chance of receiving timely reviews and actionable feedback.
123
-
124
- ## FAQ
125
-
126
- ### Is it worth creating a design document?
127
-
128
- It is always useful to have a design document. Its length can vary depending on the scope of the proposed change.
129
-
130
- ### When should the design process be kicked off?
131
-
132
- As soon as possible so that a wide range of opinions can be taken into consideration. If you share your idea or prototype at a later stage, you risk having to redo the work because you missed a constraint.
133
-
134
- ### How to decide who to add to the list of LGTM providers?
135
-
136
- Some pointers when people should be added to the list of LGTM providers:
137
-
138
- - OWNERs of the source files/directories you anticipate to touch
139
- - Main component expert of the components you anticipate to touch
140
- - Downstream consumers of your changes e.g. when you change an API
141
-
142
- ### Where can I find a template for design documents?
143
-
144
- [goo.gle/devtools-design-doc-template](https://goo.gle/devtools-design-doc-template)
145
-
146
- ### What if I made big changes to the design document?
147
-
148
- Make sure you still have the LGTMs e.g. by pinging the LGTM providers.
149
-
150
- ### LGTM providers do not comment on my design document, what should I do?
151
-
152
- In this case you can follow this path of escalation:
153
-
154
- 1. Ping them directly via mail, chat or comment/assignment in the doc and specifically ask them explicitly to add an LGTM or non-LGTM.
155
- 1. Get your TL involved and ask them for help.
156
- 1. Escalate to EnReOw.
157
-
158
- ### Somebody added me as an LGTM provider to a doc, what should I do?
159
-
160
- Review the design document. If you think there are other people who should take a look, add them as LGTM providers or as reviewers. If you don't think you are the right person, remove yourself as LGTM provider.
161
-
162
- If you agree with the design, add an LGTM to the table. If you have blocking concerns, add "Not LGTM, because <reason>" to the table. Be prepared to re-review the design after another iteration.
163
-
164
- ### How does this work together with the Blink Intents process?
165
-
166
- The Chromium DevTools Design Review Guidelines complement [Chromium’s feature launch process](https://www.chromium.org/blink/launching-features). If you are launching a new Web platform feature, please follow the Chromium launch process. It likely makes sense to have all the LGTMs gathered at the point in time you would send an Intent to Implement.
@@ -1 +0,0 @@
1
- This document has moved [here](./contributing/design.md#Review-Guidelines).