@opentui/core 0.1.19-snapshot5-5ed8b651 → 0.1.19

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
@@ -1,6 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  ASCIIFontSelectionHelper,
4
+ BaseRenderable,
4
5
  BorderCharArrays,
5
6
  BorderChars,
6
7
  CliRenderEvents,
@@ -113,12 +114,11 @@ import {
113
114
  strikethrough,
114
115
  stringToStyledText,
115
116
  t,
116
- tn,
117
117
  underline,
118
118
  white,
119
119
  wrapWithDelegates,
120
120
  yellow
121
- } from "./index-grak7z0n.js";
121
+ } from "./index-0h2r5adk.js";
122
122
  // src/post/filters.ts
123
123
  function applyScanlines(buffer, strength = 0.8, step = 2) {
124
124
  const width = buffer.width;
@@ -1444,6 +1444,158 @@ class FrameBufferRenderable extends Renderable {
1444
1444
  super.destroySelf();
1445
1445
  }
1446
1446
  }
1447
+ // src/renderables/TextNode.ts
1448
+ var BrandedTextNodeRenderable = Symbol.for("@opentui/core/TextNodeRenderable");
1449
+ function isTextNodeRenderable(obj) {
1450
+ return !!obj?.[BrandedTextNodeRenderable];
1451
+ }
1452
+
1453
+ class TextNodeRenderable extends BaseRenderable {
1454
+ [BrandedTextNodeRenderable] = true;
1455
+ fg;
1456
+ bg;
1457
+ attributes;
1458
+ _children = [];
1459
+ parent = null;
1460
+ constructor(options) {
1461
+ super(options);
1462
+ this.fg = options.fg ? parseColor(options.fg) : undefined;
1463
+ this.bg = options.bg ? parseColor(options.bg) : undefined;
1464
+ this.attributes = options.attributes ?? 0;
1465
+ }
1466
+ get children() {
1467
+ return this._children;
1468
+ }
1469
+ set children(children) {
1470
+ this._children = children;
1471
+ this.requestRender();
1472
+ }
1473
+ requestRender() {
1474
+ this.markDirty();
1475
+ this.parent?.requestRender();
1476
+ }
1477
+ add(obj, index) {
1478
+ if (typeof obj === "string") {
1479
+ if (index !== undefined) {
1480
+ this._children.splice(index, 0, obj);
1481
+ this.requestRender();
1482
+ return index;
1483
+ } else {
1484
+ const insertIndex = this._children.length;
1485
+ this._children.push(obj);
1486
+ this.requestRender();
1487
+ return insertIndex;
1488
+ }
1489
+ }
1490
+ if (isTextNodeRenderable(obj)) {
1491
+ if (index !== undefined) {
1492
+ this._children.splice(index, 0, obj);
1493
+ obj.parent = this;
1494
+ this.requestRender();
1495
+ return index;
1496
+ } else {
1497
+ const insertIndex = this._children.length;
1498
+ this._children.push(obj);
1499
+ obj.parent = this;
1500
+ this.requestRender();
1501
+ return insertIndex;
1502
+ }
1503
+ }
1504
+ throw new Error("TextNodeRenderable only accepts strings or other TextNodeRenderable instances");
1505
+ }
1506
+ insertBefore(child, anchorNode) {
1507
+ const anchorIndex = this._children.indexOf(anchorNode);
1508
+ if (anchorIndex === -1) {
1509
+ throw new Error("Anchor node not found in children");
1510
+ }
1511
+ this._children.splice(anchorIndex, 0, child);
1512
+ if (typeof child !== "string") {
1513
+ child.parent = this;
1514
+ }
1515
+ this.requestRender();
1516
+ return this;
1517
+ }
1518
+ remove(child) {
1519
+ const childIndex = this._children.indexOf(child);
1520
+ if (childIndex === -1) {
1521
+ throw new Error("Child not found in children");
1522
+ }
1523
+ this._children.splice(childIndex, 1);
1524
+ if (typeof child !== "string") {
1525
+ child.parent = null;
1526
+ }
1527
+ this.requestRender();
1528
+ return this;
1529
+ }
1530
+ clear() {
1531
+ this._children = [];
1532
+ this.requestRender();
1533
+ }
1534
+ mergeStyles(parentStyle) {
1535
+ return {
1536
+ fg: this.fg ?? parentStyle.fg,
1537
+ bg: this.bg ?? parentStyle.bg,
1538
+ attributes: this.attributes | parentStyle.attributes
1539
+ };
1540
+ }
1541
+ gatherWithInheritedStyle(parentStyle = { fg: undefined, bg: undefined, attributes: 0 }) {
1542
+ const currentStyle = this.mergeStyles(parentStyle);
1543
+ const chunks = [];
1544
+ for (const child of this._children) {
1545
+ if (typeof child === "string") {
1546
+ chunks.push({
1547
+ __isChunk: true,
1548
+ text: child,
1549
+ fg: currentStyle.fg,
1550
+ bg: currentStyle.bg,
1551
+ attributes: currentStyle.attributes
1552
+ });
1553
+ } else {
1554
+ const childChunks = child.gatherWithInheritedStyle(currentStyle);
1555
+ chunks.push(...childChunks);
1556
+ }
1557
+ }
1558
+ this.markClean();
1559
+ return chunks;
1560
+ }
1561
+ static fromString(text, options = {}) {
1562
+ const node = new TextNodeRenderable(options);
1563
+ node.add(text);
1564
+ return node;
1565
+ }
1566
+ static fromNodes(nodes, options = {}) {
1567
+ const node = new TextNodeRenderable(options);
1568
+ for (const childNode of nodes) {
1569
+ node.add(childNode);
1570
+ }
1571
+ return node;
1572
+ }
1573
+ toChunks(parentStyle = { fg: undefined, bg: undefined, attributes: 0 }) {
1574
+ return this.gatherWithInheritedStyle(parentStyle);
1575
+ }
1576
+ getChildren() {
1577
+ return this._children.filter((child) => typeof child !== "string");
1578
+ }
1579
+ getChildrenCount() {
1580
+ return this._children.length;
1581
+ }
1582
+ getRenderable(id) {
1583
+ return this._children.find((child) => typeof child !== "string" && child.id === id);
1584
+ }
1585
+ }
1586
+
1587
+ class RootTextNodeRenderable extends TextNodeRenderable {
1588
+ ctx;
1589
+ constructor(ctx, options) {
1590
+ super(options);
1591
+ this.ctx = ctx;
1592
+ }
1593
+ requestRender() {
1594
+ this.markDirty();
1595
+ this.ctx.requestRender();
1596
+ }
1597
+ }
1598
+
1447
1599
  // src/renderables/Text.ts
