diff --git a/packages/vkui/src/components/Calendar/Calendar.stories.tsx b/packages/vkui/src/components/Calendar/Calendar.stories.tsx index aa9617dcb9..b45520100f 100644 --- a/packages/vkui/src/components/Calendar/Calendar.stories.tsx +++ b/packages/vkui/src/components/Calendar/Calendar.stories.tsx @@ -1,6 +1,7 @@ import { useArgs } from '@storybook/preview-api'; import type { Meta, StoryObj } from '@storybook/react'; import { CanvasFullLayout, DisableCartesianParam } from '../../storybook/constants'; +import { createCalendarDayRenderField } from '../../testing/presets/createCalendarDayRenderField'; import { Calendar, type CalendarProps } from './Calendar'; const story: Meta = { @@ -20,6 +21,7 @@ const story: Meta = { shouldDisableDate: { control: false, }, + renderDayContent: createCalendarDayRenderField(), }, }; diff --git a/packages/vkui/src/components/Calendar/Calendar.tsx b/packages/vkui/src/components/Calendar/Calendar.tsx index 2528762c7e..13bda74ae2 100644 --- a/packages/vkui/src/components/Calendar/Calendar.tsx +++ b/packages/vkui/src/components/Calendar/Calendar.tsx @@ -28,7 +28,7 @@ export interface CalendarProps | 'prevMonthProps' | 'nextMonthProps' >, - Pick { + Pick { value?: Date; /** * Запрещает выбор даты в прошлом. @@ -109,6 +109,7 @@ export const Calendar = ({ nextMonthProps, dayProps, listenDayChangesForUpdate, + renderDayContent, minDateTime, maxDateTime, ...props @@ -224,6 +225,7 @@ export const Calendar = ({ size={size} dayProps={dayProps} listenDayChangesForUpdate={listenDayChangesForUpdate} + renderDayContent={renderDayContent} /> {enableTime && value && size !== 's' && (
diff --git a/packages/vkui/src/components/CalendarDay/CalendarDay.test.tsx b/packages/vkui/src/components/CalendarDay/CalendarDay.test.tsx index e5a4d91c5d..bf293faf68 100644 --- a/packages/vkui/src/components/CalendarDay/CalendarDay.test.tsx +++ b/packages/vkui/src/components/CalendarDay/CalendarDay.test.tsx @@ -38,4 +38,14 @@ describe('CalendarDay', () => { ); expect(screen.getByText('Children')).toBeInTheDocument(); }); + + it('check renderDayContent render', () => { + render( + {day.getDate()}} + />, + ); + expect(screen.queryByTestId('day')).toBeTruthy(); + expect(screen.queryByText('1')).toBeTruthy(); + }); }); diff --git a/packages/vkui/src/components/CalendarDay/CalendarDay.tsx b/packages/vkui/src/components/CalendarDay/CalendarDay.tsx index b8f285a314..cbd629dc38 100644 --- a/packages/vkui/src/components/CalendarDay/CalendarDay.tsx +++ b/packages/vkui/src/components/CalendarDay/CalendarDay.tsx @@ -29,6 +29,8 @@ export interface CalendarDayProps extends CalendarDayElementProps { onChange: (value: Date) => void; onEnter?: (value: Date) => void; onLeave?: (value: Date) => void; + // Функция отрисовки контента в ячейке дня + renderDayContent?: (day: Date) => React.ReactNode; } export const CalendarDay: React.FC = React.memo( @@ -52,6 +54,7 @@ export const CalendarDay: React.FC = React.memo( size, className, children, + renderDayContent, ...restProps }: CalendarDayProps) => { const { locale } = useConfigProvider(); @@ -74,6 +77,18 @@ export const CalendarDay: React.FC = React.memo( } }, [focused]); + const content = React.useMemo(() => { + if (renderDayContent) { + return renderDayContent(day); + } + return ( +
+ {children ?? label} + {day.getDate()} +
+ ); + }, [renderDayContent, day, children, label]); + if (hidden) { return
; } @@ -116,10 +131,7 @@ export const CalendarDay: React.FC = React.memo( active && !disabled && styles['CalendarDay__inner--active'], )} > -
- {children ?? label} - {day.getDate()} -
+ {content}
diff --git a/packages/vkui/src/components/CalendarDays/CalendarDays.tsx b/packages/vkui/src/components/CalendarDays/CalendarDays.tsx index 8d5cd26524..c13e86aa39 100644 --- a/packages/vkui/src/components/CalendarDays/CalendarDays.tsx +++ b/packages/vkui/src/components/CalendarDays/CalendarDays.tsx @@ -5,14 +5,19 @@ import { useExternRef } from '../../hooks/useExternRef'; import { useTodayDate } from '../../hooks/useTodayDate'; import { getDaysNames, getWeeks } from '../../lib/calendar'; import type { HTMLAttributesWithRootRef } from '../../types'; -import { CalendarDay, type CalendarDayElementProps } from '../CalendarDay/CalendarDay'; +import { + CalendarDay, + type CalendarDayElementProps, + type CalendarDayProps, +} from '../CalendarDay/CalendarDay'; import { useConfigProvider } from '../ConfigProvider/ConfigProviderContext'; import { RootComponent } from '../RootComponent/RootComponent'; import { Footnote } from '../Typography/Footnote/Footnote'; import styles from './CalendarDays.module.css'; export interface CalendarDaysProps - extends Omit, 'onChange'> { + extends Omit, 'onChange'>, + Pick { value?: Date | Array; viewDate: Date; weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6; @@ -55,6 +60,7 @@ export const CalendarDays = ({ dayProps, listenDayChangesForUpdate = false, getRootRef, + renderDayContent, ...props }: CalendarDaysProps): React.ReactNode => { const { locale } = useConfigProvider(); @@ -122,6 +128,7 @@ export const CalendarDays = ({ hinted={isDayHinted?.(day)} sameMonth={sameMonth} size={size} + renderDayContent={renderDayContent} {...dayProps} /> ); diff --git a/packages/vkui/src/components/CalendarRange/CalendarRange.stories.tsx b/packages/vkui/src/components/CalendarRange/CalendarRange.stories.tsx index c3a63ac71d..5b8d5fb515 100644 --- a/packages/vkui/src/components/CalendarRange/CalendarRange.stories.tsx +++ b/packages/vkui/src/components/CalendarRange/CalendarRange.stories.tsx @@ -1,6 +1,7 @@ import { useArgs } from '@storybook/preview-api'; import type { Meta, StoryObj } from '@storybook/react'; import { CanvasFullLayout, DisableCartesianParam } from '../../storybook/constants'; +import { createCalendarDayRenderField } from '../../testing/presets/createCalendarDayRenderField'; import { CalendarRange, type CalendarRangeProps } from './CalendarRange'; type StoryCalendarRangeProps = CalendarRangeProps & { startDate: number; endDate: number }; @@ -32,6 +33,7 @@ const story: Meta = { }, control: { type: 'date' }, }, + renderDayContent: createCalendarDayRenderField(), }, }; diff --git a/packages/vkui/src/components/CalendarRange/CalendarRange.tsx b/packages/vkui/src/components/CalendarRange/CalendarRange.tsx index a526b95a97..a4897389c1 100644 --- a/packages/vkui/src/components/CalendarRange/CalendarRange.tsx +++ b/packages/vkui/src/components/CalendarRange/CalendarRange.tsx @@ -31,7 +31,7 @@ export interface CalendarRangeProps | 'prevMonthIcon' | 'nextMonthIcon' >, - Pick { + Pick { value?: DateRangeType; disablePast?: boolean; disableFuture?: boolean; @@ -71,6 +71,7 @@ export const CalendarRange = ({ prevMonthIcon, nextMonthIcon, listenDayChangesForUpdate, + renderDayContent, ...props }: CalendarRangeProps): React.ReactNode => { const { @@ -222,6 +223,7 @@ export const CalendarRange = ({ isHintedDaySelectionStart={isHintedDaySelectionStart} isDayDisabled={isDayDisabled} listenDayChangesForUpdate={listenDayChangesForUpdate} + renderDayContent={renderDayContent} aria-label={changeDayLabel} /> @@ -260,6 +262,7 @@ export const CalendarRange = ({ isHintedDaySelectionStart={isHintedDaySelectionStart} isDayDisabled={isDayDisabled} listenDayChangesForUpdate={listenDayChangesForUpdate} + renderDayContent={renderDayContent} tabIndex={0} onBlur={resetSelectedDay} /> diff --git a/packages/vkui/src/components/DateInput/DateInput.stories.tsx b/packages/vkui/src/components/DateInput/DateInput.stories.tsx index d1e44174ee..621524f6b9 100644 --- a/packages/vkui/src/components/DateInput/DateInput.stories.tsx +++ b/packages/vkui/src/components/DateInput/DateInput.stories.tsx @@ -1,6 +1,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { fn } from '@storybook/test'; import { CanvasFullLayout, DisableCartesianParam } from '../../storybook/constants'; +import { createCalendarDayRenderField } from '../../testing/presets/createCalendarDayRenderField'; import { getFormFieldIconsPresets } from '../../testing/presets/getFormFieldIconsPresets'; import { DateInput, type DateInputProps } from './DateInput'; @@ -17,6 +18,7 @@ const story: Meta = { }, after: iconsPresets, before: iconsPresets, + renderDayContent: createCalendarDayRenderField(), }, }; diff --git a/packages/vkui/src/components/DateInput/DateInput.tsx b/packages/vkui/src/components/DateInput/DateInput.tsx index fbeef374c7..b378ee79d0 100644 --- a/packages/vkui/src/components/DateInput/DateInput.tsx +++ b/packages/vkui/src/components/DateInput/DateInput.tsx @@ -53,6 +53,7 @@ export interface DateInputProps | 'nextMonthIcon' | 'minDateTime' | 'maxDateTime' + | 'renderDayContent' >, HasRootRef, Omit { @@ -145,6 +146,7 @@ export const DateInput = ({ prevMonthIcon, nextMonthIcon, disableCalendar = false, + renderDayContent, ...props }: DateInputProps): React.ReactNode => { const daysRef = React.useRef(null); @@ -330,6 +332,7 @@ export const DateInput = ({ changeYearLabel={changeYearLabel} changeDayLabel={changeDayLabel} showNeighboringMonth={showNeighboringMonth} + renderDayContent={renderDayContent} size={size} viewDate={viewDate} onHeaderChange={onHeaderChange} diff --git a/packages/vkui/src/components/DateRangeInput/DateRangeInput.stories.tsx b/packages/vkui/src/components/DateRangeInput/DateRangeInput.stories.tsx index 554bb96f9b..076461875d 100644 --- a/packages/vkui/src/components/DateRangeInput/DateRangeInput.stories.tsx +++ b/packages/vkui/src/components/DateRangeInput/DateRangeInput.stories.tsx @@ -1,6 +1,7 @@ import { useArgs } from '@storybook/preview-api'; import type { Meta, StoryObj } from '@storybook/react'; import { CanvasFullLayout, DisableCartesianParam } from '../../storybook/constants'; +import { createCalendarDayRenderField } from '../../testing/presets/createCalendarDayRenderField'; import { getFormFieldIconsPresets } from '../../testing/presets/getFormFieldIconsPresets'; import { DateRangeInput, type DateRangeInputProps } from './DateRangeInput'; @@ -37,6 +38,7 @@ const story: Meta = { }, before: iconsPresets, after: iconsPresets, + renderDayContent: createCalendarDayRenderField(), }, }; diff --git a/packages/vkui/src/components/DateRangeInput/DateRangeInput.tsx b/packages/vkui/src/components/DateRangeInput/DateRangeInput.tsx index 31889eac3c..3113e22197 100644 --- a/packages/vkui/src/components/DateRangeInput/DateRangeInput.tsx +++ b/packages/vkui/src/components/DateRangeInput/DateRangeInput.tsx @@ -47,6 +47,7 @@ export interface DateRangeInputProps | 'changeDayLabel' | 'prevMonthIcon' | 'nextMonthIcon' + | 'renderDayContent' >, HasRootRef, Omit { @@ -139,6 +140,7 @@ export const DateRangeInput = ({ prevMonthIcon, nextMonthIcon, disableCalendar = false, + renderDayContent, ...props }: DateRangeInputProps): React.ReactNode => { const daysStartRef = React.useRef(null); @@ -342,6 +344,7 @@ export const DateRangeInput = ({ changeDayLabel={changeDayLabel} prevMonthIcon={prevMonthIcon} nextMonthIcon={nextMonthIcon} + renderDayContent={renderDayContent} /> )} diff --git a/packages/vkui/src/testing/presets/createCalendarDayRenderField.tsx b/packages/vkui/src/testing/presets/createCalendarDayRenderField.tsx new file mode 100644 index 0000000000..1943036957 --- /dev/null +++ b/packages/vkui/src/testing/presets/createCalendarDayRenderField.tsx @@ -0,0 +1,48 @@ +import { Icon12Education } from '@vkontakte/icons'; +import { Caption } from '../../components/Typography/Caption/Caption'; +import { DisplayTitle } from '../../components/Typography/DisplayTitle/DisplayTitle'; +import { Text } from '../../components/Typography/Text/Text'; + +export const createCalendarDayRenderField = () => { + return { + control: 'select' as const, + options: ['None', 'DayWithDayName', 'DayWithIcon'], + mapping: { + None: undefined, + DayWithDayName: (date: Date) => { + return ( +
+ + {date.getDate()} + + + {date.toLocaleDateString('ru-RU', { weekday: 'short' })} + +
+ ); + }, + DayWithIcon: (date: Date) => { + return ( +
+ {date.getDate()} + +
+ ); + }, + }, + }; +};