@opentui/core 0.0.0-20251106-dd34dace → 0.0.0-20251108-0c7899b1

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/index.js CHANGED
@@ -33,6 +33,7 @@ import {
33
33
  StdinBuffer,
34
34
  StyledText,
35
35
  TerminalConsole,
36
+ TerminalPalette,
36
37
  TextAttributes,
37
38
  TextBuffer,
38
39
  TreeSitterClient,
@@ -65,6 +66,7 @@ import {
65
66
  coordinateToCharacterIndex,
66
67
  createCliRenderer,
67
68
  createExtmarksController,
69
+ createTerminalPalette,
68
70
  createTextAttributes,
69
71
  cyan,
70
72
  delegate,
@@ -134,7 +136,7 @@ import {
134
136
  white,
135
137
  wrapWithDelegates,
136
138
  yellow
137
- } from "./index-n8nbvvhk.js";
139
+ } from "./index-z5bb2h2z.js";
138
140
  // src/text-buffer-view.ts
139
141
  class TextBufferView {
140
142
  lib;
@@ -2659,9 +2661,8 @@ class CodeRenderable extends TextBufferRenderable {
2659
2661
  _syntaxStyle;
2660
2662
  _isHighlighting = false;
2661
2663
  _treeSitterClient;
2662
- _pendingRehighlight = false;
2663
- _pendingUpdate = false;
2664
- _currentHighlightId = 0;
2664
+ _highlightsDirty = false;
2665
+ _highlightSnapshotId = 0;
2665
2666
  _conceal;
2666
2667
  _drawUnstyledText;
2667
2668
  _shouldRenderTextBuffer = true;
@@ -2683,7 +2684,7 @@ class CodeRenderable extends TextBufferRenderable {
2683
2684
  this._conceal = options.conceal ?? this._contentDefaultOptions.conceal;
2684
2685
  this._drawUnstyledText = options.drawUnstyledText ?? this._contentDefaultOptions.drawUnstyledText;
2685
2686
  this._streaming = options.streaming ?? this._contentDefaultOptions.streaming;
2686
- this.updateContent(this._content);
2687
+ this._highlightsDirty = this._content.length > 0;
2687
2688
  }
2688
2689
  get content() {
2689
2690
  return this._content;
@@ -2691,7 +2692,7 @@ class CodeRenderable extends TextBufferRenderable {
2691
2692
  set content(value) {
2692
2693
  if (this._content !== value) {
2693
2694
  this._content = value;
2694
- this.scheduleUpdate();
2695
+ this._highlightsDirty = true;
2695
2696
  }
2696
2697
  }
2697
2698
  get filetype() {
@@ -2700,7 +2701,7 @@ class CodeRenderable extends TextBufferRenderable {
2700
2701
  set filetype(value) {
2701
2702
  if (this._filetype !== value) {
2702
2703
  this._filetype = value;
2703
- this.scheduleUpdate();
2704
+ this._highlightsDirty = true;
2704
2705
  }
2705
2706
  }
2706
2707
  get syntaxStyle() {
@@ -2709,7 +2710,7 @@ class CodeRenderable extends TextBufferRenderable {
2709
2710
  set syntaxStyle(value) {
2710
2711
  if (this._syntaxStyle !== value) {
2711
2712
  this._syntaxStyle = value;
2712
- this.scheduleUpdate();
2713
+ this._highlightsDirty = true;
2713
2714
  }
2714
2715
  }
2715
2716
  get conceal() {
@@ -2718,7 +2719,7 @@ class CodeRenderable extends TextBufferRenderable {
2718
2719
  set conceal(value) {
2719
2720
  if (this._conceal !== value) {
2720
2721
  this._conceal = value;
2721
- this.scheduleUpdate();
2722
+ this._highlightsDirty = true;
2722
2723
  }
2723
2724
  }
2724
2725
  get drawUnstyledText() {
@@ -2727,7 +2728,7 @@ class CodeRenderable extends TextBufferRenderable {
2727
2728
  set drawUnstyledText(value) {
2728
2729
  if (this._drawUnstyledText !== value) {
2729
2730
  this._drawUnstyledText = value;
2730
- this.scheduleUpdate();
2731
+ this._highlightsDirty = true;
2731
2732
  }
2732
2733
  }
2733
2734
  get streaming() {
@@ -2738,7 +2739,7 @@ class CodeRenderable extends TextBufferRenderable {
2738
2739
  this._streaming = value;
2739
2740
  this._hadInitialContent = false;
2740
2741
  this._lastHighlights = [];
2741
- this.scheduleUpdate();
2742
+ this._highlightsDirty = true;
2742
2743
  }
2743
2744
  }
2744
2745
  get treeSitterClient() {
@@ -2747,53 +2748,66 @@ class CodeRenderable extends TextBufferRenderable {
2747
2748
  set treeSitterClient(value) {
2748
2749
  if (this._treeSitterClient !== value) {
2749
2750
  this._treeSitterClient = value;
2750
- this.scheduleUpdate();
2751
+ this._highlightsDirty = true;
2751
2752
  }
2752
2753
  }
2753
- scheduleUpdate() {
2754
- if (this._pendingUpdate)
2755
- return;
2756
- this._pendingUpdate = true;
2757
- queueMicrotask(() => {
2758
- this._pendingUpdate = false;
2759
- this.updateContent(this._content);
2760
- });
2761
- }
2762
- async updateContent(content) {
2763
- if (content.length === 0)
2764
- return;
2754
+ ensureVisibleTextBeforeHighlight() {
2755
+ const content = this._content;
2765
2756
  if (!this._filetype) {
2766
- this.fallback(content);
2757
+ if (this.isDestroyed)
2758
+ return;
2759
+ this.textBuffer.setText(content);
2767
2760
  this._shouldRenderTextBuffer = true;
2761
+ this.updateTextInfo();
2768
2762
  return;
2769
2763
  }
2770
- this._currentHighlightId++;
2771
- const highlightId = this._currentHighlightId;
2772
2764
  const isInitialContent = this._streaming && !this._hadInitialContent;
2773
- if (isInitialContent) {
2774
- this._hadInitialContent = true;
2775
- }
2776
2765
  const shouldDrawUnstyledNow = this._streaming ? isInitialContent && this._drawUnstyledText : this._drawUnstyledText;
2777
- this.fallback(content);
2778
- if (!shouldDrawUnstyledNow) {
2779
- this._shouldRenderTextBuffer = false;
2780
- }
2781
- if (this._streaming && !isInitialContent && this._lastHighlights.length > 0) {
2782
- const chunks = treeSitterToTextChunks(content, this._lastHighlights, this._syntaxStyle, {
2783
- enabled: this._conceal
2784
- });
2785
- const partialStyledText = new StyledText(chunks);
2766
+ if (this._streaming && !isInitialContent) {
2767
+ if (this._lastHighlights.length > 0) {
2768
+ const chunks = treeSitterToTextChunks(content, this._lastHighlights, this._syntaxStyle, {
2769
+ enabled: this._conceal
2770
+ });
2771
+ const partialStyledText = new StyledText(chunks);
2772
+ if (this.isDestroyed)
2773
+ return;
2774
+ this.textBuffer.setStyledText(partialStyledText);
2775
+ this._shouldRenderTextBuffer = true;
2776
+ this.updateTextInfo();
2777
+ } else {
2778
+ if (this.isDestroyed)
2779
+ return;
2780
+ this.textBuffer.setText(content);
2781
+ this._shouldRenderTextBuffer = true;
2782
+ this.updateTextInfo();
2783
+ }
2784
+ } else if (shouldDrawUnstyledNow) {
2786
2785
  if (this.isDestroyed)
2787
2786
  return;
2788
- this.textBuffer.setStyledText(partialStyledText);
2787
+ this.textBuffer.setText(content);
2789
2788
  this._shouldRenderTextBuffer = true;
2790
2789
  this.updateTextInfo();
2790
+ } else {
2791
+ if (this.isDestroyed)
2792
+ return;
2793
+ this._shouldRenderTextBuffer = false;
2794
+ this.updateTextInfo();
2795
+ }
2796
+ }
2797
+ async startHighlight() {
2798
+ const content = this._content;
2799
+ const filetype = this._filetype;
2800
+ const snapshotId = ++this._highlightSnapshotId;
2801
+ if (!filetype)
2802
+ return;
2803
+ const isInitialContent = this._streaming && !this._hadInitialContent;
2804
+ if (isInitialContent) {
2805
+ this._hadInitialContent = true;
2791
2806
  }
2792
2807
  this._isHighlighting = true;
2793
- this._pendingRehighlight = false;
2794
2808
  try {
2795
- const result = await this._treeSitterClient.highlightOnce(content, this._filetype);
2796
- if (highlightId !== this._currentHighlightId) {
2809
+ const result = await this._treeSitterClient.highlightOnce(content, filetype);
2810
+ if (snapshotId !== this._highlightSnapshotId) {
2797
2811
  return;
2798
2812
  }
2799
2813
  if (this.isDestroyed)
@@ -2808,46 +2822,53 @@ class CodeRenderable extends TextBufferRenderable {
2808
2822
  const styledText = new StyledText(chunks);
2809
2823
  this.textBuffer.setStyledText(styledText);
2810
2824
  } else {
2811
- this.fallback(content);
2825
+ this.textBuffer.setText(content);
2812
2826
  }
2813
2827
  this._shouldRenderTextBuffer = true;
2814
2828
  this.updateTextInfo();
2829
+ this._isHighlighting = false;
2830
+ this._highlightsDirty = false;
2831
+ this.requestRender();
2815
2832
  } catch (error) {
2816
- if (highlightId !== this._currentHighlightId) {
2833
+ if (snapshotId !== this._highlightSnapshotId) {
2817
2834
  return;
2818
2835
  }
2819
2836
  console.warn("Code highlighting failed, falling back to plain text:", error);
2820
- this.fallback(content);
2837
+ if (this.isDestroyed)
2838
+ return;
2839
+ this.textBuffer.setText(content);
2821
2840
  this._shouldRenderTextBuffer = true;
2822
- } finally {
2823
- if (highlightId === this._currentHighlightId) {
2824
- this._isHighlighting = false;
2825
- }
2841
+ this.updateTextInfo();
2842
+ this._isHighlighting = false;
2843
+ this._highlightsDirty = false;
2844
+ this.requestRender();
2826
2845
  }
2827
2846
  }
2828
- fallback(content) {
2829
- const fallbackStyledText = this.createFallbackStyledText(content);
2830
- if (this.isDestroyed)
2831
- return;
2832
- this.textBuffer.setStyledText(fallbackStyledText);
2833
- this.updateTextInfo();
2834
- }
2835
- createFallbackStyledText(content) {
2836
- const chunks = [
2837
- {
2838
- __isChunk: true,
2839
- text: content,
2840
- fg: this._defaultFg,
2841
- bg: this._defaultBg,
2842
- attributes: this._defaultAttributes
2843
- }
2844
- ];
2845
- return new StyledText(chunks);
2846
- }
2847
2847
  getLineHighlights(lineIdx) {
2848
2848
  return this.textBuffer.getLineHighlights(lineIdx);
2849
2849
  }
2850
2850
  renderSelf(buffer) {
2851
+ if (this._highlightsDirty) {
2852
+ if (this._content.length === 0) {
2853
+ if (this.isDestroyed)
2854
+ return;
2855
+ this.textBuffer.setText("");
2856
+ this._shouldRenderTextBuffer = false;
2857
+ this._highlightsDirty = false;
2858
+ this.updateTextInfo();
2859
+ } else if (!this._filetype) {
2860
+ if (this.isDestroyed)
2861
+ return;
2862
+ this.textBuffer.setText(this._content);
2863
+ this._shouldRenderTextBuffer = true;
2864
+ this._highlightsDirty = false;
2865
+ this.updateTextInfo();
2866
+ } else {
2867
+ this.ensureVisibleTextBeforeHighlight();
2868
+ this._highlightsDirty = false;
2869
+ this.startHighlight();
2870
+ }
2871
+ }
2851
2872
  if (!this._shouldRenderTextBuffer)
2852
2873
  return;
2853
2874
  super.renderSelf(buffer);
@@ -4044,11 +4065,11 @@ class ContentRenderable extends BoxRenderable {
4044
4065
  set viewportCulling(value) {
4045
4066
  this._viewportCulling = value;
4046
4067
  }
4047
- _getChildren() {
4068
+ _getVisibleChildren() {
4048
4069
  if (this._viewportCulling) {
4049
- return getObjectsInViewport(this.viewport, this.getChildrenSortedByPrimaryAxis(), this.primaryAxis);
4070
+ return getObjectsInViewport(this.viewport, this.getChildrenSortedByPrimaryAxis(), this.primaryAxis).map((child) => child.num);
4050
4071
  }
4051
- return this.getChildrenSortedByPrimaryAxis();
4072
+ return this.getChildrenSortedByPrimaryAxis().map((child) => child.num);
4052
4073
  }
4053
4074
  }
4054
4075
 
@@ -4080,6 +4101,7 @@ class ScrollBoxRenderable extends BoxRenderable {
4080
4101
  _stickyScrollRight = false;
4081
4102
  _stickyStart;
4082
4103
  _hasManualScroll = false;
4104
+ _isApplyingStickyScroll = false;
4083
4105
  scrollAccel;
4084
4106
  get stickyScroll() {
4085
4107
  return this._stickyScroll;
@@ -4100,7 +4122,12 @@ class ScrollBoxRenderable extends BoxRenderable {
4100
4122
  }
4101
4123
  set scrollTop(value) {
4102
4124
  this.verticalScrollBar.scrollPosition = value;
4103
- this._hasManualScroll = true;
4125
+ if (!this._isApplyingStickyScroll) {
4126
+ const maxScrollTop = Math.max(0, this.scrollHeight - this.viewport.height);
4127
+ if (!this.isAtStickyPosition() && maxScrollTop > 1) {
4128
+ this._hasManualScroll = true;
4129
+ }
4130
+ }
4104
4131
  this.updateStickyState();
4105
4132
  }
4106
4133
  get scrollLeft() {
@@ -4108,7 +4135,12 @@ class ScrollBoxRenderable extends BoxRenderable {
4108
4135
  }
4109
4136
  set scrollLeft(value) {
4110
4137
  this.horizontalScrollBar.scrollPosition = value;
4111
- this._hasManualScroll = true;
4138
+ if (!this._isApplyingStickyScroll) {
4139
+ const maxScrollLeft = Math.max(0, this.scrollWidth - this.viewport.width);
4140
+ if (!this.isAtStickyPosition() && maxScrollLeft > 1) {
4141
+ this._hasManualScroll = true;
4142
+ }
4143
+ }
4112
4144
  this.updateStickyState();
4113
4145
  }
4114
4146
  get scrollWidth() {
@@ -4144,6 +4176,7 @@ class ScrollBoxRenderable extends BoxRenderable {
4144
4176
  }
4145
4177
  }
4146
4178
  applyStickyStart(stickyStart) {
4179
+ this._isApplyingStickyScroll = true;
4147
4180
  switch (stickyStart) {
4148
4181
  case "top":
4149
4182
  this._stickyScrollTop = true;
@@ -4166,6 +4199,7 @@ class ScrollBoxRenderable extends BoxRenderable {
4166
4199
  this.horizontalScrollBar.scrollPosition = Math.max(0, this.scrollWidth - this.viewport.width);
4167
4200
  break;
4168
4201
  }
4202
+ this._isApplyingStickyScroll = false;
4169
4203
  }
4170
4204
  constructor(ctx, {
4171
4205
  wrapperOptions,
@@ -4239,7 +4273,12 @@ class ScrollBoxRenderable extends BoxRenderable {
4239
4273
  orientation: "vertical",
4240
4274
  onChange: (position) => {
4241
4275
  this.content.translateY = -position;
4242
- this._hasManualScroll = true;
4276
+ if (!this._isApplyingStickyScroll) {
4277
+ const maxScrollTop = Math.max(0, this.scrollHeight - this.viewport.height);
4278
+ if (!this.isAtStickyPosition() && maxScrollTop > 1) {
4279
+ this._hasManualScroll = true;
4280
+ }
4281
+ }
4243
4282
  this.updateStickyState();
4244
4283
  }
4245
4284
  });
@@ -4255,7 +4294,12 @@ class ScrollBoxRenderable extends BoxRenderable {
4255
4294
  orientation: "horizontal",
4256
4295
  onChange: (position) => {
4257
4296
  this.content.translateX = -position;
4258
- this._hasManualScroll = true;
4297
+ if (!this._isApplyingStickyScroll) {
4298
+ const maxScrollLeft = Math.max(0, this.scrollWidth - this.viewport.width);
4299
+ if (!this.isAtStickyPosition() && maxScrollLeft > 1) {
4300
+ this._hasManualScroll = true;
4301
+ }
4302
+ }
4259
4303
  this.updateStickyState();
4260
4304
  }
4261
4305
  });
@@ -4282,7 +4326,6 @@ class ScrollBoxRenderable extends BoxRenderable {
4282
4326
  this.verticalScrollBar.scrollBy(delta.y, unit);
4283
4327
  this.horizontalScrollBar.scrollBy(delta.x, unit);
4284
4328
  }
4285
- this._hasManualScroll = true;
4286
4329
  }
4287
4330
  scrollTo(position) {
4288
4331
  if (typeof position === "number") {
@@ -4292,6 +4335,25 @@ class ScrollBoxRenderable extends BoxRenderable {
4292
4335
  this.scrollLeft = position.x;
4293
4336
  }
4294
4337
  }
4338
+ isAtStickyPosition() {
4339
+ if (!this._stickyScroll || !this._stickyStart) {
4340
+ return false;
4341
+ }
4342
+ const maxScrollTop = Math.max(0, this.scrollHeight - this.viewport.height);
4343
+ const maxScrollLeft = Math.max(0, this.scrollWidth - this.viewport.width);
4344
+ switch (this._stickyStart) {
4345
+ case "top":
4346
+ return this.scrollTop === 0;
4347
+ case "bottom":
4348
+ return this.scrollTop >= maxScrollTop;
4349
+ case "left":
4350
+ return this.scrollLeft === 0;
4351
+ case "right":
4352
+ return this.scrollLeft >= maxScrollLeft;
4353
+ default:
4354
+ return false;
4355
+ }
4356
+ }
4295
4357
  add(obj, index) {
4296
4358
  return this.content.add(obj, index);
4297
4359
  }
@@ -4321,7 +4383,11 @@ class ScrollBoxRenderable extends BoxRenderable {
4321
4383
  } else if (dir === "right") {
4322
4384
  this.scrollLeft += baseDelta * multiplier;
4323
4385
  }
4324
- this._hasManualScroll = true;
4386
+ const maxScrollTop = Math.max(0, this.scrollHeight - this.viewport.height);
4387
+ const maxScrollLeft = Math.max(0, this.scrollWidth - this.viewport.width);
4388
+ if (maxScrollTop > 1 || maxScrollLeft > 1) {
4389
+ this._hasManualScroll = true;
4390
+ }
4325
4391
  }
4326
4392
  if (event.type === "drag" && event.isSelecting) {
4327
4393
  this.updateAutoScroll(event.x, event.y);
@@ -4449,6 +4515,8 @@ class ScrollBoxRenderable extends BoxRenderable {
4449
4515
  }
4450
4516
  }
4451
4517
  recalculateBarProps() {
4518
+ const wasApplyingStickyScroll = this._isApplyingStickyScroll;
4519
+ this._isApplyingStickyScroll = true;
4452
4520
  this.verticalScrollBar.scrollSize = this.content.height;
4453
4521
  this.verticalScrollBar.viewportSize = this.viewport.height;
4454
4522
  this.horizontalScrollBar.scrollSize = this.content.width;
@@ -4471,6 +4539,7 @@ class ScrollBoxRenderable extends BoxRenderable {
4471
4539
  }
4472
4540
  }
4473
4541
  }
4542
+ this._isApplyingStickyScroll = wasApplyingStickyScroll;
4474
4543
  process.nextTick(() => {
4475
4544
  this.requestRender();
4476
4545
  });
@@ -6222,6 +6291,7 @@ export {
6222
6291
  cyan,
6223
6292
  createTimeline,
6224
6293
  createTextAttributes,
6294
+ createTerminalPalette,
6225
6295
  createExtmarksController,
6226
6296
  createCliRenderer,
6227
6297
  coordinateToCharacterIndex,
@@ -6272,6 +6342,7 @@ export {
6272
6342
  TextBuffer,
6273
6343
  TextAttributes,
6274
6344
  Text,
6345
+ TerminalPalette,
6275
6346
  TerminalConsole,
6276
6347
  TabSelectRenderableEvents,
6277
6348
  TabSelectRenderable,
@@ -6334,5 +6405,5 @@ export {
6334
6405
  ASCIIFont
6335
6406
  };
6336
6407
 
6337
- //# debugId=44707EEC392262B964756E2164756E21
6408
+ //# debugId=33D29679C10495BA64756E2164756E21
6338
6409
  //# sourceMappingURL=index.js.map