import type { HTMLAttributes } from 'react';
import type { AsyncProperty, LazyImport, LazyMarkType, PiTypeConfig } from '@piying/view-core';
/** 懒加载约定恒为 `() => Promise<组件类型>`, lazyMark 的包装形态一并解开 */
export type ResolveLazyComponent = T extends LazyImport ? R : T extends LazyMarkType ? R : never;
/**
* 组件 -> props。
*
* React 没有统一的「组件实例」概念, props 的落点有三种:
* 函数组件取首参, class 组件取实例的 props 字段, 懒加载先解开一层。
*/
type ComponentPropsOf = C extends LazyImport ? ComponentPropsOf : C extends LazyMarkType ? ComponentPropsOf : C extends (props: infer P, ...args: any[]) => any ? P : C extends abstract new (...args: any) => infer I ? ComponentPropsOf : C extends {
props: infer P;
} ? P : never;
type StringKey = Extract;
/** React 内置在 props 上的 key, 既不是业务 input 也不是业务 output */
type BuiltinPropKey = 'ref' | 'key';
/** `any` 会让 `X extends Fn` 恒真, 先把 any 挑出来单独处理 */
type IsAny = 0 extends 1 & T ? true : false;
/**
* 值为函数的 prop。
*
* React 侧 outputs 是以「prop 名原样」下发的(field-template 把 inputs/outputs/attributes
* 一起 spread 成 props), 所以函数 prop 就是 output, 不做 onXxx -> xxx 的重命名。
* 只按名字判断会把 `onClick?: string` 这类普通 prop 误判成事件, 所以再校验一次形态;
* `any` 形态必须排除, 否则 `value?: any` 会被当成 output。
*/
type FunctionPropKey = {
[K in StringKey]: IsAny extends true ? never : [NonNullable] extends [(...args: any[]) => any] ? K : never;
}[Exclude, BuiltinPropKey>];
/** 非函数 prop 的 key */
type InputPropKey = Exclude, BuiltinPropKey | FunctionPropKey>;
/**
* 保留真实参数元组的处理器形态。
* 直接写 `NonNullable` 的上界会落到 `{}`, 过不了 `Record` 约束。
*/
type HandlerOf = T extends (...args: infer A) => any ? (...args: A) => any : never;
/** 组件 input(非函数 prop) 名 -> 值类型 */
export type GetComponentInputs = {
[K in InputPropKey>]: ComponentPropsOf[K];
};
/** 组件 output(函数 prop) 名 -> 处理器签名 */
export type GetComponentEmits = {
[K in FunctionPropKey>]: HandlerOf[K]>;
};
export type GetComponentInputsOrigin = Partial>;
export type GetComponentInputsAsync = Partial<{
[K in keyof GetComponentInputs]: AsyncProperty[K]>;
}>;
export type GetComponentInputsKeys = keyof GetComponentInputs;
export type GetComponentOutputsOrigin = Partial>;
export type GetComponentOutputsAsync = Partial<{
[K in keyof GetComponentEmits]: AsyncProperty[K]>;
}>;
export type GetComponentOutputsKeys = keyof GetComponentEmits;
/**
* 非 Partial 形态的「output 名 -> 处理器签名」映射。
* 用于把 outputChange 的 list 逐位推成真实 emit 参数元组。
*/
export type GetComponentOutputsHandlerMap = GetComponentEmits;
/** 可作为「组件标识」传入的形态 */
export type ReactComponent = ((props: any) => React.ReactNode) | (abstract new (props: any) => any) | LazyImport;
/** 组件标识的完整集合: 额外放行 lazyMark 包装形态 */
export type ReactComponentKey = ReactComponent | LazyMarkType;
/**
* 由类型配置项解析出真正的组件类型。
*
* 解析不出组件时落到 never 而不是 any:
* `any` 会让后续 input/output 的 key 约束整体静默失效。
*/
export type ActionComponent = A['type'] extends ReactComponent ? A['type'] : [ResolveLazyComponent] extends [never] ? NonNullable[0]['__type'] : ResolveLazyComponent;
/**
* attributes 的标准名: 直接借 React 自带的 HTMLAttributes,
* 摘掉 `onXxx`(那是 events 的地盘, 不属于 attributes)。
*/
export type ReactStandardAttrName = Exclude, string>, `on${string}`>;
/** 标准名 ∪ 任意自定义名(data-* 与组件自有的透传属性等) */
export type ReactAttributeName = ReactStandardAttrName | (string & {});
export {};