ronantakizawa/codereview-bench huggingface dataset:
Repository: element-plus/element-plus
File: packages/components/timeline/src/timeline-item.vue (Vue)

Code before:
      <div
        v-if="!hideTimestamp && placement === 'bottom'"
        :class="[ns.e('timestamp'), ns.is('bottom')]"
      >
        {{ timestamp }}
      </div>
    </div>
  </li>
</template>

<script lang="ts" setup>
import { computed, inject } from 'vue'
import { ElIcon } from '@element-plus/components/icon'
import { useNamespace } from '@element-plus/hooks'
import { TIMELINE_INJECTION_KEY } from './tokens'

import type { TimelineProvider } from './tokens'
import type { TimelineItemProps } from './timeline-item'

defineOptions({
  name: 'ElTimelineItem',
})

const props = withDefaults(defineProps<TimelineItemProps>(), {
  timestamp: '',
  placement: 'bottom',
  color: '',
  size: 'normal',
})
const { props: timelineProps } = inject<TimelineProvider>(
  TIMELINE_INJECTION_KEY
)!

const ns = useNamespace('timeline-item')
const defaultNodeKls = computed(() => [
  ns.e('node'),
  ns.em('node', props.size || ''),
  ns.em('node', props.type || ''),
  ns.is('hollow', props.hollow),
])

const timelineItemKls = computed(() => [
  ns.b(),
  { [ns.e('center')]: props.center },
  ns.is(timelineProps.mode),
])
</script>


Review comment (suggestion):
```suggestion
  placement: 'bottom',
  type: '',
```

Code after:
      <div
        v-if="!hideTimestamp && placement === 'bottom'"
        :class="[ns.e('timestamp'), ns.is('bottom')]"
      >
        {{ timestamp }}
      </div>
    </div>
  </li>
</template>

<script lang="ts" setup>
import { computed, inject } from 'vue'
import { ElIcon } from '@element-plus/components/icon'
import { useNamespace } from '@element-plus/hooks'
import { TIMELINE_INJECTION_KEY } from './tokens'

import type { TimelineProvider } from './tokens'
import type { TimelineItemProps } from './timeline-item'

defineOptions({
  name: 'ElTimelineItem',
})

const props = withDefaults(defineProps<TimelineItemProps>(), {
  timestamp: '',
  placement: 'bottom',
  type: '',
  color: '',
  size: 'normal',
})
const { props: timelineProps } = inject<TimelineProvider>(
  TIMELINE_INJECTION_KEY
)!

const ns = useNamespace('timeline-item')
const defaultNodeKls = computed(() => [
  ns.e('node'),
  ns.em('node', props.size || ''),
  ns.em('node', props.type || ''),
  ns.is('hollow', props.hollow),
])

const timelineItemKls = computed(() => [
  ns.b(),
  { [ns.e('center')]: props.center },
  ns.is(timelineProps.mode),
])
</script>
Repository: element-plus/element-plus
File: packages/components/checkbox/src/checkbox-group.ts (TypeScript)

Code before:
import { ComponentSize, UPDATE_MODEL_EVENT } from '@element-plus/constants'
import { AriaProps, useAriaProps, useSizeProp } from '@element-plus/hooks'
import { buildProps, definePropType, isArray } from '@element-plus/utils'

import type { ExtractPublicPropTypes } from 'vue'
import type checkboxGroup from './checkbox-group.vue'
import type { CheckboxProps, CheckboxValueType } from './checkbox'

export type CheckboxGroupValueType = Exclude<CheckboxValueType, boolean>[]

