chrome-devtools-frontend 1.0.1606789 → 1.0.1608868

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 (75) hide show
  1. package/docs/ui_engineering.md +2 -0
  2. package/eslint.config.mjs +2 -0
  3. package/front_end/core/common/VersionController.ts +18 -1
  4. package/front_end/core/host/UserMetrics.ts +0 -2
  5. package/front_end/core/platform/node/HostRuntime.ts +1 -1
  6. package/front_end/core/root/ExperimentNames.ts +0 -2
  7. package/front_end/core/sdk/AccessibilityModel.ts +13 -1
  8. package/front_end/core/sdk/ServiceWorkerCacheModel.ts +0 -13
  9. package/front_end/core/sdk/StorageBucketsModel.ts +0 -12
  10. package/front_end/entrypoints/main/MainImpl.ts +2 -11
  11. package/front_end/generated/InspectorBackendCommands.ts +3 -33
  12. package/front_end/generated/SupportedCSSProperties.js +8 -4
  13. package/front_end/generated/protocol-mapping.d.ts +7 -26
  14. package/front_end/generated/protocol-proxy-api.d.ts +5 -24
  15. package/front_end/generated/protocol.ts +2 -296
  16. package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +2 -2
  17. package/front_end/models/ai_assistance/agents/BreakpointDebuggerAgent.ts +1 -1
  18. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +6 -6
  19. package/front_end/models/ai_assistance/agents/ConversationSummaryAgent.ts +2 -1
  20. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +46 -21
  21. package/front_end/{panels/profiler → models/heap_snapshot_model}/ChildrenProvider.ts +3 -4
  22. package/front_end/{panels/profiler → models/heap_snapshot_model}/HeapSnapshotProxy.ts +19 -36
  23. package/front_end/models/heap_snapshot_model/heap_snapshot_model.ts +4 -0
  24. package/front_end/models/javascript_metadata/NativeFunctions.js +0 -4
  25. package/front_end/panels/accessibility/AccessibilitySidebarView.ts +53 -10
  26. package/front_end/panels/accessibility/accessibility.ts +0 -2
  27. package/front_end/panels/accessibility/accessibilitySidebarView.css +10 -0
  28. package/front_end/panels/ai_assistance/components/ChatMessage.ts +6 -5
  29. package/front_end/panels/ai_assistance/components/WalkthroughView.ts +36 -17
  30. package/front_end/panels/ai_assistance/components/chatMessage.css +7 -0
  31. package/front_end/panels/ai_assistance/components/walkthroughView.css +39 -11
  32. package/front_end/panels/application/CrashReportContextView.ts +237 -0
  33. package/front_end/panels/application/IndexedDBModel.ts +0 -10
  34. package/front_end/panels/application/InterestGroupStorageModel.ts +0 -11
  35. package/front_end/panels/application/ReportingApiTreeElement.ts +40 -1
  36. package/front_end/panels/application/SharedStorageModel.ts +0 -11
  37. package/front_end/panels/application/WebMCPView.ts +389 -52
  38. package/front_end/panels/application/application.ts +4 -0
  39. package/front_end/panels/application/components/CrashReportContextGrid.ts +154 -0
  40. package/front_end/panels/application/components/components.ts +2 -0
  41. package/front_end/panels/application/webMCPView.css +107 -10
  42. package/front_end/panels/common/AiCodeCompletionDisclaimer.ts +12 -2
  43. package/front_end/panels/elements/AccessibilityTreeView.ts +10 -6
  44. package/front_end/panels/elements/ElementsPanel.ts +9 -50
  45. package/front_end/panels/elements/StylePropertiesSection.ts +1 -1
  46. package/front_end/panels/elements/elements-meta.ts +1 -0
  47. package/front_end/panels/elements/elementsPanel.css +4 -14
  48. package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +23 -13
  49. package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +30 -30
  50. package/front_end/panels/profiler/HeapSnapshotView.ts +16 -13
  51. package/front_end/panels/profiler/profiler.ts +0 -4
  52. package/front_end/panels/snippets/SnippetsQuickOpen.ts +5 -5
  53. package/front_end/panels/sources/FilteredUISourceCodeListProvider.ts +2 -2
  54. package/front_end/panels/sources/sources-meta.ts +7 -7
  55. package/front_end/panels/timeline/CompatibilityTracksAppender.ts +1 -3
  56. package/front_end/panels/timeline/ThirdPartyTreeView.ts +6 -1
  57. package/front_end/panels/timeline/ThreadAppender.ts +1 -3
  58. package/front_end/panels/timeline/TimelineController.ts +2 -2
  59. package/front_end/panels/timeline/TimelinePanel.ts +2 -4
  60. package/front_end/panels/timeline/TimelineTreeView.ts +32 -2
  61. package/front_end/panels/timeline/components/LiveMetricsView.ts +75 -54
  62. package/front_end/panels/timeline/components/timelineRangeSummaryView.css +8 -0
  63. package/front_end/panels/timeline/thirdPartyTreeView.css +0 -1
  64. package/front_end/panels/timeline/timeline-meta.ts +13 -0
  65. package/front_end/third_party/chromium/README.chromium +1 -1
  66. package/front_end/ui/legacy/TabbedPane.ts +3 -1
  67. package/front_end/ui/legacy/components/quick_open/CommandMenu.ts +3 -3
  68. package/front_end/ui/legacy/components/quick_open/FilteredListWidget.ts +2 -5
  69. package/front_end/ui/legacy/components/quick_open/HelpQuickOpen.ts +4 -4
  70. package/front_end/ui/legacy/components/quick_open/QuickOpen.ts +5 -1
  71. package/front_end/ui/legacy/components/utils/Linkifier.ts +2 -1
  72. package/front_end/ui/legacy/components/utils/imagePreview.css +1 -1
  73. package/front_end/ui/visual_logging/KnownContextValues.ts +2 -3
  74. package/package.json +1 -1
  75. package/front_end/panels/accessibility/AXBreadcrumbsPane.ts +0 -653
