stream-monaco 0.0.40 → 0.0.41

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.
@@ -264,32 +264,45 @@ function error(tag, ...args) {
264
264
 
265
265
  //#endregion
266
266
  //#region src/utils/height.ts
267
- function createHeightManager(container, computeNext) {
267
+ const DEFAULT_TRANSITION_MS = 120;
268
+ const DEFAULT_TRANSITION_EASING = "cubic-bezier(0.4, 0, 0.2, 1)";
269
+ const DEFAULT_HYSTERESIS_PX = 12;
270
+ const DEFAULT_DEBOUNCE_MS = 0;
271
+ function prefersReducedMotion() {
272
+ return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
273
+ }
274
+ function createHeightManager(container, computeNext, options = {}) {
275
+ const transitionMs = Math.max(0, options.transitionMs ?? DEFAULT_TRANSITION_MS);
276
+ const transitionEasing = options.transitionEasing ?? DEFAULT_TRANSITION_EASING;
277
+ const hysteresisPx = Math.max(0, options.hysteresisPx ?? DEFAULT_HYSTERESIS_PX);
278
+ const debounceMs = Math.max(0, options.debounceMs ?? DEFAULT_DEBOUNCE_MS);
279
+ const transitionEnabled = options.smooth === true && transitionMs > 0 && !prefersReducedMotion();
280
+ const previousTransition = container.style.transition || "";
281
+ const heightTransition = `height ${transitionMs}ms ${transitionEasing}`;
282
+ if (transitionEnabled) container.style.transition = previousTransition ? `${previousTransition}, ${heightTransition}` : heightTransition;
268
283
  let raf = null;
269
284
  let debounceTimer = null;
270
285
  let lastApplied = -1;
271
286
  let suppressed = false;
272
- const HYSTERESIS_PX = 12;
273
- const DEBOUNCE_MS = 0;
274
287
  function apply() {
275
288
  var _container$getBoundin;
276
289
  const next = computeNext();
277
- if (next == null) return;
290
+ if (next == null) return null;
278
291
  log("heightManager", "computeNext ->", {
279
292
  next,
280
293
  lastApplied
281
294
  });
282
295
  if (!Number.isFinite(next) || next <= 0) {
283
296
  log("heightManager", "invalid next height, ignoring", next);
284
- return;
297
+ return null;
285
298
  }
286
299
  const currentHeight = Number.parseFloat(container.style.height || "") || ((_container$getBoundin = container.getBoundingClientRect) === null || _container$getBoundin === void 0 ? void 0 : _container$getBoundin.call(container).height) || 0;
287
- if (currentHeight > 0 && Math.abs(next - currentHeight) <= HYSTERESIS_PX) {
300
+ if (currentHeight > 0 && Math.abs(next - currentHeight) <= hysteresisPx) {
288
301
  lastApplied = next;
289
- return;
302
+ return next;
290
303
  }
291
- if (lastApplied !== -1 && Math.abs(next - lastApplied) <= HYSTERESIS_PX) return;
292
- if (next === lastApplied) return;
304
+ if (lastApplied !== -1 && Math.abs(next - lastApplied) <= hysteresisPx) return next;
305
+ if (next === lastApplied) return next;
293
306
  suppressed = true;
294
307
  container.style.height = `${next}px`;
295
308
  lastApplied = next;
@@ -297,13 +310,14 @@ function createHeightManager(container, computeNext) {
297
310
  queueMicrotask(() => {
298
311
  suppressed = false;
299
312
  });
313
+ return next;
300
314
  }
301
315
  function scheduleApply() {
302
316
  if (debounceTimer != null) {
303
317
  clearTimeout(debounceTimer);
304
318
  debounceTimer = null;
305
319
  }
306
- if (DEBOUNCE_MS === 0) {
320
+ if (debounceMs === 0) {
307
321
  if (raf != null) return;
308
322
  raf = requestAnimationFrame(() => {
309
323
  raf = null;
@@ -318,11 +332,22 @@ function createHeightManager(container, computeNext) {
318
332
  raf = null;
319
333
  apply();
320
334
  });
321
- }, DEBOUNCE_MS);
335
+ }, debounceMs);
322
336
  }
323
337
  function update() {
324
338
  scheduleApply();
325
339
  }
340
+ function updateNow() {
341
+ if (raf != null) {
342
+ cancelAnimationFrame(raf);
343
+ raf = null;
344
+ }
345
+ if (debounceTimer != null) {
346
+ clearTimeout(debounceTimer);
347
+ debounceTimer = null;
348
+ }
349
+ return apply();
350
+ }
326
351
  function dispose() {
327
352
  if (raf != null) {
328
353
  cancelAnimationFrame(raf);
@@ -332,6 +357,10 @@ function createHeightManager(container, computeNext) {
332
357
  clearTimeout(debounceTimer);
333
358
  debounceTimer = null;
334
359
  }
360
+ if (transitionEnabled) {
361
+ const currentTransition = container.style.transition || "";
362
+ if (currentTransition.includes(heightTransition)) container.style.transition = currentTransition.replace(heightTransition, "").replace(/\s*,\s*,\s*/g, ", ").replace(/^\s*,\s*|\s*,\s*$/g, "").trim();
363
+ }
335
364
  }
336
365
  function isSuppressed() {
337
366
  return suppressed;
@@ -339,11 +368,16 @@ function createHeightManager(container, computeNext) {
339
368
  function getLastApplied() {
340
369
  return lastApplied;
341
370
  }
371
+ function getTransitionMs() {
372
+ return transitionEnabled ? transitionMs : 0;
373
+ }
342
374
  return {
343
375
  update,
376
+ updateNow,
344
377
  dispose,
345
378
  isSuppressed,
346
- getLastApplied
379
+ getLastApplied,
380
+ getTransitionMs
347
381
  };
348
382
  }
349
383
 
@@ -1434,6 +1468,7 @@ var DiffEditorManager = class DiffEditorManager {
1434
1468
  }
1435
1469
  }
1436
1470
  clearAsyncWork() {
1471
+ this.revealTicketDiff += 1;
1437
1472
  this.cancelRafs();
1438
1473
  this.pendingDiffUpdate = null;
1439
1474
  this.lastKnownModifiedDirty = false;
@@ -4971,7 +5006,6 @@ var DiffEditorManager = class DiffEditorManager {
4971
5006
  this.lastContainer.innerHTML = "";
4972
5007
  this.lastContainer = null;
4973
5008
  }
4974
- this.revealTicketDiff = 0;
4975
5009
  this.lastRevealLineDiff = null;
4976
5010
  this.diffPersistedUnchangedModelState = null;
4977
5011
  this.diffPreviousUnchangedModelState = null;
@@ -4999,7 +5033,6 @@ var DiffEditorManager = class DiffEditorManager {
4999
5033
  this.diffHeightManager.dispose();
5000
5034
  this.diffHeightManager = null;
5001
5035
  }
5002
- this.revealTicketDiff = 0;
5003
5036
  this.lastRevealLineDiff = null;
5004
5037
  this.diffPersistedUnchangedModelState = null;
5005
5038
  this.diffPreviousUnchangedModelState = null;
@@ -5278,6 +5311,12 @@ var DiffEditorManager = class DiffEditorManager {
5278
5311
 
5279
5312
  //#endregion
5280
5313
  //#region src/core/EditorManager.ts
5314
+ const defaultHeightTransitionMs = 120;
5315
+ const defaultHeightTransitionEasing = "cubic-bezier(0.4, 0, 0.2, 1)";
5316
+ const smoothHeightTolerancePx = 1;
5317
+ const legacyHeightTolerancePx = 12;
5318
+ const smoothHeightDebounceMs = 16;
5319
+ const legacyHeightDebounceMs = 0;
5281
5320
  var EditorManager = class {
5282
5321
  editorView = null;
5283
5322
  lastContainer = null;
@@ -5324,10 +5363,12 @@ var EditorManager = class {
5324
5363
  appendBufferScheduled = false;
5325
5364
  rafScheduler = createRafScheduler();
5326
5365
  editorHeightManager = null;
5366
+ previousScrollbarGutter = null;
5327
5367
  revealDebounceId = null;
5328
5368
  revealDebounceMs = defaultRevealDebounceMs;
5329
5369
  revealIdleTimerId = null;
5330
5370
  revealTicket = 0;
5371
+ layoutTicket = 0;
5331
5372
  revealStrategyOption;
5332
5373
  revealBatchOnIdleMsOption;
5333
5374
  scrollWatcherSuppressionMs = 500;
@@ -5352,6 +5393,7 @@ var EditorManager = class {
5352
5393
  this.rafScheduler.cancel("maybe-scroll");
5353
5394
  this.rafScheduler.cancel("reveal");
5354
5395
  this.rafScheduler.cancel("immediate-reveal");
5396
+ this.rafScheduler.cancel("layout-after-height");
5355
5397
  this.rafScheduler.cancel("maybe-resume");
5356
5398
  this.rafScheduler.cancel("append");
5357
5399
  }
@@ -5370,6 +5412,8 @@ var EditorManager = class {
5370
5412
  this.appendBuffer.length = 0;
5371
5413
  }
5372
5414
  clearAsyncWork() {
5415
+ this.revealTicket += 1;
5416
+ this.layoutTicket += 1;
5373
5417
  this.cancelRafs();
5374
5418
  this.pendingUpdate = null;
5375
5419
  this.lastKnownCodeDirty = false;
@@ -5414,6 +5458,37 @@ var EditorManager = class {
5414
5458
  if (!m) return false;
5415
5459
  return this._hasScrollBar = m.scrollHeight > m.computedHeight + padding / 2;
5416
5460
  }
5461
+ isSmoothHeightTransitionEnabled() {
5462
+ return this.options.smoothHeightTransition ?? false;
5463
+ }
5464
+ isAutomaticLayoutEnabled() {
5465
+ return this.options.automaticLayout !== false;
5466
+ }
5467
+ getHeightChangeTolerancePx() {
5468
+ return this.options.heightChangeTolerancePx ?? (this.isSmoothHeightTransitionEnabled() ? smoothHeightTolerancePx : legacyHeightTolerancePx);
5469
+ }
5470
+ getHeightManagerOptions() {
5471
+ const smooth = this.isSmoothHeightTransitionEnabled();
5472
+ return {
5473
+ smooth,
5474
+ transitionMs: this.options.heightTransitionMs ?? defaultHeightTransitionMs,
5475
+ transitionEasing: this.options.heightTransitionEasing ?? defaultHeightTransitionEasing,
5476
+ debounceMs: this.options.heightUpdateDebounceMs ?? (smooth ? smoothHeightDebounceMs : legacyHeightDebounceMs),
5477
+ hysteresisPx: this.getHeightChangeTolerancePx()
5478
+ };
5479
+ }
5480
+ setOverflowForHeight(computed$2) {
5481
+ if (!this.lastContainer) return null;
5482
+ const next = computed$2 >= this.maxHeightValue - 1 ? "auto" : "hidden";
5483
+ const prev = this.lastContainer.style.overflow;
5484
+ if (prev !== next) this.lastContainer.style.overflow = next;
5485
+ if (next === "hidden") this._hasScrollBar = false;
5486
+ return {
5487
+ prev,
5488
+ next,
5489
+ changed: prev !== next
5490
+ };
5491
+ }
5417
5492
  userIsNearBottom() {
5418
5493
  if (!this.editorView) return true;
5419
5494
  const m = this.measureViewport();
@@ -5548,46 +5623,89 @@ var EditorManager = class {
5548
5623
  this.lastScrollTop = ((_this$editorView4 = this.editorView) === null || _this$editorView4 === void 0 || (_this$editorView4$get = _this$editorView4.getScrollTop) === null || _this$editorView4$get === void 0 ? void 0 : _this$editorView4$get.call(_this$editorView4)) ?? this.lastScrollTop;
5549
5624
  } catch {}
5550
5625
  }
5551
- isOverflowAuto() {
5552
- try {
5553
- return !!this.lastContainer && this.lastContainer.style.overflow === "auto";
5554
- } catch {
5555
- return false;
5556
- }
5557
- }
5558
- shouldPerformImmediateReveal() {
5559
- return this.autoScrollOnUpdate && this.shouldAutoScroll && this.hasVerticalScrollbar() && this.isOverflowAuto();
5626
+ shouldRevealAfterLayout() {
5627
+ return this.autoScrollOnUpdate && this.shouldAutoScroll;
5628
+ }
5629
+ getRevealSuppressionMs() {
5630
+ var _this$editorHeightMan, _this$editorHeightMan2;
5631
+ const transitionMs = ((_this$editorHeightMan = this.editorHeightManager) === null || _this$editorHeightMan === void 0 || (_this$editorHeightMan2 = _this$editorHeightMan.getTransitionMs) === null || _this$editorHeightMan2 === void 0 ? void 0 : _this$editorHeightMan2.call(_this$editorHeightMan)) ?? 0;
5632
+ return Math.max(this.scrollWatcherSuppressionMs, transitionMs + 100);
5633
+ }
5634
+ syncHeightAndRevealAfterContentChange(targetLine) {
5635
+ const shouldReveal = this.shouldRevealAfterLayout();
5636
+ const willReveal = !!(shouldReveal && this.editorView && this.computedHeight(this.editorView) >= this.maxHeightValue - 1);
5637
+ if (willReveal) this.suppressScrollWatcher(this.getRevealSuppressionMs());
5638
+ const computed$2 = this.syncNonOverflowingLayout();
5639
+ if (computed$2 != null && computed$2 >= this.maxHeightValue - 1 && shouldReveal) {
5640
+ var _this$editorView5;
5641
+ const line = targetLine ?? ((_this$editorView5 = this.editorView) === null || _this$editorView5 === void 0 || (_this$editorView5 = _this$editorView5.getModel()) === null || _this$editorView5 === void 0 ? void 0 : _this$editorView5.getLineCount()) ?? 1;
5642
+ if (this.isSmoothHeightTransitionEnabled()) this.scheduleImmediateRevealAfterLayout(line);
5643
+ else this.forceReveal(line);
5644
+ } else if (!shouldReveal && targetLine != null) this.maybeScrollToBottom(targetLine);
5645
+ return computed$2;
5560
5646
  }
5561
5647
  syncNonOverflowingLayout() {
5562
- var _this$lastContainer$g, _this$lastContainer;
5648
+ var _this$editorHeightMan3, _this$editorHeightMan4;
5563
5649
  if (!this.editorView || !this.lastContainer) return null;
5564
5650
  const computed$2 = this.computedHeight(this.editorView);
5651
+ const needsRevealSync = computed$2 >= this.maxHeightValue - 1 && this.shouldRevealAfterLayout();
5652
+ const useSmoothHeightTransition = this.isSmoothHeightTransitionEnabled();
5653
+ if (needsRevealSync || !useSmoothHeightTransition) (_this$editorHeightMan3 = this.editorHeightManager) === null || _this$editorHeightMan3 === void 0 || _this$editorHeightMan3.updateNow();
5654
+ else (_this$editorHeightMan4 = this.editorHeightManager) === null || _this$editorHeightMan4 === void 0 || _this$editorHeightMan4.update();
5655
+ this.setOverflowForHeight(computed$2);
5565
5656
  if (computed$2 >= this.maxHeightValue - 1) {
5566
- this.lastContainer.style.height = `${this.maxHeightValue}px`;
5657
+ if (useSmoothHeightTransition) this.scheduleLayoutAfterHeightApplied(computed$2);
5567
5658
  return computed$2;
5568
5659
  }
5569
- const currentHeight = Number.parseFloat(this.lastContainer.style.height || "") || ((_this$lastContainer$g = (_this$lastContainer = this.lastContainer).getBoundingClientRect) === null || _this$lastContainer$g === void 0 ? void 0 : _this$lastContainer$g.call(_this$lastContainer).height) || 0;
5570
- if (currentHeight <= 0 || Math.abs(computed$2 - currentHeight) > 12) this.lastContainer.style.height = `${computed$2}px`;
5571
- this.lastContainer.style.overflow = "hidden";
5572
5660
  this._hasScrollBar = false;
5661
+ if (useSmoothHeightTransition) {
5662
+ this.scheduleLayoutAfterHeightApplied(computed$2);
5663
+ try {
5664
+ var _this$editorView$getS3, _this$editorView6, _this$editorView$setS, _this$editorView7;
5665
+ if ((((_this$editorView$getS3 = (_this$editorView6 = this.editorView).getScrollTop) === null || _this$editorView$getS3 === void 0 ? void 0 : _this$editorView$getS3.call(_this$editorView6)) ?? 0) !== 0) (_this$editorView$setS = (_this$editorView7 = this.editorView).setScrollTop) === null || _this$editorView$setS === void 0 || _this$editorView$setS.call(_this$editorView7, 0);
5666
+ this.lastScrollTop = 0;
5667
+ } catch {}
5668
+ return computed$2;
5669
+ }
5573
5670
  try {
5574
- var _this$editorView$layo, _this$editorView5;
5575
- (_this$editorView$layo = (_this$editorView5 = this.editorView).layout) === null || _this$editorView$layo === void 0 || _this$editorView$layo.call(_this$editorView5);
5671
+ var _this$editorView$layo, _this$editorView8;
5672
+ (_this$editorView$layo = (_this$editorView8 = this.editorView).layout) === null || _this$editorView$layo === void 0 || _this$editorView$layo.call(_this$editorView8);
5576
5673
  } catch {}
5577
5674
  try {
5578
- var _this$editorView$getS3, _this$editorView6, _this$editorView$setS, _this$editorView7;
5579
- if ((((_this$editorView$getS3 = (_this$editorView6 = this.editorView).getScrollTop) === null || _this$editorView$getS3 === void 0 ? void 0 : _this$editorView$getS3.call(_this$editorView6)) ?? 0) !== 0) (_this$editorView$setS = (_this$editorView7 = this.editorView).setScrollTop) === null || _this$editorView$setS === void 0 || _this$editorView$setS.call(_this$editorView7, 0);
5675
+ var _this$editorView$getS4, _this$editorView9, _this$editorView$setS2, _this$editorView10;
5676
+ if ((((_this$editorView$getS4 = (_this$editorView9 = this.editorView).getScrollTop) === null || _this$editorView$getS4 === void 0 ? void 0 : _this$editorView$getS4.call(_this$editorView9)) ?? 0) !== 0) (_this$editorView$setS2 = (_this$editorView10 = this.editorView).setScrollTop) === null || _this$editorView$setS2 === void 0 || _this$editorView$setS2.call(_this$editorView10, 0);
5580
5677
  this.lastScrollTop = 0;
5581
5678
  } catch {}
5582
5679
  return computed$2;
5583
5680
  }
5681
+ scheduleLayoutAfterHeightApplied(target) {
5682
+ if (this.isAutomaticLayoutEnabled() || !this.editorView) return;
5683
+ const editor = this.editorView;
5684
+ const ticket = ++this.layoutTicket;
5685
+ this.rafScheduler.schedule("layout-after-height", async () => {
5686
+ try {
5687
+ var _editor$layout;
5688
+ await this.waitForHeightApplied(target, 500);
5689
+ if (ticket !== this.layoutTicket || this.editorView !== editor) return;
5690
+ (_editor$layout = editor.layout) === null || _editor$layout === void 0 || _editor$layout.call(editor);
5691
+ this.measureViewport();
5692
+ } catch (err) {
5693
+ error("EditorManager", "scheduleLayoutAfterHeightApplied error", err);
5694
+ }
5695
+ });
5696
+ }
5584
5697
  async createEditor(container, code, language, currentTheme) {
5585
- var _this$editorView$getS4, _this$editorView8, _this$editorView$getO, _this$editorView9, _this$editorView$getM, _this$editorView$onDi, _this$editorView10;
5698
+ var _this$editorView$getS5, _this$editorView11, _this$editorView$getO, _this$editorView12, _this$editorView$getM, _this$editorView$onDi, _this$editorView13;
5586
5699
  this.cleanup();
5587
5700
  this.lastContainer = container;
5588
5701
  this.initDebugFlag();
5589
5702
  this.dlog("createEditor container, maxHeight", this.maxHeightValue);
5590
5703
  container.style.overflow = "hidden";
5704
+ this.previousScrollbarGutter = null;
5705
+ if (this.isSmoothHeightTransitionEnabled()) {
5706
+ this.previousScrollbarGutter = container.style.scrollbarGutter || "";
5707
+ container.style.scrollbarGutter = "stable";
5708
+ }
5591
5709
  container.style.maxHeight = this.maxHeightCSS;
5592
5710
  this.editorView = monaco_shim_exports.editor.create(container, {
5593
5711
  value: code,
@@ -5621,43 +5739,29 @@ var EditorManager = class {
5621
5739
  this.editorHeightManager = createHeightManager(container, () => {
5622
5740
  const computed$2 = this.computedHeight(this.editorView);
5623
5741
  return Math.min(computed$2, this.maxHeightValue);
5624
- });
5625
- this.editorHeightManager.update();
5626
- const initialComputed = this.computedHeight(this.editorView);
5627
- if (initialComputed >= this.maxHeightValue - 1) {
5628
- container.style.height = `${this.maxHeightValue}px`;
5629
- container.style.overflow = "auto";
5630
- this.dlog("applied immediate maxHeight on createEditor", this.maxHeightValue);
5631
- }
5632
- this.cachedScrollHeight = ((_this$editorView$getS4 = (_this$editorView8 = this.editorView).getScrollHeight) === null || _this$editorView$getS4 === void 0 ? void 0 : _this$editorView$getS4.call(_this$editorView8)) ?? null;
5633
- this.cachedLineHeight = ((_this$editorView$getO = (_this$editorView9 = this.editorView).getOption) === null || _this$editorView$getO === void 0 ? void 0 : _this$editorView$getO.call(_this$editorView9, monaco_shim_exports.editor.EditorOption.lineHeight)) ?? null;
5742
+ }, this.getHeightManagerOptions());
5743
+ const initialComputed = this.editorHeightManager.updateNow();
5744
+ if (initialComputed != null) this.setOverflowForHeight(initialComputed);
5745
+ this.cachedScrollHeight = ((_this$editorView$getS5 = (_this$editorView11 = this.editorView).getScrollHeight) === null || _this$editorView$getS5 === void 0 ? void 0 : _this$editorView$getS5.call(_this$editorView11)) ?? null;
5746
+ this.cachedLineHeight = ((_this$editorView$getO = (_this$editorView12 = this.editorView).getOption) === null || _this$editorView$getO === void 0 ? void 0 : _this$editorView$getO.call(_this$editorView12, monaco_shim_exports.editor.EditorOption.lineHeight)) ?? null;
5634
5747
  this.cachedComputedHeight = this.computedHeight(this.editorView);
5635
5748
  this.cachedLineCount = ((_this$editorView$getM = this.editorView.getModel()) === null || _this$editorView$getM === void 0 ? void 0 : _this$editorView$getM.getLineCount()) ?? null;
5636
- (_this$editorView$onDi = (_this$editorView10 = this.editorView).onDidContentSizeChange) === null || _this$editorView$onDi === void 0 || _this$editorView$onDi.call(_this$editorView10, () => {
5749
+ (_this$editorView$onDi = (_this$editorView13 = this.editorView).onDidContentSizeChange) === null || _this$editorView$onDi === void 0 || _this$editorView$onDi.call(_this$editorView13, () => {
5637
5750
  this._hasScrollBar = false;
5638
5751
  this.rafScheduler.schedule("content-size-change", () => {
5639
5752
  try {
5640
- var _this$editorView11, _this$editorHeightMan, _this$editorHeightMan2;
5753
+ var _this$editorView14, _this$editorHeightMan5;
5641
5754
  this.dlog("content-size-change frame");
5642
- this.cachedLineCount = ((_this$editorView11 = this.editorView) === null || _this$editorView11 === void 0 || (_this$editorView11 = _this$editorView11.getModel()) === null || _this$editorView11 === void 0 ? void 0 : _this$editorView11.getLineCount()) ?? this.cachedLineCount;
5755
+ this.cachedLineCount = ((_this$editorView14 = this.editorView) === null || _this$editorView14 === void 0 || (_this$editorView14 = _this$editorView14.getModel()) === null || _this$editorView14 === void 0 ? void 0 : _this$editorView14.getLineCount()) ?? this.cachedLineCount;
5643
5756
  this.cachedComputedHeight = null;
5644
5757
  const m = this.measureViewport();
5645
5758
  this.dlog("content-size-change measure", m);
5646
- if ((_this$editorHeightMan = this.editorHeightManager) === null || _this$editorHeightMan === void 0 ? void 0 : _this$editorHeightMan.isSuppressed()) {
5759
+ if ((_this$editorHeightMan5 = this.editorHeightManager) === null || _this$editorHeightMan5 === void 0 ? void 0 : _this$editorHeightMan5.isSuppressed()) {
5647
5760
  this.dlog("content-size-change skipped height update (suppressed)");
5648
5761
  return;
5649
5762
  }
5650
- this.dlog("content-size-change calling heightManager.update");
5651
- (_this$editorHeightMan2 = this.editorHeightManager) === null || _this$editorHeightMan2 === void 0 || _this$editorHeightMan2.update();
5652
- const computed$2 = this.computedHeight(this.editorView);
5653
- if (this.lastContainer) {
5654
- const prevOverflow = this.lastContainer.style.overflow;
5655
- const newOverflow = computed$2 >= this.maxHeightValue - 1 ? "auto" : "hidden";
5656
- if (prevOverflow !== newOverflow) {
5657
- this.lastContainer.style.overflow = newOverflow;
5658
- if (newOverflow === "auto" && this.shouldAutoScroll) this.maybeScrollToBottom();
5659
- }
5660
- }
5763
+ this.dlog("content-size-change syncing height/reveal");
5764
+ this.syncHeightAndRevealAfterContentChange();
5661
5765
  } catch (err) {
5662
5766
  error("EditorManager", "content-size-change error", err);
5663
5767
  }
@@ -5725,6 +5829,11 @@ var EditorManager = class {
5725
5829
  if (target !== -1 && this.editorHeightManager) await this.waitForHeightApplied(target, 500);
5726
5830
  else await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(() => r())));
5727
5831
  this.dlog("running delayed immediate reveal", "ticket=", ticket, "line=", line);
5832
+ if (ticket !== this.revealTicket) {
5833
+ this.dlog("delayed immediate reveal skipped, stale ticket", ticket, "current", this.revealTicket);
5834
+ return;
5835
+ }
5836
+ this.suppressScrollWatcher(this.scrollWatcherSuppressionMs);
5728
5837
  this.performImmediateReveal(line, ticket);
5729
5838
  } catch (err) {
5730
5839
  error("EditorManager", "scheduleImmediateRevealAfterLayout error", err);
@@ -5733,20 +5842,33 @@ var EditorManager = class {
5733
5842
  }
5734
5843
  waitForHeightApplied(target, timeoutMs = 500) {
5735
5844
  return new Promise((resolve) => {
5845
+ var _this$editorHeightMan6, _this$editorHeightMan7;
5736
5846
  const start = typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
5847
+ const tolerance = this.getHeightChangeTolerancePx();
5848
+ const transitionMs = ((_this$editorHeightMan6 = this.editorHeightManager) === null || _this$editorHeightMan6 === void 0 || (_this$editorHeightMan7 = _this$editorHeightMan6.getTransitionMs) === null || _this$editorHeightMan7 === void 0 ? void 0 : _this$editorHeightMan7.call(_this$editorHeightMan6)) ?? 0;
5849
+ let settled = false;
5850
+ const resolveAfterSettle = () => {
5851
+ if (settled) return;
5852
+ settled = true;
5853
+ if (transitionMs > 0) {
5854
+ setTimeout(resolve, transitionMs);
5855
+ return;
5856
+ }
5857
+ requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
5858
+ };
5737
5859
  const check = () => {
5738
5860
  try {
5739
- var _this$editorHeightMan3, _this$editorHeightMan4;
5740
- const last = ((_this$editorHeightMan3 = this.editorHeightManager) === null || _this$editorHeightMan3 === void 0 || (_this$editorHeightMan4 = _this$editorHeightMan3.getLastApplied) === null || _this$editorHeightMan4 === void 0 ? void 0 : _this$editorHeightMan4.call(_this$editorHeightMan3)) ?? -1;
5741
- if (last !== -1 && Math.abs(last - target) <= 12) {
5861
+ var _this$editorHeightMan8, _this$editorHeightMan9;
5862
+ const last = ((_this$editorHeightMan8 = this.editorHeightManager) === null || _this$editorHeightMan8 === void 0 || (_this$editorHeightMan9 = _this$editorHeightMan8.getLastApplied) === null || _this$editorHeightMan9 === void 0 ? void 0 : _this$editorHeightMan9.call(_this$editorHeightMan8)) ?? -1;
5863
+ if (last !== -1 && Math.abs(last - target) <= tolerance) {
5742
5864
  this.dlog("waitForHeightApplied satisfied", last, "target=", target);
5743
- resolve();
5865
+ resolveAfterSettle();
5744
5866
  return;
5745
5867
  }
5746
5868
  const now = typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
5747
5869
  if (now - start > timeoutMs) {
5748
5870
  log("EditorManager", "waitForHeightApplied timeout", last, "target=", target);
5749
- resolve();
5871
+ resolveAfterSettle();
5750
5872
  return;
5751
5873
  }
5752
5874
  } catch {}
@@ -5798,12 +5920,7 @@ var EditorManager = class {
5798
5920
  const newLineCount$1 = model.getLineCount();
5799
5921
  this.cachedLineCount = newLineCount$1;
5800
5922
  this.cachedComputedHeight = null;
5801
- if (newLineCount$1 !== prevLineCount$1) {
5802
- const shouldImmediate = this.shouldPerformImmediateReveal();
5803
- if (shouldImmediate) this.suppressScrollWatcher(this.scrollWatcherSuppressionMs);
5804
- const computed$2 = this.syncNonOverflowingLayout();
5805
- if (computed$2 != null && computed$2 >= this.maxHeightValue - 1) this.forceReveal(newLineCount$1);
5806
- }
5923
+ if (newLineCount$1 !== prevLineCount$1) this.syncHeightAndRevealAfterContentChange(newLineCount$1);
5807
5924
  return;
5808
5925
  }
5809
5926
  let prevCode;
@@ -5833,13 +5950,7 @@ var EditorManager = class {
5833
5950
  const newLineCount = model.getLineCount();
5834
5951
  this.cachedLineCount = newLineCount;
5835
5952
  this.cachedComputedHeight = null;
5836
- if (newLineCount !== prevLineCount) {
5837
- const shouldImmediate = this.shouldPerformImmediateReveal();
5838
- if (shouldImmediate) this.suppressScrollWatcher(this.scrollWatcherSuppressionMs);
5839
- this.syncNonOverflowingLayout();
5840
- if (shouldImmediate) this.scheduleImmediateRevealAfterLayout(newLineCount);
5841
- else this.maybeScrollToBottom(newLineCount);
5842
- }
5953
+ if (newLineCount !== prevLineCount) this.syncHeightAndRevealAfterContentChange(newLineCount);
5843
5954
  }
5844
5955
  appendCode(appendText, codeLanguage) {
5845
5956
  if (!this.editorView) return;
@@ -5871,10 +5982,7 @@ var EditorManager = class {
5871
5982
  this.lastKnownCode = next;
5872
5983
  const newLineCount = model.getLineCount();
5873
5984
  this.cachedLineCount = newLineCount;
5874
- if (newLineCount !== prevLineCount) {
5875
- this.syncNonOverflowingLayout();
5876
- this.maybeScrollToBottom(newLineCount);
5877
- }
5985
+ if (newLineCount !== prevLineCount) this.syncHeightAndRevealAfterContentChange(newLineCount);
5878
5986
  return;
5879
5987
  }
5880
5988
  const res = computeMinimalEdit(prev, next);
@@ -5927,13 +6035,7 @@ var EditorManager = class {
5927
6035
  if (lastLine !== newLineCount) {
5928
6036
  this.cachedLineCount = newLineCount;
5929
6037
  this.cachedComputedHeight = null;
5930
- const shouldImmediate = this.shouldPerformImmediateReveal();
5931
- if (shouldImmediate) this.suppressScrollWatcher(this.scrollWatcherSuppressionMs);
5932
- this.syncNonOverflowingLayout();
5933
- if (shouldImmediate) try {
5934
- this.forceReveal(newLineCount);
5935
- } catch {}
5936
- else this.maybeScrollToBottom(newLineCount);
6038
+ this.syncHeightAndRevealAfterContentChange(newLineCount);
5937
6039
  }
5938
6040
  }
5939
6041
  setLanguage(language, languages$1) {
@@ -5948,8 +6050,8 @@ var EditorManager = class {
5948
6050
  return this.editorView;
5949
6051
  }
5950
6052
  getCode() {
5951
- var _this$editorView12;
5952
- return ((_this$editorView12 = this.editorView) === null || _this$editorView12 === void 0 || (_this$editorView12 = _this$editorView12.getModel()) === null || _this$editorView12 === void 0 ? void 0 : _this$editorView12.getValue()) ?? null;
6053
+ var _this$editorView15;
6054
+ return ((_this$editorView15 = this.editorView) === null || _this$editorView15 === void 0 || (_this$editorView15 = _this$editorView15.getModel()) === null || _this$editorView15 === void 0 ? void 0 : _this$editorView15.getValue()) ?? null;
5953
6055
  }
5954
6056
  setUpdateThrottleMs(ms) {
5955
6057
  this.updateThrottleMs = ms;
@@ -5970,6 +6072,8 @@ var EditorManager = class {
5970
6072
  }
5971
6073
  this.lastKnownCode = null;
5972
6074
  if (this.lastContainer) {
6075
+ if (this.previousScrollbarGutter != null) this.lastContainer.style.scrollbarGutter = this.previousScrollbarGutter;
6076
+ this.previousScrollbarGutter = null;
5973
6077
  this.lastContainer.style.minHeight = "";
5974
6078
  this.lastContainer.innerHTML = "";
5975
6079
  this.lastContainer = null;
@@ -5994,6 +6098,8 @@ var EditorManager = class {
5994
6098
  this._hasScrollBar = false;
5995
6099
  this.shouldAutoScroll = !!this.autoScrollInitial;
5996
6100
  this.lastScrollTop = 0;
6101
+ if (this.lastContainer && this.previousScrollbarGutter != null) this.lastContainer.style.scrollbarGutter = this.previousScrollbarGutter;
6102
+ this.previousScrollbarGutter = null;
5997
6103
  if (this.editorHeightManager) {
5998
6104
  this.editorHeightManager.dispose();
5999
6105
  this.editorHeightManager = null;
@@ -6300,7 +6406,7 @@ let globalAppliedThemeName = null;
6300
6406
  * @param {MonacoLanguage[]} [monacoOptions.languages] - 支持的编程语言数组
6301
6407
  * @param {string} [monacoOptions.theme] - 初始主题名称
6302
6408
  * @param {boolean} [monacoOptions.isCleanOnBeforeCreate] - 是否在创建前清理之前注册的资源, 默认为 true
6303
- * @param {(monaco: typeof import('monaco-editor')) => monaco.IDisposable[]} [monacoOptions.onBeforeCreate] - 编辑器创建前的钩子函数
6409
+ * @param {(monaco: typeof import('monaco-editor/esm/vs/editor/editor.api')) => monaco.IDisposable[]} [monacoOptions.onBeforeCreate] - 编辑器创建前的钩子函数
6304
6410
  *
6305
6411
  * @returns {{
6306
6412
  * createEditor: (container: HTMLElement, code: string, language: string) => Promise<monaco.editor.IStandaloneCodeEditor>,
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "stream-monaco",
3
3
  "type": "module",
4
- "version": "0.0.40",
5
- "packageManager": "pnpm@10.33.2",
4
+ "version": "0.0.41",
6
5
  "description": "A framework-agnostic Monaco Editor integration with Shiki syntax highlighting, built for real-time streaming updates and efficient diff editing.",
7
6
  "author": "Simon He",
8
7
  "license": "MIT",
@@ -74,33 +73,6 @@
74
73
  "legacy.d.ts",
75
74
  "legacy.js"
76
75
  ],
77
- "scripts": {
78
- "build": "tsdown",
79
- "dev": "npm run build -- --watch src",
80
- "format": "prettier --write --cache .",
81
- "lint": "eslint . --cache",
82
- "lint:fix": "pnpm run lint --fix",
83
- "prepublishOnly": "pnpm build",
84
- "release": "bumpp --tag \"v%s\"",
85
- "publish:package": "pnpm build && npm publish",
86
- "start": "esno src/index.ts",
87
- "bench": "node scripts/stream-benchmark.mjs",
88
- "bench:playwright": "node scripts/playwright-bench.mjs",
89
- "smoke:diff": "node scripts/playwright-diff-smoke.mjs",
90
- "shot:diff-ux": "node scripts/playwright-diff-ux-shot.mjs",
91
- "validate:diff-gutter": "node scripts/playwright-diff-gutter-validate.mjs",
92
- "validate:diff-hunk-actions": "node scripts/playwright-diff-hunk-actions-validate.mjs",
93
- "validate:diff-hunk-custom-flow": "node scripts/playwright-diff-hunk-custom-flow-validate.mjs",
94
- "validate:diff-hunk-update-diff-flow": "node scripts/playwright-diff-hunk-update-diff-flow-validate.mjs",
95
- "validate:diff-inline": "node scripts/playwright-diff-inline-validate.mjs",
96
- "validate:diff-transition": "node scripts/playwright-diff-transition-validate.mjs",
97
- "validate:diff-unchanged-expand": "node scripts/playwright-diff-unchanged-expand-validate.mjs",
98
- "validate:diff-unchanged-reveal": "node scripts/playwright-diff-unchanged-reveal-validate.mjs",
99
- "validate:markstream-diff-theme": "node scripts/playwright-markstream-diff-theme-validate.mjs",
100
- "compare:diff-ux": "node scripts/playwright-diff-ux-compare.mjs",
101
- "test": "vitest",
102
- "typecheck": "tsc --noEmit"
103
- },
104
76
  "peerDependencies": {
105
77
  "monaco-editor": ">=0.52.2 <0.56.0"
106
78
  },
@@ -129,5 +101,32 @@
129
101
  "prettier --write --cache --ignore-unknown"
130
102
  ],
131
103
  "*.{vue,js,ts,jsx,tsx,md,json}": "eslint --fix"
104
+ },
105
+ "scripts": {
106
+ "build": "tsdown",
107
+ "dev": "npm run build -- --watch src",
108
+ "format": "prettier --write --cache .",
109
+ "lint": "eslint . --cache",
110
+ "lint:fix": "pnpm run lint --fix",
111
+ "release": "bumpp --tag \"v%s\"",
112
+ "publish:package": "pnpm build && npm publish",
113
+ "start": "esno src/index.ts",
114
+ "bench": "node scripts/stream-benchmark.mjs",
115
+ "bench:playwright": "node scripts/playwright-bench.mjs",
116
+ "smoke:diff": "node scripts/playwright-diff-smoke.mjs",
117
+ "smoke:height-stability": "node scripts/playwright-height-stability-smoke.mjs",
118
+ "shot:diff-ux": "node scripts/playwright-diff-ux-shot.mjs",
119
+ "validate:diff-gutter": "node scripts/playwright-diff-gutter-validate.mjs",
120
+ "validate:diff-hunk-actions": "node scripts/playwright-diff-hunk-actions-validate.mjs",
121
+ "validate:diff-hunk-custom-flow": "node scripts/playwright-diff-hunk-custom-flow-validate.mjs",
122
+ "validate:diff-hunk-update-diff-flow": "node scripts/playwright-diff-hunk-update-diff-flow-validate.mjs",
123
+ "validate:diff-inline": "node scripts/playwright-diff-inline-validate.mjs",
124
+ "validate:diff-transition": "node scripts/playwright-diff-transition-validate.mjs",
125
+ "validate:diff-unchanged-expand": "node scripts/playwright-diff-unchanged-expand-validate.mjs",
126
+ "validate:diff-unchanged-reveal": "node scripts/playwright-diff-unchanged-reveal-validate.mjs",
127
+ "validate:markstream-diff-theme": "node scripts/playwright-markstream-diff-theme-validate.mjs",
128
+ "compare:diff-ux": "node scripts/playwright-diff-ux-compare.mjs",
129
+ "test": "vitest",
130
+ "typecheck": "tsc --noEmit"
132
131
  }
133
- }
132
+ }