export function FormDialog()

in packages/next/src/form-dialog/index.tsx [61:242]


export function FormDialog(
  title: IDialogProps,
  id: string,
  renderer: FormDialogRenderer
): IFormDialog
export function FormDialog(
  title: IDialogProps,
  renderer: FormDialogRenderer
): IFormDialog
export function FormDialog(
  title: ModalTitle,
  id: string,
  renderer: FormDialogRenderer
): IFormDialog
export function FormDialog(
  title: ModalTitle,
  renderer: FormDialogRenderer
): IFormDialog
export function FormDialog(title: any, id: any, renderer?: any): IFormDialog {
  if (isFn(id) || React.isValidElement(id)) {
    renderer = id
    id = 'form-dialog'
  }
  const env = {
    host: document.createElement('div'),
    form: null,
    promise: null,
    openMiddlewares: [],
    confirmMiddlewares: [],
    cancelMiddlewares: [],
  }
  const root = createPortalRoot(env.host, id)
  const props = getModelProps(title)
  const modal = {
    ...props,
    style: {
      width: '40%',
      ...props.style,
    },
    afterClose: () => {
      props?.afterClose?.()
      root.unmount()
    },
  }
  const DialogContent = observer(() => {
    return <Fragment>{isFn(renderer) ? renderer(env.form) : renderer}</Fragment>
  })
  const renderDialog = (
    visible = true,
    resolve?: () => any,
    reject?: () => any
  ) => {
    const ctx = getContext()
    const prefix = modal.prefix || ctx.prefix || 'next'
    const okProps = {
      children: ctx?.locale?.Dialog?.ok || '确定',
      ...(ctx?.defaultPropsConfig?.Dialog?.okProps || {}),
      ...(modal.okProps || {}),
    }
    const cancelProps = {
      children: ctx?.locale?.Dialog?.cancel || '取消',
      ...(ctx?.defaultPropsConfig?.Dialog?.cancelProps || {}),
      ...(modal.cancelProps || {}),
    }
    const buttonMap = {
      ok: (
        <Button
          key="ok"
          type="primary"
          className={prefix + '-dialog-btn'}
          loading={env.form.submitting}
          onClick={(e) => {
            if (modal?.onOk?.(e) !== false) {
              resolve()
            }
          }}
          {...okProps}
        />
      ),
      cancel: (
        <Button
          key="cancel"
          className={prefix + '-dialog-btn'}
          onClick={(e) => {
            if (modal?.onCancel?.(e) !== false) {
              reject()
            }
          }}
          {...cancelProps}
        />
      ),
    }
    const footerActions = ctx?.defaultPropsConfig?.Dialog?.footerActions ||
      modal.footerActions || ['cancel', 'ok']

    return (
      <ConfigProvider {...ctx}>
        <Observer>
          {() => (
            <Dialog
              {...modal}
              visible={visible}
              footer={
                <Fragment>
                  {footerActions.map((item) => buttonMap[item])}
                </Fragment>
              }
              onClose={(trigger, e) => {
                modal?.onClose?.(trigger, e)
                reject()
              }}
            >
              <FormProvider form={env.form}>
                <DialogContent />
              </FormProvider>
            </Dialog>
          )}
        </Observer>
      </ConfigProvider>
    )
  }
  document.body.appendChild(env.host)
  const formDialog = {
    forOpen: (middleware: IMiddleware<IFormProps>) => {
      if (isFn(middleware)) {
        env.openMiddlewares.push(middleware)
      }
      return formDialog
    },
    forConfirm: (middleware: IMiddleware<Form>) => {
      if (isFn(middleware)) {
        env.confirmMiddlewares.push(middleware)
      }
      return formDialog
    },
    forCancel: (middleware: IMiddleware<Form>) => {
      if (isFn(middleware)) {
        env.cancelMiddlewares.push(middleware)
      }
      return formDialog
    },
    open: async (props: IFormProps) => {
      if (env.promise) return env.promise
      env.promise = new Promise(async (resolve, reject) => {
        try {
          props = await loading(modal.loadingText, () =>
            applyMiddleware(props, env.openMiddlewares)
          )
          env.form = env.form || createForm(props)
        } catch (e) {
          reject(e)
        }
        root.render(() =>
          renderDialog(
            true,
            () => {
              env.form
                .submit(async () => {
                  await applyMiddleware(env.form, env.confirmMiddlewares)
                  resolve(toJS(env.form.values))
                  formDialog.close()
                })
                .catch(() => {})
            },
            async () => {
              await loading(modal.loadingText, () =>
                applyMiddleware(env.form, env.cancelMiddlewares)
              )
              formDialog.close()
            }
          )
        )
      })
      return env.promise
    },
    close: () => {
      if (!env.host) return
      root.render(() => renderDialog(false))
    },
  }
  return formDialog
}