Class: Unmagic::Color::Units::Degrees::Direction

Inherits:
Object
  • Object
show all
Defined in:
lib/unmagic/color/units/direction.rb

Overview

Represents a gradient direction as a from/to tuple of Degrees.

Direction defines a gradient’s angle by specifying where it starts (from) and where it ends (to). Supports CSS-style direction strings with flexible parsing that infers missing components.

## Supported Formats

  • Full directions: ‘“from left to right”`, `“from bottom left to top right”`

  • Implicit from: ‘“to top”` → infers `“from bottom to top”`

  • Implicit to: ‘“from bottom”` → infers `“from bottom to top”`

  • Without “from”: ‘“left to right”` → `“from left to right”`

  • Mixed formats: ‘“from 45deg to top right”`, `“from south to 90deg”`, `“from 45° to 90°”`

  • Hash: ‘{ from: “north”, to: “south” }`

Examples:

Parse direction strings

Direction.parse("from left to right")
Direction.parse("to top")                    # Infers from bottom
Direction.parse("from bottom")               # Infers to top
Direction.parse("left to right")             # Implicit "from"
Direction.parse("from 45deg to 90deg")       # Numeric degrees
Direction.parse("from 45° to 90°")           # With ° symbol
Direction.parse("from south to top right")   # Mixed

Build from various inputs

Direction.build("from left to right")
Direction.build(from: "north", to: "south")
Direction.build(from: 45, to: 90)

Direct construction

direction = Direction.new(from: Degrees::LEFT, to: Degrees::RIGHT)
direction.from.value  #=> 270.0
direction.to.value    #=> 90.0

Constants

Direction::LEFT_TO_RIGHT
Direction::BOTTOM_LEFT_TO_TOP_RIGHT

String output

Direction::LEFT_TO_RIGHT.to_s    #=> "from left to right"
Direction::LEFT_TO_RIGHT.to_css  #=> "from left to right"

Constant Summary collapse

BOTTOM_TO_TOP =

Predefined direction constants

new(from: Degrees::BOTTOM, to: Degrees::TOP).freeze
LEFT_TO_RIGHT =

Left to right direction (horizontal)

new(from: Degrees::LEFT, to: Degrees::RIGHT).freeze
TOP_TO_BOTTOM =

Top to bottom direction (vertical, default)

new(from: Degrees::TOP, to: Degrees::BOTTOM).freeze
RIGHT_TO_LEFT =

Right to left direction (horizontal)

new(from: Degrees::RIGHT, to: Degrees::LEFT).freeze
BOTTOM_LEFT_TO_TOP_RIGHT =

Bottom-left to top-right diagonal direction

new(from: Degrees::BOTTOM_LEFT, to: Degrees::TOP_RIGHT).freeze
TOP_LEFT_TO_BOTTOM_RIGHT =

Top-left to bottom-right diagonal direction

new(from: Degrees::TOP_LEFT, to: Degrees::BOTTOM_RIGHT).freeze
TOP_RIGHT_TO_BOTTOM_LEFT =

Top-right to bottom-left diagonal direction

new(from: Degrees::TOP_RIGHT, to: Degrees::BOTTOM_LEFT).freeze
BOTTOM_RIGHT_TO_TOP_LEFT =

Bottom-right to top-left diagonal direction

new(from: Degrees::BOTTOM_RIGHT, to: Degrees::TOP_LEFT).freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(from:, to:) ⇒ Direction

Create a new Direction instance.

Parameters:



155
156
157
158
# File 'lib/unmagic/color/units/direction.rb', line 155

def initialize(from:, to:)
  @from = from
  @to = to
end

Instance Attribute Details

#fromObject (readonly)

Returns the value of attribute from.



51
52
53
# File 'lib/unmagic/color/units/direction.rb', line 51

def from
  @from
end

#toObject (readonly)

Returns the value of attribute to.



51
52
53
# File 'lib/unmagic/color/units/direction.rb', line 51

def to
  @to
end

Class Method Details

.allArray<Direction>

All predefined direction constants

Returns:

  • (Array<Direction>)

    All constant directions



57
58
59
# File 'lib/unmagic/color/units/direction.rb', line 57

def all
  all_constants
end

.build(input) ⇒ Direction

Build a Direction from various input formats.

Parameters:

  • input (String, Direction, Hash)

    Direction string, instance, or hash with :from and :to keys

Returns:



98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/unmagic/color/units/direction.rb', line 98

def build(input)
  return input if input.is_a?(Direction)

  if input.is_a?(::Hash)
    raise Degrees::ParseError, "Hash must have :from and :to keys" unless input.key?(:from) && input.key?(:to)

    from_degree = Degrees.build(input[:from])
    to_degree = Degrees.build(input[:to])
    return new(from: from_degree, to: to_degree)
  end

  parse(input)
end

.matches?(input) ⇒ Boolean

Check if a string looks like a direction keyword.

Parameters:

  • input (String)

    The string to check

Returns:

  • (Boolean)

    true if the string appears to be a direction keyword



85
86
87
88
89
90
91
92
# File 'lib/unmagic/color/units/direction.rb', line 85

def matches?(input)
  return false unless input.is_a?(::String)

  normalized = input.strip.downcase

  # Check if it contains "from" or "to" keywords
  normalized.start_with?("to ") || normalized.start_with?("from ") || normalized.include?(" to ")
end

.parse(input) ⇒ Direction

Parse a direction string into a Direction instance.

Supports mixed formats like:

  • “from 275deg to 45deg”

  • “from south to 90”

  • “from north to top right”

  • “to top” (infers from as opposite)

  • “from bottom” (infers to as opposite)

Parameters:

  • input (String)

    Direction string

Returns:

Raises:



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/unmagic/color/units/direction.rb', line 124

def parse(input)
  # Normalize: strip, downcase, and collapse whitespace
  normalized = input.strip.downcase.gsub(/\s+/, " ")

  # Remove "from " prefix if present, then split on "to "
  parts = normalized.delete_prefix("from ").split("to ", 2).map(&:strip)
  left = parts[0]
  right = parts[1]

  if left.empty? && right
    # Only right side specified: "to top"
    to_degree = Degrees.build(right)
    from_degree = to_degree.opposite
  elsif right.nil?
    # Only left side specified: "from bottom"
    from_degree = Degrees.build(left)
    to_degree = from_degree.opposite
  else
    # Both sides specified: "left to right" or "from left to right"
    from_degree = Degrees.build(left)
    to_degree = Degrees.build(right)
  end

  new(from: from_degree, to: to_degree)
end

Instance Method Details

#==(other) ⇒ Boolean

Check equality.

Parameters:

  • other (Object)

    Value to compare

Returns:

  • (Boolean)

    true if from and to are equal



182
183
184
# File 'lib/unmagic/color/units/direction.rb', line 182

def ==(other)
  other.is_a?(Direction) && @from == other.from && @to == other.to
end

#to_cssString

Convert to CSS string format.

Returns:

  • (String)

    CSS direction string (e.g., “from left to right”)



163
164
165
166
167
# File 'lib/unmagic/color/units/direction.rb', line 163

def to_css
  from_str = @from.name || @from.to_css
  to_str = @to.name || @to.to_css
  "from #{from_str} to #{to_str}"
end

#to_sString

Convert to string representation.

Returns:

  • (String)

    Canonical string format that can be parsed back



172
173
174
175
176
# File 'lib/unmagic/color/units/direction.rb', line 172

def to_s
  from_str = @from.name || @from.to_s
  to_str = @to.name || @to.to_s
  "from #{from_str} to #{to_str}"
end