fx

package
v0.22.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 9, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package fx provides a composable, time-driven cell-level effect pipeline for termdash widgets.

Wrap any widgetapi.Widget in an EffectWidget and attach a sequence of Effects (FadeIn, SweepLeft, Dissolve, …). Each effect runs for a fixed duration, then the next one begins. Once the sequence is exhausted the widget renders normally with no overhead.

Basic usage:

txt, _ := text.New()
fxWidget, _ := fx.New(txt,
    fx.FadeIn(400*time.Millisecond),
    fx.SweepLeft(300*time.Millisecond),
)
// Place fxWidget inside a container instead of txt.

Parallel effects:

fxWidget, _ := fx.New(txt, fx.Parallel(
    fx.FadeIn(500*time.Millisecond),
    fx.SweepDown(500*time.Millisecond),
))

Looping:

fxWidget, _ := fx.NewLooping(txt, fx.Dissolve(600*time.Millisecond, 42))

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsRGB6

func IsRGB6(c cell.Color) bool

IsRGB6 reports whether c is a ColorRGB6 color that supports smooth color-interpolation effects.

Types

type CellFunc

type CellFunc func(elapsed, total time.Duration, x, y, w, h int, src *buffer.Cell) *buffer.Cell

CellFunc is the signature for a cell-level transform applied during animation.

  • elapsed is how long the current effect has been running.
  • total is the full duration of the current effect.
  • x, y are the zero-based canvas column and row of the cell.
  • w, h are the canvas width and height in cells.
  • src is the cell that the wrapped widget painted; never nil.

Return nil to render the cell as a blank (space with default colors). Return src (or a copy of it) to render the original content.

type Effect

type Effect struct {
	// Duration is how long this step plays before the next one begins.
	Duration time.Duration
	// Fn is called once per canvas cell on every Draw cycle while this
	// effect is the active step.  Must be goroutine-safe.
	Fn CellFunc
}

Effect describes one step in an animation sequence.

func ColorFadeIn

func ColorFadeIn(d time.Duration) Effect

ColorFadeIn returns an Effect that interpolates cell foreground and background colors from black to their target values over duration d.

This effect produces the smoothest results when widgets use ColorRGB6 colors (termdash ColorMode256). For named or ColorNumber colors it falls back to the same three-step dim transition as FadeIn.

func ColorFadeOut

func ColorFadeOut(d time.Duration) Effect

ColorFadeOut returns an Effect that interpolates colors to black over d. It is the time-reverse of ColorFadeIn.

func Dissolve

func Dissolve(d time.Duration, seed int64) Effect

Dissolve returns an Effect that reveals canvas cells in a pseudo-random order over duration d. seed controls the pattern; the same seed always produces the same reveal sequence regardless of canvas contents.

The permutation is computed lazily on the first Draw call and cached for subsequent frames. If the canvas is resized the permutation is recomputed automatically.

func FadeIn

func FadeIn(d time.Duration) Effect

FadeIn returns an Effect that transitions the widget from invisible to fully visible over duration d.

The transition is three-step so it works on every color mode and with every widget:

t ∈ [0, 0.30)  → cell is blank
t ∈ [0.30, 0.65) → cell is visible but dimmed
t ∈ [0.65, 1.0]  → cell is fully bright

func FadeOut

func FadeOut(d time.Duration) Effect

FadeOut returns an Effect that transitions the widget from fully visible to invisible over duration d. It is the time-reverse of FadeIn.

func Glitch

func Glitch(d time.Duration, seed int64) Effect

Glitch returns an Effect that briefly floods the canvas with block-drawing noise before settling to the real content. It peaks at mid-animation and decays away by t=1.

seed makes the noise pattern reproducible. Because noise is derived from a fast integer hash (no shared mutable state) the function is allocation-free and goroutine-safe.

func Parallel

func Parallel(effects ...Effect) Effect

