@codingame/monaco-vscode-welcome-service-override 34.1.3 → 35.0.0

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 (29) hide show
  1. package/index.js +6 -2
  2. package/package.json +2 -2
  3. package/vscode/src/vs/workbench/contrib/onboarding/browser/media/onboardingTarget.css +28 -0
  4. package/vscode/src/vs/workbench/contrib/onboarding/browser/media/spotlight.css +147 -0
  5. package/vscode/src/vs/workbench/contrib/onboarding/browser/onboarding.contribution.d.ts +1 -0
  6. package/vscode/src/vs/workbench/contrib/onboarding/browser/onboarding.contribution.js +107 -0
  7. package/vscode/src/vs/workbench/contrib/onboarding/browser/onboardingService.d.ts +122 -0
  8. package/vscode/src/vs/workbench/contrib/onboarding/browser/onboardingService.js +378 -0
  9. package/vscode/src/vs/workbench/contrib/onboarding/browser/spotlight/onboardingTarget.d.ts +31 -0
  10. package/vscode/src/vs/workbench/contrib/onboarding/browser/spotlight/onboardingTarget.js +25 -0
  11. package/vscode/src/vs/workbench/contrib/onboarding/browser/spotlight/spotlightOverlay.d.ts +96 -0
  12. package/vscode/src/vs/workbench/contrib/onboarding/browser/spotlight/spotlightOverlay.js +381 -0
  13. package/vscode/src/vs/workbench/contrib/onboarding/browser/spotlight/spotlightPresentation.d.ts +24 -0
  14. package/vscode/src/vs/workbench/contrib/onboarding/browser/spotlight/spotlightPresentation.js +205 -0
  15. package/vscode/src/vs/workbench/contrib/onboarding/browser/spotlight/spotlightTypes.d.ts +49 -0
  16. package/vscode/src/vs/workbench/contrib/onboarding/browser/spotlight/spotlightTypes.js +5 -0
  17. package/vscode/src/vs/workbench/contrib/onboarding/common/onboardingPresentation.d.ts +47 -0
  18. package/vscode/src/vs/workbench/contrib/onboarding/common/onboardingPresentation.js +27 -0
  19. package/vscode/src/vs/workbench/contrib/onboarding/common/onboardingRegistry.d.ts +21 -0
  20. package/vscode/src/vs/workbench/contrib/onboarding/common/onboardingRegistry.js +35 -0
  21. package/vscode/src/vs/workbench/contrib/onboarding/common/onboardingScenario.d.ts +171 -0
  22. package/vscode/src/vs/workbench/contrib/onboarding/common/onboardingScenario.js +20 -0
  23. package/vscode/src/vs/workbench/contrib/onboarding/common/onboardingScenarioService.d.ts +41 -0
  24. package/vscode/src/vs/workbench/contrib/onboarding/common/onboardingScenarioService.js +10 -0
  25. package/vscode/src/vs/workbench/contrib/welcomeOnboarding/browser/onboardingVariationA.js +64 -64
  26. package/vscode/src/vs/workbench/contrib/welcomeOnboarding/browser/welcomeOnboarding.contribution.js +1 -1
  27. package/vscode/src/vs/workbench/contrib/welcomeViews/common/newFile.contribution.js +10 -10
  28. package/vscode/src/vs/workbench/contrib/welcomeViews/common/viewsWelcomeContribution.js +1 -1
  29. package/vscode/src/vs/workbench/contrib/welcomeViews/common/viewsWelcomeExtensionPoint.js +8 -8