1448
1600
  class TextRenderable extends Renderable {
1449
1601
  selectable = true;
@@ -1456,6 +1608,7 @@ class TextRenderable extends Renderable {
1456
1608
  lastLocalSelection = null;
1457
1609
  textBuffer;
1458
1610
  _lineInfo = { lineStarts: [], lineWidths: [] };
1611
+ rootTextNode;
1459
1612
  _defaultOptions = {
1460
1613
  content: "",
1461
1614
  fg: RGBA.fromValues(1, 1, 1, 1),
@@ -1481,15 +1634,41 @@ class TextRenderable extends Renderable {
1481
1634
  this.textBuffer.setDefaultBg(this._defaultBg);
1482
1635
  this.textBuffer.setDefaultAttributes(this._defaultAttributes);
1483
1636
  this.setupMeasureFunc();
1484
- this.updateTextInfo(styledText);
1637
+ this.rootTextNode = new RootTextNodeRenderable(ctx, {
1638
+ id: `${this.id}-root`,
1639
+ fg: this._defaultFg,
1640
+ bg: this._defaultBg,
1641
+ attributes: this._defaultAttributes
1642
+ });
1643
+ this.updateTextBuffer(styledText);
1644
+ this._text.mount(this);
1645
+ this.updateTextInfo();
1646
+ }
1647
+ updateTextBuffer(styledText) {
1648
+ this.textBuffer.setStyledText(styledText);
1649
+ this.clearChunks(styledText);
1485
1650
  }
1651
+ clearChunks(styledText) {}
1486
1652
  get content() {
1487
1653
  return this._text;
1488
1654
  }
1655
+ get plainText() {
1656
+ return this.textBuffer.getPlainText();
1657
+ }
1658
+ get textLength() {
1659
+ return this.textBuffer.length;
1660
+ }
1661
+ get chunks() {
1662
+ return this._text.chunks;
1663
+ }
1489
1664
  set content(value) {
1490
1665
  const styledText = typeof value === "string" ? stringToStyledText(value) : value;
1491
- this._text = styledText;
1492
- this.updateTextInfo(styledText);
1666
+ if (this._text !== styledText) {
1667
+ this._text = styledText;
1668
+ styledText.mount(this);
1669
+ this.updateTextBuffer(styledText);
1670
+ this.updateTextInfo();
1671
+ }
1493
1672
  }
1494
1673
  get fg() {
1495
1674
  return this._defaultFg;
@@ -1564,8 +1743,7 @@ class TextRenderable extends Renderable {
1564
1743
  }
1565
1744
  return this.textBuffer.setLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg);
1566
1745
  }
1567
- updateTextInfo(styledText) {
1568
- this.updateTextBuffer(styledText);
1746
+ updateTextInfo() {
1569
1747
  const lineInfo = this.textBuffer.lineInfo;
1570
1748
  this._lineInfo.lineStarts = lineInfo.lineStarts;
1571
1749
  this._lineInfo.lineWidths = lineInfo.lineWidths;
@@ -1601,6 +1779,72 @@ class TextRenderable extends Renderable {
1601
1779
  };
1602
1780
  this.layoutNode.yogaNode.setMeasureFunc(measureFunc);
1603
1781
  }
1782
+ insertChunk(chunk, index) {
1783
+ this.textBuffer.insertChunkGroup(index ?? this.textBuffer.chunkGroupCount, chunk.text, chunk.fg, chunk.bg, chunk.attributes);
1784
+ this.updateTextInfo();
1785
+ this.clearChunks(this._text);
1786
+ }
1787
+ removeChunk(chunk) {
1788
+ const index = this._text.chunks.indexOf(chunk);
1789
+ if (index === -1)
1790
+ return;
1791
+ this.textBuffer.removeChunkGroup(index);
1792
+ this.updateTextInfo();
1793
+ this.clearChunks(this._text);
1794
+ }
1795
+ replaceChunk(chunk, oldChunk) {
1796
+ const index = this._text.chunks.indexOf(oldChunk);
1797
+ if (index === -1)
1798
+ return;
1799
+ this.textBuffer.replaceChunkGroup(index, chunk.text, chunk.fg, chunk.bg, chunk.attributes);
1800
+ this.updateTextInfo();
1801
+ this.clearChunks(this._text);
1802
+ }
1803
+ updateTextFromNodes() {
1804
+ if (this.rootTextNode.isDirty) {
1805
+ const startTime = performance.now();
1806
+ const chunks = this.rootTextNode.gatherWithInheritedStyle({
1807
+ fg: this._defaultFg,
1808
+ bg: this._defaultBg,
1809
+ attributes: this._defaultAttributes
1810
+ });
1811
+ this.textBuffer.setStyledText(new StyledText(chunks));
1812
+ this.updateTextInfo();
1813
+ const endTime = performance.now();
1814
+ console.log(`updateTextFromNodes took ${endTime - startTime}ms`);
1815
+ }
1816
+ }
1817
+ add(obj, index) {
1818
+ if (!isTextNodeRenderable(obj)) {
1819
+ throw new Error("TextRenderable only accepts TextNodeRenderables. Use add() method.");
1820
+ }
1821
+ return this.rootTextNode.add(obj, index);
1822
+ }
1823
+ remove(id) {
1824
+ const child = this.rootTextNode.getRenderable(id);
1825
+ if (child && isTextNodeRenderable(child)) {
1826
+ this.rootTextNode.remove(child);
1827
+ }
1828
+ }
1829
+ insertBefore(obj, anchor) {
1830
+ if (!isTextNodeRenderable(obj)) {
1831
+ throw new Error("TextRenderable insertBefore only accepts TextNodeRenderables");
1832
+ }
1833
+ if (!anchor || !isTextNodeRenderable(anchor)) {
1834
+ throw new Error("Anchor must be a TextNodeRenderable");
1835
+ }
1836
+ this.rootTextNode.insertBefore(obj, anchor);
1837
+ return this.rootTextNode.children.indexOf(obj);
1838
+ }
1839
+ clear() {
1840
+ this.rootTextNode.clear();
1841
+ const emptyStyledText = stringToStyledText("");
1842
+ this._text = emptyStyledText;
1843
+ emptyStyledText.mount(this);
1844
+ this.updateTextBuffer(emptyStyledText);
1845
+ this.updateTextInfo();
1846
+ this.requestRender();
1847
+ }
1604
1848
  shouldStartSelection(x, y) {
1605
1849
  if (!this.selectable)
1606
1850
  return false;
@@ -1626,8 +1870,15 @@ class TextRenderable extends Renderable {
1626
1870
  getSelection() {
1627
1871
  return this.textBuffer.getSelection();
1628
1872
  }
1629
- updateTextBuffer(styledText) {
1630
- this.textBuffer.setStyledText(styledText);
1873
+ render(buffer, deltaTime) {
1874
+ if (!this.visible)
1875
+ return;
1876
+ this.onUpdate(deltaTime);
1877
+ this.updateFromLayout();
1878
+ this.updateTextFromNodes();
1879
+ this.markClean();
1880
+ this._ctx.addToHitGrid(this.x, this.y, this.width, this.height, this.num);
1881
+ this.renderSelf(buffer);
1631
1882
  }
1632
1883
  renderSelf(buffer) {
1633
1884
  if (this.textBuffer.ptr) {
@@ -1642,6 +1893,7 @@ class TextRenderable extends Renderable {
1642
1893
  }
1643
1894
  destroy() {
1644
1895
  this.textBuffer.destroy();
1896
+ this.rootTextNode.children.length = 0;
1645
1897
  super.destroy();
1646
1898
  }
1647
1899
  }
@@ -3509,6 +3761,37 @@ function TabSelect(props, ...children) {
3509
3761
  function FrameBuffer(props, ...children) {
3510
3762
  return h(FrameBufferRenderable, props, ...children);
3511
3763
  }
3764
+ function StyledText2(props, ...children) {
3765
+ const styledProps = props;
3766
+ const textNodeOptions = {
3767
+ ...styledProps,
3768
+ attributes: styledProps?.attributes ?? 0
3769
+ };
3770
+ const textNode = new TextNodeRenderable(textNodeOptions);
3771
+ for (const child of children) {
3772
+ textNode.add(child);
3773
+ }
3774
+ return textNode;
3775
+ }
3776
+ var vstyles = {
3777
+ bold: (...children) => StyledText2({ attributes: TextAttributes.BOLD }, ...children),
3778
+ italic: (...children) => StyledText2({ attributes: TextAttributes.ITALIC }, ...children),
3779
+ underline: (...children) => StyledText2({ attributes: TextAttributes.UNDERLINE }, ...children),
3780
+ dim: (...children) => StyledText2({ attributes: TextAttributes.DIM }, ...children),
3781
+ blink: (...children) => StyledText2({ attributes: TextAttributes.BLINK }, ...children),
3782
+ inverse: (...children) => StyledText2({ attributes: TextAttributes.INVERSE }, ...children),
3783
+ hidden: (...children) => StyledText2({ attributes: TextAttributes.HIDDEN }, ...children),
3784
+ strikethrough: (...children) => StyledText2({ attributes: TextAttributes.STRIKETHROUGH }, ...children),
3785
+ boldItalic: (...children) => StyledText2({ attributes: TextAttributes.BOLD | TextAttributes.ITALIC }, ...children),
3786
+ boldUnderline: (...children) => StyledText2({ attributes: TextAttributes.BOLD | TextAttributes.UNDERLINE }, ...children),
3787
+ italicUnderline: (...children) => StyledText2({ attributes: TextAttributes.ITALIC | TextAttributes.UNDERLINE }, ...children),
3788
+ boldItalicUnderline: (...children) => StyledText2({ attributes: TextAttributes.BOLD | TextAttributes.ITALIC | TextAttributes.UNDERLINE }, ...children),
3789
+ color: (color, ...children) => StyledText2({ fg: color }, ...children),
3790
+ bgColor: (bgColor, ...children) => StyledText2({ bg: bgColor }, ...children),
3791
+ fg: (color, ...children) => StyledText2({ fg: color }, ...children),
3792
+ bg: (bgColor, ...children) => StyledText2({ bg: bgColor }, ...children),
3793
+ styled: (attributes = 0, ...children) => StyledText2({ attributes }, ...children)
3794
+ };
3512
3795
  // src/renderables/composition/VRenderable.ts
3513
3796
  class VRenderable extends Renderable {
3514
3797
  options;
@@ -3526,8 +3809,8 @@ export {
3526
3809
  yellow,
3527
3810
  wrapWithDelegates,
3528
3811
  white,
3812
+ vstyles,
3529
3813
  underline,
3530
- tn,
3531
3814
  t,
3532
3815
  stringToStyledText,
3533
3816
  strikethrough,
@@ -3561,6 +3844,7 @@ export {
3561
3844
  italic,
3562
3845
  isValidPercentage,
3563
3846
  isVNode,
3847
+ isTextNodeRenderable,
3564
3848
  isSizeType,
3565
3849
  isRenderable,
3566
3850
  isPositionTypeType,
@@ -3627,6 +3911,7 @@ export {
3627
3911
  TrackedNode,
3628
3912
  Timeline,
3629
3913
  TextRenderable,
3914
+ TextNodeRenderable,
3630
3915
  TextBuffer,
3631
3916
  TextAttributes,
3632
3917
  Text,
@@ -3642,6 +3927,7 @@ export {
3642
3927
  Select,
3643
3928
  ScrollBoxRenderable,
3644
3929
  ScrollBarRenderable,
3930
+ RootTextNodeRenderable,
3645
3931
  RootRenderable,
3646
3932
  RenderableEvents,
3647
3933
  Renderable,
@@ -3671,11 +3957,12 @@ export {
3671
3957
  BorderCharArrays,
3672
3958
  BlurEffect,
3673
3959
  BloomEffect,
3960
+ BaseRenderable,
3674
3961
  ArrowRenderable,
3675
3962
  ASCIIFontSelectionHelper,
3676
3963
  ASCIIFontRenderable,
3677
3964
  ASCIIFont
3678
3965
  };
3679
3966
 
3680
- //# debugId=288AEFAF1D35CBD764756E2164756E21
3967
+ //# debugId=AFF1AC494BCD215264756E2164756E21
3681
3968
  //# sourceMappingURL=index.js.map