@@ -1,653 +0,0 @@
1
- // Copyright 2016 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
- /* eslint-disable @devtools/no-imperative-dom-api */
5
-
6
- import * as Common from '../../core/common/common.js';
7
- import * as Host from '../../core/host/host.js';
8
- import * as i18n from '../../core/i18n/i18n.js';
9
- import * as Root from '../../core/root/root.js';
10
- import * as SDK from '../../core/sdk/sdk.js';
11
- import type * as Protocol from '../../generated/protocol.js';
12
- import * as Feedback from '../../ui/components/panel_feedback/panel_feedback.js';
13
- import * as UI from '../../ui/legacy/legacy.js';
14
- import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
15
-
16
- import type {AccessibilitySidebarView} from './AccessibilitySidebarView.js';
17
- import {AccessibilitySubPane} from './AccessibilitySubPane.js';
18
- import axBreadcrumbsStyles from './axBreadcrumbs.css.js';
19
-
20
- const UIStrings = {
21
- /**
22
- * @description Text in AXBreadcrumbs Pane of the Accessibility panel
23
- */
24
- accessibilityTree: 'Accessibility Tree',
25
- /**
26
- * @description Text to scroll the displayed content into view
27
- */
28
- scrollIntoView: 'Scroll into view',
29
- /**
30
- * @description Ignored node element text content in AXBreadcrumbs Pane of the Accessibility panel
31
- */
32
- ignored: 'Ignored',
33
- /**
34
- * @description Name for experimental tree toggle.
35
- */
36
- fullTreeExperimentName: 'Enable full-page accessibility tree',
37
- /**
38
- * @description Description text for experimental tree toggle.
39
- */
40
- fullTreeExperimentDescription: 'The accessibility tree moved to the top right corner of the DOM tree.',
41
- /**
42
- * @description Message saying that DevTools must be restarted before the experiment is enabled.
43
- */
44
- reloadRequired: 'Reload required before the change takes effect',
45
- } as const;
46
- const str_ = i18n.i18n.registerUIStrings('panels/accessibility/AXBreadcrumbsPane.ts', UIStrings);
47
- const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
48
- export class AXBreadcrumbsPane extends AccessibilitySubPane {
49
- private readonly axSidebarView: AccessibilitySidebarView;
50
- private preselectedBreadcrumb: AXBreadcrumb|null;
51
- private inspectedNodeBreadcrumb: AXBreadcrumb|null;
52
- private collapsingBreadcrumbId: number;
53
- private hoveredBreadcrumb: AXBreadcrumb|null;
54
- private readonly rootElement: HTMLElement;
55
- #legacyTreeDisabled = false;
56
-
57
- constructor(axSidebarView: AccessibilitySidebarView) {
58
- super({
59
- title: i18nString(UIStrings.accessibilityTree),
60
- viewId: 'accessibility-tree',
61
- jslog: `${VisualLogging.section('accessibility-tree')}`,
62
- });
63
- this.registerRequiredCSS(axBreadcrumbsStyles);
64
-
65
- this.element.classList.add('ax-subpane');
66
- this.element.tabIndex = -1;
67
-
68
- this.axSidebarView = axSidebarView;
69
- this.preselectedBreadcrumb = null;
70
- this.inspectedNodeBreadcrumb = null;
71
-
72
- this.collapsingBreadcrumbId = -1;
73
-
74
- this.rootElement = this.element.createChild('div', 'ax-breadcrumbs');
75
-
76
- this.hoveredBreadcrumb = null;
77
- const previewToggle = new Feedback.PreviewToggle.PreviewToggle();
78
- previewToggle.setAttribute('jslog', `${VisualLogging.toggle('full-accessibility-tree')}`);
79
- const name = i18nString(UIStrings.fullTreeExperimentName);
80
- const experiment = Root.ExperimentNames.ExperimentName.FULL_ACCESSIBILITY_TREE;
81
- const onChangeCallback: (checked: boolean) => void = checked => {
82
- Host.userMetrics.experimentChanged(experiment, checked);
83
- UI.InspectorView.InspectorView.instance().displayReloadRequiredWarning(i18nString(UIStrings.reloadRequired));
84
- };
85
- if (Root.Runtime.experiments.isEnabled(experiment)) {
86
- this.#legacyTreeDisabled = true;
87
- const feedbackURL = 'https://g.co/devtools/a11y-tree-feedback';
88
- previewToggle.data = {
89
- name,
90
- helperText: i18nString(UIStrings.fullTreeExperimentDescription),
91
- feedbackURL,
92
- experiment,
93
- onChangeCallback,
94
- };
95
- this.element.appendChild(previewToggle);
96
- return;
97
- }
98
- previewToggle.data = {name, helperText: null, feedbackURL: null, experiment, onChangeCallback};
99
- this.element.prepend(previewToggle);
100
-
101
- UI.ARIAUtils.markAsTree(this.rootElement);
102
-
103
- this.rootElement.addEventListener('keydown', this.onKeyDown.bind(this), true);
104
- this.rootElement.addEventListener('mousemove', this.onMouseMove.bind(this), false);
105
- this.rootElement.addEventListener('mouseleave', this.onMouseLeave.bind(this), false);
106
- this.rootElement.addEventListener('click', this.onClick.bind(this), false);
107
- this.rootElement.addEventListener('contextmenu', this.contextMenuEventFired.bind(this), false);
108
- this.rootElement.addEventListener('focusout', this.onFocusOut.bind(this), false);
109
- }
110
-
111
- override focus(): void {
112
- if (this.inspectedNodeBreadcrumb) {
113
- this.inspectedNodeBreadcrumb.nodeElement().focus();
114
- } else {
115
- this.element.focus();
116
- }
117
- }
118
-
119
- override setAXNode(axNode: SDK.AccessibilityModel.AccessibilityNode|null): void {
120
- if (this.#legacyTreeDisabled) {
121
- return;
122
- }
123
- const hadFocus = this.element.hasFocus();
124
- super.setAXNode(axNode);
125
-
126
- this.rootElement.removeChildren();
127
-
128
- if (!axNode) {
129
- return;
130
- }
131
-
132
- const ancestorChain = [];
133
- let ancestor: (SDK.AccessibilityModel.AccessibilityNode|null)|SDK.AccessibilityModel.AccessibilityNode = axNode;
134
- while (ancestor) {
135
- ancestorChain.push(ancestor);
136
- ancestor = ancestor.parentNode();
137
- }
138
- ancestorChain.reverse();
139
-
140
- let depth = 0;
141
- let parent: AXBreadcrumb|null = null;
142
- this.inspectedNodeBreadcrumb = null;
143
- for (ancestor of ancestorChain) {
144
- if (ancestor !== axNode && ancestor.ignored() && ancestor.parentNode()) {
145
- continue;
146
- }
147
- const breadcrumb = new AXBreadcrumb(ancestor, depth, (ancestor === axNode));
148
- if (parent) {
149
- parent.appendChild(breadcrumb);
150
- } else {
151
- this.rootElement.appendChild(breadcrumb.element());
152
- }
153
- parent = breadcrumb;
154
- depth++;
155
- this.inspectedNodeBreadcrumb = breadcrumb;
156
- }
157
-
158
- if (this.inspectedNodeBreadcrumb) {
159
- this.inspectedNodeBreadcrumb.setPreselected(true, hadFocus);
160
- }
161
-
162
- this.setPreselectedBreadcrumb(this.inspectedNodeBreadcrumb);
163
-
164
- function append(
165
- parentBreadcrumb: AXBreadcrumb, axNode: SDK.AccessibilityModel.AccessibilityNode, localDepth: number): void {
166
- if (axNode.ignored()) {
167
- axNode.children().map(child => append(parentBreadcrumb, child, localDepth));
168
- return;
169
- }
170
- const childBreadcrumb = new AXBreadcrumb(axNode, localDepth, false);
171
- parentBreadcrumb.appendChild(childBreadcrumb);
172
-
173
- // In most cases there will be no children here, but there are some special cases.
174
- for (const child of axNode.children()) {
175
- append(childBreadcrumb, child, localDepth + 1);
176
- }
177
- }
178
-
179
- if (this.inspectedNodeBreadcrumb && !axNode.ignored()) {
180
- for (const child of axNode.children()) {
181
- append(this.inspectedNodeBreadcrumb, child, depth);
182
- if (child.backendDOMNodeId() === this.collapsingBreadcrumbId) {
183
- this.setPreselectedBreadcrumb(this.inspectedNodeBreadcrumb.lastChild());
184
- }
185
- }
186
- }
187
- this.collapsingBreadcrumbId = -1;
188
- }
189
-
190
- override willHide(): void {
191
- super.willHide();
192
- this.setPreselectedBreadcrumb(null);
193
- }
194
-
195
- private onKeyDown(event: Event): void {
196
- const preselectedBreadcrumb = this.preselectedBreadcrumb;
197
- if (!preselectedBreadcrumb) {
198
- return;
199
- }
200
- const keyboardEvent = event as KeyboardEvent;
201
- if (!keyboardEvent.composedPath().some(element => element === preselectedBreadcrumb.element())) {
202
- return;
203
- }
204
- if (keyboardEvent.shiftKey || keyboardEvent.metaKey || keyboardEvent.ctrlKey) {
205
- return;
206
- }
207
-
208
- let handled = false;
209
- if (keyboardEvent.key === 'ArrowUp' && !keyboardEvent.altKey) {
210
- handled = this.preselectPrevious();
211
- } else if ((keyboardEvent.key === 'ArrowDown') && !keyboardEvent.altKey) {
212
- handled = this.preselectNext();
213
- } else if (keyboardEvent.key === 'ArrowLeft' && !keyboardEvent.altKey) {
214
- if (preselectedBreadcrumb.hasExpandedChildren()) {
215
- this.collapseBreadcrumb(preselectedBreadcrumb);
216
- } else {
217
- handled = this.preselectParent();
218
- }
219
- } else if ((keyboardEvent.key === 'Enter' ||
220
- (keyboardEvent.key === 'ArrowRight' && !keyboardEvent.altKey &&
221
- preselectedBreadcrumb.axNode().hasOnlyUnloadedChildren()))) {
222
- handled = this.inspectDOMNode(preselectedBreadcrumb.axNode());
223
- }
224
-
225
- if (handled) {
226
- keyboardEvent.consume(true);
227
- }
228
- }
229
-
230
- private preselectPrevious(): boolean {
231
- if (!this.preselectedBreadcrumb) {
232
- return false;
233
- }
234
- const previousBreadcrumb = this.preselectedBreadcrumb.previousBreadcrumb();
235
- if (!previousBreadcrumb) {
236
- return false;
237
- }
238
- this.setPreselectedBreadcrumb(previousBreadcrumb);
239
- return true;
240
- }
241
-
242
- private preselectNext(): boolean {
243
- if (!this.preselectedBreadcrumb) {
244
- return false;
245
- }
246
- const nextBreadcrumb = this.preselectedBreadcrumb.nextBreadcrumb();
247
- if (!nextBreadcrumb) {
248
- return false;
249
- }
250
- this.setPreselectedBreadcrumb(nextBreadcrumb);
251
- return true;
252
- }
253
-
254
- private preselectParent(): boolean {
255
- if (!this.preselectedBreadcrumb) {
256
- return false;
257
- }
258
- const parentBreadcrumb = this.preselectedBreadcrumb.parentBreadcrumb();
259
- if (!parentBreadcrumb) {
260
- return false;
261
- }
262
- this.setPreselectedBreadcrumb(parentBreadcrumb);
263
- return true;
264
- }
265
-
266
- private setPreselectedBreadcrumb(breadcrumb: AXBreadcrumb|null): void {
267
- if (breadcrumb === this.preselectedBreadcrumb) {
268
- return;
269
- }
270
- const hadFocus = this.element.hasFocus();
271
- if (this.preselectedBreadcrumb) {
272
- this.preselectedBreadcrumb.setPreselected(false, hadFocus);
273
- }
274
-
275
- if (breadcrumb) {
276
- this.preselectedBreadcrumb = breadcrumb;
277
- } else {
278
- this.preselectedBreadcrumb = this.inspectedNodeBreadcrumb;
279
- }
280
- if (this.preselectedBreadcrumb) {
281
- this.preselectedBreadcrumb.setPreselected(true, hadFocus);
282
- }
283
- if (!breadcrumb && hadFocus) {
284
- SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight();
285
- }
286
- }
287
-
288
- private collapseBreadcrumb(breadcrumb: AXBreadcrumb): void {
289
- if (!breadcrumb.parentBreadcrumb()) {
290
- return;
291
- }
292
- const backendNodeId = breadcrumb.axNode().backendDOMNodeId();
293
- if (backendNodeId !== null) {
294
- this.collapsingBreadcrumbId = backendNodeId;
295
- }
296
- const parentBreadcrumb = breadcrumb.parentBreadcrumb();
297
- if (parentBreadcrumb) {
298
- this.inspectDOMNode(parentBreadcrumb.axNode());
299
- }
300
- }
301
-
302
- private onMouseLeave(_event: Event): void {
303
- this.setHoveredBreadcrumb(null);
304
- }
305
-
306
- private onMouseMove(event: Event): void {
307
- const target = event.target as Element | null;
308
- if (!target) {
309
- return;
310
- }
311
- const breadcrumbElement = target.enclosingNodeOrSelfWithClass('ax-breadcrumb');
312
- if (!breadcrumbElement) {
313
- this.setHoveredBreadcrumb(null);
314
- return;
315
- }
316
- const breadcrumb = elementsToAXBreadcrumb.get(breadcrumbElement);
317
- if (!breadcrumb?.isDOMNode()) {
318
- return;
319
- }
320
- this.setHoveredBreadcrumb(breadcrumb);
321
- }
322
-
323
- private onFocusOut(event: Event): void {
324
- if (!this.preselectedBreadcrumb || event.target !== this.preselectedBreadcrumb.nodeElement()) {
325
- return;
326
- }
327
- this.setPreselectedBreadcrumb(null);
328
- }
329
-
330
- private onClick(event: Event): void {
331
- const target = event.target as Element | null;
332
- if (!target) {
333
- return;
334
- }
335
- const breadcrumbElement = target.enclosingNodeOrSelfWithClass('ax-breadcrumb');
336
- if (!breadcrumbElement) {
337
- this.setHoveredBreadcrumb(null);
338
- return;
339
- }
340
- const breadcrumb = elementsToAXBreadcrumb.get(breadcrumbElement);
341
- if (!breadcrumb) {
342
- return;
343
- }
344
- if (breadcrumb.inspected()) {
345
- // This will collapse and preselect/focus the breadcrumb.
346
- this.collapseBreadcrumb(breadcrumb);
347
- breadcrumb.nodeElement().focus();
348
- void VisualLogging.logClick(breadcrumb.expandLoggable, event);
349
- return;
350
- }
351
- if (!breadcrumb.isDOMNode()) {
352
- return;
353
- }
354
- this.inspectDOMNode(breadcrumb.axNode());
355
- void VisualLogging.logClick(breadcrumb.expandLoggable, event);
356
- }
357
-
358
- private setHoveredBreadcrumb(breadcrumb: AXBreadcrumb|null): void {
359
- if (breadcrumb === this.hoveredBreadcrumb) {
360
- return;
361
- }
362
-
363
- if (this.hoveredBreadcrumb) {
364
- this.hoveredBreadcrumb.setHovered(false);
365
- }
366
- const node = this.node();
367
- if (breadcrumb) {
368
- breadcrumb.setHovered(true);
369
- } else if (node?.id) {
370
- // Highlight and scroll into view the currently inspected node.
371
- node.domModel().overlayModel().nodeHighlightRequested({nodeId: node.id});
372
- }
373
-
374
- this.hoveredBreadcrumb = breadcrumb;
375
- }
376
-
377
- private inspectDOMNode(axNode: SDK.AccessibilityModel.AccessibilityNode): boolean {
378
- if (!axNode.isDOMNode()) {
379
- return false;
380
- }
381
-
382
- const deferredNode = axNode.deferredDOMNode();
383
- if (deferredNode) {
384
- deferredNode.resolve(domNode => {
385
- this.axSidebarView.setNode(domNode, true /* fromAXTree */);
386
- void Common.Revealer.reveal(domNode, true /* omitFocus */);
387
- });
388
- }
389
-
390
- return true;
391
- }
392
-
393
- private contextMenuEventFired(event: Event): void {
394
- const target = event.target as Element | null;
395
- if (!target) {
396
- return;
397
- }
398
- const breadcrumbElement = target.enclosingNodeOrSelfWithClass('ax-breadcrumb');
399
- if (!breadcrumbElement) {
400
- return;
401
- }
402
-
403
- const breadcrumb = elementsToAXBreadcrumb.get(breadcrumbElement);
404
- if (!breadcrumb) {
405
- return;
406
- }
407
-
408
- const axNode = breadcrumb.axNode();
409
- if (!axNode.isDOMNode() || !axNode.deferredDOMNode()) {
410
- return;
411
- }
412
-
413
- const contextMenu = new UI.ContextMenu.ContextMenu(event);
414
- contextMenu.viewSection().appendItem(i18nString(UIStrings.scrollIntoView), () => {
415
- const deferredNode = axNode.deferredDOMNode();
416
- if (!deferredNode) {
417
- return;
418
- }
419
- void deferredNode.resolvePromise().then(domNode => {
420
- if (!domNode) {
421
- return;
422
- }
423
- void domNode.scrollIntoView();
424
- });
425
- }, {jslogContext: 'scroll-into-view'});
426
-
427
- const deferredNode = axNode.deferredDOMNode();
428
- if (deferredNode) {
429
- contextMenu.appendApplicableItems(deferredNode);
430
- }
431
- void contextMenu.show();
432
- }
433
- }
434
-
435
- const elementsToAXBreadcrumb = new WeakMap<Element, AXBreadcrumb>();
436
-
437
- export class AXBreadcrumb {
438
- readonly #axNode: SDK.AccessibilityModel.AccessibilityNode;
439
- readonly #element: HTMLDivElement;
440
- #nodeElement: HTMLDivElement;
441
- private readonly nodeWrapper: HTMLDivElement;
442
- private readonly selectionElement: HTMLDivElement;
443
- private readonly childrenGroupElement: HTMLDivElement;
444
- private readonly children: AXBreadcrumb[];
445
- private hovered: boolean;
446
- #preselected: boolean;
447
- private parent: AXBreadcrumb|null;
448
- #inspected: boolean;
449
- expandLoggable = {};
450
- constructor(axNode: SDK.AccessibilityModel.AccessibilityNode, depth: number, inspected: boolean) {
451
- this.#axNode = axNode;
452
-
453
- this.#element = document.createElement('div');
454
- this.#element.classList.add('ax-breadcrumb');
455
- this.#element.setAttribute('jslog', `${VisualLogging.treeItem().track({
456
- click: true,
457
- resize: true,
458
- keydown: 'ArrowUp|ArrowDown|ArrowLeft|ArrowRight|Enter'
459
- })}`);
460
- elementsToAXBreadcrumb.set(this.#element, this);
461
-
462
- this.#nodeElement = document.createElement('div');
463
- this.#nodeElement.classList.add('ax-node');
464
- UI.ARIAUtils.markAsTreeitem(this.#nodeElement);
465
- this.#nodeElement.tabIndex = -1;
466
- this.#element.appendChild(this.#nodeElement);
467
- this.nodeWrapper = document.createElement('div');
468
- this.nodeWrapper.classList.add('wrapper');
469
- this.#nodeElement.appendChild(this.nodeWrapper);
470
-
471
- this.selectionElement = document.createElement('div');
472
- this.selectionElement.classList.add('selection');
473
- this.selectionElement.classList.add('fill');
474
- this.#nodeElement.appendChild(this.selectionElement);
475
-
476
- this.childrenGroupElement = document.createElement('div');
477
- this.childrenGroupElement.classList.add('children');
478
- UI.ARIAUtils.markAsGroup(this.childrenGroupElement);
479
- this.#element.appendChild(this.childrenGroupElement);
480
-
481
- this.children = [];
482
- this.hovered = false;
483
- this.#preselected = false;
484
- this.parent = null;
485
-
486
- this.#inspected = inspected;
487
- this.#nodeElement.classList.toggle('inspected', inspected);
488
-
489
- this.#nodeElement.style.paddingLeft = (16 * depth + 4) + 'px';
490
-
491
- if (this.#axNode.ignored()) {
492
- this.appendIgnoredNodeElement();
493
- } else {
494
- this.appendRoleElement(this.#axNode.role());
495
- const axNodeName = this.#axNode.name();
496
- if (axNodeName?.value) {
497
- this.nodeWrapper.createChild('span', 'separator').textContent = '\xA0';
498
- this.appendNameElement(axNodeName.value as string);
499
- }
500
- }
501
-
502
- if (!this.#axNode.ignored() && this.#axNode.hasOnlyUnloadedChildren()) {
503
- this.#nodeElement.classList.add('children-unloaded');
504
- UI.ARIAUtils.setExpanded(this.#nodeElement, false);
505
- VisualLogging.registerLoggable(
506
- this.expandLoggable, `${VisualLogging.expand()}`, this.#element, new DOMRect(0, 0, 16, 16));
507
- }
508
-
509
- if (!this.#axNode.isDOMNode()) {
510
- this.#nodeElement.classList.add('no-dom-node');
511
- }
512
- }
513
-
514
- element(): HTMLElement {
515
- return this.#element;
516
- }
517
-
518
- nodeElement(): HTMLElement {
519
- return this.#nodeElement;
520
- }
521
-
522
- appendChild(breadcrumb: AXBreadcrumb): void {
523
- this.children.push(breadcrumb);
524
- breadcrumb.setParent(this);
525
- this.#nodeElement.classList.add('parent');
526
- UI.ARIAUtils.setExpanded(this.#nodeElement, true);
527
- this.childrenGroupElement.appendChild(breadcrumb.element());
528
- VisualLogging.registerLoggable(
529
- this.expandLoggable, `${VisualLogging.expand()}`, this.#element, new DOMRect(0, 0, 16, 16));
530
- }
531
-
532
- hasExpandedChildren(): number {
533
- return this.children.length;
534
- }
535
-
536
- setParent(breadcrumb: AXBreadcrumb): void {
537
- this.parent = breadcrumb;
538
- }
539
-
540
- preselected(): boolean {
541
- return this.#preselected;
542
- }
543
-
544
- setPreselected(preselected: boolean, selectedByUser: boolean): void {
545
- if (this.#preselected === preselected) {
546
- return;
547
- }
548
- this.#preselected = preselected;
549
- this.#nodeElement.classList.toggle('preselected', preselected);
550
- if (preselected) {
551
- this.#nodeElement.tabIndex = 0;
552
- } else {
553
- this.#nodeElement.tabIndex = -1;
554
- }
555
- if (this.#preselected) {
556
- if (selectedByUser) {
557
- this.#nodeElement.focus();
558
- }
559
- if (!this.#inspected) {
560
- this.#axNode.highlightDOMNode();
561
- } else {
562
- SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight();
563
- }
564
- }
565
- }
566
-
567
- setHovered(hovered: boolean): void {
568
- if (this.hovered === hovered) {
569
- return;
570
- }
571
- this.hovered = hovered;
572
- this.#nodeElement.classList.toggle('hovered', hovered);
573
- if (this.hovered) {
574
- this.#nodeElement.classList.toggle('hovered', true);
575
- this.#axNode.highlightDOMNode();
576
- }
577
- }
578
-
579
- axNode(): SDK.AccessibilityModel.AccessibilityNode {
580
- return this.#axNode;
581
- }
582
-
583
- inspected(): boolean {
584
- return this.#inspected;
585
- }
586
-
587
- isDOMNode(): boolean {
588
- return this.#axNode.isDOMNode();
589
- }
590
-
591
- nextBreadcrumb(): AXBreadcrumb|null {
592
- if (this.children.length) {
593
- return this.children[0];
594
- }
595
- const nextSibling = this.element().nextSibling;
596
- if (nextSibling) {
597
- return elementsToAXBreadcrumb.get(nextSibling as HTMLElement) || null;
598
- }
599
- return null;
600
- }
601
-
602
- previousBreadcrumb(): AXBreadcrumb|null {
603
- const previousSibling = this.element().previousSibling;
604
- if (previousSibling) {
605
- return elementsToAXBreadcrumb.get(previousSibling as HTMLElement) || null;
606
- }
607
-
608
- return this.parent;
609
- }
610
-
611
- parentBreadcrumb(): AXBreadcrumb|null {
612
- return this.parent;
613
- }
614
-
615
- lastChild(): AXBreadcrumb {
616
- return this.children[this.children.length - 1];
617
- }
618
-
619
- private appendNameElement(name: string): void {
620
- const nameElement = document.createElement('span');
621
- nameElement.textContent = '"' + name + '"';
622
- nameElement.classList.add('ax-readable-string');
623
- this.nodeWrapper.appendChild(nameElement);
624
- }
625
-
626
- private appendRoleElement(role: Protocol.Accessibility.AXValue|null): void {
627
- if (!role) {
628
- return;
629
- }
630
-
631
- const roleElement = document.createElement('span');
632
- roleElement.classList.add('monospace');
633
- roleElement.classList.add(RoleStyles[role.type]);
634
- roleElement.setTextContentTruncatedIfNeeded(role.value || '');
635
-
636
- this.nodeWrapper.appendChild(roleElement);
637
- }
638
-
639
- private appendIgnoredNodeElement(): void {
640
- const ignoredNodeElement = document.createElement('span');
641
- ignoredNodeElement.classList.add('monospace');
642
- ignoredNodeElement.textContent = i18nString(UIStrings.ignored);
643
- ignoredNodeElement.classList.add('ax-breadcrumbs-ignored-node');
644
- this.nodeWrapper.appendChild(ignoredNodeElement);
645
- }
646
- }
647
-
648
- type RoleStyles = Record<string, string>;
649
-
650
- export const RoleStyles: RoleStyles = {
651
- internalRole: 'ax-internal-role',
652
- role: 'ax-role',
653
- };