baseui
Version:
A React Component library implementing the Base design language
731 lines (722 loc) • 23.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.StyledWeekdayHeader = exports.StyledWeek = exports.StyledStartDate = exports.StyledSelectorContainer = exports.StyledRoot = exports.StyledPrevButton = exports.StyledNextButton = exports.StyledMonthYearSelectIconContainer = exports.StyledMonthYearSelectButton = exports.StyledMonthHeader = exports.StyledMonthContainer = exports.StyledMonth = exports.StyledInputWrapper = exports.StyledInputLabel = exports.StyledInputContainer = exports.StyledEndDate = exports.StyledDayLabel = exports.StyledDay = exports.StyledCalendarHeader = exports.StyledCalendarContainer = void 0;
var _styles = require("../styles");
var _dayState = _interopRequireDefault(require("./utils/day-state"));
var _constants = require("./constants");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/*
Copyright (c) Uber Technologies, Inc.
This source code is licensed under the MIT license found in the
LICENSE file in the root directory of this source tree.
*/
/**
* Main component container element
*/
const StyledInputWrapper = exports.StyledInputWrapper = (0, _styles.styled)('div', props => {
const {
$separateRangeInputs
} = props;
return {
width: '100%',
...($separateRangeInputs ? {
display: 'flex',
justifyContent: 'center'
} : {})
};
});
StyledInputWrapper.displayName = "StyledInputWrapper";
StyledInputWrapper.displayName = 'StyledInputWrapper';
const StyledInputLabel = exports.StyledInputLabel = (0, _styles.styled)('div', ({
$theme
}) => ({
...$theme.typography.LabelMedium,
marginBottom: $theme.sizing.scale300
}));
StyledInputLabel.displayName = "StyledInputLabel";
StyledInputLabel.displayName = 'StyledInputLabel';
const StyledStartDate = exports.StyledStartDate = (0, _styles.styled)('div', ({
$theme
}) => ({
width: '100%',
marginRight: $theme.sizing.scale300
}));
StyledStartDate.displayName = "StyledStartDate";
StyledStartDate.displayName = 'StyledStartDate';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const StyledEndDate = exports.StyledEndDate = (0, _styles.styled)('div', ({
$theme
}) => ({
width: '100%'
}));
StyledEndDate.displayName = "StyledEndDate";
StyledEndDate.displayName = 'StyledEndDate';
/**
* Main component container element
*/
const StyledRoot = exports.StyledRoot = (0, _styles.styled)('div', props => {
const {
$theme: {
typography,
colors,
borders,
sizing
}
} = props;
return {
...typography.font200,
color: colors.calendarForeground,
backgroundColor: colors.calendarBackground,
textAlign: 'center',
borderTopLeftRadius: borders.radius400,
borderTopRightRadius: borders.radius400,
borderBottomRightRadius: borders.radius400,
borderBottomLeftRadius: borders.radius400,
display: 'inline-block',
paddingTop: sizing.scale500,
paddingBottom: sizing.scale500,
paddingLeft: sizing.scale500,
paddingRight: sizing.scale500
};
});
StyledRoot.displayName = "StyledRoot";
StyledRoot.displayName = 'StyledRoot';
const StyledMonthContainer = exports.StyledMonthContainer = (0, _styles.styled)('div', props => {
const {
$orientation
} = props;
return {
display: 'flex',
flexDirection: $orientation === _constants.ORIENTATION.vertical ? 'column' : 'row',
gap: '16px'
};
});
StyledMonthContainer.displayName = "StyledMonthContainer";
StyledMonthContainer.displayName = 'StyledMonthContainer';
const StyledCalendarContainer = exports.StyledCalendarContainer = (0, _styles.styled)('div', {});
StyledCalendarContainer.displayName = "StyledCalendarContainer";
StyledCalendarContainer.displayName = 'StyledCalendarContainer';
const StyledSelectorContainer = exports.StyledSelectorContainer = (0, _styles.styled)('div', ({
$theme
}) => {
const textAlign = $theme.direction === 'rtl' ? 'right' : 'left';
return {
marginBottom: $theme.sizing.scale600,
paddingLeft: $theme.sizing.scale600,
paddingRight: $theme.sizing.scale600,
textAlign
};
});
StyledSelectorContainer.displayName = "StyledSelectorContainer";
StyledSelectorContainer.displayName = 'StyledSelectorContainer';
const StyledCalendarHeader = exports.StyledCalendarHeader = (0, _styles.styled)('div', props => {
const {
$theme: {
typography,
borders,
colors,
sizing
},
$density
} = props;
return {
...($density === _constants.DENSITY.high ? typography.LabelMedium : typography.LabelLarge),
boxSizing: 'border-box',
color: colors.calendarHeaderForeground,
display: 'grid',
gridTemplateColumns: '1fr auto auto 1fr',
alignItems: 'center',
backgroundColor: colors.calendarHeaderBackground,
borderTopLeftRadius: borders.surfaceBorderRadius,
borderTopRightRadius: borders.surfaceBorderRadius,
borderBottomRightRadius: 0,
borderBottomLeftRadius: 0,
// account for the left/right arrow heights
minHeight: $density === _constants.DENSITY.high ? `calc(${sizing.scale800} + ${sizing.scale0})` : sizing.scale950,
width: $density === _constants.DENSITY.high ? '100%' : '392px'
};
});
StyledCalendarHeader.displayName = "StyledCalendarHeader";
StyledCalendarHeader.displayName = 'StyledCalendarHeader';
const StyledMonthHeader = exports.StyledMonthHeader = (0, _styles.styled)('div', props => {
return {
display: 'flex',
justifyContent: 'space-around',
color: props.$theme.colors.calendarHeaderForeground,
backgroundColor: props.$theme.colors.calendarHeaderBackground,
whiteSpace: 'nowrap',
width: '100%'
};
});
StyledMonthHeader.displayName = "StyledMonthHeader";
StyledMonthHeader.displayName = 'StyledMonthHeader';
const StyledMonthYearSelectButton = exports.StyledMonthYearSelectButton = (0, _styles.styled)('button', props => {
const {
$theme: {
typography,
colors,
sizing
},
$isFocusVisible,
$density
} = props;
return {
...($density === _constants.DENSITY.high ? typography.LabelMedium : typography.LabelLarge),
alignItems: 'center',
backgroundColor: 'transparent',
borderLeftWidth: 0,
borderRightWidth: 0,
borderTopWidth: 0,
borderBottomWidth: 0,
color: colors.calendarHeaderForeground,
cursor: 'pointer',
display: 'flex',
height: $density === _constants.DENSITY.high ? '48px' : '56px',
paddingTop: $density === _constants.DENSITY.high ? sizing.scale400 : sizing.scale550,
paddingBottom: $density === _constants.DENSITY.high ? sizing.scale400 : sizing.scale550,
paddingLeft: $density === _constants.DENSITY.high ? sizing.scale500 : sizing.scale600,
paddingRight: $density === _constants.DENSITY.high ? sizing.scale500 : sizing.scale600,
outline: 'none',
':focus': {
boxShadow: $isFocusVisible ? `0 0 0 3px ${colors.borderAccent}` : 'none'
}
};
});
StyledMonthYearSelectButton.displayName = "StyledMonthYearSelectButton";
StyledMonthYearSelectButton.displayName = 'StyledMonthYearSelectButton';
const StyledMonthYearSelectIconContainer = exports.StyledMonthYearSelectIconContainer = (0, _styles.styled)('span', props => {
const marginDirection = props.$theme.direction === 'rtl' ? 'marginRight' : 'marginLeft';
return {
alignItems: 'center',
display: 'flex',
[marginDirection]: props.$theme.sizing.scale500
};
});
StyledMonthYearSelectIconContainer.displayName = "StyledMonthYearSelectIconContainer";
StyledMonthYearSelectIconContainer.displayName = 'StyledMonthYearSelectIconContainer';
// @ts-ignore
function getArrowBtnStyle({
$theme,
$disabled,
$isFocusVisible,
$density,
$isTrailing
}) {
return {
alignItems: 'center',
boxSizing: 'border-box',
display: 'flex',
color: $disabled ? $theme.colors.calendarHeaderForegroundDisabled : $theme.colors.calendarHeaderForeground,
cursor: $disabled ? 'default' : 'pointer',
backgroundColor: 'transparent',
borderLeftWidth: 0,
borderRightWidth: 0,
borderTopWidth: 0,
borderBottomWidth: 0,
height: '48px',
justifyContent: 'center',
justifySelf: $isTrailing ? 'end' : 'start',
paddingTop: $density === _constants.DENSITY.high ? '6px' : 0,
paddingBottom: $density === _constants.DENSITY.high ? '6px' : 0,
paddingLeft: $density === _constants.DENSITY.high ? '6px' : 0,
paddingRight: $density === _constants.DENSITY.high ? '6px' : 0,
marginBottom: 0,
marginTop: 0,
outline: 'none',
':focus': $disabled ? {} : {
boxShadow: $isFocusVisible ? `0 0 0 3px ${$theme.colors.borderAccent}` : 'none'
},
width: '48px'
};
}
const StyledPrevButton = exports.StyledPrevButton = (0, _styles.styled)('button', getArrowBtnStyle);
StyledPrevButton.displayName = "StyledPrevButton";
StyledPrevButton.displayName = 'StyledPrevButton';
const StyledNextButton = exports.StyledNextButton = (0, _styles.styled)('button', getArrowBtnStyle);
StyledNextButton.displayName = "StyledNextButton";
StyledNextButton.displayName = 'StyledNextButton';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const StyledMonth = exports.StyledMonth = (0, _styles.styled)('div', props => {
return {
display: 'inline-block',
width: '100%'
};
});
StyledMonth.displayName = "StyledMonth";
StyledMonth.displayName = 'StyledMonth';
const StyledWeek = exports.StyledWeek = (0, _styles.styled)('div', props => {
const {
$theme: {
sizing
}
} = props;
return {
whiteSpace: 'nowrap',
display: 'flex',
marginBottom: sizing.scale0,
justifyContent: 'space-around',
width: '100%'
};
});
StyledWeek.displayName = "StyledWeek";
StyledWeek.displayName = 'StyledWeek';
// @ts-ignore
function generateDayStyles(defaultCode, defaultStyle) {
const codeForSM = defaultCode.substr(0, 12) + '1' + defaultCode.substr(12 + 1);
const codeForEM = defaultCode.substr(0, 13) + '1' + defaultCode.substr(13 + 1);
return {
[defaultCode]: defaultStyle,
[codeForSM]: defaultStyle,
[codeForEM]: defaultStyle
};
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function getDayStyles(code, {
colors
}) {
const undefinedDayStyle = {
// @ts-ignore
':before': {
content: null
},
// @ts-ignore
':after': {
content: null
}
};
let defaultDayStyle = undefinedDayStyle;
const disabledDateStyle = {
color: colors.calendarForegroundDisabled,
// @ts-ignore
':before': {
content: null
},
// @ts-ignore
':after': {
content: null
}
};
const outsideMonthDateStyle = {
color: colors.calendarForegroundDisabled,
':before': {
borderTopStyle: 'none',
borderBottomStyle: 'none',
borderLeftStyle: 'none',
borderRightStyle: 'none',
backgroundColor: 'transparent'
},
':after': {
borderTopLeftRadius: '0%',
borderTopRightRadius: '0%',
borderBottomLeftRadius: '0%',
borderBottomRightRadius: '0%',
borderTopColor: 'transparent',
borderBottomColor: 'transparent',
borderRightColor: 'transparent',
borderLeftColor: 'transparent'
}
};
const highlightedStyle = {
// @ts-ignore
':before': {
content: null
}
};
const CODE_DISABLED_INDEX = 1;
if (code && code[CODE_DISABLED_INDEX] === '1') {
defaultDayStyle = disabledDateStyle;
}
// See the ./utils/day-state.js file for the description of all available states
// rdhsrSsDeDpSrHpHrRrLsMeMoM
// '000000000000000'
const dayStateStyle = Object.assign({},
// highlighted date
generateDayStyles('001000000000000', {
color: colors.calendarDayForegroundPseudoSelected
}),
// selected date
generateDayStyles('000100000000000', {
color: colors.calendarDayForegroundSelected
}),
// selected highlighted date
generateDayStyles('001100000000000', {
color: colors.calendarDayForegroundSelectedHighlighted
}),
// disabled date
{
'010000000000000': {
color: colors.calendarForegroundDisabled,
':after': {
content: null
}
}
},
// disabled highlighted date
{
'011000000000000': {
color: colors.calendarForegroundDisabled,
':after': {
content: null
}
}
},
// date outside of the currently displayed month (when peekNextMonth is true)
generateDayStyles('000000000000001', outsideMonthDateStyle),
// Range Datepicker
// range: highlighted date outside of a selected range
generateDayStyles('101000000000000', highlightedStyle), generateDayStyles('101010000000000', highlightedStyle),
// range: selected date
generateDayStyles('100100000000000', {
color: colors.calendarDayForegroundSelected
}),
// range: selected highlighted date
// when single date selected in a range
generateDayStyles('101100000000000', {
color: colors.calendarDayForegroundSelectedHighlighted,
':before': {
content: null
}
}),
// range: selected start and end dates are the same
generateDayStyles('100111100000000', {
color: colors.calendarDayForegroundSelected,
':before': {
content: null
}
}), generateDayStyles('101111100000000', {
color: colors.calendarDayForegroundSelectedHighlighted,
':before': {
content: null
}
}),
// range: selected start date
generateDayStyles('100111000000000', {
color: colors.calendarDayForegroundSelected
}),
// range: selected end date
generateDayStyles('100110100000000', {
color: colors.calendarDayForegroundSelected,
':before': {
left: null,
right: '50%'
}
}),
// range: first selected date while a range is highlighted but no second date selected yet
// highlighted range on the right from the selected
generateDayStyles('100100001010000', {
color: colors.calendarDayForegroundSelected
}),
// highlighted range on the left from the selected
generateDayStyles('100100001001000', {
color: colors.calendarDayForegroundSelected,
':before': {
left: null,
right: '50%'
}
}),
// range: second date in a range that is highlighted but not selected
generateDayStyles('101000001010000', {
':before': {
left: null,
right: '50%'
}
}), {
'101000001001000': {}
}, {
'101000001001100': {}
}, {
'101000001001010': {}
},
// range: pseudo-selected date
generateDayStyles('100010010000000', {
color: colors.calendarDayForegroundPseudoSelected,
':before': {
left: '0',
width: '100%'
},
':after': {
content: null
}
}),
// range: pseudo-highlighted date (in a range where only one date is
// selected and second date is highlighted)
{
'101000001100000': {
color: colors.calendarDayForegroundPseudoSelected,
':before': {
left: '0',
width: '100%'
},
':after': {
content: null
}
}
}, generateDayStyles('100000001100000', {
color: colors.calendarDayForegroundPseudoSelected,
':before': {
left: '0',
width: '100%'
},
':after': {
content: null
}
}),
// highlighted start date in a range
generateDayStyles('101111000000000', {
color: colors.calendarDayForegroundSelectedHighlighted
}),
// highlighted end date in a range
generateDayStyles('101110100000000', {
color: colors.calendarDayForegroundSelectedHighlighted,
':before': {
left: null,
right: '50%'
}
}),
// range: pseudo-selected date
generateDayStyles('101010010000000', {
color: colors.calendarDayForegroundPseudoSelectedHighlighted,
':before': {
left: '0',
width: '100%'
}
}),
// Range is true Date outside current month (when peekNextMonth is true)
generateDayStyles('100000000000001', outsideMonthDateStyle),
// peekNextMonth is true, date is outside month, start date is selected and range is highlighted is on right
generateDayStyles('100000001010001', outsideMonthDateStyle),
// peekNextMonth is true, date is outside month, start date is selected and range is highlighted is on left
generateDayStyles('100000001001001', outsideMonthDateStyle),
// peekNextMonth is true, date is outside month, range is selected
generateDayStyles('100010000000001', outsideMonthDateStyle));
return dayStateStyle[code] || defaultDayStyle;
}
const StyledDay = exports.StyledDay = (0, _styles.styled)('div', props => {
const {
$disabled,
$isFocusVisible,
$isHighlighted,
$peekNextMonth,
$pseudoSelected,
$range,
$selected,
$outsideMonth,
$outsideMonthWithinRange,
$hasDateLabel,
$density,
$hasLockedBehavior,
$selectedInput,
$value,
$theme: {
colors,
typography,
sizing
}
} = props;
const code = (0, _dayState.default)(props);
let height;
if ($hasDateLabel) {
if ($density === _constants.DENSITY.high) {
height = '64px';
} else {
height = '72px';
}
} else {
if ($density === _constants.DENSITY.high) {
height = '44px';
} else {
height = '52px';
}
}
let circleHeight;
if ($hasDateLabel) {
if ($density === _constants.DENSITY.high) {
circleHeight = '60px';
} else {
circleHeight = '70px';
}
} else {
if ($density === _constants.DENSITY.high) {
circleHeight = '40px';
} else {
circleHeight = '48px';
}
}
const [startDate, endDate] = Array.isArray($value) ? $value : [$value, null];
const oppositeInputIsPopulated = $selectedInput === _constants.INPUT_ROLE.startDate ? endDate !== null && typeof endDate !== 'undefined' : startDate !== null && typeof startDate !== 'undefined';
const shouldHighlightRange = $range && !($hasLockedBehavior && !oppositeInputIsPopulated);
return {
...($density === _constants.DENSITY.high ? typography.ParagraphSmall : typography.ParagraphMedium),
boxSizing: 'border-box',
position: 'relative',
cursor: $disabled || !$peekNextMonth && $outsideMonth ? 'default' : 'pointer',
color: colors.calendarForeground,
display: 'inline-block',
width: $density === _constants.DENSITY.high ? '52px' : '56px',
height: height,
// setting lineHeight equal to the contents height to vertically center the text
lineHeight: $density === _constants.DENSITY.high ? sizing.scale850 : sizing.scale950,
textAlign: 'center',
paddingTop: sizing.scale300,
paddingBottom: sizing.scale300,
paddingLeft: sizing.scale300,
paddingRight: sizing.scale300,
marginTop: 0,
marginBottom: 0,
marginLeft: 0,
marginRight: 0,
outline: 'none',
backgroundColor: 'transparent',
// `transform` creates a stacking context so
// a z-index used on its' children doesn't
// interfere with anything outside the component
transform: 'scale(1)',
...getDayStyles(code, props.$theme),
// :after pseudo element defines the selected
// or highlighted day's circle styles
':after': {
zIndex: -1,
content: '""',
boxSizing: 'border-box',
display: 'inline-block',
boxShadow: $isFocusVisible && (!$outsideMonth || $peekNextMonth) ? `0 0 0 3px ${colors.borderAccent}` : 'none',
backgroundColor: $selected ? colors.calendarDayBackgroundSelectedHighlighted : $pseudoSelected && $isHighlighted ? colors.calendarDayBackgroundPseudoSelectedHighlighted : colors.calendarBackground,
height: circleHeight,
width: $density === _constants.DENSITY.high ? '40px' : '48px',
position: 'absolute',
top: '2px',
left: $density === _constants.DENSITY.high ? '6px' : '4px',
paddingTop: sizing.scale200,
paddingBottom: sizing.scale200,
borderLeftWidth: '2px',
borderRightWidth: '2px',
borderTopWidth: '2px',
borderBottomWidth: '2px',
borderLeftStyle: 'solid',
borderRightStyle: 'solid',
borderTopStyle: 'solid',
borderBottomStyle: 'solid',
borderTopColor: colors.borderSelected,
borderBottomColor: colors.borderSelected,
borderRightColor: colors.borderSelected,
borderLeftColor: colors.borderSelected,
borderTopLeftRadius: $hasDateLabel ? sizing.scale850 : '100%',
borderTopRightRadius: $hasDateLabel ? sizing.scale850 : '100%',
borderBottomLeftRadius: $hasDateLabel ? sizing.scale850 : '100%',
borderBottomRightRadius: $hasDateLabel ? sizing.scale850 : '100%',
...(getDayStyles(code, props.$theme)[':after'] || {}),
...($outsideMonthWithinRange ? {
content: null
} : {})
},
...(shouldHighlightRange ? {
// :before pseudo element defines a grey background style that extends
// the selected/highlighted day's circle and spans through a range
':before': {
zIndex: -1,
content: '""',
boxSizing: 'border-box',
display: 'inline-block',
backgroundColor: colors.backgroundTertiary,
position: 'absolute',
height: circleHeight,
width: '50%',
top: '2px',
left: '50%',
borderTopWidth: '2px',
borderBottomWidth: '2px',
borderLeftWidth: '0',
borderRightWidth: '0',
borderTopStyle: 'solid',
borderBottomStyle: 'solid',
borderLeftStyle: 'solid',
borderRightStyle: 'solid',
borderTopColor: 'transparent',
borderBottomColor: 'transparent',
borderLeftColor: 'transparent',
borderRightColor: 'transparent',
...(getDayStyles(code, props.$theme)[':before'] || {}),
...($outsideMonthWithinRange ? {
backgroundColor: colors.backgroundTertiary,
left: '0',
width: '100%',
content: '""'
} : {})
}
} :
// a hack to make flow happy, otherwise it complains about complexity
// eslint-disable-next-line @typescript-eslint/no-explicit-any
{})
};
});
StyledDay.displayName = "StyledDay";
StyledDay.displayName = 'StyledDay';
const StyledDayLabel = exports.StyledDayLabel = (0, _styles.styled)('div', props => {
const {
$theme: {
typography,
colors
},
$selected
} = props;
return {
...typography.ParagraphXSmall,
color: $selected ? colors.contentInverseTertiary : colors.contentTertiary
};
});
StyledDayLabel.displayName = "StyledDayLabel";
StyledDayLabel.displayName = 'StyledDayLabel';
const StyledWeekdayHeader = exports.StyledWeekdayHeader = (0, _styles.styled)('div', props => {
const {
$theme: {
typography,
colors,
sizing
},
$density
} = props;
return {
...typography.LabelMedium,
color: colors.contentTertiary,
boxSizing: 'border-box',
position: 'relative',
cursor: 'default',
display: 'inline-block',
width: $density === _constants.DENSITY.high ? '44px' : '52px',
height: $density === _constants.DENSITY.high ? '44px' : '52px',
textAlign: 'center',
// setting lineHeight equal to the contents height to vertically center the text
lineHeight: sizing.scale900,
paddingTop: sizing.scale300,
paddingBottom: sizing.scale300,
paddingLeft: sizing.scale200,
paddingRight: sizing.scale200,
marginTop: 0,
marginBottom: 0,
marginLeft: 0,
marginRight: 0,
backgroundColor: 'transparent'
};
});
StyledWeekdayHeader.displayName = "StyledWeekdayHeader";
StyledWeekdayHeader.displayName = 'StyledWeekdayHeader';
const StyledInputContainer = exports.StyledInputContainer = (0, _styles.styled)('div', props => {
const {
$theme,
$separateRangeInputs
} = props;
return {
width: '100%',
...($separateRangeInputs ? {
display: 'flex',
justifyContent: 'center'
} : {}),
backgroundColor: $theme.colors.backgroundPrimary,
outline: 'none',
paddingInlineStart: 'unset'
};
});
StyledInputContainer.displayName = "StyledInputContainer";
StyledInputContainer.displayName = 'StyledInputContainer';