chrome-devtools-frontend 1.0.1660788 → 1.0.1662289

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 (177) hide show
  1. package/.agents/skills/evaluate-ai-css-completion/SKILL.md +143 -0
  2. package/.agents/skills/evaluate-ai-css-completion/scripts/evaluate.js +104 -0
  3. package/.agents/skills/migrate-chromium-test/SKILL.md +7 -2
  4. package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +7 -1
  5. package/docs/ui_engineering.md +75 -42
  6. package/eslint.config.mjs +7 -0
  7. package/extension-api/ExtensionAPI.d.ts +88 -0
  8. package/front_end/core/common/SettingRegistration.ts +0 -5
  9. package/front_end/core/host/InspectorFrontendHost.ts +1 -0
  10. package/front_end/core/host/InspectorFrontendHostStub.ts +2 -0
  11. package/front_end/core/platform/ArrayUtilities.ts +10 -0
  12. package/front_end/core/platform/StringUtilities.ts +20 -4
  13. package/front_end/core/sdk/CPUThrottlingManager.ts +2 -0
  14. package/front_end/core/sdk/DOMDebuggerModel.ts +2 -0
  15. package/front_end/core/sdk/DOMModel.ts +1 -0
  16. package/front_end/core/sdk/DebuggerModel.ts +4 -4
  17. package/front_end/core/sdk/EventBreakpointsModel.ts +2 -0
  18. package/front_end/core/sdk/FrameManager.ts +1 -0
  19. package/front_end/core/sdk/IsolateManager.ts +1 -0
  20. package/front_end/core/sdk/NetworkManager.ts +2 -0
  21. package/front_end/core/sdk/NetworkRequest.ts +1 -0
  22. package/front_end/core/sdk/PageResourceLoader.ts +2 -0
  23. package/front_end/core/sdk/SourceMap.ts +5 -5
  24. package/front_end/core/sdk/SourceMapManager.ts +3 -2
  25. package/front_end/core/sdk/TargetManager.ts +4 -0
  26. package/front_end/entrypoints/main/MainImpl.ts +2 -1
  27. package/front_end/foundation/README.md +86 -0
  28. package/front_end/generated/InspectorBackendCommands.ts +4 -5
  29. package/front_end/generated/protocol.ts +20 -38
  30. package/front_end/models/bindings/CompilerScriptMapping.ts +5 -5
  31. package/front_end/models/bindings/ContentProviderBasedProject.ts +2 -3
  32. package/front_end/models/bindings/DebuggerLanguagePlugins.ts +3 -3
  33. package/front_end/models/bindings/DefaultScriptMapping.ts +3 -3
  34. package/front_end/models/bindings/ResourceMapping.ts +3 -3
  35. package/front_end/models/bindings/ResourceScriptMapping.ts +2 -2
  36. package/front_end/models/bindings/SASSSourceMapping.ts +3 -3
  37. package/front_end/models/bindings/TempFile.ts +8 -3
  38. package/front_end/models/extensions/ExtensionAPI.ts +110 -46
  39. package/front_end/models/extensions/RecorderExtensionEndpoint.ts +7 -5
  40. package/front_end/models/formatter/ScriptFormatter.ts +8 -11
  41. package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +14 -5
  42. package/front_end/models/issues_manager/CheckFormsIssuesTrigger.ts +8 -9
  43. package/front_end/models/issues_manager/CookieIssue.ts +21 -9
  44. package/front_end/models/issues_manager/Issue.ts +3 -4
  45. package/front_end/models/issues_manager/IssueAggregator.ts +0 -9
  46. package/front_end/models/issues_manager/IssueResolver.ts +2 -2
  47. package/front_end/models/issues_manager/IssuesManager.ts +136 -137
  48. package/front_end/models/issues_manager/RelatedIssue.ts +10 -8
  49. package/front_end/models/issues_manager/issues_manager.ts +0 -2
  50. package/front_end/models/javascript_metadata/NativeFunctions.js +1 -1
  51. package/front_end/models/logs/RequestResolver.ts +2 -2
  52. package/front_end/models/source_map_scopes/FunctionCodeResolver.ts +12 -9
  53. package/front_end/models/trace/handlers/FramesHandler.ts +4 -7
  54. package/front_end/models/trace/handlers/ModelHandlers.ts +0 -1
  55. package/front_end/models/trace/handlers/RendererHandler.ts +2 -15
  56. package/front_end/models/trace/handlers/Threads.ts +4 -11
  57. package/front_end/models/trace/insights/DOMSize.ts +1 -1
  58. package/front_end/models/workspace_diff/WorkspaceDiff.ts +10 -4
  59. package/front_end/panels/ai_assistance/components/ChatMessage.ts +2 -1
  60. package/front_end/panels/application/ApplicationPanelSidebar.ts +0 -44
  61. package/front_end/panels/application/CookieItemsView.ts +1 -1
  62. package/front_end/panels/application/ServiceWorkersView.ts +494 -411
  63. package/front_end/panels/application/WebMCPView.ts +38 -43
  64. package/front_end/panels/application/application.ts +0 -6
  65. package/front_end/panels/application/components/AdsView.ts +201 -30
  66. package/front_end/panels/application/components/adsView.css +25 -0
  67. package/front_end/panels/application/components/components.ts +0 -2
  68. package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +1 -1
  69. package/front_end/panels/application/preloading/components/RuleSetDetailsView.ts +2 -2
  70. package/front_end/panels/application/serviceWorkersView.css +40 -4
  71. package/front_end/panels/browser_debugger/XHRBreakpointsSidebarPane.ts +147 -123
  72. package/front_end/panels/common/ExtensionServer.ts +3 -3
  73. package/front_end/panels/console/ConsoleView.ts +3 -2
  74. package/front_end/panels/console/PromptBuilder.ts +2 -1
  75. package/front_end/panels/emulation/DeviceModeView.ts +164 -113
  76. package/front_end/panels/issues/AffectedResourcesView.ts +1 -1
  77. package/front_end/panels/issues/IssueView.ts +0 -2
  78. package/front_end/panels/issues/IssuesPane.ts +1 -8
  79. package/front_end/panels/js_timeline/js_timeline-meta.ts +3 -2
  80. package/front_end/panels/lighthouse/LighthouseProtocolService.ts +53 -12
  81. package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorController.ts +3 -3
  82. package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorPane.ts +5 -5
  83. package/front_end/panels/linear_memory_inspector/components/LinearMemoryHighlightChipList.ts +4 -4
  84. package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +2 -2
  85. package/front_end/panels/linear_memory_inspector/components/LinearMemoryNavigator.ts +6 -6
  86. package/front_end/panels/linear_memory_inspector/components/LinearMemoryValueInterpreter.ts +3 -3
  87. package/front_end/panels/linear_memory_inspector/components/ValueInterpreterDisplay.ts +8 -9
  88. package/front_end/panels/linear_memory_inspector/components/ValueInterpreterDisplayUtils.ts +2 -2
  89. package/front_end/panels/linear_memory_inspector/components/ValueInterpreterSettings.ts +1 -1
  90. package/front_end/panels/linear_memory_inspector/linear_memory_inspector-meta.ts +2 -2
  91. package/front_end/panels/network/RequestPayloadView.ts +92 -52
  92. package/front_end/panels/network/RequestTimingView.ts +95 -127
  93. package/front_end/panels/network/components/ResponseHeaderSection.ts +5 -3
  94. package/front_end/panels/profiler/HeapSnapshotView.ts +3 -3
  95. package/front_end/panels/profiler/WritableProfileHeader.ts +2 -2
  96. package/front_end/panels/recorder/{components/ControlButton.ts → ControlButton.ts} +9 -10
  97. package/front_end/panels/recorder/{components/CreateRecordingView.ts → CreateRecordingView.ts} +48 -47
  98. package/front_end/panels/recorder/{components/ExtensionView.ts → ExtensionView.ts} +8 -8
  99. package/front_end/panels/recorder/RecorderController.ts +302 -127
  100. package/front_end/panels/recorder/RecorderPanel.ts +1 -1
  101. package/front_end/panels/recorder/{components/RecordingListView.ts → RecordingListView.ts} +19 -20
  102. package/front_end/panels/recorder/{components/RecordingView.ts → RecordingView.ts} +88 -88
  103. package/front_end/panels/recorder/{components/ReplaySection.ts → ReplaySection.ts} +11 -11
  104. package/front_end/panels/recorder/{components/SelectorPicker.ts → SelectorPicker.ts} +13 -13
  105. package/front_end/panels/recorder/{components/StepEditor.ts → StepEditor.ts} +15 -15
  106. package/front_end/panels/recorder/{components/StepView.ts → StepView.ts} +10 -10
  107. package/front_end/panels/recorder/{components/TimelineSection.ts → TimelineSection.ts} +2 -2
  108. package/front_end/panels/recorder/recorder.ts +23 -1
  109. package/front_end/panels/recorder/util/util.ts +113 -0
  110. package/front_end/panels/sources/SourcesView.ts +0 -17
  111. package/front_end/panels/sources/TabbedEditorContainer.ts +1 -1
  112. package/front_end/panels/sources/UISourceCodeFrame.ts +42 -0
  113. package/front_end/panels/sources/sources.ts +0 -2
  114. package/front_end/panels/timeline/CompatibilityTracksAppender.ts +0 -17
  115. package/front_end/panels/timeline/IsolateSelector.ts +10 -8
  116. package/front_end/panels/timeline/ThreadAppender.ts +0 -106
  117. package/front_end/panels/timeline/TimelinePanel.ts +18 -7
  118. package/front_end/panels/timeline/TimelineUIUtils.ts +144 -129
  119. package/front_end/panels/timeline/timeline-meta.ts +3 -2
  120. package/front_end/third_party/chromium/README.chromium +1 -1
  121. package/front_end/ui/components/report_view/ReportView.ts +11 -5
  122. package/front_end/ui/components/report_view/report.css +4 -1
  123. package/front_end/ui/legacy/TextPrompt.ts +49 -1
  124. package/front_end/ui/legacy/Treeoutline.ts +3 -0
  125. package/front_end/ui/legacy/UIUtils.ts +11 -1
  126. package/front_end/ui/legacy/Widget.ts +14 -15
  127. package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +2 -2
  128. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +11 -7
  129. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +2 -1
  130. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +10 -1
  131. package/front_end/ui/legacy/textPrompt.css +10 -0
  132. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  133. package/package.json +1 -1
  134. package/front_end/models/issues_manager/AttributionReportingIssue.ts +0 -247
  135. package/front_end/models/issues_manager/descriptions/arInsecureContext.md +0 -7
  136. package/front_end/models/issues_manager/descriptions/arInvalidInfoHeader.md +0 -5
  137. package/front_end/models/issues_manager/descriptions/arInvalidRegisterOsSourceHeader.md +0 -5
  138. package/front_end/models/issues_manager/descriptions/arInvalidRegisterOsTriggerHeader.md +0 -5
  139. package/front_end/models/issues_manager/descriptions/arInvalidRegisterSourceHeader.md +0 -5
  140. package/front_end/models/issues_manager/descriptions/arInvalidRegisterTriggerHeader.md +0 -5
  141. package/front_end/models/issues_manager/descriptions/arNavigationRegistrationUniqueScopeAlreadySet.md +0 -5
  142. package/front_end/models/issues_manager/descriptions/arNavigationRegistrationWithoutTransientUserActivation.md +0 -6
  143. package/front_end/models/issues_manager/descriptions/arNoRegisterOsSourceHeader.md +0 -5
  144. package/front_end/models/issues_manager/descriptions/arNoRegisterOsTriggerHeader.md +0 -5
  145. package/front_end/models/issues_manager/descriptions/arNoRegisterSourceHeader.md +0 -5
  146. package/front_end/models/issues_manager/descriptions/arNoRegisterTriggerHeader.md +0 -5
  147. package/front_end/models/issues_manager/descriptions/arNoWebOrOsSupport.md +0 -4
  148. package/front_end/models/issues_manager/descriptions/arOsSourceIgnored.md +0 -18
  149. package/front_end/models/issues_manager/descriptions/arOsTriggerIgnored.md +0 -19
  150. package/front_end/models/issues_manager/descriptions/arPermissionPolicyDisabled.md +0 -8
  151. package/front_end/models/issues_manager/descriptions/arSourceAndTriggerHeaders.md +0 -9
  152. package/front_end/models/issues_manager/descriptions/arSourceIgnored.md +0 -13
  153. package/front_end/models/issues_manager/descriptions/arTriggerIgnored.md +0 -12
  154. package/front_end/models/issues_manager/descriptions/arUntrustworthyReportingOrigin.md +0 -10
  155. package/front_end/models/issues_manager/descriptions/arWebAndOsHeaders.md +0 -11
  156. package/front_end/models/trace/handlers/AuctionWorkletsHandler.ts +0 -183
  157. package/front_end/panels/application/InterestGroupStorageModel.ts +0 -81
  158. package/front_end/panels/application/InterestGroupStorageView.ts +0 -151
  159. package/front_end/panels/application/InterestGroupTreeElement.ts +0 -65
  160. package/front_end/panels/application/components/InterestGroupAccessGrid.ts +0 -135
  161. package/front_end/panels/application/components/interestGroupAccessGrid.css +0 -27
  162. package/front_end/panels/application/interestGroupStorageView.css +0 -9
  163. package/front_end/panels/issues/AttributionReportingIssueDetailsView.ts +0 -182
  164. package/front_end/panels/recorder/components/components.ts +0 -25
  165. package/front_end/panels/recorder/components/util.ts +0 -116
  166. package/front_end/panels/sources/InplaceFormatterEditorAction.ts +0 -149
  167. /package/front_end/panels/recorder/{components/controlButton.css → controlButton.css} +0 -0
  168. /package/front_end/panels/recorder/{components/createRecordingView.css → createRecordingView.css} +0 -0
  169. /package/front_end/panels/recorder/{components/extensionView.css → extensionView.css} +0 -0
  170. /package/front_end/panels/recorder/{components/recordingListView.css → recordingListView.css} +0 -0
  171. /package/front_end/panels/recorder/{components/recordingView.css → recordingView.css} +0 -0
  172. /package/front_end/panels/recorder/{components/replaySection.css → replaySection.css} +0 -0
  173. /package/front_end/panels/recorder/{components/selectorPicker.css → selectorPicker.css} +0 -0
  174. /package/front_end/panels/recorder/{components/startView.css → startView.css} +0 -0
  175. /package/front_end/panels/recorder/{components/stepEditor.css → stepEditor.css} +0 -0
  176. /package/front_end/panels/recorder/{components/stepView.css → stepView.css} +0 -0
  177. /package/front_end/panels/recorder/{components/timelineSection.css → timelineSection.css} +0 -0
