Module: Charming::UI::Gradient

Defined in:
lib/charming/presentation/ui/gradient.rb

Overview

Gradient interpolates between two hex colors: blend a single point, build an evenly spaced ramp, or paint text with a per-character color sweep.

Class Method Summary collapse

Class Method Details

.blend(start_hex, end_hex, amount) ⇒ Object

Blends start_hex and end_hex ("#rrggbb") at fractional amount (0.0 → start, 1.0 → end), returning a "#rrggbb" string.



12
13
14
15
16
17
# File 'lib/charming/presentation/ui/gradient.rb', line 12

def blend(start_hex, end_hex, amount)
  mixed = rgb(start_hex).zip(rgb(end_hex)).map do |from, to|
    (from + ((to - from) * amount)).round
  end
  format("#%02x%02x%02x", *mixed)
end

.colorize(text, from:, to:) ⇒ Object

Paints each grapheme cluster of plain-text text with a foreground color swept from from to to across its visible characters.



29
30
31
32
33
34
35
36
# File 'lib/charming/presentation/ui/gradient.rb', line 29

def colorize(text, from:, to:)
  clusters = text.to_s.scan(Width::GRAPHEME)
  span = [clusters.length - 1, 1].max

  clusters.each_with_index.map do |cluster, index|
    Style.new(foreground: blend(from, to, index.to_f / span)).render(cluster)
  end.join
end

.rgb(hex) ⇒ Object

Decomposes "#rrggbb" into [r, g, b] integers.

Raises:

  • (ArgumentError)


39
40
41
42
43
44
# File 'lib/charming/presentation/ui/gradient.rb', line 39

def rgb(hex)
  value = hex.to_s.delete_prefix("#")
  raise ArgumentError, "gradient colors must be #rrggbb" unless value.match?(/\A[0-9a-fA-F]{6}\z/)

  [value[0..1], value[2..3], value[4..5]].map { |part| part.to_i(16) }
end

.steps(start_hex, end_hex, count) ⇒ Object

An evenly spaced ramp of count colors from start_hex to end_hex, endpoints included.



21
22
23
24
25
# File 'lib/charming/presentation/ui/gradient.rb', line 21

def steps(start_hex, end_hex, count)
  return [blend(start_hex, end_hex, 0.0)] if count <= 1

  Array.new(count) { |index| blend(start_hex, end_hex, index.to_f / (count - 1)) }
end