chrome-devtools-frontend 1.0.1721762 → 1.0.1726686
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.
- package/.agents/skills/review-ui-widgets/SKILL.md +7 -7
- package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +12 -0
- package/.agents/skills/ui-eng-vision-widget-promoter/SKILL.md +3 -3
- package/.agents/skills/ui-widgets/SKILL.md +2 -1
- package/docs/cookbook/dependencies.md +57 -11
- package/docs/get_the_code.md +15 -0
- package/front_end/core/i18n/collect-ui-strings.js +58 -12
- package/front_end/core/i18n/i18nImpl.ts +1 -1
- package/front_end/core/root/Runtime.ts +1 -1
- package/front_end/core/sdk/ResourceTreeModel.ts +16 -0
- package/front_end/core/sdk/WebAuthnModel.ts +17 -10
- package/front_end/entrypoints/js_app/js_app.ts +2 -5
- package/front_end/entrypoints/node_app/node_app.ts +2 -3
- package/front_end/generated/InspectorBackendCommands.ts +3 -3
- package/front_end/generated/protocol.ts +17 -0
- package/front_end/models/ai_assistance/skills/lighthouse.md +2 -1
- package/front_end/models/ai_assistance/skills/network.md +1 -0
- package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +26 -2
- package/front_end/models/ai_assistance/tools/GetLighthouseAudits.ts +1 -1
- package/front_end/models/ai_assistance/tools/ListNetworkRequests.ts +2 -7
- package/front_end/models/ai_assistance/tools/RunLighthouse.ts +2 -2
- package/front_end/models/comment_manager/CD4ABridge.ts +4 -0
- package/front_end/models/comment_manager/CommentManager.ts +0 -6
- package/front_end/models/comment_manager/CommentThread.ts +39 -19
- package/front_end/models/elements/StyleChanges.ts +66 -0
- package/front_end/models/trace/EventsSerializer.ts +2 -7
- package/front_end/models/trace/ModelImpl.ts +0 -2
- package/front_end/models/trace/handlers/FlowsHandler.ts +37 -29
- package/front_end/models/trace/handlers/NetworkRequestsHandler.ts +13 -6
- package/front_end/models/trace/helpers/SyntheticEvents.ts +10 -37
- package/front_end/models/trace/insights/RenderBlocking.ts +3 -1
- package/front_end/models/trace/lantern/simulation/Simulator.ts +4 -0
- package/front_end/models/trace/lantern/types/Lantern.ts +1 -0
- package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingView.ts +92 -0
- package/front_end/panels/accessibility/SourceOrderView.ts +1 -1
- package/front_end/panels/accessibility/accessibilityAnnouncementRecordingListView.css +3 -1
- package/front_end/panels/accessibility/accessibilityAnnouncementRecordingView.css +12 -1
- package/front_end/panels/application/ApplicationPanelSidebar.ts +90 -0
- package/front_end/panels/application/StorageView.ts +348 -254
- package/front_end/panels/application/SubAppsView.ts +159 -0
- package/front_end/panels/application/application.ts +2 -0
- package/front_end/panels/application/preloading/PreloadingView.ts +360 -336
- package/front_end/panels/application/preloading/components/PreloadingDisabledInfobar.ts +3 -3
- package/front_end/panels/application/preloading/components/PreloadingGrid.ts +6 -3
- package/front_end/panels/application/preloading/components/RuleSetGrid.ts +17 -17
- package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +2 -2
- package/front_end/panels/application/preloading/preloadingView.css +12 -4
- package/front_end/panels/application/preloading/preloadingViewDropDown.css +1 -1
- package/front_end/panels/application/storageView.css +16 -21
- package/front_end/panels/application/subAppsView.css +21 -0
- package/front_end/panels/browser_debugger/CategorizedBreakpointsSidebarPane.ts +2 -2
- package/front_end/panels/browser_debugger/browser_debugger-meta.ts +6 -8
- package/front_end/panels/comments/CommentsPane.ts +26 -9
- package/front_end/panels/comments/commentsPane.css +25 -6
- package/front_end/panels/common/CommentThreadWidget.ts +2 -2
- package/front_end/panels/common/CommentsOverlayWidget.ts +94 -35
- package/front_end/panels/common/commentThreadWidget.css +17 -0
- package/front_end/panels/common/commentsOverlay.css +5 -10
- package/front_end/panels/common/common-meta.ts +11 -1
- package/front_end/panels/elements/ClassesPaneWidget.ts +133 -89
- package/front_end/panels/elements/ColorSwatchPopoverIcon.ts +7 -33
- package/front_end/panels/elements/DOMTreeElementWidget.ts +3 -1
- package/front_end/panels/elements/DOMTreeWidget.ts +19 -3
- package/front_end/panels/elements/ElementStatePaneWidget.ts +11 -1
- package/front_end/panels/elements/PropertyRenderer.ts +3 -2
- package/front_end/panels/elements/StyleEditorWidget.ts +87 -39
- package/front_end/panels/elements/StylePropertiesSection.ts +32 -5
- package/front_end/panels/elements/StylePropertyTreeElement.ts +227 -162
- package/front_end/panels/elements/StylesSidebarPane.ts +1 -0
- package/front_end/panels/event_listeners/EventListenersView.ts +11 -8
- package/front_end/panels/layer_viewer/Layers3DView.ts +21 -37
- package/front_end/panels/linear_memory_inspector/components/ValueInterpreterSettings.ts +1 -1
- package/front_end/panels/network/NetworkConfigView.ts +12 -10
- package/front_end/panels/network/NetworkDataGridNode.ts +3 -1
- package/front_end/panels/network/RequestConditionsDrawer.ts +1 -1
- package/front_end/panels/network/RequestPayloadView.ts +12 -5
- package/front_end/panels/network/networkConfigView.css +8 -8
- package/front_end/panels/profiler/HeapProfileView.ts +28 -6
- package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +7 -3
- package/front_end/panels/protocol_monitor/JSONEditor.ts +0 -1
- package/front_end/panels/recorder/RecorderPanel.ts +2 -2
- package/front_end/panels/screencast/ScreencastView.ts +3 -6
- package/front_end/panels/security/SecurityPanelSidebar.ts +0 -31
- package/front_end/panels/settings/SettingsScreen.ts +1 -1
- package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +9 -16
- package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +358 -345
- package/front_end/panels/settings/emulation/components/userAgentClientHintsForm.css +136 -121
- package/front_end/panels/sources/NavigatorView.ts +105 -45
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +8 -5
- package/front_end/panels/sources/SourcesNavigator.ts +421 -213
- package/front_end/panels/sources/SourcesPanel.ts +9 -5
- package/front_end/panels/sources/TabbedEditorContainer.ts +41 -18
- package/front_end/panels/sources/UISourceCodeFrame.ts +1 -1
- package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +10 -5
- package/front_end/panels/sources/sources-meta.ts +4 -15
- package/front_end/panels/sources/sourcesNavigator.css +5 -0
- package/front_end/panels/timeline/ModificationsManager.ts +0 -2
- package/front_end/panels/timeline/README.md +2 -0
- package/front_end/panels/timeline/TimelineCommentContext.ts +171 -0
- package/front_end/panels/timeline/TimelineCommentController.ts +168 -30
- package/front_end/panels/timeline/TimelinePanel.ts +4 -0
- package/front_end/panels/timeline/components/IgnoreListSetting.ts +1 -1
- package/front_end/panels/timeline/timeline.ts +2 -0
- package/front_end/panels/timeline/utils/Treemap.ts +8 -0
- package/front_end/panels/webauthn/WebauthnPane.ts +15 -13
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/puppeteer/README.chromium +2 -2
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +113 -3
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +21311 -20981
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.d.ts +36 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.js +22 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.js +20 -18
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.d.ts +20 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.js +2 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts +40 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js +3 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.d.ts +2 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.js +41 -5
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPRequest.d.ts +2 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPRequest.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPRequest.js +23 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPRequest.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Input.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.d.ts +3 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.js +13 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/Request.d.ts +1 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/Request.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/Request.js +18 -11
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/Request.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.d.ts +2 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.js +8 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.d.ts +2 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js +24 -12
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.js +13 -7
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Frame.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Frame.js +5 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Frame.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.d.ts +22 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.js +75 -9
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkEventManager.d.ts +18 -4
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkEventManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkEventManager.js +8 -4
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkEventManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.js +65 -26
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.d.ts +3 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.js +19 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/ScreenRecording.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/ScreenRecording.js +4 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/ScreenRecording.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.d.ts +1 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.js +4 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.d.ts +2 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.js +95 -8
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.d.ts +0 -8
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.js +8 -24
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserWebSocketTransport.d.ts +1 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserWebSocketTransport.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserWebSocketTransport.js +5 -4
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserWebSocketTransport.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/ConnectOptions.d.ts +9 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/ConnectOptions.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/WaitTask.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/WaitTask.js +10 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/WaitTask.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.d.ts +10 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.js +30 -5
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/Poller.d.ts +2 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/Poller.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/Poller.js +33 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/Poller.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js +1 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/NodeWebSocketTransport.d.ts +4 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/NodeWebSocketTransport.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/NodeWebSocketTransport.js +1 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/NodeWebSocketTransport.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/encoding.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/encoding.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/types.d.ts +113 -3
- package/front_end/third_party/puppeteer/package/package.json +4 -4
- package/front_end/third_party/puppeteer/package/src/api/Browser.ts +42 -0
- package/front_end/third_party/puppeteer/package/src/api/BrowserContext.ts +25 -22
- package/front_end/third_party/puppeteer/package/src/api/HTTPRequest.ts +22 -2
- package/front_end/third_party/puppeteer/package/src/api/Page.ts +45 -2
- package/front_end/third_party/puppeteer/package/src/api/locators/locators.ts +79 -32
- package/front_end/third_party/puppeteer/package/src/bidi/HTTPRequest.ts +32 -12
- package/front_end/third_party/puppeteer/package/src/bidi/Input.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/bidi/Page.ts +18 -2
- package/front_end/third_party/puppeteer/package/src/bidi/core/Request.ts +21 -13
- package/front_end/third_party/puppeteer/package/src/cdp/Accessibility.ts +12 -2
- package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +37 -16
- package/front_end/third_party/puppeteer/package/src/cdp/EmulationManager.ts +14 -11
- package/front_end/third_party/puppeteer/package/src/cdp/Frame.ts +7 -1
- package/front_end/third_party/puppeteer/package/src/cdp/HTTPRequest.ts +101 -14
- package/front_end/third_party/puppeteer/package/src/cdp/NetworkEventManager.ts +26 -6
- package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +111 -29
- package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +37 -1
- package/front_end/third_party/puppeteer/package/src/cdp/ScreenRecording.ts +5 -4
- package/front_end/third_party/puppeteer/package/src/cdp/Target.ts +5 -0
- package/front_end/third_party/puppeteer/package/src/cdp/TargetManager.ts +122 -7
- package/front_end/third_party/puppeteer/package/src/common/BrowserConnector.ts +13 -33
- package/front_end/third_party/puppeteer/package/src/common/BrowserWebSocketTransport.ts +10 -5
- package/front_end/third_party/puppeteer/package/src/common/ConnectOptions.ts +10 -0
- package/front_end/third_party/puppeteer/package/src/common/WaitTask.ts +12 -0
- package/front_end/third_party/puppeteer/package/src/common/util.ts +39 -5
- package/front_end/third_party/puppeteer/package/src/generated/injected.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/injected/Poller.ts +35 -3
- package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +4 -2
- package/front_end/third_party/puppeteer/package/src/node/NodeWebSocketTransport.ts +5 -0
- package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
- package/front_end/third_party/puppeteer/package/src/util/encoding.ts +2 -2
- package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
- package/front_end/ui/comments/CommentAnchorResolver.ts +3 -0
- package/front_end/ui/comments/CommentOverlayManager.ts +2 -4
- package/front_end/ui/components/lists/List.ts +14 -1
- package/front_end/ui/components/panel_feedback/PreviewToggle.ts +1 -1
- package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +23 -14
- package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +3 -0
- package/front_end/ui/helpers/OpenInNewTab.ts +8 -0
- package/front_end/ui/legacy/LinkContextMenuProvider.ts +1 -1
- package/front_end/ui/legacy/ListWidget.ts +14 -18
- package/front_end/ui/legacy/TabbedPane.ts +46 -3
- package/front_end/ui/legacy/Toolbar.ts +0 -1
- package/front_end/ui/legacy/Treeoutline.ts +10 -3
- package/front_end/ui/legacy/UIUtils.ts +5 -2
- package/front_end/ui/legacy/components/inline_editor/Swatches.ts +19 -6
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +20 -11
- package/front_end/ui/legacy/components/source_frame/XMLView.ts +27 -7
- package/front_end/ui/visual_logging/KnownContextValues.ts +5 -0
- package/package.json +1 -1
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
// Copyright 2021 The Chromium Authors
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
|
-
/* eslint-disable @devtools/no-lit-render-outside-of-view*/
|
|
5
4
|
|
|
6
5
|
import '../../../../ui/kit/kit.js';
|
|
7
|
-
import '../../../../ui/legacy/legacy.js';
|
|
8
6
|
|
|
7
|
+
import * as Common from '../../../../core/common/common.js';
|
|
9
8
|
import * as i18n from '../../../../core/i18n/i18n.js';
|
|
10
9
|
import * as Platform from '../../../../core/platform/platform.js';
|
|
11
10
|
import type * as Protocol from '../../../../generated/protocol.js';
|
|
12
11
|
import * as Buttons from '../../../../ui/components/buttons/buttons.js';
|
|
13
12
|
import * as Input from '../../../../ui/components/input/input.js';
|
|
14
|
-
import
|
|
13
|
+
import * as UI from '../../../../ui/legacy/legacy.js';
|
|
15
14
|
import * as Lit from '../../../../ui/lit/lit.js';
|
|
16
15
|
import * as VisualLogging from '../../../../ui/visual_logging/visual_logging.js';
|
|
17
16
|
import * as EmulationUtils from '../utils/utils.js';
|
|
18
17
|
|
|
19
18
|
import userAgentClientHintsFormStyles from './userAgentClientHintsForm.css.js';
|
|
20
19
|
|
|
21
|
-
const {html} = Lit;
|
|
20
|
+
const {html, Directives: {ref}} = Lit;
|
|
22
21
|
|
|
23
22
|
const UIStrings = {
|
|
24
23
|
/**
|
|
@@ -194,20 +193,20 @@ const UIStrings = {
|
|
|
194
193
|
const str_ = i18n.i18n.registerUIStrings('panels/settings/emulation/components/UserAgentClientHintsForm.ts', UIStrings);
|
|
195
194
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
196
195
|
|
|
197
|
-
export
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
super(ClientHintsChangeEvent.eventName);
|
|
201
|
-
}
|
|
196
|
+
export const enum Events {
|
|
197
|
+
CLIENT_HINTS_CHANGE = 'clienthintschange',
|
|
198
|
+
CLIENT_HINTS_SUBMIT = 'clienthintssubmit',
|
|
202
199
|
}
|
|
203
200
|
|
|
204
|
-
export
|
|
205
|
-
|
|
206
|
-
|
|
201
|
+
export interface EventTypes {
|
|
202
|
+
[Events.CLIENT_HINTS_CHANGE]: Protocol.Emulation.UserAgentMetadata;
|
|
203
|
+
[Events.CLIENT_HINTS_SUBMIT]: Protocol.Emulation.UserAgentMetadata;
|
|
204
|
+
}
|
|
207
205
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
206
|
+
declare global {
|
|
207
|
+
interface HTMLElementEventMap {
|
|
208
|
+
[Events.CLIENT_HINTS_CHANGE]: CustomEvent<Protocol.Emulation.UserAgentMetadata>;
|
|
209
|
+
[Events.CLIENT_HINTS_SUBMIT]: CustomEvent<Protocol.Emulation.UserAgentMetadata>;
|
|
211
210
|
}
|
|
212
211
|
}
|
|
213
212
|
|
|
@@ -249,12 +248,72 @@ export const ALL_PROTOCOL_FORM_FACTORS: string[] = [
|
|
|
249
248
|
UIStrings.formFactorWatch,
|
|
250
249
|
] as const;
|
|
251
250
|
|
|
251
|
+
type BrandList = 'brands'|'fullVersionList';
|
|
252
|
+
type BrandInputType = 'brandName'|'brandVersion';
|
|
253
|
+
type TextField = 'fullVersion'|'platform'|'platformVersion'|'architecture'|'model';
|
|
254
|
+
|
|
255
|
+
export interface BrandRow {
|
|
256
|
+
brand: string;
|
|
257
|
+
version: string;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const BRAND_INPUT_ID_PREFIXES: Record<BrandList, string> = {
|
|
261
|
+
brands: 'ua',
|
|
262
|
+
fullVersionList: 'fvl',
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
const ADD_BRAND_BUTTON_IDS: Record<BrandList, string> = {
|
|
266
|
+
brands: 'add-brand-button',
|
|
267
|
+
fullVersionList: 'add-fvl-brand-button',
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
export interface ViewInput {
|
|
271
|
+
brands: BrandRow[];
|
|
272
|
+
fullVersionList: BrandRow[];
|
|
273
|
+
fullVersion: string;
|
|
274
|
+
formFactors: string[];
|
|
275
|
+
platform: string;
|
|
276
|
+
platformVersion: string;
|
|
277
|
+
architecture: string;
|
|
278
|
+
model: string;
|
|
279
|
+
mobile: boolean;
|
|
280
|
+
isFormOpened: boolean;
|
|
281
|
+
isFormDisabled: boolean;
|
|
282
|
+
showMobileCheckbox: boolean;
|
|
283
|
+
showSubmitButton: boolean;
|
|
284
|
+
useragentModifiedAriaMessage: string;
|
|
285
|
+
onTreeToggle: (key?: string) => void;
|
|
286
|
+
onBrandAdd: (list: BrandList) => void;
|
|
287
|
+
onBrandDelete: (list: BrandList, index: number) => void;
|
|
288
|
+
onBrandInputChange: (list: BrandList, index: number, brandInputType: BrandInputType, value: string) => void;
|
|
289
|
+
onTextFieldChange: (field: TextField, value: string) => void;
|
|
290
|
+
onMobileChange: (mobile: boolean) => void;
|
|
291
|
+
onFormFactorChange: (formFactor: string, isChecked: boolean) => void;
|
|
292
|
+
onSubmit: () => void;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export interface ViewOutput {
|
|
296
|
+
focusBrandInput?: (list: BrandList, index: number) => void;
|
|
297
|
+
focusAddBrandButton?: (list: BrandList) => void;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
type View = typeof DEFAULT_VIEW;
|
|
301
|
+
|
|
302
|
+
const UserAgentClientHintsFormBase: Common.ObjectWrapper.EventMixin<EventTypes, typeof UI.Widget.Widget> =
|
|
303
|
+
Common.ObjectWrapper.eventMixin(UI.Widget.Widget);
|
|
304
|
+
|
|
252
305
|
/**
|
|
253
306
|
* Component for user agent client hints form, it is used in device settings panel
|
|
254
307
|
* and network conditions panel. It is customizable through showMobileCheckbox and showSubmitButton.
|
|
308
|
+
*
|
|
309
|
+
* The form dispatches {@link Events.CLIENT_HINTS_CHANGE} when the user changes
|
|
310
|
+
* a value, and {@link Events.CLIENT_HINTS_SUBMIT} when the user submits the
|
|
311
|
+
* form. The widget element also dispatches each event as a DOM `CustomEvent`
|
|
312
|
+
* with the metadata in `detail`.
|
|
255
313
|
*/
|
|
256
|
-
export class UserAgentClientHintsForm extends
|
|
257
|
-
readonly #
|
|
314
|
+
export class UserAgentClientHintsForm extends UserAgentClientHintsFormBase {
|
|
315
|
+
readonly #view: View;
|
|
316
|
+
readonly #viewOutput: ViewOutput = {};
|
|
258
317
|
|
|
259
318
|
#isFormOpened = false;
|
|
260
319
|
#isFormDisabled = false;
|
|
@@ -263,6 +322,11 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
263
322
|
#showSubmitButton = false;
|
|
264
323
|
#useragentModifiedAriaMessage = '';
|
|
265
324
|
|
|
325
|
+
constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
|
|
326
|
+
super(element);
|
|
327
|
+
this.#view = view;
|
|
328
|
+
}
|
|
329
|
+
|
|
266
330
|
set value(data: UserAgentClientHintsFormData) {
|
|
267
331
|
const {metaData = DEFAULT_METADATA, showMobileCheckbox = false, showSubmitButton = false} = data;
|
|
268
332
|
this.#metaData = {
|
|
@@ -271,7 +335,7 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
271
335
|
};
|
|
272
336
|
this.#showMobileCheckbox = showMobileCheckbox;
|
|
273
337
|
this.#showSubmitButton = showSubmitButton;
|
|
274
|
-
this
|
|
338
|
+
this.requestUpdate();
|
|
275
339
|
}
|
|
276
340
|
|
|
277
341
|
get value(): UserAgentClientHintsFormData {
|
|
@@ -281,23 +345,26 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
281
345
|
}
|
|
282
346
|
|
|
283
347
|
set disabled(disableForm: boolean) {
|
|
348
|
+
if (this.#isFormDisabled === disableForm) {
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
284
351
|
this.#isFormDisabled = disableForm;
|
|
285
|
-
|
|
286
|
-
|
|
352
|
+
if (disableForm) {
|
|
353
|
+
this.#isFormOpened = false;
|
|
354
|
+
}
|
|
355
|
+
this.requestUpdate();
|
|
287
356
|
}
|
|
288
357
|
|
|
289
358
|
get disabled(): boolean {
|
|
290
359
|
return this.#isFormDisabled;
|
|
291
360
|
}
|
|
292
361
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
};
|
|
362
|
+
override wasShown(): void {
|
|
363
|
+
super.wasShown();
|
|
364
|
+
this.requestUpdate();
|
|
365
|
+
}
|
|
299
366
|
|
|
300
|
-
#handleTreeClick = (key
|
|
367
|
+
#handleTreeClick = (key?: string): void => {
|
|
301
368
|
if (this.#isFormDisabled) {
|
|
302
369
|
return;
|
|
303
370
|
}
|
|
@@ -305,11 +372,11 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
305
372
|
return;
|
|
306
373
|
}
|
|
307
374
|
this.#isFormOpened = !this.#isFormOpened;
|
|
308
|
-
this
|
|
375
|
+
this.requestUpdate();
|
|
309
376
|
};
|
|
310
377
|
|
|
311
|
-
#
|
|
312
|
-
const
|
|
378
|
+
#handleBrandInputChange = (list: BrandList, index: number, brandInputType: BrandInputType, value: string): void => {
|
|
379
|
+
const updatedBrands = this.#metaData[list]?.map((browserBrand, brandIndex) => {
|
|
313
380
|
if (brandIndex === index) {
|
|
314
381
|
const {brand, version} = browserBrand;
|
|
315
382
|
if (brandInputType === 'brandName') {
|
|
@@ -327,138 +394,51 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
327
394
|
});
|
|
328
395
|
this.#metaData = {
|
|
329
396
|
...this.#metaData,
|
|
330
|
-
|
|
331
|
-
};
|
|
332
|
-
this.dispatchEvent(new ClientHintsChangeEvent());
|
|
333
|
-
this.#render();
|
|
334
|
-
};
|
|
335
|
-
|
|
336
|
-
#handleFullVersionListInputChange =
|
|
337
|
-
(value: string, index: number, brandInputType: 'brandName'|'brandVersion'): void => {
|
|
338
|
-
const fullVersionList = this.#metaData.fullVersionList?.map((browserBrand, brandIndex) => {
|
|
339
|
-
if (brandIndex === index) {
|
|
340
|
-
const {brand, version} = browserBrand;
|
|
341
|
-
if (brandInputType === 'brandName') {
|
|
342
|
-
return {
|
|
343
|
-
brand: value,
|
|
344
|
-
version,
|
|
345
|
-
};
|
|
346
|
-
}
|
|
347
|
-
return {
|
|
348
|
-
brand,
|
|
349
|
-
version: value,
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
return browserBrand;
|
|
353
|
-
});
|
|
354
|
-
this.#metaData = {
|
|
355
|
-
...this.#metaData,
|
|
356
|
-
fullVersionList,
|
|
357
|
-
};
|
|
358
|
-
this.dispatchEvent(new ClientHintsChangeEvent());
|
|
359
|
-
this.#render();
|
|
360
|
-
};
|
|
361
|
-
|
|
362
|
-
#handleUseragentDelete = (index: number): void => {
|
|
363
|
-
const {brands = []} = this.#metaData;
|
|
364
|
-
brands.splice(index, 1);
|
|
365
|
-
this.#metaData = {
|
|
366
|
-
...this.#metaData,
|
|
367
|
-
brands,
|
|
397
|
+
[list]: updatedBrands,
|
|
368
398
|
};
|
|
369
|
-
this.
|
|
370
|
-
this
|
|
371
|
-
this.#render();
|
|
372
|
-
|
|
373
|
-
// after deleting a brand row, focus on next Brand input if available,
|
|
374
|
-
// otherwise focus on the "Add Brand" button
|
|
375
|
-
let nextFocusElement = this.shadowRoot?.getElementById(`ua-brand-${index + 1}-input`);
|
|
376
|
-
if (!nextFocusElement) {
|
|
377
|
-
nextFocusElement = this.shadowRoot?.getElementById('add-brand-button');
|
|
378
|
-
}
|
|
379
|
-
(nextFocusElement as HTMLElement)?.focus();
|
|
399
|
+
this.dispatchEventToListeners(Events.CLIENT_HINTS_CHANGE, this.#metaData);
|
|
400
|
+
this.requestUpdate();
|
|
380
401
|
};
|
|
381
402
|
|
|
382
|
-
#
|
|
383
|
-
const {
|
|
384
|
-
|
|
403
|
+
#handleBrandDelete = async(list: BrandList, index: number): Promise<void> => {
|
|
404
|
+
const {[list]: brands = []} = this.#metaData;
|
|
405
|
+
const updatedBrands = brands.filter((_, brandIndex) => brandIndex !== index);
|
|
385
406
|
this.#metaData = {
|
|
386
407
|
...this.#metaData,
|
|
387
|
-
|
|
408
|
+
[list]: updatedBrands,
|
|
388
409
|
};
|
|
389
|
-
this.
|
|
410
|
+
this.dispatchEventToListeners(Events.CLIENT_HINTS_CHANGE, this.#metaData);
|
|
390
411
|
this.#useragentModifiedAriaMessage = i18nString(UIStrings.deletedBrand);
|
|
391
|
-
this
|
|
412
|
+
this.requestUpdate();
|
|
413
|
+
await this.updateComplete;
|
|
392
414
|
|
|
393
415
|
// after deleting a brand row, focus on next Brand input if available,
|
|
394
416
|
// otherwise focus on the "Add Brand" button
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
(nextFocusElement as HTMLElement)?.focus();
|
|
400
|
-
};
|
|
401
|
-
|
|
402
|
-
#handleAddUseragentBrandClick = (): void => {
|
|
403
|
-
const {brands} = this.#metaData;
|
|
404
|
-
this.#metaData = {
|
|
405
|
-
...this.#metaData,
|
|
406
|
-
brands: [
|
|
407
|
-
...(Array.isArray(brands) ? brands : []),
|
|
408
|
-
{
|
|
409
|
-
brand: '',
|
|
410
|
-
version: '',
|
|
411
|
-
},
|
|
412
|
-
],
|
|
413
|
-
};
|
|
414
|
-
this.dispatchEvent(new ClientHintsChangeEvent());
|
|
415
|
-
this.#useragentModifiedAriaMessage = i18nString(UIStrings.addedBrand);
|
|
416
|
-
this.#render();
|
|
417
|
-
const brandInputElements = this.shadowRoot?.querySelectorAll('.ua-brand-name-input');
|
|
418
|
-
if (brandInputElements) {
|
|
419
|
-
const lastBrandInputElement = Array.from(brandInputElements).pop();
|
|
420
|
-
if (lastBrandInputElement) {
|
|
421
|
-
(lastBrandInputElement as HTMLInputElement).focus();
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
};
|
|
425
|
-
|
|
426
|
-
#handleAddUseragentBrandKeyPress = (event: KeyboardEvent): void => {
|
|
427
|
-
if (event.code === 'Space' || event.code === 'Enter') {
|
|
428
|
-
event.preventDefault();
|
|
429
|
-
this.#handleAddUseragentBrandClick();
|
|
417
|
+
if (index < updatedBrands.length) {
|
|
418
|
+
this.#viewOutput.focusBrandInput?.(list, index);
|
|
419
|
+
} else {
|
|
420
|
+
this.#viewOutput.focusAddBrandButton?.(list);
|
|
430
421
|
}
|
|
431
422
|
};
|
|
432
423
|
|
|
433
|
-
#
|
|
434
|
-
const {
|
|
424
|
+
#handleBrandAdd = async(list: BrandList): Promise<void> => {
|
|
425
|
+
const {[list]: brands} = this.#metaData;
|
|
426
|
+
const updatedBrands = [
|
|
427
|
+
...(Array.isArray(brands) ? brands : []),
|
|
428
|
+
{
|
|
429
|
+
brand: '',
|
|
430
|
+
version: '',
|
|
431
|
+
},
|
|
432
|
+
];
|
|
435
433
|
this.#metaData = {
|
|
436
434
|
...this.#metaData,
|
|
437
|
-
|
|
438
|
-
...(Array.isArray(fullVersionList) ? fullVersionList : []),
|
|
439
|
-
{
|
|
440
|
-
brand: '',
|
|
441
|
-
version: '',
|
|
442
|
-
},
|
|
443
|
-
],
|
|
435
|
+
[list]: updatedBrands,
|
|
444
436
|
};
|
|
445
|
-
this.
|
|
437
|
+
this.dispatchEventToListeners(Events.CLIENT_HINTS_CHANGE, this.#metaData);
|
|
446
438
|
this.#useragentModifiedAriaMessage = i18nString(UIStrings.addedBrand);
|
|
447
|
-
this
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
const lastBrandInputElement = Array.from(brandInputElements).pop();
|
|
451
|
-
if (lastBrandInputElement) {
|
|
452
|
-
(lastBrandInputElement as HTMLInputElement).focus();
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
};
|
|
456
|
-
|
|
457
|
-
#handleAddFullVersionListBrandKeyPress = (event: KeyboardEvent): void => {
|
|
458
|
-
if (event.code === 'Space' || event.code === 'Enter') {
|
|
459
|
-
event.preventDefault();
|
|
460
|
-
this.#handleAddFullVersionListBrandClick();
|
|
461
|
-
}
|
|
439
|
+
this.requestUpdate();
|
|
440
|
+
await this.updateComplete;
|
|
441
|
+
this.#viewOutput.focusBrandInput?.(list, updatedBrands.length - 1);
|
|
462
442
|
};
|
|
463
443
|
|
|
464
444
|
#handleFormFactorCheckboxChange = (formFactorValue: string, isChecked: boolean): void => {
|
|
@@ -474,8 +454,8 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
474
454
|
...this.#metaData,
|
|
475
455
|
formFactors: currentFormFactors,
|
|
476
456
|
};
|
|
477
|
-
this.
|
|
478
|
-
this
|
|
457
|
+
this.dispatchEventToListeners(Events.CLIENT_HINTS_CHANGE, this.#metaData);
|
|
458
|
+
this.requestUpdate();
|
|
479
459
|
};
|
|
480
460
|
|
|
481
461
|
#handleInputChange = (stateKey: keyof Protocol.Emulation.UserAgentMetadata, value: string|boolean): void => {
|
|
@@ -484,25 +464,97 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
484
464
|
...this.#metaData,
|
|
485
465
|
[stateKey]: value,
|
|
486
466
|
};
|
|
487
|
-
this
|
|
467
|
+
this.requestUpdate();
|
|
488
468
|
}
|
|
489
|
-
this.
|
|
469
|
+
this.dispatchEventToListeners(Events.CLIENT_HINTS_CHANGE, this.#metaData);
|
|
490
470
|
};
|
|
491
471
|
|
|
492
|
-
#handleSubmit = (
|
|
493
|
-
event.preventDefault();
|
|
472
|
+
#handleSubmit = (): void => {
|
|
494
473
|
if (this.#showSubmitButton) {
|
|
495
|
-
this.
|
|
496
|
-
this
|
|
474
|
+
this.dispatchEventToListeners(Events.CLIENT_HINTS_SUBMIT, this.#metaData);
|
|
475
|
+
this.requestUpdate();
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
validate = (): UI.ListWidget.ValidatorResult => {
|
|
480
|
+
for (const [metaDataKey, metaDataValue] of Object.entries(this.#metaData)) {
|
|
481
|
+
if (metaDataKey === 'brands' || metaDataKey === 'fullVersionList') {
|
|
482
|
+
// for structured fields, check each individual brand/version
|
|
483
|
+
const brandList = metaDataValue as Protocol.Emulation.UserAgentBrandVersion[] | undefined;
|
|
484
|
+
const isBrandValid = (brandList ?? []).every(({brand, version}) => {
|
|
485
|
+
const brandNameResult = EmulationUtils.UserAgentMetadata.validateAsStructuredHeadersString(
|
|
486
|
+
brand, i18nString(UIStrings.notRepresentable));
|
|
487
|
+
const brandVersionResult = EmulationUtils.UserAgentMetadata.validateAsStructuredHeadersString(
|
|
488
|
+
version, i18nString(UIStrings.notRepresentable));
|
|
489
|
+
return brandNameResult.valid && brandVersionResult.valid;
|
|
490
|
+
});
|
|
491
|
+
if (!isBrandValid) {
|
|
492
|
+
return {valid: false, errorMessage: i18nString(UIStrings.notRepresentable)};
|
|
493
|
+
}
|
|
494
|
+
} else if (metaDataKey === 'formFactors') {
|
|
495
|
+
const formFactors = metaDataValue as string[] | undefined;
|
|
496
|
+
if (formFactors) {
|
|
497
|
+
for (const ff of formFactors) {
|
|
498
|
+
if (!ALL_PROTOCOL_FORM_FACTORS.includes(ff)) {
|
|
499
|
+
return {
|
|
500
|
+
valid: false,
|
|
501
|
+
errorMessage: i18nString(UIStrings.notRepresentable) + ` (Invalid form factor: ${ff})`,
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
const ffError = EmulationUtils.UserAgentMetadata.validateAsStructuredHeadersString(
|
|
505
|
+
ff, i18nString(UIStrings.notRepresentable));
|
|
506
|
+
if (!ffError.valid) {
|
|
507
|
+
return ffError;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
} else {
|
|
512
|
+
// otherwise, validate the value as a string
|
|
513
|
+
const metaDataError = EmulationUtils.UserAgentMetadata.validateAsStructuredHeadersString(
|
|
514
|
+
metaDataValue, i18nString(UIStrings.notRepresentable));
|
|
515
|
+
if (!metaDataError.valid) {
|
|
516
|
+
return metaDataError;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
497
519
|
}
|
|
520
|
+
return {valid: true};
|
|
498
521
|
};
|
|
499
522
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
523
|
+
override performUpdate(): void {
|
|
524
|
+
const input: ViewInput = {
|
|
525
|
+
brands: this.#metaData.brands ?? [{brand: '', version: ''}],
|
|
526
|
+
fullVersionList: this.#metaData.fullVersionList ?? [{brand: '', version: ''}],
|
|
527
|
+
fullVersion: this.#metaData.fullVersion || '',
|
|
528
|
+
formFactors: this.#metaData.formFactors ?? [],
|
|
529
|
+
platform: this.#metaData.platform,
|
|
530
|
+
platformVersion: this.#metaData.platformVersion,
|
|
531
|
+
architecture: this.#metaData.architecture,
|
|
532
|
+
model: this.#metaData.model,
|
|
533
|
+
mobile: this.#metaData.mobile,
|
|
534
|
+
isFormOpened: this.#isFormOpened,
|
|
535
|
+
isFormDisabled: this.#isFormDisabled,
|
|
536
|
+
showMobileCheckbox: this.#showMobileCheckbox,
|
|
537
|
+
showSubmitButton: this.#showSubmitButton,
|
|
538
|
+
useragentModifiedAriaMessage: this.#useragentModifiedAriaMessage,
|
|
539
|
+
onTreeToggle: this.#handleTreeClick,
|
|
540
|
+
onBrandAdd: list => void this.#handleBrandAdd(list),
|
|
541
|
+
onBrandDelete: (list, index) => void this.#handleBrandDelete(list, index),
|
|
542
|
+
onBrandInputChange: this.#handleBrandInputChange,
|
|
543
|
+
onTextFieldChange: this.#handleInputChange,
|
|
544
|
+
onMobileChange: mobile => this.#handleInputChange('mobile', mobile),
|
|
545
|
+
onFormFactorChange: this.#handleFormFactorCheckboxChange,
|
|
546
|
+
onSubmit: this.#handleSubmit,
|
|
547
|
+
};
|
|
548
|
+
this.#view(input, this.#viewOutput, this.contentElement);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLElement): void => {
|
|
553
|
+
const renderInputWithLabel = (label: string, placeholder: string, value: string,
|
|
554
|
+
stateKey: TextField): Lit.TemplateResult => {
|
|
503
555
|
const handleInputChange = (event: KeyboardEvent): void => {
|
|
504
556
|
const value = (event.target as HTMLInputElement).value;
|
|
505
|
-
|
|
557
|
+
input.onTextFieldChange(stateKey, value);
|
|
506
558
|
};
|
|
507
559
|
return html`
|
|
508
560
|
<label class="full-row label input-field-label-container">
|
|
@@ -518,17 +570,16 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
518
570
|
/>
|
|
519
571
|
</label>
|
|
520
572
|
`;
|
|
521
|
-
}
|
|
573
|
+
};
|
|
522
574
|
|
|
523
|
-
|
|
524
|
-
const {platform, platformVersion} = this.#metaData;
|
|
575
|
+
const renderPlatformSection = (): Lit.TemplateResult => {
|
|
525
576
|
const handlePlatformNameChange = (event: KeyboardEvent): void => {
|
|
526
577
|
const value = (event.target as HTMLInputElement).value;
|
|
527
|
-
|
|
578
|
+
input.onTextFieldChange('platform', value);
|
|
528
579
|
};
|
|
529
580
|
const handlePlatformVersionChange = (event: KeyboardEvent): void => {
|
|
530
581
|
const value = (event.target as HTMLInputElement).value;
|
|
531
|
-
|
|
582
|
+
input.onTextFieldChange('platformVersion', value);
|
|
532
583
|
};
|
|
533
584
|
return html`
|
|
534
585
|
<span class="full-row label">${i18nString(UIStrings.platformLabel)}</span>
|
|
@@ -537,7 +588,7 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
537
588
|
class="input-field half-row"
|
|
538
589
|
type="text"
|
|
539
590
|
@input=${handlePlatformNameChange}
|
|
540
|
-
.value=${platform}
|
|
591
|
+
.value=${input.platform}
|
|
541
592
|
placeholder=${i18nString(UIStrings.platformPlaceholder)}
|
|
542
593
|
aria-label=${i18nString(UIStrings.platformLabel)}
|
|
543
594
|
jslog=${VisualLogging.textField('platform').track({
|
|
@@ -548,7 +599,7 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
548
599
|
class="input-field half-row"
|
|
549
600
|
type="text"
|
|
550
601
|
@input=${handlePlatformVersionChange}
|
|
551
|
-
.value=${platformVersion}
|
|
602
|
+
.value=${input.platformVersion}
|
|
552
603
|
placeholder=${i18nString(UIStrings.platformVersion)}
|
|
553
604
|
aria-label=${i18nString(UIStrings.platformVersion)}
|
|
554
605
|
jslog=${VisualLogging.textField('platform-version').track({
|
|
@@ -557,21 +608,20 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
557
608
|
/>
|
|
558
609
|
</div>
|
|
559
610
|
`;
|
|
560
|
-
}
|
|
611
|
+
};
|
|
561
612
|
|
|
562
|
-
|
|
563
|
-
const {model, mobile} = this.#metaData;
|
|
613
|
+
const renderDeviceModelSection = (): Lit.TemplateResult => {
|
|
564
614
|
const handleDeviceModelChange = (event: KeyboardEvent): void => {
|
|
565
615
|
const value = (event.target as HTMLInputElement).value;
|
|
566
|
-
|
|
616
|
+
input.onTextFieldChange('model', value);
|
|
567
617
|
};
|
|
568
618
|
const handleMobileChange = (event: KeyboardEvent): void => {
|
|
569
619
|
const value = (event.target as HTMLInputElement).checked;
|
|
570
|
-
|
|
620
|
+
input.onMobileChange(value);
|
|
571
621
|
};
|
|
572
|
-
const mobileCheckboxInput =
|
|
622
|
+
const mobileCheckboxInput = input.showMobileCheckbox ? html`
|
|
573
623
|
<label class="mobile-checkbox-container">
|
|
574
|
-
<input type="checkbox" @input=${handleMobileChange} .checked=${mobile}
|
|
624
|
+
<input type="checkbox" @input=${handleMobileChange} .checked=${input.mobile}
|
|
575
625
|
jslog=${VisualLogging.toggle('mobile').track({
|
|
576
626
|
click: true,
|
|
577
627
|
})}
|
|
@@ -584,10 +634,10 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
584
634
|
<span class="full-row label">${i18nString(UIStrings.deviceModel)}</span>
|
|
585
635
|
<div class="full-row brand-row" aria-label=${i18nString(UIStrings.deviceProperties)} role="group">
|
|
586
636
|
<input
|
|
587
|
-
class="input-field ${
|
|
637
|
+
class="input-field ${input.showMobileCheckbox ? 'device-model-input' : 'full-row'}"
|
|
588
638
|
type="text"
|
|
589
639
|
@input=${handleDeviceModelChange}
|
|
590
|
-
.value=${model}
|
|
640
|
+
.value=${input.model}
|
|
591
641
|
placeholder=${i18nString(UIStrings.deviceModel)}
|
|
592
642
|
jslog=${VisualLogging.textField('model').track({
|
|
593
643
|
change: true,
|
|
@@ -596,22 +646,13 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
596
646
|
${mobileCheckboxInput}
|
|
597
647
|
</div>
|
|
598
648
|
`;
|
|
599
|
-
}
|
|
649
|
+
};
|
|
600
650
|
|
|
601
|
-
|
|
602
|
-
const {
|
|
603
|
-
brands =
|
|
604
|
-
[
|
|
605
|
-
{
|
|
606
|
-
brand: '',
|
|
607
|
-
version: '',
|
|
608
|
-
},
|
|
609
|
-
],
|
|
610
|
-
} = this.#metaData;
|
|
611
|
-
const brandElements = brands.map((brandRow, index) => {
|
|
651
|
+
const renderUseragent = (): Lit.TemplateResult => {
|
|
652
|
+
const brandElements = input.brands.map((brandRow, index) => {
|
|
612
653
|
const {brand, version} = brandRow;
|
|
613
654
|
const handleDeleteClick = (): void => {
|
|
614
|
-
|
|
655
|
+
input.onBrandDelete('brands', index);
|
|
615
656
|
};
|
|
616
657
|
const handleKeyPress = (event: KeyboardEvent): void => {
|
|
617
658
|
if (event.code === 'Space' || event.code === 'Enter') {
|
|
@@ -621,11 +662,11 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
621
662
|
};
|
|
622
663
|
const handleBrandChange = (event: KeyboardEvent): void => {
|
|
623
664
|
const value = (event.target as HTMLInputElement).value;
|
|
624
|
-
|
|
665
|
+
input.onBrandInputChange('brands', index, 'brandName', value);
|
|
625
666
|
};
|
|
626
667
|
const handleVersionChange = (event: KeyboardEvent): void => {
|
|
627
668
|
const value = (event.target as HTMLInputElement).value;
|
|
628
|
-
|
|
669
|
+
input.onBrandInputChange('brands', index, 'brandVersion', value);
|
|
629
670
|
};
|
|
630
671
|
return html`
|
|
631
672
|
<div class="full-row brand-row" aria-label=${i18nString(UIStrings.brandProperties)} role="group">
|
|
@@ -669,6 +710,12 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
669
710
|
</div>
|
|
670
711
|
`;
|
|
671
712
|
});
|
|
713
|
+
const handleAddBrandKeyPress = (event: KeyboardEvent): void => {
|
|
714
|
+
if (event.code === 'Space' || event.code === 'Enter') {
|
|
715
|
+
event.preventDefault();
|
|
716
|
+
input.onBrandAdd('brands');
|
|
717
|
+
}
|
|
718
|
+
};
|
|
672
719
|
return html`
|
|
673
720
|
<span class="full-row label">${i18nString(UIStrings.useragent)}</span>
|
|
674
721
|
${brandElements}
|
|
@@ -678,8 +725,8 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
678
725
|
tabindex="0"
|
|
679
726
|
id="add-brand-button"
|
|
680
727
|
aria-label=${i18nString(UIStrings.addBrand)}
|
|
681
|
-
@click=${
|
|
682
|
-
@keypress=${
|
|
728
|
+
@click=${() => input.onBrandAdd('brands')}
|
|
729
|
+
@keypress=${handleAddBrandKeyPress}
|
|
683
730
|
>
|
|
684
731
|
<devtools-icon
|
|
685
732
|
aria-hidden="true" name="plus" class="medium">
|
|
@@ -687,22 +734,13 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
687
734
|
${i18nString(UIStrings.addBrand)}
|
|
688
735
|
</div>
|
|
689
736
|
`;
|
|
690
|
-
}
|
|
737
|
+
};
|
|
691
738
|
|
|
692
|
-
|
|
693
|
-
const {
|
|
694
|
-
fullVersionList =
|
|
695
|
-
[
|
|
696
|
-
{
|
|
697
|
-
brand: '',
|
|
698
|
-
version: '',
|
|
699
|
-
},
|
|
700
|
-
],
|
|
701
|
-
} = this.#metaData;
|
|
702
|
-
const elements = fullVersionList.map((brandRow, index) => {
|
|
739
|
+
const renderFullVersionList = (): Lit.TemplateResult => {
|
|
740
|
+
const elements = input.fullVersionList.map((brandRow, index) => {
|
|
703
741
|
const {brand, version} = brandRow;
|
|
704
742
|
const handleDeleteClick = (): void => {
|
|
705
|
-
|
|
743
|
+
input.onBrandDelete('fullVersionList', index);
|
|
706
744
|
};
|
|
707
745
|
const handleKeyPress = (event: KeyboardEvent): void => {
|
|
708
746
|
if (event.code === 'Space' || event.code === 'Enter') {
|
|
@@ -712,11 +750,11 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
712
750
|
};
|
|
713
751
|
const handleBrandChange = (event: KeyboardEvent): void => {
|
|
714
752
|
const value = (event.target as HTMLInputElement).value;
|
|
715
|
-
|
|
753
|
+
input.onBrandInputChange('fullVersionList', index, 'brandName', value);
|
|
716
754
|
};
|
|
717
755
|
const handleVersionChange = (event: KeyboardEvent): void => {
|
|
718
756
|
const value = (event.target as HTMLInputElement).value;
|
|
719
|
-
|
|
757
|
+
input.onBrandInputChange('fullVersionList', index, 'brandVersion', value);
|
|
720
758
|
};
|
|
721
759
|
return html`
|
|
722
760
|
<div
|
|
@@ -751,7 +789,7 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
751
789
|
change: true,
|
|
752
790
|
})}
|
|
753
791
|
/>
|
|
754
|
-
<devtools-icon name="bin"
|
|
792
|
+
<devtools-icon name="bin"
|
|
755
793
|
title=${i18nString(UIStrings.brandFullVersionListDelete)}
|
|
756
794
|
class="medium delete-icon"
|
|
757
795
|
tabindex="0"
|
|
@@ -764,6 +802,12 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
764
802
|
</div>
|
|
765
803
|
`;
|
|
766
804
|
});
|
|
805
|
+
const handleAddBrandKeyPress = (event: KeyboardEvent): void => {
|
|
806
|
+
if (event.code === 'Space' || event.code === 'Enter') {
|
|
807
|
+
event.preventDefault();
|
|
808
|
+
input.onBrandAdd('fullVersionList');
|
|
809
|
+
}
|
|
810
|
+
};
|
|
767
811
|
return html`
|
|
768
812
|
<span class="full-row label">${i18nString(UIStrings.fullVersionList)}</span>
|
|
769
813
|
${elements}
|
|
@@ -773,8 +817,8 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
773
817
|
tabindex="0"
|
|
774
818
|
id="add-fvl-brand-button"
|
|
775
819
|
aria-label=${i18nString(UIStrings.addBrand)}
|
|
776
|
-
@click=${
|
|
777
|
-
@keypress=${
|
|
820
|
+
@click=${() => input.onBrandAdd('fullVersionList')}
|
|
821
|
+
@keypress=${handleAddBrandKeyPress}
|
|
778
822
|
>
|
|
779
823
|
<devtools-icon name="plus" class="medium"
|
|
780
824
|
aria-hidden="true">
|
|
@@ -782,11 +826,11 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
782
826
|
${i18nString(UIStrings.addBrand)}
|
|
783
827
|
</div>
|
|
784
828
|
`;
|
|
785
|
-
}
|
|
829
|
+
};
|
|
786
830
|
|
|
787
|
-
|
|
831
|
+
const renderFormFactorsSection = (): Lit.TemplateResult => {
|
|
788
832
|
const checkboxElements = ALL_PROTOCOL_FORM_FACTORS.map(ffValue => {
|
|
789
|
-
const isChecked =
|
|
833
|
+
const isChecked = input.formFactors.includes(ffValue);
|
|
790
834
|
const labelStringId = `formFactor${ffValue}` as keyof typeof UIStrings;
|
|
791
835
|
const label = i18nString(UIStrings[labelStringId]);
|
|
792
836
|
|
|
@@ -799,8 +843,7 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
799
843
|
jslog=${VisualLogging.toggle(Platform.StringUtilities.toKebabCase(ffValue)).track({
|
|
800
844
|
click: true,
|
|
801
845
|
})}
|
|
802
|
-
@change=${
|
|
803
|
-
(e: Event) => this.#handleFormFactorCheckboxChange(ffValue, (e.target as HTMLInputElement).checked)}
|
|
846
|
+
@change=${(e: Event) => input.onFormFactorChange(ffValue, (e.target as HTMLInputElement).checked)}
|
|
804
847
|
/>
|
|
805
848
|
${label}
|
|
806
849
|
</label>
|
|
@@ -816,138 +859,108 @@ export class UserAgentClientHintsForm extends HTMLElement {
|
|
|
816
859
|
${checkboxElements}
|
|
817
860
|
</div>
|
|
818
861
|
`;
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
#render(): void {
|
|
822
|
-
const {fullVersion, architecture} = this.#metaData;
|
|
823
|
-
const useragentSection = this.#renderUseragent();
|
|
824
|
-
const fullVersionListSection = this.#renderFullVersionList();
|
|
825
|
-
const fullBrowserInput = this.#renderInputWithLabel(
|
|
826
|
-
i18nString(UIStrings.fullBrowserVersion), i18nString(UIStrings.fullBrowserVersionPlaceholder),
|
|
827
|
-
fullVersion || '', 'fullVersion');
|
|
828
|
-
const formFactorsSection = this.#renderFormFactorsSection();
|
|
829
|
-
const platformSection = this.#renderPlatformSection();
|
|
830
|
-
const architectureInput = this.#renderInputWithLabel(
|
|
831
|
-
i18nString(UIStrings.architecture), i18nString(UIStrings.architecturePlaceholder), architecture,
|
|
832
|
-
'architecture');
|
|
833
|
-
const deviceModelSection = this.#renderDeviceModelSection();
|
|
834
|
-
// clang-format off
|
|
835
|
-
const submitButton = this.#showSubmitButton ? html`
|
|
836
|
-
<devtools-button
|
|
837
|
-
.variant=${Buttons.Button.Variant.OUTLINED}
|
|
838
|
-
.type=${'submit'}
|
|
839
|
-
>
|
|
840
|
-
${i18nString(UIStrings.update)}
|
|
841
|
-
</devtools-button>
|
|
842
|
-
` : Lit.nothing;
|
|
843
|
-
// clang-format on
|
|
844
|
-
|
|
845
|
-
// clang-format off
|
|
846
|
-
const output = html`
|
|
847
|
-
<style>${Input.checkboxStyles}</style>
|
|
848
|
-
<style>${userAgentClientHintsFormStyles}</style>
|
|
849
|
-
<section class="root">
|
|
850
|
-
<div class="tree-title">
|
|
851
|
-
<div
|
|
852
|
-
role=button
|
|
853
|
-
@click=${this.#handleTreeClick}
|
|
854
|
-
tabindex=${this.#isFormDisabled ? '-1' : '0'}
|
|
855
|
-
@keydown=${this.#handleTreeExpand}
|
|
856
|
-
aria-expanded=${this.#isFormOpened}
|
|
857
|
-
aria-controls=form-container
|
|
858
|
-
aria-disabled=${this.#isFormDisabled}
|
|
859
|
-
aria-label=${i18nString(UIStrings.title)}
|
|
860
|
-
jslog=${VisualLogging.toggleSubpane().track({click: true})}>
|
|
861
|
-
<devtools-icon name=triangle-right></devtools-icon>
|
|
862
|
-
<devtools-icon name=triangle-down></devtools-icon>
|
|
863
|
-
${i18nString(UIStrings.title)}
|
|
864
|
-
</div>
|
|
865
|
-
<devtools-icon tabindex=${this.#isFormDisabled ? '-1' : '0'} class=info-icon name=info aria-label=${i18nString(UIStrings.userAgentClientHintsInfo)} title=${i18nString(UIStrings.userAgentClientHintsInfo)}></devtools-icon>
|
|
866
|
-
<devtools-link
|
|
867
|
-
tabindex=${this.#isFormDisabled ? '-1' : '0'}
|
|
868
|
-
href="https://web.dev/user-agent-client-hints/"
|
|
869
|
-
class="link"
|
|
870
|
-
aria-label=${i18nString(UIStrings.learnMore)}
|
|
871
|
-
jslogcontext="learn-more"
|
|
872
|
-
>
|
|
873
|
-
${i18nString(UIStrings.learnMore)}
|
|
874
|
-
</devtools-link>
|
|
875
|
-
</div>
|
|
876
|
-
<form
|
|
877
|
-
id="form-container"
|
|
878
|
-
class="form-container ${this.#isFormOpened ? '' : 'hide-container'}"
|
|
879
|
-
@submit=${this.#handleSubmit}
|
|
880
|
-
>
|
|
881
|
-
${useragentSection}
|
|
882
|
-
<hr class="section-separator">
|
|
883
|
-
${fullVersionListSection}
|
|
884
|
-
<hr class="section-separator">
|
|
885
|
-
${fullBrowserInput}
|
|
886
|
-
<hr class="section-separator">
|
|
887
|
-
${formFactorsSection}
|
|
888
|
-
<hr class="section-separator">
|
|
889
|
-
${platformSection}
|
|
890
|
-
<hr class="section-separator">
|
|
891
|
-
${architectureInput}
|
|
892
|
-
<hr class="section-separator">
|
|
893
|
-
${deviceModelSection}
|
|
894
|
-
${submitButton}
|
|
895
|
-
</form>
|
|
896
|
-
<div aria-live="polite" aria-label=${this.#useragentModifiedAriaMessage}></div>
|
|
897
|
-
</section>
|
|
898
|
-
`;
|
|
899
|
-
// clang-format on
|
|
900
|
-
Lit.render(output, this.#shadow, {host: this});
|
|
901
|
-
}
|
|
862
|
+
};
|
|
902
863
|
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
const formFactors = metaDataValue as string[] | undefined;
|
|
919
|
-
if (formFactors) {
|
|
920
|
-
for (const ff of formFactors) {
|
|
921
|
-
if (!ALL_PROTOCOL_FORM_FACTORS.includes(ff)) {
|
|
922
|
-
return {
|
|
923
|
-
valid: false,
|
|
924
|
-
errorMessage: i18nString(UIStrings.notRepresentable) + ` (Invalid form factor: ${ff})`,
|
|
925
|
-
};
|
|
926
|
-
}
|
|
927
|
-
const ffError = EmulationUtils.UserAgentMetadata.validateAsStructuredHeadersString(
|
|
928
|
-
ff, i18nString(UIStrings.notRepresentable));
|
|
929
|
-
if (!ffError.valid) {
|
|
930
|
-
return ffError;
|
|
931
|
-
}
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
} else {
|
|
935
|
-
// otherwise, validate the value as a string
|
|
936
|
-
const metaDataError = EmulationUtils.UserAgentMetadata.validateAsStructuredHeadersString(
|
|
937
|
-
metaDataValue, i18nString(UIStrings.notRepresentable));
|
|
938
|
-
if (!metaDataError.valid) {
|
|
939
|
-
return metaDataError;
|
|
940
|
-
}
|
|
941
|
-
}
|
|
864
|
+
const useragentSection = renderUseragent();
|
|
865
|
+
const fullVersionListSection = renderFullVersionList();
|
|
866
|
+
const fullBrowserInput =
|
|
867
|
+
renderInputWithLabel(i18nString(UIStrings.fullBrowserVersion),
|
|
868
|
+
i18nString(UIStrings.fullBrowserVersionPlaceholder), input.fullVersion, 'fullVersion');
|
|
869
|
+
const formFactorsSection = renderFormFactorsSection();
|
|
870
|
+
const platformSection = renderPlatformSection();
|
|
871
|
+
const architectureInput =
|
|
872
|
+
renderInputWithLabel(i18nString(UIStrings.architecture), i18nString(UIStrings.architecturePlaceholder),
|
|
873
|
+
input.architecture, 'architecture');
|
|
874
|
+
const deviceModelSection = renderDeviceModelSection();
|
|
875
|
+
const handleTreeKeyDown = (event: KeyboardEvent): void => {
|
|
876
|
+
if (event.code === 'Space' || event.code === 'Enter' || event.code === 'ArrowLeft' || event.code === 'ArrowRight') {
|
|
877
|
+
event.consume(true);
|
|
878
|
+
input.onTreeToggle(event.code);
|
|
942
879
|
}
|
|
943
|
-
return {valid: true};
|
|
944
880
|
};
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
881
|
+
const handleSubmit = (event: SubmitEvent): void => {
|
|
882
|
+
event.preventDefault();
|
|
883
|
+
input.onSubmit();
|
|
884
|
+
};
|
|
885
|
+
const setFormElement = (element: Element|undefined): void => {
|
|
886
|
+
if (!(element instanceof HTMLFormElement)) {
|
|
887
|
+
output.focusBrandInput = undefined;
|
|
888
|
+
output.focusAddBrandButton = undefined;
|
|
889
|
+
return;
|
|
890
|
+
}
|
|
891
|
+
output.focusBrandInput = (list: BrandList, index: number): void => {
|
|
892
|
+
element.querySelector<HTMLElement>(`#${BRAND_INPUT_ID_PREFIXES[list]}-brand-${index + 1}-input`)?.focus();
|
|
893
|
+
};
|
|
894
|
+
output.focusAddBrandButton = (list: BrandList): void => {
|
|
895
|
+
element.querySelector<HTMLElement>(`#${ADD_BRAND_BUTTON_IDS[list]}`)?.focus();
|
|
896
|
+
};
|
|
897
|
+
};
|
|
898
|
+
// clang-format off
|
|
899
|
+
const submitButton = input.showSubmitButton ? html`
|
|
900
|
+
<devtools-button
|
|
901
|
+
.variant=${Buttons.Button.Variant.OUTLINED}
|
|
902
|
+
.type=${'submit'}
|
|
903
|
+
>
|
|
904
|
+
${i18nString(UIStrings.update)}
|
|
905
|
+
</devtools-button>
|
|
906
|
+
` : Lit.nothing;
|
|
907
|
+
// clang-format on
|
|
908
|
+
|
|
909
|
+
// clang-format off
|
|
910
|
+
const template = html`
|
|
911
|
+
<style>${Input.checkboxStyles}</style>
|
|
912
|
+
<style>${userAgentClientHintsFormStyles}</style>
|
|
913
|
+
<section class="root">
|
|
914
|
+
<div class="tree-title">
|
|
915
|
+
<div
|
|
916
|
+
role=button
|
|
917
|
+
@click=${() => input.onTreeToggle()}
|
|
918
|
+
tabindex=${input.isFormDisabled ? '-1' : '0'}
|
|
919
|
+
@keydown=${handleTreeKeyDown}
|
|
920
|
+
aria-expanded=${input.isFormOpened}
|
|
921
|
+
aria-controls=form-container
|
|
922
|
+
aria-disabled=${input.isFormDisabled}
|
|
923
|
+
aria-label=${i18nString(UIStrings.title)}
|
|
924
|
+
jslog=${VisualLogging.toggleSubpane().track({click: true})}>
|
|
925
|
+
<devtools-icon name=triangle-right></devtools-icon>
|
|
926
|
+
<devtools-icon name=triangle-down></devtools-icon>
|
|
927
|
+
${i18nString(UIStrings.title)}
|
|
928
|
+
</div>
|
|
929
|
+
<devtools-icon tabindex=${input.isFormDisabled ? '-1' : '0'} class=info-icon name=info aria-label=${i18nString(UIStrings.userAgentClientHintsInfo)} title=${i18nString(UIStrings.userAgentClientHintsInfo)}></devtools-icon>
|
|
930
|
+
<devtools-link
|
|
931
|
+
tabindex=${input.isFormDisabled ? '-1' : '0'}
|
|
932
|
+
href="https://web.dev/user-agent-client-hints/"
|
|
933
|
+
class="link"
|
|
934
|
+
aria-label=${i18nString(UIStrings.learnMore)}
|
|
935
|
+
jslogcontext="learn-more"
|
|
936
|
+
>
|
|
937
|
+
${i18nString(UIStrings.learnMore)}
|
|
938
|
+
</devtools-link>
|
|
939
|
+
</div>
|
|
940
|
+
<form
|
|
941
|
+
id="form-container"
|
|
942
|
+
class="form-container ${input.isFormOpened ? '' : 'hide-container'}"
|
|
943
|
+
@submit=${handleSubmit}
|
|
944
|
+
${ref(setFormElement)}
|
|
945
|
+
>
|
|
946
|
+
${useragentSection}
|
|
947
|
+
<hr class="section-separator">
|
|
948
|
+
${fullVersionListSection}
|
|
949
|
+
<hr class="section-separator">
|
|
950
|
+
${fullBrowserInput}
|
|
951
|
+
<hr class="section-separator">
|
|
952
|
+
${formFactorsSection}
|
|
953
|
+
<hr class="section-separator">
|
|
954
|
+
${platformSection}
|
|
955
|
+
<hr class="section-separator">
|
|
956
|
+
${architectureInput}
|
|
957
|
+
<hr class="section-separator">
|
|
958
|
+
${deviceModelSection}
|
|
959
|
+
${submitButton}
|
|
960
|
+
</form>
|
|
961
|
+
<div aria-live="polite" aria-label=${input.useragentModifiedAriaMessage}></div>
|
|
962
|
+
</section>
|
|
963
|
+
`;
|
|
964
|
+
// clang-format on
|
|
965
|
+
Lit.render(template, target);
|
|
966
|
+
};
|