/* * Copyright (c) 2023-2024, Matthew Olsson * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include namespace Web::Animations { using EasingValue = Variant>; // https://www.w3.org/TR/web-animations-1/#the-keyframeeffectoptions-dictionary struct KeyframeEffectOptions : public EffectTiming { Bindings::CompositeOperation composite { Bindings::CompositeOperation::Replace }; Optional pseudo_element {}; }; // https://www.w3.org/TR/web-animations-1/#dictdef-basepropertyindexedkeyframe // Note: This is an intermediate structure used only when parsing Keyframes provided by the caller in a slightly // different format. It is converted to BaseKeyframe, which is why it doesn't need to store the parsed properties struct BasePropertyIndexedKeyframe { Variant, Vector>> offset { Vector> {} }; Variant> easing { Vector {} }; Variant> composite { Vector {} }; HashMap> properties {}; }; // https://www.w3.org/TR/web-animations-1/#dictdef-basekeyframe struct BaseKeyframe { using UnparsedProperties = HashMap; using ParsedProperties = HashMap>; Optional offset {}; EasingValue easing { "linear"_string }; Bindings::CompositeOperationOrAuto composite { Bindings::CompositeOperationOrAuto::Auto }; Optional computed_offset {}; Variant properties { UnparsedProperties {} }; UnparsedProperties& unparsed_properties() { return properties.get(); } ParsedProperties& parsed_properties() { return properties.get(); } }; // https://www.w3.org/TR/web-animations-1/#the-keyframeeffect-interface class KeyframeEffect : public AnimationEffect { WEB_PLATFORM_OBJECT(KeyframeEffect, AnimationEffect); JS_DECLARE_ALLOCATOR(KeyframeEffect); public: static JS::NonnullGCPtr create(JS::Realm&); static WebIDL::ExceptionOr> construct_impl( JS::Realm&, JS::Handle const& target, Optional> const& keyframes, Variant options = KeyframeEffectOptions {}); static WebIDL::ExceptionOr> construct_impl(JS::Realm&, JS::NonnullGCPtr source); DOM::Element* target() const override { return m_target_element; } void set_target(DOM::Element* target) { m_target_element = target; } Optional pseudo_element() const { return m_target_pseudo_selector; } void set_pseudo_element(Optional); Bindings::CompositeOperation composite() const { return m_composite; } void set_composite(Bindings::CompositeOperation value) { m_composite = value; } WebIDL::ExceptionOr> get_keyframes(); WebIDL::ExceptionOr set_keyframes(Optional> const&); private: KeyframeEffect(JS::Realm&); virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; // https://www.w3.org/TR/web-animations-1/#effect-target-target-element JS::GCPtr m_target_element {}; // https://www.w3.org/TR/web-animations-1/#dom-keyframeeffect-pseudoelement Optional m_target_pseudo_selector {}; // https://www.w3.org/TR/web-animations-1/#dom-keyframeeffect-composite Bindings::CompositeOperation m_composite { Bindings::CompositeOperation::Replace }; // https://www.w3.org/TR/web-animations-1/#keyframe Vector m_keyframes {}; // A cached version of m_keyframes suitable for returning from get_keyframes() Vector m_keyframe_objects {}; }; }