@@ -22,17 +22,36 @@ import * as UI from '../../ui/legacy/legacy.js';
22
22
  import * as Lit from '../../ui/lit/lit.js';
23
23
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
24
24
 
25
- import * as Components from './components/components.js';
26
- import type {AddBreakpointEvent, RemoveBreakpointEvent} from './components/StepView.js';
27
25
  import * as Converters from './converters/converters.js';
26
+ import {CreateRecordingView} from './CreateRecordingView.js';
28
27
  import * as Extensions from './extensions/extensions.js';
29
28
  import * as Models from './models/models.js';
30
29
  import * as Actions from './recorder-actions/recorder-actions.js';
31
30
  import recorderControllerStyles from './recorderController.css.js';
32
31
  import * as Events from './RecorderEvents.js';
33
-
34
- const {html, Decorators, Directives: {ref}, LitElement} = Lit;
35
- const {customElement, state} = Decorators;
32
+ import {
33
+ DeleteRecordingEvent,
34
+ OpenRecordingEvent,
35
+ PlayRecordingEvent as ListViewPlayRecordingEvent,
36
+ RecordingListView
37
+ } from './RecordingListView.js';
38
+ import {
39
+ type PlayRecordingEvent as ViewPlayRecordingEvent,
40
+ RecordingView,
41
+ type ReplayState,
42
+ TargetPanel
43
+ } from './RecordingView.js';
44
+ import type {RequestSelectorAttributeEvent} from './SelectorPicker.js';
45
+ import {
46
+ type AddBreakpointEvent,
47
+ type AddStep,
48
+ AddStepPosition,
49
+ type RemoveBreakpointEvent,
50
+ type RemoveStep,
51
+ type StepChanged
52
+ } from './StepView.js';
53
+
54
+ const {html, Directives: {ref}} = Lit;
36
55
 
