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.
Files changed (190) hide show
  1. package/front_end/core/common/VersionController.ts +9 -7
  2. package/front_end/core/common/common.ts +0 -4
  3. package/front_end/core/host/AidaClient.ts +1 -1
  4. package/front_end/core/host/AidaClientTypes.ts +2 -0
  5. package/front_end/core/host/AidaGcaTranslation.ts +2 -2
  6. package/front_end/core/host/Platform.ts +0 -9
  7. package/front_end/core/host/UserMetrics.ts +0 -55
  8. package/front_end/core/root/ExperimentNames.ts +0 -1
  9. package/front_end/core/sdk/CPUThrottlingManager.ts +1 -1
  10. package/front_end/core/sdk/CSSMetadata.ts +60 -63
  11. package/front_end/core/sdk/CSSProperty.ts +1 -5
  12. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +11 -32
  13. package/front_end/{panels/application → core/sdk}/DOMStorageModel.ts +12 -10
  14. package/front_end/core/sdk/sdk.ts +2 -0
  15. package/front_end/entrypoints/main/MainImpl.ts +12 -8
  16. package/front_end/entrypoints/main/SimpleApp.ts +3 -4
  17. package/front_end/entrypoints/main/main-meta.ts +1 -1
  18. package/front_end/generated/InspectorBackendCommands.ts +3 -3
  19. package/front_end/generated/SupportedCSSProperties.js +21 -21
  20. package/front_end/generated/protocol.ts +4 -1
  21. package/front_end/models/ai_assistance/StorageItem.ts +16 -0
  22. package/front_end/models/ai_assistance/agents/StorageAgent.ts +82 -0
  23. package/front_end/models/ai_assistance/ai_assistance.ts +4 -0
  24. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +9 -37
  25. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +26 -3
  26. package/front_end/models/ai_code_completion/AiCodeCompletion.ts +10 -2
  27. package/front_end/models/ai_code_generation/AiCodeGeneration.ts +5 -1
  28. package/front_end/models/issues_manager/CookieIssue.ts +0 -4
  29. package/front_end/models/issues_manager/RelatedIssue.ts +0 -14
  30. package/front_end/models/javascript_metadata/NativeFunctions.js +0 -4
  31. package/front_end/models/web_mcp/WebMCPModel.ts +11 -2
  32. package/front_end/models/workspace/IgnoreListManager.ts +1 -1
  33. package/front_end/models/workspace/UISourceCode.ts +10 -5
  34. package/front_end/panels/ai_assistance/ai_assistance-meta.ts +6 -1
  35. package/front_end/panels/ai_assistance/components/ChatMessage.ts +26 -9
  36. package/front_end/panels/application/ApplicationPanelSidebar.ts +32 -42
  37. package/front_end/panels/application/BackForwardCacheTreeElement.ts +2 -2
  38. package/front_end/panels/application/BounceTrackingMitigationsTreeElement.ts +2 -2
  39. package/front_end/panels/application/DOMStorageItemsView.ts +18 -13
  40. package/front_end/panels/application/InterestGroupTreeElement.ts +2 -2
  41. package/front_end/panels/application/ReportingApiTreeElement.ts +3 -3
  42. package/front_end/panels/application/ResourcesPanel.ts +1 -2
  43. package/front_end/panels/application/ServiceWorkerCacheTreeElement.ts +1 -2
  44. package/front_end/panels/application/StorageView.ts +1 -2
  45. package/front_end/panels/application/TrustTokensTreeElement.ts +2 -2
  46. package/front_end/panels/application/WebMCPTreeElement.ts +2 -2
  47. package/front_end/panels/application/WebMCPView.ts +74 -16
  48. package/front_end/panels/application/application.ts +0 -2
  49. package/front_end/panels/application/webMCPView.css +13 -2
  50. package/front_end/panels/console/ConsolePrompt.ts +1 -1
  51. package/front_end/panels/console/ConsoleView.ts +3 -4
  52. package/front_end/panels/elements/ColorSwatchPopoverIcon.ts +0 -152
  53. package/front_end/panels/elements/ElementsTreeElement.ts +4 -9
  54. package/front_end/panels/elements/StandaloneStylesContainer.ts +3 -0
  55. package/front_end/panels/elements/StylePropertiesSection.ts +0 -61
  56. package/front_end/panels/elements/StylePropertyTreeElement.ts +36 -23
  57. package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +6 -4
  58. package/front_end/panels/elements/StylesContainer.ts +1 -0
  59. package/front_end/panels/elements/StylesSidebarPane.ts +12 -7
  60. package/front_end/panels/elements/stylesSidebarPane.css +0 -8
  61. package/front_end/panels/emulation/AdvancedApp.ts +3 -3
  62. package/front_end/panels/emulation/DeviceModeToolbar.ts +207 -377
  63. package/front_end/panels/emulation/emulation-meta.ts +1 -1
  64. package/front_end/panels/network/NetworkPanel.ts +1 -1
  65. package/front_end/panels/profiler/HeapProfilerPanel.ts +1 -2
  66. package/front_end/panels/screencast/ScreencastApp.ts +3 -3
  67. package/front_end/panels/screencast/screencast-meta.ts +1 -2
  68. package/front_end/panels/settings/SettingsScreen.ts +2 -2
  69. package/front_end/panels/sources/AiCodeCompletionPlugin.ts +2 -4
  70. package/front_end/panels/sources/ScopeChainSidebarPane.ts +5 -1
  71. package/front_end/panels/sources/SourcesNavigator.ts +1 -1
  72. package/front_end/panels/sources/UISourceCodeFrame.ts +1 -3
  73. package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +179 -145
  74. package/front_end/panels/timeline/TimelinePanel.ts +2 -2
  75. package/front_end/panels/timeline/timelineTreeView.css +2 -2
  76. package/front_end/third_party/chromium/README.chromium +1 -1
  77. package/front_end/third_party/puppeteer/README.chromium +2 -2
  78. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts +2 -2
  79. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/locators/locators.d.ts +3 -2
  80. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/locators/locators.d.ts.map +1 -1
  81. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/locators/locators.js +53 -23
  82. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/locators/locators.js.map +1 -1
  83. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.d.ts +3 -2
  84. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.d.ts.map +1 -1
  85. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js +18 -8
  86. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js.map +1 -1
  87. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserConnector.d.ts.map +1 -1
  88. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserConnector.js +2 -2
  89. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserConnector.js.map +1 -1
  90. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts.map +1 -1
  91. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js +4 -0
  92. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js.map +1 -1
  93. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/TargetManager.d.ts +1 -1
  94. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/TargetManager.d.ts.map +1 -1
  95. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/TargetManager.js +54 -19
  96. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/TargetManager.js.map +1 -1
  97. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/WebMCP.d.ts +5 -0
  98. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/WebMCP.d.ts.map +1 -1
  99. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/WebMCP.js +2 -9
  100. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/WebMCP.js.map +1 -1
  101. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/BrowserConnector.d.ts.map +1 -1
  102. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/BrowserConnector.js +3 -0
  103. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/BrowserConnector.js.map +1 -1
  104. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConnectOptions.d.ts +37 -1
  105. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConnectOptions.d.ts.map +1 -1
  106. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  107. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
  108. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js +5 -2
  109. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js.map +1 -1
  110. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
  111. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js +1 -0
  112. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js.map +1 -1
  113. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
  114. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
  115. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  116. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
  117. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
  118. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +47 -65
  119. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +143 -55
  120. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts +2 -2
  121. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/locators/locators.d.ts +3 -2
  122. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/locators/locators.d.ts.map +1 -1
  123. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/locators/locators.js +53 -23
  124. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/locators/locators.js.map +1 -1
  125. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.d.ts +3 -2
  126. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.d.ts.map +1 -1
  127. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js +18 -8
  128. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js.map +1 -1
  129. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserConnector.d.ts.map +1 -1
  130. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserConnector.js +2 -2
  131. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserConnector.js.map +1 -1
  132. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts.map +1 -1
  133. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js +4 -0
  134. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js.map +1 -1
  135. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/TargetManager.d.ts +1 -1
  136. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/TargetManager.d.ts.map +1 -1
  137. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/TargetManager.js +54 -19
  138. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/TargetManager.js.map +1 -1
  139. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/WebMCP.d.ts +5 -0
  140. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/WebMCP.d.ts.map +1 -1
  141. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/WebMCP.js +2 -9
  142. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/WebMCP.js.map +1 -1
  143. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/BrowserConnector.d.ts.map +1 -1
  144. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/BrowserConnector.js +3 -0
  145. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/BrowserConnector.js.map +1 -1
  146. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/ConnectOptions.d.ts +37 -1
  147. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/ConnectOptions.d.ts.map +1 -1
  148. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
  149. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js +5 -2
  150. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js.map +1 -1
  151. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
  152. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js +1 -0
  153. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js.map +1 -1
  154. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
  155. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
  156. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
  157. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
  158. package/front_end/third_party/puppeteer/package/lib/types.d.ts +47 -65
  159. package/front_end/third_party/puppeteer/package/package.json +6 -6
  160. package/front_end/third_party/puppeteer/package/src/api/Page.ts +2 -2
  161. package/front_end/third_party/puppeteer/package/src/api/locators/locators.ts +69 -27
  162. package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +27 -8
  163. package/front_end/third_party/puppeteer/package/src/cdp/BrowserConnector.ts +4 -2
  164. package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +6 -0
  165. package/front_end/third_party/puppeteer/package/src/cdp/TargetManager.ts +60 -18
  166. package/front_end/third_party/puppeteer/package/src/cdp/WebMCP.ts +7 -9
  167. package/front_end/third_party/puppeteer/package/src/common/BrowserConnector.ts +3 -0
  168. package/front_end/third_party/puppeteer/package/src/common/ConnectOptions.ts +37 -1
  169. package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +7 -2
  170. package/front_end/third_party/puppeteer/package/src/node/ChromeLauncher.ts +1 -0
  171. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  172. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  173. package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +19 -14
  174. package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +8 -7
  175. package/front_end/ui/components/tooltips/Tooltip.ts +3 -3
  176. package/front_end/{core/common → ui/legacy}/AppProvider.ts +1 -1
  177. package/front_end/ui/legacy/InspectorView.ts +4 -3
  178. package/front_end/ui/legacy/TabbedPane.ts +1 -1
  179. package/front_end/ui/legacy/UIUserMetrics.ts +70 -0
  180. package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +1 -8
  181. package/front_end/ui/legacy/components/inline_editor/inline_editor.ts +0 -6
  182. package/front_end/ui/legacy/legacy.ts +6 -0
  183. package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
  184. package/package.json +1 -1
  185. package/front_end/Images/src/custom-typography.svg +0 -3
  186. package/front_end/ui/legacy/components/inline_editor/FontEditor.ts +0 -798
  187. package/front_end/ui/legacy/components/inline_editor/FontEditorUnitConverter.ts +0 -250
  188. package/front_end/ui/legacy/components/inline_editor/FontEditorUtils.ts +0 -204
  189. package/front_end/ui/legacy/components/inline_editor/fontEditor.css +0 -185
  190. /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
- }