export interface CheckboxGroupProps extends Pick<AriaProps, 'ariaLabel'> {
  /**
   * @description binding value
   */
  modelValue?: CheckboxGroupValueType
  /**
   * @description whether the nesting checkboxes are disabled
   */
  disabled?: boolean
  /**
   * @description minimum number of checkbox checked
   */
  min?: number
  /**
   * @description maximum number of checkbox checked
   */

Review comment (suggestion):
Type imports and variable imports should be written separately, and type imports are placed below other type imports.

Code after:
import { UPDATE_MODEL_EVENT } from '@element-plus/constants'
import { useAriaProps, useSizeProp } from '@element-plus/hooks'
import { buildProps, definePropType, isArray } from '@element-plus/utils'

import type { ExtractPublicPropTypes } from 'vue'
import type checkboxGroup from './checkbox-group.vue'
import type { CheckboxProps, CheckboxValueType } from './checkbox'
import type { ComponentSize } from '@element-plus/constants'
import type { AriaProps } from '@element-plus/hooks'

export type CheckboxGroupValueType = Exclude<CheckboxValueType, boolean>[]

export interface CheckboxGroupProps extends Pick<AriaProps, 'ariaLabel'> {
  /**
   * @description binding value
   */
  modelValue?: CheckboxGroupValueType
  /**
   * @description whether the nesting checkboxes are disabled
   */
  disabled?: boolean
  /**
   * @description minimum number of checkbox checked
   */
  min?: number
  /**
Repository: element-plus/element-plus
File: packages/components/form/src/form-item.ts (TypeScript)

Code before:
import { ExtractPublicPropTypes } from 'vue'
import { componentSizes } from '@element-plus/constants'
import { buildProps, definePropType } from '@element-plus/utils'

import type { ComponentSize } from '@element-plus/constants'
import type { Arrayable } from '@element-plus/utils'
import type { FormItemRule } from './types'

export const formItemValidateStates = [
  '',
  'error',
  'validating',
  'success',
] as const
export type FormItemValidateState = (typeof formItemValidateStates)[number]

export type FormItemProp = Arrayable<string>

export interface FormItemProps {
  /**
   * @description Label text.
   */
  label?: string
  /**
   * @description Width of label, e.g. `'50px'`. `'auto'` is supported.
   */

Review comment (refactor):
It’s better to use `import type { ExtractPublicPropTypes } from 'vue'`, the same applies to `form.ts`.

Code after:
import { componentSizes } from '@element-plus/constants'
import { buildProps, definePropType } from '@element-plus/utils'

import type { ExtractPublicPropTypes } from 'vue'
import type { ComponentSize } from '@element-plus/constants'
import type { Arrayable } from '@element-plus/utils'
import type { FormItemRule } from './types'

export const formItemValidateStates = [
  '',
  'error',
  'validating',
  'success',
] as const
export type FormItemValidateState = (typeof formItemValidateStates)[number]

export type FormItemProp = Arrayable<string>

export interface FormItemProps {
  /**
   * @description Label text.
   */
  label?: string
  /**
   * @description Width of label, e.g. `'50px'`. `'auto'` is supported.
   */
Repository: element-plus/element-plus
File: packages/components/carousel/__tests__/carousel.test.tsx (TypeScript)

Code before:
                </CarouselItem>
              ))}
            </Carousel>
          </div>
        )
      },
    })

    await nextTick()
    const vm = wrapper.vm

    expect(vm.$refs.carousel.activeIndex).toBe(0)

    await wait(40)
    expect(vm.$refs.carousel.activeIndex).toBe(1)

    data.push(4)
    await nextTick()

    expect(wrapper.findAll('.el-carousel__item').length).toBe(4)
    expect(vm.$refs.carousel.activeIndex).toBe(0)

    await wait(80)
    const currentIndex = vm.$refs.carousel.activeIndex
    expect(currentIndex).toBeGreaterThan(0)
    expect(currentIndex).toBeLessThanOrEqual(3)
  })
})


Review comment (suggestion):
```suggestion
    expect(vm.$refs.carousel.activeIndex).toBe(2)
```

Code after:
                </CarouselItem>
              ))}
            </Carousel>
          </div>
        )
      },
    })

    await nextTick()
    const vm = wrapper.vm

    expect(vm.$refs.carousel.activeIndex).toBe(0)

    await wait(40)
    expect(vm.$refs.carousel.activeIndex).toBe(1)

    data.push(4)
    await nextTick()

    expect(wrapper.findAll('.el-carousel__item').length).toBe(4)
    expect(vm.$refs.carousel.activeIndex).toBe(0)

    await wait(80)
    expect(vm.$refs.carousel.activeIndex).toBe(2)
  })
})
Repository: element-plus/element-plus
File: packages/components/message-box/src/index.vue (Vue)