37
56
  const UIStrings = {
38
57
  /**
@@ -157,12 +176,6 @@ const GET_EXTENSIONS_URL = 'https://goo.gle/recorder-extension-list' as Platform
157
176
  const RECORDER_EXPLANATION_URL = 'https://developer.chrome.com/docs/devtools/recorder';
158
177
  const FEEDBACK_URL = 'https://goo.gle/recorder-feedback' as Platform.DevToolsPath.UrlString;
159
178
 
160
- declare global {
161
- interface HTMLElementTagNameMap {
162
- 'devtools-recorder-controller': RecorderController;
163
- }
164
- }
165
-
166
179
  interface StoredRecording {
167
180
  storageName: string;
168
181
  flow: Models.Schema.UserFlow;
@@ -205,45 +218,209 @@ function verifyFlowSize(flow: Models.Schema.UserFlow): void {
205
218
  }
206
219
  }
207
220
 
208
- @customElement('devtools-recorder-controller')
209
- export class RecorderController extends LitElement {
210
- @state() declare private currentRecordingSession?: Models.RecordingSession.RecordingSession;
211
- @state() declare private currentRecording: StoredRecording|undefined;
212
- @state() declare private currentStep?: Models.Schema.Step;
213
- @state() declare private recordingError?: Error;
221
+ export class RecorderController extends UI.Widget.VBox<DocumentFragment> {
222
+ #currentRecordingSession?: Models.RecordingSession.RecordingSession;
223
+ get currentRecordingSession(): Models.RecordingSession.RecordingSession|undefined {
224
+ return this.#currentRecordingSession;
225
+ }
226
+ set currentRecordingSession(value: Models.RecordingSession.RecordingSession|undefined) {
227
+ if (this.#currentRecordingSession !== value) {
228
+ this.#currentRecordingSession = value;
229
+ this.requestUpdate();
230
+ }
231
+ }
232
+
233
+ #currentRecording: StoredRecording|undefined;
234
+ get currentRecording(): StoredRecording|undefined {
235
+ return this.#currentRecording;
236
+ }
237
+ set currentRecording(value: StoredRecording|undefined) {
238
+ if (this.#currentRecording !== value) {
239
+ this.#currentRecording = value;
240
+ this.requestUpdate();
241
+ }
242
+ }
243
+
244
+ #currentStep?: Models.Schema.Step;
245
+ get currentStep(): Models.Schema.Step|undefined {
246
+ return this.#currentStep;
247
+ }
248
+ set currentStep(value: Models.Schema.Step|undefined) {
249
+ if (this.#currentStep !== value) {
250
+ this.#currentStep = value;
251
+ this.requestUpdate();
252
+ }
253
+ }
254
+
255
+ #recordingError?: Error;
256
+ get recordingError(): Error|undefined {
257
+ return this.#recordingError;
258
+ }
259
+ set recordingError(value: Error|undefined) {
260
+ if (this.#recordingError !== value) {
261
+ this.#recordingError = value;
262
+ this.requestUpdate();
263
+ }
264
+ }
214
265
 
215
266
  #storage = Models.RecordingStorage.RecordingStorage.instance();
216
267
  #screenshotStorage = Models.ScreenshotStorage.ScreenshotStorage.instance();
217
268
 
218
- @state() declare private isRecording: boolean;
219
- @state() declare private isToggling: boolean;
269
+ #isRecording = false;
270
+ get isRecording(): boolean {
271
+ return this.#isRecording;
272
+ }
273
+ set isRecording(value: boolean) {
274
+ if (this.#isRecording !== value) {
275
+ this.#isRecording = value;
276
+ this.requestUpdate();
277
+ }
278
+ }
279
+
280
+ #isToggling = false;
281
+ get isToggling(): boolean {
282
+ return this.#isToggling;
283
+ }
284
+ set isToggling(value: boolean) {
285
+ if (this.#isToggling !== value) {
286
+ this.#isToggling = value;
287
+ this.requestUpdate();
288
+ }
289
+ }
220
290
 
221
291
  // TODO: we keep the functionality to allow/disallow replay but right now it's not used.
222
292
  // It can be used to decide if we allow replay on a certain target for example.
223
293
  #replayAllowed = true;
224
- @state() declare private recordingPlayer?: Models.RecordingPlayer.RecordingPlayer;
225
- @state() declare private lastReplayResult?: Models.RecordingPlayer.ReplayResult;
226
- readonly #replayState: Components.RecordingView.ReplayState = {isPlaying: false, isPausedOnBreakpoint: false};
227
294
 
228
- @state() declare private currentPage: Pages;
229
- @state() declare private previousPage?: Pages;
295
+ #recordingPlayer?: Models.RecordingPlayer.RecordingPlayer;
296
+ get recordingPlayer(): Models.RecordingPlayer.RecordingPlayer|undefined {
297
+ return this.#recordingPlayer;
298
+ }
299
+ set recordingPlayer(value: Models.RecordingPlayer.RecordingPlayer|undefined) {
300
+ if (this.#recordingPlayer !== value) {
301
+ this.#recordingPlayer = value;
302
+ this.requestUpdate();
303
+ }
304
+ }
305
+
306
+ #lastReplayResult?: Models.RecordingPlayer.ReplayResult;
307
+ get lastReplayResult(): Models.RecordingPlayer.ReplayResult|undefined {
308
+ return this.#lastReplayResult;
309
+ }
310
+ set lastReplayResult(value: Models.RecordingPlayer.ReplayResult|undefined) {
311
+ if (this.#lastReplayResult !== value) {
312
+ this.#lastReplayResult = value;
313
+ this.requestUpdate();
314
+ }
315
+ }
316
+
317
+ readonly #replayState: ReplayState = {isPlaying: false, isPausedOnBreakpoint: false};
318
+
319
+ #currentPage: Pages = Pages.START_PAGE;
320
+ get currentPage(): Pages {
321
+ return this.#currentPage;
322
+ }
323
+ set currentPage(value: Pages) {
324
+ if (this.#currentPage !== value) {
325
+ this.#currentPage = value;
326
+ this.requestUpdate();
327
+ }
328
+ }
329
+
330
+ #previousPage?: Pages;
331
+ get previousPage(): Pages|undefined {
332
+ return this.#previousPage;
333
+ }
334
+ set previousPage(value: Pages|undefined) {
335
+ if (this.#previousPage !== value) {
336
+ this.#previousPage = value;
337
+ this.requestUpdate();
338
+ }
339
+ }
340
+
230
341
  #fileSelector?: HTMLInputElement;
231
342
 
232
- @state() declare private sections?: Models.Section.Section[];
233
- @state() declare private settings?: Models.RecordingSettings.RecordingSettings;
343
+ #sections?: Models.Section.Section[];
344
+ get sections(): Models.Section.Section[]|undefined {
345
+ return this.#sections;
346
+ }
347
+ set sections(value: Models.Section.Section[]|undefined) {
348
+ if (this.#sections !== value) {
349
+ this.#sections = value;
350
+ this.requestUpdate();
351
+ }
352
+ }
234
353
 
235
- @state() declare private importError?: Error;
354
+ #settings?: Models.RecordingSettings.RecordingSettings;
355
+ get settings(): Models.RecordingSettings.RecordingSettings|undefined {
356
+ return this.#settings;
357
+ }
358
+ set settings(value: Models.RecordingSettings.RecordingSettings|undefined) {
359
+ if (this.#settings !== value) {
360
+ this.#settings = value;
361
+ this.requestUpdate();
362
+ }
363
+ }
364
+
365
+ #importError?: Error;
366
+ get importError(): Error|undefined {
367
+ return this.#importError;
368
+ }
369
+ set importError(value: Error|undefined) {
370
+ if (this.#importError !== value) {
371
+ this.#importError = value;
372
+ this.requestUpdate();
373
+ }
374
+ }
375
+
376
+ #exportMenuExpanded = false;
377
+ get exportMenuExpanded(): boolean {
378
+ return this.#exportMenuExpanded;
379
+ }
380
+ set exportMenuExpanded(value: boolean) {
381
+ if (this.#exportMenuExpanded !== value) {
382
+ this.#exportMenuExpanded = value;
383
+ this.requestUpdate();
384
+ }
385
+ }
236
386
 
237
- @state() declare private exportMenuExpanded: boolean;
238
387
  #exportMenuButton: Buttons.Button.Button|undefined;
239
388
 
240
389
  #stepBreakpointIndexes = new Set<number>();
241
390
 
242
391
  #builtInConverters: readonly Converters.Converter.Converter[];
243
- @state() declare private extensionConverters: Converters.Converter.Converter[];
244
- @state() declare private replayExtensions: Extensions.ExtensionManager.Extension[];
392
+ #extensionConverters: Converters.Converter.Converter[] = [];
393
+ get extensionConverters(): Converters.Converter.Converter[] {
394
+ return this.#extensionConverters;
395
+ }
396
+ set extensionConverters(value: Converters.Converter.Converter[]) {
397
+ if (this.#extensionConverters !== value) {
398
+ this.#extensionConverters = value;
399
+ this.requestUpdate();
400
+ }
401
+ }
245
402
 
246
- @state() declare private viewDescriptor?: PublicExtensions.RecorderPluginManager.ViewDescriptor;
403
+ #replayExtensions: Extensions.ExtensionManager.Extension[] = [];
404
+ get replayExtensions(): Extensions.ExtensionManager.Extension[] {
405
+ return this.#replayExtensions;
406
+ }
407
+ set replayExtensions(value: Extensions.ExtensionManager.Extension[]) {
408
+ if (this.#replayExtensions !== value) {
409
+ this.#replayExtensions = value;
410
+ this.requestUpdate();
411
+ }
412
+ }
413
+
414
+ #viewDescriptor?: PublicExtensions.RecorderPluginManager.ViewDescriptor;
415
+ get viewDescriptor(): PublicExtensions.RecorderPluginManager.ViewDescriptor|undefined {
416
+ return this.#viewDescriptor;
417
+ }
418
+ set viewDescriptor(value: PublicExtensions.RecorderPluginManager.ViewDescriptor|undefined) {
419
+ if (this.#viewDescriptor !== value) {
420
+ this.#viewDescriptor = value;
421
+ this.requestUpdate();
422
+ }
423
+ }
247
424
  #extensionViewShowRequestedListener?:
248
425
  (event: Common.EventTarget.EventTargetEvent<PublicExtensions.RecorderPluginManager.ViewDescriptor>) => void;
249
426
 
@@ -255,11 +432,12 @@ export class RecorderController extends LitElement {
255
432
  #selfXssWarningDisabledSetting = Common.Settings.Settings.instance().createSetting(
256
433
  'disable-self-xss-warning', false, Common.Settings.SettingStorageType.SYNCED);
257
434
 
258
- #recordingView?: Components.RecordingView.RecordingView;
259
- #createRecordingView?: Components.CreateRecordingView.CreateRecordingView;
435
+ #recordingView?: RecordingView;
436
+ #createRecordingView?: CreateRecordingView;
260
437
 
261
438
  constructor() {
262
- super();
439
+ const element = document.createElement('devtools-recorder-controller');
440
+ super(element, {useShadowDom: 'pure'});
263
441
 
264
442
  this.isRecording = false;
265
443
  this.isToggling = false;
@@ -286,11 +464,12 @@ export class RecorderController extends LitElement {
286
464
  });
287
465
 
288
466
  // used in e2e tests only.
289
- this.addEventListener('setrecording', (event: Event) => this.#onSetRecording(event));
467
+ /* eslint-disable-next-line @devtools/no-imperative-dom-api */
468
+ this.element.addEventListener('setrecording', (event: Event) => this.#onSetRecording(event));
290
469
  }
291
470
 
292
- override disconnectedCallback(): void {
293
- super.disconnectedCallback();
471
+ override onDetach(): void {
472
+ super.onDetach();
294
473
 
295
474
  if (this.currentRecordingSession) {
296
475
  void this.currentRecordingSession.stop();
@@ -316,7 +495,7 @@ export class RecorderController extends LitElement {
316
495
  this.isRecording = isRecording;
317
496
  }
318
497
 
319
- setRecordingStateForTesting(state: Components.RecordingView.ReplayState): void {
498
+ setRecordingStateForTesting(state: ReplayState): void {
320
499
  this.#replayState.isPlaying = state.isPlaying;
321
500
  this.#replayState.isPausedOnBreakpoint = state.isPausedOnBreakpoint;
322
501
  }
@@ -348,9 +527,8 @@ export class RecorderController extends LitElement {
348
527
 
349
528
  async #importFile(file: File): Promise<void> {
350
529
  const outputStream = new Common.StringOutputStream.StringOutputStream();
351
- const reader = new Bindings.FileUtils.ChunkedFileReader(
352
- file,
353
- /* chunkSize */ 10000000);
530
+ const reader = new Bindings.FileUtils.ChunkedFileReader(file,
531
+ /* chunkSize */ 10000000);
354
532
  const success = await reader.read(outputStream);
355
533
  if (!success) {
356
534
  throw reader.error() ?? new Error('Unknown');
@@ -426,9 +604,8 @@ export class RecorderController extends LitElement {
426
604
  }
427
605
  if (!settings.networkConditionsSettings && step.type === 'emulateNetworkConditions') {
428
606
  settings.networkConditionsSettings = {...step};
429
- for (const preset
430
- of [SDK.NetworkManager.OfflineConditions, SDK.NetworkManager.Slow3GConditions,
431
- SDK.NetworkManager.Slow4GConditions, SDK.NetworkManager.Fast4GConditions]) {
607
+ for (const preset of [SDK.NetworkManager.OfflineConditions, SDK.NetworkManager.Slow3GConditions,
608
+ SDK.NetworkManager.Slow4GConditions, SDK.NetworkManager.Fast4GConditions]) {
432
609
  // Using i18nTitleKey as a title here because we only want to compare the parameters of the network conditions.
433
610
  if (SDK.NetworkManager.networkConditionsEqual(
434
611
  {...preset, title: preset.i18nTitleKey || ''},
@@ -530,7 +707,7 @@ export class RecorderController extends LitElement {
530
707
  Host.userMetrics.recordingReplayStarted(Host.UserMetrics.RecordingReplayStarted.REPLAY_VIA_EXTENSION);
531
708
  }
532
709
 
533
- async #onPlayRecording(event: Components.RecordingView.PlayRecordingEvent): Promise<void> {
710
+ async #onPlayRecording(event: ViewPlayRecordingEvent): Promise<void> {
534
711
  if (!this.currentRecording || !this.#replayAllowed) {
535
712
  return;
536
713
  }
@@ -548,7 +725,7 @@ export class RecorderController extends LitElement {
548
725
  return await this.#onPlayViaExtension(event.extension);
549
726
  }
550
727
  Host.userMetrics.recordingReplayStarted(
551
- event.targetPanel !== Components.RecordingView.TargetPanel.DEFAULT ?
728
+ event.targetPanel !== TargetPanel.DEFAULT ?
552
729
  Host.UserMetrics.RecordingReplayStarted.REPLAY_WITH_PERFORMANCE_TRACING :
553
730
  Host.UserMetrics.RecordingReplayStarted.REPLAY_ONLY);
554
731
  this.#replayState.isPlaying = true;
@@ -563,7 +740,7 @@ export class RecorderController extends LitElement {
563
740
  this.recordingPlayer = new Models.RecordingPlayer.RecordingPlayer(
564
741
  this.currentRecording.flow, {speed: event.speed, breakpointIndexes: this.#stepBreakpointIndexes});
565
742
 
566
- const withPerformanceTrace = event.targetPanel === Components.RecordingView.TargetPanel.PERFORMANCE_PANEL;
743
+ const withPerformanceTrace = event.targetPanel === TargetPanel.PERFORMANCE_PANEL;
567
744
  const sectionsWithScreenshot = new Set();
568
745
  this.recordingPlayer.addEventListener(Models.RecordingPlayer.Events.STEP, async ({data: {step, resolve}}) => {
569
746
  this.currentStep = step;
@@ -605,7 +782,7 @@ export class RecorderController extends LitElement {
605
782
  Host.userMetrics.recordingReplayFinished(Host.UserMetrics.RecordingReplayFinished.OTHER_ERROR);
606
783
  }
607
784
  // Dispatch an event for e2e testing.
608
- this.dispatchEvent(new Events.ReplayFinishedEvent());
785
+ this.element.dispatchEvent(new Events.ReplayFinishedEvent());
609
786
  });
610
787
 
611
788
  this.recordingPlayer.addEventListener(Models.RecordingPlayer.Events.DONE, () => {
@@ -615,7 +792,7 @@ export class RecorderController extends LitElement {
615
792
  }
616
793
  this.lastReplayResult = Models.RecordingPlayer.ReplayResult.SUCCESS;
617
794
  // Dispatch an event for e2e testing.
618
- this.dispatchEvent(new Events.ReplayFinishedEvent());
795
+ this.element.dispatchEvent(new Events.ReplayFinishedEvent());
619
796
  Host.userMetrics.recordingReplayFinished(Host.UserMetrics.RecordingReplayFinished.SUCCESS);
620
797
  });
621
798
 
@@ -633,7 +810,7 @@ export class RecorderController extends LitElement {
633
810
 
634
811
  let performanceTracing = null;
635
812
  switch (event.targetPanel) {
636
- case Components.RecordingView.TargetPanel.PERFORMANCE_PANEL:
813
+ case TargetPanel.PERFORMANCE_PANEL:
637
814
  performanceTracing = new Tracing.PerformanceTracing.PerformanceTracing(this.#getMainTarget(), {
638
815
  tracingBufferUsage(): void{},
639
816
  eventsRetrievalProgress(): void{},
@@ -658,7 +835,7 @@ export class RecorderController extends LitElement {
658
835
  this.#replayState.isPlaying = false;
659
836
  this.recordingPlayer = undefined;
660
837
  await UI.InspectorView.InspectorView.instance().showPanel(event.targetPanel as string);
661
- if (event.targetPanel === Components.RecordingView.TargetPanel.PERFORMANCE_PANEL) {
838
+ if (event.targetPanel === TargetPanel.PERFORMANCE_PANEL) {
662
839
  // Note: this is not passing any metadata to the Performance panel.
663
840
  const trace = new SDK.TraceObject.TraceObject(events as Trace.Types.Events.Event[]);
664
841
  void Common.Revealer.reveal(trace);
@@ -690,7 +867,7 @@ export class RecorderController extends LitElement {
690
867
  this.#setCurrentRecording(await this.#storage.upsertRecording(Models.SchemaUtils.parse(json)));
691
868
  this.#setCurrentPage(Pages.RECORDING_PAGE);
692
869
  this.#clearError();
693
- this.dispatchEvent(new Events.SetRecordingFinishedEvent());
870
+ this.element.dispatchEvent(new Events.SetRecordingFinishedEvent());
694
871
  }
695
872
 
696
873
  // Used by e2e tests to inspect the current recording.
@@ -698,7 +875,7 @@ export class RecorderController extends LitElement {
698
875
  return this.currentRecording?.flow;
699
876
  }
700
877
 
701
- async #handleRecordingChanged(event: Components.StepView.StepChanged): Promise<void> {
878
+ async #handleRecordingChanged(event: StepChanged): Promise<void> {
702
879
  if (!this.currentRecording) {
703
880
  throw new Error('Current recording expected to be defined.');
704
881
  }
@@ -709,15 +886,14 @@ export class RecorderController extends LitElement {
709
886
  steps: this.currentRecording.flow.steps.map(step => step === event.currentStep ? event.newStep : step),
710
887
  },
711
888
  };
712
- this.#setCurrentRecording(
713
- await this.#storage.upsertRecording(
714
- recording.flow,
715
- recording.storageName,
716
- ),
717
- {keepBreakpoints: true, updateSession: true});
889
+ this.#setCurrentRecording(await this.#storage.upsertRecording(
890
+ recording.flow,
891
+ recording.storageName,
892
+ ),
893
+ {keepBreakpoints: true, updateSession: true});
718
894
  }
719
895
 
720
- async #handleStepAdded(event: Components.StepView.AddStep): Promise<void> {
896
+ async #handleStepAdded(event: AddStep): Promise<void> {
721
897
  if (!this.currentRecording) {
722
898
  throw new Error('Current recording expected to be defined.');
723
899
  }
@@ -730,13 +906,13 @@ export class RecorderController extends LitElement {
730
906
  if (sectionIdx === undefined || sectionIdx === -1) {
731
907
  throw new Error('There is no section to add a step to');
732
908
  }
733
- if (event.position === Components.StepView.AddStepPosition.AFTER) {
909
+ if (event.position === AddStepPosition.AFTER) {
734
910
  if (this.sections?.[sectionIdx].steps.length) {
735
911
  step = this.sections?.[sectionIdx].steps[0];
736
- position = Components.StepView.AddStepPosition.BEFORE;
912
+ position = AddStepPosition.BEFORE;
737
913
  } else {
738
914
  step = this.sections?.[sectionIdx].causingStep;
739
- position = Components.StepView.AddStepPosition.AFTER;
915
+ position = AddStepPosition.AFTER;
740
916
  }
741
917
  } else {
742
918
  if (sectionIdx <= 0) {
@@ -744,7 +920,7 @@ export class RecorderController extends LitElement {
744
920
  }
745
921
  const prevSection = this.sections?.[sectionIdx - 1];
746
922
  step = prevSection?.steps[prevSection.steps.length - 1];
747
- position = Components.StepView.AddStepPosition.AFTER;
923
+ position = AddStepPosition.AFTER;
748
924
  }
749
925
  } else {
750
926
  // step
@@ -755,7 +931,7 @@ export class RecorderController extends LitElement {
755
931
  }
756
932
  const steps = this.currentRecording.flow.steps;
757
933
  const currentIndex = steps.indexOf(step);
758
- const indexToInsertAt = currentIndex + (position === Components.StepView.AddStepPosition.BEFORE ? 0 : 1);
934
+ const indexToInsertAt = currentIndex + (position === AddStepPosition.BEFORE ? 0 : 1);
759
935
  steps.splice(indexToInsertAt, 0, {type: Models.Schema.StepType.WaitForElement, selectors: ['body']});
760
936
  const recording = {...this.currentRecording, flow: {...this.currentRecording.flow, steps}};
761
937
  this.#stepBreakpointIndexes = new Set([...this.#stepBreakpointIndexes.values()].map(breakpointIndex => {
@@ -765,12 +941,11 @@ export class RecorderController extends LitElement {
765
941
 
766
942
  return breakpointIndex + 1;
767
943
  }));
768
- this.#setCurrentRecording(
769
- await this.#storage.upsertRecording(
770
- recording.flow,
771
- recording.storageName,
772
- ),
773
- {keepBreakpoints: true, updateSession: true});
944
+ this.#setCurrentRecording(await this.#storage.upsertRecording(
945
+ recording.flow,
946
+ recording.storageName,
947
+ ),
948
+ {keepBreakpoints: true, updateSession: true});
774
949
  }
775
950
 
776
951
  async #handleRecordingTitleChanged(title: string): Promise<void> {
@@ -785,7 +960,7 @@ export class RecorderController extends LitElement {
785
960
  ));
786
961
  }
787
962
 
788
- async #handleStepRemoved(event: Components.StepView.RemoveStep): Promise<void> {
963
+ async #handleStepRemoved(event: RemoveStep): Promise<void> {
789
964
  if (!this.currentRecording) {
790
965
  throw new Error('Current recording expected to be defined.');
791
966
  }
@@ -807,12 +982,11 @@ export class RecorderController extends LitElement {
807
982
  return breakpointIndex - 1;
808
983
  })
809
984
  .filter(index => index >= 0));
810
- this.#setCurrentRecording(
811
- await this.#storage.upsertRecording(
812
- flow,
813
- this.currentRecording.storageName,
814
- ),
815
- {keepBreakpoints: true, updateSession: true});
985
+ this.#setCurrentRecording(await this.#storage.upsertRecording(
986
+ flow,
987
+ this.currentRecording.storageName,
988
+ ),
989
+ {keepBreakpoints: true, updateSession: true});
816
990
  }
817
991
 
818
992
  async #onNetworkConditionsChanged(data?: SDK.NetworkManager.Conditions): Promise<void> {
@@ -867,7 +1041,7 @@ export class RecorderController extends LitElement {
867
1041
 
868
1042
  async #onDeleteRecording(event: Event): Promise<void> {
869
1043
  event.stopPropagation();
870
- if (event instanceof Components.RecordingListView.DeleteRecordingEvent) {
1044
+ if (event instanceof DeleteRecordingEvent) {
871
1045
  await this.#storage.deleteRecording(event.storageName);
872
1046
  this.#screenshotStorage.deleteScreenshotsForRecording(event.storageName);
873
1047
  this.requestUpdate();
@@ -931,25 +1105,25 @@ export class RecorderController extends LitElement {
931
1105
  const screenshot = await screenshotPromise;
932
1106
  screenshotPromise = undefined;
933
1107
  currentSection.screenshot = screenshot;
934
- Models.ScreenshotStorage.ScreenshotStorage.instance().storeScreenshotForSection(
935
- currentRecording.storageName, currentSectionIndex, screenshot);
1108
+ Models.ScreenshotStorage.ScreenshotStorage.instance().storeScreenshotForSection(currentRecording.storageName,
1109
+ currentSectionIndex, screenshot);
936
1110
  previousSectionIndex = currentSectionIndex;
937
1111
  this.#updateScreenshotsForSections();
938
1112
  };
939
1113
 
940
- this.currentRecordingSession.addEventListener(
941
- Models.RecordingSession.Events.RECORDING_UPDATED, async ({data}: {data: Models.Schema.UserFlow}) => {
942
- if (!this.currentRecording) {
943
- throw new Error('No current recording found');
944
- }
945
- this.#setCurrentRecording(await this.#storage.upsertRecording(
946
- data,
947
- this.currentRecording.storageName,
948
- ));
949
- this.#recordingView?.scrollToBottom();
1114
+ this.currentRecordingSession.addEventListener(Models.RecordingSession.Events.RECORDING_UPDATED,
1115
+ async ({data}: {data: Models.Schema.UserFlow}) => {
1116
+ if (!this.currentRecording) {
1117
+ throw new Error('No current recording found');
1118
+ }
1119
+ this.#setCurrentRecording(await this.#storage.upsertRecording(
1120
+ data,
1121
+ this.currentRecording.storageName,
1122
+ ));
1123
+ this.#recordingView?.scrollToBottom();
950
1124
 
951
- await takeScreenshot(this.currentRecording);
952
- });
1125
+ await takeScreenshot(this.currentRecording);
1126
+ });
953
1127
 
954
1128
  this.currentRecordingSession.addEventListener(
955
1129
  Models.RecordingSession.Events.RECORDING_STOPPED, async ({data}: {data: Models.Schema.UserFlow}) => {
@@ -973,7 +1147,7 @@ export class RecorderController extends LitElement {
973
1147
  this.#setCurrentPage(Pages.RECORDING_PAGE);
974
1148
 
975
1149
  // Dispatch an event for e2e testing.
976
- this.dispatchEvent(new Events.RecordingStateChangedEvent((this.currentRecording as StoredRecording).flow));
1150
+ this.element.dispatchEvent(new Events.RecordingStateChangedEvent((this.currentRecording as StoredRecording).flow));
977
1151
  }
978
1152
 
979
1153
  async #onRecordingFinished(): Promise<void> {
@@ -996,7 +1170,7 @@ export class RecorderController extends LitElement {
996
1170
  this.isRecording = false;
997
1171
 
998
1172
  // Dispatch an event for e2e testing.
999
- this.dispatchEvent(new Events.RecordingStateChangedEvent(this.currentRecording.flow));
1173
+ this.element.dispatchEvent(new Events.RecordingStateChangedEvent(this.currentRecording.flow));
1000
1174
  }
1001
1175
 
1002
1176
  async onRecordingCancelled(): Promise<void> {
@@ -1006,8 +1180,7 @@ export class RecorderController extends LitElement {
1006
1180
  }
1007
1181
 
1008
1182
  async #onRecordingSelected(event: Event): Promise<void> {
1009
- const storageName = event instanceof Components.RecordingListView.OpenRecordingEvent ||
1010
- event instanceof Components.RecordingListView.PlayRecordingEvent ?
1183
+ const storageName = event instanceof OpenRecordingEvent || event instanceof ListViewPlayRecordingEvent ?
1011
1184
  event.storageName :
1012
1185
  ((event as InputEvent).target as HTMLSelectElement)?.value;
1013
1186
  this.#setCurrentRecording(await this.#storage.getRecording(storageName));
@@ -1071,12 +1244,11 @@ export class RecorderController extends LitElement {
1071
1244
  }
1072
1245
  const flow = this.currentRecordingSession.cloneUserFlow();
1073
1246
  flow.steps.push({type: 'waitForElement' as Models.Schema.StepType.WaitForElement, selectors: [['.cls']]});
1074
- this.#setCurrentRecording(
1075
- await this.#storage.upsertRecording(
1076
- flow,
1077
- this.currentRecording.storageName,
1078
- ),
1079
- {keepBreakpoints: true, updateSession: true});
1247
+ this.#setCurrentRecording(await this.#storage.upsertRecording(
1248
+ flow,
1249
+ this.currentRecording.storageName,
1250
+ ),
1251
+ {keepBreakpoints: true, updateSession: true});
1080
1252
  await this.updateComplete;
1081
1253
  // FIXME: call a method on the recording view widget.
1082
1254
  await this.#recordingView?.updateComplete;
@@ -1124,10 +1296,9 @@ export class RecorderController extends LitElement {
1124
1296
  }
1125
1297
  }
1126
1298
 
1127
- async #onPlayRecordingByName(event: Components.RecordingListView.PlayRecordingEvent): Promise<void> {
1299
+ async #onPlayRecordingByName(event: ListViewPlayRecordingEvent): Promise<void> {
1128
1300
  await this.#onRecordingSelected(event);
1129
- await this.#onPlayRecording(
1130
- {targetPanel: Components.RecordingView.TargetPanel.DEFAULT, speed: this.#recorderSettings.speed});
1301
+ await this.#onPlayRecording({targetPanel: TargetPanel.DEFAULT, speed: this.#recorderSettings.speed});
1131
1302
  }
1132
1303
 
1133
1304
  #onAddBreakpoint = (event: AddBreakpointEvent): void => {
@@ -1178,8 +1349,7 @@ export class RecorderController extends LitElement {
1178
1349
  return;
1179
1350
 
1180
1351
  case Actions.RecorderActions.REPLAY_RECORDING:
1181
- void this.#onPlayRecording(
1182
- {targetPanel: Components.RecordingView.TargetPanel.DEFAULT, speed: this.#recorderSettings.speed});
1352
+ void this.#onPlayRecording({targetPanel: TargetPanel.DEFAULT, speed: this.#recorderSettings.speed});
1183
1353
  return;
1184
1354
 
1185
1355
  case Actions.RecorderActions.TOGGLE_CODE_VIEW: {
@@ -1253,17 +1423,17 @@ export class RecorderController extends LitElement {
1253
1423
  // clang-format off
1254
1424
  return html`
1255
1425
  <devtools-widget
1256
- ${widget(Components.RecordingListView.RecordingListView, {
1426
+ ${widget(RecordingListView, {
1257
1427
  recordings: recordings.map(recording => ({
1258
1428
  storageName: recording.storageName,
1259
1429
  name: recording.flow.title,
1260
1430
  })),
1261
1431
  replayAllowed: this.#replayAllowed,
1262
1432
  })}
1263
- @createrecording=${this.#onCreateNewRecording}
1264
- @deleterecording=${this.#onDeleteRecording}
1265
- @openrecording=${this.#onRecordingSelected}
1266
- @playrecording=${this.#onPlayRecordingByName}
1433
+ @createrecording=${this.#onCreateNewRecording.bind(this)}
1434
+ @deleterecording=${this.#onDeleteRecording.bind(this)}
1435
+ @openrecording=${this.#onRecordingSelected.bind(this)}
1436
+ @playrecording=${this.#onPlayRecordingByName.bind(this)}
1267
1437
  >
1268
1438
  </devtools-widget>
1269
1439
  `;
@@ -1283,7 +1453,7 @@ export class RecorderController extends LitElement {
1283
1453
  jslogcontext="learn-more"
1284
1454
  >${i18nString(UIStrings.learnMore)}</devtools-link>
1285
1455
  </div>
1286
- <devtools-button .variant=${Buttons.Button.Variant.TONAL} jslogContext=${Actions.RecorderActions.CREATE_RECORDING} @click=${this.#onCreateNewRecording}>${i18nString(UIStrings.createRecording)}</devtools-button>
1456
+ <devtools-button .variant=${Buttons.Button.Variant.TONAL} jslogContext=${Actions.RecorderActions.CREATE_RECORDING} @click=${this.#onCreateNewRecording.bind(this)}>${i18nString(UIStrings.createRecording)}</devtools-button>
1287
1457
  </div>
1288
1458
  `;
1289
1459
  // clang-format on
@@ -1294,7 +1464,7 @@ export class RecorderController extends LitElement {
1294
1464
  return html`
1295
1465
  <devtools-widget
1296
1466
  class="recording-view"
1297
- ${widget(Components.RecordingView.RecordingView, {
1467
+ ${widget(RecordingView, {
1298
1468
  recording: this.currentRecording?.flow ?? {title: '', steps: []},
1299
1469
  replayState: this.#replayState,
1300
1470
  isRecording: this.isRecording,
@@ -1320,7 +1490,7 @@ export class RecorderController extends LitElement {
1320
1490
  titleChanged: this.#handleRecordingTitleChanged.bind(this),
1321
1491
  })}
1322
1492
  @requestselectorattribute=${(
1323
- event: Components.SelectorPicker.RequestSelectorAttributeEvent,
1493
+ event: RequestSelectorAttributeEvent,
1324
1494
  ) => {
1325
1495
  event.send(this.currentRecording?.flow.selectorAttribute);
1326
1496
  }}
@@ -1330,7 +1500,7 @@ export class RecorderController extends LitElement {
1330
1500
  @addbreakpoint=${this.#onAddBreakpoint.bind(this)}
1331
1501
  @removebreakpoint=${this.#onRemoveBreakpoint.bind(this)}
1332
1502
  @recorderextensionviewclosed=${this.#onExtensionViewClosed.bind(this)}
1333
- ${UI.Widget.widgetRef(Components.RecordingView.RecordingView, widget => {this.#recordingView = widget;})}
1503
+ ${UI.Widget.widgetRef(RecordingView, widget => {this.#recordingView = widget;})}
1334
1504
  ></devtools-widget>
1335
1505
  `;
1336
1506
  // clang-format on
@@ -1341,13 +1511,13 @@ export class RecorderController extends LitElement {
1341
1511
  return html`
1342
1512
  <devtools-widget
1343
1513
  class="recording-view"
1344
- ${widget(Components.CreateRecordingView.CreateRecordingView, {
1514
+ ${widget(CreateRecordingView, {
1345
1515
  recorderSettings: this.#recorderSettings,
1346
1516
  onRecordingStarted: this.#onRecordingStarted.bind(this),
1347
1517
  onRecordingCancelled: this.onRecordingCancelled.bind(this),
1348
1518
  })}
1349
1519
  ${UI.Widget.widgetRef(
1350
- Components.CreateRecordingView.CreateRecordingView,
1520
+ CreateRecordingView,
1351
1521
  widget => {
1352
1522
  this.#createRecordingView = widget;
1353
1523
  },
@@ -1374,7 +1544,12 @@ export class RecorderController extends LitElement {
1374
1544
  this.exportMenuExpanded = false;
1375
1545
  }
1376
1546
 
1377
- protected override render(): Lit.TemplateResult {
1547
+ override performUpdate(): void {
1548
+ // eslint-disable-next-line @devtools/no-lit-render-outside-of-view
1549
+ Lit.render(this.render(), this.contentElement);
1550
+ }
1551
+
1552
+ protected render(): Lit.TemplateResult {
1378
1553
  const recordings = this.#storage.getRecordings();
1379
1554
  const selectValue: string = this.currentRecording ? this.currentRecording.storageName : this.currentPage;
1380
1555
  // clang-format off
@@ -1403,7 +1578,7 @@ export class RecorderController extends LitElement {
1403
1578
  <div class="wrapper">
1404
1579
  <div class="header" jslog=${VisualLogging.toolbar()}>
1405
1580
  <devtools-button
1406
- @click=${this.#onCreateNewRecording}
1581
+ @click=${this.#onCreateNewRecording.bind(this)}
1407
1582
  .data=${
1408
1583
  {
1409
1584
  variant: Buttons.Button.Variant.TOOLBAR,
@@ -1429,7 +1604,7 @@ export class RecorderController extends LitElement {
1429
1604
  this.isToggling
1430
1605
  }
1431
1606
  @click=${(e: Event) => e.stopPropagation()}
1432
- @change=${this.#onRecordingSelected}
1607
+ @change=${this.#onRecordingSelected.bind(this)}
1433
1608
  jslog=${VisualLogging.dropDown('recordings').track({change: true})}
1434
1609
  >
1435
1610
  ${Lit.Directives.repeat(
@@ -1442,7 +1617,7 @@ export class RecorderController extends LitElement {
1442
1617
  </select>
1443
1618
  <div class="separator"></div>
1444
1619
  <devtools-button
1445
- @click=${this.#onImportRecording}
1620
+ @click=${this.#onImportRecording.bind(this)}
1446
1621
  .data=${
1447
1622
  {
1448
1623
  variant: Buttons.Button.Variant.TOOLBAR,
@@ -1454,7 +1629,7 @@ export class RecorderController extends LitElement {
1454
1629
  ></devtools-button>
1455
1630
  <devtools-button
1456
1631
  id='origin'
1457
- @click=${this.#onExportRecording}
1632
+ @click=${this.#onExportRecording.bind(this)}
1458
1633
  ${ref(el => {
1459
1634
  if (el instanceof HTMLElement) {
1460
1635
  this.#exportMenuButton = el as Buttons.Button.Button;
@@ -1471,8 +1646,8 @@ export class RecorderController extends LitElement {
1471
1646
  jslog=${VisualLogging.dropDown('export-recording').track({click: true})}
1472
1647
  ></devtools-button>
1473
1648
  <devtools-menu
1474
- @menucloserequest=${this.#onExportMenuClosed}
1475
- @menuitemselected=${this.#onExportOptionSelected}
1649
+ @menucloserequest=${this.#onExportMenuClosed.bind(this)}
1650
+ @menuitemselected=${this.#onExportOptionSelected.bind(this)}
1476
1651
  .origin=${this.#getExportMenuButton}
1477
1652
  .showDivider=${false}
1478
1653
  .showSelectedItem=${false}
@@ -1511,7 +1686,7 @@ export class RecorderController extends LitElement {
1511
1686
  </devtools-menu-group>
1512
1687
  </devtools-menu>
1513
1688
  <devtools-button
1514
- @click=${this.#onDeleteRecording}
1689
+ @click=${this.#onDeleteRecording.bind(this)}
1515
1690
  .data=${
1516
1691
  {
1517
1692
  variant: Buttons.Button.Variant.TOOLBAR,