Parallel returns a single Effect that applies all of the provided effects simultaneously. The combined duration equals the longest individual duration; shorter effects hold their final frame until the combined effect finishes.

func ScanLine

func ScanLine(d time.Duration) Effect

ScanLine returns an Effect that draws a bright horizontal scan-line that sweeps from top to bottom, illuminating cells it passes over and leaving them fully revealed behind it.

func Scramble

func Scramble(seed int64) Effect

Scramble returns an Effect that permanently replaces all non-blank cells with animated block-drawing noise, hiding the underlying widget content.

The noise pattern changes every 80 ms so the scramble appears to animate. Use NewLooping to keep the effect running indefinitely:

fx.NewLooping(inner, fx.Scramble(42))

seed makes the noise pattern reproducible across runs.

func SweepDown

func SweepDown(d time.Duration) Effect

SweepDown returns an Effect that reveals the canvas from top to bottom, row by row, over duration d.

func SweepLeft

func SweepLeft(d time.Duration) Effect

SweepLeft returns an Effect that reveals the canvas from left to right, column by column, over duration d.

func SweepRight

func SweepRight(d time.Duration) Effect

SweepRight returns an Effect that reveals the canvas from right to left over duration d.

func SweepUp

func SweepUp(d time.Duration) Effect

SweepUp returns an Effect that reveals the canvas from bottom to top over duration d.

func WipeDiagonal

func WipeDiagonal(d time.Duration) Effect

WipeDiagonal returns an Effect that reveals the canvas along a diagonal sweep from the top-left corner to the bottom-right over duration d. The reveal frontier is a line perpendicular to the main diagonal.

type EffectWidget

type EffectWidget struct {
	// contains filtered or unexported fields
}

EffectWidget wraps any widgetapi.Widget and plays a sequential pipeline of Effects on its rendered output each frame.

All widget methods are fully delegated to the inner widget so keyboard and mouse handling, size negotiation, and options work transparently.

Implements widgetapi.Widget. This object is thread-safe.

func New

func New(inner widgetapi.Widget, effects ...Effect) (*EffectWidget, error)

New wraps inner and plays each effect in order. After all effects finish the widget passes through its inner widget's output unmodified.

func NewLooping

func NewLooping(inner widgetapi.Widget, effects ...Effect) (*EffectWidget, error)

NewLooping wraps inner and replays the effect sequence forever.

func (*EffectWidget) Done

func (w *EffectWidget) Done() bool

Done reports whether all effects have finished playing. Always returns false for a looping EffectWidget.

func (*EffectWidget) Draw

func (w *EffectWidget) Draw(cvs *canvas.Canvas, meta *widgetapi.Meta) error

Draw implements widgetapi.Widget.

func (*EffectWidget) Keyboard

func (w *EffectWidget) Keyboard(k *terminalapi.Keyboard, meta *widgetapi.EventMeta) error

Keyboard implements widgetapi.Widget.

func (*EffectWidget) Mouse

func (w *EffectWidget) Mouse(m *terminalapi.Mouse, meta *widgetapi.EventMeta) error

Mouse implements widgetapi.Widget.

func (*EffectWidget) Options

func (w *EffectWidget) Options() widgetapi.Options

Options implements widgetapi.Widget.

func (*EffectWidget) Reset

func (w *EffectWidget) Reset()

Reset restarts the effect sequence from the beginning. Safe to call from any goroutine.

type FocusEffectWidget

type FocusEffectWidget struct {

	// OnFocusChange, if non-nil, is called in a new goroutine on each focus
	// transition.  gained=true means the container just received focus.
	OnFocusChange func(gained bool)
	// contains filtered or unexported fields
}

FocusEffectWidget wraps any widgetapi.Widget and plays different effect sequences when the container gains or loses keyboard focus.

Create with FocusNew, then optionally set OnFocusChange to be notified of each focus transition.

Example:

