@theia/core 1.67.0-next.3 → 1.67.0-next.59
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/README.md +14 -12
- package/lib/browser/authentication-service.d.ts +1 -0
- package/lib/browser/authentication-service.d.ts.map +1 -1
- package/lib/browser/authentication-service.js.map +1 -1
- package/lib/browser/badges/badge-service.d.ts +14 -0
- package/lib/browser/badges/badge-service.d.ts.map +1 -0
- package/lib/browser/badges/badge-service.js +45 -0
- package/lib/browser/badges/badge-service.js.map +1 -0
- package/lib/browser/badges/index.d.ts +3 -0
- package/lib/browser/badges/index.d.ts.map +1 -0
- package/lib/browser/badges/index.js +21 -0
- package/lib/browser/badges/index.js.map +1 -0
- package/lib/browser/badges/tabbar-badge-decorator.d.ts +14 -0
- package/lib/browser/badges/tabbar-badge-decorator.d.ts.map +1 -0
- package/lib/browser/badges/tabbar-badge-decorator.js +68 -0
- package/lib/browser/badges/tabbar-badge-decorator.js.map +1 -0
- package/lib/browser/catalog.json +57 -42
- package/lib/browser/context-key-service.d.ts +4 -1
- package/lib/browser/context-key-service.d.ts.map +1 -1
- package/lib/browser/context-key-service.js +1 -0
- package/lib/browser/context-key-service.js.map +1 -1
- package/lib/browser/dialogs.d.ts.map +1 -1
- package/lib/browser/dialogs.js +2 -1
- package/lib/browser/dialogs.js.map +1 -1
- package/lib/browser/frontend-application-module.d.ts.map +1 -1
- package/lib/browser/frontend-application-module.js +2 -0
- package/lib/browser/frontend-application-module.js.map +1 -1
- package/lib/browser/index.d.ts +3 -0
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +3 -0
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/markdown-rendering/markdown-renderer.d.ts.map +1 -1
- package/lib/browser/markdown-rendering/markdown-renderer.js +2 -1
- package/lib/browser/markdown-rendering/markdown-renderer.js.map +1 -1
- package/lib/browser/markdown-rendering/markdown.d.ts +127 -0
- package/lib/browser/markdown-rendering/markdown.d.ts.map +1 -0
- package/lib/browser/markdown-rendering/markdown.js +188 -0
- package/lib/browser/markdown-rendering/markdown.js.map +1 -0
- package/lib/browser/markdown-rendering/markdown.spec.d.ts +2 -0
- package/lib/browser/markdown-rendering/markdown.spec.d.ts.map +1 -0
- package/lib/browser/markdown-rendering/markdown.spec.js +243 -0
- package/lib/browser/markdown-rendering/markdown.spec.js.map +1 -0
- package/lib/browser/shell/tab-bars.d.ts +1 -1
- package/lib/browser/shell/tab-bars.d.ts.map +1 -1
- package/lib/browser/shell/tab-bars.js +52 -49
- package/lib/browser/shell/tab-bars.js.map +1 -1
- package/lib/browser/widgets/select-component.d.ts +1 -1
- package/lib/browser/widgets/select-component.d.ts.map +1 -1
- package/lib/browser/widgets/select-component.js +6 -2
- package/lib/browser/widgets/select-component.js.map +1 -1
- package/lib/browser/widgets/widget.d.ts +1 -0
- package/lib/browser/widgets/widget.d.ts.map +1 -1
- package/lib/browser/widgets/widget.js +5 -0
- package/lib/browser/widgets/widget.js.map +1 -1
- package/lib/common/markdown-rendering/markdown-string.d.ts +1 -1
- package/lib/common/markdown-rendering/markdown-string.d.ts.map +1 -1
- package/lib/common/markdown-rendering/markdown-string.js.map +1 -1
- package/lib/common/theme.d.ts +2 -0
- package/lib/common/theme.d.ts.map +1 -1
- package/lib/common/theme.js +14 -1
- package/lib/common/theme.js.map +1 -1
- package/package.json +21 -16
- package/shared/markdown-it-anchor/index.d.ts +2 -0
- package/shared/markdown-it-anchor/index.js +1 -0
- package/shared/markdown-it-emoji/index.d.ts +2 -0
- package/shared/markdown-it-emoji/index.js +1 -0
- package/src/browser/authentication-service.ts +1 -0
- package/src/browser/badges/badge-service.ts +44 -0
- package/src/browser/badges/index.ts +18 -0
- package/src/browser/badges/tabbar-badge-decorator.ts +63 -0
- package/src/browser/context-key-service.ts +5 -1
- package/src/browser/dialogs.ts +3 -2
- package/src/browser/frontend-application-module.ts +2 -0
- package/src/browser/index.ts +3 -0
- package/src/browser/markdown-rendering/markdown-renderer.ts +2 -1
- package/src/browser/markdown-rendering/markdown.spec.tsx +371 -0
- package/src/browser/markdown-rendering/markdown.tsx +282 -0
- package/src/browser/shell/tab-bars.ts +24 -26
- package/src/browser/widgets/select-component.tsx +6 -2
- package/src/browser/widgets/widget.ts +6 -0
- package/src/common/markdown-rendering/markdown-string.ts +1 -1
- package/src/common/theme.ts +13 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2025 EclipseSource and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import * as React from 'react';
|
|
18
|
+
import { MarkdownRenderer, MarkdownRenderResult } from './markdown-renderer';
|
|
19
|
+
import { MarkdownString, MarkdownStringImpl } from '../../common/markdown-rendering/markdown-string';
|
|
20
|
+
import { nls } from '../../common/nls';
|
|
21
|
+
import { FormatType } from '../../common/i18n/localization';
|
|
22
|
+
|
|
23
|
+
export interface MarkdownProps {
|
|
24
|
+
/**
|
|
25
|
+
* The markdown content to render. Can be a string, a MarkdownString, or undefined.
|
|
26
|
+
* If undefined or empty, an empty div will be rendered.
|
|
27
|
+
*/
|
|
28
|
+
markdown?: string | MarkdownString;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The MarkdownRenderer instance to use for rendering.
|
|
32
|
+
*/
|
|
33
|
+
markdownRenderer: MarkdownRenderer;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Additional CSS class name(s) to apply to the container element.
|
|
37
|
+
*/
|
|
38
|
+
className?: string;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Options to pass to MarkdownStringImpl if markdown is a string.
|
|
42
|
+
* Common options include:
|
|
43
|
+
* - supportHtml: Allow HTML in markdown (default: false)
|
|
44
|
+
* - supportThemeIcons: Allow theme icons (default: false)
|
|
45
|
+
* - isTrusted: Trust level for command execution (default: false)
|
|
46
|
+
*/
|
|
47
|
+
markdownOptions?: {
|
|
48
|
+
supportHtml?: boolean;
|
|
49
|
+
supportThemeIcons?: boolean;
|
|
50
|
+
isTrusted?: boolean | { enabledCommands: string[] };
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Optional callback that receives the rendered HTML element.
|
|
55
|
+
* Useful for post-processing or adding event listeners.
|
|
56
|
+
* Receives undefined when content is empty.
|
|
57
|
+
*/
|
|
58
|
+
onRender?: (element: HTMLElement | undefined) => void;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* A React component for rendering markdown content.
|
|
63
|
+
*
|
|
64
|
+
* @example Basic usage
|
|
65
|
+
* ```tsx
|
|
66
|
+
* const MyComponent = ({ markdownRenderer }: { markdownRenderer: MarkdownRenderer }) => {
|
|
67
|
+
* return (
|
|
68
|
+
* <Markdown
|
|
69
|
+
* markdown="Hello **World**!"
|
|
70
|
+
* markdownRenderer={markdownRenderer}
|
|
71
|
+
* className="my-content"
|
|
72
|
+
* markdownOptions={{ supportHtml: true }}
|
|
73
|
+
* />
|
|
74
|
+
* );
|
|
75
|
+
* };
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* @example With localized content
|
|
79
|
+
* ```tsx
|
|
80
|
+
* const MyComponent = ({ markdownRenderer }: { markdownRenderer: MarkdownRenderer }) => {
|
|
81
|
+
* const content = nls.localize('my.key', 'Hello **{0}**!', 'World');
|
|
82
|
+
*
|
|
83
|
+
* return (
|
|
84
|
+
* <Markdown
|
|
85
|
+
* markdown={content}
|
|
86
|
+
* markdownRenderer={markdownRenderer}
|
|
87
|
+
* className="my-content"
|
|
88
|
+
* />
|
|
89
|
+
* );
|
|
90
|
+
* };
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* @example With command links
|
|
94
|
+
* ```tsx
|
|
95
|
+
* const content = nls.localize(
|
|
96
|
+
* 'my.key',
|
|
97
|
+
* 'Open [settings]({0}) to configure.',
|
|
98
|
+
* `command:${CommonCommands.OPEN_PREFERENCES.id}`
|
|
99
|
+
* );
|
|
100
|
+
*
|
|
101
|
+
* return (
|
|
102
|
+
* <Markdown
|
|
103
|
+
* markdown={content}
|
|
104
|
+
* markdownRenderer={markdownRenderer}
|
|
105
|
+
* markdownOptions={{
|
|
106
|
+
* isTrusted: { enabledCommands: [CommonCommands.OPEN_PREFERENCES.id] }
|
|
107
|
+
* }}
|
|
108
|
+
* />
|
|
109
|
+
* );
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
const MarkdownComponent: React.FC<MarkdownProps> = ({
|
|
113
|
+
markdown,
|
|
114
|
+
markdownRenderer,
|
|
115
|
+
className,
|
|
116
|
+
markdownOptions,
|
|
117
|
+
onRender
|
|
118
|
+
}) => {
|
|
119
|
+
const ref = useMarkdown(markdown, markdownRenderer, markdownOptions, onRender);
|
|
120
|
+
return <div className={className} ref={ref} />;
|
|
121
|
+
};
|
|
122
|
+
MarkdownComponent.displayName = 'Markdown';
|
|
123
|
+
|
|
124
|
+
export const Markdown = React.memo(MarkdownComponent);
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* A React hook for rendering markdown content.
|
|
128
|
+
*
|
|
129
|
+
* This hook integrates MarkdownRenderer with React's lifecycle,
|
|
130
|
+
* ensuring that:
|
|
131
|
+
* - Markdown is rendered only when content or renderer changes
|
|
132
|
+
* - MarkdownRenderResult is properly disposed when component unmounts
|
|
133
|
+
* - DOM elements are correctly managed by React
|
|
134
|
+
* - Event listeners and other imperative DOM operations are preserved
|
|
135
|
+
*
|
|
136
|
+
* Returns a ref that should be attached to a DOM element.
|
|
137
|
+
*
|
|
138
|
+
* @example Basic usage
|
|
139
|
+
* ```tsx
|
|
140
|
+
* const MyComponent = ({ markdownRenderer }: { markdownRenderer: MarkdownRenderer }) => {
|
|
141
|
+
* const ref = useMarkdown('Hello **World**!', markdownRenderer, { supportHtml: true });
|
|
142
|
+
* return <div className="my-content" ref={ref} />;
|
|
143
|
+
* };
|
|
144
|
+
* ```
|
|
145
|
+
*
|
|
146
|
+
* @example With localized content
|
|
147
|
+
* ```tsx
|
|
148
|
+
* const MyComponent = ({ markdownRenderer }: { markdownRenderer: MarkdownRenderer }) => {
|
|
149
|
+
* const content = nls.localize('my.key', 'Hello **{0}**!', 'World');
|
|
150
|
+
* const ref = useMarkdown(content, markdownRenderer);
|
|
151
|
+
* return <div className="my-content" ref={ref} />;
|
|
152
|
+
* };
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
export function useMarkdown(
|
|
156
|
+
markdown: string | MarkdownString | undefined,
|
|
157
|
+
markdownRenderer: MarkdownRenderer,
|
|
158
|
+
markdownOptions?: MarkdownProps['markdownOptions'],
|
|
159
|
+
onRender?: (element: HTMLElement | undefined) => void
|
|
160
|
+
): React.RefObject<HTMLDivElement> {
|
|
161
|
+
// eslint-disable-next-line no-null/no-null
|
|
162
|
+
const containerRef = React.useRef<HTMLDivElement>(null);
|
|
163
|
+
const renderResultRef = React.useRef<MarkdownRenderResult | undefined>();
|
|
164
|
+
|
|
165
|
+
const renderedElement = React.useMemo(() => {
|
|
166
|
+
renderResultRef.current?.dispose();
|
|
167
|
+
renderResultRef.current = undefined;
|
|
168
|
+
|
|
169
|
+
if (!markdown || (typeof markdown === 'string' && markdown.trim() === '')) {
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const markdownString = typeof markdown === 'string'
|
|
174
|
+
? new MarkdownStringImpl(markdown, markdownOptions)
|
|
175
|
+
: markdown;
|
|
176
|
+
|
|
177
|
+
const rendered = markdownRenderer.render(markdownString);
|
|
178
|
+
renderResultRef.current = rendered;
|
|
179
|
+
|
|
180
|
+
return rendered.element;
|
|
181
|
+
}, [markdown, markdownRenderer, markdownOptions]);
|
|
182
|
+
|
|
183
|
+
React.useEffect(() => {
|
|
184
|
+
if (containerRef.current && renderedElement) {
|
|
185
|
+
containerRef.current.replaceChildren(renderedElement);
|
|
186
|
+
onRender?.(renderedElement);
|
|
187
|
+
} else if (containerRef.current && !renderedElement) {
|
|
188
|
+
containerRef.current.replaceChildren();
|
|
189
|
+
onRender?.(undefined);
|
|
190
|
+
}
|
|
191
|
+
}, [renderedElement, onRender]);
|
|
192
|
+
|
|
193
|
+
React.useEffect(() => () => {
|
|
194
|
+
renderResultRef.current?.dispose();
|
|
195
|
+
}, []);
|
|
196
|
+
|
|
197
|
+
return containerRef;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export interface LocalizedMarkdownProps extends MarkdownProps {
|
|
201
|
+
/**
|
|
202
|
+
* The localization key for the markdown content.
|
|
203
|
+
*/
|
|
204
|
+
localizationKey: string;
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* The default markdown content (in English) with placeholders.
|
|
208
|
+
* Use {0}, {1}, etc. for parameter substitution.
|
|
209
|
+
*/
|
|
210
|
+
defaultMarkdown: string;
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Arguments to substitute into the markdown template.
|
|
214
|
+
* Can be strings, numbers, booleans, or undefined.
|
|
215
|
+
*/
|
|
216
|
+
args?: FormatType[];
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* A React component that combines localization with markdown rendering.
|
|
221
|
+
*
|
|
222
|
+
* This component automatically handles the localization of markdown content using `nls.localize`
|
|
223
|
+
* and then renders it using the Markdown component.
|
|
224
|
+
*
|
|
225
|
+
* @example Basic usage
|
|
226
|
+
* ```tsx
|
|
227
|
+
* <LocalizedMarkdown
|
|
228
|
+
* localizationKey="theia/mypackage/welcome"
|
|
229
|
+
* defaultMarkdown="Welcome to **Theia**!"
|
|
230
|
+
* markdownRenderer={this.markdownRenderer}
|
|
231
|
+
* className="welcome-message"
|
|
232
|
+
* />
|
|
233
|
+
* ```
|
|
234
|
+
*
|
|
235
|
+
* @example With parameters
|
|
236
|
+
* ```tsx
|
|
237
|
+
* <LocalizedMarkdown
|
|
238
|
+
* localizationKey="theia/mypackage/greeting"
|
|
239
|
+
* defaultMarkdown="Hello **{0}**! You have {1} new messages."
|
|
240
|
+
* args={['Alice', 5]}
|
|
241
|
+
* markdownRenderer={this.markdownRenderer}
|
|
242
|
+
* />
|
|
243
|
+
* ```
|
|
244
|
+
*
|
|
245
|
+
* @example With command links
|
|
246
|
+
* ```tsx
|
|
247
|
+
* <LocalizedMarkdown
|
|
248
|
+
* localizationKey="theia/mypackage/settings"
|
|
249
|
+
* defaultMarkdown="Open [settings]({0}) to configure."
|
|
250
|
+
* args={[`command:${CommonCommands.OPEN_PREFERENCES.id}`]}
|
|
251
|
+
* markdownRenderer={this.markdownRenderer}
|
|
252
|
+
* markdownOptions={{
|
|
253
|
+
* isTrusted: { enabledCommands: [CommonCommands.OPEN_PREFERENCES.id] }
|
|
254
|
+
* }}
|
|
255
|
+
* />
|
|
256
|
+
* ```
|
|
257
|
+
*/
|
|
258
|
+
export const LocalizedMarkdown: React.FC<LocalizedMarkdownProps> = ({
|
|
259
|
+
localizationKey,
|
|
260
|
+
defaultMarkdown,
|
|
261
|
+
args = [],
|
|
262
|
+
markdownRenderer,
|
|
263
|
+
className,
|
|
264
|
+
markdownOptions,
|
|
265
|
+
onRender
|
|
266
|
+
}) => {
|
|
267
|
+
const localizedMarkdown = React.useMemo(
|
|
268
|
+
() => nls.localize(localizationKey, defaultMarkdown, ...args),
|
|
269
|
+
[localizationKey, defaultMarkdown, ...args]
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
return (
|
|
273
|
+
<Markdown
|
|
274
|
+
markdown={localizedMarkdown}
|
|
275
|
+
markdownRenderer={markdownRenderer}
|
|
276
|
+
className={className}
|
|
277
|
+
markdownOptions={markdownOptions}
|
|
278
|
+
onRender={onRender}
|
|
279
|
+
/>
|
|
280
|
+
);
|
|
281
|
+
};
|
|
282
|
+
LocalizedMarkdown.displayName = 'LocalizedMarkdown';
|
|
@@ -183,11 +183,9 @@ export class TabBarRenderer extends TabBar.Renderer {
|
|
|
183
183
|
? nls.localizeByDefault('Unpin')
|
|
184
184
|
: nls.localizeByDefault('Close');
|
|
185
185
|
|
|
186
|
-
const hover =
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
onmouseenter: this.handleMouseEnterEvent
|
|
190
|
-
};
|
|
186
|
+
const hover = {
|
|
187
|
+
onmouseenter: this.handleMouseEnterEvent
|
|
188
|
+
};
|
|
191
189
|
|
|
192
190
|
const tabLabel = h.div(
|
|
193
191
|
{ className: 'theia-tab-icon-label' },
|
|
@@ -550,7 +548,7 @@ export class TabBarRenderer extends TabBar.Renderer {
|
|
|
550
548
|
return h.div({ className: baseClassName, style }, data.title.iconLabel);
|
|
551
549
|
}
|
|
552
550
|
|
|
553
|
-
protected renderEnhancedPreview
|
|
551
|
+
protected renderEnhancedPreview(title: Title<Widget>): HTMLDivElement {
|
|
554
552
|
const hoverBox = document.createElement('div');
|
|
555
553
|
hoverBox.classList.add('theia-horizontal-tabBar-hover-div');
|
|
556
554
|
const labelElement = document.createElement('p');
|
|
@@ -625,26 +623,26 @@ export class TabBarRenderer extends TabBar.Renderer {
|
|
|
625
623
|
}
|
|
626
624
|
|
|
627
625
|
protected handleMouseEnterEvent = (event: MouseEvent) => {
|
|
628
|
-
if (this.tabBar
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
}
|
|
626
|
+
if (!this.tabBar || !this.hoverService || !(event.currentTarget instanceof HTMLElement)) { return; }
|
|
627
|
+
const id = event.currentTarget.id;
|
|
628
|
+
const title = this.tabBar.titles.find(t => this.createTabId(t) === id);
|
|
629
|
+
if (!title) { return; }
|
|
630
|
+
if (this.tabBar.orientation === 'horizontal' && this.corePreferences?.['window.tabbar.enhancedPreview'] !== 'classic' && EnhancedPreviewWidget.is(title.owner)) {
|
|
631
|
+
this.hoverService.requestHover({
|
|
632
|
+
content: this.renderEnhancedPreview(title),
|
|
633
|
+
target: event.currentTarget,
|
|
634
|
+
position: 'bottom',
|
|
635
|
+
cssClasses: ['extended-tab-preview'],
|
|
636
|
+
visualPreview: this.corePreferences?.['window.tabbar.enhancedPreview'] === 'visual' ? width => this.renderVisualPreview(width, title) : undefined
|
|
637
|
+
});
|
|
638
|
+
} else if (title.caption) {
|
|
639
|
+
const position = this.tabBar.orientation === 'horizontal' ? 'bottom' : 'right';
|
|
640
|
+
const tooltip = ArrayUtils.coalesce([title.caption, ...this.getDecorationData(title, 'tooltip')]).join(' - ');
|
|
641
|
+
this.hoverService.requestHover({
|
|
642
|
+
content: tooltip,
|
|
643
|
+
target: event.currentTarget,
|
|
644
|
+
position
|
|
645
|
+
});
|
|
648
646
|
}
|
|
649
647
|
};
|
|
650
648
|
|
|
@@ -266,7 +266,7 @@ export class SelectComponent extends React.Component<SelectComponentProps, Selec
|
|
|
266
266
|
this.selectOption(selected, this.props.options[selected]);
|
|
267
267
|
}
|
|
268
268
|
} else if (ev.key === 'Escape' || ev.key === 'Tab') {
|
|
269
|
-
this.hide();
|
|
269
|
+
this.hide(undefined, true);
|
|
270
270
|
}
|
|
271
271
|
ev.stopPropagation();
|
|
272
272
|
ev.nativeEvent.stopImmediatePropagation();
|
|
@@ -290,7 +290,7 @@ export class SelectComponent extends React.Component<SelectComponentProps, Selec
|
|
|
290
290
|
}
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
-
protected hide(index?: number): void {
|
|
293
|
+
protected hide(index?: number, releaseFocus = false): void {
|
|
294
294
|
const selectedIndex = index === undefined ? this.state.original : index;
|
|
295
295
|
this.setState({
|
|
296
296
|
dimensions: undefined,
|
|
@@ -298,6 +298,10 @@ export class SelectComponent extends React.Component<SelectComponentProps, Selec
|
|
|
298
298
|
original: selectedIndex,
|
|
299
299
|
hover: selectedIndex
|
|
300
300
|
});
|
|
301
|
+
// Force releasing focus of the select element to allow closing via escape later on
|
|
302
|
+
if (releaseFocus && document.activeElement && document.activeElement === this.fieldRef.current) {
|
|
303
|
+
this.fieldRef.current.blur();
|
|
304
|
+
}
|
|
301
305
|
}
|
|
302
306
|
|
|
303
307
|
protected renderDropdown(): React.ReactNode {
|
|
@@ -121,6 +121,12 @@ export class BaseWidget extends Widget implements PreviewableWidget {
|
|
|
121
121
|
super(options);
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
override get isVisible(): boolean {
|
|
125
|
+
// Reverted to @lumino/widgets pre-2.7.0 behavior using the IsVisible flag instead of the recursive parent check.
|
|
126
|
+
// Theia relies on this flag-based implementation and we need to transition to the new behavior in a follow-up (GH-16585)
|
|
127
|
+
return this.testFlag(Widget.Flag.IsVisible);
|
|
128
|
+
}
|
|
129
|
+
|
|
124
130
|
override dispose(): void {
|
|
125
131
|
if (this.isDisposed) {
|
|
126
132
|
return;
|
|
@@ -57,7 +57,7 @@ export class MarkdownStringImpl implements MarkdownString {
|
|
|
57
57
|
|
|
58
58
|
constructor(
|
|
59
59
|
value: string = '',
|
|
60
|
-
isTrustedOrOptions: boolean | { isTrusted?: boolean; supportThemeIcons?: boolean; supportHtml?: boolean } = false,
|
|
60
|
+
isTrustedOrOptions: boolean | { isTrusted?: boolean | MarkdownStringTrustedOptions; supportThemeIcons?: boolean; supportHtml?: boolean } = false,
|
|
61
61
|
) {
|
|
62
62
|
this.value = value;
|
|
63
63
|
if (typeof this.value !== 'string') {
|
package/src/common/theme.ts
CHANGED
|
@@ -47,11 +47,24 @@ export interface ThemeColor {
|
|
|
47
47
|
readonly id: string;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
// Copied from https://github.com/microsoft/vscode/blob/1.106.1/src/vs/base/common/themables.ts
|
|
51
|
+
export function isThemeColor(obj: unknown): obj is ThemeColor {
|
|
52
|
+
return !!obj && typeof obj === 'object' && typeof (<ThemeColor>obj).id === 'string';
|
|
53
|
+
}
|
|
54
|
+
|
|
50
55
|
export interface ThemeIcon {
|
|
51
56
|
readonly id: string;
|
|
52
57
|
readonly color?: ThemeColor;
|
|
53
58
|
}
|
|
54
59
|
|
|
60
|
+
// Copied and modified from https://github.com/microsoft/vscode/blob/1.106.1/src/vs/base/common/themables.ts
|
|
61
|
+
export function isThemeIcon(obj: unknown): obj is ThemeIcon {
|
|
62
|
+
return !!obj &&
|
|
63
|
+
typeof obj === 'object' &&
|
|
64
|
+
typeof (<ThemeIcon>obj).id === 'string' &&
|
|
65
|
+
(typeof (<ThemeIcon>obj).color === 'undefined' || isThemeColor((<ThemeIcon>obj).color));
|
|
66
|
+
}
|
|
67
|
+
|
|
55
68
|
export interface IconDefinition {
|
|
56
69
|
font?: IconFontContribution; // undefined for the default font (codicon)
|
|
57
70
|
fontCharacter: string;
|