@vimeo/iris
Version:
Vimeo Design System
234 lines (231 loc) • 16.1 kB
JavaScript
import { a as __makeTemplateObject, _ as __read, b as __rest, c as __assign } from '../../../../tslib.es6-7f0e734f.js';
import React__default, { useMemo, useReducer, useState, useRef, useLayoutEffect } from 'react';
import styled, { css } from 'styled-components';
import { useDaysFromViewport } from './useDaysFromViewport.esm.js';
import { i as initialState, r as reducer } from '../../../../Calendar.state-4c10d987.js';
import { CalendarDay } from './CalendarDay.esm.js';
import { rgba, rem } from 'polished';
import { translations } from '../DateRange/translations.esm.js';
import { Header } from '../../../../typography/Header/Header.esm.js';
import { blue, white } from '../../../../color/colors.esm.js';
import { geometry } from '../../../../utils/DOM/geometry.esm.js';
import { ChevronLeft } from '../../../../icons/ui/ChevronLeft.esm.js';
import { ChevronRight } from '../../../../icons/ui/ChevronRight.esm.js';
import '../DateRange/DateFormat.esm.js';
import './CalendarDayLabel.esm.js';
import '../../../../typography/Paragraph/Paragraph.esm.js';
import '../../../../typography/Paragraph/Paragraph.style.esm.js';
import '../../../../typography/Text/Text.esm.js';
import '../../../../typography/Text/Text.style.esm.js';
import '../../../../typography/typography.esm.js';
import '../../../../tokens/core.esm.js';
import '../../../../tokens/color/index.esm.js';
import '../../../../tokens/color/background/background.esm.js';
import '../../../../tokens/util/readToken.esm.js';
import '../../../../tokens/util/clamp.esm.js';
import '../../../../tokens/color/format/format.esm.js';
import '../../../../tokens/color/format/primary.esm.js';
import '../../../../tokens/color/format/secondary.esm.js';
import '../../../../tokens/color/format/tertiary.esm.js';
import '../../../../tokens/color/rainbow/rainbow.esm.js';
import '../../../../tokens/color/rainbow/conic/index.esm.js';
import '../../../../tokens/color/rainbow/conic/sm.esm.js';
import '../../../../tokens/color/rainbow/conic/xl.esm.js';
import '../../../../tokens/color/rainbow/linear/index.esm.js';
import '../../../../tokens/color/rainbow/linear/sm.esm.js';
import '../../../../tokens/color/rainbow/linear/xl.esm.js';
import '../../../../tokens/color/livestream/livestream.esm.js';
import '../../../../tokens/color/status/status.esm.js';
import '../../../../tokens/color/status/caution.esm.js';
import '../../../../tokens/color/status/negative.esm.js';
import '../../../../tokens/color/status/positive.esm.js';
import '../../../../tokens/color/stroke/stroke.esm.js';
import '../../../../tokens/color/surface/surface.esm.js';
import '../../../../tokens/color/text/text.esm.js';
import '../../../../tokens/util/round.esm.js';
import '../../../../tokens/color/upsell/upsell.esm.js';
import '../../../../tokens/color/upsell/sm.esm.js';
import '../../../../tokens/color/upsell/xl.esm.js';
import '../../../../tokens/color/upsell/new.esm.js';
import '../../../../tokens/edge/edge.esm.js';
import '../../../../tokens/space/space.esm.js';
import '../../../../tokens/typography/index.esm.js';
import '../../../../tokens/typography/size/size.esm.js';
import '../../../../typography/Text/EditableText.esm.js';
import '../../../../utils/HOCs/withIris.esm.js';
import '../../../../utils/hooks/useLayoutStyles.esm.js';
import '../../../../utils/css.esm.js';
import '../../../../typography/Header/Header.style.esm.js';
var Calendar = function (_a) {
var onClick = _a.onClick, selected = _a.selected, minDate = _a.minDate, maxDate = _a.maxDate, _b = _a.backOnly, backOnly = _b === void 0 ? false : _b, _c = _a.forwardOnly, forwardOnly = _c === void 0 ? false : _c, backOnClick = _a.backOnClick, forwardOnClick = _a.forwardOnClick, isRange = _a.isRange, _d = _a.range, _e = _d === void 0 ? [null, null] : _d, _f = __read(_e, 2), selectionStart = _f[0], selectionEnd = _f[1], _g = _a.hoverRange, _h = _g === void 0 ? [null, null] : _g, _j = __read(_h, 2), hoverStart = _j[0], hoverEnd = _j[1], onMouseEnter = _a.onMouseEnter, _k = _a.translation, translation = _k === void 0 ? translations['en'] : _k, _l = _a.initialMonth, initialMonth = _l === void 0 ? new Date() : _l, props = __rest(_a, ["onClick", "selected", "minDate", "maxDate", "backOnly", "forwardOnly", "backOnClick", "forwardOnClick", "isRange", "range", "hoverRange", "onMouseEnter", "translation", "initialMonth"]);
var date = initialMonth;
var DAY_LABELS = useMemo(function () { return Object.values(translation.daysAbbreviated); }, [translation.daysAbbreviated]);
var month = function (currentDate) {
var numericalMonth = currentDate.getMonth();
var numericalYear = currentDate.getFullYear();
var month = getMonthName(numericalMonth);
return "".concat(translation.months[month], " ").concat(numericalYear);
};
var initialViewportDate = new Date(date.getFullYear(), date.getMonth(), 1);
var initialStateWithMonth = __assign(__assign({}, initialState), { viewportDate: initialViewportDate });
var _m = __read(useReducer(reducer, initialStateWithMonth), 2), state = _m[0], dispatch = _m[1];
var viewportDate = state.viewportDate;
// Memoize the start and end selections for our range as a tuple.
var range = useMemo(function () {
return [
hoverStart && hoverStart < selectionStart
? hoverStart
: selectionStart,
hoverEnd && hoverEnd > selectionEnd ? hoverEnd : selectionEnd,
];
}, [selectionStart, selectionEnd, hoverStart, hoverEnd]);
var _o = __read(useState(0), 2), width = _o[0], setWidth = _o[1];
var actualDate = isRange ? initialMonth : viewportDate;
var days = useDaysFromViewport(gotoMonth(actualDate, 0));
var resetMonth = function () {
// TODO make this work for date range?
var payload = new Date();
dispatch({ type: 'CHANGE_VIEWPORT', payload: payload });
};
var next = function () {
var payload = new Date(viewportDate.getFullYear(), viewportDate.getMonth() + 1, 1);
dispatch({ type: 'CHANGE_VIEWPORT', payload: payload });
};
var prev = function () {
var payload = new Date(viewportDate.getFullYear(), viewportDate.getMonth() - 1, 1);
dispatch({ type: 'CHANGE_VIEWPORT', payload: payload });
};
function select(date) {
var newMonth = date.getMonth() !== initialMonth.getMonth();
return function () {
if (newMonth)
dispatch({ type: 'SELECT_DATE', payload: date });
onClick(date);
};
}
var inCurrentMonth = function (date) {
return date.getMonth() === actualDate.getMonth();
};
var inCurrentYear = function (date) {
return date.getFullYear() === actualDate.getFullYear();
};
function isCurrentDate(date) {
var selectedDate = new Date(selected);
var sameDate = selectedDate.getDate() === date.getDate();
var sameMonth = inCurrentMonth(selectedDate);
var sameYear = inCurrentYear(selectedDate);
return sameDate && sameMonth && sameYear;
}
function handleClick(date) {
if (onClick) {
onClick(date);
}
}
function handleMouseOver(date) {
if (onMouseEnter) {
onMouseEnter(date);
}
}
function handleMouseOut() {
if (onMouseEnter) {
onMouseEnter(null);
}
}
var ref = useRef();
var maxMonth = new Date(actualDate.getFullYear(), actualDate.getMonth() + 1, 1);
var minMonth = new Date(actualDate.getFullYear(), actualDate.getMonth(), 1);
useLayoutEffect(function () { return setWidth(geometry(ref.current).width); }, [setWidth]);
return (React__default.createElement(Wrapper, __assign({}, props, { onMouseOut: handleMouseOut }),
React__default.createElement(MonthNav, null,
React__default.createElement(MonthNavButton, { type: "button", "aria-label": "Previous", onClick: !forwardOnly
? backOnClick
? backOnClick
: prev
: undefined, inactive: minDate ? minMonth < minDate : undefined, hidden: forwardOnly },
React__default.createElement(ChevronLeft, null)),
React__default.createElement(MonthLabel, { size: "4", onClick: resetMonth }, month(actualDate)),
React__default.createElement(MonthNavButton, { type: "button", "aria-label": "Next", onClick: !backOnly
? forwardOnClick
? forwardOnClick
: next
: undefined, inactive: maxDate ? maxMonth > maxDate : undefined, hidden: backOnly },
React__default.createElement(ChevronRight, null))),
React__default.createElement(Days, { ref: ref, width: width },
DAY_LABELS.map(function (day, i) { return (React__default.createElement(DayLabel, { size: width / 7, key: i }, day)); }),
days.map(function (day, i) {
var pastMinDate = minDate &&
new Date(day.toDateString()) <
new Date(minDate.toDateString());
var pastMaxDate = maxDate &&
new Date(day.toDateString()) >
new Date(maxDate.toDateString());
var inactive = day.getMonth() !== actualDate.getMonth() ||
day.getFullYear() !== actualDate.getFullYear();
if (isRange) {
return (React__default.createElement(CalendarDay, { key: i, inactive: inactive, pastMinDate: pastMinDate, pastMaxDate: pastMaxDate, range: range, draftRange: [selectionStart, selectionEnd], date: day, onClick: function () { return handleClick(day); }, onMouseEnter: function () { return handleMouseOver(day); } }, String(day.getDate()).padStart(2, '0')));
}
return (React__default.createElement(Day, { key: i, size: width / 7, onClick: !pastMinDate && !pastMaxDate ? select(day) : undefined, isCurrentDate: isCurrentDate(day), inCurrentMonth: inCurrentMonth(day), disabled: pastMinDate || pastMaxDate }, String(day.getDate()).padStart(2, '0')));
}))));
};
function getMonthName(month) {
switch (month) {
case 0:
return 'january';
case 1:
return 'february';
case 2:
return 'march';
case 3:
return 'april';
case 4:
return 'may';
case 5:
return 'june';
case 6:
return 'july';
case 7:
return 'august';
case 8:
return 'september';
case 9:
return 'october';
case 10:
return 'november';
case 11:
return 'december';
}
}
function gotoMonth(viewingMonth, i) {
return new Date(viewingMonth.getFullYear(), viewingMonth.getMonth() + i, 1);
}
var Wrapper = styled.div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n width: 100%;\n"], ["\n width: 100%;\n"])));
var MonthNav = styled.div(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n display: flex;\n position: relative;\n width: 100%;\n padding-top: 1rem;\n align-items: center;\n justify-content: center;\n"], ["\n display: flex;\n position: relative;\n width: 100%;\n padding-top: 1rem;\n align-items: center;\n justify-content: center;\n"])));
var MonthLabel = styled(Header)(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n margin: 0;\n flex-grow: 2;\n text-align: center;\n padding: 0 0.5rem;\n color: ", ";\n cursor: pointer;\n"], ["\n margin: 0;\n flex-grow: 2;\n text-align: center;\n padding: 0 0.5rem;\n color: ", ";\n cursor: pointer;\n"])), function (_a) {
var theme = _a.theme;
return theme.content.color;
});
var MonthNavButton = styled.button(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n width: 2rem;\n padding: 0;\n margin: 0 0.75rem;\n cursor: pointer;\n pointer-events: ", ";\n\n ", "\n\n * {\n fill: ", ";\n stroke-width: 1px;\n }\n"], ["\n width: 2rem;\n padding: 0;\n margin: 0 0.75rem;\n cursor: pointer;\n pointer-events: ", ";\n\n ", "\n\n * {\n fill: ", ";\n stroke-width: 1px;\n }\n"])), function (props) {
return props.inactive || props.hidden ? 'none' : 'default';
}, function (props) {
if (props.hidden) {
return css(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n opacity: 0;\n visibility: hidden;\n "], ["\n opacity: 0;\n visibility: hidden;\n "])));
}
}, function (props) {
return props.inactive
? rgba(props.theme.content.color, 0.2)
: rgba(props.theme.content.color, 0.75);
});
var Days = styled.div(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n display: flex;\n flex-flow: row wrap;\n align-items: flex-start;\n align-content: flex-start;\n padding: 0 0.5rem 0.5rem;\n height: ", ";\n width: 100%;\n"], ["\n display: flex;\n flex-flow: row wrap;\n align-items: flex-start;\n align-content: flex-start;\n padding: 0 0.5rem 0.5rem;\n height: ", ";\n width: 100%;\n"])), function (p) { return rem(p.width); });
var Day = styled.div(templateObject_9 || (templateObject_9 = __makeTemplateObject(["\n position: relative;\n cursor: default;\n flex: 0 0 calc(100% / 7);\n width: calc(100% / 7);\n height: calc(100% / 7);\n display: flex;\n flex-direction: column;\n justify-content: center;\n text-align: center;\n font-size: ", ";\n font-weight: 500;\n padding: 0.75rem 0.25rem;\n color: ", ";\n opacity: ", ";\n z-index: 0;\n background: transparent;\n\n &::after {\n content: '';\n pointer-events: none;\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: ", ";\n border-radius: 50%;\n transition: 120ms ease-in-out;\n z-index: -1;\n }\n\n ", ";\n\n ", "\n"], ["\n position: relative;\n cursor: default;\n flex: 0 0 calc(100% / 7);\n width: calc(100% / 7);\n height: calc(100% / 7);\n display: flex;\n flex-direction: column;\n justify-content: center;\n text-align: center;\n font-size: ", ";\n font-weight: 500;\n padding: 0.75rem 0.25rem;\n color: ", ";\n opacity: ", ";\n z-index: 0;\n background: transparent;\n\n &::after {\n content: '';\n pointer-events: none;\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: ", ";\n border-radius: 50%;\n transition: 120ms ease-in-out;\n z-index: -1;\n }\n\n ", ";\n\n ", "\n"])), function (p) { return rem(14 + (p.size > 45.8 && p.size / 7)); }, function (_a) {
var theme = _a.theme;
return theme.content.color;
}, function (p) { return (p.inCurrentMonth && !p.disabled ? 1 : 0.125); }, rgba(blue(500), 0), function (p) {
return p.isCurrentDate &&
p.inCurrentMonth &&
!p.disabled && css(templateObject_7 || (templateObject_7 = __makeTemplateObject(["\n color: ", ";\n\n &::after {\n background: ", ";\n }\n "], ["\n color: ", ";\n\n &::after {\n background: ", ";\n }\n "])), white, rgba(blue(500), 1));
}, function (p) {
return !p.disabled && css(templateObject_8 || (templateObject_8 = __makeTemplateObject(["\n cursor: pointer;\n\n &:hover {\n color: ", ";\n\n &::after {\n background: ", ";\n }\n }\n "], ["\n cursor: pointer;\n\n &:hover {\n color: ", ";\n\n &::after {\n background: ", ";\n }\n }\n "])), white, rgba(blue(500), 1));
});
var DayLabel = styled(Day)(templateObject_10 || (templateObject_10 = __makeTemplateObject(["\n font-weight: bold;\n opacity: 1;\n pointer-events: none;\n"], ["\n font-weight: bold;\n opacity: 1;\n pointer-events: none;\n"])));
var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9, templateObject_10;
export { Calendar };