Repository: ant-design/ant-design-mobile (ts)

Issue:
DatePicker renderLabel能否入参当前selected
### Version of antd-mobile

5.39.0

### What is this feature about?

目前有场景需要在DatePicker中显示日期对应的星期数，由于renderLabel没有传递面板的selected，且无法从ref中获取。现阶段只能通过querySelector解决，但不够优雅。

期望：
useRenderLabel hook中的renderLabel可以传参selected

Pull request description:
feature(DatePicker): renderLabel add selected parameter
resolve #6867 

Patch:
diff --git a/src/components/date-picker-view/date-picker-view.tsx b/src/components/date-picker-view/date-picker-view.tsx
index 1d0d9c4dc..f0ca9a326 100644
--- a/src/components/date-picker-view/date-picker-view.tsx
+++ b/src/components/date-picker-view/date-picker-view.tsx
@@ -1,24 +1,30 @@
-import React, { useCallback, useMemo } from 'react'
 import type { FC, ReactNode } from 'react'
-import PickerView from '../picker-view'
-import type { PickerValue, PickerViewProps } from '../picker-view'
+import React, { useCallback, useMemo } from 'react'
 import { NativeProps, withNativeProps } from '../../utils/native-props'
-import { mergeProps } from '../../utils/with-default-props'
 import { usePropsValue } from '../../utils/use-props-value'
+import { mergeProps } from '../../utils/with-default-props'
+import type {
+  DatePickerFilter,
+  Precision,
+} from '../date-picker/date-picker-utils'
 import {
-  generateDatePickerColumns,
   convertDateToStringArray,
   convertStringArrayToDate,
+  generateDatePickerColumns,
 } from '../date-picker/date-picker-utils'
-import type {
-  Precision,
-  DatePickerFilter,
-} from '../date-picker/date-picker-utils'
-import useRenderLabel from './useRenderLabel'
-import { TILL_NOW } from '../date-picker/util'
 import type { PickerDate } from '../date-picker/util'
+import { TILL_NOW } from '../date-picker/util'
+import type { PickerValue, PickerViewProps } from '../picker-view'
+import PickerView from '../picker-view'
+import useRenderLabel from './useRenderLabel'
 
-export type RenderLabel = (type: Precision | 'now', data: number) => ReactNode
+export type RenderLabel = (
+  type: Precision | 'now',
+  data: number,
+  info: {
+    selected: boolean
+  }
+) => ReactNode
 
 export type DatePickerViewProps = Pick<
   PickerViewProps,
