/// <reference types="@rbxts/types" />
import { Signal } from "@rbxts/beacon";
export interface ComponentConfig {
    /**
     * CollectionService tag.
     */
    tag?: string;
    /**
     * Descendant whitelist. Component will only be active
     * if it is a descendant of one of the instances in
     * this list.
     */
    whitelistDescendants?: Instance[];
    /**
     * Descendant blacklist. Component will only be
     * active if it is _not_ a descendant of any of the
     * instances in this list.
     */
    blacklistDescendants?: Instance[];
}
/**
 * Base class for components. All components should
 * extend from this class.
 *
 * ```ts
 * class MyComponent extends BaseComponent<BasePart> {
 * 	onStart() {}
 * 	onStop() {}
 * }
 * ```
 */
export declare abstract class BaseComponent<I extends Instance = Instance> {
    /**
     * Attached instance.
     */
    instance: I;
    /**
     * CollectionService tag.
     */
    tag: string;
    /**
     * Called when the instance is started. This can be called multiple
     * times within the lifetime of the class instance. However, it is
     * guaranteed that `onStop()` will be called in-between calls.
     */
    abstract onStart(): void;
    /**
     * Called when the instance is stopped. This can be called multiple
     * times within the lifetime of the class instance. Therefore, it is
     * important that this method is idempotent.
     */
    abstract onStop(): void;
}
/**
 * Component decorator.
 * @param config Component configuration
 */
export declare function Component(config: ComponentConfig): <B extends new () => BaseComponent>(componentClass: B) => void;
/**
 * Get a component attached to the given instance. Returns
 * `undefined` if nothing is found.
 *
 * ```ts
 * const component = getComponent(MyComponent, someInstance);
 * ```
 *
 * @param componentClass Component class
 * @param instance Roblox instance
 * @returns Component or undefined
 */
export declare function getComponent<I extends C["instance"], C extends BaseComponent>(componentClass: new () => C, instance: I): C | undefined;
/**
 * Get all component instances for a given component class.
 * @param componentClass Component class
 * @returns Component instances
 */
export declare function getAllComponents<C extends BaseComponent>(componentClass: new () => C): C[];
/**
 * Get a signal for the given component class that will be fired any time
 * a new component instance for the given class is started.
 *
 * ```ts
 * getComponentStartedSignal(MyComponent).Connect((myComponent) => {});
 * ```
 *
 * @param componentClass Component class
 * @returns Signal
 */
export declare function getComponentStartedSignal<C extends BaseComponent>(componentClass: new () => C): Signal<[component: C]>;
/**
 * Get a signal for the given component class that will be fired any time
 * a new component instance for the given class is stopped.
 *
 * ```ts
 * getComponentStoppedSignal(MyComponent).Connect((myComponent) => {});
 * ```
 *
 * @param componentClass Component class
 * @returns Signal
 */
export declare function getComponentStoppedSignal<C extends BaseComponent>(componentClass: new () => C): Signal<[component: C]>;
/**
 * Observe each component instance during its lifetime. The `observer` function
 * will be called for each component instance that starts. The observer should
 * return a cleanup function, which will then be called when the component stops.
 *
 * A root cleanup function is returned from this function too, which will stop
 * all observations and call all current cleanup functions from your observer.
 *
 * ```ts
 * const stopObserving = observeComponent(MyComponent, (myComponent) => {
 * 	print("myComponent instance started");
 * 	return () => {
 * 		print("myComponent instance stopped");
 * 	};
 * });
 *
 * // If observations should stop, call the returned cleanup function:
 * stopObserving();
 * ```
 *
 * @param componentClass Component class
 * @param observer Observer function
 * @returns Root cleanup
 */
export declare function observeComponent<C extends BaseComponent>(componentClass: new () => C, observer: (component: C) => () => void): () => void;
/**
 * Add a component manually (bypass CollectionService).
 * @param componentClass Component class
 * @param instance Instance
 */
export declare function addComponent<I extends C["instance"], C extends BaseComponent>(componentClass: new () => C, instance: I): C;
/**
 * Remove a component manually.
 * @param componentClass Component class
 * @param instance Instance
 */
export declare function removeComponent<I extends C["instance"], C extends BaseComponent>(componentClass: new () => C, instance: I): void;
