Repository: element-plus/element-plus
File: packages/components/dialog/src/dialog.ts (TypeScript)

Code before:
import { buildProps, definePropType, isBoolean } from '@element-plus/utils'
import { UPDATE_MODEL_EVENT } from '@element-plus/constants'
import { teleportProps } from '@element-plus/components/teleport'
import { dialogContentProps } from './dialog-content'

import type { ExtractPublicPropTypes, InjectionKey, TransitionProps } from 'vue'
import type { DialogContentProps } from './dialog-content'
import type Dialog from './dialog.vue'

type DoneFn = (cancel?: boolean) => void

export type DialogBeforeCloseFn = (done: DoneFn) => void

export type DialogTransition = string | TransitionProps

/**
 * @description dialog component props
 */
export interface DialogProps extends DialogContentProps {
  /**
   * @description whether to append Dialog itself to body. A nested Dialog should have this attribute set to `true`
   */
  appendToBody?: boolean
  /**
   * @description which element the Dialog appends to
   */
  appendTo?: string | HTMLElement
  /**
   * @description callback before Dialog closes, and it will prevent Dialog from closing, use done to close the dialog
   */
  beforeClose?: DialogBeforeCloseFn
  /**
   * @description destroy elements in Dialog when closed
   */
  destroyOnClose?: boolean
  /**
   * @description whether the Dialog can be closed by clicking the mask
   */
  closeOnClickModal?: boolean
  /**
   * @description whether the Dialog can be closed by pressing ESC
   */
  closeOnPressEscape?: boolean
  /**
   * @description whether scroll of body is disabled while Dialog is displayed
   */
  lockScroll?: boolean
  /**
   * @description whether a mask is displayed
   */
  modal?: boolean
  /**
   * @description whether the mask is penetrable
   */
  modalPenetrable?: boolean
  /**
   * @description the Time(milliseconds) before open
   */
  openDelay?: number
  /**
   * @description the Time(milliseconds) before close
   */
  closeDelay?: number
  /**
   * @description value for `margin-top` of Dialog CSS, default is 15vh
   */
  top?: string
  /**
   * @description visibility of Dialog
   */
  modelValue?: boolean
  /**
   * @description custom class names for mask
   */
  modalClass?: string
  /**
   * @description width of Dialog, default is 50%
   */
  width?: string | number
  /**
   * @description same as z-index in native CSS, z-order of dialog
   */
  zIndex?: number
  /**
   * @description trap focus within dialog
   */
  trapFocus?: boolean
  /**
   * @description header's aria-level attribute
   */
  headerAriaLevel?: string
  /**
   * @description custom transition configuration for dialog animation, it can be a string (transition name) or an object with Vue transition props
   */
  transition?: DialogTransition
}

/**
 * @deprecated Removed after 3.0.0, Use `DialogProps` instead.
 */