Code before:

    onBeforeUnmount(() => {
      if (props.closeOnHashChange) {
        window.removeEventListener('hashchange', doClose)
      }
    })

    function doClose() {
      if (!visible.value) return
      visible.value = false
      nextTick(() => {
        if (state.action) emit('action', state.action)
      })
    }

    const handleWrapperClick = () => {
      if (props.closeOnClickModal) {
        handleAction(state.distinguishCancelAndClose ? 'close' : 'cancel')
      }
    }

    const overlayEvent = useSameTarget(handleWrapperClick)

    const handleInputEnter = (e: KeyboardEvent | Event) => {
      if ((e as KeyboardEvent).isComposing) return
      if (state.inputType !== 'textarea') {
        e.preventDefault()
        return handleAction('confirm')
      }
    }

    const handleAction = (action: Action) => {
      if (props.boxType === 'prompt' && action === 'confirm' && !validate()) {
        return
      }

      state.action = action

      if (state.beforeClose) {
        state.beforeClose?.(action, state, doClose)
      } else {
        doClose()
      }
    }

    const validate = () => {
      if (props.boxType === 'prompt') {
        const inputPattern = state.inputPattern
        if (inputPattern && !inputPattern.test(state.inputValue || '')) {
          state.editorErrorMessage =
            state.inputErrorMessage || t('el.messagebox.error')

Review comment (suggestion):
```suggestion
      if (state.inputType !== 'textarea' && !inputRef.value?.isComposing) {
```
See:
https://github.com/element-plus/element-plus/blob/ac6a316444254b13328bd7497cb590f9245324b6/packages/components/input/src/input.vue#L588

Code after:
    })

    onBeforeUnmount(() => {
      if (props.closeOnHashChange) {
        window.removeEventListener('hashchange', doClose)
      }
    })

    function doClose() {
      if (!visible.value) return
      visible.value = false
      nextTick(() => {
        if (state.action) emit('action', state.action)
      })
    }

    const handleWrapperClick = () => {
      if (props.closeOnClickModal) {
        handleAction(state.distinguishCancelAndClose ? 'close' : 'cancel')
      }
    }

    const overlayEvent = useSameTarget(handleWrapperClick)

    const handleInputEnter = (e: KeyboardEvent | Event) => {
      if (state.inputType !== 'textarea' && !inputRef.value?.isComposing) {
        e.preventDefault()
        return handleAction('confirm')
      }
    }

    const handleAction = (action: Action) => {
      if (props.boxType === 'prompt' && action === 'confirm' && !validate()) {
        return
      }

      state.action = action

      if (state.beforeClose) {
        state.beforeClose?.(action, state, doClose)
      } else {
        doClose()
      }
    }

    const validate = () => {
      if (props.boxType === 'prompt') {
        const inputPattern = state.inputPattern
        if (inputPattern && !inputPattern.test(state.inputValue || '')) {
          state.editorErrorMessage =
            state.inputErrorMessage || t('el.messagebox.error')
Repository: element-plus/element-plus
File: packages/components/select/__tests__/select.test.ts (TypeScript)

Code before:
    options[1].click()
    await nextTick()
    options[2].click()
    selectRef.vm.states.collapseItemWidth = 38
    await nextTick()
    expect(tagWrapperDom.style.maxWidth).toBe('156px')
  })

  test('multiple select with collapseTagsTooltip', async () => {
    // This is convenient for testing the default value label rendering when persistent is false.
    process.env.RUN_TEST_WITH_PERSISTENT = 'true'

    wrapper = _mount(
      `
      <div>
        <div class="append-target"></div>
        <el-select
          v-model="selectedList"
          multiple
          collapseTags
          collapse-tags-tooltip
          tooltip-append-to=".append-target"
          placeholder="请选择"
        >
          <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
          </el-option>
        </el-select>
      </div>
    `,
      () => ({
        options: [
          {
            value: '选项1',
            label: '黄金糕',
          },
          {
            value: '选项2',
            label: '双皮奶',
          },
          {
            value: '选项3',
            label: '蚵仔煎',
          },
          {
            value: '选项4',
            label: '龙须面',
          },
          {
            value: '选项5',
            label: '北京烤鸭',
          },

Review comment (suggestion):
```suggestion
          <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
```

Code after:
    options[1].click()
    await nextTick()
    options[2].click()
    selectRef.vm.states.collapseItemWidth = 38
    await nextTick()
    expect(tagWrapperDom.style.maxWidth).toBe('156px')
  })

  test('multiple select with collapseTagsTooltip', async () => {
    // This is convenient for testing the default value label rendering when persistent is false.
    process.env.RUN_TEST_WITH_PERSISTENT = 'true'

    wrapper = _mount(
      `
      <div>
        <div class="append-target"></div>
        <el-select
          v-model="selectedList"
          multiple
          collapseTags
          collapse-tags-tooltip
          :tag-tooltip="{ appendTo: '.append-target' }"
          placeholder="请选择"
        >
          <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
      </div>
    `,
      () => ({
        options: [
          {
            value: '选项1',
            label: '黄金糕',
          },
          {
            value: '选项2',
            label: '双皮奶',
          },
          {
            value: '选项3',
            label: '蚵仔煎',
          },
          {
            value: '选项4',
            label: '龙须面',
          },
          {
            value: '选项5',
            label: '北京烤鸭',
          },
        ],
Repository: element-plus/element-plus
File: packages/components/select/src/select.ts (TypeScript)

Code before:

import type { EmitFn } from '@element-plus/utils'
import type {
  CSSProperties,
  ExtractPropTypes,
  ExtractPublicPropTypes,
} from 'vue'
import type Select from './select.vue'
import type {
  Options,
  Placement,
  PopperEffect,
} from '@element-plus/components/popper'
import type { OptionValue } from './type'
import type { Props } from '@element-plus/components/select-v2/src/useProps'

/**
 * @description Tag tooltip configuration interface
 */
export interface TagTooltipProps {
  appendTo?: string | HTMLElement
  placement?: Placement
  fallbackPlacements?: Placement[]
  effect?: PopperEffect
  popperClass?: string
  popperStyle?: CSSProperties
  teleported?: boolean
  popperOptions?: Partial<Options>
  showAfter?: number
  offset?: number
}

export const selectProps = buildProps({
  /**
   * @description the name attribute of select input
   */
  name: String,
  /**
   * @description native input id
   */
  id: String,
  /**
   * @description binding value
   */
  modelValue: {
    type: definePropType<OptionValue | OptionValue[] | null>([
      Array,
      String,
      Number,
      Boolean,
      Object,

Review comment (suggestion):
```suggestion
  popperStyle?: string | CSSProperties
```

Code after:

import type { EmitFn } from '@element-plus/utils'
import type {
  CSSProperties,
  ExtractPropTypes,
  ExtractPublicPropTypes,
} from 'vue'
import type Select from './select.vue'
import type {
  Options,
  Placement,
  PopperEffect,
} from '@element-plus/components/popper'
import type { OptionValue } from './type'
import type { Props } from '@element-plus/components/select-v2/src/useProps'

/**
 * @description Tag tooltip configuration interface
 */
export interface TagTooltipProps {
  appendTo?: string | HTMLElement
  placement?: Placement
  fallbackPlacements?: Placement[]
  effect?: PopperEffect
  popperClass?: string
  popperStyle?: string | CSSProperties
  transition?: string
  teleported?: boolean
  popperOptions?: Partial<Options>
  showAfter?: number
  hideAfter?: number
  autoClose?: number
  offset?: number
}

export const selectProps = buildProps({
  /**
   * @description the name attribute of select input
   */
  name: String,
  /**
   * @description native input id
   */
  id: String,
  /**
   * @description binding value
   */
  modelValue: {
    type: definePropType<OptionValue | OptionValue[] | null>([
      Array,
      String,
Repository: element-plus/element-plus
File: packages/components/color-picker-panel/src/color-picker-panel.ts (TypeScript)

Code before:
import { UPDATE_MODEL_EVENT } from '@element-plus/constants'

import type { ComputedRef, ExtractPublicPropTypes, InjectionKey } from 'vue'
import type ColorPickerPanel from './color-picker-panel.vue'
import type Color from './utils/color'

export const colorFormats = ['hsl', 'hsv', 'hex', 'rgb'] as const
export type ColorFormat = (typeof colorFormats)[number]

export interface ColorPickerPanelProps {
  /**
   * @description binding value
   */
  modelValue?: string | null
  /**
   * @description whether the color picker is bordered
   */
  border?: boolean
  /**
   * @description whether to display the alpha slider
   */
  showAlpha?: boolean
  /**
   * @description color format of v-model
   */
  colorFormat?: ColorFormat
  /**
   * @description whether to disable the color picker
   */
  disabled?: boolean
  /**
   * @description predefined color options
   */
  predefine?: string[]
  /**
   * @description whether to trigger form validation
   */
  validateEvent?: boolean
}

/**
 * @deprecated Removed after 3.0.0, Use `ColorPickerPanelProps` instead.
 */
export const colorPickerPanelProps = buildProps({
  /**
   * @description binding value
   */
  modelValue: {
    type: definePropType<string | null>(String),
    default: undefined,
  },

Review comment (suggestion):
<img width="1225" height="285" alt="Image" src="https://github.com/user-attachments/assets/7cd2a171-3830-4cd2-b0ee-813122ebdb8b" />
It seems we shouldn't restrict its type; we can leave it as is.

Code after:
import { UPDATE_MODEL_EVENT } from '@element-plus/constants'

import type { ComputedRef, ExtractPublicPropTypes, InjectionKey } from 'vue'
import type { ColorFormats } from '@ctrl/tinycolor'
import type ColorPickerPanel from './color-picker-panel.vue'
import type Color from './utils/color'

export interface ColorPickerPanelProps {
  /**
   * @description binding value
   */
  modelValue?: string | null
  /**
   * @description whether the color picker is bordered
   */
  border?: boolean
  /**
   * @description whether to display the alpha slider
   */
  showAlpha?: boolean
  /**
   * @description color format of v-model
   */
  colorFormat?: ColorFormats
  /**
   * @description whether to disable the color picker
   */
  disabled?: boolean
  /**
   * @description predefined color options
   */
  predefine?: string[]
  /**
   * @description whether to trigger form validation
   */
  validateEvent?: boolean
}

/**
 * @deprecated Removed after 3.0.0, Use `ColorPickerPanelProps` instead.
 */
export const colorPickerPanelProps = buildProps({
  /**
   * @description binding value
   */
  modelValue: {
    type: definePropType<string | null>(String),
    default: undefined,
  },
  /**
   * @description whether the color picker is bordered
Repository: element-plus/element-plus
File: packages/components/table/src/table-column/watcher-helper.ts (TypeScript)

Code before:
        watch(
          () => owner.value.props[key],
          (newVal) => {
            if (instance.columnConfig.value.type === 'selection') return
            if (!isUndefined(props_[key])) return
            instance.columnConfig.value[key] = newVal as never
          }
        )
      }
    })

    const globalConfig = useGlobalConfig('table')
    if (
      globalConfig.value &&
      hasOwn(globalConfig.value, 'showOverflowTooltip')
    ) {
      watch(
        () => globalConfig.value?.showOverflowTooltip,
        (newVal) => {
          if (instance.columnConfig.value.type === 'selection') return
          if (
            !isUndefined(props_['showOverflowTooltip']) ||
            !isUndefined(owner.value.props['showOverflowTooltip'])
          )
            return
          instance.columnConfig.value['showOverflowTooltip'] = newVal as never
        }
      )
    }
  }

  return {
    registerComplexWatchers,
    registerNormalWatchers,
  }
}

export default useWatcher


Review comment (bug):
**nit**: we can maybe leave the array call
```suggestion
            !isUndefined(props_.showOverflowTooltip) ||
            !isUndefined(owner.value.props.showOverflowTooltip)
          )
            return
          instance.columnConfig.value.showOverflowTooltip = newVal as never
```

Code after:
        watch(
          () => owner.value.props[key],
          (newVal) => {
            if (instance.columnConfig.value.type === 'selection') return
            if (!isUndefined(props_[key])) return
            instance.columnConfig.value[key] = newVal as never
          }
        )
      }
    })

    const globalConfig = useGlobalConfig('table')
    if (
      globalConfig.value &&
      hasOwn(globalConfig.value, 'showOverflowTooltip')
    ) {
      watch(
        () => globalConfig.value?.showOverflowTooltip,
        (newVal) => {
          if (instance.columnConfig.value.type === 'selection') return
          if (
            !isUndefined(props_.showOverflowTooltip) ||
            !isUndefined(owner.value.props.showOverflowTooltip)
          )
            return
          instance.columnConfig.value.showOverflowTooltip = newVal as never
        }
      )
    }
  }

  return {
    registerComplexWatchers,
    registerNormalWatchers,
  }
}

export default useWatcher
Repository: element-plus/element-plus
File: packages/components/time-select/src/time-select.vue (Vue)

Code before:
  const result: { value: string; rawValue: string; disabled: boolean }[] = []
  const push = (formattedValue: string, rawValue: string) => {
    result.push({
      value: formattedValue,
      rawValue,
      disabled:
        compareTime(rawValue, minTime.value || '-1:-1') <= 0 ||
        compareTime(rawValue, maxTime.value || '100:100') >= 0,
    })
  }

  if (props.start && props.end && props.step) {
    if (isInvalidStep.value) {
      debugWarn(
        'ElTimeSelect',
        `invalid step, fallback to default step (${DEFAULT_STEP}).`
      )
    }
    let current = start.value
    let currentTime: string
    while (current && end.value && compareTime(current, end.value) <= 0) {
      currentTime = dayjs(current, 'HH:mm')
        .locale(lang.value)
        .format(props.format)
      push(currentTime, current)
      current = nextTime(current, step.value)
    }
    if (
      props.includeEndTime &&
      end.value &&
      result[result.length - 1]?.rawValue !== end.value
    ) {
      const formattedValue = dayjs(end.value, 'HH:mm')
        .locale(lang.value)
        .format(props.format)
      push(formattedValue, end.value)
    }
  }
  return result
})

const blur = () => {
  select.value?.blur?.()
}

const focus = () => {
  select.value?.focus?.()
}

defineExpose({
  /**

Review comment (suggestion):
```suggestion
      current = nextTime(current, step.value!)
```

There’s no need to change this. I think preserving the Git history is more important than removing these redundant assertions.

Code after:
    result.push({
      value: formattedValue,
      rawValue,
      disabled:
        compareTime(rawValue, minTime.value || '-1:-1') <= 0 ||
        compareTime(rawValue, maxTime.value || '100:100') >= 0,
    })
  }

  if (props.start && props.end && props.step) {
    let current = start.value
    let currentTime: string
    while (current && end.value && compareTime(current, end.value) <= 0) {
      currentTime = dayjs(current, 'HH:mm')
        .locale(lang.value)
        .format(props.format)
      push(currentTime, current)
      current = nextTime(current, step.value!)
    }
    if (
      props.includeEndTime &&
      end.value &&
      result[result.length - 1]?.rawValue !== end.value
    ) {
      const formattedValue = dayjs(end.value, 'HH:mm')
        .locale(lang.value)
        .format(props.format)
      push(formattedValue, end.value)
    }
  }
  return result
})

const blur = () => {
  select.value?.blur?.()
}

const focus = () => {
  select.value?.focus?.()
}

defineExpose({
  /**
   * @description blur the Input component
   */
  blur,
  /**
   * @description focus the Input component
   */
  focus,
})