fw, _ := fx.FocusNew(myWidget,
    []fx.Effect{fx.FadeIn(300*time.Millisecond)},   // gained
    []fx.Effect{fx.FadeOut(300*time.Millisecond)},  // lost
)
fw.OnFocusChange = func(gained bool) {
    // update the container border or widget border here
}

Implements widgetapi.Widget. Thread-safe.

func FocusNew

func FocusNew(inner widgetapi.Widget, focusIn, focusOut []Effect) (*FocusEffectWidget, error)

FocusNew wraps inner, playing focusIn when the container gains focus and focusOut when it loses focus. Either slice may be nil or empty to skip the corresponding animation.

func (*FocusEffectWidget) Draw

func (w *FocusEffectWidget) Draw(cvs *canvas.Canvas, meta *widgetapi.Meta) error

Draw implements widgetapi.Widget.

func (*FocusEffectWidget) Keyboard

Keyboard implements widgetapi.Widget.

func (*FocusEffectWidget) Mouse

Mouse implements widgetapi.Widget.

func (*FocusEffectWidget) Options

func (w *FocusEffectWidget) Options() widgetapi.Options

Options implements widgetapi.Widget.

type FramedOption

type FramedOption interface {
	// contains filtered or unexported methods
}

FramedOption configures a FramedWidget.

func FramedBorderOpts

func FramedBorderOpts(opts ...cell.Option) FramedOption

FramedBorderOpts sets the initial cell options applied to all border cells (e.g. foreground color, bold). These are used as a base; SetBorderColor layered on top without discarding the base options.

func FramedLineStyle

func FramedLineStyle(ls linestyle.LineStyle) FramedOption

FramedLineStyle sets the border line style. Default: linestyle.Round.

func FramedTitle

func FramedTitle(title string, opts ...cell.Option) FramedOption

FramedTitle sets the title text drawn in the top border row. opts are applied to the title characters only.

type FramedWidget

type FramedWidget struct {
	// contains filtered or unexported fields
}

FramedWidget wraps any widgetapi.Widget and paints its own border directly onto the widget canvas so that effect wrappers (EffectWidget, FocusEffectWidget) animate the border characters together with the inner content.

The typical stack for a whole-container focus effect is:

inner  → FramedNew(inner, ...)     → fx.NewLooping(framed, effect)
       → fx.FocusNew(ew, in, out)

Place the outermost widget in a container with linestyle.None so the container does not draw a second border on top.

The border color can be updated at runtime by calling SetBorderColor — it is safe to call from any goroutine.

Create with FramedNew.

func FramedNew

func FramedNew(inner widgetapi.Widget, opts ...FramedOption) (*FramedWidget, error)

FramedNew wraps inner with a self-drawn border. The returned widget should be placed in a container with linestyle.None to avoid a double border.

func (*FramedWidget) Draw

func (fw *FramedWidget) Draw(cvs *canvas.Canvas, meta *widgetapi.Meta) error

Draw implements widgetapi.Widget.

func (*FramedWidget) Keyboard

func (fw *FramedWidget) Keyboard(k *terminalapi.Keyboard, meta *widgetapi.EventMeta) error

Keyboard implements widgetapi.Widget.

func (*FramedWidget) Mouse

func (fw *FramedWidget) Mouse(m *terminalapi.Mouse, meta *widgetapi.EventMeta) error

Mouse implements widgetapi.Widget.

func (*FramedWidget) Options

func (fw *FramedWidget) Options() widgetapi.Options

Options implements widgetapi.Widget.

func (*FramedWidget) SetBorderColor

func (fw *FramedWidget) SetBorderColor(c cell.Color)

SetBorderColor updates the foreground color of all border cells. It overlays the color on top of any options set via FramedBorderOpts. Safe to call from any goroutine; takes effect on the next Draw call.

Directories

Path Synopsis
Binary fxdemo showcases every built-in effect in the widgets/fx package.
Binary fxdemo showcases every built-in effect in the widgets/fx package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL