@oslokommune/punkt-react
Version:
React komponentbibliotek til Punkt, et designsystem laget av Oslo Origo
91 lines (81 loc) • 3.41 kB
text/typescript
import classNames from 'classnames'
import { formatISODate, newDateYMD, formatReadableDate } from 'shared-utils/date-utils'
import type { TDateRangeMap } from 'shared-types/calendar'
import type { TDayViewData } from './types'
export interface IDayViewContext {
year: number
month: number
activeSelected: string[]
focusedDate: string | null
// Side-effect ref: tracks which day gets tabindex="0" (first non-disabled day)
tabIndexSetRef: React.MutableRefObject<number>
isDayDisabled: (date: Date, isSelected: boolean) => boolean
}
export interface IDayCellClassContext {
range: boolean
activeSelected: string[]
rangeHovered: Date | null
inRange: TDateRangeMap
isExcluded: (date: Date) => boolean
}
export function getDayViewData(dayCounter: number, today: Date, ctx: IDayViewContext): TDayViewData {
const currentDate = newDateYMD(ctx.year, ctx.month, dayCounter)
const currentDateISO = formatISODate(currentDate)
const isToday = currentDateISO === formatISODate(today)
const isSelected = ctx.activeSelected.includes(currentDateISO)
const isDisabledVal = ctx.isDayDisabled(currentDate, isSelected)
let tabindex: string
if (ctx.focusedDate) {
tabindex = ctx.focusedDate === currentDateISO && !isDisabledVal ? '0' : '-1'
} else if (!isDisabledVal && ctx.tabIndexSetRef.current === 0) {
ctx.tabIndexSetRef.current = dayCounter
tabindex = '0'
} else {
tabindex = ctx.tabIndexSetRef.current === dayCounter ? '0' : '-1'
}
return {
currentDate,
currentDateISO,
isToday,
isSelected,
isDisabled: isDisabledVal,
ariaLabel: formatReadableDate(currentDate),
tabindex,
}
}
export function getDayCellClasses(data: TDayViewData, ctx: IDayCellClassContext): string {
const { currentDateISO, isToday, isSelected } = data
const isRangeStart =
ctx.range &&
(ctx.activeSelected.length === 2 || ctx.rangeHovered !== null) &&
currentDateISO === ctx.activeSelected[0]
const isRangeEnd = ctx.range && ctx.activeSelected.length === 2 && currentDateISO === ctx.activeSelected[1]
return classNames({
'pkt-cal-today': isToday,
'pkt-cal-selected': isSelected,
'pkt-cal-in-range': ctx.inRange[currentDateISO],
'pkt-cal-excluded': ctx.isExcluded(data.currentDate),
'pkt-cal-in-range-first': isRangeStart,
'pkt-cal-in-range-last': isRangeEnd,
'pkt-cal-range-hover': ctx.rangeHovered !== null && currentDateISO === formatISODate(ctx.rangeHovered),
})
}
export function getDayButtonClasses(data: TDayViewData, ctx: IDayCellClassContext): string {
const { currentDateISO, isToday, isSelected, isDisabled: isDisabledVal } = data
const isRangeStart =
ctx.range &&
(ctx.activeSelected.length === 2 || ctx.rangeHovered !== null) &&
currentDateISO === ctx.activeSelected[0]
const isRangeEnd = ctx.range && ctx.activeSelected.length === 2 && currentDateISO === ctx.activeSelected[1]
return classNames({
'pkt-calendar__date': true,
'pkt-calendar__date--today': isToday,
'pkt-calendar__date--selected': isSelected,
'pkt-calendar__date--disabled': isDisabledVal,
'pkt-calendar__date--in-range': ctx.inRange[currentDateISO],
'pkt-calendar__date--in-range-hover':
ctx.rangeHovered !== null && currentDateISO === formatISODate(ctx.rangeHovered),
'pkt-calendar__date--range-start': isRangeStart,
'pkt-calendar__date--range-end': isRangeEnd,
})
}