Skip to content

[vtable-editors] 关于自定义编辑器的接口定义 #1005

@martesi

Description

@martesi

IEditor

IEditor 定义如下:

export interface IEditor {
    editorType?: string;
    editorConfig: any;
    container: HTMLElement;
    successCallback?: Function;
    getValue: () => string | number | null;
    beginEditing: (container: HTMLElement, referencePosition: {
        rect: RectProps;
        placement?: Placement;
    }, value?: string) => void;
    exit: () => void;
    targetIsOnEditor: (target: HTMLElement) => boolean;
    bindSuccessCallback?: (callback: Function) => void;
}

非必要的定义

editorConfig, container 被定义为必选字段,而在实现中,这些内容并不提供给 VTable 使用(container 由 VTable 提供,但实际使用仍然是作为与 element 一样的环境变量)。

考虑到开发者自定义开发时不一定会以官方相同的方式来做传参定义,也许这两个参数定义应该从 IEditor 上移除。

// 一个基于 antd 的输入框
export default class EditorInput implements IEditor {
  Component = () => {
    const update = useUpdate()

    useMount(() => {
      this.element?.focus()
    })

    return (
      <ConfigProvider theme={{ components: { Input: { fontFamily: 'Alibaba PuHuiTi' } } }}>
        <Input
          ref={element => Reflect.set(this, 'element', element)}
          value={this.value}
          className={'absolute inset-0 bg-white'}
          variant={'borderless'}
          onChange={e => {
            Reflect.set(this, 'value', e.target.value)
            update()
          }}
        />
      </ConfigProvider>
    )
  }

  beginEditing(
    container: HTMLElement,
    {
      rect: { top, left, width, height },
    }: {
      rect: RectProps
      placement?: Placement
    },
    value: string | undefined,
  ) {
    const { Component } = this
    Object.assign(this, {
      value,
      exit: () => {
        container.removeChild(holder)
        Object.assign(this, {
          value: void 0,
          exit: noop,
        })
      },
    })

    const holder = document.createElement('div')
    container.append(holder)
    createRoot(holder).render(
      <StrictMode>
        <div
          className={'relative'}
          style={{ top: top + 1, left: left + 1, width: width - 2, height: height - 2 }}
        >
          <Component />
        </div>
      </StrictMode>,
    )
  }

  getValue = () => this.value
  targetIsOnEditor = (target: HTMLElement) => target === this.element?.input
  element?: InputRef
  exit = noop
  // @ts-expect-error antd 期望 undefined 或者 string,而 getValue 不接收 undefined
  value: string
  

  // 实际上压根没用到,只是为了不让 IEditor 属性实现报错
  editorConfig: any
  // @ts-expect-error container 只在 beginEditing() 中使用,exit() 在其中被重新定义
  container: HTMLElement
}

不对称 value 的定义

valuebeginEditing() 传入时类型标注为 string | undefined, 而 getValue() 的返回值要求却为 string | number | null

考虑到值应该是由用户 records 中定义,实际是 unknown,是否在 IEditor 上添加泛型定义会更加合理?

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions