import { type Component, type ComponentOptions, type ComponentPublicInstance, type ComputedRef, type Prop, type PropType, type Ref, type RendererElement, type RendererNode, type Slots, type VNode, type WritableComputedOptions } from 'vue';
import type { AbstractConstructor, KeysMatching, StringEnumLike, StringEnumValue, Thing } from './mapped-types';
/** 组件选项中的hook名 */
export type VueHookName = ExcludeSubtype<KeysMatching<OmitStartsWith<RemoveIndex<ComponentOptions>, '_'>, {
    (): void;
} | undefined>, 'serverPrefetch' | 'emits' | 'computed' | 'extends' | 'methods' | 'call' | undefined>;
export type VueHookFunction = (this: ComponentPublicInstance) => void;
/**
 * 模仿Vue的计算属性的写法
 * @see ComputedOptions
 */
export type Property<T> = T | {
    (): T;
} | {
    get(): T;
    set?(value: T): void;
};
/**
 * ## Vue2
 * 和typed()联合使用, 写成: `props: typed<Props<Options>>({...})`, 可以将`Options`作为属性的类型声明,
 * ### 注意
 * 1. 对于`Options`中可选的属性, 漏了VSCode不会报错...要小心
 * 2. `...`中理论上来说只要写Vue的纯js式的类型验证信息(Boolean/Number/String/Object/...)就行了, 并且还有ts的类型检查
 * 3. 对于`Options`中可选的`boolean`属性, 若将类型验证信息写为`Boolean`时, 该属性的默认值并不是`undefined`而是`false`, 这和它的类型声明(`boolean | undefined`)不匹配, 推荐写成`optionalProp(Boolean)`
 * 4. 因为存在上述特殊情况, 推荐使用{@link requiredProp},{@link optionalProp}等快捷方法写类型验证信息, 方法的传入参数直接写Vue的纯js式的类型验证信息, 就行了
 *
 * ## Vue3
 * 需要用`props: {...} satisfies Props<Options>`替代`typed()`, 防止{@link NotNullProp}被Vue看成必选的属性
 * */
export type Props<T> = {
    [K in keyof T]-?: T[K] extends {} ? NotNullProp<T[K]> : Prop<Exclude<T[K], undefined>>;
};
/** 表示一个非空的Prop, `required`为true 或者 设置了`default`的{@link Prop}, 才是非空的Prop */
type NotNullProp<T = any, D = T> = {
    type: PropType<T>;
} & ({
    required: true;
} | {
    default: D | (() => D);
});
export declare function stringEnumProp<E extends StringEnumLike>(enumObject: E, defaultValue: E[keyof E]): {
    type: PropType<StringEnumValue<E>>;
    default: E[keyof E];
};
export declare function stringEnumProp<E extends StringEnumLike>(enumObject: E): {
    type: PropType<StringEnumValue<E>>;
};
export declare function stringUnionPropFromValues<T extends string>(values: readonly T[], defaultValue: T): {
    type: PropType<T[][number]>;
    default: T;
};
export declare function stringUnionPropFromValues<T extends string>(values: readonly T[]): {
    type: PropType<T[][number]>;
};
export declare function requiredProp<T>(type: PropType<T>): {
    type: PropType<T>;
    required: true;
};
export declare function optionalProp<T>(type: PropType<T>, defaultValue: T | (() => T)): {
    type: PropType<T>;
    default: T;
};
export declare function optionalProp<T>(type: PropType<T>): {
    type: PropType<T>;
};
/**
 * 保存在this上的属性
 * @param defaultValues 属性的默认值
 *
 * @deprecated Vue3中已经不支持`cache: false`的计算属性, 使用setup中返回普通的值替代
 */
export declare function computedSaveOnThis<T>(defaultValues: {
    [K in keyof T]: T[K];
}): {
    [K in keyof T]: WritableComputedOptions<T[K]>;
};
/**
 * 模仿Vue的计算属性的写法, 将方法转换成属性
 * @deprecated 在Vue2时用来将provide的方法转换成属性, 方便使用, Vue3中不生效, 故废弃
 */
export declare function createPropertyObject(obj: any): any;
/**
 * 相比{@link createPropertyObject}增加类型信息
 * @see createPropertyObject
 * @deprecated Vue3中没用
 * */
export declare function createPropertyObjectTyped<T>(obj: {
    [K in keyof T]: Property<T[K]>;
}): T;
/**
 * 创建空节点
 *
 * Vue2中使用`this._e()`创建空节点: https://github.com/vuejs/vue/blob/b6247fc9d7442c50d60ccf366a7cb183a4d02129/src/core/instance/render-helpers/index.js#L28
 *
 * Vue3中等价的实现是{@link createCommentVNode}: https://github.com/vuejs/core/blob/650f5c26f464505d9e865bdb0eafb24350859528/packages/runtime-core/src/compat/instance.ts#L162
 */
export declare function createEmptyVNode(): VNode;
/**
 * @see https://github.com/vuejs/vue/blob/43b98fe25151b0b6bacd36f3ee27c5d61add5fdb/packages/weex-vue-framework/factory.js/#L2906
 * */
export declare function callHook(vm: ComponentPublicInstance, hookName: VueHookName): void;
/**
 * {@link import('./mapped-types.ts').safeAsComponent}
 * @deprecated Vue3已经不能遍历子组件的实例了, 所以这个方法目前没用
 */
export declare function findByComponentType<T extends Component & AbstractConstructor>(arr: ComponentPublicInstance[], component: T): InstanceType<T> | undefined;
/**
 * 通过构造slots内容的方式, 提取出slots中对应{@link component}的VNode, {@link VNode.props}就是当前给组件设置的属性值
 *
 * 注意, 该方法并无法获取到{@link component}的实例
 *
 * @see https://stackoverflow.com/questions/64154002/vue-3-how-to-get-information-about-children
 */
export declare function extractVNodeFromSlotsByComponent<Props>(slots: Slots, component: ComponentOptions<Props>): VNode<RendererNode, RendererElement, Props> | undefined;
/**
 * Vue3中 class/style/未声明的事件/未声明的属性 都会集合到`this.$attrs`中
 * 默认情况下(`inheritAttrs`为true), 将被透传给组件的根节点
 *
 * 而Vue2, `this.$attrs`值包含 未声明的属性, 所有事件放到了`this.$listeners`中
 *
 * 这里模仿Vue2的行为, 从{@link attrs}中拆分出未声明的事件, 方便将他们透传给地图的对象
 * 同时若传入{@link props}, 也会从它里面拆分出 声明的事件类型的属性
 *
 * ## 如何给事件添加类型信息
 *
 * - 声明在`emits`中的事件, 会给emit方法添加类型信息, 但没办法在运行时判断是否有被设置
 * - 声明在`props`中的事件, 不会.................. , 但可以通过读取`this.$props`判断是否被设置
 *
 * 所有我们最终选择用{@link EventProps}在`props`中声明事件, 同时用{@link EventEmits}在`emits`上声明事件的类型,
 * 达到既有类型信息, 又能判断是否存在的效果, 写法如下:
 * ```
 * {
 *   props: {...} satisfies EventProps<TgMapEmits>,
 *   emits: undefined as any as EventEmits<TgMapEmits>,
 * }
 * ```
 *
 * ## 参考
 * - https://cn.vuejs.org/guide/components/attrs.html#disabling-attribute-inheritance
 * - https://v3-migration.vuejs.org/zh/breaking-changes/listeners-removed.html
 * - https://eslint.vuejs.org/rules/require-explicit-emits.html#options
 */
export declare function splitAttrs(attrs: Record<string, unknown>, props?: Record<string, unknown>): {
    /** class/style/未声明的属性 等 */
    binds: Record<string, unknown>;
    /** 未声明的事件 */
    listeners: Record<string, unknown>;
    /** 声明在`props`中的事件 */
    listenerProps: Record<string, unknown>;
};
/** 响应式的{@link splitAttrs} */
export declare function useSplittedAttrs(attrs: Record<string, unknown>, props?: Record<string, unknown>): ComputedRef<{
    /** class/style/未声明的属性 等 */
    binds: Record<string, unknown>;
    /** 未声明的事件 */
    listeners: Record<string, unknown>;
    /** 声明在`props`中的事件 */
    listenerProps: Record<string, unknown>;
}>;
export type EventCallback<E = any> = (event: E) => void;
/**
 * 事件类型的属性
 * @see splitAttrs
 * */
export type EventProps<Emits> = Emits extends string ? {
    [K in Emits as `on${Capitalize<K>}`]: Prop<Function>;
} : {
    [K in keyof Emits as K extends string ? `on${Capitalize<K>}` : never]: Prop<EventCallback<Emits[K]>>;
};
/**
 * 用来声明事件的类型信息
 * @see splitAttrs
 *  */
export type EventEmits<T> = {
    [K in keyof T]: (event: T[K]) => boolean;
};
/** 给事件类型的属性标注类型 */
export declare function eventProp<E = any>(): Prop<EventCallback<E>>;
export declare const useEventLogMethods: () => {
    eventLog: (event: Thing | null | undefined) => void;
    eventLogLess: (this: any, event: Thing | null | undefined) => void;
};
/**
 * 值可能是Ref的对象
 * 可以用来给{@link reactive}的参数做类型约束
 * */
export type MaybeWrapRefs<T> = {
    [P in keyof T]: Ref<T[P]> | T[P] | ComputedRef<T[P]>;
};
export {};
