Packages
Multi-surface application runtime for Elixir. One TEA module renders to terminal, browser (LiveView), SSH, and MCP (agents). 30+ widgets, flexbox + CSS grid, AI agent runtime, distributed swarm with CRDTs, time-travel debugging, session recording, sandboxed REPL, and agentic commerce.
Current section
Files
Jump to
Current section
Files
lib/raxol/animation/adaptation.ex
defmodule Raxol.Animation.Adaptation do
@moduledoc """
Handles animation adaptation based on user preferences and accessibility settings.
This module is responsible for:
- Re-adapting animations when user preferences change
- Managing animation adaptation for accessibility
- Handling preference change notifications
"""
require Raxol.Core.Runtime.Log
alias Raxol.Animation.StateManager
alias Raxol.Animation.Accessibility, as: AnimAccessibility
alias Raxol.Animation.Lifecycle
@doc """
Re-adapt existing animations if settings have changed.
This function checks if user preferences have changed and re-adapts all active animations accordingly.
Returns a list of animations that were completed due to being disabled.
"""
def re_adapt_animations_if_needed(
user_preferences_pid,
active_animations \\ nil
) do
active_animations =
active_animations || StateManager.get_active_animations()
Raxol.Core.Runtime.Log.debug(
"[Animation] Re-adapting #{map_size(active_animations)} active animations"
)
# Fetch current preferences
current_reduced_motion =
Raxol.Core.UserPreferences.get(
[:accessibility, :reduced_motion],
user_preferences_pid
) || false
current_cognitive_accessibility =
Raxol.Core.UserPreferences.get(
[:accessibility, :cognitive_accessibility],
user_preferences_pid
) || false
# Update StateManager settings
settings = StateManager.get_settings()
new_settings = %{
settings
| reduced_motion: current_reduced_motion,
cognitive_accessibility: current_cognitive_accessibility
}
StateManager.init(new_settings)
# Now re-fetch settings for use below
settings = StateManager.get_settings()
reduce_motion? = Map.get(settings, :reduced_motion, false)
cognitive_accessibility? =
Map.get(settings, :cognitive_accessibility, false)
completed_due_to_disable =
Enum.flat_map(active_animations, fn {element_id, element_animations} ->
Enum.flat_map(element_animations, fn {animation_name, instance} ->
animation = instance.animation
# Re-adapt the animation
adapted_animation =
AnimAccessibility.adapt_animation(
animation,
reduce_motion?,
cognitive_accessibility?
)
# Update the instance with the adapted animation
updated_instance = Map.put(instance, :animation, adapted_animation)
# Handle disabled animations properly
if AnimAccessibility.disabled?(adapted_animation) do
# For disabled animations, mark as pending completion and ensure they complete quickly
updated_instance =
Map.put(updated_instance, :pending_completion, true)
# Immediately send completion message for disabled animations
Lifecycle.handle_animation_completion(
adapted_animation,
element_id,
animation_name,
updated_instance,
user_preferences_pid
)
# Return as completed due to disable
[{element_id, animation_name, updated_instance}]
else
# For enabled animations, remove pending_completion flag if it was set
_updated_instance =
Map.delete(updated_instance, :pending_completion)
# Not completed
[]
end
# Update the instance in the state manager
StateManager.put_active_animation(
element_id,
animation_name,
updated_instance
)
[]
end)
end)
completed_due_to_disable
end
@doc """
Check if animations should be reduced due to user preferences.
"""
def should_reduce_motion?(user_preferences_pid \\ nil) do
Raxol.Core.UserPreferences.get(
[:accessibility, :reduced_motion],
user_preferences_pid
) || false
end
@doc """
Check if cognitive accessibility should be applied.
"""
def should_apply_cognitive_accessibility? do
Raxol.Core.UserPreferences.get([:accessibility, :cognitive_accessibility]) ||
false
end
end