/* * Copyright (c) 2025, Psychpsyo * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include namespace Web::ViewTransition { // https://drafts.csswg.org/css-view-transitions-1/#named-view-transition-pseudo class NamedViewTransitionPseudoElement : public DOM::PseudoElementTreeNode { GC_CELL(NamedViewTransitionPseudoElement, DOM::PseudoElementTreeNode); GC_DECLARE_ALLOCATOR(NamedViewTransitionPseudoElement); NamedViewTransitionPseudoElement(CSS::PseudoElement, FlyString); CSS::PseudoElement m_type; // Several of the view transition pseudo-elements are named view transition pseudo-elements, which are // functional tree-abiding view transition pseudo-elements associated with a view transition name. FlyString m_view_transition_name; }; // https://drafts.csswg.org/css-view-transitions-1/#::view-transition-old // https://drafts.csswg.org/css-view-transitions-1/#::view-transition-new class ReplacedNamedViewTransitionPseudoElement : public NamedViewTransitionPseudoElement { GC_CELL(ReplacedNamedViewTransitionPseudoElement, NamedViewTransitionPseudoElement); GC_DECLARE_ALLOCATOR(ReplacedNamedViewTransitionPseudoElement); ReplacedNamedViewTransitionPseudoElement(CSS::PseudoElement, FlyString, RefPtr); RefPtr m_content; }; // https://drafts.csswg.org/css-view-transitions-1/#captured-element struct CapturedElement : public JS::Cell { GC_CELL(CapturedElement, JS::Cell) GC_DECLARE_ALLOCATOR(CapturedElement); RefPtr old_image {}; CSSPixels old_width = 0; CSSPixels old_height = 0; // FIXME: Make this an identity transform function by default. CSS::Transformation old_transform = CSS::Transformation(CSS::TransformFunction::Translate, Vector()); Optional old_writing_mode {}; Optional old_direction {}; // FIXME: old_text_orientation Optional old_mix_blend_mode {}; CSS::Filter old_backdrop_filter {}; Optional old_color_scheme {}; GC::Ptr new_element {}; GC::Ptr group_keyframes {}; GC::Ptr group_animation_name_rule {}; GC::Ptr group_styles_rule {}; GC::Ptr image_pair_isolation_rule {}; GC::Ptr image_animation_name_rule {}; private: virtual void visit_edges(JS::Cell::Visitor&) override; }; // https://drafts.csswg.org/css-view-transitions-1/#callbackdef-viewtransitionupdatecallback using ViewTransitionUpdateCallback = GC::Ptr; class ViewTransition final : public Bindings::PlatformObject { WEB_PLATFORM_OBJECT(ViewTransition, Bindings::PlatformObject); GC_DECLARE_ALLOCATOR(ViewTransition); public: static GC::Ref create(JS::Realm&); virtual ~ViewTransition() override = default; // https://drafts.csswg.org/css-view-transitions-1/#dom-viewtransition-updatecallbackdone GC::Ref update_callback_done() const { return m_update_callback_done_promise; } // https://drafts.csswg.org/css-view-transitions-1/#dom-viewtransition-ready GC::Ref ready() const { return m_ready_promise; } // https://drafts.csswg.org/css-view-transitions-1/#dom-viewtransition-finished GC::Ref finished() const { return m_finished_promise; } // https://drafts.csswg.org/css-view-transitions-1/#dom-viewtransition-skiptransition void skip_transition(); // https://drafts.csswg.org/css-view-transitions-1/#setup-view-transition void setup_view_transition(); // https://drafts.csswg.org/css-view-transitions-1/#activate-view-transition void activate_view_transition(); // https://drafts.csswg.org/css-view-transitions-1/#capture-the-old-state ErrorOr capture_the_old_state(); // https://drafts.csswg.org/css-view-transitions-1/#capture-the-new-state ErrorOr capture_the_new_state(); // https://drafts.csswg.org/css-view-transitions-1/#setup-transition-pseudo-elements void setup_transition_pseudo_elements(); // https://drafts.csswg.org/css-view-transitions-1/#call-the-update-callback void call_the_update_callback(); // https://drafts.csswg.org/css-view-transitions-1/#schedule-the-update-callback void schedule_the_update_callback(); // https://drafts.csswg.org/css-view-transitions-1/#skip-the-view-transition void skip_the_view_transition(JS::Value reason); // https://drafts.csswg.org/css-view-transitions-1/#handle-transition-frame void handle_transition_frame(); // https://drafts.csswg.org/css-view-transitions-1/#update-pseudo-element-styles ErrorOr update_pseudo_element_styles(); // https://drafts.csswg.org/css-view-transitions-1/#clear-view-transition void clear_view_transition(); // https://drafts.csswg.org/css-view-transitions-1/#viewtransition-phase enum class Phase : u8 { PendingCapture, UpdateCallbackCalled, Animating, Done, }; Phase phase() const { return m_phase; } void set_update_callback(ViewTransitionUpdateCallback callback) { m_update_callback = callback; } private: ViewTransition(JS::Realm&, GC::Ref, GC::Ref, GC::Ref); virtual void initialize(JS::Realm&) override; virtual void visit_edges(JS::Cell::Visitor&) override; // https://drafts.csswg.org/css-view-transitions-1/#viewtransition-named-elements HashMap> m_named_elements = {}; // https://drafts.csswg.org/css-view-transitions-1/#viewtransition-phase Phase m_phase = Phase::PendingCapture; // https://drafts.csswg.org/css-view-transitions-1/#viewtransition-update-callback ViewTransitionUpdateCallback m_update_callback = {}; // https://drafts.csswg.org/css-view-transitions-1/#viewtransition-ready-promise GC::Ref m_ready_promise; // https://drafts.csswg.org/css-view-transitions-1/#viewtransition-update-callback-done-promise GC::Ref m_update_callback_done_promise; // https://drafts.csswg.org/css-view-transitions-1/#viewtransition-finished-promise GC::Ref m_finished_promise; // https://drafts.csswg.org/css-view-transitions-1/#viewtransition-transition-root-pseudo-element GC::Ref m_transition_root_pseudo_element; // https://drafts.csswg.org/css-view-transitions-1/#viewtransition-initial-snapshot-containing-block-size Optional m_initial_snapshot_containing_block_size; }; }