mirror of
https://github.com/mark3labs/kit.git
synced 2026-06-14 03:30:26 +00:00
28d2de8f39
Moved leaf utility files to subpackages for better organization: - events.go -> core/ (core message types) - clipboard.go -> clipboard/ (clipboard operations) - commands.go -> commands/ (slash commands) - file_processor.go -> fileutil/ (file attachment processing) - preferences.go -> prefs/ (theme/model preferences) - enhanced_styles.go, styles.go, themes.go -> style/ (theming system) Added exports.go to re-export commonly used types for backward compatibility. External importers can still use ui.XXX without changes. All tests pass, basic smoke test successful.
235 lines
6.4 KiB
Go
235 lines
6.4 KiB
Go
package ui
|
|
|
|
import (
|
|
"image/color"
|
|
|
|
"charm.land/lipgloss/v2"
|
|
|
|
"github.com/mark3labs/kit/internal/ui/style"
|
|
)
|
|
|
|
// blockRenderer handles rendering of content blocks with configurable options
|
|
type blockRenderer struct {
|
|
align *lipgloss.Position
|
|
borderColor *color.Color
|
|
background *color.Color
|
|
foreground *color.Color
|
|
fullWidth bool
|
|
noBorder bool
|
|
paddingTop int
|
|
paddingBottom int
|
|
paddingLeft int
|
|
paddingRight int
|
|
marginTop int
|
|
marginBottom int
|
|
width int
|
|
}
|
|
|
|
// renderingOption configures block rendering
|
|
type renderingOption func(*blockRenderer)
|
|
|
|
// WithFullWidth returns a renderingOption that configures the block renderer
|
|
// to expand to the full available width of its container. When enabled, the
|
|
// block will fill the entire horizontal space rather than sizing to its content.
|
|
func WithFullWidth() renderingOption {
|
|
return func(c *blockRenderer) {
|
|
c.fullWidth = true
|
|
}
|
|
}
|
|
|
|
// WithNoBorder returns a renderingOption that disables all borders on the
|
|
// block, rendering content with only padding.
|
|
func WithNoBorder() renderingOption {
|
|
return func(c *blockRenderer) {
|
|
c.noBorder = true
|
|
}
|
|
}
|
|
|
|
// WithAlign returns a renderingOption that sets the horizontal alignment
|
|
// of the block content within its container. The align parameter accepts
|
|
// lipgloss.Left, lipgloss.Center, or lipgloss.Right positions.
|
|
func WithAlign(align lipgloss.Position) renderingOption {
|
|
return func(c *blockRenderer) {
|
|
c.align = &align
|
|
}
|
|
}
|
|
|
|
// WithBorderColor returns a renderingOption that sets the border color
|
|
// for the block. The color parameter uses lipgloss.AdaptiveColor to support
|
|
// both light and dark terminal themes automatically.
|
|
func WithBorderColor(c color.Color) renderingOption {
|
|
return func(br *blockRenderer) {
|
|
br.borderColor = &c
|
|
}
|
|
}
|
|
|
|
// WithMarginTop returns a renderingOption that sets the top margin
|
|
// for the block. The margin is specified in number of lines and adds
|
|
// vertical space above the block.
|
|
func WithMarginTop(margin int) renderingOption {
|
|
return func(c *blockRenderer) {
|
|
c.marginTop = margin
|
|
}
|
|
}
|
|
|
|
// WithMarginBottom returns a renderingOption that sets the bottom margin
|
|
// for the block. The margin is specified in number of lines and adds
|
|
// vertical space below the block.
|
|
func WithMarginBottom(margin int) renderingOption {
|
|
return func(c *blockRenderer) {
|
|
c.marginBottom = margin
|
|
}
|
|
}
|
|
|
|
// WithPaddingLeft returns a renderingOption that sets the left padding
|
|
// for the block content. The padding is specified in number of characters
|
|
// and adds horizontal space between the left border and the content.
|
|
func WithPaddingLeft(padding int) renderingOption {
|
|
return func(c *blockRenderer) {
|
|
c.paddingLeft = padding
|
|
}
|
|
}
|
|
|
|
// WithPaddingRight returns a renderingOption that sets the right padding
|
|
// for the block content. The padding is specified in number of characters
|
|
// and adds horizontal space between the content and the right border.
|
|
func WithPaddingRight(padding int) renderingOption {
|
|
return func(c *blockRenderer) {
|
|
c.paddingRight = padding
|
|
}
|
|
}
|
|
|
|
// WithPaddingTop returns a renderingOption that sets the top padding
|
|
// for the block content. The padding is specified in number of lines
|
|
// and adds vertical space between the top border and the content.
|
|
func WithPaddingTop(padding int) renderingOption {
|
|
return func(c *blockRenderer) {
|
|
c.paddingTop = padding
|
|
}
|
|
}
|
|
|
|
// WithPaddingBottom returns a renderingOption that sets the bottom padding
|
|
// for the block content. The padding is specified in number of lines
|
|
// and adds vertical space between the content and the bottom border.
|
|
func WithPaddingBottom(padding int) renderingOption {
|
|
return func(c *blockRenderer) {
|
|
c.paddingBottom = padding
|
|
}
|
|
}
|
|
|
|
// WithBackground returns a renderingOption that sets the background color
|
|
// for the entire block. The color parameter accepts any color.Color value,
|
|
// typically a lipgloss hex color (e.g. lipgloss.Color("#1e1e2e")).
|
|
func WithBackground(c color.Color) renderingOption {
|
|
return func(br *blockRenderer) {
|
|
br.background = &c
|
|
}
|
|
}
|
|
|
|
// WithForeground returns a renderingOption that overrides the default text
|
|
// foreground color (theme.Text) for the block. Useful for muted or
|
|
// de-emphasized content blocks.
|
|
func WithForeground(c color.Color) renderingOption {
|
|
return func(br *blockRenderer) {
|
|
br.foreground = &c
|
|
}
|
|
}
|
|
|
|
// WithWidth returns a renderingOption that sets a specific width for the block
|
|
// in characters. This overrides the default container width and allows precise
|
|
// control over the block's horizontal dimensions.
|
|
func WithWidth(width int) renderingOption {
|
|
return func(c *blockRenderer) {
|
|
c.width = width
|
|
}
|
|
}
|
|
|
|
// renderContentBlock renders content with configurable styling options
|
|
func renderContentBlock(content string, containerWidth int, options ...renderingOption) string {
|
|
renderer := &blockRenderer{
|
|
fullWidth: true,
|
|
paddingTop: 1,
|
|
paddingBottom: 1,
|
|
paddingLeft: 2,
|
|
paddingRight: 0,
|
|
width: containerWidth,
|
|
}
|
|
|
|
for _, option := range options {
|
|
option(renderer)
|
|
}
|
|
|
|
// Resolve border configuration.
|
|
hasBorder := !renderer.noBorder
|
|
borderChars := 0
|
|
|
|
borderAlign := lipgloss.Left
|
|
if renderer.align != nil {
|
|
borderAlign = *renderer.align
|
|
}
|
|
|
|
var borderColor color.Color = lipgloss.NoColor{}
|
|
if renderer.borderColor != nil {
|
|
borderColor = *renderer.borderColor
|
|
}
|
|
|
|
if hasBorder {
|
|
borderChars = 1
|
|
}
|
|
|
|
theme := style.GetTheme()
|
|
|
|
// Resolve foreground color: caller override or theme default.
|
|
fgColor := theme.Text
|
|
if renderer.foreground != nil {
|
|
fgColor = *renderer.foreground
|
|
}
|
|
|
|
// Single-pass render: padding, border, and foreground in one style.
|
|
style := lipgloss.NewStyle().
|
|
PaddingLeft(renderer.paddingLeft).
|
|
PaddingRight(renderer.paddingRight).
|
|
PaddingTop(renderer.paddingTop).
|
|
PaddingBottom(renderer.paddingBottom).
|
|
Foreground(fgColor)
|
|
|
|
if hasBorder {
|
|
style = style.BorderStyle(lipgloss.ThickBorder())
|
|
|
|
switch borderAlign {
|
|
case lipgloss.Right:
|
|
style = style.
|
|
BorderRight(true).
|
|
BorderRightForeground(borderColor)
|
|
default:
|
|
style = style.
|
|
BorderLeft(true).
|
|
BorderLeftForeground(borderColor)
|
|
}
|
|
}
|
|
|
|
if renderer.background != nil {
|
|
style = style.Background(*renderer.background)
|
|
}
|
|
|
|
if renderer.fullWidth {
|
|
style = style.Width(renderer.width - borderChars)
|
|
}
|
|
|
|
content = style.Render(content)
|
|
|
|
// Add margins
|
|
if renderer.marginTop > 0 {
|
|
for range renderer.marginTop {
|
|
content = "\n" + content
|
|
}
|
|
}
|
|
if renderer.marginBottom > 0 {
|
|
for range renderer.marginBottom {
|
|
content = content + "\n"
|
|
}
|
|
}
|
|
|
|
return content
|
|
}
|