chrome-devtools-frontend 1.0.1625079 → 1.0.1626437
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/front_end/core/common/VersionController.ts +9 -7
- package/front_end/core/common/common.ts +0 -4
- package/front_end/core/host/AidaClient.ts +1 -1
- package/front_end/core/host/AidaClientTypes.ts +2 -0
- package/front_end/core/host/AidaGcaTranslation.ts +2 -2
- package/front_end/core/host/Platform.ts +0 -9
- package/front_end/core/host/UserMetrics.ts +0 -55
- package/front_end/core/root/ExperimentNames.ts +0 -1
- package/front_end/core/sdk/CPUThrottlingManager.ts +1 -1
- package/front_end/core/sdk/CSSMetadata.ts +60 -63
- package/front_end/core/sdk/CSSProperty.ts +1 -5
- package/front_end/core/sdk/CSSPropertyParserMatchers.ts +11 -32
- package/front_end/{panels/application → core/sdk}/DOMStorageModel.ts +12 -10
- package/front_end/core/sdk/sdk.ts +2 -0
- package/front_end/entrypoints/main/MainImpl.ts +12 -8
- package/front_end/entrypoints/main/SimpleApp.ts +3 -4
- package/front_end/entrypoints/main/main-meta.ts +1 -1
- package/front_end/generated/InspectorBackendCommands.ts +3 -3
- package/front_end/generated/SupportedCSSProperties.js +21 -21
- package/front_end/generated/protocol.ts +4 -1
- package/front_end/models/ai_assistance/StorageItem.ts +16 -0
- package/front_end/models/ai_assistance/agents/StorageAgent.ts +82 -0
- package/front_end/models/ai_assistance/ai_assistance.ts +4 -0
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +9 -37
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +26 -3
- package/front_end/models/ai_code_completion/AiCodeCompletion.ts +10 -2
- package/front_end/models/ai_code_generation/AiCodeGeneration.ts +5 -1
- package/front_end/models/issues_manager/CookieIssue.ts +0 -4
- package/front_end/models/issues_manager/RelatedIssue.ts +0 -14
- package/front_end/models/javascript_metadata/NativeFunctions.js +0 -4
- package/front_end/models/web_mcp/WebMCPModel.ts +11 -2
- package/front_end/models/workspace/IgnoreListManager.ts +1 -1
- package/front_end/models/workspace/UISourceCode.ts +10 -5
- package/front_end/panels/ai_assistance/ai_assistance-meta.ts +6 -1
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +26 -9
- package/front_end/panels/application/ApplicationPanelSidebar.ts +32 -42
- package/front_end/panels/application/BackForwardCacheTreeElement.ts +2 -2
- package/front_end/panels/application/BounceTrackingMitigationsTreeElement.ts +2 -2
- package/front_end/panels/application/DOMStorageItemsView.ts +18 -13
- package/front_end/panels/application/InterestGroupTreeElement.ts +2 -2
- package/front_end/panels/application/ReportingApiTreeElement.ts +3 -3
- package/front_end/panels/application/ResourcesPanel.ts +1 -2
- package/front_end/panels/application/ServiceWorkerCacheTreeElement.ts +1 -2
- package/front_end/panels/application/StorageView.ts +1 -2
- package/front_end/panels/application/TrustTokensTreeElement.ts +2 -2
- package/front_end/panels/application/WebMCPTreeElement.ts +2 -2
- package/front_end/panels/application/WebMCPView.ts +74 -16
- package/front_end/panels/application/application.ts +0 -2
- package/front_end/panels/application/webMCPView.css +13 -2
- package/front_end/panels/console/ConsolePrompt.ts +1 -1
- package/front_end/panels/console/ConsoleView.ts +3 -4
- package/front_end/panels/elements/ColorSwatchPopoverIcon.ts +0 -152
- package/front_end/panels/elements/ElementsTreeElement.ts +4 -9
- package/front_end/panels/elements/StandaloneStylesContainer.ts +3 -0
- package/front_end/panels/elements/StylePropertiesSection.ts +0 -61
- package/front_end/panels/elements/StylePropertyTreeElement.ts +36 -23
- package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +6 -4
- package/front_end/panels/elements/StylesContainer.ts +1 -0
- package/front_end/panels/elements/StylesSidebarPane.ts +12 -7
- package/front_end/panels/elements/stylesSidebarPane.css +0 -8
- package/front_end/panels/emulation/AdvancedApp.ts +3 -3
- package/front_end/panels/emulation/DeviceModeToolbar.ts +207 -377
- package/front_end/panels/emulation/emulation-meta.ts +1 -1
- package/front_end/panels/network/NetworkPanel.ts +1 -1
- package/front_end/panels/profiler/HeapProfilerPanel.ts +1 -2
- package/front_end/panels/screencast/ScreencastApp.ts +3 -3
- package/front_end/panels/screencast/screencast-meta.ts +1 -2
- package/front_end/panels/settings/SettingsScreen.ts +2 -2
- package/front_end/panels/sources/AiCodeCompletionPlugin.ts +2 -4
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +5 -1
- package/front_end/panels/sources/SourcesNavigator.ts +1 -1
- package/front_end/panels/sources/UISourceCodeFrame.ts +1 -3
- package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +179 -145
- package/front_end/panels/timeline/TimelinePanel.ts +2 -2
- package/front_end/panels/timeline/timelineTreeView.css +2 -2
- 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/cjs/puppeteer/api/Page.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/locators/locators.d.ts +3 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/locators/locators.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/locators/locators.js +53 -23
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/locators/locators.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.d.ts +3 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js +18 -8
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserConnector.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserConnector.js +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserConnector.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js +4 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/TargetManager.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/TargetManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/TargetManager.js +54 -19
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/TargetManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/WebMCP.d.ts +5 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/WebMCP.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/WebMCP.js +2 -9
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/WebMCP.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/BrowserConnector.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/BrowserConnector.js +3 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/BrowserConnector.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConnectOptions.d.ts +37 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConnectOptions.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js +5 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js +1 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +47 -65
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +143 -55
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/locators/locators.d.ts +3 -2
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/locators/locators.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/locators/locators.js +53 -23
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/locators/locators.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.d.ts +3 -2
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js +18 -8
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserConnector.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserConnector.js +2 -2
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserConnector.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js +4 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/TargetManager.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/TargetManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/TargetManager.js +54 -19
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/TargetManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/WebMCP.d.ts +5 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/WebMCP.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/WebMCP.js +2 -9
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/WebMCP.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/BrowserConnector.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/BrowserConnector.js +3 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/BrowserConnector.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/ConnectOptions.d.ts +37 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/ConnectOptions.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js +5 -2
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js +1 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/types.d.ts +47 -65
- package/front_end/third_party/puppeteer/package/package.json +6 -6
- package/front_end/third_party/puppeteer/package/src/api/Page.ts +2 -2
- package/front_end/third_party/puppeteer/package/src/api/locators/locators.ts +69 -27
- package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +27 -8
- package/front_end/third_party/puppeteer/package/src/cdp/BrowserConnector.ts +4 -2
- package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +6 -0
- package/front_end/third_party/puppeteer/package/src/cdp/TargetManager.ts +60 -18
- package/front_end/third_party/puppeteer/package/src/cdp/WebMCP.ts +7 -9
- package/front_end/third_party/puppeteer/package/src/common/BrowserConnector.ts +3 -0
- package/front_end/third_party/puppeteer/package/src/common/ConnectOptions.ts +37 -1
- package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +7 -2
- package/front_end/third_party/puppeteer/package/src/node/ChromeLauncher.ts +1 -0
- package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
- package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
- package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +19 -14
- package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +8 -7
- package/front_end/ui/components/tooltips/Tooltip.ts +3 -3
- package/front_end/{core/common → ui/legacy}/AppProvider.ts +1 -1
- package/front_end/ui/legacy/InspectorView.ts +4 -3
- package/front_end/ui/legacy/TabbedPane.ts +1 -1
- package/front_end/ui/legacy/UIUserMetrics.ts +70 -0
- package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +1 -8
- package/front_end/ui/legacy/components/inline_editor/inline_editor.ts +0 -6
- package/front_end/ui/legacy/legacy.ts +6 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
- package/package.json +1 -1
- package/front_end/Images/src/custom-typography.svg +0 -3
- package/front_end/ui/legacy/components/inline_editor/FontEditor.ts +0 -798
- package/front_end/ui/legacy/components/inline_editor/FontEditorUnitConverter.ts +0 -250
- package/front_end/ui/legacy/components/inline_editor/FontEditorUtils.ts +0 -204
- package/front_end/ui/legacy/components/inline_editor/fontEditor.css +0 -185
- /package/front_end/{core/common → ui/legacy}/App.ts +0 -0
|
@@ -1,798 +0,0 @@
|
|
|
1
|
-
// Copyright 2020 The Chromium Authors
|
|
2
|
-
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
-
// found in the LICENSE file.
|
|
4
|
-
/* eslint-disable @devtools/no-imperative-dom-api */
|
|
5
|
-
|
|
6
|
-
import '../../legacy.js';
|
|
7
|
-
|
|
8
|
-
import * as Common from '../../../../core/common/common.js';
|
|
9
|
-
import * as i18n from '../../../../core/i18n/i18n.js';
|
|
10
|
-
import * as Platform from '../../../../core/platform/platform.js';
|
|
11
|
-
import {Icon} from '../../../kit/kit.js';
|
|
12
|
-
import * as VisualLogging from '../../../visual_logging/visual_logging.js';
|
|
13
|
-
import * as UI from '../../legacy.js';
|
|
14
|
-
|
|
15
|
-
import fontEditorStyles from './fontEditor.css.js';
|
|
16
|
-
import * as FontEditorUnitConverter from './FontEditorUnitConverter.js';
|
|
17
|
-
import * as FontEditorUtils from './FontEditorUtils.js';
|
|
18
|
-
|
|
19
|
-
const UIStrings = {
|
|
20
|
-
/**
|
|
21
|
-
* @description Font editor label for font family selector
|
|
22
|
-
*/
|
|
23
|
-
fontFamily: 'Font Family',
|
|
24
|
-
/**
|
|
25
|
-
* @description Section header for CSS property inputs
|
|
26
|
-
*/
|
|
27
|
-
cssProperties: 'CSS Properties',
|
|
28
|
-
/**
|
|
29
|
-
* @description Font size slider label for Font Editor
|
|
30
|
-
*/
|
|
31
|
-
fontSize: 'Font Size',
|
|
32
|
-
/**
|
|
33
|
-
* @description Line height slider label for Font Editor
|
|
34
|
-
*/
|
|
35
|
-
lineHeight: 'Line Height',
|
|
36
|
-
/**
|
|
37
|
-
* @description Font weight slider label for Font Editor
|
|
38
|
-
*/
|
|
39
|
-
fontWeight: 'Font Weight',
|
|
40
|
-
/**
|
|
41
|
-
* @description Label for letter-spacing labels
|
|
42
|
-
*/
|
|
43
|
-
spacing: 'Spacing',
|
|
44
|
-
/**
|
|
45
|
-
* @description Label for numbered fallback selectors
|
|
46
|
-
* @example {2} PH1
|
|
47
|
-
*/
|
|
48
|
-
fallbackS: 'Fallback {PH1}',
|
|
49
|
-
/**
|
|
50
|
-
* @description Announcement for deleting an empty font family selector in the Font Editor
|
|
51
|
-
* @example {2} PH1
|
|
52
|
-
*/
|
|
53
|
-
thereIsNoValueToDeleteAtIndexS: 'There is no value to delete at index: {PH1}',
|
|
54
|
-
/**
|
|
55
|
-
* @description Announcement when deleting a font selector in the Font Editor
|
|
56
|
-
* @example {2} PH1
|
|
57
|
-
*/
|
|
58
|
-
fontSelectorDeletedAtIndexS: 'Font Selector deleted at index: {PH1}',
|
|
59
|
-
/**
|
|
60
|
-
* @description Label for Font Editor button to delete font family/fallback selectors
|
|
61
|
-
* @example {Fallback 1} PH1
|
|
62
|
-
*/
|
|
63
|
-
deleteS: 'Delete {PH1}',
|
|
64
|
-
/**
|
|
65
|
-
* @description Warning message for Font Editor invalid text input. The placeholder is the name of
|
|
66
|
-
* the CSS attribute that is incorrect.
|
|
67
|
-
* @example {font-size} PH1
|
|
68
|
-
*/
|
|
69
|
-
PleaseEnterAValidValueForSText: '* Please enter a valid value for {PH1} text input',
|
|
70
|
-
/**
|
|
71
|
-
* @description Error text in Font Editor
|
|
72
|
-
* @example {font-size} PH1
|
|
73
|
-
*/
|
|
74
|
-
thisPropertyIsSetToContainUnits:
|
|
75
|
-
'This property is set to contain units but does not have a defined corresponding unitsArray: {PH1}',
|
|
76
|
-
/**
|
|
77
|
-
* @description Label for slider input in the Font Editor.
|
|
78
|
-
* @example {font-size} PH1
|
|
79
|
-
*/
|
|
80
|
-
sSliderInput: '{PH1} Slider Input',
|
|
81
|
-
/**
|
|
82
|
-
* @description Accessible label for a text input for a property in the Font Editor.
|
|
83
|
-
* @example {font-size} PH1
|
|
84
|
-
*/
|
|
85
|
-
sTextInput: '{PH1} Text Input',
|
|
86
|
-
/**
|
|
87
|
-
* @description Font Editor units text box label
|
|
88
|
-
*/
|
|
89
|
-
units: 'Units',
|
|
90
|
-
/**
|
|
91
|
-
* @description Accessible name for Font Editor unit input. The placeholder is the name of the font
|
|
92
|
-
* property that this UI input controls. e.g. font-size, line-height, line-weight.
|
|
93
|
-
* @example {font-size} PH1
|
|
94
|
-
*/
|
|
95
|
-
sUnitInput: '{PH1} Unit Input',
|
|
96
|
-
/**
|
|
97
|
-
* @description Text used in the Font Editor for the key values selector
|
|
98
|
-
* @example {font-size} PH1
|
|
99
|
-
*/
|
|
100
|
-
sKeyValueSelector: '{PH1} Key Value Selector',
|
|
101
|
-
/**
|
|
102
|
-
* @description Label for Font Editor toggle input type button. The placeholder is the name of the
|
|
103
|
-
* font property that this UI input controls. e.g. font-size, line-height, line-weight. Tooltip for
|
|
104
|
-
* a button next to the text input which allows the user to change the input type. When they click
|
|
105
|
-
* this button, the UI changes to allow the user to choose from a list of pre-selected font
|
|
106
|
-
* categories.
|
|
107
|
-
* @example {font-size} PH1
|
|
108
|
-
*/
|
|
109
|
-
sToggleInputType: '{PH1} toggle input type',
|
|
110
|
-
/**
|
|
111
|
-
* @description Label for Font Editor alert in CSS Properties section when toggling inputs
|
|
112
|
-
*/
|
|
113
|
-
selectorInputMode: 'Selector Input Mode',
|
|
114
|
-
/**
|
|
115
|
-
* @description Label for Font Editor alert in CSS Properties section when toggling inputs
|
|
116
|
-
*/
|
|
117
|
-
sliderInputMode: 'Slider Input Mode',
|
|
118
|
-
} as const;
|
|
119
|
-
const str_ = i18n.i18n.registerUIStrings('ui/legacy/components/inline_editor/FontEditor.ts', UIStrings);
|
|
120
|
-
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
121
|
-
|
|
122
|
-
export class FontEditor extends Common.ObjectWrapper.eventMixin<EventTypes, typeof UI.Widget.VBox>(UI.Widget.VBox) {
|
|
123
|
-
private readonly propertyMap: Map<string, string>;
|
|
124
|
-
private readonly fontSelectorSection: HTMLElement;
|
|
125
|
-
private fontSelectors: FontEditor.FontSelectorObject[];
|
|
126
|
-
private fontsList: Array<Map<string, string[]>>|null;
|
|
127
|
-
|
|
128
|
-
constructor(propertyMap: Map<string, string>) {
|
|
129
|
-
super({useShadowDom: true});
|
|
130
|
-
this.registerRequiredCSS(fontEditorStyles);
|
|
131
|
-
this.propertyMap = propertyMap;
|
|
132
|
-
this.contentElement.tabIndex = 0;
|
|
133
|
-
this.contentElement.setAttribute(
|
|
134
|
-
'jslog', `${VisualLogging.dialog('font-editor').parent('mapped').track({keydown: 'Enter|Escape'})}`);
|
|
135
|
-
this.setDefaultFocusedElement(this.contentElement);
|
|
136
|
-
|
|
137
|
-
// Font Selector Section
|
|
138
|
-
this.fontSelectorSection = this.contentElement.createChild('div', 'font-selector-section');
|
|
139
|
-
this.fontSelectorSection.createChild('h2', 'font-section-header').textContent = i18nString(UIStrings.fontFamily);
|
|
140
|
-
|
|
141
|
-
this.fontSelectors = [];
|
|
142
|
-
|
|
143
|
-
this.fontsList = null;
|
|
144
|
-
|
|
145
|
-
const propertyValue: string|undefined = this.propertyMap.get('font-family');
|
|
146
|
-
|
|
147
|
-
void this.createFontSelectorSection(propertyValue);
|
|
148
|
-
|
|
149
|
-
// CSS Font Property Section
|
|
150
|
-
const cssPropertySection = this.contentElement.createChild('div', 'font-section');
|
|
151
|
-
cssPropertySection.createChild('h2', 'font-section-header').textContent = i18nString(UIStrings.cssProperties);
|
|
152
|
-
|
|
153
|
-
// The regexes only handle valid property values as invalid values are not passed into the property map.
|
|
154
|
-
const fontSizePropertyInfo = this.getPropertyInfo('font-size', FontEditorUtils.FontSizeStaticParams.regex);
|
|
155
|
-
|
|
156
|
-
const lineHeightPropertyInfo = this.getPropertyInfo('line-height', FontEditorUtils.LineHeightStaticParams.regex);
|
|
157
|
-
|
|
158
|
-
const fontWeightPropertyInfo = this.getPropertyInfo('font-weight', FontEditorUtils.FontWeightStaticParams.regex);
|
|
159
|
-
|
|
160
|
-
const letterSpacingPropertyInfo =
|
|
161
|
-
this.getPropertyInfo('letter-spacing', FontEditorUtils.LetterSpacingStaticParams.regex);
|
|
162
|
-
|
|
163
|
-
new FontPropertyInputs(
|
|
164
|
-
'font-size', i18nString(UIStrings.fontSize), cssPropertySection, fontSizePropertyInfo,
|
|
165
|
-
FontEditorUtils.FontSizeStaticParams, this.updatePropertyValue.bind(this), this.resizePopout.bind(this),
|
|
166
|
-
/** hasUnits= */ true);
|
|
167
|
-
new FontPropertyInputs(
|
|
168
|
-
'line-height', i18nString(UIStrings.lineHeight), cssPropertySection, lineHeightPropertyInfo,
|
|
169
|
-
FontEditorUtils.LineHeightStaticParams, this.updatePropertyValue.bind(this), this.resizePopout.bind(this),
|
|
170
|
-
/** hasUnits= */ true);
|
|
171
|
-
new FontPropertyInputs(
|
|
172
|
-
'font-weight', i18nString(UIStrings.fontWeight), cssPropertySection, fontWeightPropertyInfo,
|
|
173
|
-
FontEditorUtils.FontWeightStaticParams, this.updatePropertyValue.bind(this), this.resizePopout.bind(this),
|
|
174
|
-
/** hasUnits= */ false);
|
|
175
|
-
new FontPropertyInputs(
|
|
176
|
-
'letter-spacing', i18nString(UIStrings.spacing), cssPropertySection, letterSpacingPropertyInfo,
|
|
177
|
-
FontEditorUtils.LetterSpacingStaticParams, this.updatePropertyValue.bind(this), this.resizePopout.bind(this),
|
|
178
|
-
/** hasUnits= */ true);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
private async createFontSelectorSection(propertyValue?: string): Promise<void> {
|
|
182
|
-
if (propertyValue) {
|
|
183
|
-
// FIXME(crbug.com/1148434): propertyValue will not be split correctly for font family names that contain commas.
|
|
184
|
-
// e.g. font-family: "Name,with,commas"
|
|
185
|
-
const splitValue = propertyValue.split(',');
|
|
186
|
-
await this.createFontSelector(splitValue[0], /* isPrimary= */ true);
|
|
187
|
-
if (!FontEditorUtils.GlobalValues.includes(splitValue[0])) {
|
|
188
|
-
// We add one to the splitValue length so that we have an additional empty fallback selector
|
|
189
|
-
for (let i = 1; i < splitValue.length + 1; i++) {
|
|
190
|
-
void this.createFontSelector(splitValue[i]);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
} else {
|
|
194
|
-
void this.createFontSelector('', true);
|
|
195
|
-
}
|
|
196
|
-
this.resizePopout();
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
private async createFontsList(): Promise<Array<Map<string, string[]>>> {
|
|
200
|
-
const computedFontArray = await FontEditorUtils.generateComputedFontArray();
|
|
201
|
-
const computedMap = new Map<string, string[]>();
|
|
202
|
-
const splicedArray = this.splitComputedFontArray(computedFontArray);
|
|
203
|
-
|
|
204
|
-
computedMap.set('Computed Fonts', splicedArray);
|
|
205
|
-
const systemMap = new Map<string, string[]>();
|
|
206
|
-
systemMap.set('System Fonts', FontEditorUtils.SystemFonts);
|
|
207
|
-
systemMap.set('Generic Families', FontEditorUtils.GenericFonts);
|
|
208
|
-
|
|
209
|
-
const fontList = [];
|
|
210
|
-
fontList.push(computedMap);
|
|
211
|
-
fontList.push(systemMap);
|
|
212
|
-
return fontList;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
private splitComputedFontArray(computedFontArray: string[]): string[] {
|
|
216
|
-
const array: string[] = [];
|
|
217
|
-
for (const fontFamilyValue of computedFontArray) {
|
|
218
|
-
if (fontFamilyValue.includes(',')) {
|
|
219
|
-
const fonts = fontFamilyValue.split(',');
|
|
220
|
-
fonts.forEach(element => {
|
|
221
|
-
if (array.findIndex(item => item.toLowerCase() === element.trim().toLowerCase().replace(/"/g, '\'')) === -1) {
|
|
222
|
-
array.push(element.trim().replace(/"/g, ''));
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
} else if (
|
|
226
|
-
array.findIndex(item => item.toLowerCase() === fontFamilyValue.toLowerCase().replace('"', '\'')) === -1) {
|
|
227
|
-
array.push(fontFamilyValue.replace(/"/g, ''));
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
return array;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
private async createFontSelector(value: string, isPrimary?: boolean): Promise<void> {
|
|
234
|
-
// FIXME(crbug.com/1148434): Custom font family names that use single/double quotes in the font family name will not be handled correctly.
|
|
235
|
-
// e.g. font-family: "FontWith\"DoubleQuotes"
|
|
236
|
-
value = value ? value.trim() : '';
|
|
237
|
-
if (value) {
|
|
238
|
-
const firstChar = value.charAt(0);
|
|
239
|
-
if (firstChar === '\'') {
|
|
240
|
-
value = value.replace(/'/g, '');
|
|
241
|
-
} else if (firstChar === '"') {
|
|
242
|
-
value = value.replace(/"/g, '');
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
const selectorField = this.fontSelectorSection.createChild('div', 'shadow-editor-field shadow-editor-flex-field');
|
|
246
|
-
if (!this.fontsList) {
|
|
247
|
-
this.fontsList = await this.createFontsList();
|
|
248
|
-
}
|
|
249
|
-
let label;
|
|
250
|
-
if (isPrimary) {
|
|
251
|
-
label = i18nString(UIStrings.fontFamily);
|
|
252
|
-
const globalValuesMap = new Map([['Global Values', FontEditorUtils.GlobalValues]]);
|
|
253
|
-
const primaryFontList = [...this.fontsList];
|
|
254
|
-
primaryFontList.push(globalValuesMap);
|
|
255
|
-
this.createSelector(selectorField, label, primaryFontList, value.trim(), 'primary-font-family');
|
|
256
|
-
} else {
|
|
257
|
-
label = i18nString(UIStrings.fallbackS, {PH1: this.fontSelectors.length});
|
|
258
|
-
this.createSelector(selectorField, label, this.fontsList, value.trim(), 'fallback-font-family');
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
private deleteFontSelector(index: number, isGlobalValue?: boolean): void {
|
|
263
|
-
let fontSelectorObject: FontEditor.FontSelectorObject = this.fontSelectors[index];
|
|
264
|
-
const isPrimary = index === 0;
|
|
265
|
-
if (fontSelectorObject.input.value === '' && !isGlobalValue) {
|
|
266
|
-
UI.ARIAUtils.LiveAnnouncer.alert(i18nString(UIStrings.thereIsNoValueToDeleteAtIndexS, {PH1: index}));
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
if (isPrimary) {
|
|
270
|
-
// When deleting the primary font selector, we overwrite the value of the primary selector
|
|
271
|
-
// with the value of the secondary selector and delete the secondary selector.
|
|
272
|
-
const secondarySelector = this.fontSelectors[1];
|
|
273
|
-
let newPrimarySelectorValue = '';
|
|
274
|
-
if (secondarySelector) {
|
|
275
|
-
newPrimarySelectorValue = secondarySelector.input.value;
|
|
276
|
-
fontSelectorObject = secondarySelector;
|
|
277
|
-
}
|
|
278
|
-
const primarySelector = this.fontSelectors[0].input;
|
|
279
|
-
primarySelector.value = newPrimarySelectorValue;
|
|
280
|
-
index = 1;
|
|
281
|
-
}
|
|
282
|
-
if (fontSelectorObject.input.parentNode) {
|
|
283
|
-
const hasSecondarySelector = this.fontSelectors.length > 1;
|
|
284
|
-
if (!isPrimary || hasSecondarySelector) {
|
|
285
|
-
const selectorElement = fontSelectorObject.input.parentElement;
|
|
286
|
-
if (selectorElement) {
|
|
287
|
-
selectorElement.remove();
|
|
288
|
-
this.fontSelectors.splice(index, 1);
|
|
289
|
-
this.updateFontSelectorList();
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
UI.ARIAUtils.LiveAnnouncer.alert(i18nString(UIStrings.fontSelectorDeletedAtIndexS, {PH1: index}));
|
|
293
|
-
}
|
|
294
|
-
this.onFontSelectorChanged();
|
|
295
|
-
this.resizePopout();
|
|
296
|
-
const focusIndex = isPrimary ? 0 : index - 1;
|
|
297
|
-
this.fontSelectors[focusIndex].input.focus();
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
private updateFontSelectorList(): void {
|
|
301
|
-
for (let i = 0; i < this.fontSelectors.length; i++) {
|
|
302
|
-
const fontSelectorObject = this.fontSelectors[i];
|
|
303
|
-
let label;
|
|
304
|
-
if (i === 0) {
|
|
305
|
-
label = i18nString(UIStrings.fontFamily);
|
|
306
|
-
} else {
|
|
307
|
-
label = i18nString(UIStrings.fallbackS, {PH1: i});
|
|
308
|
-
}
|
|
309
|
-
fontSelectorObject.label.textContent = label;
|
|
310
|
-
UI.ARIAUtils.setLabel(fontSelectorObject.input, label);
|
|
311
|
-
fontSelectorObject.deleteButton.setTitle(i18nString(UIStrings.deleteS, {PH1: label}));
|
|
312
|
-
fontSelectorObject.index = i;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
private getPropertyInfo(name: string, regex: RegExp): FontEditor.PropertyInfo {
|
|
317
|
-
const value = this.propertyMap.get(name);
|
|
318
|
-
if (value) {
|
|
319
|
-
const valueString = value;
|
|
320
|
-
const match = valueString.match(regex);
|
|
321
|
-
if (match) {
|
|
322
|
-
const retValue = match[1].charAt(0) === '+' ? match[1].substr(1) : match[1];
|
|
323
|
-
const retUnits = match[2] ? match[2] : '';
|
|
324
|
-
return {value: retValue, units: retUnits};
|
|
325
|
-
}
|
|
326
|
-
return {value: valueString, units: null};
|
|
327
|
-
}
|
|
328
|
-
return {value: null, units: null};
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
private createSelector(
|
|
332
|
-
field: Element, label: string, options: Array<Map<string, string[]>>, currentValue: string,
|
|
333
|
-
jslogContext: string): void {
|
|
334
|
-
const index = this.fontSelectors.length;
|
|
335
|
-
const selectInput = (UI.UIUtils.createSelect(label, options));
|
|
336
|
-
selectInput.value = currentValue;
|
|
337
|
-
selectInput.setAttribute('jslog', `${VisualLogging.dropDown(jslogContext).track({click: true, change: true})}`);
|
|
338
|
-
const selectLabel = UI.UIUtils.createLabel(label, 'shadow-editor-label', selectInput);
|
|
339
|
-
selectInput.addEventListener('input', this.onFontSelectorChanged.bind(this), false);
|
|
340
|
-
// We want to prevent the Enter key from propagating to the SwatchPopoverHelper which will close the editor.
|
|
341
|
-
selectInput.addEventListener('keydown', (event: KeyboardEvent) => {
|
|
342
|
-
if (event.key === 'Enter') {
|
|
343
|
-
event.consume();
|
|
344
|
-
}
|
|
345
|
-
}, false);
|
|
346
|
-
field.appendChild(selectLabel);
|
|
347
|
-
field.appendChild(selectInput);
|
|
348
|
-
|
|
349
|
-
const deleteToolbar = field.createChild('devtools-toolbar');
|
|
350
|
-
const deleteButton =
|
|
351
|
-
new UI.Toolbar.ToolbarButton(i18nString(UIStrings.deleteS, {PH1: label}), 'bin', undefined, 'delete');
|
|
352
|
-
deleteToolbar.appendToolbarItem(deleteButton);
|
|
353
|
-
const fontSelectorObject = {label: selectLabel, input: selectInput, deleteButton, index};
|
|
354
|
-
deleteButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {
|
|
355
|
-
this.deleteFontSelector(fontSelectorObject.index);
|
|
356
|
-
});
|
|
357
|
-
deleteButton.element.addEventListener('keydown', (event: KeyboardEvent) => {
|
|
358
|
-
if (Platform.KeyboardUtilities.isEnterOrSpaceKey(event)) {
|
|
359
|
-
this.deleteFontSelector(fontSelectorObject.index);
|
|
360
|
-
event.consume();
|
|
361
|
-
}
|
|
362
|
-
}, false);
|
|
363
|
-
this.fontSelectors.push(fontSelectorObject);
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
private onFontSelectorChanged(): void {
|
|
367
|
-
let value = '';
|
|
368
|
-
const isGlobalValue = FontEditorUtils.GlobalValues.includes(this.fontSelectors[0].input.value);
|
|
369
|
-
|
|
370
|
-
if (isGlobalValue) {
|
|
371
|
-
for (let i = 1; i < this.fontSelectors.length; i++) {
|
|
372
|
-
this.deleteFontSelector(i, /** isGlobalValue= */ true);
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
for (const fontSelector of this.fontSelectors) {
|
|
376
|
-
const fontSelectorInput = fontSelector.input;
|
|
377
|
-
if (fontSelectorInput.value !== '') {
|
|
378
|
-
if (value === '') {
|
|
379
|
-
value = this.fontSelectors[0].input.value;
|
|
380
|
-
} else {
|
|
381
|
-
value += ', ' + fontSelectorInput.value;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
// Add an extra blank selector as long as the last selector doesn't have an empty value, the primary
|
|
386
|
-
// selector's value is not a global value and if the list of selectors has not exceeded 10.
|
|
387
|
-
if (this.fontSelectors[this.fontSelectors.length - 1].input.value !== '' && !isGlobalValue &&
|
|
388
|
-
this.fontSelectors.length < 10) {
|
|
389
|
-
void this.createFontSelector(/** value= */ '');
|
|
390
|
-
this.resizePopout();
|
|
391
|
-
}
|
|
392
|
-
this.updatePropertyValue('font-family', value);
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
private updatePropertyValue(propertyName: string, value: string): void {
|
|
396
|
-
this.dispatchEventToListeners(Events.FONT_CHANGED, {propertyName, value});
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
private resizePopout(): void {
|
|
400
|
-
this.dispatchEventToListeners(Events.FONT_EDITOR_RESIZED);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
namespace FontEditor {
|
|
405
|
-
export interface PropertyInfo {
|
|
406
|
-
value: string|null;
|
|
407
|
-
units: string|null;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
export interface FontSelectorObject {
|
|
411
|
-
label: Element;
|
|
412
|
-
input: HTMLSelectElement;
|
|
413
|
-
deleteButton: UI.Toolbar.ToolbarButton;
|
|
414
|
-
index: number;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
export interface PropertyRange {
|
|
418
|
-
min: number;
|
|
419
|
-
max: number;
|
|
420
|
-
step: number;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
export interface FontPropertyInputStaticParams {
|
|
424
|
-
regex: RegExp;
|
|
425
|
-
units: Set<string>|null;
|
|
426
|
-
keyValues: Set<string>;
|
|
427
|
-
rangeMap: Map<string, FontEditor.PropertyRange>;
|
|
428
|
-
defaultUnit: string|null;
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
export const enum Events {
|
|
433
|
-
FONT_CHANGED = 'FontChanged',
|
|
434
|
-
FONT_EDITOR_RESIZED = 'FontEditorResized',
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
export interface FontChangedEvent {
|
|
438
|
-
propertyName: string;
|
|
439
|
-
value: string;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
export interface EventTypes {
|
|
443
|
-
[Events.FONT_CHANGED]: FontChangedEvent;
|
|
444
|
-
[Events.FONT_EDITOR_RESIZED]: void;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
class FontPropertyInputs {
|
|
448
|
-
private showSliderMode: boolean;
|
|
449
|
-
private errorText: HTMLElement;
|
|
450
|
-
private propertyInfo: FontEditor.PropertyInfo;
|
|
451
|
-
private readonly propertyName: string;
|
|
452
|
-
private readonly staticParams: FontEditor.FontPropertyInputStaticParams;
|
|
453
|
-
private readonly hasUnits: boolean|undefined;
|
|
454
|
-
private units: string;
|
|
455
|
-
private readonly addedUnit: boolean|undefined;
|
|
456
|
-
private initialRange: FontEditor.PropertyRange;
|
|
457
|
-
private readonly boundUpdateCallback: (arg0: string, arg1: string) => void;
|
|
458
|
-
private readonly boundResizeCallback: () => void;
|
|
459
|
-
private sliderInput: HTMLInputElement;
|
|
460
|
-
private textBoxInput: HTMLInputElement;
|
|
461
|
-
private unitInput: HTMLSelectElement;
|
|
462
|
-
private selectorInput: HTMLSelectElement;
|
|
463
|
-
private applyNextInput: boolean;
|
|
464
|
-
|
|
465
|
-
constructor(
|
|
466
|
-
propertyName: string, label: string, field: Element, propertyInfo: FontEditor.PropertyInfo,
|
|
467
|
-
staticParams: FontEditor.FontPropertyInputStaticParams, updateCallback: (arg0: string, arg1: string) => void,
|
|
468
|
-
resizeCallback: () => void, hasUnits?: boolean) {
|
|
469
|
-
this.showSliderMode = true;
|
|
470
|
-
const propertyField = field.createChild('div', 'shadow-editor-field shadow-editor-flex-field');
|
|
471
|
-
this.errorText = field.createChild('div', 'error-text');
|
|
472
|
-
this.errorText.textContent = i18nString(UIStrings.PleaseEnterAValidValueForSText, {PH1: propertyName});
|
|
473
|
-
this.errorText.hidden = true;
|
|
474
|
-
UI.ARIAUtils.markAsAlert(this.errorText);
|
|
475
|
-
this.propertyInfo = propertyInfo;
|
|
476
|
-
this.propertyName = propertyName;
|
|
477
|
-
this.staticParams = staticParams;
|
|
478
|
-
|
|
479
|
-
// Unit handling
|
|
480
|
-
this.hasUnits = hasUnits;
|
|
481
|
-
if (this.hasUnits && this.staticParams.units && this.staticParams.defaultUnit !== null) {
|
|
482
|
-
const defaultUnits = this.staticParams.defaultUnit;
|
|
483
|
-
this.units = propertyInfo.units !== null ? propertyInfo.units : defaultUnits;
|
|
484
|
-
this.addedUnit = !this.staticParams.units.has(this.units);
|
|
485
|
-
} else if (this.hasUnits) {
|
|
486
|
-
throw new Error(i18nString(UIStrings.thisPropertyIsSetToContainUnits, {PH1: propertyName}));
|
|
487
|
-
} else {
|
|
488
|
-
this.units = '';
|
|
489
|
-
}
|
|
490
|
-
this.initialRange = this.getUnitRange();
|
|
491
|
-
|
|
492
|
-
this.boundUpdateCallback = updateCallback;
|
|
493
|
-
this.boundResizeCallback = resizeCallback;
|
|
494
|
-
const propertyLabel = UI.UIUtils.createLabel(label, 'shadow-editor-label');
|
|
495
|
-
propertyField.append(propertyLabel);
|
|
496
|
-
this.sliderInput = this.createSliderInput(propertyField, propertyName);
|
|
497
|
-
this.textBoxInput = this.createTextBoxInput(propertyField, propertyName);
|
|
498
|
-
UI.ARIAUtils.bindLabelToControl(propertyLabel, this.textBoxInput);
|
|
499
|
-
this.unitInput = this.createUnitInput(propertyField, `${propertyName}-unit`);
|
|
500
|
-
this.selectorInput = this.createSelectorInput(propertyField, propertyName);
|
|
501
|
-
this.createTypeToggle(propertyField, `${propertyName}-value-type`);
|
|
502
|
-
this.checkSelectorValueAndToggle();
|
|
503
|
-
this.applyNextInput = false;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
private setInvalidTextBoxInput(invalid: boolean): void {
|
|
507
|
-
if (invalid) {
|
|
508
|
-
if (this.errorText.hidden) {
|
|
509
|
-
this.errorText.hidden = false;
|
|
510
|
-
this.textBoxInput.classList.add('error-input');
|
|
511
|
-
this.boundResizeCallback();
|
|
512
|
-
}
|
|
513
|
-
} else if (!this.errorText.hidden) {
|
|
514
|
-
this.errorText.hidden = true;
|
|
515
|
-
this.textBoxInput.classList.remove('error-input');
|
|
516
|
-
this.boundResizeCallback();
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
private checkSelectorValueAndToggle(): boolean {
|
|
521
|
-
if (this.staticParams.keyValues && this.propertyInfo.value !== null &&
|
|
522
|
-
(this.staticParams.keyValues.has(this.propertyInfo.value))) {
|
|
523
|
-
this.toggleInputType();
|
|
524
|
-
return true;
|
|
525
|
-
}
|
|
526
|
-
return false;
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
private getUnitRange(): FontEditor.PropertyRange {
|
|
530
|
-
let min = 0;
|
|
531
|
-
let max = 100;
|
|
532
|
-
let step = 1;
|
|
533
|
-
if (this.propertyInfo.value !== null && /\d/.test(this.propertyInfo.value)) {
|
|
534
|
-
if (this.staticParams.rangeMap.get(this.units)) {
|
|
535
|
-
const unitRangeMap = this.staticParams.rangeMap.get(this.units);
|
|
536
|
-
if (unitRangeMap) {
|
|
537
|
-
min = Math.min(unitRangeMap.min, parseFloat(this.propertyInfo.value));
|
|
538
|
-
max = Math.max(unitRangeMap.max, parseFloat(this.propertyInfo.value));
|
|
539
|
-
step = unitRangeMap.step;
|
|
540
|
-
}
|
|
541
|
-
} else {
|
|
542
|
-
const unitRangeMap = this.staticParams.rangeMap.get('px');
|
|
543
|
-
if (unitRangeMap) {
|
|
544
|
-
min = Math.min(unitRangeMap.min, parseFloat(this.propertyInfo.value));
|
|
545
|
-
max = Math.max(unitRangeMap.max, parseFloat(this.propertyInfo.value));
|
|
546
|
-
step = unitRangeMap.step;
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
} else {
|
|
550
|
-
const unitRangeMap = this.staticParams.rangeMap.get(this.units);
|
|
551
|
-
if (unitRangeMap) {
|
|
552
|
-
min = unitRangeMap.min;
|
|
553
|
-
max = unitRangeMap.max;
|
|
554
|
-
step = unitRangeMap.step;
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
return {min, max, step};
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
private createSliderInput(field: Element, jslogContext: string): HTMLInputElement {
|
|
561
|
-
const min = this.initialRange.min;
|
|
562
|
-
const max = this.initialRange.max;
|
|
563
|
-
const step = this.initialRange.step;
|
|
564
|
-
|
|
565
|
-
const slider = UI.UIUtils.createSlider(min, max, -1);
|
|
566
|
-
slider.step = step.toString();
|
|
567
|
-
slider.tabIndex = 0;
|
|
568
|
-
if (this.propertyInfo.value) {
|
|
569
|
-
slider.value = this.propertyInfo.value;
|
|
570
|
-
} else {
|
|
571
|
-
const newValue = (min + max) / 2;
|
|
572
|
-
slider.value = newValue.toString();
|
|
573
|
-
}
|
|
574
|
-
slider.addEventListener('input', event => {
|
|
575
|
-
this.onSliderInput(event, /** apply= */ false);
|
|
576
|
-
});
|
|
577
|
-
|
|
578
|
-
slider.addEventListener('mouseup', event => {
|
|
579
|
-
this.onSliderInput(event, /** apply= */ true);
|
|
580
|
-
});
|
|
581
|
-
slider.addEventListener('keydown', event => {
|
|
582
|
-
if (event.key === 'ArrowUp' || event.key === 'ArrowDown' || event.key === 'ArrowLeft' ||
|
|
583
|
-
event.key === 'ArrowRight') {
|
|
584
|
-
// Pressing an arrow key will trigger two events for the slider: A keyboard event and an input event
|
|
585
|
-
// The keyboard event will come before the slider value has changed and the subsequent input event will cause
|
|
586
|
-
// the value to change. We use the applyNextInput boolean to tell onSliderInput that the next input event
|
|
587
|
-
// is coming because of the keyboard event and that it should be applied to the section.
|
|
588
|
-
this.applyNextInput = true;
|
|
589
|
-
}
|
|
590
|
-
});
|
|
591
|
-
field.appendChild(slider);
|
|
592
|
-
UI.ARIAUtils.setLabel(slider, i18nString(UIStrings.sSliderInput, {PH1: this.propertyName}));
|
|
593
|
-
slider.setAttribute('jslog', `${VisualLogging.slider(jslogContext).track({change: true})}`);
|
|
594
|
-
return slider;
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
private createTextBoxInput(field: Element, jslogContext: string): HTMLInputElement {
|
|
598
|
-
const textBoxInput: HTMLInputElement = UI.UIUtils.createInput('shadow-editor-text-input', 'number', jslogContext);
|
|
599
|
-
|
|
600
|
-
textBoxInput.step = this.initialRange.step.toString();
|
|
601
|
-
textBoxInput.classList.add('font-editor-text-input');
|
|
602
|
-
if (this.propertyInfo.value !== null) {
|
|
603
|
-
if (this.propertyInfo.value.charAt(0) === '+') {
|
|
604
|
-
this.propertyInfo.value = this.propertyInfo.value.substr(1);
|
|
605
|
-
}
|
|
606
|
-
textBoxInput.value = this.propertyInfo.value;
|
|
607
|
-
}
|
|
608
|
-
textBoxInput.step = 'any';
|
|
609
|
-
textBoxInput.addEventListener('input', this.onTextBoxInput.bind(this), false);
|
|
610
|
-
field.appendChild(textBoxInput);
|
|
611
|
-
UI.ARIAUtils.setLabel(textBoxInput, i18nString(UIStrings.sTextInput, {PH1: this.propertyName}));
|
|
612
|
-
return textBoxInput;
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
private createUnitInput(field: Element, jslogContext: string): HTMLSelectElement {
|
|
616
|
-
let unitInput;
|
|
617
|
-
if (this.hasUnits && this.staticParams.units) {
|
|
618
|
-
const currentValue = this.propertyInfo.units;
|
|
619
|
-
const options = this.staticParams.units;
|
|
620
|
-
unitInput = UI.UIUtils.createSelect(i18nString(UIStrings.units), options);
|
|
621
|
-
unitInput.classList.add('font-editor-select');
|
|
622
|
-
if (this.addedUnit && currentValue) {
|
|
623
|
-
unitInput.add(new Option(currentValue, currentValue));
|
|
624
|
-
}
|
|
625
|
-
if (currentValue) {
|
|
626
|
-
unitInput.value = currentValue;
|
|
627
|
-
}
|
|
628
|
-
unitInput.addEventListener('change', this.onUnitInput.bind(this), false);
|
|
629
|
-
} else {
|
|
630
|
-
unitInput = UI.UIUtils.createSelect(i18nString(UIStrings.units), []);
|
|
631
|
-
unitInput.classList.add('font-editor-select');
|
|
632
|
-
unitInput.disabled = true;
|
|
633
|
-
}
|
|
634
|
-
unitInput.setAttribute('jslog', `${VisualLogging.dropDown(jslogContext).track({click: true, change: true})}`);
|
|
635
|
-
// We want to prevent the Enter key from propagating to the SwatchPopoverHelper which will close the editor.
|
|
636
|
-
unitInput.addEventListener('keydown', (event: KeyboardEvent) => {
|
|
637
|
-
if (event.key === 'Enter') {
|
|
638
|
-
event.consume();
|
|
639
|
-
}
|
|
640
|
-
}, false);
|
|
641
|
-
field.appendChild(unitInput);
|
|
642
|
-
UI.ARIAUtils.setLabel(unitInput, i18nString(UIStrings.sUnitInput, {PH1: this.propertyName}));
|
|
643
|
-
|
|
644
|
-
return unitInput;
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
private createSelectorInput(field: Element, jslogContext: string): HTMLSelectElement {
|
|
648
|
-
const selectInput: HTMLSelectElement = UI.UIUtils.createSelect(
|
|
649
|
-
i18nString(UIStrings.sKeyValueSelector, {PH1: this.propertyName}), this.staticParams.keyValues);
|
|
650
|
-
selectInput.classList.add('font-selector-input');
|
|
651
|
-
if (this.propertyInfo.value) {
|
|
652
|
-
selectInput.value = this.propertyInfo.value;
|
|
653
|
-
}
|
|
654
|
-
selectInput.addEventListener('input', this.onSelectorInput.bind(this), false);
|
|
655
|
-
// We want to prevent the Enter key from propagating to the SwatchPopoverHelper which will close the editor.
|
|
656
|
-
selectInput.addEventListener('keydown', (event: KeyboardEvent) => {
|
|
657
|
-
if (event.key === 'Enter') {
|
|
658
|
-
event.consume();
|
|
659
|
-
}
|
|
660
|
-
}, false);
|
|
661
|
-
field.appendChild(selectInput);
|
|
662
|
-
selectInput.hidden = true;
|
|
663
|
-
selectInput.setAttribute('jslog', `${VisualLogging.dropDown(jslogContext).track({click: true, change: true})}`);
|
|
664
|
-
return selectInput;
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
private onSelectorInput(event: Event): void {
|
|
668
|
-
if (event.currentTarget) {
|
|
669
|
-
const value = (event.currentTarget as HTMLInputElement).value;
|
|
670
|
-
this.textBoxInput.value = '';
|
|
671
|
-
const newValue = (parseFloat(this.sliderInput.min) + parseFloat(this.sliderInput.max)) / 2;
|
|
672
|
-
this.sliderInput.value = newValue.toString();
|
|
673
|
-
this.setInvalidTextBoxInput(false);
|
|
674
|
-
this.boundUpdateCallback(this.propertyName, value);
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
private onSliderInput(event: Event, apply: boolean): void {
|
|
679
|
-
const target = (event.currentTarget as HTMLInputElement);
|
|
680
|
-
if (target) {
|
|
681
|
-
const value = target.value;
|
|
682
|
-
this.textBoxInput.value = value;
|
|
683
|
-
this.selectorInput.value = '';
|
|
684
|
-
const valueString = this.hasUnits ? value + this.unitInput.value : value.toString();
|
|
685
|
-
this.setInvalidTextBoxInput(false);
|
|
686
|
-
if (apply || this.applyNextInput) {
|
|
687
|
-
this.boundUpdateCallback(this.propertyName, valueString);
|
|
688
|
-
this.applyNextInput = false;
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
private onTextBoxInput(event: Event): void {
|
|
694
|
-
const target = (event.currentTarget as HTMLInputElement);
|
|
695
|
-
if (target) {
|
|
696
|
-
const value = target.value;
|
|
697
|
-
const units = value === '' ? '' : this.unitInput.value;
|
|
698
|
-
const valueString = value + units;
|
|
699
|
-
if (this.staticParams.regex.test(valueString) || (value === '' && !target.validationMessage.length)) {
|
|
700
|
-
if (parseFloat(value) > parseFloat(this.sliderInput.max)) {
|
|
701
|
-
this.sliderInput.max = value;
|
|
702
|
-
} else if (parseFloat(value) < parseFloat(this.sliderInput.min)) {
|
|
703
|
-
this.sliderInput.min = value;
|
|
704
|
-
}
|
|
705
|
-
this.sliderInput.value = value;
|
|
706
|
-
this.selectorInput.value = '';
|
|
707
|
-
this.setInvalidTextBoxInput(false);
|
|
708
|
-
this.boundUpdateCallback(this.propertyName, valueString);
|
|
709
|
-
} else {
|
|
710
|
-
this.setInvalidTextBoxInput(true);
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
private async onUnitInput(event: Event): Promise<void> {
|
|
716
|
-
const unitInput = (event.currentTarget as HTMLInputElement);
|
|
717
|
-
const hasFocus = unitInput.hasFocus();
|
|
718
|
-
const newUnit = unitInput.value;
|
|
719
|
-
unitInput.disabled = true;
|
|
720
|
-
const prevUnit = this.units;
|
|
721
|
-
const conversionMultiplier =
|
|
722
|
-
await FontEditorUnitConverter.getUnitConversionMultiplier(prevUnit, newUnit, this.propertyName === 'font-size');
|
|
723
|
-
this.setInputUnits(conversionMultiplier, newUnit);
|
|
724
|
-
if (this.textBoxInput.value) {
|
|
725
|
-
this.boundUpdateCallback(this.propertyName, this.textBoxInput.value + newUnit);
|
|
726
|
-
}
|
|
727
|
-
this.units = newUnit;
|
|
728
|
-
unitInput.disabled = false;
|
|
729
|
-
if (hasFocus) {
|
|
730
|
-
unitInput.focus();
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
private createTypeToggle(field: Element, jslogContext: string): void {
|
|
735
|
-
const displaySwitcher = field.createChild('div', 'spectrum-switcher');
|
|
736
|
-
const icon = new Icon();
|
|
737
|
-
icon.name = 'fold-more';
|
|
738
|
-
icon.classList.add('medium');
|
|
739
|
-
displaySwitcher.appendChild(icon);
|
|
740
|
-
UI.UIUtils.setTitle(displaySwitcher, i18nString(UIStrings.sToggleInputType, {PH1: this.propertyName}));
|
|
741
|
-
displaySwitcher.tabIndex = 0;
|
|
742
|
-
self.onInvokeElement(displaySwitcher, this.toggleInputType.bind(this));
|
|
743
|
-
UI.ARIAUtils.markAsButton(displaySwitcher);
|
|
744
|
-
displaySwitcher.setAttribute('jslog', `${VisualLogging.toggle(jslogContext).track({click: true})}`);
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
private toggleInputType(event?: Event): void {
|
|
748
|
-
if (event && (event as KeyboardEvent).key === 'Enter') {
|
|
749
|
-
event.consume();
|
|
750
|
-
}
|
|
751
|
-
if (this.showSliderMode) {
|
|
752
|
-
// Show selector input type
|
|
753
|
-
this.sliderInput.hidden = true;
|
|
754
|
-
this.textBoxInput.hidden = true;
|
|
755
|
-
this.unitInput.hidden = true;
|
|
756
|
-
this.selectorInput.hidden = false;
|
|
757
|
-
this.showSliderMode = false;
|
|
758
|
-
UI.ARIAUtils.LiveAnnouncer.alert(i18nString(UIStrings.selectorInputMode));
|
|
759
|
-
} else {
|
|
760
|
-
// Show sliderinput type
|
|
761
|
-
this.sliderInput.hidden = false;
|
|
762
|
-
this.textBoxInput.hidden = false;
|
|
763
|
-
this.unitInput.hidden = false;
|
|
764
|
-
this.selectorInput.hidden = true;
|
|
765
|
-
this.showSliderMode = true;
|
|
766
|
-
UI.ARIAUtils.LiveAnnouncer.alert(i18nString(UIStrings.sliderInputMode));
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
|
|
770
|
-
private setInputUnits(multiplier: number, newUnit: string): void {
|
|
771
|
-
const newRangeMap = this.staticParams.rangeMap.get(newUnit);
|
|
772
|
-
let newMin, newMax, newStep;
|
|
773
|
-
if (newRangeMap) {
|
|
774
|
-
newMin = newRangeMap.min;
|
|
775
|
-
newMax = newRangeMap.max;
|
|
776
|
-
newStep = newRangeMap.step;
|
|
777
|
-
} else {
|
|
778
|
-
newMin = 0;
|
|
779
|
-
newMax = 100;
|
|
780
|
-
newStep = 1;
|
|
781
|
-
}
|
|
782
|
-
let hasValue = false;
|
|
783
|
-
const roundingPrecision = FontEditorUtils.getRoundingPrecision(newStep);
|
|
784
|
-
let newValue: number = (newMin + newMax) / 2;
|
|
785
|
-
if (this.textBoxInput.value) {
|
|
786
|
-
hasValue = true;
|
|
787
|
-
newValue = parseFloat((parseFloat(this.textBoxInput.value) * multiplier).toFixed(roundingPrecision));
|
|
788
|
-
}
|
|
789
|
-
this.sliderInput.min = Math.min(newValue, newMin).toString();
|
|
790
|
-
this.sliderInput.max = Math.max(newValue, newMax).toString();
|
|
791
|
-
this.sliderInput.step = newStep.toString();
|
|
792
|
-
this.textBoxInput.step = newStep.toString();
|
|
793
|
-
if (hasValue) {
|
|
794
|
-
this.textBoxInput.value = newValue.toString();
|
|
795
|
-
}
|
|
796
|
-
this.sliderInput.value = newValue.toString();
|
|
797
|
-
}
|
|
798
|
-
}
|