export const dialogProps = buildProps({
  ...dialogContentProps,
  /**
   * @description whether to append Dialog itself to body. A nested Dialog should have this attribute set to `true`
   */
  appendToBody: Boolean,
  /**
   * @description which element the Dialog appends to
   */
  appendTo: {
    type: teleportProps.to.type,
    default: 'body',
  },
  /**
   * @description callback before Dialog closes, and it will prevent Dialog from closing, use done to close the dialog
   */
  beforeClose: {
    type: definePropType<DialogBeforeCloseFn>(Function),
  },
  /**
   * @description destroy elements in Dialog when closed
   */
  destroyOnClose: Boolean,
  /**
   * @description whether the Dialog can be closed by clicking the mask
   */
  closeOnClickModal: {
    type: Boolean,
    default: true,
  },
  /**
   * @description whether the Dialog can be closed by pressing ESC
   */
  closeOnPressEscape: {
    type: Boolean,
    default: true,
  },
  /**
   * @description whether scroll of body is disabled while Dialog is displayed
   */
  lockScroll: {
    type: Boolean,
    default: true,
  },
  /**
   * @description whether a mask is displayed
   */
  modal: {
    type: Boolean,
    default: true,
  },
  /**
   * @description whether the mask is penetrable
   */
  modalPenetrable: Boolean,
  /**
   * @description the Time(milliseconds) before open
   */
  openDelay: {
    type: Number,
    default: 0,
  },
  /**
   * @description the Time(milliseconds) before close
   */
  closeDelay: {
    type: Number,
    default: 0,
  },
  /**
   * @description value for `margin-top` of Dialog CSS, default is 15vh
   */
  top: {
    type: String,
  },
  /**
   * @description visibility of Dialog
   */
  modelValue: Boolean,
  /**
   * @description custom class names for mask
   */
  modalClass: String,
  /**
   * @description custom class names for header wrapper
   */
  headerClass: String,
  /**
   * @description custom class names for body wrapper
   */
  bodyClass: String,
  /**
   * @description custom class names for footer wrapper
   */
  footerClass: String,
  /**
   * @description width of Dialog, default is 50%
   */
  width: {
    type: [String, Number],
  },
  /**
   * @description same as z-index in native CSS, z-order of dialog
   */
  zIndex: {
    type: Number,
  },
  trapFocus: Boolean,
  /**
   * @description header's aria-level attribute
   */
  headerAriaLevel: {
    type: String,
    default: '2',
  },
  /**
   * @description custom transition configuration for dialog animation, it can be a string (transition name) or an object with Vue transition props
   */
  transition: {
    type: definePropType<DialogTransition>([String, Object]),
    default: undefined,
  },
} as const)

/**
 * @deprecated Removed after 3.0.0, Use `DialogProps` instead.
 */
export type DialogPropsPublic = ExtractPublicPropTypes<typeof dialogProps>

export const dialogEmits = {
  open: () => true,
  opened: () => true,
  close: () => true,
  closed: () => true,
  [UPDATE_MODEL_EVENT]: (value: boolean) => isBoolean(value),
  openAutoFocus: () => true,
  closeAutoFocus: () => true,
}
export type DialogEmits = typeof dialogEmits
export type DialogInstance = InstanceType<typeof Dialog> & unknown
export interface DialogConfigContext {
  alignCenter?: boolean
  draggable?: boolean
  overflow?: boolean
  transition?: DialogTransition
}

export const dialogContextKey: InjectionKey<DialogConfigContext> =
  Symbol('dialogContextKey')

export const dialogPropsDefaults = {
  appendTo: 'body',
  closeOnClickModal: true,
  closeOnPressEscape: true,
  lockScroll: true,
  modal: true,
  openDelay: 0,
  closeDelay: 0,
  headerAriaLevel: '2',
  transition: undefined,
} as const


Review comment (security):
`dialogContentPropsDefaults` is also a part of `dialogPropsDefaults`


```suggestion
export const dialogPropsDefaults = {
  ...dialogContentPropsDefaults,
  appendTo: 'body',
  closeOnClickModal: true,
  closeOnPressEscape: true,
  lockScroll: true,
  modal: true,
  openDelay: 0,
  closeDelay: 0,
  headerAriaLevel: '2',
  transition: undefined,
} as const
```

Code after:
  closeAutoFocus: () => true,
}
export type DialogEmits = typeof dialogEmits
export type DialogInstance = InstanceType<typeof Dialog> & unknown
export interface DialogConfigContext {
  alignCenter?: boolean
  draggable?: boolean
  overflow?: boolean
  transition?: DialogTransition
}

export const dialogContextKey: InjectionKey<DialogConfigContext> =
  Symbol('dialogContextKey')

export const dialogPropsDefaults = {
  ...dialogContentPropsDefaults,
  appendTo: 'body',
  closeOnClickModal: true,
  closeOnPressEscape: true,
  lockScroll: true,
  modal: true,
  openDelay: 0,
  closeDelay: 0,
  headerAriaLevel: '2',
  transition: undefined,
} as const