mirror of
https://github.com/zoriya/bubbles.git
synced 2026-08-16 01:43:21 +00:00
feat(textarea): make max width/height configurable
This commit is contained in:
committed by
Maas Lalani
parent
dc58240609
commit
afb975b469
+38
-11
@@ -21,8 +21,8 @@ const (
|
|||||||
defaultHeight = 6
|
defaultHeight = 6
|
||||||
defaultWidth = 40
|
defaultWidth = 40
|
||||||
defaultCharLimit = 400
|
defaultCharLimit = 400
|
||||||
maxHeight = 99
|
defaultMaxHeight = 99
|
||||||
maxWidth = 500
|
defaultMaxWidth = 500
|
||||||
)
|
)
|
||||||
|
|
||||||
// Internal messages for clipboard operations.
|
// Internal messages for clipboard operations.
|
||||||
@@ -174,6 +174,14 @@ type Model struct {
|
|||||||
// accept. If 0 or less, there's no limit.
|
// accept. If 0 or less, there's no limit.
|
||||||
CharLimit int
|
CharLimit int
|
||||||
|
|
||||||
|
// MaxHeight is the maximum height of the text area in rows. If 0 or less,
|
||||||
|
// there's no limit.
|
||||||
|
MaxHeight int
|
||||||
|
|
||||||
|
// MaxWidth is the maximum width of the text area in columns. If 0 or less,
|
||||||
|
// there's no limit.
|
||||||
|
MaxWidth int
|
||||||
|
|
||||||
// If promptFunc is set, it replaces Prompt as a generator for
|
// If promptFunc is set, it replaces Prompt as a generator for
|
||||||
// prompt strings at the beginning of each line.
|
// prompt strings at the beginning of each line.
|
||||||
promptFunc func(line int) string
|
promptFunc func(line int) string
|
||||||
@@ -228,6 +236,8 @@ func New() Model {
|
|||||||
|
|
||||||
m := Model{
|
m := Model{
|
||||||
CharLimit: defaultCharLimit,
|
CharLimit: defaultCharLimit,
|
||||||
|
MaxHeight: defaultMaxHeight,
|
||||||
|
MaxWidth: defaultMaxWidth,
|
||||||
Prompt: lipgloss.ThickBorder().Left + " ",
|
Prompt: lipgloss.ThickBorder().Left + " ",
|
||||||
style: &blurredStyle,
|
style: &blurredStyle,
|
||||||
FocusedStyle: focusedStyle,
|
FocusedStyle: focusedStyle,
|
||||||
@@ -237,7 +247,7 @@ func New() Model {
|
|||||||
Cursor: cur,
|
Cursor: cur,
|
||||||
KeyMap: DefaultKeyMap,
|
KeyMap: DefaultKeyMap,
|
||||||
|
|
||||||
value: make([][]rune, minHeight, maxHeight),
|
value: make([][]rune, minHeight, defaultMaxHeight),
|
||||||
focus: false,
|
focus: false,
|
||||||
col: 0,
|
col: 0,
|
||||||
row: 0,
|
row: 0,
|
||||||
@@ -336,8 +346,8 @@ func (m *Model) insertRunesFromUserInput(runes []rune) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Obey the maximum height limit.
|
// Obey the maximum height limit.
|
||||||
if len(m.value)+len(lines)-1 > maxHeight {
|
if m.MaxHeight > 0 && len(m.value)+len(lines)-1 > m.MaxHeight {
|
||||||
allowedHeight := max(0, maxHeight-len(m.value)+1)
|
allowedHeight := max(0, m.MaxHeight-len(m.value)+1)
|
||||||
lines = lines[:allowedHeight]
|
lines = lines[:allowedHeight]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,7 +540,11 @@ func (m *Model) Blur() {
|
|||||||
|
|
||||||
// Reset sets the input to its default state with no input.
|
// Reset sets the input to its default state with no input.
|
||||||
func (m *Model) Reset() {
|
func (m *Model) Reset() {
|
||||||
m.value = make([][]rune, minHeight, maxHeight)
|
startCap := m.MaxHeight
|
||||||
|
if startCap <= 0 {
|
||||||
|
startCap = defaultMaxHeight
|
||||||
|
}
|
||||||
|
m.value = make([][]rune, minHeight, startCap)
|
||||||
m.col = 0
|
m.col = 0
|
||||||
m.row = 0
|
m.row = 0
|
||||||
m.viewport.GotoTop()
|
m.viewport.GotoTop()
|
||||||
@@ -830,7 +844,11 @@ func (m *Model) moveToEnd() {
|
|||||||
// It is important that the width of the textarea be exactly the given width
|
// It is important that the width of the textarea be exactly the given width
|
||||||
// and no more.
|
// and no more.
|
||||||
func (m *Model) SetWidth(w int) {
|
func (m *Model) SetWidth(w int) {
|
||||||
m.viewport.Width = clamp(w, minWidth, maxWidth)
|
if m.MaxWidth > 0 {
|
||||||
|
m.viewport.Width = clamp(w, minWidth, m.MaxWidth)
|
||||||
|
} else {
|
||||||
|
m.viewport.Width = max(w, minWidth)
|
||||||
|
}
|
||||||
|
|
||||||
// Since the width of the textarea input is dependent on the width of the
|
// Since the width of the textarea input is dependent on the width of the
|
||||||
// prompt and line numbers, we need to calculate it by subtracting.
|
// prompt and line numbers, we need to calculate it by subtracting.
|
||||||
@@ -847,7 +865,11 @@ func (m *Model) SetWidth(w int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inputWidth -= m.promptWidth
|
inputWidth -= m.promptWidth
|
||||||
m.width = clamp(inputWidth, minWidth, maxWidth)
|
if m.MaxWidth > 0 {
|
||||||
|
m.width = clamp(inputWidth, minWidth, m.MaxWidth)
|
||||||
|
} else {
|
||||||
|
m.width = max(inputWidth, minWidth)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPromptFunc supersedes the Prompt field and sets a dynamic prompt
|
// SetPromptFunc supersedes the Prompt field and sets a dynamic prompt
|
||||||
@@ -869,8 +891,13 @@ func (m Model) Height() int {
|
|||||||
|
|
||||||
// SetHeight sets the height of the textarea.
|
// SetHeight sets the height of the textarea.
|
||||||
func (m *Model) SetHeight(h int) {
|
func (m *Model) SetHeight(h int) {
|
||||||
m.height = clamp(h, minHeight, maxHeight)
|
if m.MaxHeight > 0 {
|
||||||
m.viewport.Height = clamp(h, minHeight, maxHeight)
|
m.height = clamp(h, minHeight, m.MaxHeight)
|
||||||
|
m.viewport.Height = clamp(h, minHeight, m.MaxHeight)
|
||||||
|
} else {
|
||||||
|
m.height = max(h, minHeight)
|
||||||
|
m.viewport.Height = max(h, minHeight)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update is the Bubble Tea update loop.
|
// Update is the Bubble Tea update loop.
|
||||||
@@ -940,7 +967,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
m.deleteWordRight()
|
m.deleteWordRight()
|
||||||
case key.Matches(msg, m.KeyMap.InsertNewline):
|
case key.Matches(msg, m.KeyMap.InsertNewline):
|
||||||
if len(m.value) >= maxHeight {
|
if m.MaxHeight > 0 && len(m.value) >= m.MaxHeight {
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
m.col = clamp(m.col, 0, len(m.value[m.row]))
|
m.col = clamp(m.col, 0, len(m.value[m.row]))
|
||||||
|
|||||||
Reference in New Issue
Block a user