chrome-devtools-frontend 1.0.1662289 → 1.0.1664496

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 (319) hide show
  1. package/.agents/skills/{creating-a-model → devtools-model-management}/SKILL.md +0 -1
  2. package/.agents/skills/devtools-unicode-escaping/SKILL.md +64 -0
  3. package/.agents/skills/devtools-ux-writing-refactor/SKILL.md +2 -1
  4. package/.agents/skills/fixing-skipped-tests/SKILL.md +3 -3
  5. package/.agents/skills/merging-devtools-module/SKILL.md +1 -1
  6. package/.agents/skills/migrate-chromium-test/SKILL.md +32 -6
  7. package/.agents/skills/repro-flaky-tests/SKILL.md +71 -31
  8. package/.agents/skills/ui-eng-vision-widget-promoter/SKILL.md +1 -0
  9. package/docs/ui_engineering.md +2 -0
  10. package/eslint.config.mjs +1 -0
  11. package/front_end/core/common/SettingRegistration.ts +0 -5
  12. package/front_end/core/common/Settings.ts +144 -3
  13. package/front_end/core/platform/StringUtilities.ts +38 -6
  14. package/front_end/core/protocol_client/PuppeteerDevToolsConnection.ts +112 -0
  15. package/front_end/core/sdk/CPUProfilerModel.ts +21 -13
  16. package/front_end/core/sdk/CSSContainerQuery.ts +1 -1
  17. package/front_end/core/sdk/CSSLayer.ts +1 -1
  18. package/front_end/core/sdk/CSSMedia.ts +1 -1
  19. package/front_end/core/sdk/CSSModel.ts +1 -1
  20. package/front_end/core/sdk/CSSNavigation.ts +1 -1
  21. package/front_end/core/sdk/CSSProperty.ts +1 -1
  22. package/front_end/core/sdk/CSSQuery.ts +1 -1
  23. package/front_end/core/sdk/CSSRule.ts +1 -1
  24. package/front_end/core/sdk/CSSScope.ts +1 -1
  25. package/front_end/core/sdk/CSSStartingStyle.ts +1 -1
  26. package/front_end/core/sdk/CSSStyleDeclaration.ts +1 -1
  27. package/front_end/core/sdk/CSSStyleSheetHeader.ts +1 -1
  28. package/front_end/core/sdk/CSSSupports.ts +1 -1
  29. package/front_end/core/sdk/CompilerSourceMappingContentProvider.ts +1 -1
  30. package/front_end/core/sdk/NetworkManager.ts +1 -1
  31. package/front_end/core/sdk/NetworkRequest.ts +7 -7
  32. package/front_end/core/sdk/Resource.ts +1 -1
  33. package/front_end/core/sdk/ScopeTreeCache.ts +1 -1
  34. package/front_end/core/sdk/Script.ts +1 -1
  35. package/front_end/core/sdk/ServerSentEvents.ts +1 -1
  36. package/front_end/core/sdk/ServiceWorkerCacheModel.ts +0 -10
  37. package/front_end/core/sdk/SourceMap.ts +1 -1
  38. package/front_end/core/sdk/SourceMapScopesInfo.ts +1 -1
  39. package/front_end/core/sdk/StorageBucketsModel.ts +0 -10
  40. package/front_end/core/sdk/sdk-meta.ts +3 -4
  41. package/front_end/{models → core}/text_utils/ContentProvider.ts +4 -6
  42. package/front_end/{models → core}/text_utils/StaticContentProvider.ts +4 -6
  43. package/front_end/{models → core}/text_utils/StreamingContentData.ts +1 -2
  44. package/front_end/{models → core}/text_utils/TextRange.ts +6 -3
  45. package/front_end/{models → core}/text_utils/TextUtils.ts +7 -7
  46. package/front_end/{models → core}/text_utils/WasmDisassembly.ts +2 -2
  47. package/front_end/core/text_utils/text_utils.ts +27 -0
  48. package/front_end/entrypoints/formatter_worker/AcornTokenizer.ts +1 -1
  49. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotLoader.ts +1 -1
  50. package/front_end/entrypoints/inspector_main/OutermostTargetSelector.ts +0 -13
  51. package/front_end/entrypoints/inspector_main/RenderingOptions.ts +8 -3
  52. package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +3 -3
  53. package/front_end/entrypoints/main/MainImpl.ts +21 -3
  54. package/front_end/foundation/Universe.ts +16 -0
  55. package/front_end/generated/InspectorBackendCommands.ts +2 -14
  56. package/front_end/generated/protocol-mapping.d.ts +0 -53
  57. package/front_end/generated/protocol-proxy-api.d.ts +0 -46
  58. package/front_end/generated/protocol.ts +0 -148
  59. package/front_end/models/ai_assistance/AgentProject.ts +1 -1
  60. package/front_end/models/ai_assistance/AiAgent2.ts +3 -3
  61. package/front_end/models/ai_assistance/AiConversation.ts +21 -10
  62. package/front_end/models/ai_assistance/AiHistoryStorage.ts +21 -10
  63. package/front_end/models/ai_assistance/ChangeManager.ts +2 -2
  64. package/front_end/models/ai_assistance/ExtensionScope.ts +6 -2
  65. package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +4 -7
  66. package/front_end/models/ai_assistance/agents/AiAgent.ts +9 -2
  67. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +19 -11
  68. package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +2 -2
  69. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +23 -10
  70. package/front_end/models/ai_assistance/agents/StorageAgent.ts +19 -18
  71. package/front_end/models/ai_assistance/agents/StylingAgent.ts +3 -4
  72. package/front_end/models/ai_assistance/contexts/FileContext.ts +7 -3
  73. package/front_end/models/ai_assistance/contexts/PerformanceTraceContext.ts +39 -11
  74. package/front_end/models/ai_assistance/data_formatters/FileFormatter.ts +6 -3
  75. package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +1 -1
  76. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +4 -4
  77. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +8 -8
  78. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +76 -3
  79. package/front_end/models/ai_assistance/tools/ListNetworkRequests.ts +11 -1
  80. package/front_end/models/badges/AiExplorerBadge.ts +8 -3
  81. package/front_end/models/badges/Badge.ts +1 -0
  82. package/front_end/models/badges/UserBadges.ts +43 -23
  83. package/front_end/models/bindings/CompilerScriptMapping.ts +1 -1
  84. package/front_end/models/bindings/ContentProviderBasedProject.ts +1 -1
  85. package/front_end/models/bindings/DebuggerLanguagePlugins.ts +2 -2
  86. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +1 -1
  87. package/front_end/models/bindings/DefaultScriptMapping.ts +1 -1
  88. package/front_end/models/bindings/FileUtils.ts +1 -1
  89. package/front_end/models/bindings/NetworkProject.ts +16 -4
  90. package/front_end/models/bindings/PresentationConsoleMessageHelper.ts +7 -10
  91. package/front_end/models/bindings/ResourceMapping.ts +1 -1
  92. package/front_end/models/bindings/ResourceScriptMapping.ts +1 -1
  93. package/front_end/models/bindings/SASSSourceMapping.ts +1 -1
  94. package/front_end/models/bindings/StylesSourceMapping.ts +1 -1
  95. package/front_end/models/breakpoints/BreakpointManager.ts +1 -1
  96. package/front_end/models/crux-manager/CrUXManager.ts +1 -1
  97. package/front_end/models/emulation/DeviceModeModel.ts +67 -5
  98. package/front_end/models/emulation/EmulatedDevices.ts +3 -2
  99. package/front_end/models/extensions/RecorderPluginManager.ts +10 -6
  100. package/front_end/models/har/Importer.ts +1 -1
  101. package/front_end/models/har/Log.snapshot.txt +193 -0
  102. package/front_end/models/har/Log.ts +3 -2
  103. package/front_end/models/har/Writer.ts +1 -1
  104. package/front_end/models/issues_manager/IssueAggregator.ts +9 -0
  105. package/front_end/models/issues_manager/IssuesManager.ts +5 -0
  106. package/front_end/models/issues_manager/LazyLoadImageIssue.ts +76 -0
  107. package/front_end/models/issues_manager/descriptions/lazyLoadImageZeroSize.md +7 -0
  108. package/front_end/models/issues_manager/issues_manager.ts +2 -0
  109. package/front_end/models/javascript_metadata/NativeFunctions.js +9 -10
  110. package/front_end/models/live-metrics/LiveMetrics.ts +2 -3
  111. package/front_end/models/logs/NetworkLog.ts +4 -3
  112. package/front_end/models/logs/logs-meta.ts +3 -3
  113. package/front_end/models/network_time_calculator/NetworkTimeCalculator.ts +4 -4
  114. package/front_end/models/persistence/Automapping.ts +1 -1
  115. package/front_end/models/persistence/AutomaticFileSystemWorkspaceBinding.ts +2 -2
  116. package/front_end/models/persistence/FileSystemWorkspaceBinding.ts +1 -1
  117. package/front_end/models/persistence/IsolatedFileSystem.ts +2 -2
  118. package/front_end/models/persistence/NetworkPersistenceManager.ts +1 -1
  119. package/front_end/models/persistence/PersistenceImpl.ts +1 -1
  120. package/front_end/models/persistence/PlatformFileSystem.ts +1 -1
  121. package/front_end/models/source_map_scopes/FunctionCodeResolver.ts +8 -6
  122. package/front_end/models/source_map_scopes/NamesResolver.ts +37 -31
  123. package/front_end/models/stack_trace/StackTrace.ts +17 -0
  124. package/front_end/models/text_utils/text_utils.ts +2 -24
  125. package/front_end/models/trace/insights/ImageDelivery.ts +2 -2
  126. package/front_end/models/trace/insights/LegacyJavaScript.ts +1 -1
  127. package/front_end/models/trace/insights/RenderBlocking.ts +1 -1
  128. package/front_end/models/trace/insights/ThirdParties.ts +1 -1
  129. package/front_end/models/workspace/FileManager.ts +1 -1
  130. package/front_end/models/workspace/UISourceCode.ts +1 -1
  131. package/front_end/models/workspace/WorkspaceImpl.ts +1 -1
  132. package/front_end/models/workspace_diff/WorkspaceDiff.ts +1 -1
  133. package/front_end/panels/accessibility/AccessibilityNodeView.ts +1 -1
  134. package/front_end/panels/accessibility/AccessibilityStrings.ts +2 -2
  135. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +1 -1
  136. package/front_end/panels/ai_assistance/ExportConversation.ts +1 -1
  137. package/front_end/panels/ai_assistance/ai_assistance-meta.ts +1 -1
  138. package/front_end/panels/ai_assistance/components/ChatMessage.ts +1 -1
  139. package/front_end/panels/application/AppManifestView.ts +4 -4
  140. package/front_end/panels/application/ApplicationPanelSidebar.ts +1 -2
  141. package/front_end/panels/application/CrashReportContextView.ts +1 -1
  142. package/front_end/panels/application/DOMStorageItemsView.ts +1 -1
  143. package/front_end/panels/application/DeviceBoundSessionsView.ts +4 -4
  144. package/front_end/panels/application/ExtensionStorageItemsView.ts +1 -1
  145. package/front_end/panels/application/FrameDetailsView.ts +1 -1
  146. package/front_end/panels/application/IndexedDBModel.ts +0 -10
  147. package/front_end/panels/application/IndexedDBViews.ts +240 -164
  148. package/front_end/panels/application/ServiceWorkerCacheTreeElement.ts +12 -2
  149. package/front_end/panels/application/ServiceWorkerCacheViews.ts +1 -1
  150. package/front_end/panels/application/SharedStorageModel.ts +0 -10
  151. package/front_end/panels/application/application.ts +2 -0
  152. package/front_end/panels/application/components/AdsView.ts +23 -0
  153. package/front_end/panels/application/components/BackForwardCacheView.ts +21 -5
  154. package/front_end/panels/application/components/CrashReportContextGrid.ts +1 -1
  155. package/front_end/panels/application/components/SharedStorageAccessGrid.ts +1 -1
  156. package/front_end/panels/application/components/TrustTokensView.ts +2 -2
  157. package/front_end/panels/application/components/adsView.css +21 -1
  158. package/front_end/panels/application/indexedDBViews.css +1 -1
  159. package/front_end/panels/application/preloading/PreloadingView.ts +1 -1
  160. package/front_end/panels/application/preloading/components/PreloadingDisabledInfobar.ts +2 -2
  161. package/front_end/panels/application/preloading/components/PreloadingString.ts +2 -2
  162. package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +4 -4
  163. package/front_end/panels/autofill/AutofillView.ts +1 -1
  164. package/front_end/panels/common/AiCodeCompletionTeaser.ts +1 -1
  165. package/front_end/panels/common/ExtensionServer.ts +1 -1
  166. package/front_end/panels/console/ConsoleFilter.ts +1 -1
  167. package/front_end/panels/console/ConsoleSidebar.ts +1 -1
  168. package/front_end/panels/console/ConsoleView.ts +1 -1
  169. package/front_end/panels/console/ConsoleViewMessage.ts +1 -1
  170. package/front_end/panels/console/PromptBuilder.ts +1 -1
  171. package/front_end/panels/coverage/CoverageDecorationManager.ts +9 -1
  172. package/front_end/panels/coverage/CoverageModel.ts +1 -1
  173. package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +1 -1
  174. package/front_end/panels/developer_resources/DeveloperResourcesListView.ts +1 -1
  175. package/front_end/panels/developer_resources/DeveloperResourcesView.ts +1 -1
  176. package/front_end/panels/elements/AccessibilityTreeView.ts +38 -3
  177. package/front_end/panels/elements/AdoptedStyleSheetTreeElement.ts +1 -1
  178. package/front_end/panels/elements/ElementIssueUtils.ts +2 -2
  179. package/front_end/panels/elements/ElementsTreeElement.ts +10 -3
  180. package/front_end/panels/elements/StandaloneStylesContainer.ts +1 -1
  181. package/front_end/panels/elements/StylePropertiesSection.ts +1 -1
  182. package/front_end/panels/elements/StylePropertyTreeElement.ts +1 -1
  183. package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +1 -1
  184. package/front_end/panels/elements/StylesContainer.ts +1 -1
  185. package/front_end/panels/elements/StylesSidebarPane.ts +1 -1
  186. package/front_end/panels/elements/components/CSSPropertyDocsView.ts +1 -1
  187. package/front_end/panels/explain/components/ConsoleInsight.ts +2 -2
  188. package/front_end/panels/issues/AffectedLazyLoadImagesView.ts +76 -0
  189. package/front_end/panels/issues/AffectedResourcesView.ts +1 -1
  190. package/front_end/panels/issues/CorsIssueDetailsView.ts +1 -1
  191. package/front_end/panels/issues/IssueView.ts +2 -0
  192. package/front_end/panels/issues/issues.ts +2 -0
  193. package/front_end/panels/layer_viewer/Layers3DView.ts +1 -1
  194. package/front_end/panels/lighthouse/LighthouseController.ts +5 -0
  195. package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +1 -1
  196. package/front_end/panels/network/BinaryResourceView.ts +1 -1
  197. package/front_end/panels/network/NetworkDataGridNode.ts +72 -8
  198. package/front_end/panels/network/NetworkLogView.ts +1 -1
  199. package/front_end/panels/network/NetworkLogViewColumns.ts +6 -6
  200. package/front_end/panels/network/NetworkPanel.ts +4 -4
  201. package/front_end/panels/network/NetworkSearchScope.ts +1 -1
  202. package/front_end/panels/network/RequestConditionsDrawer.ts +1 -1
  203. package/front_end/panels/network/RequestHTMLView.ts +1 -1
  204. package/front_end/panels/network/RequestInitiatorView.ts +24 -2
  205. package/front_end/panels/network/RequestPayloadView.ts +1 -1
  206. package/front_end/panels/network/RequestPreviewView.ts +1 -1
  207. package/front_end/panels/network/RequestResponseView.ts +1 -1
  208. package/front_end/panels/network/ResourceChunkView.ts +1 -1
  209. package/front_end/panels/network/ResourceDirectSocketChunkView.ts +1 -1
  210. package/front_end/panels/network/ResourceWebSocketFrameView.ts +1 -1
  211. package/front_end/panels/network/components/ResponseHeaderSection.ts +1 -1
  212. package/front_end/panels/network/forward/UIRequestLocation.ts +1 -1
  213. package/front_end/panels/network/network-meta.ts +3 -3
  214. package/front_end/panels/network/networkLogView.css +5 -0
  215. package/front_end/panels/network/requestInitiatorViewTree.css +5 -0
  216. package/front_end/panels/profiler/HeapProfileView.ts +200 -81
  217. package/front_end/panels/profiler/HeapSnapshotView.ts +1 -1
  218. package/front_end/panels/profiler/ProfileDataGrid.ts +12 -8
  219. package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +1 -1
  220. package/front_end/panels/recorder/README.md +1 -2
  221. package/front_end/panels/recorder/RecorderPanel.ts +1861 -17
  222. package/front_end/panels/recorder/RecordingListView.ts +8 -37
  223. package/front_end/panels/recorder/RecordingView.ts +54 -27
  224. package/front_end/panels/recorder/SelectorPicker.ts +0 -13
  225. package/front_end/panels/recorder/StepEditor.ts +6 -14
  226. package/front_end/panels/recorder/StepView.ts +36 -105
  227. package/front_end/panels/recorder/recorder.ts +0 -2
  228. package/front_end/panels/search/SearchResultsPane.ts +1 -1
  229. package/front_end/panels/security/SecurityPanel.ts +3 -3
  230. package/front_end/panels/settings/AISettingsTab.ts +17 -4
  231. package/front_end/panels/settings/components/SyncSection.ts +4 -4
  232. package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +3 -3
  233. package/front_end/panels/snippets/ScriptSnippetFileSystem.ts +1 -1
  234. package/front_end/panels/sources/BreakpointsView.ts +1 -1
  235. package/front_end/panels/sources/CoveragePlugin.ts +1 -1
  236. package/front_end/panels/sources/DebuggerPlugin.ts +4 -4
  237. package/front_end/panels/sources/FilteredUISourceCodeListProvider.ts +27 -3
  238. package/front_end/panels/sources/NavigatorView.ts +1 -1
  239. package/front_end/panels/sources/PersistenceActions.ts +1 -1
  240. package/front_end/panels/sources/SourcesNavigator.ts +1 -1
  241. package/front_end/panels/sources/SourcesSearchScope.ts +1 -1
  242. package/front_end/panels/sources/TabbedEditorContainer.ts +3 -3
  243. package/front_end/panels/sources/UISourceCodeFrame.ts +1 -1
  244. package/front_end/panels/sources/components/HeadersView.ts +1 -1
  245. package/front_end/panels/sources/filteredUISourceCodeListProvider.css +12 -1
  246. package/front_end/panels/sources/sources-meta.ts +1 -1
  247. package/front_end/panels/timeline/StatusDialog.ts +1 -1
  248. package/front_end/panels/timeline/TimelineController.ts +24 -3
  249. package/front_end/panels/timeline/TimelinePanel.ts +116 -25
  250. package/front_end/panels/timeline/TimelineSelectorStatsView.ts +2 -2
  251. package/front_end/panels/timeline/TimelineUIUtils.ts +1 -1
  252. package/front_end/panels/timeline/components/CWVMetrics.ts +1 -1
  253. package/front_end/panels/timeline/components/IgnoreListSetting.ts +1 -1
  254. package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +2 -2
  255. package/front_end/panels/timeline/timeline-meta.ts +13 -0
  256. package/front_end/services/tracing/TracingManager.ts +27 -2
  257. package/front_end/third_party/chromium/README.chromium +1 -1
  258. package/front_end/third_party/lighthouse/README.chromium +2 -2
  259. package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +1418 -1413
  260. package/front_end/third_party/lighthouse/locales/en-US.json +12 -6
  261. package/front_end/third_party/lighthouse/locales/en-XL.json +12 -6
  262. package/front_end/third_party/lighthouse/report-assets/report-generator.mjs +1 -1
  263. package/front_end/third_party/puppeteer/puppeteer.ts +20 -1
  264. package/front_end/ui/components/highlighting/HighlightElement.ts +4 -1
  265. package/front_end/ui/components/highlighting/HighlightManager.ts +1 -1
  266. package/front_end/ui/components/highlighting/MarkupHighlight.ts +1 -1
  267. package/front_end/ui/components/markdown_view/MarkdownView.ts +46 -2
  268. package/front_end/ui/components/markdown_view/markdownView.css +23 -0
  269. package/front_end/ui/components/spinners/Spinner.ts +29 -32
  270. package/front_end/ui/components/spinners/spinner.css +32 -84
  271. package/front_end/ui/components/text_editor/config.ts +1 -1
  272. package/front_end/ui/components/tree_outline/TreeOutline.ts +7 -1
  273. package/front_end/ui/legacy/Infobar.ts +1 -1
  274. package/front_end/ui/legacy/InspectorView.ts +12 -7
  275. package/front_end/ui/legacy/SuggestBox.ts +1 -1
  276. package/front_end/ui/legacy/TextPrompt.ts +1 -1
  277. package/front_end/ui/legacy/Toolbar.ts +5 -2
  278. package/front_end/ui/legacy/Treeoutline.ts +40 -13
  279. package/front_end/ui/legacy/UIUtils.ts +25 -10
  280. package/front_end/ui/legacy/Widget.ts +17 -10
  281. package/front_end/ui/legacy/components/color_picker/Spectrum.ts +1 -1
  282. package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +37 -8
  283. package/front_end/ui/legacy/components/data_grid/ViewportDataGrid.ts +1 -1
  284. package/front_end/ui/legacy/components/data_grid/dataGrid.css +1 -1
  285. package/front_end/ui/legacy/components/inline_editor/AnimationTimingUI.ts +27 -13
  286. package/front_end/ui/legacy/components/inline_editor/BezierEditor.ts +5 -2
  287. package/front_end/ui/legacy/components/inline_editor/CSSLinearEasingModel.ts +23 -0
  288. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +223 -121
  289. package/front_end/ui/legacy/components/object_ui/RemoteObjectPreviewFormatter.ts +1 -1
  290. package/front_end/ui/legacy/components/object_ui/objectValue.css +2 -1
  291. package/front_end/ui/legacy/components/quick_open/FilteredListWidget.ts +1 -1
  292. package/front_end/ui/legacy/components/source_frame/BinaryResourceViewFactory.ts +1 -1
  293. package/front_end/ui/legacy/components/source_frame/FontView.ts +1 -1
  294. package/front_end/ui/legacy/components/source_frame/ImageView.ts +1 -1
  295. package/front_end/ui/legacy/components/source_frame/JSONView.ts +105 -115
  296. package/front_end/ui/legacy/components/source_frame/PreviewFactory.ts +1 -1
  297. package/front_end/ui/legacy/components/source_frame/ResourceSourceFrame.ts +1 -1
  298. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +3 -3
  299. package/front_end/ui/legacy/components/source_frame/StreamingContentHexView.ts +1 -1
  300. package/front_end/ui/legacy/components/source_frame/XMLView.ts +5 -1
  301. package/front_end/ui/legacy/components/source_frame/jsonView.css +4 -0
  302. package/front_end/ui/legacy/components/utils/Linkifier.ts +1 -1
  303. package/front_end/ui/legacy/inspectorCommon.css +10 -6
  304. package/front_end/ui/lit/lit.ts +1 -0
  305. package/front_end/ui/lit/render.ts +44 -10
  306. package/front_end/ui/lit/strip-whitespace.ts +23 -2
  307. package/front_end/ui/settings/SettingUIRegistration.ts +105 -0
  308. package/front_end/ui/settings/settings.ts +9 -0
  309. package/front_end/ui/visual_logging/KnownContextValues.ts +13 -0
  310. package/mcp/mcp.ts +1 -0
  311. package/package.json +1 -1
  312. package/front_end/panels/recorder/RecorderController.ts +0 -1759
  313. /package/.agents/skills/{verification → devtools-verification}/SKILL.md +0 -0
  314. /package/front_end/{models → core}/text_utils/CodeMirrorUtils.ts +0 -0
  315. /package/front_end/{models → core}/text_utils/ContentData.ts +0 -0
  316. /package/front_end/{models → core}/text_utils/Text.ts +0 -0
  317. /package/front_end/{models → core}/text_utils/TextCursor.ts +0 -0
  318. /package/front_end/{models → core}/text_utils/TextUtils.snapshot.txt +0 -0
  319. /package/front_end/panels/recorder/{recorderController.css → recorderPanel.css} +0 -0
@@ -11,7 +11,7 @@ import * as Root from '../../core/root/root.js';
11
11
  import * as Buttons from '../../ui/components/buttons/buttons.js';
12
12
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
13
13
  import {createIcon} from '../kit/kit.js';
14
- import type {TemplateResult} from '../lit/lit.js';
14
+ import {nothing, render, type TemplateResult} from '../lit/lit.js';
15
15
 
16
16
  import {type Action, Events as ActionEvents} from './ActionRegistration.js';
17
17
  import {ActionRegistry} from './ActionRegistry.js';
@@ -412,10 +412,13 @@ export class Toolbar extends HTMLElement {
412
412
  const widget = Widget.get(item.element);
413
413
  if (widget) {
414
414
  widget.detach();
415
+ } else {
416
+ item.element.remove();
415
417
  }
416
418
  }
417
419
  this.items = [];
418
- this.removeChildren();
420
+ // eslint-disable-next-line @devtools/no-lit-render-outside-of-view
421
+ render(nothing, this);
419
422
  }
420
423
 
421
424
  hideSeparatorDupes(): void {
@@ -37,7 +37,7 @@
37
37
  import * as Common from '../../core/common/common.js';
38
38
  import * as Platform from '../../core/platform/platform.js';
39
39
  import * as SDK from '../../core/sdk/sdk.js';
40
- import type * as TextUtils from '../../models/text_utils/text_utils.js';
40
+ import type * as TextUtils from '../../core/text_utils/text_utils.js';
41
41
  import type * as Buttons from '../components/buttons/buttons.js';
42
42
  import * as Highlighting from '../components/highlighting/highlighting.js';
43
43
  import type {Icon} from '../kit/kit.js';
@@ -1427,8 +1427,8 @@ function hasBooleanAttribute(element: Element, name: string): boolean {
1427
1427
  return element.hasAttribute(name) && element.getAttribute(name) !== 'false';
1428
1428
  }
1429
1429
 
1430
- interface TreeNode<NodeT> {
1431
- children(): NodeT[];
1430
+ export interface TreeNode<NodeT> {
1431
+ treeNodeChildren(): Iterable<NodeT>;
1432
1432
  }
1433
1433
 
1434
1434
  export interface TreeSearchResult<NodeT> {
@@ -1438,17 +1438,23 @@ export interface TreeSearchResult<NodeT> {
1438
1438
  }
1439
1439
 
1440
1440
  export class TreeSearch < NodeT extends TreeNode<NodeT>,
1441
- SearchResultT extends TreeSearchResult<NodeT >= TreeSearchResult<NodeT>> {
1441
+ SearchResultT extends TreeSearchResult<NodeT >= TreeSearchResult<NodeT>> extends
1442
+ Common.ObjectWrapper.ObjectWrapper<TreeSearch.EventTypes> {
1442
1443
  #matches: SearchResultT[] = [];
1443
1444
  #currentMatchIndex = 0;
1444
1445
  #nodeMatchMap: WeakMap<NodeT, SearchResultT[]>|undefined;
1445
1446
 
1446
- reset(): void {
1447
+ #reset(): void {
1447
1448
  this.#matches = [];
1448
1449
  this.#nodeMatchMap = undefined;
1449
1450
  this.#currentMatchIndex = 0;
1450
1451
  }
1451
1452
 
1453
+ reset(): void {
1454
+ this.#reset();
1455
+ this.dispatchEventToListeners(TreeSearch.Events.SEARCH_CHANGED);
1456
+ }
1457
+
1452
1458
  currentMatch(): SearchResultT|undefined {
1453
1459
  return this.#matches.at(this.#currentMatchIndex);
1454
1460
  }
@@ -1497,11 +1503,13 @@ export class TreeSearch < NodeT extends TreeNode<NodeT>,
1497
1503
 
1498
1504
  next(): SearchResultT|undefined {
1499
1505
  this.#currentMatchIndex = Platform.NumberUtilities.mod(this.#currentMatchIndex + 1, this.#matches.length);
1506
+ this.dispatchEventToListeners(TreeSearch.Events.SEARCH_CHANGED);
1500
1507
  return this.currentMatch();
1501
1508
  }
1502
1509
 
1503
1510
  prev(): SearchResultT|undefined {
1504
1511
  this.#currentMatchIndex = Platform.NumberUtilities.mod(this.#currentMatchIndex - 1, this.#matches.length);
1512
+ this.dispatchEventToListeners(TreeSearch.Events.SEARCH_CHANGED);
1505
1513
  return this.currentMatch();
1506
1514
  }
1507
1515
 
@@ -1529,7 +1537,7 @@ export class TreeSearch < NodeT extends TreeNode<NodeT>,
1529
1537
  this.#matches.push(...preOrderMatches);
1530
1538
  updateCurrentMatchIndex(/* isPostOrder=*/ false);
1531
1539
  yield* preOrderMatches.values();
1532
- for (const child of node.children()) {
1540
+ for (const child of node.treeNodeChildren()) {
1533
1541
  yield* this.#innerSearch(child, currentMatch, jumpBackwards, match);
1534
1542
  }
1535
1543
  const postOrderMatches = match(node, /* isPostOrder=*/ true);
@@ -1540,16 +1548,27 @@ export class TreeSearch < NodeT extends TreeNode<NodeT>,
1540
1548
 
1541
1549
  search(node: NodeT, jumpBackwards: boolean, match: (node: NodeT, isPostOrder: boolean) => SearchResultT[]): number {
1542
1550
  const currentMatch = this.currentMatch();
1543
- this.reset();
1551
+ this.#reset();
1544
1552
  // eslint-disable-next-line @typescript-eslint/naming-convention,@typescript-eslint/no-unused-vars
1545
1553
  for (const _ of this.#innerSearch(node, currentMatch, jumpBackwards, match)) {
1546
1554
  // run the generator
1547
1555
  }
1548
1556
  this.#currentMatchIndex = Platform.NumberUtilities.mod(this.#currentMatchIndex, this.#matches.length);
1557
+ this.dispatchEventToListeners(TreeSearch.Events.SEARCH_CHANGED);
1549
1558
  return this.#matches.length;
1550
1559
  }
1551
1560
  }
1552
1561
 
1562
+ export namespace TreeSearch {
1563
+ export const enum Events {
1564
+ SEARCH_CHANGED = 'SearchChanged',
1565
+ }
1566
+
1567
+ export interface EventTypes {
1568
+ [Events.SEARCH_CHANGED]: void;
1569
+ }
1570
+ }
1571
+
1553
1572
  class TreeViewTreeElement extends TreeElement {
1554
1573
  static readonly CLONED_ATTRIBUTES = SDK.DOMModel.ARIA_ATTRIBUTES.union(new Set(['jslog']));
1555
1574
  #clonedAttributes = new Set<string>();
@@ -1864,7 +1883,7 @@ export class TreeViewElement extends HTMLElementWithLightDOMTemplate {
1864
1883
  }
1865
1884
  }
1866
1885
 
1867
- protected override addNodes(nodes: NodeList|Node[], nextSibling?: Node|null): void {
1886
+ protected override addNodes(nodes: NodeList|Node[]): void {
1868
1887
  for (const node of getTreeNodes(nodes)) {
1869
1888
  if (TreeViewTreeElement.get(node)) {
1870
1889
  continue; // Not sure this can happen
@@ -1876,10 +1895,18 @@ export class TreeViewElement extends HTMLElementWithLightDOMTemplate {
1876
1895
  if (parent.treeElement.childCount() === 0) {
1877
1896
  parent.treeElement.childrenListElement.classList.add(...parent.classes.values());
1878
1897
  }
1879
- while (nextSibling && nextSibling.nodeType !== Node.ELEMENT_NODE) {
1880
- nextSibling = nextSibling.nextSibling;
1898
+ let nextElement: TreeElement|null = null;
1899
+ for (let e: Element|null = node.nextElementSibling; e; e = e.nextElementSibling) {
1900
+ const nextTreeEl = TreeViewTreeElement.get(e);
1901
+ if (nextTreeEl) {
1902
+ nextElement = nextTreeEl;
1903
+ break;
1904
+ }
1905
+ if (e instanceof TreeElementWrapper && e.treeElement && e.treeElement.parent === parent.treeElement) {
1906
+ nextElement = e.treeElement;
1907
+ break;
1908
+ }
1881
1909
  }
1882
- const nextElement = nextSibling ? TreeViewTreeElement.get(nextSibling) : null;
1883
1910
  const index = nextElement ? parent.treeElement.indexOfChild(nextElement) : parent.treeElement.children().length;
1884
1911
  let treeElement;
1885
1912
  if (node instanceof HTMLLIElement) {
@@ -1906,12 +1933,12 @@ export class TreeViewElement extends HTMLElementWithLightDOMTemplate {
1906
1933
  }
1907
1934
  }
1908
1935
  }
1909
- for (const element of getStyleElements(nodes)) {
1936
+ for (const element of new Set(getStyleElements(nodes))) {
1910
1937
  this.#treeOutline.shadowRoot.appendChild(element.cloneNode(true));
1911
1938
  }
1912
1939
  }
1913
1940
 
1914
- protected override removeNodes(nodes: NodeList): void {
1941
+ protected override removeNodes(nodes: NodeList|Node[]): void {
1915
1942
  for (const node of getTreeNodes(nodes)) {
1916
1943
  if (node instanceof HTMLLIElement) {
1917
1944
  TreeViewTreeElement.get(node)?.remove();
@@ -2124,10 +2124,6 @@ export class HTMLElementWithLightDOMTemplate extends HTMLElement {
2124
2124
  value['_$litType$'] === 1);
2125
2125
  }
2126
2126
 
2127
- function isLitDirective(value: unknown): value is {values: unknown[]} {
2128
- return Boolean(typeof value === 'object' && value && '_$litDirective$' in value && 'values' in value);
2129
- }
2130
-
2131
2127
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2132
2128
  function isCallable(value: unknown): value is(...args: any[]) => any {
2133
2129
  // Native class constructors cannot be invoked without 'new', and we shouldn't attempt to wrap them.
@@ -2148,7 +2144,7 @@ export class HTMLElementWithLightDOMTemplate extends HTMLElement {
2148
2144
  HTMLElementWithLightDOMTemplate.patchLitTemplate(value);
2149
2145
  return value;
2150
2146
  }
2151
- if (isLitDirective(value)) {
2147
+ if (Lit.isLitDirective(value)) {
2152
2148
  for (let i = 0; i < value.values.length; i++) {
2153
2149
  const subvalue = value.values[i];
2154
2150
  if (isCallable(subvalue)) {
@@ -2186,9 +2182,28 @@ export class HTMLElementWithLightDOMTemplate extends HTMLElement {
2186
2182
 
2187
2183
  #onChange(mutationList: MutationRecord[]): void {
2188
2184
  this.onChange(mutationList);
2189
- for (const mutation of mutationList) {
2190
- this.removeNodes(mutation.removedNodes);
2191
- this.addNodes(mutation.addedNodes, mutation.nextSibling);
2185
+ const addedNodes = new Set<Node>();
2186
+ const removedNodes = new Set<Node>();
2187
+ for (let i = 0; i < mutationList.length; i++) {
2188
+ const mutation = mutationList[i];
2189
+ for (const node of mutation.addedNodes) {
2190
+ addedNodes.add(node);
2191
+ }
2192
+ for (const node of mutation.removedNodes) {
2193
+ removedNodes.add(node);
2194
+ }
2195
+ }
2196
+ if (removedNodes.size > 0) {
2197
+ this.removeNodes([...removedNodes]);
2198
+ }
2199
+
2200
+ const finalAddedNodes = [...addedNodes].filter(n => this.templateRoot.contains(n));
2201
+ if (finalAddedNodes.length > 0) {
2202
+ this.addNodes(finalAddedNodes);
2203
+ }
2204
+
2205
+ for (let i = 0; i < mutationList.length; i++) {
2206
+ const mutation = mutationList[i];
2192
2207
  this.updateNode(mutation.target, mutation.attributeName);
2193
2208
  }
2194
2209
  }
@@ -2199,10 +2214,10 @@ export class HTMLElementWithLightDOMTemplate extends HTMLElement {
2199
2214
  protected updateNode(_node: Node, _attributeName: string|null): void {
2200
2215
  }
2201
2216
 
2202
- protected addNodes(_nodes: NodeList|Node[], _nextSibling?: Node|null): void {
2217
+ protected addNodes(_nodes: NodeList|Node[]): void {
2203
2218
  }
2204
2219
 
2205
- protected removeNodes(_nodes: NodeList): void {
2220
+ protected removeNodes(_nodes: NodeList|Node[]): void {
2206
2221
  }
2207
2222
 
2208
2223
  static findCorrespondingElement(
@@ -76,16 +76,20 @@ export function widgetConfig<F extends WidgetFactory<AnyWidget>, ParamKeys exten
76
76
  let currentUpdateQueue: Map<AnyWidget, PromiseWithResolvers<void>>|null = null;
77
77
  const currentlyProcessed = new Set<AnyWidget>();
78
78
  let nextUpdateQueue = new Map<AnyWidget, PromiseWithResolvers<void>>();
79
- let pendingAnimationFrame: number|null = null;
79
+ const pendingAnimationFrames = new WeakMap<Window, number>();
80
80
  let overallUpdatePromise: PromiseWithResolvers<void>|null = null;
81
81
 
82
82
  function enqueueIntoNextUpdateQueue(widget: AnyWidget): Promise<void> {
83
83
  const scheduledUpdate = nextUpdateQueue.get(widget) ?? Promise.withResolvers<void>();
84
84
  nextUpdateQueue.delete(widget);
85
85
  nextUpdateQueue.set(widget, scheduledUpdate);
86
- if (pendingAnimationFrame === null) {
87
- const widgetWindow = widget.contentElement.window() || window;
88
- pendingAnimationFrame = widgetWindow.requestAnimationFrame(runNextUpdate);
86
+ const widgetWindow = widget.contentElement.window() || window;
87
+ if (!pendingAnimationFrames.has(widgetWindow)) {
88
+ const frameId = widgetWindow.requestAnimationFrame(() => {
89
+ pendingAnimationFrames.delete(widgetWindow);
90
+ runNextUpdate();
91
+ });
92
+ pendingAnimationFrames.set(widgetWindow, frameId);
89
93
  }
90
94
  return scheduledUpdate.promise;
91
95
  }
@@ -121,14 +125,13 @@ function cancelUpdate(widget: AnyWidget): void {
121
125
 
122
126
  function resolveOverallUpdatePromise(): void {
123
127
  if (currentlyProcessed.size === 0 && (!currentUpdateQueue || currentUpdateQueue.size === 0) &&
124
- nextUpdateQueue.size === 0 && !pendingAnimationFrame && overallUpdatePromise) {
128
+ nextUpdateQueue.size === 0 && overallUpdatePromise) {
125
129
  overallUpdatePromise.resolve();
126
130
  overallUpdatePromise = null;
127
131
  }
128
132
  }
129
133
 
130
134
  function runNextUpdate(): void {
131
- pendingAnimationFrame = null;
132
135
  if (!currentUpdateQueue) {
133
136
  currentUpdateQueue = nextUpdateQueue;
134
137
  nextUpdateQueue = new Map();
@@ -155,9 +158,13 @@ function runNextUpdate(): void {
155
158
  const nextUpdate = nextUpdateQueue.get(widget);
156
159
  if (nextUpdate) {
157
160
  void nextUpdate.promise.then(resolve);
158
- if (pendingAnimationFrame === null) {
159
- const widgetWindow = widget.contentElement.window() || window;
160
- pendingAnimationFrame = widgetWindow.requestAnimationFrame(runNextUpdate);
161
+ const widgetWindow = widget.contentElement.window() || window;
162
+ if (!pendingAnimationFrames.has(widgetWindow)) {
163
+ const frameId = widgetWindow.requestAnimationFrame(() => {
164
+ pendingAnimationFrames.delete(widgetWindow);
165
+ runNextUpdate();
166
+ });
167
+ pendingAnimationFrames.set(widgetWindow, frameId);
161
168
  }
162
169
  } else {
163
170
  resolve();
@@ -578,7 +585,7 @@ export class Widget<ContentTypeT extends HTMLElement|DocumentFragment = HTMLElem
578
585
  }
579
586
 
580
587
  static get allUpdatesComplete(): Promise<void> {
581
- if (!pendingAnimationFrame && !currentUpdateQueue && currentlyProcessed.size === 0) {
588
+ if (nextUpdateQueue.size === 0 && !currentUpdateQueue && currentlyProcessed.size === 0) {
582
589
  return Promise.resolve();
583
590
  }
584
591
  if (!overallUpdatePromise) {
@@ -38,7 +38,7 @@ import * as Host from '../../../../core/host/host.js';
38
38
  import * as i18n from '../../../../core/i18n/i18n.js';
39
39
  import * as Platform from '../../../../core/platform/platform.js';
40
40
  import * as SDK from '../../../../core/sdk/sdk.js';
41
- import * as TextUtils from '../../../../models/text_utils/text_utils.js';
41
+ import * as TextUtils from '../../../../core/text_utils/text_utils.js';
42
42
  import * as SrgbOverlay from '../../../components/srgb_overlay/srgb_overlay.js';
43
43
  import {createIcon, Icon} from '../../../kit/kit.js';
44
44
  import * as VisualLogging from '../../../visual_logging/visual_logging.js';
@@ -4,7 +4,7 @@
4
4
  /* eslint-disable @devtools/no-imperative-dom-api */
5
5
 
6
6
  import type * as Platform from '../../../../core/platform/platform.js';
7
- import type * as TextUtils from '../../../../models/text_utils/text_utils.js';
7
+ import type * as TextUtils from '../../../../core/text_utils/text_utils.js';
8
8
  import * as Lit from '../../../lit/lit.js';
9
9
  import * as UI from '../../legacy.js';
10
10
 
@@ -71,6 +71,7 @@ export class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate
71
71
  #hideableColumns = new Set<string>();
72
72
  #hiddenColumns = new Set<string>();
73
73
  #usedCreationNode: DataGridElementNode|null = null;
74
+ #sortingChangedScheduled = false;
74
75
 
75
76
  constructor() {
76
77
  super();
@@ -247,6 +248,7 @@ export class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate
247
248
  const sort = column.getAttribute('sort') === 'descending' ? Order.Descending :
248
249
  column.getAttribute('sort') === 'ascending' ? Order.Ascending :
249
250
  undefined;
251
+ const disclosure = hasBooleanAttribute(column, 'disclosure');
250
252
  const columnDescriptor = {
251
253
  id,
252
254
  title: title as Platform.UIString.LocalizedString,
@@ -259,6 +261,7 @@ export class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate
259
261
  weight,
260
262
  editable,
261
263
  dataType,
264
+ disclosure,
262
265
  };
263
266
  this.#dataGrid.addColumn(columnDescriptor);
264
267
  this.#columns.push(columnDescriptor);
@@ -289,7 +292,7 @@ export class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate
289
292
  return false;
290
293
  }
291
294
 
292
- #getDataRows(nodes: NodeList): HTMLElement[] {
295
+ #getDataRows(nodes: NodeList|Node[]): HTMLElement[] {
293
296
  return [...nodes]
294
297
  .flatMap(node => {
295
298
  if (node instanceof HTMLTableRowElement) {
@@ -303,7 +306,7 @@ export class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate
303
306
  .filter(node => node.querySelector('td') && !hasBooleanAttribute(node, 'placeholder'));
304
307
  }
305
308
 
306
- #getStyleElements(nodes: NodeList): HTMLElement[] {
309
+ #getStyleElements(nodes: NodeList|Node[]): HTMLElement[] {
307
310
  return [...nodes].flatMap(node => {
308
311
  if (node instanceof HTMLStyleElement) {
309
312
  return [node];
@@ -325,10 +328,16 @@ export class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate
325
328
  return null;
326
329
  }
327
330
 
328
- override addNodes(nodes: NodeList): void {
331
+ override addNodes(nodes: NodeList|Node[]): void {
329
332
  for (const element of this.#getDataRows(nodes)) {
333
+ if (getNode(element)) {
334
+ continue;
335
+ }
330
336
  const parentRow = element.parentElement?.closest('td')?.closest('tr');
331
337
  const parentDataGridNode = parentRow ? getNode(parentRow) : undefined;
338
+ if (parentRow && !parentDataGridNode) {
339
+ continue;
340
+ }
332
341
  const parentNode = parentDataGridNode || this.#dataGrid.rootNode();
333
342
  const nextNode = this.#findNextExistingNode(element);
334
343
  const index = nextNode ? parentNode.children.indexOf(nextNode) : parentNode.children.length;
@@ -352,14 +361,17 @@ export class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate
352
361
  if (hasBooleanAttribute(element, 'highlighted')) {
353
362
  node.setHighlighted(true);
354
363
  }
364
+ if (hasBooleanAttribute(element, 'expanded')) {
365
+ node.expand();
366
+ }
355
367
  }
356
- for (const element of this.#getStyleElements(nodes)) {
368
+ for (const element of new Set(this.#getStyleElements(nodes))) {
357
369
  this.#shadowRoot.appendChild(element.cloneNode(true));
358
370
  }
359
- this.#dataGrid.dispatchEventToListeners(DataGridEvents.SORTING_CHANGED);
371
+ this.#scheduleSortingChanged();
360
372
  }
361
373
 
362
- override removeNodes(nodes: NodeList): void {
374
+ override removeNodes(nodes: NodeList|Node[]): void {
363
375
  for (const element of this.#getDataRows(nodes)) {
364
376
  const node = getNode(element);
365
377
  if (node) {
@@ -387,6 +399,12 @@ export class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate
387
399
  dataGridNode.setInactive(hasBooleanAttribute(dataRow, 'inactive'));
388
400
  } else if (attributeName === 'highlighted') {
389
401
  dataGridNode.setHighlighted(hasBooleanAttribute(dataRow, 'highlighted'));
402
+ } else if (attributeName === 'expanded') {
403
+ if (hasBooleanAttribute(dataRow, 'expanded')) {
404
+ dataGridNode.expand();
405
+ } else {
406
+ dataGridNode.collapse();
407
+ }
390
408
  } else {
391
409
  this.#updateHasChildren(dataGridNode, dataRow);
392
410
  dataGridNode.refresh();
@@ -394,6 +412,17 @@ export class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate
394
412
  }
395
413
  }
396
414
 
415
+ #scheduleSortingChanged(): void {
416
+ if (this.#sortingChangedScheduled) {
417
+ return;
418
+ }
419
+ this.#sortingChangedScheduled = true;
420
+ queueMicrotask(() => {
421
+ this.#sortingChangedScheduled = false;
422
+ this.#dataGrid.dispatchEventToListeners(DataGridEvents.SORTING_CHANGED);
423
+ });
424
+ }
425
+
397
426
  deselectRow(): void {
398
427
  this.#dataGrid.selectedNode?.deselect();
399
428
  }
@@ -430,7 +459,7 @@ export class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate
430
459
  // However, if we have nodes added, that will trigger a sort anyway so we
431
460
  // don't need to re-sort again.
432
461
  if (this.#dataGrid.sortColumnId() !== null && !hadAddedNodes) {
433
- this.#dataGrid.dispatchEventToListeners(DataGridEvents.SORTING_CHANGED);
462
+ this.#scheduleSortingChanged();
434
463
  }
435
464
  }
436
465
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  import * as Common from '../../../../core/common/common.js';
6
6
  import * as Platform from '../../../../core/platform/platform.js';
7
- import type * as TextUtils from '../../../../models/text_utils/text_utils.js';
7
+ import type * as TextUtils from '../../../../core/text_utils/text_utils.js';
8
8
  import * as RenderCoordinator from '../../../components/render_coordinator/render_coordinator.js';
9
9
 
10
10
  import {type DataGridData, DataGridImpl, DataGridNode, Events as DataGridEvents, type Parameters} from './DataGrid.js';
@@ -36,7 +36,7 @@
36
36
  position: sticky;
37
37
  top: 0;
38
38
  height: 21px;
39
- z-index: 1;
39
+ z-index: 2;
40
40
  }
41
41
 
42
42
  .data-grid .aria-live-label {
@@ -3,6 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
  /* eslint-disable @devtools/no-imperative-dom-api */
5
5
 
6
+ import * as i18n from '../../../../core/i18n/i18n.js';
6
7
  import * as Platform from '../../../../core/platform/platform.js';
7
8
  import * as Geometry from '../../../../models/geometry/geometry.js';
8
9
  import * as VisualLogging from '../../../visual_logging/visual_logging.js';
@@ -12,6 +13,15 @@ import type {AnimationTimingModel} from './AnimationTimingModel.js';
12
13
  import {BezierUI} from './BezierUI.js';
13
14
  import {CSSLinearEasingModel, type Point} from './CSSLinearEasingModel.js';
14
15
 
16
+ const UIStrings = {
17
+ /**
18
+ * @description Tooltip text for control points in the linear easing editor.
19
+ */
20
+ doubleClickToDelete: 'Double-click to delete',
21
+ } as const;
22
+ const str_ = i18n.i18n.registerUIStrings('ui/legacy/components/inline_editor/AnimationTimingUI.ts', UIStrings);
23
+ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
24
+
15
25
  const DOUBLE_CLICK_DELAY = 500;
16
26
 
17
27
  interface Params {
@@ -130,6 +140,10 @@ class LinearEasingPresentation {
130
140
  circle.setAttribute('cx', String(controlX));
131
141
  circle.setAttribute('cy', String(controlY));
132
142
  circle.setAttribute('r', String(this.params.pointRadius));
143
+ // SVG sub-elements do not support tooltips via the 'title' attribute.
144
+ // Instead, a child <title> element must be appended to the shape.
145
+ const title = UI.UIUtils.createSVGChild(circle, 'title');
146
+ title.textContent = i18nString(UIStrings.doubleClickToDelete);
133
147
  }
134
148
 
135
149
  timingPointToPosition(point: Point): Position {
@@ -178,6 +192,10 @@ class LinearEasingUI {
178
192
  #doubleClickTimer?: number;
179
193
  #pointIndexForDoubleClick?: number;
180
194
  #mouseDownPosition?: {x: number, y: number};
195
+ /**
196
+ * The rendered SVG coordinate position of the dragged control point at the start of the drag gesture.
197
+ */
198
+ #dragStartPointPosition?: Position;
181
199
 
182
200
  #svg: Element;
183
201
 
@@ -214,6 +232,8 @@ class LinearEasingUI {
214
232
  #handleControlPointClick(event: MouseEvent, pointIndex: number): void {
215
233
  this.#selectedPointIndex = pointIndex;
216
234
  this.#mouseDownPosition = {x: event.x, y: event.y};
235
+ const controlPosition = this.#presentation.renderedPositions?.[pointIndex];
236
+ this.#dragStartPointPosition = controlPosition ? {...controlPosition} : undefined;
217
237
 
218
238
  // This is a workaround to understand whether the user double clicked
219
239
  // a point or not. The reason is, we also want to handle drag interactions
@@ -259,26 +279,20 @@ class LinearEasingUI {
259
279
  }
260
280
 
261
281
  #updatePointPosition(mouseX: number, mouseY: number): void {
262
- if (this.#selectedPointIndex === undefined || this.#mouseDownPosition === undefined) {
263
- return;
264
- }
265
-
266
- const controlPosition = this.#presentation.renderedPositions?.[this.#selectedPointIndex];
267
- if (!controlPosition) {
282
+ if (this.#selectedPointIndex === undefined || this.#mouseDownPosition === undefined ||
283
+ this.#dragStartPointPosition === undefined) {
268
284
  return;
269
285
  }
270
286
 
287
+ // By calculating the position relative to the initial drag start position (#dragStartPointPosition)
288
+ // and the total drag distance (deltaX/deltaY), we avoid incremental coordinate drift and rounding
289
+ // errors that would accumulate if we updated the mouse starting point relative to the previous frame's position.
271
290
  const deltaX = mouseX - this.#mouseDownPosition.x;
272
291
  const deltaY = mouseY - this.#mouseDownPosition.y;
273
292
 
274
- this.#mouseDownPosition = {
275
- x: mouseX,
276
- y: mouseY,
277
- };
278
-
279
293
  const newPoint = {
280
- x: controlPosition.x + deltaX,
281
- y: controlPosition.y + deltaY,
294
+ x: this.#dragStartPointPosition.x + deltaX,
295
+ y: this.#dragStartPointPosition.y + deltaY,
282
296
  };
283
297
 
284
298
  this.#model.setPoint(this.#selectedPointIndex, this.#presentation.positionToTimingPoint(newPoint));
@@ -4,6 +4,7 @@
4
4
  /* eslint-disable @devtools/no-imperative-dom-api */
5
5
 
6
6
  import * as Common from '../../../../core/common/common.js';
7
+ import * as Platform from '../../../../core/platform/platform.js';
7
8
  import * as VisualLogging from '../../../visual_logging/visual_logging.js';
8
9
  import * as UI from '../../legacy.js';
9
10
 
@@ -135,11 +136,13 @@ export class BezierEditor extends Common.ObjectWrapper.eventMixin<EventTypes, ty
135
136
  if (!pivot) {
136
137
  return null;
137
138
  }
139
+ const logContext = VisualLogging.bezierPresetCategory()
140
+ .track({click: true})
141
+ .context(Platform.StringUtilities.toKebabCase(presetGroup[0].name));
138
142
 
139
143
  const presetElement = document.createElement('div');
140
144
  presetElement.classList.add('bezier-preset-category');
141
- presetElement.setAttribute(
142
- 'jslog', `${VisualLogging.bezierPresetCategory().track({click: true}).context(presetGroup[0].name)}`);
145
+ presetElement.setAttribute('jslog', `${logContext}`);
143
146
  const iconElement = UI.UIUtils.createSVGChild(presetElement, 'svg', 'bezier-preset monospace');
144
147
  const category = {presets: presetGroup, presetIndex: 0, icon: presetElement};
145
148
  this.presetUI.draw(pivot, iconElement);
@@ -6,8 +6,17 @@ import * as CodeMirror from '../../../../third_party/codemirror.next/codemirror.
6
6
 
7
7
  const cssParser = CodeMirror.css.cssLanguage.parser;
8
8
 
9
+ /**
10
+ * Represents a point in a linear easing function graph.
11
+ */
9
12
  export interface Point {
13
+ /**
14
+ * The timeline percentage fraction (0 to 100).
15
+ */
10
16
  input: number;
17
+ /**
18
+ * The progress value (typically between 0 and 1, but can exceed bounds for bounce/elastic effects).
19
+ */
11
20
  output: number;
12
21
  }
13
22
 
@@ -105,6 +114,10 @@ const KeywordToValue: Record<string, string> = {
105
114
  linear: 'linear(0 0%, 1 100%)',
106
115
  };
107
116
 
117
+ /**
118
+ * Model representing a CSS `linear()` easing function, conforming to the CSS Easing Level 1 specification.
119
+ * It parses CSS linear easing text into a list of control points and manages point mutations.
120
+ */
108
121
  export class CSSLinearEasingModel {
109
122
  #points: Point[];
110
123
 
@@ -207,7 +220,17 @@ export class CSSLinearEasingModel {
207
220
  this.#points.splice(index, 1);
208
221
  }
209
222
 
223
+ /**
224
+ * Sets the timing point at the specified index, clamping its input value (percentage)
225
+ * to ensure it remains non-decreasing and within the bounds of neighboring points.
226
+ *
227
+ * @param index The index of the point to update.
228
+ * @param point The new timing point coordinates.
229
+ */
210
230
  setPoint(index: number, point: Point): void {
231
+ const minInput = index > 0 ? this.#points[index - 1].input : 0;
232
+ const maxInput = index < this.#points.length - 1 ? this.#points[index + 1].input : 100;
233
+ point.input = Math.max(minInput, Math.min(point.input, maxInput));
211
234
  this.#points[index] = point;
212
235
  }
213
236