import type { ComponentData } from "../../component-parser"; import type { PropertyEditorProps } from "../property-editors"; import React from "react"; import "./component-editor.scss"; import { PropertyEditorWrapperContext } from "./property-editor-wrapper"; import { PropertyEditors } from "../property-editors"; export type TComponentData = ComponentData & { props: T; }; /** 判断值是否为组件数据形态:同时具备 type 与 props 字段,且 props 为对象 */ export declare function isComponentData(value: unknown): value is ComponentData; /** 取属性容器:组件数据形态取 props,普通对象形态取对象自身 */ export declare function propsOf(value?: V): V | undefined; /** 属性编辑器条目:编辑器元素(当前形态)或旧的配置对象 `{ editor, label, description... }`(存量兼容) */ export type PropertyEditorEntry = React.ReactElement>; export interface Props extends PropertyEditorProps { value?: V; onChange?: (value?: V) => void; onInnerClick?: (e: React.MouseEvent) => void; /** * 编辑器配置:除子类以 static 属性声明外,也允许直接以 * `` 的形式传入(如 ObjectEditor 的 editors), * 便于把配置对象当作 React 元素使用。 */ propertyEditors?: PropertyEditors & { hidden?: React.ReactElement>; }; /** 属性过滤器 */ propertyFilter?: string; /** * 隐藏属性行工具栏(false/对象 开关 + 展开抽屉按钮)。 * 用于「组合式复用」场景:外层编辑器(如 DataSourceEditor)内嵌 ObjectEditor 渲染属性行时, * 由外层统一提供工具栏,内层不再抢占,避免抽屉内容与开关行为错乱。 */ hideToolBar?: boolean; /** 内置显示模式下显示的属性 */ innerProperites?: string[]; } /** 别名:与 barrel 的 `ComponentEditorProps` 保持一致,便于本目录下文件直接从此模块导入(避免循环依赖) */ export type { Props as ComponentEditorProps }; export interface State { /** * 当前值。普通对象编辑器允许 false(开关关闭)与 undefined(未设置), * 故此处类型包含 false;组件编辑器实际只会用到 V | undefined。 */ value?: V; /** 分组折叠状态:分组名 → 是否已折叠 */ collapsed?: Record; } export interface Helper { showDetailEditor(componentId: string): void; } /** * 组件编辑器基类:子类以 static 属性声明 propertyEditors(参考 node-shop-v2 的 HeroBannerEditor 写法), * 由基类负责渲染属性编辑行(支持分组、内嵌模式、子组件跳转)。 */ export declare abstract class ComposeEditor = Props, S extends State = State> extends React.Component { /** 子类的编辑器配置(static):属性名 → 属性编辑器元素(与 props 同型,便于子类以 `ComponentEditorProps["propertyEditors"]` 声明) */ static propertyEditors?: PropertyEditors; /** 组件类型名(元信息,供注册表/调试使用) */ targetType?: string; /** 属性行工具栏上下文:子类通过 setToolBar 在属性行标签区注入开关/展开按钮 */ static contextType: React.Context; context: React.ContextType; constructor(props: T); /** * 当前显示模式:displayMode 优先,兼容已废弃的 mode 字段,缺省为 normal。 * * 注意:不能把归一化结果写回 props——React 在开发模式下会冻结 props 对象, * 赋值将抛 "Cannot add property displayMode, object is not extensible"。 * 因此统一通过本 getter 读取,子类请勿直接访问 `this.props.displayMode`。 */ protected get displayMode(): "inner" | "normal"; /** * 取编辑器配置,来源优先级:props(`` 形态) * → 子类 static(注册表形态)。 * * 与「直接渲染注册表中的编辑器元素」语义保持一致:外部显式传入的配置覆盖类上的默认配置 * (与旧实现 static 优先相反,旧顺序会让 cloneElement 注入的配置失效)。 */ protected get propertyEditors(): Record>>; componentDidMount(): void; /** * 在属性行标签区注入工具栏:右侧的「false/对象 开关」(关闭时取值为 undefined)+「展开到抽屉」按钮。 * 仅在编辑器处于 PropertyEditorWrapper 提供的工具栏上下文中生效(否则 this.context 为 undefined,静默跳过)。 * 子类可通过重写 setToolBar / openDrawer 自定义工具栏内容与抽屉行为(如 ObjectEditor 的 hideSwitch 抽屉)。 */ protected setToolBar(): void; /** 打开 popup 抽屉:以当前值创建同类型编辑器实例(displayMode=normal)并弹窗编辑 */ protected openDrawer: () => void; /** * 把 propertyEditors 中声明了 defaultValue、而组件数据里尚无值的属性回写到组件数据。 * 旧实现由 PropertyEditorContainer 在挂载时完成,现由基类统一处理。 */ private applyDefaultValues; /** 分组折叠切换 */ protected toggleGroup: (name: string) => void; abstract changeProperty(propertyName: string, newValue: any): void; renderInnerEditor(value?: V): React.JSX.Element | null; renderNormalEditor(value?: V): React.ReactNode; /** * 渲染单个属性行。editor 为属性编辑器元素,标签/描述/分组/默认值取自元素 props *(如 ``)。 */ protected renderProperty(propertyName: string, editor: React.ReactElement>, props?: V): React.ReactNode; render(): string | number | boolean | Iterable | React.JSX.Element | null | undefined; }