From 6a799f4d58cc0eaeab0874f4ce9c98b5a922bd01 Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Tue, 24 Feb 2026 08:24:36 -0500 Subject: [PATCH 01/12] docs(readme): update header image, minor corrections --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 87109d2b..e6eca454 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ # Bubbles - + [![Latest Release](https://img.shields.io/github/release/charmbracelet/bubbles.svg)](https://github.com/charmbracelet/bubbles/releases) [![GoDoc](https://godoc.org/github.com/golang/gddo?status.svg)](https://pkg.go.dev/github.com/charmbracelet/bubbles) [![Build Status](https://github.com/charmbracelet/bubbles/workflows/build/badge.svg)](https://github.com/charmbracelet/bubbles/actions) [![Go ReportCard](https://goreportcard.com/badge/charmbracelet/bubbles)](https://goreportcard.com/report/charmbracelet/bubbles) -Some components for [Bubble Tea](https://github.com/charmbracelet/bubbletea) +Primatives for [Bubble Tea](https://github.com/charmbracelet/bubbletea) applications. These components are used in production in [Crush][crush], and [many other applications][otherstuff]. > [!TIP] @@ -194,7 +194,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { To check out community-maintained Bubbles see [Charm & Friends][charmandfriends]. Made a cool Bubble that you want to share? [PRs][prs] are welcome! -[charmandfriends]: +[charmandfriends]: https://github.com/charm-and-friends/additional-bubbles [prs]: https://github.com/charm-and-friends/additional-bubbles?tab=readme-ov-file#what-is-a-complete-project ## Contributing From 8d9107ff1fde016d265edd01733d4bc5887f2bfa Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Tue, 24 Feb 2026 18:34:07 +0300 Subject: [PATCH 02/12] chore: bump bubbletea and lipgloss to v2.0.0 --- go.mod | 19 +++++++++---------- go.sum | 38 ++++++++++++++++++-------------------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/go.mod b/go.mod index 8f22a95e..e894ecdc 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module charm.land/bubbles/v2 go 1.24.2 require ( - charm.land/bubbletea/v2 v2.0.0-rc.1.0.20251106192006-06c0cda318b3 - charm.land/lipgloss/v2 v2.0.0-beta.3.0.20251106192539-4b304240aab7 + charm.land/bubbletea/v2 v2.0.0 + charm.land/lipgloss/v2 v2.0.0 github.com/MakeNowJust/heredoc v1.0.0 github.com/atotto/clipboard v0.1.4 github.com/charmbracelet/harmonica v0.2.0 @@ -17,19 +17,18 @@ require ( ) require ( - github.com/aymanbagabas/go-udiff v0.3.1 // indirect - github.com/charmbracelet/colorprofile v0.4.1 // indirect - github.com/charmbracelet/ultraviolet v0.0.0-20251106190538-99ea45596692 // indirect + github.com/aymanbagabas/go-udiff v0.4.0 // indirect + github.com/charmbracelet/colorprofile v0.4.2 // indirect + github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8 // indirect github.com/charmbracelet/x/term v0.2.2 // indirect github.com/charmbracelet/x/termios v0.1.1 // indirect github.com/charmbracelet/x/windows v0.2.2 // indirect - github.com/clipperhouse/displaywidth v0.9.0 // indirect - github.com/clipperhouse/stringish v0.1.1 // indirect - github.com/clipperhouse/uax29/v2 v2.5.0 // indirect + github.com/clipperhouse/displaywidth v0.11.0 // indirect + github.com/clipperhouse/uax29/v2 v2.7.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/lucasb-eyer/go-colorful v1.3.0 // indirect github.com/muesli/cancelreader v0.2.2 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - golang.org/x/sync v0.17.0 // indirect - golang.org/x/sys v0.38.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.41.0 // indirect ) diff --git a/go.sum b/go.sum index 38e03deb..f4fc74a4 100644 --- a/go.sum +++ b/go.sum @@ -1,19 +1,19 @@ -charm.land/bubbletea/v2 v2.0.0-rc.1.0.20251106192006-06c0cda318b3 h1:kHeOXDvccLh2f0gH3qxyMhN07VEnmc/3gPAZ50wn8ko= -charm.land/bubbletea/v2 v2.0.0-rc.1.0.20251106192006-06c0cda318b3/go.mod h1:e3yWIY4Tl/LJnOMOv9H4YgvDwrknVDm5az5ep5QRLfk= -charm.land/lipgloss/v2 v2.0.0-beta.3.0.20251106192539-4b304240aab7 h1:059k1h5vvZ4ASinki9nmBguxu9Rq0UDDSa6q8LOUphk= -charm.land/lipgloss/v2 v2.0.0-beta.3.0.20251106192539-4b304240aab7/go.mod h1:1qZyvvVCenJO2M1ac2mX0yyiIZJoZmDM4DG4s0udJkU= +charm.land/bubbletea/v2 v2.0.0 h1:p0d6CtWyJXJ9GfzMpUUqbP/XUUhhlk06+vCKWmox1wQ= +charm.land/bubbletea/v2 v2.0.0/go.mod h1:3LRff2U4WIYXy7MTxfbAQ+AdfM3D8Xuvz2wbsOD9OHQ= +charm.land/lipgloss/v2 v2.0.0 h1:sd8N/B3x892oiOjFfBQdXBQp3cAkvjGaU5TvVZC3ivo= +charm.land/lipgloss/v2 v2.0.0/go.mod h1:w6SnmsBFBmEFBodiEDurGS/sdUY/u1+v72DqUzc6J14= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= -github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY= -github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E= -github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk= -github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk= +github.com/aymanbagabas/go-udiff v0.4.0 h1:TKnLPh7IbnizJIBKFWa9mKayRUBQ9Kh1BPCk6w2PnYM= +github.com/aymanbagabas/go-udiff v0.4.0/go.mod h1:0L9PGwj20lrtmEMeyw4WKJ/TMyDtvAoK9bf2u/mNo3w= +github.com/charmbracelet/colorprofile v0.4.2 h1:BdSNuMjRbotnxHSfxy+PCSa4xAmz7szw70ktAtWRYrY= +github.com/charmbracelet/colorprofile v0.4.2/go.mod h1:0rTi81QpwDElInthtrQ6Ni7cG0sDtwAd4C4le060fT8= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= -github.com/charmbracelet/ultraviolet v0.0.0-20251106190538-99ea45596692 h1:r/3jQZ1LjWW6ybp8HHfhrKrwHIWiJhUuY7wwYIWZulQ= -github.com/charmbracelet/ultraviolet v0.0.0-20251106190538-99ea45596692/go.mod h1:Y8B4DzWeTb0ama8l3+KyopZtkE8fZjwRQ3aEAPEXHE0= +github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8 h1:eyFRbAmexyt43hVfeyBofiGSEmJ7krjLOYt/9CF5NKA= +github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8/go.mod h1:SQpCTRNBtzJkwku5ye4S3HEuthAlGy2n9VXZnWkEW98= github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8= github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ= github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f h1:pk6gmGpCE7F3FcjaOEKYriCvpmIN4+6OS/RD0vm4uIA= @@ -24,12 +24,10 @@ github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8 github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo= github.com/charmbracelet/x/windows v0.2.2 h1:IofanmuvaxnKHuV04sC0eBy/smG6kIKrWG2/jYn2GuM= github.com/charmbracelet/x/windows v0.2.2/go.mod h1:/8XtdKZzedat74NQFn0NGlGL4soHB0YQZrETF96h75k= -github.com/clipperhouse/displaywidth v0.9.0 h1:Qb4KOhYwRiN3viMv1v/3cTBlz3AcAZX3+y9OLhMtAtA= -github.com/clipperhouse/displaywidth v0.9.0/go.mod h1:aCAAqTlh4GIVkhQnJpbL0T/WfcrJXHcj8C0yjYcjOZA= -github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs= -github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= -github.com/clipperhouse/uax29/v2 v2.5.0 h1:x7T0T4eTHDONxFJsL94uKNKPHrclyFI0lm7+w94cO8U= -github.com/clipperhouse/uax29/v2 v2.5.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= +github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSEFgwIwO+UVM8= +github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0= +github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk= +github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= @@ -48,7 +46,7 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavM github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= -golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= -golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= From c2c79e37a53cf89c278896e028f7618cdfe8ba81 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Mar 2026 09:09:57 +0000 Subject: [PATCH 03/12] chore(deps): bump the all group with 2 updates (#902) Bumps the all group with 2 updates: [charm.land/bubbletea/v2](https://github.com/charmbracelet/bubbletea) and [github.com/mattn/go-runewidth](https://github.com/mattn/go-runewidth). Updates `charm.land/bubbletea/v2` from 2.0.0 to 2.0.1 - [Release notes](https://github.com/charmbracelet/bubbletea/releases) - [Commits](https://github.com/charmbracelet/bubbletea/compare/v2.0.0...v2.0.1) Updates `github.com/mattn/go-runewidth` from 0.0.20 to 0.0.21 - [Commits](https://github.com/mattn/go-runewidth/compare/v0.0.20...v0.0.21) --- updated-dependencies: - dependency-name: charm.land/bubbletea/v2 dependency-version: 2.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all - dependency-name: github.com/mattn/go-runewidth dependency-version: 0.0.21 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index e894ecdc..7bf5dfe9 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module charm.land/bubbles/v2 go 1.24.2 require ( - charm.land/bubbletea/v2 v2.0.0 + charm.land/bubbletea/v2 v2.0.1 charm.land/lipgloss/v2 v2.0.0 github.com/MakeNowJust/heredoc v1.0.0 github.com/atotto/clipboard v0.1.4 @@ -11,7 +11,7 @@ require ( github.com/charmbracelet/x/ansi v0.11.6 github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f github.com/dustin/go-humanize v1.0.1 - github.com/mattn/go-runewidth v0.0.20 + github.com/mattn/go-runewidth v0.0.21 github.com/rivo/uniseg v0.4.7 github.com/sahilm/fuzzy v0.1.1 ) diff --git a/go.sum b/go.sum index f4fc74a4..66911548 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -charm.land/bubbletea/v2 v2.0.0 h1:p0d6CtWyJXJ9GfzMpUUqbP/XUUhhlk06+vCKWmox1wQ= -charm.land/bubbletea/v2 v2.0.0/go.mod h1:3LRff2U4WIYXy7MTxfbAQ+AdfM3D8Xuvz2wbsOD9OHQ= +charm.land/bubbletea/v2 v2.0.1 h1:B8e9zzK7x9JJ+XvHGF4xnYu9Xa0E0y0MyggY6dbaCfQ= +charm.land/bubbletea/v2 v2.0.1/go.mod h1:3LRff2U4WIYXy7MTxfbAQ+AdfM3D8Xuvz2wbsOD9OHQ= charm.land/lipgloss/v2 v2.0.0 h1:sd8N/B3x892oiOjFfBQdXBQp3cAkvjGaU5TvVZC3ivo= charm.land/lipgloss/v2 v2.0.0/go.mod h1:w6SnmsBFBmEFBodiEDurGS/sdUY/u1+v72DqUzc6J14= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= @@ -34,8 +34,8 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag= github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/mattn/go-runewidth v0.0.20 h1:WcT52H91ZUAwy8+HUkdM3THM6gXqXuLJi9O3rjcQQaQ= -github.com/mattn/go-runewidth v0.0.20/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= +github.com/mattn/go-runewidth v0.0.21 h1:jJKAZiQH+2mIinzCJIaIG9Be1+0NR+5sz/lYEEjdM8w= +github.com/mattn/go-runewidth v0.0.21/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= From d2b804ead2717c24a8480843489c6153b82993a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Mar 2026 09:09:36 +0000 Subject: [PATCH 04/12] chore(deps): bump the all group with 2 updates (#908) Bumps the all group with 2 updates: [charm.land/bubbletea/v2](https://github.com/charmbracelet/bubbletea) and [charm.land/lipgloss/v2](https://github.com/charmbracelet/lipgloss). Updates `charm.land/bubbletea/v2` from 2.0.1 to 2.0.2 - [Release notes](https://github.com/charmbracelet/bubbletea/releases) - [Commits](https://github.com/charmbracelet/bubbletea/compare/v2.0.1...v2.0.2) Updates `charm.land/lipgloss/v2` from 2.0.0 to 2.0.2 - [Release notes](https://github.com/charmbracelet/lipgloss/releases) - [Commits](https://github.com/charmbracelet/lipgloss/compare/v2.0.0...v2.0.2) --- updated-dependencies: - dependency-name: charm.land/bubbletea/v2 dependency-version: 2.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all - dependency-name: charm.land/lipgloss/v2 dependency-version: 2.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index 7bf5dfe9..2300fe5d 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,10 @@ module charm.land/bubbles/v2 -go 1.24.2 +go 1.25.0 require ( - charm.land/bubbletea/v2 v2.0.1 - charm.land/lipgloss/v2 v2.0.0 + charm.land/bubbletea/v2 v2.0.2 + charm.land/lipgloss/v2 v2.0.2 github.com/MakeNowJust/heredoc v1.0.0 github.com/atotto/clipboard v0.1.4 github.com/charmbracelet/harmonica v0.2.0 @@ -17,7 +17,7 @@ require ( ) require ( - github.com/aymanbagabas/go-udiff v0.4.0 // indirect + github.com/aymanbagabas/go-udiff v0.4.1 // indirect github.com/charmbracelet/colorprofile v0.4.2 // indirect github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8 // indirect github.com/charmbracelet/x/term v0.2.2 // indirect @@ -30,5 +30,5 @@ require ( github.com/muesli/cancelreader v0.2.2 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect golang.org/x/sync v0.19.0 // indirect - golang.org/x/sys v0.41.0 // indirect + golang.org/x/sys v0.42.0 // indirect ) diff --git a/go.sum b/go.sum index 66911548..57d712ff 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,13 @@ -charm.land/bubbletea/v2 v2.0.1 h1:B8e9zzK7x9JJ+XvHGF4xnYu9Xa0E0y0MyggY6dbaCfQ= -charm.land/bubbletea/v2 v2.0.1/go.mod h1:3LRff2U4WIYXy7MTxfbAQ+AdfM3D8Xuvz2wbsOD9OHQ= -charm.land/lipgloss/v2 v2.0.0 h1:sd8N/B3x892oiOjFfBQdXBQp3cAkvjGaU5TvVZC3ivo= -charm.land/lipgloss/v2 v2.0.0/go.mod h1:w6SnmsBFBmEFBodiEDurGS/sdUY/u1+v72DqUzc6J14= +charm.land/bubbletea/v2 v2.0.2 h1:4CRtRnuZOdFDTWSff9r8QFt/9+z6Emubz3aDMnf/dx0= +charm.land/bubbletea/v2 v2.0.2/go.mod h1:3LRff2U4WIYXy7MTxfbAQ+AdfM3D8Xuvz2wbsOD9OHQ= +charm.land/lipgloss/v2 v2.0.2 h1:xFolbF8JdpNkM2cEPTfXEcW1p6NRzOWTSamRfYEw8cs= +charm.land/lipgloss/v2 v2.0.2/go.mod h1:KjPle2Qd3YmvP1KL5OMHiHysGcNwq6u83MUjYkFvEkM= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= -github.com/aymanbagabas/go-udiff v0.4.0 h1:TKnLPh7IbnizJIBKFWa9mKayRUBQ9Kh1BPCk6w2PnYM= -github.com/aymanbagabas/go-udiff v0.4.0/go.mod h1:0L9PGwj20lrtmEMeyw4WKJ/TMyDtvAoK9bf2u/mNo3w= +github.com/aymanbagabas/go-udiff v0.4.1 h1:OEIrQ8maEeDBXQDoGCbbTTXYJMYRCRO1fnodZ12Gv5o= +github.com/aymanbagabas/go-udiff v0.4.1/go.mod h1:0L9PGwj20lrtmEMeyw4WKJ/TMyDtvAoK9bf2u/mNo3w= github.com/charmbracelet/colorprofile v0.4.2 h1:BdSNuMjRbotnxHSfxy+PCSa4xAmz7szw70ktAtWRYrY= github.com/charmbracelet/colorprofile v0.4.2/go.mod h1:0rTi81QpwDElInthtrQ6Ni7cG0sDtwAd4C4le060fT8= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= @@ -48,5 +48,5 @@ golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= -golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= -golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= +golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= From f1daacfa0cfee07e31a12498078426d275aa5286 Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Wed, 25 Mar 2026 08:00:38 -0400 Subject: [PATCH 05/12] feat(textarea): dynamic height (#910) Co-authored-by: Andrey Nering --- textarea/textarea.go | 108 +++++++++- textarea/textarea_test.go | 416 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 523 insertions(+), 1 deletion(-) diff --git a/textarea/textarea.go b/textarea/textarea.go index 7e4508ab..f0c0ca54 100644 --- a/textarea/textarea.go +++ b/textarea/textarea.go @@ -287,6 +287,23 @@ type Model struct { // there's no limit. MaxWidth int + // DynamicHeight, when true, causes the textarea to automatically grow + // and shrink its height to fit the content. The height is clamped between + // MinHeight and MaxHeight. + DynamicHeight bool + + // MinHeight is the minimum height of the text area in rows when + // DynamicHeight is enabled. If 0 or less, defaults to 1. + MinHeight int + + // MaxContentHeight is the maximum content height in visual rows + // (accounting for soft wraps). When set (> 0), input is blocked once + // the total visual lines reach this limit, while MaxHeight controls + // only the visible viewport height. When 0, the content guard falls + // back to the legacy MaxHeight behavior (blocking at MaxHeight + // logical lines) for backward compatibility. + MaxContentHeight int + // Styling. Styles are defined in [Styles]. Use [SetStyles] and [GetStyles] // to work with this value publicly. styles Styles @@ -464,16 +481,19 @@ func (m *Model) updateVirtualCursorStyle() { func (m *Model) SetValue(s string) { m.Reset() m.InsertString(s) + m.recalculateHeight() } // InsertString inserts a string at the cursor position. func (m *Model) InsertString(s string) { m.insertRunesFromUserInput([]rune(s)) + m.recalculateHeight() } // InsertRune inserts a rune at the cursor position. func (m *Model) InsertRune(r rune) { m.insertRunesFromUserInput([]rune{r}) + m.recalculateHeight() } // insertRunesFromUserInput inserts runes at the current cursor position. @@ -521,6 +541,18 @@ func (m *Model) insertRunesFromUserInput(runes []rune) { lines = lines[:allowedHeight] } + // Obey MaxContentHeight in visual rows when set. + if m.MaxContentHeight > 0 { + budget := m.MaxContentHeight - m.totalVisualLines() + // Trim lines from the end until we fit within the budget. + for len(lines) > 1 && m.visualLinesForInsert(lines) > budget { + lines = lines[:len(lines)-1] + } + if m.visualLinesForInsert(lines) > budget { + return + } + } + if len(lines) == 0 { // Nothing left to insert. return @@ -740,6 +772,7 @@ func (m *Model) Reset() { m.row = 0 m.viewport.GotoTop() m.SetCursorColumn(0) + m.recalculateHeight() } // Word returns the word at the cursor position. @@ -1134,6 +1167,7 @@ func (m *Model) SetWidth(w int) { m.viewport.SetWidth(inputWidth - reservedOuter) m.width = inputWidth - reservedOuter - reservedInner + m.recalculateHeight() } // SetPromptFunc supersedes the Prompt field and sets a dynamic prompt instead. @@ -1238,7 +1272,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { } m.deleteWordRight() case key.Matches(msg, m.KeyMap.InsertNewline): - if m.MaxHeight > 0 && len(m.value) >= m.MaxHeight { + if m.atContentLimit() { return m, nil } m.col = clamp(m.col, 0, len(m.value[m.row])) @@ -1289,6 +1323,8 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { m.Err = msg } + m.recalculateHeight() + // Make sure we set the content of the viewport before updating it. view := m.view() m.viewport.SetContent(view) @@ -1627,6 +1663,76 @@ func (m Model) cursorLineNumber() int { return line } +// totalVisualLines returns the total number of display lines across all +// logical lines, accounting for soft wraps. +func (m *Model) totalVisualLines() int { + n := 0 + for _, line := range m.value { + n += len(m.memoizedWrap(line, m.width)) + } + return n +} + +// recalculateHeight recomputes and applies the textarea height based on +// content when DynamicHeight is enabled. It is a no-op otherwise. +func (m *Model) recalculateHeight() { + if !m.DynamicHeight { + return + } + minH := max(m.MinHeight, minHeight) + total := m.totalVisualLines() + h := max(total, minH) + if m.MaxHeight > 0 { + h = min(h, m.MaxHeight) + } + if maxOffset := total - h; m.viewport.YOffset() > maxOffset { + m.viewport.SetYOffset(max(0, maxOffset)) + } + m.SetHeight(h) +} + +// atContentLimit reports whether the textarea has reached its content limit. +// When MaxContentHeight is set (> 0), it checks total visual lines. +// Otherwise it falls back to the legacy MaxHeight logical-line check for +// backward compatibility. +func (m *Model) atContentLimit() bool { + if m.MaxContentHeight > 0 { + return m.totalVisualLines() >= m.MaxContentHeight + } + return m.MaxHeight > 0 && len(m.value) >= m.MaxHeight +} + +// visualLinesForInsert estimates how many additional visual lines would result +// from inserting the given lines at the current cursor position. The first +// element merges into the current line; subsequent elements become new lines. +func (m *Model) visualLinesForInsert(lines [][]rune) int { + if len(lines) == 0 { + return 0 + } + + // The current row's visual line count before insertion. + currentRowVisual := len(m.memoizedWrap(m.value[m.row], m.width)) + + // Simulate merging the first paste line into the current row. + merged := make([]rune, m.col+len(lines[0])) + copy(merged, m.value[m.row][:m.col]) + copy(merged[m.col:], lines[0]) + if len(lines) == 1 { + merged = append(merged, m.value[m.row][m.col:]...) + } + delta := len(m.memoizedWrap(merged, m.width)) - currentRowVisual + + // Each additional line is a new logical line. + for i, content := range lines { + if i == len(lines)-1 { + content = append(content, m.value[m.row][m.col:]...) + } + delta += len(m.memoizedWrap(content, m.width)) + } + + return delta +} + // mergeLineBelow merges the current line the cursor is on with the line below. func (m *Model) mergeLineBelow(row int) { if row >= len(m.value)-1 { diff --git a/textarea/textarea_test.go b/textarea/textarea_test.go index d942dd40..41d51f74 100644 --- a/textarea/textarea_test.go +++ b/textarea/textarea_test.go @@ -1974,6 +1974,422 @@ func TestWord(t *testing.T) { }) } +func newDynamicTextArea(minH, maxH int) Model { + ta := New() + ta.Prompt = "" + ta.ShowLineNumbers = false + ta.DynamicHeight = true + ta.MinHeight = minH + ta.MaxHeight = maxH + ta.SetWidth(20) + ta.Focus() + ta, _ = ta.Update(nil) + return ta +} + +func TestDynamicHeight_DefaultUnchanged(t *testing.T) { + ta := newTextArea() + ta.SetHeight(6) + ta.SetWidth(40) + + for _, k := range "hello\nworld\n" { + ta, _ = ta.Update(keyPress(k)) + } + + if ta.Height() != 6 { + t.Errorf("expected static height 6, got %d", ta.Height()) + } +} + +func TestDynamicHeight_GrowsOnNewline(t *testing.T) { + ta := newDynamicTextArea(1, 20) + + ta, _ = ta.Update(keyPress('a')) + if ta.Height() != 1 { + t.Errorf("expected height 1 after single char, got %d", ta.Height()) + } + + enter := tea.KeyPressMsg{Code: tea.KeyEnter} + ta, _ = ta.Update(enter) + if ta.Height() != 2 { + t.Errorf("expected height 2 after first newline, got %d", ta.Height()) + } + + ta, _ = ta.Update(enter) + if ta.Height() != 3 { + t.Errorf("expected height 3 after second newline, got %d", ta.Height()) + } +} + +func TestDynamicHeight_GrowsOnSoftWrap(t *testing.T) { + ta := newDynamicTextArea(1, 20) + // width=20, so typing >20 chars should cause a soft wrap + input := "abcdefghijklmnopqrstuvwxyz" + for _, k := range input { + ta, _ = ta.Update(keyPress(k)) + } + + if ta.Height() < 2 { + t.Errorf("expected height >= 2 after soft wrap, got %d", ta.Height()) + } +} + +func TestDynamicHeight_ShrinksOnLineDeletion(t *testing.T) { + ta := newDynamicTextArea(1, 20) + + enter := tea.KeyPressMsg{Code: tea.KeyEnter} + ta, _ = ta.Update(keyPress('a')) + ta, _ = ta.Update(enter) + ta, _ = ta.Update(keyPress('b')) + ta, _ = ta.Update(enter) + ta, _ = ta.Update(keyPress('c')) + + if ta.Height() != 3 { + t.Fatalf("expected height 3 before deletion, got %d", ta.Height()) + } + + // Backspace at start of line 3 merges with line 2 + ta.CursorStart() + backspace := tea.KeyPressMsg{Code: tea.KeyBackspace} + ta, _ = ta.Update(backspace) + + if ta.Height() != 2 { + t.Errorf("expected height 2 after line merge, got %d", ta.Height()) + } +} + +func TestDynamicHeight_RespectsMinHeight(t *testing.T) { + ta := newDynamicTextArea(5, 20) + + ta, _ = ta.Update(keyPress('a')) + + if ta.Height() != 5 { + t.Errorf("expected min height 5, got %d", ta.Height()) + } +} + +func TestDynamicHeight_RespectsMaxHeight(t *testing.T) { + ta := newDynamicTextArea(1, 5) + + enter := tea.KeyPressMsg{Code: tea.KeyEnter} + for range 10 { + ta, _ = ta.Update(keyPress('x')) + ta, _ = ta.Update(enter) + } + + if ta.Height() != 5 { + t.Errorf("expected max height 5, got %d", ta.Height()) + } +} + +func TestDynamicHeight_GrowsOnPaste(t *testing.T) { + ta := newDynamicTextArea(1, 20) + + paste := tea.PasteMsg{Content: "line1\nline2\nline3\nline4\nline5"} + ta, _ = ta.Update(paste) + + if ta.Height() != 5 { + t.Errorf("expected height 5 after pasting 5 lines, got %d", ta.Height()) + } +} + +func TestDynamicHeight_RecalculatesOnSetWidth(t *testing.T) { + ta := newDynamicTextArea(1, 50) + ta.SetWidth(40) + + // Insert a line that fits in 40 cols but wraps in 10 cols + ta.SetValue("abcdefghijklmnopqrstuvwxyz") + + if ta.Height() != 1 { + t.Fatalf("expected height 1 at width 40, got %d", ta.Height()) + } + + ta.SetWidth(10) + + if ta.Height() < 3 { + t.Errorf("expected height >= 3 after narrowing to width 10, got %d", ta.Height()) + } +} + +func TestDynamicHeight_RecalculatesOnSetValue(t *testing.T) { + ta := newDynamicTextArea(1, 20) + + ta.SetValue("a\nb\nc\nd\ne") + + if ta.Height() != 5 { + t.Errorf("expected height 5 after SetValue with 5 lines, got %d", ta.Height()) + } +} + +func TestDynamicHeight_CursorPositionAfterGrow(t *testing.T) { + ta := newDynamicTextArea(1, 20) + + enter := tea.KeyPressMsg{Code: tea.KeyEnter} + for i := range 5 { + ta, _ = ta.Update(keyPress(rune('a' + i))) + ta, _ = ta.Update(enter) + } + ta, _ = ta.Update(keyPress('f')) + + // Cursor should be on the last line (row 5, 0-indexed) + if ta.Line() != 5 { + t.Errorf("expected cursor on row 5, got %d", ta.Line()) + } + + // Cursor visual line should be within the viewport + cursorLine := ta.cursorLineNumber() + minVisible := ta.viewport.YOffset() + maxVisible := minVisible + ta.viewport.Height() - 1 + if cursorLine < minVisible || cursorLine > maxVisible { + t.Errorf("cursor line %d outside viewport [%d, %d]", cursorLine, minVisible, maxVisible) + } +} + +func TestDynamicHeight_CursorPositionAfterShrink(t *testing.T) { + ta := newDynamicTextArea(1, 20) + + enter := tea.KeyPressMsg{Code: tea.KeyEnter} + for i := range 5 { + ta, _ = ta.Update(keyPress(rune('a' + i))) + ta, _ = ta.Update(enter) + } + ta, _ = ta.Update(keyPress('f')) + + if ta.Height() != 6 { + t.Fatalf("expected height 6 before shrink, got %d", ta.Height()) + } + + // Delete lines by backspacing + backspace := tea.KeyPressMsg{Code: tea.KeyBackspace} + ta, _ = ta.Update(backspace) // delete 'f' + ta, _ = ta.Update(backspace) // merge line 5 into 4 + ta, _ = ta.Update(backspace) // delete 'e' + ta, _ = ta.Update(backspace) // merge line 4 into 3 + + cursorLine := ta.cursorLineNumber() + minVisible := ta.viewport.YOffset() + maxVisible := minVisible + ta.viewport.Height() - 1 + if cursorLine < minVisible || cursorLine > maxVisible { + t.Errorf("cursor line %d outside viewport [%d, %d] after shrink", cursorLine, minVisible, maxVisible) + } +} + +func TestDynamicHeight_CursorPositionAfterPaste(t *testing.T) { + ta := newDynamicTextArea(1, 20) + + paste := tea.PasteMsg{Content: "line1\nline2\nline3\nline4\nline5"} + ta, _ = ta.Update(paste) + + // Cursor should be at the end of the last pasted line + if ta.Line() != 4 { + t.Errorf("expected cursor on row 4, got %d", ta.Line()) + } + + cursorLine := ta.cursorLineNumber() + minVisible := ta.viewport.YOffset() + maxVisible := minVisible + ta.viewport.Height() - 1 + if cursorLine < minVisible || cursorLine > maxVisible { + t.Errorf("cursor line %d outside viewport [%d, %d] after paste", cursorLine, minVisible, maxVisible) + } +} + +func TestMaxContentHeight_ScrollsBeyondMaxHeight(t *testing.T) { + ta := newDynamicTextArea(1, 5) + ta.MaxContentHeight = 10 + + enter := tea.KeyPressMsg{Code: tea.KeyEnter} + for range 8 { + ta, _ = ta.Update(keyPress('x')) + ta, _ = ta.Update(enter) + } + + if ta.Height() != 5 { + t.Errorf("expected visible height capped at 5, got %d", ta.Height()) + } + + if ta.LineCount() != 9 { + t.Errorf("expected 9 logical lines, got %d", ta.LineCount()) + } +} + +func TestMaxContentHeight_BlocksAtLimit(t *testing.T) { + ta := New() + ta.Prompt = "" + ta.ShowLineNumbers = false + ta.MaxContentHeight = 5 + ta.SetWidth(20) + ta.Focus() + ta, _ = ta.Update(nil) + + enter := tea.KeyPressMsg{Code: tea.KeyEnter} + for range 10 { + ta, _ = ta.Update(keyPress('x')) + ta, _ = ta.Update(enter) + } + + if ta.totalVisualLines() > 5 { + t.Errorf("expected total visual lines <= 5, got %d", ta.totalVisualLines()) + } +} + +func TestMaxContentHeight_BackwardCompat(t *testing.T) { + ta := New() + ta.Prompt = "" + ta.ShowLineNumbers = false + ta.MaxHeight = 10 + ta.SetWidth(20) + ta.Focus() + ta, _ = ta.Update(nil) + + enter := tea.KeyPressMsg{Code: tea.KeyEnter} + for range 15 { + ta, _ = ta.Update(keyPress('x')) + ta, _ = ta.Update(enter) + } + + if ta.LineCount() > 10 { + t.Errorf("expected logical line count <= 10 (legacy behavior), got %d", ta.LineCount()) + } +} + +func TestMaxContentHeight_WithoutDynamicHeight(t *testing.T) { + ta := New() + ta.Prompt = "" + ta.ShowLineNumbers = false + ta.MaxContentHeight = 5 + ta.SetHeight(3) + ta.SetWidth(20) + ta.Focus() + ta, _ = ta.Update(nil) + + enter := tea.KeyPressMsg{Code: tea.KeyEnter} + for range 10 { + ta, _ = ta.Update(keyPress('x')) + ta, _ = ta.Update(enter) + } + + if ta.Height() != 3 { + t.Errorf("expected fixed height 3, got %d", ta.Height()) + } + + if ta.totalVisualLines() > 5 { + t.Errorf("expected content capped at 5 visual lines, got %d", ta.totalVisualLines()) + } +} + +func TestMaxContentHeight_CursorVisibleWhileScrolling(t *testing.T) { + ta := newDynamicTextArea(1, 5) + ta.MaxContentHeight = 10 + + enter := tea.KeyPressMsg{Code: tea.KeyEnter} + for range 8 { + ta, _ = ta.Update(keyPress('x')) + ta, _ = ta.Update(enter) + } + ta, _ = ta.Update(keyPress('y')) + + cursorLine := ta.cursorLineNumber() + minVisible := ta.viewport.YOffset() + maxVisible := minVisible + ta.viewport.Height() - 1 + if cursorLine < minVisible || cursorLine > maxVisible { + t.Errorf("cursor line %d outside viewport [%d, %d] while scrolling", cursorLine, minVisible, maxVisible) + } +} + +func TestMaxContentHeight_PasteCapped(t *testing.T) { + ta := New() + ta.Prompt = "" + ta.ShowLineNumbers = false + ta.MaxContentHeight = 5 + ta.SetWidth(20) + ta.Focus() + ta, _ = ta.Update(nil) + + paste := tea.PasteMsg{Content: "1\n2\n3\n4\n5\n6\n7\n8\n9\n10"} + ta, _ = ta.Update(paste) + + if ta.totalVisualLines() > 5 { + t.Errorf("expected paste capped at 5 visual lines, got %d", ta.totalVisualLines()) + } +} + +func TestDynamicHeight_ShrinksWhenScrolledAndLinesDeleted(t *testing.T) { + ta := newDynamicTextArea(1, 5) + ta.MaxContentHeight = 10 + + enter := tea.KeyPressMsg{Code: tea.KeyEnter} + // Type 8 lines so we exceed MaxHeight (5) and start scrolling + for range 7 { + ta, _ = ta.Update(keyPress('x')) + ta, _ = ta.Update(enter) + } + ta, _ = ta.Update(keyPress('x')) + + if ta.Height() != 5 { + t.Fatalf("expected height 5 (capped at MaxHeight), got %d", ta.Height()) + } + if ta.LineCount() != 8 { + t.Fatalf("expected 8 lines, got %d", ta.LineCount()) + } + + // Now delete lines from the bottom by selecting all on current line and backspacing + backspace := tea.KeyPressMsg{Code: tea.KeyBackspace} + for ta.LineCount() > 4 { + ta.CursorEnd() + for len(ta.value[ta.row]) > 0 { + ta, _ = ta.Update(backspace) + } + ta, _ = ta.Update(backspace) // merge with previous line + } + + // Now we have 4 lines, which is less than MaxHeight (5). + // Height should shrink to 4. + if ta.Height() != 4 { + t.Errorf("expected height to shrink to 4 (matching content), got %d", ta.Height()) + } + if ta.viewport.YOffset() != 0 { + t.Errorf("expected yOffset 0 after shrinking, got %d", ta.viewport.YOffset()) + } +} + +func TestDynamicHeight_ShrinksWhenScrolledNoMaxContent(t *testing.T) { + // DynamicHeight with MaxHeight but no MaxContentHeight + ta := newDynamicTextArea(1, 99) + + enter := tea.KeyPressMsg{Code: tea.KeyEnter} + // Type 8 lines + for range 7 { + ta, _ = ta.Update(keyPress('x')) + ta, _ = ta.Update(enter) + } + ta, _ = ta.Update(keyPress('x')) + + if ta.Height() != 8 { + t.Fatalf("expected height 8, got %d", ta.Height()) + } + + // Manually set a smaller MaxHeight to simulate scrolling scenario + ta.MaxHeight = 5 + ta, _ = ta.Update(nil) + + // Now delete lines from the bottom + backspace := tea.KeyPressMsg{Code: tea.KeyBackspace} + for ta.LineCount() > 3 { + ta.CursorEnd() + for len(ta.value[ta.row]) > 0 { + ta, _ = ta.Update(backspace) + } + ta, _ = ta.Update(backspace) + } + + if ta.Height() != 3 { + t.Errorf("expected height to shrink to 3 (matching content), got %d", ta.Height()) + } + if ta.viewport.YOffset() != 0 { + t.Errorf("expected yOffset 0 after shrinking, got %d", ta.viewport.YOffset()) + } +} + func newTextArea() Model { textarea := New() From a13f110fba4f13ce5fe9bc7fd51619f5782077b9 Mon Sep 17 00:00:00 2001 From: Rohan Santhosh Kumar <181558744+Rohan5commit@users.noreply.github.com> Date: Mon, 30 Mar 2026 20:41:06 +0800 Subject: [PATCH 06/12] docs: fix typo in README (#921) Co-authored-by: rohan436 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e6eca454..e4936e09 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Build Status](https://github.com/charmbracelet/bubbles/workflows/build/badge.svg)](https://github.com/charmbracelet/bubbles/actions) [![Go ReportCard](https://goreportcard.com/badge/charmbracelet/bubbles)](https://goreportcard.com/report/charmbracelet/bubbles) -Primatives for [Bubble Tea](https://github.com/charmbracelet/bubbletea) +Primitives for [Bubble Tea](https://github.com/charmbracelet/bubbletea) applications. These components are used in production in [Crush][crush], and [many other applications][otherstuff]. > [!TIP] From 204774bbee53ba2ce351262274907a958ceb5a4e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 09:08:44 +0000 Subject: [PATCH 07/12] chore(deps): bump github.com/mattn/go-runewidth in the all group (#945) Bumps the all group with 1 update: [github.com/mattn/go-runewidth](https://github.com/mattn/go-runewidth). Updates `github.com/mattn/go-runewidth` from 0.0.21 to 0.0.22 - [Commits](https://github.com/mattn/go-runewidth/compare/v0.0.21...v0.0.22) --- updated-dependencies: - dependency-name: github.com/mattn/go-runewidth dependency-version: 0.0.22 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2300fe5d..99d2d061 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/charmbracelet/x/ansi v0.11.6 github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f github.com/dustin/go-humanize v1.0.1 - github.com/mattn/go-runewidth v0.0.21 + github.com/mattn/go-runewidth v0.0.22 github.com/rivo/uniseg v0.4.7 github.com/sahilm/fuzzy v0.1.1 ) diff --git a/go.sum b/go.sum index 57d712ff..bd7d4841 100644 --- a/go.sum +++ b/go.sum @@ -34,8 +34,8 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag= github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/mattn/go-runewidth v0.0.21 h1:jJKAZiQH+2mIinzCJIaIG9Be1+0NR+5sz/lYEEjdM8w= -github.com/mattn/go-runewidth v0.0.21/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= +github.com/mattn/go-runewidth v0.0.22 h1:76lXsPn6FyHtTY+jt2fTTvsMUCZq1k0qwRsAMuxzKAk= +github.com/mattn/go-runewidth v0.0.22/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= From 0d62ce2b43f60164f108e591287b0d468135c46c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 09:16:50 +0000 Subject: [PATCH 08/12] chore(deps): bump dependabot/fetch-metadata from 2 to 3 in the all group (#953) Bumps the all group with 1 update: [dependabot/fetch-metadata](https://github.com/dependabot/fetch-metadata). Updates `dependabot/fetch-metadata` from 2 to 3 - [Release notes](https://github.com/dependabot/fetch-metadata/releases) - [Commits](https://github.com/dependabot/fetch-metadata/compare/v2...v3) --- updated-dependencies: - dependency-name: dependabot/fetch-metadata dependency-version: '3' dependency-type: direct:production update-type: version-update:semver-major dependency-group: all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a23325e2..126a9652 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,7 +36,7 @@ jobs: if: ${{ github.actor == 'dependabot[bot]' && github.event_name == 'pull_request'}} steps: - id: metadata - uses: dependabot/fetch-metadata@v2 + uses: dependabot/fetch-metadata@v3 with: github-token: "${{ secrets.GITHUB_TOKEN }}" - run: | From 42130e89579382bb1944b4b1d57e75cae5286d01 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 09:23:14 +0000 Subject: [PATCH 09/12] chore(deps): bump github.com/mattn/go-runewidth in the all group (#952) Bumps the all group with 1 update: [github.com/mattn/go-runewidth](https://github.com/mattn/go-runewidth). Updates `github.com/mattn/go-runewidth` from 0.0.22 to 0.0.23 - [Commits](https://github.com/mattn/go-runewidth/compare/v0.0.22...v0.0.23) --- updated-dependencies: - dependency-name: github.com/mattn/go-runewidth dependency-version: 0.0.23 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 99d2d061..9475e3cd 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/charmbracelet/x/ansi v0.11.6 github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f github.com/dustin/go-humanize v1.0.1 - github.com/mattn/go-runewidth v0.0.22 + github.com/mattn/go-runewidth v0.0.23 github.com/rivo/uniseg v0.4.7 github.com/sahilm/fuzzy v0.1.1 ) diff --git a/go.sum b/go.sum index bd7d4841..4f685421 100644 --- a/go.sum +++ b/go.sum @@ -34,8 +34,8 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag= github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/mattn/go-runewidth v0.0.22 h1:76lXsPn6FyHtTY+jt2fTTvsMUCZq1k0qwRsAMuxzKAk= -github.com/mattn/go-runewidth v0.0.22/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= +github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw= +github.com/mattn/go-runewidth v0.0.23/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= From 6feda242335b791e5b81cc05166236eb753be865 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2026 09:45:13 +0000 Subject: [PATCH 10/12] chore(deps): bump the all group with 3 updates (#958) Bumps the all group with 3 updates: [charm.land/bubbletea/v2](https://github.com/charmbracelet/bubbletea), [charm.land/lipgloss/v2](https://github.com/charmbracelet/lipgloss) and [github.com/charmbracelet/x/ansi](https://github.com/charmbracelet/x). Updates `charm.land/bubbletea/v2` from 2.0.2 to 2.0.6 - [Release notes](https://github.com/charmbracelet/bubbletea/releases) - [Commits](https://github.com/charmbracelet/bubbletea/compare/v2.0.2...v2.0.6) Updates `charm.land/lipgloss/v2` from 2.0.2 to 2.0.3 - [Release notes](https://github.com/charmbracelet/lipgloss/releases) - [Commits](https://github.com/charmbracelet/lipgloss/compare/v2.0.2...v2.0.3) Updates `github.com/charmbracelet/x/ansi` from 0.11.6 to 0.11.7 - [Commits](https://github.com/charmbracelet/x/compare/ansi/v0.11.6...ansi/v0.11.7) --- updated-dependencies: - dependency-name: charm.land/bubbletea/v2 dependency-version: 2.0.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all - dependency-name: charm.land/lipgloss/v2 dependency-version: 2.0.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all - dependency-name: github.com/charmbracelet/x/ansi dependency-version: 0.11.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 16 ++++++++-------- go.sum | 32 ++++++++++++++++---------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 9475e3cd..755ce650 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,12 @@ module charm.land/bubbles/v2 go 1.25.0 require ( - charm.land/bubbletea/v2 v2.0.2 - charm.land/lipgloss/v2 v2.0.2 + charm.land/bubbletea/v2 v2.0.6 + charm.land/lipgloss/v2 v2.0.3 github.com/MakeNowJust/heredoc v1.0.0 github.com/atotto/clipboard v0.1.4 github.com/charmbracelet/harmonica v0.2.0 - github.com/charmbracelet/x/ansi v0.11.6 + github.com/charmbracelet/x/ansi v0.11.7 github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f github.com/dustin/go-humanize v1.0.1 github.com/mattn/go-runewidth v0.0.23 @@ -18,17 +18,17 @@ require ( require ( github.com/aymanbagabas/go-udiff v0.4.1 // indirect - github.com/charmbracelet/colorprofile v0.4.2 // indirect - github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8 // indirect + github.com/charmbracelet/colorprofile v0.4.3 // indirect + github.com/charmbracelet/ultraviolet v0.0.0-20260416155717-489999b90468 // indirect github.com/charmbracelet/x/term v0.2.2 // indirect github.com/charmbracelet/x/termios v0.1.1 // indirect github.com/charmbracelet/x/windows v0.2.2 // indirect github.com/clipperhouse/displaywidth v0.11.0 // indirect github.com/clipperhouse/uax29/v2 v2.7.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/lucasb-eyer/go-colorful v1.3.0 // indirect + github.com/lucasb-eyer/go-colorful v1.4.0 // indirect github.com/muesli/cancelreader v0.2.2 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - golang.org/x/sync v0.19.0 // indirect - golang.org/x/sys v0.42.0 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/sys v0.43.0 // indirect ) diff --git a/go.sum b/go.sum index 4f685421..022748cd 100644 --- a/go.sum +++ b/go.sum @@ -1,21 +1,21 @@ -charm.land/bubbletea/v2 v2.0.2 h1:4CRtRnuZOdFDTWSff9r8QFt/9+z6Emubz3aDMnf/dx0= -charm.land/bubbletea/v2 v2.0.2/go.mod h1:3LRff2U4WIYXy7MTxfbAQ+AdfM3D8Xuvz2wbsOD9OHQ= -charm.land/lipgloss/v2 v2.0.2 h1:xFolbF8JdpNkM2cEPTfXEcW1p6NRzOWTSamRfYEw8cs= -charm.land/lipgloss/v2 v2.0.2/go.mod h1:KjPle2Qd3YmvP1KL5OMHiHysGcNwq6u83MUjYkFvEkM= +charm.land/bubbletea/v2 v2.0.6 h1:UHN/91OyuhaOFGSrBXQ/hMZD8IO1Uc4BvHlgHXL2WJo= +charm.land/bubbletea/v2 v2.0.6/go.mod h1:MH/D8ZLlN3op37vQvijKuU29g3rqTp+aQapURFonF9g= +charm.land/lipgloss/v2 v2.0.3 h1:yM2zJ4Cf5Y51b7RHIwioil4ApI/aypFXXVHSwlM6RzU= +charm.land/lipgloss/v2 v2.0.3/go.mod h1:7myLU9iG/3xluAWzpY/fSxYYHCgoKTie7laxk6ATwXA= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aymanbagabas/go-udiff v0.4.1 h1:OEIrQ8maEeDBXQDoGCbbTTXYJMYRCRO1fnodZ12Gv5o= github.com/aymanbagabas/go-udiff v0.4.1/go.mod h1:0L9PGwj20lrtmEMeyw4WKJ/TMyDtvAoK9bf2u/mNo3w= -github.com/charmbracelet/colorprofile v0.4.2 h1:BdSNuMjRbotnxHSfxy+PCSa4xAmz7szw70ktAtWRYrY= -github.com/charmbracelet/colorprofile v0.4.2/go.mod h1:0rTi81QpwDElInthtrQ6Ni7cG0sDtwAd4C4le060fT8= +github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q= +github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= -github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8 h1:eyFRbAmexyt43hVfeyBofiGSEmJ7krjLOYt/9CF5NKA= -github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8/go.mod h1:SQpCTRNBtzJkwku5ye4S3HEuthAlGy2n9VXZnWkEW98= -github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8= -github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ= +github.com/charmbracelet/ultraviolet v0.0.0-20260416155717-489999b90468 h1:Q9fO0y1Zo5KB/5Vu8JZoLGm1N3RzF9bNj3Ao3xoR+Ac= +github.com/charmbracelet/ultraviolet v0.0.0-20260416155717-489999b90468/go.mod h1:bAAz7dh/FTYfC+oiHavL4mX1tOIBZ0ZwYjSi3qE6ivM= +github.com/charmbracelet/x/ansi v0.11.7 h1:kzv1kJvjg2S3r9KHo8hDdHFQLEqn4RBCb39dAYC84jI= +github.com/charmbracelet/x/ansi v0.11.7/go.mod h1:9qGpnAVYz+8ACONkZBUWPtL7lulP9No6p1epAihUZwQ= github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f h1:pk6gmGpCE7F3FcjaOEKYriCvpmIN4+6OS/RD0vm4uIA= github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f/go.mod h1:IfZAMTHB6XkZSeXUqriemErjAWCCzT0LwjKFYCZyw0I= github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk= @@ -32,8 +32,8 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag= -github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/lucasb-eyer/go-colorful v1.4.0 h1:UtrWVfLdarDgc44HcS7pYloGHJUjHV/4FwW4TvVgFr4= +github.com/lucasb-eyer/go-colorful v1.4.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw= github.com/mattn/go-runewidth v0.0.23/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= @@ -46,7 +46,7 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavM github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= -golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= -golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= -golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= -golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= +golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= From ef0090e82011ea6f6cf3926a4843626baa9b8c19 Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Wed, 22 Apr 2026 11:14:34 -0300 Subject: [PATCH 11/12] chore: remove CODEOWNERS --- .github/CODEOWNERS | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index df42f0f2..00000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1,14 +0,0 @@ -* @meowgorithm @bashbunni -cursor/ @aymanbagabas -filepicker/ @bashbunni -help/ @meowgorithm -key/ @meowgorithm -list/ @meowgorithm -paginator/ @meowgorithm -progress/ @meowgorithm -spinner/ @meowgorithm -stopwatch/ @caarlos0 -table/ @aymanbagabas -textarea/ @aymanbagabas -textinput/ @meowgorithm -viewport/ @meowgorithm From 877b20eb8e6aa38a5549f7911392aab3c2782d0f Mon Sep 17 00:00:00 2001 From: Hermes Semantic Memory Date: Thu, 30 Apr 2026 11:26:08 +0800 Subject: [PATCH 12/12] feat(cursor): export BlinkCanceled type Export the previously unexported blinkCanceled type as BlinkCanceled so that external consumers can handle blink cancellation events in their own cursor implementations. Closes #834 --- cursor/cursor.go | 8 ++++---- cursor/cursor_test.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cursor/cursor.go b/cursor/cursor.go index 662ad18f..3ec5d8f2 100644 --- a/cursor/cursor.go +++ b/cursor/cursor.go @@ -31,8 +31,8 @@ type BlinkMsg struct { tag int } -// blinkCanceled is sent when a blink operation is canceled. -type blinkCanceled struct{} +// BlinkCanceled is sent when a blink operation is canceled. +type BlinkCanceled struct{} // blinkCtx manages cursor blinking. type blinkCtx struct { @@ -151,7 +151,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { } return m, cmd - case blinkCanceled: // no-op + case BlinkCanceled: // no-op return m, nil } return m, nil @@ -201,7 +201,7 @@ func (m *Model) Blink() tea.Cmd { if ctx.Err() == context.DeadlineExceeded { return blinkMsg } - return blinkCanceled{} + return BlinkCanceled{} } } diff --git a/cursor/cursor_test.go b/cursor/cursor_test.go index e2083f6d..4f3fd92e 100644 --- a/cursor/cursor_test.go +++ b/cursor/cursor_test.go @@ -16,7 +16,7 @@ import ( // if ctx.Err() == context.DeadlineExceeded { // return BlinkMsg{id: m.id, tag: m.blinkTag} // } -// return blinkCanceled{} +// return BlinkCanceled{} // } // // A race on “m.blinkTag” will occur if: