Skip to content

Commit

Permalink
Merge branch 'anu/datepicker' into anu/datepicker-docs
Browse files Browse the repository at this point in the history
  • Loading branch information
anuraghazra committed May 20, 2024
2 parents 889199b + 31e087f commit cb67ae1
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 57 deletions.
6 changes: 0 additions & 6 deletions packages/blade/src/components/DatePicker/Calendar.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { levelToPicker, pickerToLevel } from './utils';
import { classes } from './constants';
import { useControllableState } from '~utils/useControllable';
import { useIsMobile } from '~utils/useIsMobile';
import BaseBox from '~components/Box/BaseBox';
import { throwBladeError } from '~utils/logger';

const Calendar = <Type extends DateSelectionType>({
Expand Down Expand Up @@ -152,11 +151,6 @@ const Calendar = <Type extends DateSelectionType>({
firstDayOfWeek={firstDayOfWeek}
// @ts-expect-error unable to narrow props based on `type`
allowSingleDateInRange={allowSingleDateInRange}
renderDay={(date) => {
return (
<BaseBox data-date={`${date.getMonth()}-${date.getDate()}`}>{date.getDate()}</BaseBox>
);
}}
classNames={{
levelsGroup: classes.levelsGroup,
day: classes.dayCell,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ const CalendarFooter = ({
return (
<BaseBox display="flex" flexDirection="column" gap="spacing.5">
{isMobile ? null : <Divider />}
<BaseBox width="auto" marginLeft="auto" display="flex" flexDirection="row" gap="spacing.4">
<BaseBox
width={{ base: '100%', m: 'auto' }}
marginLeft="auto"
display="flex"
flexDirection="row"
gap="spacing.4"
>
<Button isFullWidth={isMobile} variant="tertiary" size="medium" onClick={onCancel}>
Cancel
</Button>
Expand Down
91 changes: 51 additions & 40 deletions packages/blade/src/components/DatePicker/CalendarStyles.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { classes } from './constants';
import BaseBox from '~components/Box/BaseBox';
import getTextStyles from '~components/Typography/Text/getTextStyles';
import { size } from '~tokens/global';
import { makeSpace } from '~utils';
import { makeBorderSize, makeSpace } from '~utils';
import getIn from '~utils/lodashButBetter/get';
import { useIsMobile } from '~utils/useIsMobile';

Expand Down Expand Up @@ -46,17 +46,31 @@ const todayCell = {
} as const;

const selectedCell = {
background: {
default: 'interactive.background.primary.default',
hover: 'interactive.background.primary.highlighted',
},
border: {
default: 'interactive.border.primary.default',
hover: 'interactive.border.primary.faded',
day: {
background: {
default: 'interactive.background.primary.default',
hover: 'interactive.background.primary.highlighted',
},
border: {
default: 'interactive.border.primary.default',
hover: 'interactive.border.primary.faded',
},
text: {
default: 'interactive.text.onPrimary.normal',
hover: 'interactive.text.onPrimary.normal',
},
},
text: {
default: 'interactive.text.onPrimary.normal',
hover: 'interactive.text.onPrimary.normal',
month: {
background: {
default: 'transparent',
hover: 'interactive.background.primary.faded',
},
border: {
default: 'interactive.border.primary.default',
},
text: {
default: 'interactive.text.primary.normal',
},
},
} as const;

Expand Down Expand Up @@ -98,22 +112,14 @@ const CalendarGradientStyles = styled(BaseBox)<{ date: Date; isRange: boolean }>
const calendar2FirstGradient = `${cal2.month()}-${cal2FirstDay.date()}`;
const calendar2LastGradient = `${cal2.month()}-${cal2LastDay.date()}`;

const gradientCell = {
pointerEvents: 'none',
position: 'relative',
width: 'inherit',
height: 'inherit',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
} as const;
const gradientBefore = {
content: '""',
position: 'absolute',
width: '100%',
top: 0,
bottom: 0,
right: 0,
pointerEvents: 'none',
} as const;
const rightGradient = {
...gradientBefore,
Expand All @@ -134,21 +140,17 @@ const CalendarGradientStyles = styled(BaseBox)<{ date: Date; isRange: boolean }>

return {
[`.${classes.dayCell}`]: {
[`&[data-in-range]:not(&[data-first-in-range]) [data-date="${calendar1FirstGradient}"]`]: {
...gradientCell,
[`&[data-in-range]:not(&[data-first-in-range])[data-date="${calendar1FirstGradient}"]`]: {
'&:before': cal1IsFirstDayStartOfTheWeek ? {} : rightGradient,
},
[`&[data-in-range]:not(&[data-last-in-range]) [data-date="${calendar1LastGradient}"]`]: {
...gradientCell,
[`&[data-in-range]:not(&[data-last-in-range])[data-date="${calendar1LastGradient}"]`]: {
'&:before': cal1IsLastDayEndOfTheWeek ? {} : leftGradient,
},
// Second calendar column
[`&[data-in-range]:not(&[data-first-in-range]) [data-date="${calendar2FirstGradient}"]`]: {
...gradientCell,
[`&[data-in-range]:not(&[data-first-in-range])[data-date="${calendar2FirstGradient}"]`]: {
'&:before': cal2IsFirstDayStartOfTheWeek ? {} : rightGradient,
},
[`&[data-in-range]:not(&[data-last-in-range]) [data-date="${calendar2LastGradient}"]`]: {
...gradientCell,
[`&[data-in-range]:not(&[data-last-in-range])[data-date="${calendar2LastGradient}"]`]: {
'&:before': cal2IsLastDayEndOfTheWeek ? {} : leftGradient,
},
},
Expand Down Expand Up @@ -186,21 +188,30 @@ const CalendarStyles = styled(BaseBox)<{ pickerType?: PickerType }>(({ theme, pi

const selected = {
'&[data-selected]': {
backgroundColor: getIn(theme.colors, selectedCell.background.default),
outlineColor: getIn(theme.colors, selectedCell.border.default),
color: getIn(theme.colors, selectedCell.text.default),
'&[data-celltype="day"]': {
backgroundColor: getIn(theme.colors, selectedCell.day.background.default),
outlineColor: getIn(theme.colors, selectedCell.day.border.default),
color: getIn(theme.colors, selectedCell.day.text.default),
':hover': {
backgroundColor: getIn(theme.colors, selectedCell.day.background.hover),
color: getIn(theme.colors, selectedCell.day.text.hover),
},
},
'&[data-celltype="month"], &[data-celltype="year"]': {
backgroundColor: 'transparent',
outlineStyle: 'solid',
outlineWidth: makeBorderSize(theme.border.width.thin),
outlineOffset: makeSpace(-theme.border.width.thin),
outlineColor: getIn(theme.colors, selectedCell.month.border.default),
color: getIn(theme.colors, selectedCell.month.text.default),
':hover': {
backgroundColor: getIn(theme.colors, selectedCell.month.background.hover),
},
},
':before': {
backgroundColor: getIn(theme.colors, selectedCell.text.default),
backgroundColor: getIn(theme.colors, selectedCell.day.text.default),
},
},
'&[data-selected] [data-date]': {
background: 'none !important',
},
'&[data-selected]:hover': {
backgroundColor: getIn(theme.colors, selectedCell.background.hover),
outlineColor: 'red',
color: getIn(theme.colors, selectedCell.text.hover),
},
} as const;

const ranges = {
Expand Down
31 changes: 24 additions & 7 deletions packages/blade/src/components/DatePicker/DatePicker.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import React from 'react';
import { FloatingFocusManager, FloatingPortal } from '@floating-ui/react';
import { Calendar } from './Calendar';
import { PresetSideBar } from './QuickSelection/PresetSideBar';
import type { DatePickerProps, DateSelectionType } from './types';
import type { DatePickerProps, DateSelectionType, PickerType } from './types';
import { useDatesState } from './useDatesState';
import { DatePickerInput } from './DateInput';
import { usePopup } from './usePopup';
Expand Down Expand Up @@ -45,6 +45,9 @@ const DatePicker = <Type extends DateSelectionType = 'single'>({
successText,
validationState,
size,
defaultPicker = 'day',
picker,
onPickerChange,
...props
}: DatePickerProps<Type>): React.ReactElement => {
const _selectionType = selectionType ?? 'single';
Expand All @@ -54,6 +57,15 @@ const DatePicker = <Type extends DateSelectionType = 'single'>({
const [_, forceRerenderBottomSheet] = React.useReducer((x: number) => x + 1, 0);

const [selectedPreset, setSelectedPreset] = React.useState<DatesRangeValue | null>(null);

const [_picker, setPicker] = useControllableState<PickerType>({
defaultValue: defaultPicker,
value: picker,
onChange: (picker) => {
onPickerChange?.(picker);
},
});

const {
onDateChange,
onRootMouseLeave,
Expand All @@ -63,7 +75,7 @@ const DatePicker = <Type extends DateSelectionType = 'single'>({
controlledValue,
setControlledValue,
} = useDatesState({
level: 'day',
level: _picker,
type: isSingle ? 'default' : 'range',
allowDeselect: false,
allowSingleDateInRange,
Expand Down Expand Up @@ -163,10 +175,14 @@ const DatePicker = <Type extends DateSelectionType = 'single'>({
__onDayClick={(_event, date) => {
onDateChange(date);
}}
getMonthControlProps={(date) => {
return getControlProps(date);
}}
getYearControlProps={(date) => {
return getControlProps(date);
}}
getDayProps={(date) => {
return {
...getControlProps(date),
};
return getControlProps(date);
}}
onMonthSelect={(date) => {
props?.onMonthSelect?.(date);
Expand All @@ -184,8 +200,9 @@ const DatePicker = <Type extends DateSelectionType = 'single'>({
props?.onPrevious?.(date);
forceRerenderBottomSheet();
}}
onPickerChange={(date) => {
props?.onPickerChange?.(date);
picker={_picker}
onPickerChange={(picker) => {
setPicker(() => picker);
forceRerenderBottomSheet();
}}
/>
Expand Down
15 changes: 13 additions & 2 deletions packages/blade/src/components/DatePicker/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,21 @@ type Preset = {
};

type DateSelectionType = 'single' | 'range';
type MantineInternalProps = '__onDayMouseEnter' | '__onDayClick' | 'getDayProps' | 'onMouseLeave';
type MantineInternalProps =
| '__onDayMouseEnter'
| '__onDayClick'
| 'getDayProps'
| 'getYearControlProps'
| 'getMonthControlProps';
type CalendarProps<SelectionType extends DateSelectionType> = Pick<
MantineDatePickerProps<SelectionType extends 'single' ? 'default' : 'range'>,
MantineInternalProps | 'value' | 'defaultValue' | 'onChange' | 'onMonthSelect' | 'onYearSelect'
| MantineInternalProps
| 'onMouseLeave'
| 'value'
| 'defaultValue'
| 'onChange'
| 'onMonthSelect'
| 'onYearSelect'
> & {
/**
* Sets the selection mode of the calendar
Expand Down
9 changes: 8 additions & 1 deletion packages/blade/src/components/DatePicker/useDatesState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,18 @@ export function useDatesState<Type extends DatePickerType = 'default'>({
firstInRange: isFirstInRange(date),
lastInRange: isLastInRange(date),
'data-autofocus': (!!_value[0] && dayjs(_value[0]).isSame(date, level)) || undefined,
'data-celltype': level,
'data-date': `${date.getMonth()}-${date.getDate()}`,
};
}

const selected = dayjs(_value).isSame(date, level);
return { selected, 'data-autofocus': selected || undefined };
return {
selected,
'data-autofocus': selected || undefined,
'data-celltype': level,
'data-date': `${date.getMonth()}-${date.getDate()}`,
};
};

const onHoveredDateChange = type === 'range' && pickedDate ? setHoveredDate : () => {};
Expand Down

0 comments on commit cb67ae1

Please sign in to comment.