import { ReactiveObject, ReactiveAdapter, getObservers, computed, partialReactive, } from "@cfcs/core"; import { isFunction } from "@daybrush/utils"; import Scene from "../Scene"; import SceneItem from "../SceneItem"; import { SceneOptions, SceneEvents, AnimatorState } from "../types"; import { isScene } from "../utils"; import { ANIMATOR_METHODS, getMethodNames, AnimatorReactiveState, ReactiveMethods } from "./reactive"; export const SCENE_METHODS = [ ...ANIMATOR_METHODS, ...getMethodNames(Scene), ]; /** * @typedef * @memberof Reactive */ export interface SceneReactiveOptions { options?: Partial; [key: string | number]: any; } /** * @typedef * @memberof Reactive */ export type SceneReactiveProps = SceneReactiveOptions | Scene | (() => SceneReactiveOptions | Scene); /** * @typedef * @memberof Reactive */ export interface SceneReactiveData { props?: SceneReactiveProps; options?: Partial; } export type SceneReactiveMethods = ReactiveMethods; export type SceneReactiveInstance = ReactiveObject & SceneReactiveMethods & { getInstance(): Scene; }; export const SCENE_REACTIVE: ReactiveAdapter< SceneReactiveInstance, AnimatorReactiveState, keyof SceneReactiveMethods, SceneReactiveData, SceneEvents > = { methods: SCENE_METHODS as Array, created(data: SceneReactiveData) { const dataProps = data.props; const dataObject = isFunction(dataProps) ? dataProps() : dataProps; const scene = isScene(dataObject) ? dataObject : new Scene(dataObject, { noRegisterElement: false, ...data.options, }); const obj = scene.state as any as ReactiveObject; const observers = getObservers(obj); const totalDuration = computed(() => { return scene.getTotalDuration(); }); const nextObj = { totalDuration, ...observers, ...SCENE_METHODS.reduce((methodObject, cur) => { methodObject[cur] = (...args) => { return scene[cur].call(scene, ...args); }; return methodObject; }, {}), getInstance() { return scene; }, }; const nextReactiveObject = partialReactive(nextObj) as SceneReactiveInstance; return nextReactiveObject; }, mounted(data, inst) { const scene = inst.getInstance(); const state = scene.state; const selector = state.selector; if (selector && !(state as any).__REACTIVE_MOUNTED__) { inst.setSelector(selector); (state as any).__REACTIVE_MOUNTED__ = true; inst.forEach(function mountFlag(child: Scene | SceneItem) { const childState = child.state; if (childState.selector) { (childState as any).__REACTIVE_MOUNTED__ = true; } if (isScene(child)) { child.forEach(mountFlag); } }); } }, on(inst, eventName, callback) { inst.on(eventName, callback); }, off(inst, eventName, callback) { inst.off(eventName, callback); }, destroy(inst) { const scene = inst.getInstance(); const state = scene.state; (state as any).__REACTIVE_MOUNTED__ = false; inst.forEach(function unmountFlag(child: Scene | SceneItem) { (child.state as any).__REACTIVE_MOUNTED__ = false; if (isScene(child)) { child.forEach(unmountFlag); } }); }, };