@@ -0,0 +1,378 @@
1
+
2
+ import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
3
+ import { DeferredPromise } from '@codingame/monaco-vscode-api/vscode/vs/base/common/async';
4
+ import { onUnexpectedError } from '@codingame/monaco-vscode-api/vscode/vs/base/common/errors';
5
+ import { Emitter } from '@codingame/monaco-vscode-api/vscode/vs/base/common/event';
6
+ import { Disposable, DisposableStore } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
7
+ import '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/index';
8
+ import { mainWindow } from '@codingame/monaco-vscode-api/vscode/vs/base/browser/window';
9
+ import { IConfigurationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configuration.service';
10
+ import { IContextKeyService } from '@codingame/monaco-vscode-api/vscode/vs/platform/contextkey/common/contextkey.service';
11
+ import { ITelemetryService } from '@codingame/monaco-vscode-api/vscode/vs/platform/telemetry/common/telemetry.service';
12
+ import { ILifecycleService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/lifecycle/common/lifecycle.service';
13
+ import { StorageScope, StorageTarget } from '@codingame/monaco-vscode-api/vscode/vs/platform/storage/common/storage';
14
+ import { IStorageService } from '@codingame/monaco-vscode-api/vscode/vs/platform/storage/common/storage.service';
15
+ import { IWorkbenchAssignmentService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/assignment/common/assignmentService.service';
16
+ import { Memento } from '@codingame/monaco-vscode-api/vscode/vs/workbench/common/memento';
17
+ import { onboardingPresentationRegistry } from '../common/onboardingPresentation.js';
18
+ import { onboardingScenarioRegistry } from '../common/onboardingRegistry.js';
19
+ import { ONBOARDING_ASSIGNMENT_CONTEXT_PREFIX, OnboardingOutcome } from '../common/onboardingScenario.js';
20
+ import { ONBOARDING_ENABLED_CONFIG, ONBOARDING_DEVELOPER_MODE_CONFIG, isOnboardingDeveloperModeEnabled } from '../common/onboardingScenarioService.js';
21
+ import { autorun } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/reactions/autorun';
22
+
23
+ var OnboardingScenarioService_1;
24
+ let OnboardingScenarioService = class OnboardingScenarioService extends Disposable {
25
+ static {
26
+ OnboardingScenarioService_1 = this;
27
+ }
28
+ static {
29
+ this.MEMENTO_ID = "onboarding";
30
+ }
31
+ static {
32
+ this.OPENED_IDS_STORAGE_KEY = "onboarding.openedAssignmentContextIds";
33
+ }
34
+ constructor(
35
+ storageService,
36
+ contextKeyService,
37
+ configurationService,
38
+ lifecycleService,
39
+ assignmentService,
40
+ telemetryService
41
+ ) {
42
+ super();
43
+ this.storageService = storageService;
44
+ this.contextKeyService = contextKeyService;
45
+ this.configurationService = configurationService;
46
+ this.lifecycleService = lifecycleService;
47
+ this.assignmentService = assignmentService;
48
+ this.telemetryService = telemetryService;
49
+ this._triggerListeners = this._register(( new DisposableStore()));
50
+ this._pending = ( new Set());
51
+ this._queue = [];
52
+ this._inflight = ( new Map());
53
+ this._pumping = false;
54
+ this._experimentStates = ( new Map());
55
+ this._onDidChangeOpenedIds = this._register(( new Emitter()));
56
+ this._started = false;
57
+ this._stopped = false;
58
+ this._shownSinceStart = ( new Set());
59
+ this._memento = ( new Memento(OnboardingScenarioService_1.MEMENTO_ID, this.storageService));
60
+ this._state = this._memento.getMemento(StorageScope.APPLICATION, StorageTarget.MACHINE);
61
+ this._openedAssignmentContextIds = this._loadOpenedIds();
62
+ this.assignmentService.addTelemetryAssignmentFilter({
63
+ id: "onboarding",
64
+ exclude: assignment => assignment.startsWith(ONBOARDING_ASSIGNMENT_CONTEXT_PREFIX) && !( this._openedAssignmentContextIds.has(assignment)),
65
+ onDidChange: this._onDidChangeOpenedIds.event
66
+ });
67
+ this._register(this.lifecycleService.onWillShutdown(() => this._stop()));
68
+ }
69
+ _stop() {
70
+ this._stopped = true;
71
+ this._activeAbort?.fire();
72
+ let entry;
73
+ while ((entry = this._queue.shift())) {
74
+ this._pending.delete(entry.scenario.id);
75
+ entry.deferred.complete(OnboardingOutcome.Aborted);
76
+ }
77
+ }
78
+ start() {
79
+ if (this._started) {
80
+ return;
81
+ }
82
+ this._started = true;
83
+ this._register(onboardingScenarioRegistry.onDidChange(() => {
84
+ this._registerTriggerListeners();
85
+ this._resolveExperiments();
86
+ this._evaluate();
87
+ }));
88
+ this._register(this.contextKeyService.onDidChangeContext(() => this._evaluate()));
89
+ this._register(this.configurationService.onDidChangeConfiguration(e => {
90
+ if (e.affectsConfiguration(ONBOARDING_ENABLED_CONFIG) || e.affectsConfiguration(ONBOARDING_DEVELOPER_MODE_CONFIG)) {
91
+ this._evaluate();
92
+ }
93
+ }));
94
+ this._registerTriggerListeners();
95
+ this._resolveExperiments();
96
+ this._evaluate();
97
+ }
98
+ getScenarios() {
99
+ return onboardingScenarioRegistry.getScenarios();
100
+ }
101
+ async runScenario(id) {
102
+ const scenario = onboardingScenarioRegistry.getScenario(id);
103
+ if (!scenario) {
104
+ throw ( new Error(`Unknown onboarding scenario '${id}'.`));
105
+ }
106
+ return this._enqueue(scenario);
107
+ }
108
+ hasBeenShown(id) {
109
+ const scenario = onboardingScenarioRegistry.getScenario(id);
110
+ return this._hasBeenShownKey(scenario ? this._seenKey(scenario) : id, id);
111
+ }
112
+ reset(id) {
113
+ const scenario = onboardingScenarioRegistry.getScenario(id);
114
+ delete this._state[scenario ? this._seenKey(scenario) : id];
115
+ this._memento.saveMemento();
116
+ }
117
+ resetAll() {
118
+ for (const key of ( Object.keys(this._state))) {
119
+ delete this._state[key];
120
+ }
121
+ this._memento.saveMemento();
122
+ }
123
+ get _enabled() {
124
+ return this.configurationService.getValue(ONBOARDING_ENABLED_CONFIG) !== false;
125
+ }
126
+ _isDeveloperMode(scenarioId) {
127
+ return isOnboardingDeveloperModeEnabled(this.configurationService, scenarioId);
128
+ }
129
+ _evaluate() {
130
+ if (!this._enabled || this._stopped) {
131
+ return;
132
+ }
133
+ const claimedSeenKeys = ( new Set());
134
+ for (const scenario of onboardingScenarioRegistry.getScenarios()) {
135
+ if (!scenario.repeatable && ( this._pending.has(scenario.id))) {
136
+ claimedSeenKeys.add(this._seenKey(scenario));
137
+ }
138
+ }
139
+ for (const scenario of onboardingScenarioRegistry.getScenarios()) {
140
+ if (!this._isAutoEligible(scenario)) {
141
+ continue;
142
+ }
143
+ const seenKey = this._seenKey(scenario);
144
+ if (!scenario.repeatable && ( claimedSeenKeys.has(seenKey))) {
145
+ continue;
146
+ }
147
+ const experiment = scenario.experiment ? this._experimentStates.get(scenario.id) : undefined;
148
+ if (experiment?.active && !this._isDeveloperMode(scenario.id)) {
149
+ this._openGate(experiment.assignmentContextId);
150
+ if (!experiment.behavior) {
151
+ continue;
152
+ }
153
+ }
154
+ this._enqueue(scenario);
155
+ if (!scenario.repeatable) {
156
+ claimedSeenKeys.add(seenKey);
157
+ }
158
+ }
159
+ }
160
+ _isAutoEligible(scenario) {
161
+ if (scenario.trigger.kind === "command") {
162
+ return false;
163
+ }
164
+ if (( this._pending.has(scenario.id))) {
165
+ return false;
166
+ }
167
+ if (!scenario.repeatable && this._hasBeenShownKey(this._seenKey(scenario), scenario.id)) {
168
+ return false;
169
+ }
170
+ if (scenario.when && !this.contextKeyService.contextMatchesRules(scenario.when)) {
171
+ return false;
172
+ }
173
+ if (scenario.experiment && this._experimentStates.get(scenario.id)?.active !== true && !this._isDeveloperMode(scenario.id)) {
174
+ return false;
175
+ }
176
+ if (scenario.trigger.kind === "observable" && scenario.trigger.signal.get() !== true) {
177
+ return false;
178
+ }
179
+ return true;
180
+ }
181
+ _enqueue(scenario) {
182
+ if (this._stopped) {
183
+ return Promise.resolve(OnboardingOutcome.Aborted);
184
+ }
185
+ const queued = this._queue.find(entry => entry.scenario.id === scenario.id);
186
+ if (queued) {
187
+ return queued.deferred.p;
188
+ }
189
+ const inflight = this._inflight.get(scenario.id);
190
+ if (inflight) {
191
+ return inflight.p;
192
+ }
193
+ const deferred = ( new DeferredPromise());
194
+ this._pending.add(scenario.id);
195
+ this._queue.push({
196
+ scenario,
197
+ deferred
198
+ });
199
+ this._queue.sort((a, b) => (b.scenario.priority ?? 0) - (a.scenario.priority ?? 0));
200
+ this._pump();
201
+ return deferred.p;
202
+ }
203
+ _pump() {
204
+ if (this._pumping) {
205
+ return;
206
+ }
207
+ this._pumping = true;
208
+ this._doPump();
209
+ }
210
+ async _doPump() {
211
+ await Promise.resolve();
212
+ try {
213
+ let entry;
214
+ while (!this._stopped && (entry = this._queue.shift())) {
215
+ const {
216
+ scenario,
217
+ deferred
218
+ } = entry;
219
+ this._inflight.set(scenario.id, deferred);
220
+ let outcome;
221
+ try {
222
+ outcome = await this._runPresentation(scenario);
223
+ } catch (error) {
224
+ onUnexpectedError(error);
225
+ outcome = OnboardingOutcome.Aborted;
226
+ } finally {
227
+ this._inflight.delete(scenario.id);
228
+ this._pending.delete(scenario.id);
229
+ }
230
+ deferred.complete(outcome);
231
+ }
232
+ } finally {
233
+ this._pumping = false;
234
+ }
235
+ }
236
+ async _runPresentation(scenario) {
237
+ const presentation = onboardingPresentationRegistry.get(scenario.presentation.kind);
238
+ if (!presentation) {
239
+ return OnboardingOutcome.Aborted;
240
+ }
241
+ this._markShown(this._seenKey(scenario));
242
+ const abort = ( new Emitter());
243
+ this._activeAbort = abort;
244
+ const startTime = Date.now();
245
+ try {
246
+ const result = await presentation.run(scenario, {
247
+ targetWindow: mainWindow,
248
+ onAbort: abort.event
249
+ });
250
+ this._recordOutcome(this._seenKey(scenario), result.outcome);
251
+ if (result.shown) {
252
+ this._reportOutcome(scenario, result, Date.now() - startTime);
253
+ }
254
+ return result.outcome;
255
+ } finally {
256
+ this._activeAbort = undefined;
257
+ abort.dispose();
258
+ }
259
+ }
260
+ _reportOutcome(scenario, result, durationMs) {
261
+ const experimentActive = !!scenario.experiment && this._experimentStates.get(scenario.id)?.active === true;
262
+ this.telemetryService.publicLog2("onboarding.scenarioOutcome", {
263
+ scenarioId: scenario.id,
264
+ outcome: result.outcome,
265
+ dismissReason: result.dismissReason,
266
+ lastStepIndex: result.lastStepIndex,
267
+ stepCount: result.stepCount,
268
+ durationMs,
269
+ experimentActive
270
+ });
271
+ }
272
+ _registerTriggerListeners() {
273
+ this._triggerListeners.clear();
274
+ for (const scenario of onboardingScenarioRegistry.getScenarios()) {
275
+ if (scenario.trigger.kind === "observable") {
276
+ const signal = scenario.trigger.signal;
277
+ this._triggerListeners.add(autorun(reader => {
278
+ signal.read(reader);
279
+ this._evaluate();
280
+ }));
281
+ }
282
+ }
283
+ }
284
+ _resolveExperiments() {
285
+ for (const scenario of onboardingScenarioRegistry.getScenarios()) {
286
+ const experiment = scenario.experiment;
287
+ if (!experiment || ( this._experimentStates.has(scenario.id))) {
288
+ continue;
289
+ }
290
+ this._experimentStates.set(scenario.id, {
291
+ active: false,
292
+ behavior: false,
293
+ assignmentContextId: ""
294
+ });
295
+ Promise.all([
296
+ this.assignmentService.getTreatment(experiment.behaviorFlag),
297
+ this.assignmentService.getTreatment(experiment.assignmentContextIdFlag)
298
+ ]).then(([behavior, assignmentContextId]) => {
299
+ const hasBehavior = typeof behavior === "boolean";
300
+ const hasId = typeof assignmentContextId === "string" && assignmentContextId.length > 0;
301
+ const hasValidId = hasId && assignmentContextId.startsWith(ONBOARDING_ASSIGNMENT_CONTEXT_PREFIX);
302
+ if (hasId && !hasValidId) {
303
+ onUnexpectedError(( new Error(
304
+ `Onboarding experiment for scenario '${scenario.id}' resolved an assignment-context id '${assignmentContextId}' that does not start with the required '${ONBOARDING_ASSIGNMENT_CONTEXT_PREFIX}' prefix; treating the experiment as inactive.`
305
+ )));
306
+ }
307
+ const active = hasBehavior && hasValidId;
308
+ this._experimentStates.set(scenario.id, {
309
+ active,
310
+ behavior: behavior === true,
311
+ assignmentContextId: active ? assignmentContextId : ""
312
+ });
313
+ if (active) {
314
+ this._evaluate();
315
+ }
316
+ }, error => onUnexpectedError(error));
317
+ }
318
+ }
319
+ _loadOpenedIds() {
320
+ const raw = this.storageService.get(
321
+ OnboardingScenarioService_1.OPENED_IDS_STORAGE_KEY,
322
+ StorageScope.APPLICATION
323
+ );
324
+ if (!raw) {
325
+ return ( new Set());
326
+ }
327
+ try {
328
+ const parsed = JSON.parse(raw);
329
+ return Array.isArray(parsed) ? ( new Set(parsed.filter(id => typeof id === "string"))) : ( new Set());
330
+ } catch (error) {
331
+ onUnexpectedError(error);
332
+ return ( new Set());
333
+ }
334
+ }
335
+ _openGate(assignmentContextId) {
336
+ if (!assignmentContextId || ( this._openedAssignmentContextIds.has(assignmentContextId))) {
337
+ return;
338
+ }
339
+ this._openedAssignmentContextIds.add(assignmentContextId);
340
+ this.storageService.store(
341
+ OnboardingScenarioService_1.OPENED_IDS_STORAGE_KEY,
342
+ JSON.stringify(Array.from(this._openedAssignmentContextIds)),
343
+ StorageScope.APPLICATION,
344
+ StorageTarget.MACHINE
345
+ );
346
+ this._onDidChangeOpenedIds.fire();
347
+ }
348
+ _seenKey(scenario) {
349
+ return scenario.seenKey ?? scenario.id;
350
+ }
351
+ _hasBeenShownKey(key, scenarioId) {
352
+ if (this._isDeveloperMode(scenarioId)) {
353
+ return ( this._shownSinceStart.has(key));
354
+ }
355
+ return !!this._state[key]?.shownAt;
356
+ }
357
+ _markShown(id) {
358
+ this._shownSinceStart.add(id);
359
+ const previous = this._state[id];
360
+ const next = {
361
+ shownAt: Date.now(),
362
+ outcome: previous?.outcome,
363
+ seenCount: (previous?.seenCount ?? 0) + 1
364
+ };
365
+ this._state[id] = next;
366
+ this._memento.saveMemento();
367
+ }
368
+ _recordOutcome(id, outcome) {
369
+ const state = this._state[id];
370
+ if (state) {
371
+ state.outcome = outcome;
372
+ this._memento.saveMemento();
373
+ }
374
+ }
375
+ };
376
+ OnboardingScenarioService = OnboardingScenarioService_1 = ( __decorate([( __param(0, IStorageService)), ( __param(1, IContextKeyService)), ( __param(2, IConfigurationService)), ( __param(3, ILifecycleService)), ( __param(4, IWorkbenchAssignmentService)), ( __param(5, ITelemetryService))], OnboardingScenarioService));
377
+
378
+ export { OnboardingScenarioService };
@@ -0,0 +1,31 @@
1
+ import { IDisposable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle";
2
+ /**
3
+ * Attribute used to mark a DOM element as an onboarding spotlight target.
4
+ *
5
+ * Components opt in by tagging their *own* element with this attribute. Tours
6
+ * reference the id; they never reach into another component's markup or CSS
7
+ * classes to locate a target (see the sessions "DOM Traversal & Intent" rule).
8
+ */
9
+ export declare const ONBOARDING_TARGET_ATTR = "data-onboarding-id";
10
+ export declare const ONBOARDING_TARGET_PULSE_CLASS = "onboarding-target-pulse";
11
+ /**
12
+ * Marks `element` as the onboarding target identified by `id`.
13
+ *
14
+ * @returns A disposable that removes the attribute again.
15
+ */
16
+ export declare function markOnboardingTarget(element: HTMLElement, id: string): IDisposable;
17
+ /**
18
+ * Applies the standard onboarding pulse treatment to `element`.
19
+ *
20
+ * @returns A disposable that removes the pulse again.
21
+ */
22
+ export declare function pulseOnboardingTarget(element: HTMLElement): IDisposable;
23
+ /**
24
+ * Resolves the element marked with the given onboarding target id within the
25
+ * provided window's document. Returns `undefined` if no such element exists
26
+ * (e.g. the feature is not currently rendered).
27
+ *
28
+ * This is the *only* place onboarding queries the DOM, and it matches solely on
29
+ * the onboarding attribute — never on foreign classes or structure.
30
+ */
31
+ export declare function findOnboardingTarget(targetWindow: Window, id: string): HTMLElement | undefined;
@@ -0,0 +1,25 @@
1
+
2
+ import { registerCss } from '@codingame/monaco-vscode-api/css';
3
+ import '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
4
+ import * as onboardingTarget from '../media/onboardingTarget.css';
5
+
6
+ registerCss(onboardingTarget);
7
+ const ONBOARDING_TARGET_ATTR = "data-onboarding-id";
8
+ function findOnboardingTarget(targetWindow, id) {
9
+ const selector = `[${ONBOARDING_TARGET_ATTR}="${CSS.escape(id)}"]`;
10
+ const targets = Array.from(targetWindow.document.querySelectorAll(selector));
11
+ return targets.find(target => isVisibleOnboardingTarget(targetWindow, target));
12
+ }
13
+ function isVisibleOnboardingTarget(targetWindow, target) {
14
+ if (!target.isConnected) {
15
+ return false;
16
+ }
17
+ const style = targetWindow.getComputedStyle(target);
18
+ if (style.display === "none" || style.visibility === "hidden") {
19
+ return false;
20
+ }
21
+ const rect = target.getBoundingClientRect();
22
+ return rect.width > 0 && rect.height > 0;
23
+ }
24
+
25
+ export { ONBOARDING_TARGET_ATTR, findOnboardingTarget };
@@ -0,0 +1,96 @@
1
+ import { Disposable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle";
2
+ import { Event } from "@codingame/monaco-vscode-api/vscode/vs/base/common/event";
3
+ import { IMarkdownString } from "@codingame/monaco-vscode-api/vscode/vs/base/common/htmlContent";
4
+ import { SpotlightPlacement } from "./spotlightTypes.js";
5
+ import { OnboardingDismissReason } from "../../common/onboardingScenario.js";
6
+ /** How the user advanced to the next step. */
7
+ export type SpotlightAdvanceSource = "button" | "target";
8
+ /** Why a step ended in a skip: the Skip button or the Escape key. */
9
+ export type SpotlightSkipReason = OnboardingDismissReason.SkipButton | OnboardingDismissReason.EscapeKey;
10
+ /** Content rendered inside the spotlight callout for a single step. */
11
+ export interface ISpotlightContent {
12
+ readonly title: string;
13
+ readonly description: string | IMarkdownString;
14
+ /** Zero-based index of the current step. */
15
+ readonly stepIndex: number;
16
+ /** Total number of steps in the tour. */
17
+ readonly stepCount: number;
18
+ /** Whether a "Back" action should be offered. */
19
+ readonly canGoBack: boolean;
20
+ /** Whether this is the final step (the primary button becomes "Done"). */
21
+ readonly isLastStep: boolean;
22
+ }
23
+ /** Options controlling how a step is shown. */
24
+ export interface ISpotlightShowOptions {
25
+ readonly placement?: SpotlightPlacement;
26
+ readonly allowTargetInteraction?: boolean;
27
+ readonly padding?: number;
28
+ /**
29
+ * When set, the step advances (fires `onDidClickNext`) when the user clicks
30
+ * the spotlighted target itself. The "Next" button is hidden and the target
31
+ * is kept interactive so the user can press it to continue.
32
+ */
33
+ readonly advanceOnTargetClick?: boolean;
34
+ }
35
+ /**
36
+ * A pure-DOM spotlight overlay: dims the window, cuts a highlight hole around a
37
+ * target element and shows an anchored callout. It owns no VS Code services so
38
+ * it can be unit-tested and reused. Scheduling and content come from the
39
+ * spotlight presentation.
40
+ */
41
+ export declare class SpotlightOverlay extends Disposable {
42
+ private readonly _container;
43
+ private readonly _resizeObserverCtor;
44
+ private readonly _root;
45
+ private readonly _blockers;
46
+ private readonly _hole;
47
+ private readonly _pointer;
48
+ private readonly _callout;
49
+ private readonly _title;
50
+ private readonly _description;
51
+ private readonly _counter;
52
+ private readonly _descriptionRenderStore;
53
+ private readonly _backButton;
54
+ private readonly _nextButton;
55
+ private readonly _skipButton;
56
+ /** Listeners scoped to the currently shown step (re-layout sources). */
57
+ private readonly _stepListeners;
58
+ private readonly _onDidClickNext;
59
+ readonly onDidClickNext: Event<SpotlightAdvanceSource>;
60
+ private readonly _onDidClickPrevious;
61
+ readonly onDidClickPrevious: Event<void>;
62
+ private readonly _onDidSkip;
63
+ readonly onDidSkip: Event<SpotlightSkipReason>;
64
+ private _target;
65
+ private _options;
66
+ private _previousFocus;
67
+ private _scheduledLayout;
68
+ constructor(_container: HTMLElement, _resizeObserverCtor?: typeof ResizeObserver);
69
+ /** Show `content` spotlighting `target`. */
70
+ show(target: HTMLElement, content: ISpotlightContent, options?: ISpotlightShowOptions): void;
71
+ /** Recompute the hole and callout positions for the current target. */
72
+ layout(): void;
73
+ private _layoutBlocker;
74
+ private _layoutCallout;
75
+ private _centerCallout;
76
+ private _getPointerSide;
77
+ private _offsetCalloutForPointer;
78
+ private _layoutPointer;
79
+ private _clamp;
80
+ private _resolvePlacement;
81
+ private _renderContent;
82
+ private _onKeyDown;
83
+ private _trapFocus;
84
+ /**
85
+ * The focusable elements participating in the focus trap, in DOM order: the
86
+ * spotlighted target (when the step advances by pressing it), then any
87
+ * interactive content in the (possibly markdown) description, then the visible
88
+ * action buttons. Including the target keeps the spotlighted control
89
+ * keyboard-reachable, and querying the description keeps markdown links
90
+ * reachable despite `aria-modal`.
91
+ */
92
+ private _collectFocusable;
93
+ scheduleLayout(): void;
94
+ private _restoreFocus;
95
+ dispose(): void;
96
+ }