Repository: ant-design/ant-design-mobile
Pull request #6244 (2023-07-12 09:40:20)

chore: master merge feature


Patch:
diff --git a/docs/guide/i18n.en.md b/docs/guide/i18n.en.md
index cb1c01666..28805a62c 100644
--- a/docs/guide/i18n.en.md
+++ b/docs/guide/i18n.en.md
@@ -33,6 +33,7 @@ The following languages are currently supported:
 | Danish                | da-DK    |
 | Norwegian (Bokmål)    | nb-NO    |
 | Dutch (Netherlands)   | nl-NL    |
+| Russian (Russia)      | ru-RU    |
 
 See more usage at [ConfigProvider](../components/config-provider).
 
diff --git a/docs/guide/i18n.zh.md b/docs/guide/i18n.zh.md
index a692b6f23..d0e812576 100644
--- a/docs/guide/i18n.zh.md
+++ b/docs/guide/i18n.zh.md
@@ -33,6 +33,7 @@ return (
 | 丹麦语               | da-DK  |
 | 挪威                 | nb-NO  |
 | 荷兰语               | nl-NL  |
+| 俄罗斯语             | ru-RU  |
 
 具体的使用方法请参考 [ConfigProvider](../components/config-provider) 文档。
 
diff --git a/src/components/calendar/convert.ts b/src/components/calendar/convert.ts
index c69226160..11c6eea7d 100644
--- a/src/components/calendar/convert.ts
+++ b/src/components/calendar/convert.ts
@@ -5,12 +5,8 @@ export function convertValueToRange(
   selectionMode: 'single' | 'range' | undefined,
   value: Date | [Date, Date] | null
 ): DateRange {
-  if (selectionMode === undefined) {
-    return null
-  }
-  if (value === null) {
-    return null
-  }
+  if (selectionMode === undefined || value === null) return null
+
   if (Array.isArray(value)) {
     return value
   }
diff --git a/src/components/capsule-tabs/capsule-tabs.tsx b/src/components/capsule-tabs/capsule-tabs.tsx
index 1dc0470e3..8b50f5842 100644
--- a/src/components/capsule-tabs/capsule-tabs.tsx
+++ b/src/components/capsule-tabs/capsule-tabs.tsx
@@ -2,7 +2,7 @@ import React, {
   FC,
   ReactNode,
   ReactElement,
-  ComponentProps,
+  isValidElement,
   useRef,
 } from 'react'
 import classNames from 'classnames'
@@ -25,9 +25,7 @@ export type CapsuleTabProps = {
   children?: ReactNode
 } & NativeProps
 
-export const CapsuleTab: FC<CapsuleTabProps> = () => {
-  return null
-}
+export const CapsuleTab: FC<CapsuleTabProps> = () => null
 
 export type CapsuleTabsProps = {
   activeKey?: string | null
@@ -42,10 +40,10 @@ export const CapsuleTabs: FC<CapsuleTabsProps> = props => {
   const keyToIndexRecord: Record<string, number> = {}
   let firstActiveKey: string | null = null
 
-  const panes: ReactElement<ComponentProps<typeof CapsuleTab>>[] = []
+  const panes: ReactElement<CapsuleTabProps>[] = []
 
   traverseReactNode(props.children, (child, index) => {
-    if (!React.isValidElement(child)) return
+    if (!isValidElement<CapsuleTabProps>(child)) return
     const key = child.key
     if (typeof key !== 'string') return
     if (index === 0) {
diff --git a/src/components/checkbox/checkbox.tsx b/src/components/checkbox/checkbox.tsx
index fa0f713e7..f3c7f8719 100644
--- a/src/components/checkbox/checkbox.tsx
+++ b/src/components/checkbox/checkbox.tsx
@@ -25,6 +25,7 @@ export type CheckboxProps = {
   id?: string
   icon?: (checked: boolean, indeterminate: boolean) => React.ReactNode
   children?: React.ReactNode
+  onClick?: (event: React.MouseEvent<HTMLLabelElement, MouseEvent>) => void
 } & NativeProps<'--icon-size' | '--font-size' | '--gap'>
 
 const defaultProps = {
@@ -110,6 +111,7 @@ export const Checkbox = forwardRef<CheckboxRef, CheckboxProps>((p, ref) => {
   return withNativeProps(
     props,
     <label
+      onClick={props.onClick}
       className={classNames(classPrefix, {
         [`${classPrefix}-checked`]: checked && !props.indeterminate,
         [`${classPrefix}-indeterminate`]: props.indeterminate,
diff --git a/src/components/checkbox/index.en.md b/src/components/checkbox/index.en.md
index fd79b3cb8..4b50d679b 100644
--- a/src/components/checkbox/index.en.md
+++ b/src/components/checkbox/index.en.md
@@ -28,11 +28,12 @@ type CheckboxValue = string | number
 | block | Whether to render as a block-level element | `boolean` | `false` |
 | checked | To specify whether selected or not currently | `boolean` | `false` |
 | defaultChecked | Selected or not initially | `boolean` | `false` |
-| disabled | Disabled state | `boolean` | `false` |
+| disabled | Failure state | `boolean` | `false` |
 | icon | The customized `icon` | `(checked: boolean, indeterminate: boolean) => React.ReactNode` | - |
 | id | The id of the input element, often used in conjunction with the label | `string` | - |
 | indeterminate | To set the `indeterminate` state, only responsible for style control | `boolean` | `false` |
 | onChange | Callback function when changing | `(val: boolean) => void` | - |
+| onClick | Checkbox's click event | `(event: React.MouseEvent<HTMLLabelElement, MouseEvent>) => void` | - |
 | value | The value carrying identification, used in `Group` mode | `CheckboxValue` | - |
 
 ### Ref
diff --git a/src/components/checkbox/index.zh.md b/src/components/checkbox/index.zh.md
index 5b14d5ff3..8278e1345 100644
--- a/src/components/checkbox/index.zh.md
+++ b/src/components/checkbox/index.zh.md
@@ -28,11 +28,12 @@ type CheckboxValue = string | number
 | block | 是否渲染为块级元素 | `boolean` | `false` |
 | checked | 指定当前是否选中 | `boolean` | `false` |
 | defaultChecked | 初始是否选中 | `boolean` | `false` |
-| disabled | 禁用状态 | `boolean` | `false` |
+| disabled | 失效状态 | `boolean` | `false` |
 | icon | 自定义 `icon` 图标 | `(checked: boolean, indeterminate: boolean) => React.ReactNode` | - |
 | id | `input` 元素的 `id`，常用来配合 `label` 使用 | `string` | - |
 | indeterminate | 设置 `indeterminate` 状态，只负责样式控制 | `boolean` | `false` |
 | onChange | 变化时回调函数 | `(val: boolean) => void` | - |
+| onClick | Checkbox 的点击事件 | `(event: React.MouseEvent<HTMLLabelElement, MouseEvent>) => void` | - |
 | value | 携带的标识值，用于 `Group` 模式 | `CheckboxValue` | - |
 
 ### Ref
diff --git a/src/components/collapse/collapse.tsx b/src/components/collapse/collapse.tsx
index 0011063e4..02190e313 100644
--- a/src/components/collapse/collapse.tsx
+++ b/src/components/collapse/collapse.tsx
@@ -1,4 +1,4 @@
-import React, { FC, ReactElement, ComponentProps, useRef } from 'react'
+import React, { FC, ReactElement, isValidElement, useRef } from 'react'
 import { NativeProps, withNativeProps } from '../../utils/native-props'
 import List from '../list'
 import { DownOutline } from 'antd-mobile-icons'
@@ -120,11 +120,12 @@ export type CollapseProps = (
 } & NativeProps
 
 export const Collapse: FC<CollapseProps> = props => {
-  const panels: ReactElement<ComponentProps<typeof CollapsePanel>>[] = []
+  const panels: ReactElement<CollapsePanelProps>[] = []
   traverseReactNode(props.children, child => {
-    if (!React.isValidElement(child)) return
+    if (!isValidElement<CollapsePanelProps>(child)) return
     const key = child.key
     if (typeof key !== 'string') return
+
     panels.push(child)
   })
 
diff --git a/src/components/date-picker-view/date-picker-view.tsx b/src/components/date-picker-view/date-picker-view.tsx
index 89a4c518b..d876811a6 100644
--- a/src/components/date-picker-view/date-picker-view.tsx
+++ b/src/components/date-picker-view/date-picker-view.tsx
@@ -14,6 +14,8 @@ import type {
   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'
 
 export type RenderLabel = (type: Precision | 'now', data: number) => ReactNode
 
@@ -21,14 +23,15 @@ export type DatePickerViewProps = Pick<
   PickerViewProps,
   'style' | 'mouseWheel' | 'loading' | 'loadingContent'
 > & {
-  value?: Date
-  defaultValue?: Date
-  onChange?: (value: Date) => void
-  min?: Date
-  max?: Date
+  value?: PickerDate
+  defaultValue?: PickerDate
+  onChange?: (value: PickerDate) => void
+  min?: PickerDate
+  max?: PickerDate
   precision?: Precision
   renderLabel?: RenderLabel
   filter?: DatePickerFilter
+  tillNow?: boolean
 } & NativeProps
 
 const thisYear = new Date().getFullYear()
@@ -43,17 +46,20 @@ export const DatePickerView: FC<DatePickerViewProps> = p => {
   const props = mergeProps(defaultProps, p)
   const { renderLabel } = props
 
-  const [value, setValue] = usePropsValue<Date | null>({
+  const [value, setValue] = usePropsValue<PickerDate | null>({
     value: props.value,
     defaultValue: props.defaultValue ?? null,
   })
 
   const mergedRenderLabel = useRenderLabel(renderLabel)
 
-  const pickerValue = useMemo(
-    () => convertDateToStringArray(value, props.precision),
-    [value, props.precision]
-  )
+  const pickerValue = useMemo(() => {
+    if (value?.tillNow) {
+      return [TILL_NOW, null, null]
+    }
+
+    return convertDateToStringArray(value, props.precision)
+  }, [value, props.precision])
 
   const onChange = useCallback(
     (val: PickerValue[]) => {
@@ -76,7 +82,8 @@ export const DatePickerView: FC<DatePickerViewProps> = p => {
           props.max,
           props.precision,
           mergedRenderLabel,
-          props.filter
+          props.filter,
+          props.tillNow
         )
       }
       loading={props.loading}
diff --git a/src/components/date-picker-view/demos/demo1.tsx b/src/components/date-picker-view/demos/demo1.tsx
index 8ccc72492..ef8016d85 100644
--- a/src/components/date-picker-view/demos/demo1.tsx
+++ b/src/components/date-picker-view/demos/demo1.tsx
@@ -51,6 +51,15 @@ export default () => {
           filter={dateFilter}
         />
       </DemoBlock>
+
+      <DemoBlock title='至今' padding='0'>
+        <DatePickerView
+          defaultValue={now}
+          max={now}
+          tillNow
+          onChange={val => console.log(`Till Now: ${!!val.tillNow}`)}
+        />
+      </DemoBlock>
     </>
   )
 }
diff --git a/src/components/date-picker/date-picker-date-utils.ts b/src/components/date-picker/date-picker-date-utils.ts
index 5ad0f23d0..94624b01a 100644
--- a/src/components/date-picker/date-picker-date-utils.ts
+++ b/src/components/date-picker/date-picker-date-utils.ts
@@ -104,12 +104,10 @@ export function generateDatePickerColumns(
     const upper = maxYear
     const years = generateColumn(lower, upper, 'year')
     ret.push(
-      years.map(v => {
-        return {
-          label: renderLabel('year', v),
-          value: v.toString(),
-        }
-      })
+      years.map(v => ({
+        label: renderLabel('year', v),
+        value: v.toString(),
+      }))
     )
   }
 
@@ -118,12 +116,10 @@ export function generateDatePickerColumns(
     const upper = isInMaxYear ? maxMonth : 12
     const months = generateColumn(lower, upper, 'month')
     ret.push(
-      months.map(v => {
-        return {
-          label: renderLabel('month', v),
-          value: v.toString(),
-        }
-      })
+      months.map(v => ({
+        label: renderLabel('month', v),
+        value: v.toString(),
+      }))
     )
   }
   if (rank >= precisionRankRecord.day) {
@@ -131,12 +127,10 @@ export function generateDatePickerColumns(
     const upper = isInMaxMonth ? maxDay : firstDayInSelectedMonth.daysInMonth()
     const days = generateColumn(lower, upper, 'day')
     ret.push(
-      days.map(v => {
-        return {
-          label: renderLabel('day', v),
-          value: v.toString(),
-        }
-      })
+      days.map(v => ({
+        label: renderLabel('day', v),
+        value: v.toString(),
+      }))
     )
   }
   if (rank >= precisionRankRecord.hour) {
@@ -144,12 +138,10 @@ export function generateDatePickerColumns(
     const upper = isInMaxDay ? maxHour : 23
     const hours = generateColumn(lower, upper, 'hour')
     ret.push(
-      hours.map(v => {
-        return {
-          label: renderLabel('hour', v),
-          value: v.toString(),
-        }
-      })
+      hours.map(v => ({
+        label: renderLabel('hour', v),
+        value: v.toString(),
+      }))
     )
   }
   if (rank >= precisionRankRecord.minute) {
@@ -157,12 +149,10 @@ export function generateDatePickerColumns(
     const upper = isInMaxHour ? maxMinute : 59
     const minutes = generateColumn(lower, upper, 'minute')
     ret.push(
-      minutes.map(v => {
-        return {
-          label: renderLabel('minute', v),
-          value: v.toString(),
-        }
-      })
+      minutes.map(v => ({
+        label: renderLabel('minute', v),
+        value: v.toString(),
+      }))
     )
   }
   if (rank >= precisionRankRecord.second) {
@@ -170,12 +160,10 @@ export function generateDatePickerColumns(
     const upper = isInMaxMinute ? maxSecond : 59
     const seconds = generateColumn(lower, upper, 'second')
     ret.push(
-      seconds.map(v => {
-        return {
-          label: renderLabel('second', v),
-          value: v.toString(),
-        }
-      })
+      seconds.map(v => ({
+        label: renderLabel('second', 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 51b9b0db5..d295cb168 100644
--- a/src/components/date-picker/date-picker-week-utils.ts
+++ b/src/components/date-picker/date-picker-week-utils.ts
@@ -77,12 +77,10 @@ export function generateDatePickerColumns(
     const upper = maxYear
     const years = generateColumn(lower, upper, 'year')
     ret.push(
-      years.map(v => {
-        return {
-          label: renderLabel('year', v),
-          value: v.toString(),
-        }
-      })
+      years.map(v => ({
+        label: renderLabel('year', v),
+        value: v.toString(),
+      }))
     )
   }
 
@@ -91,12 +89,10 @@ export function generateDatePickerColumns(
     const upper = isInMaxYear ? maxWeek : selectedYearWeeks
     const weeks = generateColumn(lower, upper, 'week')
     ret.push(
-      weeks.map(v => {
-        return {
-          label: renderLabel('week', v),
-          value: v.toString(),
-        }
-      })
+      weeks.map(v => ({
+        label: renderLabel('week', v),
+        value: v.toString(),
+      }))
     )
   }
   if (rank >= precisionRankRecord['week-day']) {
@@ -104,12 +100,10 @@ export function generateDatePickerColumns(
     const upper = isInMaxWeek ? maxWeekday : 7
     const weeks = generateColumn(lower, upper, 'week-day')
     ret.push(
-      weeks.map(v => {
-        return {
-          label: renderLabel('week-day', v),
-          value: v.toString(),
-        }
-      })
+      weeks.map(v => ({
+        label: renderLabel('week-day', v),
+        value: v.toString(),
+      }))
     )
   }
 
diff --git a/src/components/dropdown/dropdown.tsx b/src/components/dropdown/dropdown.tsx
index ed60fe132..ae76dc812 100644
--- a/src/components/dropdown/dropdown.tsx
+++ b/src/components/dropdown/dropdown.tsx
@@ -9,6 +9,7 @@ import React, {
   useState,
   forwardRef,
   useImperativeHandle,
+  isValidElement,
 } from 'react'
 import Popup, { PopupProps } from '../popup'
 import Item, { ItemChildrenWrap } from './item'
@@ -25,7 +26,6 @@ export type DropdownProps = {
   closeOnMaskClick?: boolean
   closeOnClickAway?: boolean
   onChange?: (key: string | null) => void
-  // mask?: boolean;
   arrow?: React.ReactNode
   getContainer?: PopupProps['getContainer']
 } & NativeProps
@@ -84,7 +84,7 @@ const Dropdown = forwardRef<
   let popupForceRender = false
   const items: ReactElement<ComponentProps<typeof Item>>[] = []
   const navs = React.Children.map(props.children, child => {
-    if (React.isValidElement(child)) {
+    if (isValidElement<ComponentProps<typeof Item>>(child)) {
       const childProps = {
         ...child.props,
         onClick: () => {
diff --git a/src/components/footer/footer.tsx b/src/components/footer/footer.tsx
index 90e337244..88e9a419c 100644
--- a/src/components/footer/footer.tsx
+++ b/src/components/footer/footer.tsx
@@ -60,40 +60,36 @@ export const Footer: FC<FooterProps> = p => {
           <Divider>{label}</Divider>
         </div>
       )}
-      {links && links.length > 0 && (
+      {!!links?.length && (
         <div className={`${classPrefix}-links`}>
-          {links.map((link, index) => {
-            return (
-              <React.Fragment key={index}>
-                <a
-                  href={link.href}
-                  rel='noopener noreferrer'
-                  onClick={event => clickLinkItem(link, index, event)}
-                >
-                  {link.text}
-                </a>
-                {index !== links.length - 1 && <Divider direction='vertical' />}
-              </React.Fragment>
-            )
-          })}
+          {links.map((link, index) => (
+            <React.Fragment key={index}>
+              <a
+                href={link.href}
+                rel='noopener noreferrer'
+                onClick={event => clickLinkItem(link, index, event)}
+              >
+                {link.text}
+              </a>
+              {index !== links.length - 1 && <Divider direction='vertical' />}
+            </React.Fragment>
+          ))}
         </div>
       )}
       {content && <div className={`${classPrefix}-content`}>{content}</div>}
       {chips && chips.length > 0 && (
         <div className={`${classPrefix}-chips`}>
-          {chips.map((chip, index) => {
-            return (
-              <div
-                key={index}
-                onClick={() => clickChipItem(chip, index)}
-                className={classNames(`${classPrefix}-chip`, {
-                  [`${classPrefix}-chip-link`]: chip.type === 'link',
-                })}
-              >
-                {chip.text}
-              </div>
-            )
-          })}
+          {chips.map((chip, index) => (
+            <div
+              key={index}
+              onClick={() => clickChipItem(chip, index)}
+              className={classNames(`${classPrefix}-chip`, {
+                [`${classPrefix}-chip-link`]: chip.type === 'link',
+              })}
+            >
+              {chip.text}
+            </div>
+          ))}
         </div>
       )}
     </div>
diff --git a/src/components/form/form-array.tsx b/src/components/form/form-array.tsx
index 1f84b1eb7..64c07a5ed 100644
--- a/src/components/form/form-array.tsx
+++ b/src/components/form/form-array.tsx
@@ -16,7 +16,6 @@ export interface FormArrayOperation {
 
 export interface FormArrayProps {
   name: string | number | (string | number)[]
-  // rules?: ValidatorRule[]
   initialValue?: any[]
   renderHeader?: (
     field: FormArrayField,
diff --git a/src/components/image-uploader/image-uploader.tsx b/src/components/image-uploader/image-uploader.tsx
index 94c668730..c38bd34d3 100644
--- a/src/components/image-uploader/image-uploader.tsx
+++ b/src/components/image-uploader/image-uploader.tsx
@@ -159,9 +159,7 @@ export const ImageUploader: FC<ImageUploaderProps> = p => {
     e.target.value = '' // HACK: fix the same file doesn't trigger onChange
 
     if (props.beforeUpload) {
-      const postFiles = files.map(file => {
-        return processFile(file, files)
-      })
+      const postFiles = files.map(file => processFile(file, files))
 
       await Promise.all(postFiles).then(filesList => {
         files = filesList.filter(Boolean) as File[]
diff --git a/src/components/jumbo-tabs/jumbo-tabs.tsx b/src/components/jumbo-tabs/jumbo-tabs.tsx
index a0885837d..176c5026b 100644
--- a/src/components/jumbo-tabs/jumbo-tabs.tsx
+++ b/src/components/jumbo-tabs/jumbo-tabs.tsx
@@ -2,7 +2,7 @@ import React, {
   FC,
   ReactNode,
   ReactElement,
-  ComponentProps,
+  isValidElement,
   useRef,
 } from 'react'
 import classNames from 'classnames'
@@ -43,12 +43,13 @@ export const JumboTabs: FC<JumboTabsProps> = props => {
   const keyToIndexRecord: Record<string, number> = {}
   let firstActiveKey: string | null = null
 
-  const panes: ReactElement<ComponentProps<typeof JumboTab>>[] = []
+  const panes: ReactElement<JumboTabProps>[] = []
 
   traverseReactNode(props.children, (child, index) => {
-    if (!React.isValidElement(child)) return
+    if (!isValidElement<JumboTabProps>(child)) return
     const key = child.key
     if (typeof key !== 'string') return
+
     if (index === 0) {
       firstActiveKey = key
     }
diff --git a/src/components/modal/modal.tsx b/src/components/modal/modal.tsx
index 22d0d22db..59a2e0900 100644
--- a/src/components/modal/modal.tsx
+++ b/src/components/modal/modal.tsx
@@ -72,23 +72,21 @@ export const Modal: FC<ModalProps> = p => {
           props.actions.length === 0 && cls('footer-empty')
         )}
       >
-        {props.actions.map((action, index) => {
-          return (
-            <ModalActionButton
-              key={action.key}
-              action={action}
-              onAction={async () => {
-                await Promise.all([
-                  action.onClick?.(),
-                  props.onAction?.(action, index),
-                ])
-                if (props.closeOnAction) {
-                  props.onClose?.()
-                }
-              }}
-            />
-          )
-        })}
+        {props.actions.map((action, index) => (
+          <ModalActionButton
+            key={action.key}
+            action={action}
+            onAction={async () => {
+              await Promise.all([
+                action.onClick?.(),
+                props.onAction?.(action, index),
+              ])
+              if (props.closeOnAction) {
+                props.onClose?.()
+              }
+            }}
+          />
+        ))}
       </Space>
     </>
   )
diff --git a/src/components/picker-view/index.en.md b/src/components/picker-view/index.en.md
index 77d20e05b..4a5558a38 100644
--- a/src/components/picker-view/index.en.md
+++ b/src/components/picker-view/index.en.md
@@ -69,19 +69,26 @@ DatePickerView is the content area of [DatePicker](/components/picker/#datepicke
 
 ### Props
 
-| Name | Description | Type | Default |
-| --- | --- | --- | --- |
-| defaultValue | Default selected options | `Date` | - |
+```typescript
+type PickerDate = Date & {
+  tillNow?: boolean
+}
+```
+
+| Name | Description | Type | Default | Version |
+| --- | --- | --- | --- | --- |
+| defaultValue | Default selected options | `PickerDate` | - |
 | filter | Filter available time | `DatePickerFilter` | - |
-| max | Max value | `Date` | ten years later |
-| min | Minimum value | `Date` | ten years ago |
+| max | Max value | `PickerDate` | ten years later |
+| min | Minimum value | `PickerDate` | ten years ago |
 | mouseWheel | Whether to allow interact with mouse wheel | `boolean` | `false` |
-| onChange | Triggered when the options are changed | `(value: Date) => void` | - |
+| onChange | Triggered when the options are changed | `(value: PickerDate) => void` | - |
 | precision | Precision | `'year' \| 'month' \| 'day' \| 'hour' \| 'minute' \| 'second' \| 'week' \| 'week-day'` | `'day'` |
 | renderLabel | The function to custom rendering the label shown on a column. `type` means any value in `precision`, `data` means the default number | `(type: string, data: number) => ReactNode` | - |
-| value | Selected options | `Date` | - |
+| value | Selected options | `PickerDate` | - |
 | loading | Should the Picker displays as loading state | `boolean` | `false` |
 | loadingContent | The loading content displayed in loading state | `ReactNode` | `provide a default SpinLoading content` |
+| tillNow | Show till now in list | `boolean` | - | 5.32.0 |
 
 For the type definition and usage of `DatePickerFilter`, please refer to the document of [DatePicker](/components/picker#datepicker).
 
diff --git a/src/components/picker-view/index.zh.md b/src/components/picker-view/index.zh.md
index 21530f0c4..69dcb6837 100644
--- a/src/components/picker-view/index.zh.md
+++ b/src/components/picker-view/index.zh.md
@@ -69,19 +69,26 @@ DatePickerView 是 [DatePicker](/zh/components/picker/#datepicker) 的内容区
 
 ### 属性
 
-| 属性 | 说明 | 类型 | 默认值 |
-| --- | --- | --- | --- |
-| defaultValue | 默认选中项 | `Date` | - |
+```typescript
+type PickerDate = Date & {
+  tillNow?: boolean
+}
+```
+
+| 属性 | 说明 | 类型 | 默认值 | 版本 |
+| --- | --- | --- | --- | --- |
+| defaultValue | 默认选中项 | `PickerDate` | - |
 | filter | 过滤可供选择的时间 | `DatePickerFilter` | - |
-| max | 最大值 | `Date` | 十年后 |
-| min | 最小值 | `Date` | 十年前 |
+| max | 最大值 | `PickerDate` | 十年后 |
+| min | 最小值 | `PickerDate` | 十年前 |
 | mouseWheel | 是否允许通过鼠标滚轮进行选择 | `boolean` | `false` |
-| onChange | 选项改变时触发 | `(value: Date) => void` | - |
+| onChange | 选项改变时触发 | `(value: PickerDate) => void` | - |
 | precision | 精度 | `'year' \| 'month' \| 'day' \| 'hour' \| 'minute' \| 'second' \| 'week' \| 'week-day'` | `'day'` |
 | renderLabel | 自定义渲染每列展示的内容。其中 `type` 参数为 `precision` 中的任意值，`data` 参数为默认渲染的数字 | `(type: string, data: number) => ReactNode` | - |
-| value | 选中项 | `Date` | - |
+| value | 选中项 | `PickerDate` | - |
 | loading | 是否处于加载状态 | `boolean` | `false` |
 | loadingContent | 加载状态下展示的内容 | `ReactNode` | `默认提供了转圈加载中的加载效果` |
+| tillNow | 是否展示“至今” | `boolean` | - | 5.32.0 |
 
 关于 `DatePickerFilter` 的类型定义和使用，请参考 [DatePicker](/zh/components/picker#datepicker) 的文档。
 
diff --git a/src/components/picker/index.zh.md b/src/components/picker/index.zh.md
index 79876746c..4b1b100d1 100644
--- a/src/components/picker/index.zh.md
+++ b/src/components/picker/index.zh.md
@@ -155,7 +155,7 @@ type PickerDate = Date & {
 | 属性 | 说明 | 类型 | 默认值 | 版本 |
 | --- | --- | --- | --- | --- |
 | children | 所选项的渲染函数 | `(value: PickerDate, actions: PickerActions) => ReactNode` | - |
-| defaultValue | 默认选中值 | `PickerDate` | - |
+| defaultValue | 选中值 | `PickerDate` | - |
 | destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `false` |
 | filter | 过滤可供选择的时间 | `DatePickerFilter` | - |
 | forceRender | 强制渲染内容 | `boolean` | `false` |
diff --git a/src/components/popover/index.en.md b/src/components/popover/index.en.md
index 54fcd6145..b9cb1c3e4 100644
--- a/src/components/popover/index.en.md
+++ b/src/components/popover/index.en.md
@@ -22,7 +22,7 @@ Navigation applicable to functions can only be evoked by the icons on the naviga
 
 | Name | Description | Type | Default |
 | --- | --- | --- | --- |
-| children | The element that triggered the Popover | `React.ReactElement` | - |
+| children | The element that triggered the popover | `React.ReactElement` | - |
 | content | The content of the Popover | `React.ReactNode` | - |
 | defaultVisible | Whether to show or hide by default | `boolean` | `false` |
 | destroyOnHide | When hiding, whether to destroy the content of `tooltip` | `boolean` | `false` |
diff --git a/src/components/popover/index.zh.md b/src/components/popover/index.zh.md
index b09e4b0a4..d28aa5e41 100644
--- a/src/components/popover/index.zh.md
+++ b/src/components/popover/index.zh.md
@@ -22,7 +22,7 @@
 
 | 属性 | 说明 | 类型 | 默认值 |
 | --- | --- | --- | --- |
-| children | 触发 `Popover` 的元素 | `React.ReactElement` | - |
+| children | 触发 `popover` 的元素 | `React.ReactElement` | - |
 | content | 弹出内容 | `React.ReactNode` | - |
 | defaultVisible | 默认是否显隐 | `boolean` | `false` |
 | destroyOnHide | 隐藏时，是否销毁 `tooltip` 内容 | `boolean` | `false` |
diff --git a/src/components/popover/popover.tsx b/src/components/popover/popover.tsx
index 036a17b86..3a56c4c39 100644
--- a/src/components/popover/popover.tsx
+++ b/src/components/popover/popover.tsx
@@ -77,13 +77,11 @@ export const Popover = forwardRef<PopoverRef, PopoverProps>((p, ref) => {
 
   useImperativeHandle(
     ref,
-    () => {
-      return {
-        show: () => setVisible(true),
-        hide: () => setVisible(false),
-        visible,
-      }
-    },
+    () => ({
+      show: () => setVisible(true),
+      hide: () => setVisible(false),
+      visible,
+    }),
     [visible]
   )
 
diff --git a/src/components/popup/popup.tsx b/src/components/popup/popup.tsx
index ab3e7a1b1..8726b3af3 100644
--- a/src/components/popup/popup.tsx
+++ b/src/components/popup/popup.tsx
@@ -32,7 +32,6 @@ const defaultProps = {
 
 export const Popup: FC<PopupProps> = p => {
   const props = mergeProps(defaultProps, p)
-  const { locale } = useConfig()
 
   const bodyCls = classNames(
     `${classPrefix}-body`,
@@ -40,16 +39,17 @@ export const Popup: FC<PopupProps> = p => {
     `${classPrefix}-body-position-${props.position}`
   )
 
+  const { locale } = useConfig()
   const [active, setActive] = useState(props.visible)
+  const ref = useRef<HTMLDivElement>(null)
+  useLockScroll(ref, props.disableBodyScroll && active ? 'strict' : false)
+
   useIsomorphicLayoutEffect(() => {
     if (props.visible) {
       setActive(true)
     }
   }, [props.visible])
 
-  const ref = useRef<HTMLDivElement>(null)
-  useLockScroll(ref, props.disableBodyScroll && active ? 'strict' : false)
-
   const unmountedRef = useUnmountedRef()
   const { percent } = useSpring({
     percent: props.visible ? 0 : 100,
diff --git a/src/components/progress-bar/index.zh.md b/src/components/progress-bar/index.zh.md
index abcd14a5d..02320286d 100644
--- a/src/components/progress-bar/index.zh.md
+++ b/src/components/progress-bar/index.zh.md
@@ -18,7 +18,7 @@
 
 | 参数 | 说明 | 类型 | 默认值 |
 | --- | --- | --- | --- |
-| percent | 进度条百分比 | `number` | `0` |
+| percent | 百分比 | `number` | `0` |
 | rounded | 是否圆角 | `boolean` | `true` |
 | text | 是否显示进度文字，支持自定义渲染内容 | `boolean \| ReactNode \| ((percent: number) => ReactNode)` | `false` |
 
diff --git a/src/components/progress-circle/index.zh.md b/src/components/progress-circle/index.zh.md
index 1996ed9d7..7e9b6e27e 100644
--- a/src/components/progress-circle/index.zh.md
+++ b/src/components/progress-circle/index.zh.md
@@ -14,10 +14,10 @@
 
 ### 属性
 
-| 参数     | 说明         | 类型              | 默认值 |
-| -------- | ------------ | ----------------- | ------ |
-| children | 自定义信息   | `React.ReactNode` | -      |
-| percent  | 进度圈百分比 | `number`          | `0`    |
+| 参数     | 说明       | 类型              | 默认值 |
+| -------- | ---------- | ----------------- | ------ |
+| children | 自定义信息 | `React.ReactNode` | -      |
+| percent  | 百分比     | `number`          | `0`    |
 
 ### CSS 变量
 
diff --git a/src/components/radio/index.en.md b/src/components/radio/index.en.md
index 2d5594cf3..74037c821 100644
--- a/src/components/radio/index.en.md
+++ b/src/components/radio/index.en.md
@@ -31,6 +31,7 @@ type RadioValue = string | number
 | icon | Customized `icon` icon | `(checked: boolean) => React.ReactNode` | - |
 | id | The id of the input element, often used in conjunction with the label | `string` | - |
 | onChange | Callback function when checked is changed | `(val: boolean) => void` | - |
+| onClick | Radio's click event | `(event: React.MouseEvent<HTMLLabelElement, MouseEvent>) => void` | - |
 | value | Value is carrying identification, used in `Group` mode | `RadioValue` | - |
 
 ### Radio.Group
diff --git a/src/components/radio/index.zh.md b/src/components/radio/index.zh.md
index 5132d16f4..b9d448e89 100644
--- a/src/components/radio/index.zh.md
+++ b/src/components/radio/index.zh.md
@@ -27,10 +27,11 @@ type RadioValue = string | number
 | block | 是否渲染为块级元素 | `boolean` | `false` |
 | checked | 指定当前是否选中 | `boolean` | `false` |
 | defaultChecked | 初始是否选中 | `boolean` | `false` |
-| disabled | 禁用状态 | `boolean` | `false` |
+| disabled | 失效状态 | `boolean` | `false` |
 | icon | 自定义 `icon` 图标 | `(checked: boolean) => React.ReactNode` | - |
 | id | `input` 元素的 `id`，常用来配合 `label` 使用 | `string` | - |
 | onChange | 变化时回调函数 | `(val: boolean) => void` | - |
+| onClick | Radio 的点击事件 | `(event: React.MouseEvent<HTMLLabelElement, MouseEvent>) => void` | - |
 | value | 携带的标识值，用于 `Group` 模式 | `RadioValue` | - |
 
 ### Radio.Group
diff --git a/src/components/radio/radio.tsx b/src/components/radio/radio.tsx
index c5457d199..b50623f15 100644
--- a/src/components/radio/radio.tsx
+++ b/src/components/radio/radio.tsx
@@ -23,6 +23,7 @@ export type RadioProps = {
   id?: string
   icon?: (checked: boolean) => React.ReactNode
   children?: React.ReactNode
+  onClick?: (event: React.MouseEvent<HTMLLabelElement, MouseEvent>) => void
 } & NativeProps<'--icon-size' | '--font-size' | '--gap'>
 
 const defaultProps = {
@@ -86,6 +87,7 @@ export const Radio: FC<RadioProps> = p => {
   return withNativeProps(
     props,
     <label
+      onClick={props.onClick}
       className={classNames(classPrefix, {
         [`${classPrefix}-checked`]: checked,
         [`${classPrefix}-disabled`]: disabled,
diff --git a/src/components/rate/star.tsx b/src/components/rate/star.tsx
index cb640c430..84ff30097 100644
--- a/src/components/rate/star.tsx
+++ b/src/components/rate/star.tsx
@@ -1,5 +1,5 @@
 import React from 'react'
-import { FC } from 'react'
+import type { FC } from 'react'
 
 export const Star: FC = () => {
   return (
diff --git a/src/components/result/result.tsx b/src/components/result/result.tsx
index b5b9c1a3c..a1311b8fb 100644
--- a/src/components/result/result.tsx
+++ b/src/components/result/result.tsx
@@ -42,9 +42,9 @@ export const Result: FC<ResultProps> = p => {
     <div className={classNames(classPrefix, `${classPrefix}-${status}`)}>
       <div className={`${classPrefix}-icon`}>{resultIcon}</div>
       <div className={`${classPrefix}-title`}>{title}</div>
-      {description ? (
+      {!!description && (
         <div className={`${classPrefix}-description`}>{description}</div>
-      ) : null}
+      )}
     </div>
   )
 }
diff --git a/src/components/safe-area/safe-area.tsx b/src/components/safe-area/safe-area.tsx
index cdf9ef580..ef1d3e7fa 100644
--- a/src/components/safe-area/safe-area.tsx
+++ b/src/components/safe-area/safe-area.tsx
@@ -1,6 +1,7 @@
-import { FC } from 'react'
-import { NativeProps, withNativeProps } from '../../utils/native-props'
 import React from 'react'
+import type { FC } from 'react'
+import { NativeProps, withNativeProps } from '../../utils/native-props'
+
 import classNames from 'classnames'
 
 const classPrefix = 'adm-safe-area'
diff --git a/src/components/selector/index.en.md b/src/components/selector/index.en.md
index 4f317e104..a2d27b57c 100644
--- a/src/components/selector/index.en.md
+++ b/src/components/selector/index.en.md
@@ -20,7 +20,7 @@ Provides multiple options for the user to choose from, typically used in filters
 | --- | --- | --- | --- |
 | columns | Number of the displayed columns (Note that `grid` layout not support in IOS 9) | `number` | - |
 | defaultValue | Selected value by default | `SelectorValue[]` | `[]` |
-| disabled | Whether to all disable selecting | `boolean` | `false` |
+| disabled | Whether to disable selecting | `boolean` | `false` |
 | multiple | Whether to allow multiple selections | `boolean` | `false` |
 | onChange | Triggered when the value is changed | `(value: SelectorValue[], extend: { items: SelectorOption[] }) => void` | - |
 | options | Optional selector | `SelectorOption[]` | - |
diff --git a/src/components/selector/index.zh.md b/src/components/selector/index.zh.md
index f949133f3..bc1fb1e72 100644
--- a/src/components/selector/index.zh.md
+++ b/src/components/selector/index.zh.md
@@ -20,7 +20,7 @@
 | --- | --- | --- | --- |
 | columns | 列数（注意 `grid` 布局在 IOS 9 下不支持） | `number` | - |
 | defaultValue | 默认项 | `SelectorValue[]` | `[]` |
-| disabled | 是否全部禁止选中 | `boolean` | `false` |
+| disabled | 是否全局禁止选中 | `boolean` | `false` |
 | multiple | 是否允许多选 | `boolean` | `false` |
 | onChange | 选项改变时触发 | `(value: SelectorValue[], extend: { items: SelectorOption[] }) => void` | - |
 | options | 可选项 | `SelectorOption[]` | - |
diff --git a/src/components/side-bar/side-bar.tsx b/src/components/side-bar/side-bar.tsx
index cce90d434..e5243b4c9 100644
--- a/src/components/side-bar/side-bar.tsx
+++ b/src/components/side-bar/side-bar.tsx
@@ -1,5 +1,4 @@
-import { FC, ReactNode, ReactElement, ComponentProps } from 'react'
-import React from 'react'
+import React, { FC, ReactNode, ReactElement, isValidElement } from 'react'
 import classNames from 'classnames'
 import Badge, { BadgeProps } from '../badge'
 import { NativeProps, withNativeProps } from '../../utils/native-props'
@@ -32,12 +31,13 @@ export type SideBarProps = {
 export const SideBar: FC<SideBarProps> = props => {
   let firstActiveKey: string | null = null
 
-  const items: ReactElement<ComponentProps<typeof SideBarItem>>[] = []
+  const items: ReactElement<SideBarItemProps>[] = []
 
   traverseReactNode(props.children, (child, index) => {
-    if (!React.isValidElement(child)) return
+    if (!isValidElement<SideBarItemProps>(child)) return
     const key = child.key
     if (typeof key !== 'string') return
+
     if (index === 0) {
       firstActiveKey = key
     }
diff --git a/src/components/skeleton/skeleton.tsx b/src/components/skeleton/skeleton.tsx
index 5fbbd81d8..5c08f4efb 100644
--- a/src/components/skeleton/skeleton.tsx
+++ b/src/components/skeleton/skeleton.tsx
@@ -1,5 +1,5 @@
-import { FC } from 'react'
 import React from 'react'
+import type { FC } from 'react'
 import { NativeProps, withNativeProps } from '../../utils/native-props'
 import classNames from 'classnames'
 import { generateIntArray } from '../../utils/generate-int-array'
diff --git a/src/components/stepper/index.en.md b/src/components/stepper/index.en.md
index 51dd23898..fa958229d 100644
--- a/src/components/stepper/index.en.md
+++ b/src/components/stepper/index.en.md
@@ -32,7 +32,7 @@ It is suitable for inputting and adjusting the current value within a certain ra
 | onChange | Callback when value is changed | `(value: number \| null) => void` | - |
 | onFocus | Triggered when the input get focus | `(e: React.FocusEvent<HTMLInputElement>) => void` | - |
 | parser | Parse input text into number which should work with `formatter` | `(text: string) => number` | - | 5.26.0 |
-| step | The value to increase or decrease each time, can be a decimal | `number` | `1` |
+| step | Change the number of steps each time, it can be a decimal | `number` | `1` |
 | stringMode | Set value as string to support high precision decimals. Will set `defaultValue`,`value`, `min`, `max`, `onChange` to `string` type | `boolean` | `false` | 5.27.0 |
 | value | Current number, controlled value | `number \| null` | - |
 
diff --git a/src/components/stepper/index.zh.md b/src/components/stepper/index.zh.md
index 77832e9a8..1af978fe2 100644
--- a/src/components/stepper/index.zh.md
+++ b/src/components/stepper/index.zh.md
@@ -32,7 +32,7 @@
 | onChange | 变化时的回调 | `(value: number \| null) => void` | - |
 | onFocus | 输入框获得焦点时触发 | `(e: React.FocusEvent<HTMLInputElement>) => void` | - |
 | parser | 将输入解析为对应数字，一般配合 `formatter` 使用 | `(text: string) => number` | - | 5.26.0 |
-| step | 每次增加或减少的值，可以为小数 | `number` | `1` |
+| step | 每次改变步数，可以为小数 | `number` | `1` |
 | stringMode | 字符值模式，开启后支持高精度小数。开启后 `defaultValue`、`value`、`min`、`max`、`onChange` 等都将转换为 `string` 类型 | `boolean` | `false` | 5.27.0 |
 | value | 当前数，受控值 | `number \| null` | - |
 
diff --git a/src/components/stepper/stepper.tsx b/src/components/stepper/stepper.tsx
index 825b5f2d2..e66cb7e0d 100644
--- a/src/components/stepper/stepper.tsx
+++ b/src/components/stepper/stepper.tsx
@@ -101,7 +101,6 @@ export function InnerStepper<ValueType extends number | string>(
     defaultValue = 0 as ValueType,
     value,
     onChange,
-
     disabled,
     step,
     max,
@@ -153,11 +152,7 @@ export function InnerStepper<ValueType extends number | string>(
   const formatValue = (value: ValueType | null): string => {
     if (value === null) return ''
 
-    if (formatter) {
-      return formatter(value)
-    } else {
-      return fixedValue(value)
-    }
+    return formatter ? formatter(value) : fixedValue(value)
   }
 
   // ======================== Value & InputValue ========================
diff --git a/src/components/swipe-action/index.en.md b/src/components/swipe-action/index.en.md
index ede2be1e0..d0a73019a 100644
--- a/src/components/swipe-action/index.en.md
+++ b/src/components/swipe-action/index.en.md
@@ -19,10 +19,10 @@ Swipe to reveal hidden function menus.
 | closeOnAction | Whether to return to the position automatically when the operation button is clicked | `boolean` | `true` |
 | closeOnTouchOutside | Whether to return to the position automatically when other areas is clicked | `boolean` | `true` |
 | leftActions | List of operation buttons on the left | `Action[]` | `[]` |
-| rightActions | List of operation buttons on the right | `Action[]` | `[]` |
 | onAction | Triggered when operation button is clicked | `(action: Action, e: React.MouseEvent) => void` | - |
+| rightActions | List of operation buttons on the right | `Action[]` | `[]` |
 | stopPropagation | Stop the propagation of some events. | `PropagationEvent[]` | `[]` |
-| onActionsReveal | Triggered when the operation button appears completely | `(side: 'left' \| 'right') => void` | - |
+| onActionsReveal | Triggered when the operation button appears completely | (side: 'left' \| 'right') => void | - |
 
 ### Action
 
diff --git a/src/components/swipe-action/index.zh.md b/src/components/swipe-action/index.zh.md
index b9dbcc08b..44896474f 100644
--- a/src/components/swipe-action/index.zh.md
+++ b/src/components/swipe-action/index.zh.md
@@ -19,10 +19,10 @@
 | closeOnAction | 是否在点击操作按钮时自动归位 | `boolean` | `true` |
 | closeOnTouchOutside | 是否在点击其他区域时自动归位 | `boolean` | `true` |
 | leftActions | 左侧的操作按钮列表 | `Action[]` | `[]` |
-| rightActions | 右侧的操作按钮列表 | `Action[]` | `[]` |
 | onAction | 点击操作按钮时触发 | `(action: Action, e: React.MouseEvent) => void` | - |
+| rightActions | 右侧的操作按钮列表 | `Action[]` | `[]` |
 | stopPropagation | 阻止某些事件的冒泡 | `PropagationEven[]` | `[]` |
-| onActionsReveal | 按钮完全出现时触发 | `(side: 'left' \| 'right') => void` | - |
+| onActionsReveal | 按钮完全出现时触发 | (side: 'left' \| 'right') => void | - |
 
 ### Action
 
diff --git a/src/components/switch/index.en.md b/src/components/switch/index.en.md
index e4f5b3e5a..46a8fd86e 100644
--- a/src/components/switch/index.en.md
+++ b/src/components/switch/index.en.md
@@ -19,7 +19,7 @@ switch selector.
 
 | Name | Description | Type | Default |
 | --- | --- | --- | --- |
-| beforeChange（deprecated） | Execute before change （Deprecated, recommend using the `onChange` attribute.） | `(val: boolean) => Promise<void>` | - |
+| beforeChange | Execute before change | `(val: boolean) => Promise<void>` | - |
 | checked | Specify whether it is currently opened | `boolean` | `false` |
 | checkedText | Selected text | `ReactNode` | - |
 | defaultChecked | Whether to open initially | `boolean` | `false` |
diff --git a/src/components/tab-bar/tab-bar.tsx b/src/components/tab-bar/tab-bar.tsx
index df0fc130d..13be270d1 100644
--- a/src/components/tab-bar/tab-bar.tsx
+++ b/src/components/tab-bar/tab-bar.tsx
@@ -1,5 +1,4 @@
-import { FC, ReactNode, ReactElement, ComponentProps } from 'react'
-import React from 'react'
+import React, { FC, ReactNode, ReactElement, isValidElement } from 'react'
 import classNames from 'classnames'
 import { NativeProps, withNativeProps } from '../../utils/native-props'
 import { mergeProps } from '../../utils/with-default-props'
@@ -38,10 +37,10 @@ export const TabBar: FC<TabBarProps> = p => {
 
   let firstActiveKey: string | null = null
 
-  const items: ReactElement<ComponentProps<typeof TabBarItem>>[] = []
+  const items: ReactElement<TabBarItemProps>[] = []
 
   traverseReactNode(props.children, (child, index) => {
-    if (!React.isValidElement(child)) return
+    if (!isValidElement<TabBarItemProps>(child)) return
     const key = child.key
     if (typeof key !== 'string') return
     if (index === 0) {
diff --git a/src/components/tabs/tabs.tsx b/src/components/tabs/tabs.tsx
index 9beab2cd1..3301f15ef 100644
--- a/src/components/tabs/tabs.tsx
+++ b/src/components/tabs/tabs.tsx
@@ -2,7 +2,7 @@ import React, {
   FC,
   ReactNode,
   ReactElement,
-  ComponentProps,
+  isValidElement,
   useRef,
 } from 'react'
 import classNames from 'classnames'
@@ -61,10 +61,11 @@ export const Tabs: FC<TabsProps> = p => {
   const keyToIndexRecord: Record<string, number> = {}
   let firstActiveKey: string | null = null
 
-  const panes: ReactElement<ComponentProps<typeof Tab>>[] = []
+  const panes: ReactElement<TabProps>[] = []
 
   traverseReactNode(props.children, (child, index) => {
-    if (!React.isValidElement(child)) return
+    if (!isValidElement<TabProps>(child)) return
+
     const key = child.key
     if (typeof key !== 'string') return
     if (index === 0) {
diff --git a/src/components/text-area/text-area.less b/src/components/text-area/text-area.less
index 048f80f54..c2c10679f 100644
--- a/src/components/text-area/text-area.less
+++ b/src/components/text-area/text-area.less
@@ -5,7 +5,7 @@
   --disabled-color: var(--adm-color-weak);
   --text-align: left;
   --count-text-align: right;
-  position: relative;
+
   width: 100%;
   max-width: 100%;
   max-height: 100%;
diff --git a/src/components/tree-select/multiple.tsx b/src/components/tree-select/multiple.tsx
index 5ce9b2649..fa6b87764 100644
--- a/src/components/tree-select/multiple.tsx
+++ b/src/components/tree-select/multiple.tsx
@@ -320,18 +320,14 @@ export const Multiple: FC<MultipleProps> = p => {
       return (
         <>
           {renderSelectAllLeafItem(columnOptions, index)}
-          {columnOptions.map(option => {
-            return renderLeafItem(option)
-          })}
+          {columnOptions.map(option => renderLeafItem(option))}
         </>
       )
     }
     return (
       <>
         {renderSelectAllItem(columnOptions, index)}
-        {columnOptions.map(option => {
-          return renderItem(option)
-        })}
+        {columnOptions.map(option => renderItem(option))}
       </>
     )
   }
diff --git a/src/components/virtual-input/virtual-input.tsx b/src/components/virtual-input/virtual-input.tsx
index 11751f9fc..6e764320b 100644
--- a/src/components/virtual-input/virtual-input.tsx
+++ b/src/components/virtual-input/virtual-input.tsx
@@ -151,7 +151,7 @@ export const VirtualInput = forwardRef<VirtualInputRef, VirtualInputProps>(
             <CloseCircleFill />
           </div>
         )}
-        {[undefined, null, ''].includes(value) && (
+        {!value && (
           <div className={`${classPrefix}-placeholder`}>
             {props.placeholder}
           </div>
diff --git a/src/locales/ru-RU.ts b/src/locales/ru-RU.ts
new file mode 100644
index 000000000..37d736257
--- /dev/null
+++ b/src/locales/ru-RU.ts
@@ -0,0 +1,141 @@
+import { mergeLocale } from '../utils/merge-locale'
+import { base } from './base'
+
+const typeTemplate = '${label} не соответствует типу ${type}'
+
+const ruRU = mergeLocale(base, {
+  locale: 'ru',
+  common: {
+    confirm: 'Подтвердить',
+    cancel: 'Отменить',
+    loading: 'Загрузка',
+    close: 'Закрыть',
+  },
+  Calendar: {
+    markItems: ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'],
+    renderYearAndMonth: (year: number, month: number) => `${year}/${month}`,
+  },
+  Cascader: {
+    placeholder: 'Выбор',
+  },
+  Dialog: {
+    ok: 'ОК',
+  },
+  DatePicker: {
+    tillNow: 'До настоящего времени',
+  },
+  ErrorBlock: {
+    default: {
+      title: 'Упс! Что-то пошло не так',
+      description: 'Пожалуйста, подождите минуту и повторите попытку',
+    },
+    busy: {
+      title: 'Упс, не загружается',
+      description: 'Попробуйте обновить страницу',
+    },
+    disconnected: {
+      title: 'Сеть занята',
+      description: 'Попробуйте обновить страницу',
+    },
+    empty: {
+      title: 'Хм, не могу найти...',
+      description: 'Хотите попробовать другой запрос?',
+    },
+  },
+  Form: {
+    required: 'Обязательное',
+    optional: 'Опциональное',
+    defaultValidateMessages: {
+      default: 'Ошибка валидации поля ${label}',
+      required: 'Пожалуйста, заполните поле ${label}',
+      enum: 'Значение ${label} должно быть одним из [${enum}]',
+      whitespace: '${label} не может быть пустым символом',
+      date: {
+        format: '${label} имеет некорректный формат даты',
+        parse: '${label} не может быть конвертировано в дату',
+        invalid: '${label} не является валидной датой',
+      },
+      types: {
+        string: typeTemplate,
+        method: typeTemplate,
+        array: typeTemplate,
+        object: typeTemplate,
+        number: typeTemplate,
+        date: typeTemplate,
+        boolean: typeTemplate,
+        integer: typeTemplate,
+        float: typeTemplate,
+        regexp: typeTemplate,
+        email: typeTemplate,
+        url: typeTemplate,
+        hex: typeTemplate,
+      },
+      string: {
+        len: 'Длина ${label} должна быть ${len} символов(-а)',
+        min: 'Длина ${label} должна быть не меньше ${min} символов(-а)',
+        max: 'Длина ${label} должна быть не больше ${max} символов(-а)',
+        range:
+          'Длина ${label} должна быть в диапазоне от ${min} до ${max} символов(-а)',
+      },
+      number: {
+        len: '${label} должно быть равно ${len}',
+        min: '${label} должно быть значением не меньше ${min}',
+        max: '${label} должно быть значением не больше ${max}',
+        range: '${label} должно быть значением в диапазоне от ${min} до ${max}',
+      },
+      array: {
+        len: 'Размер ${label} должен быть ${len}',
+        min: 'Размер ${label} должен быть не меньше ${min}',
+        max: 'Размер ${label} должен быть не больше ${max}',
+        range: 'Размер ${label} должен быть в диапазоне от ${min} до ${max}',
+      },
+      pattern: {
+        mismatch: '${label} не соответствует шаблону ${pattern}',
+      },
+    },
+  },
+  ImageUploader: {
+    uploading: 'Выгружается...',
+    upload: 'Выгрузить',
+  },
+  InfiniteScroll: {
+    noMore: 'Больше нет',
+    failedToLoad: 'Ошибка загрузки',
+    retry: 'Повторить',
+  },
+  Input: {
+    clear: 'очистить',
+  },
+  Mask: {
+    name: 'Маска',
+  },
+  Modal: {
+    ok: 'ОК',
+  },
+  PasscodeInput: {
+    name: 'Ввод пароля',
+  },
+  PullToRefresh: {
+    pulling: 'Прокрутите вниз, чтобы обновления',
+    canRelease: 'Отпустите, чтобы немедленно обновить',
+    complete: 'Обновление успешно',
+  },
+  SearchBar: {
+    name: 'Панель поиска',
+  },
+  Slider: {
+    name: 'Слайдер',
+  },
+  Stepper: {
+    decrease: 'вычесть',
+    increase: 'прибавить',
+  },
+  Switch: {
+    name: 'Переключатель',
+  },
+  Selector: {
+    name: 'Селектор',
+  },
+})
+
+export default ruRU


Test patch:
diff --git a/src/components/checkbox/tests/checkbox.test.tsx b/src/components/checkbox/tests/checkbox.test.tsx
index a11534cc9..e95043850 100644
--- a/src/components/checkbox/tests/checkbox.test.tsx
+++ b/src/components/checkbox/tests/checkbox.test.tsx
@@ -28,7 +28,16 @@ describe('Checkbox', () => {
     expect(input).not.toBeChecked()
     expect(checkbox).not.toHaveClass(`${classPrefix}-checked`)
   })
+  test('Checkbox click', () => {
+    const handleClick = jest.fn()
+    const { container } = render(
+      <Checkbox onClick={handleClick}>click</Checkbox>
+    )
+    const checkbox = container.getElementsByTagName('label')[0]
 
+    fireEvent.click(checkbox)
+    expect(handleClick).toHaveBeenCalledTimes(1)
+  })
   test('renders with disabled', async () => {
     const { container } = render(<Checkbox disabled>Checkbox</Checkbox>)
     const input = container.querySelectorAll('input')[0]
diff --git a/src/components/config-provider/tests/__snapshots__/config-provider.test.tsx.snap b/src/components/config-provider/tests/__snapshots__/config-provider.test.tsx.snap
index 08dcae1e0..da49dbf8c 100644
--- a/src/components/config-provider/tests/__snapshots__/config-provider.test.tsx.snap
+++ b/src/components/config-provider/tests/__snapshots__/config-provider.test.tsx.snap
@@ -14616,6 +14616,1224 @@ exports[`ConfigProvider should display the text as nl-NL 1`] = `
 </div>
 `;
 
+exports[`ConfigProvider should display the text as ru 1`] = `
+<div>
+  <div
+    class="adm-calendar"
+  >
+    <div
+      class="adm-calendar-header"
+    >
+      <a
+        class="adm-calendar-arrow-button adm-calendar-arrow-button-year"
+      >
+        <svg
+          height="1em"
+          viewBox="0 0 44 44"
+        >
+          <g
+            fill="none"
+            fill-rule="evenodd"
+            stroke="none"
+            stroke-width="1"
+          >
+            <g
+              transform="translate(-24.000000, -22.000000)"
+            >
+              <g
+                transform="translate(24.000000, 22.000000)"
+              >
+                <rect
+                  height="44"
+                  width="44"
+                  x="0"
+                  y="0"
+                />
+                <g
+                  fill="currentColor"
+                  fill-rule="nonzero"
+                  transform="translate(7.000000, 4.000000)"
+                >
+                  <path
+                    d="M19.4833058,2.71985611 L3.53051139,17.0699744 C3.0173831,17.5315665 2.97522952,18.3220903 3.43630803,18.8357433 L3.43630796,18.8357432 C3.46601289,18.8688164 3.49745845,18.9002801 3.53051133,18.9300007 L19.4833057,33.2801611 C20.1234001,33.8559077 20.1759552,34.8420707 19.6007967,35.4827774 C19.0256382,36.1235263 18.0404824,36.1761351 17.400388,35.6003885 L1.44759367,21.2502703 L1.4475933,21.25027 C1.33208743,21.1463692 1.22220259,21.036372 1.11840792,20.920748 C-0.49302969,19.1256817 -0.345639536,16.3628317 1.4475933,14.7497465 L17.4003877,0.399628282 C18.0404821,-0.176160428 19.0256378,-0.123509422 19.6007963,0.517239417 C20.1759548,1.1579461 20.1233997,2.14410915 19.4833053,2.7198557 L19.4833058,2.71985611 Z"
+                  />
+                  <path
+                    d="M19.5305114,17.0699744 C19.0173831,17.5315665 18.9752295,18.3220903 19.436308,18.8357433 C19.4660129,18.8688164 19.4974585,18.9002801 19.5305113,18.9300007 L29.4833057,27.2801611 C30.1234001,27.8559077 30.1759552,28.8420707 29.6007967,29.4827774 C29.0256382,30.1235263 28.0404824,30.1761351 27.400388,29.6003885 L17.4475937,21.2502703 C17.3320874,21.1463692 17.2222026,21.036372 17.1184079,20.920748 C15.5069703,19.1256817 15.6543605,16.3628317 17.4475933,14.7497465 L27.4003877,6.39962828 C28.0404821,5.82383957 29.0256378,5.87649058 29.6007963,6.51723942 C30.1759548,7.1579461 30.1233997,8.14410915 29.4833053,8.7198557 L19.5305114,17.0699744 Z"
+                  />
+                </g>
+              </g>
+            </g>
+          </g>
+        </svg>
+      </a>
+      <a
+        class="adm-calendar-arrow-button adm-calendar-arrow-button-month"
+      >
+        <svg
+          height="1em"
+          viewBox="0 0 44 44"
+        >
+          <g
+            fill="none"
+            fill-rule="evenodd"
+            stroke="none"
+            stroke-width="1"
+          >
+            <g
+              transform="translate(-100.000000, -22.000000)"
+            >
+              <g
+                transform="translate(100.000000, 22.000000)"
+              >
+                <rect
+                  height="44"
+                  width="44"
+                  x="0"
+                  y="0"
+                />
+                <g
+                  fill="currentColor"
+                  fill-rule="nonzero"
+                  transform="translate(12.000000, 4.000000)"
+                >
+                  <path
+                    d="M19.4833058,2.71985611 L3.53051139,17.0699744 C3.0173831,17.5315665 2.97522952,18.3220903 3.43630803,18.8357433 L3.43630796,18.8357432 C3.46601289,18.8688164 3.49745845,18.9002801 3.53051133,18.9300007 L19.4833057,33.2801611 C20.1234001,33.8559077 20.1759552,34.8420707 19.6007967,35.4827774 C19.0256382,36.1235263 18.0404824,36.1761351 17.400388,35.6003885 L1.44759367,21.2502703 L1.4475933,21.25027 C1.33208743,21.1463692 1.22220259,21.036372 1.11840792,20.920748 C-0.49302969,19.1256817 -0.345639536,16.3628317 1.4475933,14.7497465 L17.4003877,0.399628282 C18.0404821,-0.176160428 19.0256378,-0.123509422 19.6007963,0.517239417 C20.1759548,1.1579461 20.1233997,2.14410915 19.4833053,2.7198557 L19.4833058,2.71985611 Z"
+                  />
+                </g>
+              </g>
+            </g>
+          </g>
+        </svg>
+      </a>
+      <div
+        class="adm-calendar-title"
+      >
+        2022/3
+      </div>
+      <a
+        class="adm-calendar-arrow-button adm-calendar-arrow-button-right adm-calendar-arrow-button-right-month"
+      >
+        <svg
+          height="1em"
+          viewBox="0 0 44 44"
+        >
+          <g
+            fill="none"
+            fill-rule="evenodd"
+            stroke="none"
+            stroke-width="1"
+          >
+            <g
+              transform="translate(-100.000000, -22.000000)"
+            >
+              <g
+                transform="translate(100.000000, 22.000000)"
+              >
+                <rect
+                  height="44"
+                  width="44"
+                  x="0"
+                  y="0"
+                />
+                <g
+                  fill="currentColor"
+                  fill-rule="nonzero"
+                  transform="translate(12.000000, 4.000000)"
+                >
+                  <path
+                    d="M19.4833058,2.71985611 L3.53051139,17.0699744 C3.0173831,17.5315665 2.97522952,18.3220903 3.43630803,18.8357433 L3.43630796,18.8357432 C3.46601289,18.8688164 3.49745845,18.9002801 3.53051133,18.9300007 L19.4833057,33.2801611 C20.1234001,33.8559077 20.1759552,34.8420707 19.6007967,35.4827774 C19.0256382,36.1235263 18.0404824,36.1761351 17.400388,35.6003885 L1.44759367,21.2502703 L1.4475933,21.25027 C1.33208743,21.1463692 1.22220259,21.036372 1.11840792,20.920748 C-0.49302969,19.1256817 -0.345639536,16.3628317 1.4475933,14.7497465 L17.4003877,0.399628282 C18.0404821,-0.176160428 19.0256378,-0.123509422 19.6007963,0.517239417 C20.1759548,1.1579461 20.1233997,2.14410915 19.4833053,2.7198557 L19.4833058,2.71985611 Z"
+                  />
+                </g>
+              </g>
+            </g>
+          </g>
+        </svg>
+      </a>
+      <a
+        class="adm-calendar-arrow-button adm-calendar-arrow-button-right adm-calendar-arrow-button-right-year"
+      >
+        <svg
+          height="1em"
+          viewBox="0 0 44 44"
+        >
+          <g
+            fill="none"
+            fill-rule="evenodd"
+            stroke="none"
+            stroke-width="1"
+          >
+            <g
+              transform="translate(-24.000000, -22.000000)"
+            >
+              <g
+                transform="translate(24.000000, 22.000000)"
+              >
+                <rect
+                  height="44"
+                  width="44"
+                  x="0"
+                  y="0"
+                />
+                <g
+                  fill="currentColor"
+                  fill-rule="nonzero"
+                  transform="translate(7.000000, 4.000000)"
+                >
+                  <path
+                    d="M19.4833058,2.71985611 L3.53051139,17.0699744 C3.0173831,17.5315665 2.97522952,18.3220903 3.43630803,18.8357433 L3.43630796,18.8357432 C3.46601289,18.8688164 3.49745845,18.9002801 3.53051133,18.9300007 L19.4833057,33.2801611 C20.1234001,33.8559077 20.1759552,34.8420707 19.6007967,35.4827774 C19.0256382,36.1235263 18.0404824,36.1761351 17.400388,35.6003885 L1.44759367,21.2502703 L1.4475933,21.25027 C1.33208743,21.1463692 1.22220259,21.036372 1.11840792,20.920748 C-0.49302969,19.1256817 -0.345639536,16.3628317 1.4475933,14.7497465 L17.4003877,0.399628282 C18.0404821,-0.176160428 19.0256378,-0.123509422 19.6007963,0.517239417 C20.1759548,1.1579461 20.1233997,2.14410915 19.4833053,2.7198557 L19.4833058,2.71985611 Z"
+                  />
+                  <path
+                    d="M19.5305114,17.0699744 C19.0173831,17.5315665 18.9752295,18.3220903 19.436308,18.8357433 C19.4660129,18.8688164 19.4974585,18.9002801 19.5305113,18.9300007 L29.4833057,27.2801611 C30.1234001,27.8559077 30.1759552,28.8420707 29.6007967,29.4827774 C29.0256382,30.1235263 28.0404824,30.1761351 27.400388,29.6003885 L17.4475937,21.2502703 C17.3320874,21.1463692 17.2222026,21.036372 17.1184079,20.920748 C15.5069703,19.1256817 15.6543605,16.3628317 17.4475933,14.7497465 L27.4003877,6.39962828 C28.0404821,5.82383957 29.0256378,5.87649058 29.6007963,6.51723942 C30.1759548,7.1579461 30.1233997,8.14410915 29.4833053,8.7198557 L19.5305114,17.0699744 Z"
+                  />
+                </g>
+              </g>
+            </g>
+          </g>
+        </svg>
+      </a>
+    </div>
+    <div
+      class="adm-calendar-mark"
+    >
+      <div
+        class="adm-calendar-mark-cell"
+      >
+        Вс
+      </div>
+      <div
+        class="adm-calendar-mark-cell"
+      >
+        Пн
+      </div>
+      <div
+        class="adm-calendar-mark-cell"
+      >
+        Вт
+      </div>
+      <div
+        class="adm-calendar-mark-cell"
+      >
+        Ср
+      </div>
+      <div
+        class="adm-calendar-mark-cell"
+      >
+        Чт
+      </div>
+      <div
+        class="adm-calendar-mark-cell"
+      >
+        Пт
+      </div>
+      <div
+        class="adm-calendar-mark-cell"
+      >
+        Сб
+      </div>
+    </div>
+    <div
+      class="adm-calendar-cells"
+    >
+      <div
+        class="adm-calendar-cell adm-calendar-cell-disabled"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          27
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell adm-calendar-cell-disabled"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          28
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          1
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          2
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          3
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          4
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          5
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          6
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          7
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          8
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          9
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          10
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          11
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          12
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          13
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          14
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          15
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          16
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          17
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          18
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          19
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          20
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          21
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell adm-calendar-cell-today"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          22
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          23
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          24
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          25
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          26
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          27
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          28
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          29
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          30
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          31
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell adm-calendar-cell-disabled"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          1
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell adm-calendar-cell-disabled"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          2
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell adm-calendar-cell-disabled"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          3
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell adm-calendar-cell-disabled"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          4
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell adm-calendar-cell-disabled"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          5
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell adm-calendar-cell-disabled"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          6
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell adm-calendar-cell-disabled"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          7
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell adm-calendar-cell-disabled"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          8
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+      <div
+        class="adm-calendar-cell adm-calendar-cell-disabled"
+      >
+        <div
+          class="adm-calendar-cell-top"
+        >
+          9
+        </div>
+        <div
+          class="adm-calendar-cell-bottom"
+        />
+      </div>
+    </div>
+  </div>
+  <div
+    class="adm-error-block"
+  >
+    <div
+      class="adm-error-block-image"
+    >
+      <svg
+        viewBox="0 0 200 200"
+        xmlns="http://www.w3.org/2000/svg"
+        xmlns:xlink="http://www.w3.org/1999/xlink"
+      >
+        <defs>
+          <lineargradient
+            id="error-block-image-default-a"
+            x1="50%"
+            x2="50%"
+            y1="-116.862%"
+            y2="90.764%"
+          >
+            <stop
+              offset="0%"
+              stop-color="#72A7FD"
+              stop-opacity="0.207"
+            />
+            <stop
+              offset="80.072%"
+              stop-color="#72A7FD"
+              stop-opacity="0.115"
+            />
+            <stop
+              offset="100%"
+              stop-color="#72A7FD"
+              stop-opacity="0"
+            />
+          </lineargradient>
+          <circle
+            cx="18.823"
+            cy="18.823"
+            id="error-block-image-default-d"
+            r="18.823"
+          />
+          <rect
+            height="88"
+            id="error-block-image-default-b"
+            rx="4.571"
+            width="51.429"
+            x="3.5"
+            y="9"
+          />
+        </defs>
+        <g
+          fill="none"
+          fill-rule="evenodd"
+        >
+          <path
+            d="M73.557.004c19.435-.311 38.696 17.016 51.523 35.287 8.708-10.822 17.127-16.233 25.255-16.233 13.333 0 28.35 14.274 45.053 42.822 1.769 3.024-3.582 7.435-16.054 13.231l-41.322 1.37c-7.343 5.872-31.225.626-69.152 1.234-27.79.445-45.759-1.234-53.908-5.037C3.2 71.143-1.625 68.686.48 65.308 27.371 22.12 51.73.353 73.557.003Zm93.098 49.53a1.125 1.125 0 0 0-.401.072l-.058.023-.07.03-.028.014-.02.01c-.03.015-.059.032-.088.049a2.543 2.543 0 0 0-.568.477l-.067.074c-1.686 1.931-2.904 7.062-2.904 8.985 0 2.283 1.719 4.153 3.898 4.314l.026.001v3.805c0 .39.25.705.56.705.31 0 .56-.316.56-.705l.001-3.88c1.92-.402 3.363-2.148 3.363-4.24 0-2.39-1.882-9.734-4.204-9.734Zm-100-5a1.125 1.125 0 0 0-.331.05l-.035.01-.035.012-.058.023-.07.03-.028.014-.02.01c-.03.015-.059.032-.088.049a2.543 2.543 0 0 0-.568.477l-.067.074c-1.686 1.931-2.904 7.062-2.904 8.985 0 2.212 1.613 4.036 3.695 4.294l.203.02.026.001v3.805c0 .39.25.705.56.705.282 0 .515-.26.555-.6l.006-.105v-3.88c1.92-.402 3.363-2.148 3.363-4.24 0-2.39-1.882-9.734-4.204-9.734ZM52.64 38.348l-.15.008-.149.023-.032.007-.032.008-.078.022-.045.015-.045.016-.06.023-.038.017-.038.017-.058.028-.022.011a2.201 2.201 0 0 0-.323.204l-.05.038-.05.04-.025.02-.025.021a3.742 3.742 0 0 0-.31.294l-.036.04c-.035.037-.07.076-.105.116-.01.012-.02.025-.031.036a3.275 3.275 0 0 0-.081.098l-.063.078c-2.031 2.583-3.48 8.692-3.48 11.027 0 2.636 1.846 4.832 4.292 5.323l.224.04-.064-.012.105.018.103.014v4.618c0 .47.299.85.667.85.337 0 .615-.32.659-.735l.006-.115v-4.618c.18-.023.355-.054.527-.094l.256-.067.196-.06c2.136-.706 3.68-2.75 3.68-5.162 0-2.996-2.383-12.207-5.325-12.207Z"
+            fill="url(#error-block-image-default-a)"
+            transform="translate(2.286 22.286)"
+          />
+          <g
+            transform="rotate(-90 102.429 55.357)"
+          >
+            <path
+              d="M6.857 0H52a6.857 6.857 0 0 1 6.857 6.857v92A6.857 6.857 0 0 1 52 105.714H6.857A6.857 6.857 0 0 1 0 98.857v-92A6.857 6.857 0 0 1 6.857 0Z"
+              fill="#7EACFF"
+            />
+            <mask
+              fill="#fff"
+              id="error-block-image-default-c"
+            >
+              <use
+                xlink:href="#error-block-image-default-b"
+              />
+            </mask>
+            <use
+              fill="#377EFF"
+              xlink:href="#error-block-image-default-b"
+            />
+            <path
+              d="M11.838 91.8a.64.64 0 0 1 .627.652.64.64 0 0 1-.627.652.64.64 0 0 1-.628-.652c0-.36.281-.651.628-.651Zm-2.858 0a.64.64 0 0 1 .628.652.64.64 0 0 1-.628.652.64.64 0 0 1-.627-.652c0-.36.281-.651.627-.651Zm2.16-2.305a.64.64 0 0 1 .628.652.64.64 0 0 1-.627.651.64.64 0 0 1-.627-.651c0-.36.28-.652.627-.652Zm-2.982-.04a.64.64 0 0 1 .627.651.64.64 0 0 1-.627.652.64.64 0 0 1-.627-.652c0-.36.28-.651.627-.651Zm5.268-.531a.64.64 0 0 1 .628.651.64.64 0 0 1-.628.652.64.64 0 0 1-.627-.652c0-.36.281-.651.627-.651Zm2.858-1.143a.64.64 0 0 1 .627.651.64.64 0 0 1-.627.652.64.64 0 0 1-.628-.652c0-.36.281-.651.628-.651Zm-6.37-.917c.209 0 .377.175.377.39a.384.384 0 0 1-.376.392.384.384 0 0 1-.376-.391c0-.216.168-.391.376-.391Zm3.512-.798.093.007a.644.644 0 0 1 .535.645.64.64 0 0 1-.628.652.64.64 0 0 1-.627-.652c0-.36.281-.652.627-.652Zm5.715 0a.64.64 0 0 1 .627.652.64.64 0 0 1-.627.652.64.64 0 0 1-.627-.652c0-.36.28-.652.627-.652Zm-11.429 0a.64.64 0 0 1 .627.652.64.64 0 0 1-.627.652.64.64 0 0 1-.627-.652c0-.36.28-.652.627-.652Zm-3.261.241c.208 0 .376.175.376.39a.384.384 0 0 1-.376.392.384.384 0 0 1-.377-.391c0-.216.169-.391.377-.391Zm11.833-.812a.64.64 0 0 1 .627.652.64.64 0 0 1-.627.651.64.64 0 0 1-.628-.651c0-.36.281-.652.628-.652Zm-4.851.399c.208 0 .376.175.376.39a.384.384 0 0 1-.376.392.384.384 0 0 1-.377-.391c0-.216.169-.391.377-.391Zm10.313-2.056a.64.64 0 0 1 .628.652.64.64 0 0 1-.628.651.64.64 0 0 1-.627-.651c0-.36.281-.652.627-.652Zm-2.354-.128a.64.64 0 0 1 .627.652.64.64 0 0 1-.627.652.64.64 0 0 1-.628-.652c0-.36.281-.652.628-.652Zm-13.798.311c.207 0 .376.175.376.391a.384.384 0 0 1-.376.391.384.384 0 0 1-.377-.39c0-.217.169-.392.377-.392Zm11.832-.812a.64.64 0 0 1 .628.652.64.64 0 0 1-.628.651.64.64 0 0 1-.627-.651c0-.36.281-.652.627-.652Zm-6.285 0a.64.64 0 0 1 .627.652.64.64 0 0 1-.627.651.64.64 0 0 1-.627-.651c0-.36.28-.652.627-.652Zm3.428 0a.64.64 0 0 1 .627.652.64.64 0 0 1-.627.651.64.64 0 0 1-.627-.651c0-.36.28-.652.627-.652Zm-6.118.24c.208 0 .376.176.376.392a.384.384 0 0 1-.376.39.384.384 0 0 1-.377-.39c0-.216.169-.391.377-.391Zm11.261-2.525a.64.64 0 0 1 .627.651.64.64 0 0 1-.627.652.64.64 0 0 1-.627-.652c0-.36.28-.651.627-.651Zm-3.557.484c.208 0 .376.175.376.391a.384.384 0 0 1-.376.391.384.384 0 0 1-.376-.391c0-.216.168-.391.376-.391Zm-2.478-.555a.64.64 0 0 1 .627.652.64.64 0 0 1-.627.652.64.64 0 0 1-.627-.652c0-.36.28-.652.627-.652Zm-3.512-.26c.208 0 .376.175.376.39a.384.384 0 0 1-.376.392.384.384 0 0 1-.376-.391c0-.216.168-.391.376-.391Zm-2.857 0c.208 0 .376.175.376.39a.384.384 0 0 1-.376.392.384.384 0 0 1-.376-.391c0-.216.168-.391.376-.391Zm-4.571 0c.207 0 .376.175.376.39a.384.384 0 0 1-.376.392.384.384 0 0 1-.377-.391c0-.216.169-.391.377-.391Zm14.898-1.835a.64.64 0 0 1 .628.652.64.64 0 0 1-.628.651.64.64 0 0 1-.627-.651c0-.36.281-.652.627-.652Zm-8.027-.245c.208 0 .377.175.377.39a.384.384 0 0 1-.377.392.384.384 0 0 1-.376-.391c0-.216.169-.391.376-.391Zm6.271-1.349c.208 0 .377.175.377.391a.384.384 0 0 1-.377.391.384.384 0 0 1-.376-.39c0-.217.169-.392.376-.392Zm-11.484-.481c.208 0 .376.175.376.39a.384.384 0 0 1-.376.392.384.384 0 0 1-.376-.391c0-.216.168-.391.376-.391Zm15.103-.972c.208 0 .376.175.376.391a.384.384 0 0 1-.376.391.384.384 0 0 1-.376-.39c0-.217.168-.392.376-.392Zm-9.333-1.404c.208 0 .376.175.376.39a.384.384 0 0 1-.376.392.384.384 0 0 1-.376-.391c0-.216.168-.391.376-.391Zm-6.819-.405c.208 0 .377.175.377.39a.384.384 0 0 1-.377.392.384.384 0 0 1-.376-.391c0-.216.168-.391.376-.391Z"
+              fill="#003CFF"
+              fill-rule="nonzero"
+              mask="url(#error-block-image-default-c)"
+              transform="rotate(116 12.367 83.503)"
+            />
+            <path
+              d="M36.774 5.474H21.523"
+              stroke="#FFF"
+              stroke-linecap="round"
+              stroke-linejoin="round"
+              stroke-width="0.75"
+            />
+            <path
+              d="m67.818 94.025-4.996 3.913m4.996 11.91-4.996-3.912m-1.142 9.145-1.143-6.288m10.71-6.768h-7.262"
+              stroke="#4486FE"
+              stroke-linecap="round"
+              stroke-linejoin="round"
+              stroke-width="0.75"
+            />
+          </g>
+          <circle
+            cx="8.571"
+            cy="8.571"
+            fill="#FFCD6B"
+            fill-rule="nonzero"
+            r="8.571"
+            transform="translate(22.857 142)"
+          />
+          <g
+            transform="translate(132.857 124)"
+          >
+            <mask
+              fill="#fff"
+              id="error-block-image-default-e"
+            >
+              <use
+                xlink:href="#error-block-image-default-d"
+              />
+            </mask>
+            <use
+              fill="#FBBE47"
+              fill-rule="nonzero"
+              xlink:href="#error-block-image-default-d"
+            />
+            <circle
+              cx="13.886"
+              cy="15.12"
+              fill="#FFCD6B"
+              fill-rule="nonzero"
+              mask="url(#error-block-image-default-e)"
+              r="18.823"
+            />
+            <circle
+              cx="23.4"
+              cy="29.057"
+              fill="#FFB400"
+              fill-rule="nonzero"
+              mask="url(#error-block-image-default-e)"
+              r="1"
+            />
+            <circle
+              cx="30.343"
+              cy="29.829"
+              fill="#FFB400"
+              fill-rule="nonzero"
+              mask="url(#error-block-image-default-e)"
+              r="1"
+            />
+            <circle
+              cx="18.771"
+              cy="32.657"
+              fill="#FFB400"
+              fill-rule="nonzero"
+              mask="url(#error-block-image-default-e)"
+              r="1.286"
+            />
+            <circle
+              cx="29.571"
+              cy="25.971"
+              fill="#FFB400"
+              fill-rule="nonzero"
+              mask="url(#error-block-image-default-e)"
+              r="1.286"
+            />
+            <circle
+              cx="19.286"
+              cy="7.971"
+              fill="#FFB400"
+              fill-rule="nonzero"
+              mask="url(#error-block-image-default-e)"
+              r="1.286"
+            />
+            <circle
+              cx="26.486"
+              cy="5.914"
+              fill="#FFB400"
+              fill-rule="nonzero"
+              mask="url(#error-block-image-default-e)"
+              r="1.286"
+            />
+            <circle
+              cx="11.057"
+              cy="6.943"
+              fill="#FFB400"
+              fill-rule="nonzero"
+              mask="url(#error-block-image-default-e)"
+              r="1"
+            />
+            <circle
+              cx="30.086"
+              cy="15.686"
+              fill="#FFB400"
+              fill-rule="nonzero"
+              mask="url(#error-block-image-default-e)"
+              r="1.286"
+            />
+            <circle
+              cx="22.886"
+              cy="14.657"
+              fill="#FFB400"
+              fill-rule="nonzero"
+              mask="url(#error-block-image-default-e)"
+              r="1"
+            />
+          </g>
+          <path
+            d="m87.429 135.123 6.591-9.378v-.08h-5.99v-2.559h10.038v1.787l-6.44 9.254v.082h6.56v2.557h-10.76v-1.663Zm12.185-5.889 4.948-7.047v-.056h-4.498v-1.917h7.536v1.34l-4.849 6.942v.059h4.923v1.92h-8.06v-1.24Zm10.345.702 3.708-5.274v-.045h-3.372v-1.437h5.648v1.003l-3.628 5.206v.045H116v1.438h-6.041v-.936Z"
+            fill="#FFF"
+            fill-rule="nonzero"
+          />
+        </g>
+      </svg>
+    </div>
+    <div
+      class="adm-error-block-description"
+    >
+      <div
+        class="adm-error-block-description-title"
+      >
+        Упс! Что-то пошло не так
+      </div>
+      <div
+        class="adm-error-block-description-subtitle"
+      >
+        Пожалуйста, подождите минуту и повторите попытку
+      </div>
+    </div>
+  </div>
+  <form
+    class="adm-form"
+  >
+    <div
+      class="adm-list adm-list-default"
+    >
+      <div
+        class="adm-list-body"
+      >
+        <div
+          class="adm-list-body-inner"
+        >
+          <div
+            class="adm-list-item adm-form-item adm-form-item-vertical"
+          >
+            <div
+              class="adm-list-item-content"
+            >
+              <div
+                class="adm-list-item-content-main"
+              >
+                <div
+                  class="adm-list-item-title"
+                >
+                  <label
+                    class="adm-form-item-label"
+                    for="name"
+                  >
+                    name
+                    <span
+                      class="adm-form-item-required-text"
+                    >
+                      (
+                      Обязательное
+                      )
+                    </span>
+                  </label>
+                </div>
+                <div
+                  class="adm-form-item-child adm-form-item-child-position-normal"
+                >
+                  <div
+                    class="adm-form-item-child-inner"
+                  >
+                    <input
+                      id="name"
+                      value=""
+                    />
+                  </div>
+                </div>
+                <div
+                  class="adm-list-item-description"
+                />
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </form>
+  <div
+    class="adm-search-bar"
+  >
+    <div
+      class="adm-search-bar-input-box"
+    >
+      <div
+        class="adm-search-bar-input-box-icon"
+      >
+        <svg
+          class="antd-mobile-icon"
+          height="1em"
+          style="vertical-align: -0.125em;"
+          viewBox="0 0 48 48"
+          width="1em"
+          xmlns="http://www.w3.org/2000/svg"
+          xmlns:xlink="http://www.w3.org/1999/xlink"
+        >
+          <g
+            fill="none"
+            fill-rule="evenodd"
+            id="SearchOutline-SearchOutline"
+            stroke="none"
+            stroke-width="1"
+          >
+            <g
+              id="SearchOutline-编组"
+            >
+              <rect
+                fill="#FFFFFF"
+                height="48"
+                id="SearchOutline-矩形"
+                opacity="0"
+                width="48"
+                x="0"
+                y="0"
+              />
+              <path
+                d="M10.2434135,10.1505371 C17.2346315,3.28315429 28.5696354,3.28315429 35.5608534,10.1505371 C42.3159331,16.7859644 42.5440954,27.4048667 36.2453405,34.3093889 L43.7095294,41.6422249 C43.8671196,41.7970419 43.8693677,42.0502979 43.7145508,42.2078881 C43.7128864,42.2095822 43.7112069,42.2112616 43.7095126,42.2129259 L42.1705322,43.7246464 C42.014915,43.8775072 41.7655181,43.8775006 41.6099089,43.7246316 L34.0775268,36.3248916 L34.0775268,36.3248916 C27.0485579,41.8551751 16.7593545,41.4200547 10.2434135,35.0195303 C3.25219551,28.1521474 3.25219551,17.0179199 10.2434135,10.1505371 Z M12.3532001,12.2229532 C6.52718516,17.9457722 6.52718516,27.2242951 12.3532001,32.9471142 C18.1792151,38.6699332 27.6250517,38.6699332 33.4510667,32.9471142 C39.2770817,27.2242951 39.2770817,17.9457722 33.4510667,12.2229532 C27.6250517,6.50013419 18.1792151,6.50013419 12.3532001,12.2229532 Z"
+                fill="currentColor"
+                fill-rule="nonzero"
+                id="SearchOutline-形状"
+              />
+            </g>
+          </g>
+        </svg>
+      </div>
+      <div
+        aria-label="Панель поиска"
+        class="adm-input adm-search-bar-input"
+      >
+        <input
+          aria-label="Панель поиска"
+          class="adm-input-element"
+          enterkeyhint="search"
+          type="search"
+          value=""
+        />
+      </div>
+    </div>
+  </div>
+  <div
+    class="adm-image-uploader"
+  >
+    <div
+      class="adm-space adm-space-wrap adm-space-block adm-space-horizontal adm-image-uploader-space"
+    >
+      <div
+        class="adm-space-item"
+      >
+        <div
+          class="adm-image-uploader-cell"
+        >
+          <div
+            class="adm-image adm-image-uploader-cell-image"
+          >
+            <div
+              class="adm-image-tip"
+            >
+              <svg
+                viewBox="0 0 48 48"
+                xmlns="http://www.w3.org/2000/svg"
+              >
+                <path
+                  d="M41.396 6.234c1.923 0 3.487 1.574 3.487 3.505v29.14c0 1.937-1.568 3.51-3.491 3.51H6.604c-1.923 0-3.487-1.573-3.487-3.51V9.745c0-1.936 1.564-3.51 3.487-3.51Zm0 2.847H6.604c-.355 0-.654.3-.654.658V34.9l5.989-8.707a2.373 2.373 0 0 1 1.801-1.005 2.405 2.405 0 0 1 1.933.752l4.182 4.525 7.58-11.005a2.374 2.374 0 0 1 1.96-1.01c.79 0 1.532.38 1.966 1.01L42.05 34.89V9.74a.664.664 0 0 0-.654-.658Zm-28.305 2.763a3.119 3.119 0 0 1 3.117 3.117 3.119 3.119 0 0 1-3.117 3.117 3.122 3.122 0 0 1-3.117-3.117 3.119 3.119 0 0 1 3.117-3.117Z"
+                  fill="#DBDBDB"
+                  fill-rule="nonzero"
+                />
+              </svg>
+            </div>
+            <img
+              class="adm-image-img"
+              draggable="false"
+              src="https://images.unsplash.com/photo-1567945716310-4745a6b7844b?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=60"
+              style="object-fit: cover; display: none;"
+            />
+          </div>
+          <span
+            class="adm-image-uploader-cell-delete"
+          >
+            <svg
+              class="antd-mobile-icon adm-image-uploader-cell-delete-icon"
+              height="1em"
+              style="vertical-align: -0.125em;"
+              viewBox="0 0 48 48"
+              width="1em"
+              xmlns="http://www.w3.org/2000/svg"
+              xmlns:xlink="http://www.w3.org/1999/xlink"
+            >
+              <g
+                fill="none"
+                fill-rule="evenodd"
+                id="CloseOutline-CloseOutline"
+                stroke="none"
+                stroke-width="1"
+              >
+                <g
+                  id="CloseOutline-编组"
+                >
+                  <rect
+                    fill="#FFFFFF"
+                    height="48"
+                    id="CloseOutline-矩形"
+                    opacity="0"
+                    width="48"
+                    x="0"
+                    y="0"
+                  />
+                  <path
+                    d="M10.6085104,8.11754663 L24.1768397,21.8195031 L24.1768397,21.8195031 L37.7443031,8.1175556 C37.8194278,8.04168616 37.9217669,7.999 38.0285372,7.999 L41.1040268,7.999 C41.3249407,7.999 41.5040268,8.1780861 41.5040268,8.399 C41.5040268,8.50440471 41.4624226,8.60554929 41.3882578,8.68044752 L26.2773302,23.9408235 L26.2773302,23.9408235 L41.5021975,39.3175645 C41.65763,39.4745475 41.6563731,39.7278104 41.4993901,39.8832429 C41.4244929,39.9574004 41.3233534,39.999 41.2179546,39.999 L38.1434012,39.999 C38.0366291,39.999 37.9342885,39.9563124 37.8591634,39.8804408 L24.1768397,26.0621438 L24.1768397,26.0621438 L10.4936501,39.8804497 C10.4185257,39.9563159 10.3161889,39.999 10.2094212,39.999 L7.13584526,39.999 C6.91493136,39.999 6.73584526,39.8199139 6.73584526,39.599 C6.73584526,39.4936017 6.77744443,39.3924627 6.85160121,39.3175656 L22.0763492,23.9408235 L22.0763492,23.9408235 L6.96554081,8.68044639 C6.81010226,8.52346929 6.81134951,8.27020637 6.9683266,8.11476782 C7.04322474,8.04060377 7.14436883,7.999 7.24977299,7.999 L10.3242852,7.999 C10.4310511,7.999 10.5333863,8.04168267 10.6085104,8.11754663 Z"
+                    fill="currentColor"
+                    fill-rule="nonzero"
+                    id="CloseOutline-路径"
+                  />
+                </g>
+              </g>
+            </svg>
+          </span>
+        </div>
+      </div>
+      <div
+        class="adm-space-item"
+      >
+        <div
+          class="adm-image-uploader-upload-button-wrap"
+        >
+          <span
+            aria-label="Выгрузить"
+            class="adm-image-uploader-cell adm-image-uploader-upload-button"
+            role="button"
+          >
+            <span
+              class="adm-image-uploader-upload-button-icon"
+            >
+              <svg
+                class="antd-mobile-icon"
+                height="1em"
+                style="vertical-align: -0.125em;"
+                viewBox="0 0 48 48"
+                width="1em"
+                xmlns="http://www.w3.org/2000/svg"
+                xmlns:xlink="http://www.w3.org/1999/xlink"
+              >
+                <g
+                  fill="none"
+                  fill-rule="evenodd"
+                  id="AddOutline-AddOutline"
+                  stroke="none"
+                  stroke-width="1"
+                >
+                  <g
+                    id="AddOutline-add"
+                  >
+                    <rect
+                      fill="#FFFFFF"
+                      height="48"
+                      id="AddOutline-矩形"
+                      opacity="0"
+                      width="48"
+                      x="0"
+                      y="0"
+                    />
+                    <path
+                      d="M25.1,6.5 C25.3209139,6.5 25.5,6.6790861 25.5,6.9 L25.5,22.5 L41.1,22.5 C41.3209139,22.5 41.5,22.6790861 41.5,22.9 L41.5,25.1 C41.5,25.3209139 41.3209139,25.5 41.1,25.5 L25.5,25.5 L25.5,41.1 C25.5,41.3209139 25.3209139,41.5 25.1,41.5 L22.9,41.5 C22.6790861,41.5 22.5,41.3209139 22.5,41.1 L22.5,25.5 L6.9,25.5 C6.6790861,25.5 6.5,25.3209139 6.5,25.1 L6.5,22.9 C6.5,22.6790861 6.6790861,22.5 6.9,22.5 L22.5,22.5 L22.5,6.9 C22.5,6.6790861 22.6790861,6.5 22.9,6.5 L25.1,6.5 Z"
+                      fill="currentColor"
+                      fill-rule="nonzero"
+                      id="AddOutline-路径"
+                    />
+                  </g>
+                </g>
+              </svg>
+            </span>
+          </span>
+          <input
+            accept="image/*"
+            aria-hidden="true"
+            class="adm-image-uploader-input"
+            type="file"
+          />
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+`;
+
 exports[`ConfigProvider should display the text as zh-CH 1`] = `
 <div>
   <div
diff --git a/src/components/config-provider/tests/config-provider.test.tsx b/src/components/config-provider/tests/config-provider.test.tsx
index 2a8edcd2d..365f02b19 100644
--- a/src/components/config-provider/tests/config-provider.test.tsx
+++ b/src/components/config-provider/tests/config-provider.test.tsx
@@ -25,6 +25,7 @@ import itIT from '../../../locales/it-IT'
 import daDK from '../../../locales/da-DK'
 import nbNO from '../../../locales/nb-NO'
 import nlNL from '../../../locales/nl-NL'
+import ruRU from '../../../locales/ru-RU'
 
 const locales = [
   zhCN,
@@ -42,6 +43,7 @@ const locales = [
   daDK,
   nbNO,
   nlNL,
+  ruRU,
 ]
 
 describe('ConfigProvider', () => {
diff --git a/src/components/date-picker-view/tests/date-picker-view.test.tsx b/src/components/date-picker-view/tests/date-picker-view.test.tsx
new file mode 100644
index 000000000..881e951b5
--- /dev/null
+++ b/src/components/date-picker-view/tests/date-picker-view.test.tsx
@@ -0,0 +1,29 @@
+import { render, testA11y, fireEvent, screen, act } from 'testing'
+import React from 'react'
+import DatePickerView from '../'
+
+const now = new Date()
+
+describe('DatePickerView', () => {
+  test('passes a11y test', async () => {
+    await act(async () => {
+      await testA11y(<DatePickerView />)
+    })
+  })
+
+  test('till now should be work', async () => {
+    const fn = jest.fn()
+    render(
+      <DatePickerView defaultValue={now} max={now} tillNow onChange={fn} />
+    )
+
+    const nowEl = await screen.findByText('至今')
+    fireEvent.click(nowEl)
+    await act(async () => {
+      await Promise.resolve()
+    })
+    const res = fn.mock.calls[0][0]
+    expect(res.toDateString()).toEqual(now.toDateString())
+    expect(res.tillNow).toBeTruthy()
+  })
+})
diff --git a/src/components/passcode-input/tests/passcode-input.test.tsx b/src/components/passcode-input/tests/passcode-input.test.tsx
index 4562541f3..ccd8e6602 100644
--- a/src/components/passcode-input/tests/passcode-input.test.tsx
+++ b/src/components/passcode-input/tests/passcode-input.test.tsx
@@ -66,9 +66,6 @@ describe('PasscodeInput', () => {
   })
 
   test('native keyboard should be work', async () => {
-    const originScrollIntoView = window.HTMLElement.prototype.scrollIntoView
-    window.HTMLElement.prototype.scrollIntoView = function () {}
-
     render(<PasscodeInput plain />)
     const input = screen.getByRole('button', { name: '密码输入框' })
     fireEvent.focus(input)
@@ -76,8 +73,6 @@ describe('PasscodeInput', () => {
       await userEvent.keyboard('abc')
     })
     expect(input).toHaveTextContent('abc')
-
-    window.HTMLElement.prototype.scrollIntoView = originScrollIntoView
   })
 
   test('event callbacks should be called', async () => {
diff --git a/src/components/radio/tests/radio.test.tsx b/src/components/radio/tests/radio.test.tsx
index fa3b56fed..bfa2ce56f 100644
--- a/src/components/radio/tests/radio.test.tsx
+++ b/src/components/radio/tests/radio.test.tsx
@@ -1,7 +1,6 @@
 import React from 'react'
 import { fireEvent, render, testA11y, userEvent, screen, act } from 'testing'
 import Radio from '../'
-import { RadioGroupProps } from '../group'
 
 const classPrefix = `adm-radio`
 
@@ -22,7 +21,16 @@ describe('Radio', () => {
     expect(radio).toBeChecked()
     expect(label).toHaveClass(`${classPrefix}-checked`)
   })
+  test('Radio click ', async () => {
+    const handleClick = jest.fn()
+    render(<Radio onClick={handleClick}>Radio</Radio>)
 
+    const label = document.getElementsByTagName('label')[0]
+    expect(label).toHaveClass(`${classPrefix}`)
+
+    fireEvent.click(label)
+    expect(handleClick).toBeCalledTimes(1)
+  })
   test('onChange should be call once when the selected item is clicked multiple times', async () => {
     const onChange = jest.fn()
     render(
diff --git a/src/components/virtual-input/tests/virtual-input.test.tsx b/src/components/virtual-input/tests/virtual-input.test.tsx
index 0cd11daab..5e12b3567 100644
--- a/src/components/virtual-input/tests/virtual-input.test.tsx
+++ b/src/components/virtual-input/tests/virtual-input.test.tsx
@@ -108,9 +108,4 @@ describe('VirtualInput', () => {
       ).not.toBeVisible()
     })
   })
-
-  test('placeholder should not be shown when value is `0`', () => {
-    render(<VirtualInput value={0 as any} placeholder='placeholder' />)
-    expect(screen.queryByText('placeholder')).toBeNull()
-  })
 })