diff --git a/src/components/date-picker-view/useRenderLabel.ts b/src/components/date-picker-view/useRenderLabel.ts
index edca82c71..46af10224 100644
--- a/src/components/date-picker-view/useRenderLabel.ts
+++ b/src/components/date-picker-view/useRenderLabel.ts
@@ -6,9 +6,9 @@ export default function useRenderLabel(renderLabel?: RenderLabel): RenderLabel {
   const { locale } = useConfig()
 
   return useCallback(
-    (type, data) => {
+    (type, data, info) => {
       if (renderLabel) {
-        return renderLabel(type, data)
+        return renderLabel(type, data, info)
       }
 
       // Default render
diff --git a/src/components/date-picker/date-picker-date-utils.ts b/src/components/date-picker/date-picker-date-utils.ts
index 94624b01a..4630f32cf 100644
--- a/src/components/date-picker/date-picker-date-utils.ts
+++ b/src/components/date-picker/date-picker-date-utils.ts
@@ -1,11 +1,11 @@
 import dayjs from 'dayjs'
+import isLeapYear from 'dayjs/plugin/isLeapYear'
 import isoWeek from 'dayjs/plugin/isoWeek'
 import isoWeeksInYear from 'dayjs/plugin/isoWeeksInYear'
-import isLeapYear from 'dayjs/plugin/isLeapYear'
+import { RenderLabel } from '../date-picker-view/date-picker-view'
 import { PickerColumn } from '../picker'
 import type { DatePickerFilter } from './date-picker-utils'
 import { TILL_NOW } from './util'
-import { RenderLabel } from '../date-picker-view/date-picker-view'
 
 dayjs.extend(isoWeek)
 dayjs.extend(isoWeeksInYear)
@@ -63,6 +63,7 @@ export function generateDatePickerColumns(
   const selectedDay = parseInt(selected[2])
   const selectedHour = parseInt(selected[3])
   const selectedMinute = parseInt(selected[4])
+  const selectedSecond = parseInt(selected[5])
 
   const isInMinYear = selectedYear === minYear
   const isInMaxYear = selectedYear === maxYear
@@ -105,7 +106,7 @@ export function generateDatePickerColumns(
     const years = generateColumn(lower, upper, 'year')
     ret.push(
       years.map(v => ({
-        label: renderLabel('year', v),
+        label: renderLabel('year', v, { selected: selectedYear === v }),
         value: v.toString(),
       }))
     )
@@ -117,7 +118,7 @@ export function generateDatePickerColumns(
     const months = generateColumn(lower, upper, 'month')
     ret.push(
       months.map(v => ({
-        label: renderLabel('month', v),
+        label: renderLabel('month', v, { selected: selectedMonth === v }),
         value: v.toString(),
       }))
     )
@@ -128,7 +129,7 @@ export function generateDatePickerColumns(
     const days = generateColumn(lower, upper, 'day')
     ret.push(
       days.map(v => ({
-        label: renderLabel('day', v),
+        label: renderLabel('day', v, { selected: selectedDay === v }),
         value: v.toString(),
       }))
     )
@@ -139,7 +140,7 @@ export function generateDatePickerColumns(
     const hours = generateColumn(lower, upper, 'hour')
     ret.push(
       hours.map(v => ({
-        label: renderLabel('hour', v),
+        label: renderLabel('hour', v, { selected: selectedHour === v }),
         value: v.toString(),
       }))
     )
@@ -150,7 +151,7 @@ export function generateDatePickerColumns(
     const minutes = generateColumn(lower, upper, 'minute')
     ret.push(
       minutes.map(v => ({
-        label: renderLabel('minute', v),
+        label: renderLabel('minute', v, { selected: selectedMinute === v }),
         value: v.toString(),
       }))
     )
@@ -161,7 +162,7 @@ export function generateDatePickerColumns(
     const seconds = generateColumn(lower, upper, 'second')
     ret.push(
       seconds.map(v => ({
-        label: renderLabel('second', v),
+        label: renderLabel('second', v, { selected: selectedSecond === v }),
         value: v.toString(),
       }))
     )
@@ -170,7 +171,7 @@ export function generateDatePickerColumns(
   // Till Now
   if (tillNow) {
     ret[0].push({
-      label: renderLabel('now', null!),
+      label: renderLabel('now', null!, { selected: selected[0] === TILL_NOW }),
       value: TILL_NOW,
     })
 
@@ -199,7 +200,7 @@ export function convertDateToStringArray(
 }
 
 export function convertStringArrayToDate<
-  T extends string | number | null | undefined
+  T extends string | number | null | undefined,
 >(value: T[]): Date {
   const yearString = value[0] ?? '1900'
   const monthString = value[1] ?? '1'
diff --git a/src/components/date-picker/date-picker-quarter-utils.ts b/src/components/date-picker/date-picker-quarter-utils.ts
index f562d070d..fdff57437 100644
--- a/src/components/date-picker/date-picker-quarter-utils.ts
+++ b/src/components/date-picker/date-picker-quarter-utils.ts
@@ -18,7 +18,13 @@ export function generateDatePickerColumns(
   min: Date,
   max: Date,
   precision: QuarterPrecision,
-  renderLabel: (type: QuarterPrecision, data: number) => ReactNode,
+  renderLabel: (
+    type: QuarterPrecision,
+    data: number,
+    info: {
+      selected: boolean
+    }
+  ) => ReactNode,
   filter: DatePickerFilter | undefined
 ) {
   const ret: PickerColumn[] = []
@@ -36,6 +42,7 @@ export function generateDatePickerColumns(
   const maxDay = dayjs(max)
   const minQuarter = minDay.quarter()
   const maxQuarter = maxDay.quarter()
+  const selectedQuarter = parseInt(selected[1])
 
   const generateColumn = (
     from: number,
@@ -67,7 +74,7 @@ export function generateDatePickerColumns(
     const years = generateColumn(lower, upper, 'year')
     ret.push(
       years.map(v => ({
-        label: renderLabel('year', v),
+        label: renderLabel('year', v, { selected: selectedYear === v }),
         value: v.toString(),
       }))
     )
@@ -79,7 +86,7 @@ export function generateDatePickerColumns(
     const quarters = generateColumn(lower, upper, 'quarter')
     ret.push(
       quarters.map(v => ({
-        label: renderLabel('quarter', v),
+        label: renderLabel('quarter', v, { selected: selectedQuarter === v }),
         value: v.toString(),
       }))
     )
diff --git a/src/components/date-picker/date-picker-week-utils.ts b/src/components/date-picker/date-picker-week-utils.ts
index 8100b266a..c427fa53a 100644
--- a/src/components/date-picker/date-picker-week-utils.ts
+++ b/src/components/date-picker/date-picker-week-utils.ts
@@ -23,7 +23,13 @@ export function generateDatePickerColumns(
   min: Date,
   max: Date,
   precision: WeekPrecision,
-  renderLabel: (type: WeekPrecision, data: number) => ReactNode,
+  renderLabel: (
+    type: WeekPrecision,
+    data: number,
+    info: {
+      selected: boolean
+    }
+  ) => ReactNode,
   filter: DatePickerFilter | undefined
 ) {
   const ret: PickerColumn[] = []
@@ -44,6 +50,7 @@ export function generateDatePickerColumns(
   const minWeekday = minDay.isoWeekday()
   const maxWeekday = maxDay.isoWeekday()
   const selectedWeek = parseInt(selected[1])
+  const selectedWeekday = parseInt(selected[2])
   const isInMinWeek = isInMinYear && selectedWeek === minWeek
   const isInMaxWeek = isInMaxYear && selectedWeek === maxWeek
   const selectedYearWeeks = dayjs(`${selectedYear}-01-01`).isoWeeksInYear()
@@ -78,7 +85,7 @@ export function generateDatePickerColumns(
     const years = generateColumn(lower, upper, 'year')
     ret.push(
       years.map(v => ({
-        label: renderLabel('year', v),
+        label: renderLabel('year', v, { selected: selectedYear === v }),
         value: v.toString(),
       }))
     )
@@ -90,7 +97,7 @@ export function generateDatePickerColumns(
     const weeks = generateColumn(lower, upper, 'week')
     ret.push(
       weeks.map(v => ({
-        label: renderLabel('week', v),
+        label: renderLabel('week', v, { selected: selectedWeek === v }),
         value: v.toString(),
       }))
     )
@@ -101,7 +108,7 @@ export function generateDatePickerColumns(
     const weeks = generateColumn(lower, upper, 'week-day')
     ret.push(
       weeks.map(v => ({
-        label: renderLabel('week-day', v),
+        label: renderLabel('week-day', v, { selected: selectedWeekday === v }),
         value: v.toString(),
       }))
     )
diff --git a/src/components/picker/index.en.md b/src/components/picker/index.en.md
index 9b6b7578e..a5ec214fe 100644
--- a/src/components/picker/index.en.md
+++ b/src/components/picker/index.en.md
@@ -163,7 +163,7 @@ type PickerDate = Date & {
 | onConfirm | Triggered when confirming | `(value: PickerDate) => void` | - |
 | onSelect | Triggered when the options are changed | `(value: PickerDate) => void` | - |
 | precision | Precision | `'year' \| 'month' \| 'day' \| 'hour' \| 'minute' \| 'second' \| 'week' \| 'week-day' \| 'quarter'` | `'day'` |
-| renderLabel | The function to custom rendering the label shown on a column. `type` means any value in `precision` or `now`, `data` means the default number | `(type: Precision \| 'now', data: number) => ReactNode` | - |
+| renderLabel | The function to custom rendering the label shown on a column. `type` means any value in `precision` or `now`, `data` means the default number | `(type: Precision \| 'now', data: number, info: { selected: boolean }) => ReactNode` | - |
 | tillNow | Show till now in list | `boolean` | - | 5.27.0 |
 | value | Selected value | `PickerDate` | - |
 
diff --git a/src/components/picker/index.zh.md b/src/components/picker/index.zh.md
index a2919a119..cbab3244c 100644
--- a/src/components/picker/index.zh.md
+++ b/src/components/picker/index.zh.md
@@ -165,7 +165,7 @@ type PickerDate = Date & {
 | onConfirm | 确认时触发 | `(value: PickerDate) => void` | - |
 | onSelect | 选项改变时触发 | `(value: PickerDate) => void` | - |
 | precision | 精度 | `'year' \| 'month' \| 'day' \| 'hour' \| 'minute' \| 'second' \| 'week' \| 'week-day' \| 'quarter'` | `'day'` |
-| renderLabel | 自定义渲染每列展示的内容。其中 `type` 参数为 `precision` 中的任意值或 `now`，`data` 参数为默认渲染的数字 | `(type: Precision \| 'now', data: number) => ReactNode` | - |
+| renderLabel | 自定义渲染每列展示的内容。其中 `type` 参数为 `precision` 中的任意值或 `now`，`data` 参数为默认渲染的数字 | `(type: Precision \| 'now', data: number, info: { selected: boolean }) => ReactNode` | - |
 | tillNow | 是否展示“至今” | `boolean` | - | 5.27.0 |
 | value | 选中值 | `PickerDate` | - |
 


Test patch:
diff --git a/src/components/date-picker/tests/date-picker.test.tsx b/src/components/date-picker/tests/date-picker.test.tsx
index 398098845..a90edf856 100644
--- a/src/components/date-picker/tests/date-picker.test.tsx
+++ b/src/components/date-picker/tests/date-picker.test.tsx
@@ -218,4 +218,26 @@ describe('DatePicker', () => {
     expect(date.getMonth()).toBe(0)
     expect(date.getDate()).toBe(1)
   })
+
+  test('renderLabel should be work', async () => {
+    const labelRenderer = (
+      type: string,
+      data: number,
+      info: { selected: boolean }
+    ) => {
+      if (info.selected) {
+        return `${type}-selected`
+      }
+      return data.toString()
+    }
+
+    render(<DatePicker visible renderLabel={labelRenderer} />)
+
+    const yearEl = await screen.findByText('year-selected')
+    expect(yearEl).toBeInTheDocument()
+    const monthEl = await screen.findByText('month-selected')
+    expect(monthEl).toBeInTheDocument()
+    const dayEl = await screen.findByText('day-selected')
+    expect(dayEl).toBeInTheDocument()
+  })
 })