@amaui/ui-react
Version:
UI for React
514 lines (513 loc) • 27.2 kB
JavaScript
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = __importDefault(require("react"));
const style_react_1 = require("@amaui/style-react");
const utils_1 = require("@amaui/utils");
const date_1 = require("@amaui/date");
const Line_1 = __importDefault(require("../Line"));
const Surface_1 = __importDefault(require("../Surface"));
const Type_1 = __importDefault(require("../Type"));
const PaginationItem_1 = __importDefault(require("../PaginationItem"));
const Transitions_1 = __importDefault(require("../Transitions"));
const Transition_1 = __importDefault(require("../Transition"));
const utils_2 = require("../utils");
const useStyle = (0, style_react_1.style)(theme => ({
root: {
// for transition
overflow: 'hidden',
position: 'relative'
},
size_small: {
height: '250px'
},
size_regular: {
height: '300px'
},
size_large: {
height: '370px'
},
root_no_labels: {
height: '260px'
},
dayNames: {
width: '100%'
},
dayName: {
flex: '1 1 auto',
userSelect: 'none'
},
dayName_size_small: {
width: '30px',
height: '30px'
},
dayName_size_regular: {
width: '40px',
height: '40px'
},
dayName_size_large: {
width: '50px',
height: '50px'
},
day: {
flex: '1 1 auto',
position: 'relative'
},
day_size_small: {
width: '30px',
height: '30px'
},
day_size_regular: {
width: '40px',
height: '40px'
},
day_size_large: {
width: '50px',
height: '50px'
},
day_out: {
opacity: '0.4'
},
day_out_no: {
visibility: 'hidden',
opacity: '0'
},
dayStart: {
borderRadius: `${theme.methods.shape.radius.value(40, 'px')} 0 0 ${theme.methods.shape.radius.value(40, 'px')}`
},
dayEnd: {
borderRadius: `0 ${theme.methods.shape.radius.value(40, 'px')} ${theme.methods.shape.radius.value(40, 'px')} 0`
},
dayStartEnd: {
borderRadius: theme.methods.shape.radius.value(40, 'px')
},
dayStartSelected: {
'&::before': {
content: '""',
position: 'absolute',
left: '50%',
top: '0',
height: '100%',
width: '50%',
background: 'currentColor'
}
},
dayEndSelected: {
'&::before': {
content: '""',
position: 'absolute',
left: '0',
right: '50%',
top: '0',
height: '100%',
width: '50%',
background: 'currentColor'
}
},
weeks: {
width: '100%',
position: 'absolute',
left: '0px',
transition: theme.methods.transitions.make(['opacity', 'transform'])
},
weeks_size_small: {
top: '30px'
},
weeks_size_regular: {
top: '40px'
},
weeks_size_large: {
top: '50px'
},
weeks_no_labels: {
top: '0px'
},
week: {
width: '100%'
},
move_previous: {
'& .weeks_enter': {
opacity: '0',
transform: 'translateX(100%)',
},
'& .weeks_entering': {
opacity: '1',
transform: 'translateX(0%)'
},
'& .weeks_exit': {
opacity: '1',
transform: 'translateX(0%)',
},
'& .weeks_exiting': {
opacity: '0',
transform: 'translateX(-100%)'
}
},
move_next: {
'& .weeks_enter': {
opacity: '0',
transform: 'translateX(-100%)',
},
'& .weeks_entering': {
opacity: '1',
transform: 'translateX(0%)'
},
'& .weeks_exit': {
opacity: '1',
transform: 'translateX(0%)',
},
'& .weeks_exiting': {
opacity: '0',
transform: 'translateX(100%)'
}
},
dayValue: {
'&:hover': {
boxShadow: 'inset 0px 0px 0px 1px currentColor'
}
},
disabled: {
opacity: '0.54',
pointerEvents: 'none'
}
}), { name: 'amaui-CalendarMonth' });
const CalendarMonth = react_1.default.forwardRef((props__, ref) => {
var _a, _b, _c;
const theme = (0, style_react_1.useAmauiTheme)();
const props = react_1.default.useMemo(() => { var _a, _b, _c, _d, _e, _f, _g, _h; return (Object.assign(Object.assign(Object.assign({}, (_d = (_c = (_b = (_a = theme === null || theme === void 0 ? void 0 : theme.ui) === null || _a === void 0 ? void 0 : _a.elements) === null || _b === void 0 ? void 0 : _b.all) === null || _c === void 0 ? void 0 : _c.props) === null || _d === void 0 ? void 0 : _d.default), (_h = (_g = (_f = (_e = theme === null || theme === void 0 ? void 0 : theme.ui) === null || _e === void 0 ? void 0 : _e.elements) === null || _f === void 0 ? void 0 : _f.amauiCalendarMonth) === null || _g === void 0 ? void 0 : _g.props) === null || _h === void 0 ? void 0 : _h.default), props__)); }, [props__]);
const Line = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Line) || Line_1.default; }, [theme]);
const Surface = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Surface) || Surface_1.default; }, [theme]);
const Type = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Type) || Type_1.default; }, [theme]);
const PaginationItem = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.PaginationItem) || PaginationItem_1.default; }, [theme]);
const Transitions = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Transitions) || Transitions_1.default; }, [theme]);
const Transition = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Transition) || Transition_1.default; }, [theme]);
const { tonal = true, color = 'primary', size = 'regular', value: value_, valueDefault, onChange, calendar: calendar_, calendarDefault, onChangeCalendar, onTimeClick, range, offset = 0, outside = true, weekStartDay: weekStartDay_ = 'Monday', now = true, min, max, validate, labels = true, dayNamesFull, noTransition = true, valid: valid_, renderDay, renderDayName, disabled, DayNameProps, PaginationItemProps, TransitionProps, TransitionsProps, className } = props, other = __rest(props, ["tonal", "color", "size", "value", "valueDefault", "onChange", "calendar", "calendarDefault", "onChangeCalendar", "onTimeClick", "range", "offset", "outside", "weekStartDay", "now", "min", "max", "validate", "labels", "dayNamesFull", "noTransition", "valid", "renderDay", "renderDayName", "disabled", "DayNameProps", "PaginationItemProps", "TransitionProps", "TransitionsProps", "className"]);
const { classes } = useStyle();
const [value, setValue] = react_1.default.useState(() => {
const valueResult = (valueDefault !== undefined ? valueDefault : value_) || (now && (range ? [new date_1.AmauiDate(), new date_1.AmauiDate()] : [new date_1.AmauiDate()]));
return ((0, utils_1.is)('array', valueResult) ? valueResult : [valueResult]).filter(Boolean);
});
const [calendar, setCalendar] = react_1.default.useState((calendarDefault !== undefined ? calendarDefault : calendar_) || new date_1.AmauiDate());
let month = calendar || value[0] || new date_1.AmauiDate();
if (!(month === null || month === void 0 ? void 0 : month.valid))
month = new date_1.AmauiDate();
const refs = {
id: react_1.default.useRef(`${(month).year} ${(month).month}`),
previous: react_1.default.useRef(month),
previousTheme: react_1.default.useRef(theme.palette.light),
move: react_1.default.useRef(),
noTransition: react_1.default.useRef(undefined)
};
const weekStartDay = !['Monday', 'Sunday'].includes(weekStartDay_) ? 'Monday' : weekStartDay_;
// Value
react_1.default.useEffect(() => {
if (value_ !== undefined && value_ !== value)
setValue((((0, utils_1.is)('array', value_) ? value_ : [value_]).filter(Boolean)));
}, [value_]);
// Calendar
react_1.default.useEffect(() => {
if (calendar_ !== undefined && calendar_ !== calendar)
setCalendar(calendar_);
}, [calendar_]);
const valid = react_1.default.useCallback((...args) => {
if ((0, utils_1.is)('function', valid_))
return valid_(...args);
const amauiDate = args[0];
if (min || max || validate) {
let response = true;
if ((0, utils_1.is)('function', validate))
response = validate(amauiDate);
if (min !== undefined)
response = response && (0, date_1.is)(amauiDate, 'after or same', min);
if (max !== undefined)
response = response && (0, date_1.is)(amauiDate, 'before or same', max);
return response;
}
return true;
}, [valid_, min, max, validate]);
const onUpdateCalendar = react_1.default.useCallback((valueNew) => {
// Inner update
if (!props.hasOwnProperty('calendar'))
setCalendar(valueNew);
if ((0, utils_1.is)('function', onChangeCalendar))
onChangeCalendar(valueNew);
}, [onChangeCalendar]);
const onUpdate = react_1.default.useCallback((valueUpdated, offsetMultiplier) => {
let valueNew = [valueUpdated, value[1]].filter(Boolean);
// Previous
// Range reset
// If value is range, and is the same (in terms of day, month, year as from and/or to)
// make a reset, ie. make both values that same date
if (range) {
if (value.filter(Boolean)
.some(item => valueUpdated.year === item.year && valueUpdated.month === item.month && valueUpdated.day === item.day))
valueNew = [valueUpdated, valueUpdated];
else {
// Update the value closest to from, to value
let index;
// Update from or to
// based on if value is closer to the middle from, or middle to
if (!value[0])
index = 0;
else if (!value[1])
index = 1;
else if (valueUpdated.milliseconds < value[0].milliseconds)
index = 0;
else if (valueUpdated.milliseconds > value[1].milliseconds)
index = 1;
else {
const middle = Math.abs(value[1].milliseconds - value[0].milliseconds) / 2;
index = valueUpdated.milliseconds <= (value[0].milliseconds + middle) ? 0 : 1;
}
valueNew = [...value];
valueNew[index] = valueUpdated;
}
// start of the day
if (valueNew[0]) {
valueNew[0] = (0, date_1.startOf)(valueNew[0], 'day');
}
// end of the day
if (valueNew[1]) {
valueNew[1] = (0, date_1.endOf)(valueNew[1], 'day');
}
}
// If value isnt's same as the calendar
// update calendar to the value
if (!(valueUpdated.year === calendar.year && valueUpdated.month === calendar.month)) {
onUpdateCalendar((0, date_1.add)(offsetMultiplier !== undefined ? (offsetMultiplier * offset) : 0, 'month', valueUpdated));
}
// Inner value update
if (!props.hasOwnProperty('value'))
setValue(valueNew);
if ((0, utils_1.is)('function', onChange))
onChange((!range ? valueNew[0] : valueNew));
}, [value, range, offset, calendar, onChange]);
const dayNames = [1, 2, 3, 4, 5, 6];
if (weekStartDay === 'Monday')
dayNames.push(7);
else
dayNames.unshift(7);
const renderDayNameMethod = (0, utils_1.is)('function', renderDayName) ? renderDayName : (order_) => {
const values = {
1: dayNamesFull ? 'Monday' : 'M',
2: dayNamesFull ? 'Tuesday' : 'T',
3: dayNamesFull ? 'Wednesday' : 'W',
4: dayNamesFull ? 'Thursday' : 'T',
5: dayNamesFull ? 'Friday' : 'F',
6: dayNamesFull ? 'Saturday' : 'S',
7: dayNamesFull ? 'Sunday' : 'S'
};
return values[order_];
};
const days = [];
const monthNow = new date_1.AmauiDate();
// value or value range selected value
let id = `${month.year} ${month.month} ${month.day} ${theme.palette.light}`;
value.forEach(item => id += ` ${item.year} ${item.month} ${item.day}`);
const monthStart = (0, date_1.startOf)(month, 'month');
const previousMonth = (0, date_1.remove)(1, 'month', month);
const previousMonthEnd = (0, date_1.endOf)(previousMonth, 'month');
const nextMonth = (0, date_1.add)(1, 'month', month);
const monthSame = ((_a = refs.previous.current) === null || _a === void 0 ? void 0 : _a.year) === (calendar === null || calendar === void 0 ? void 0 : calendar.year) && ((_b = refs.previous.current) === null || _b === void 0 ? void 0 : _b.month) === (calendar === null || calendar === void 0 ? void 0 : calendar.month);
const isBetween = (day) => { var _a, _b; return day.milliseconds >= ((_a = value[0]) === null || _a === void 0 ? void 0 : _a.milliseconds) && day.milliseconds <= (((_b = value[1]) === null || _b === void 0 ? void 0 : _b.milliseconds) + 4000); };
const isSelected = (day) => value.some((item) => item.year === day.year && item.month === day.month && item.day === day.day);
const selectedIndex = (day) => value.findIndex((item) => item.year === day.year && item.month === day.month && item.day === day.day);
const selectedSame = (day) => value.filter((item) => item.year === day.year && item.month === day.month && item.day === day.day).length === 2;
let isMonthFrom = false;
let isMonthTo = false;
// Add all month days
for (let i = 0; i < month.daysInMonth; i++) {
let day = (0, date_1.set)(i + 1, 'day', month);
day = (0, date_1.set)(14, 'hour', day);
const selectedIndex_ = selectedIndex(day);
if (selectedIndex_ === 0)
isMonthFrom = true;
else if (selectedIndex_ === 1)
isMonthTo = true;
days.push({
value: i + 1,
in: true,
dayWeek: day.dayWeek,
weekend: [0, 6].includes(day.dayWeek),
today: day.year === monthNow.year && day.dayYear === monthNow.dayYear,
between: isBetween(day),
selected: isSelected(day),
selectedIndex: selectedIndex_,
selectedSame: selectedSame(day),
amauiDate: day
});
}
days[0].start = true;
days[days.length - 1].end = true;
// Add to start
if ((weekStartDay === 'Sunday' && monthStart.dayWeek !== 0) ||
(weekStartDay === 'Monday' && monthStart.dayWeek !== 1)) {
let toAdd = monthStart.dayWeek === 0 ? 6 : monthStart.dayWeek - 1;
if (weekStartDay === 'Sunday')
toAdd++;
for (let i = 0; i < toAdd; i++) {
const day = (0, date_1.set)(previousMonthEnd.day - i, 'day', previousMonth);
days.unshift({
value: day.day,
in: false,
dayWeek: day.dayWeek,
weekend: [0, 6].includes(day.dayWeek),
today: day.year === monthNow.year && day.dayYear === monthNow.dayYear,
between: isBetween(day),
selected: isSelected(day),
selectedIndex: selectedIndex(day),
selectedSame: selectedSame(day),
start: true,
amauiDate: day
});
}
}
// Add to end
const dayLast = days[days.length - 1];
if (dayLast.dayWeek < 7) {
let toAdd = 7 - dayLast.dayWeek;
if (days.length + toAdd - 1 < 42)
toAdd += 41 - (days.length + toAdd - 1);
for (let i = 0; i < toAdd; i++) {
const day = (0, date_1.set)(i + 1, 'day', nextMonth);
days.push({
value: i + 1,
in: false,
dayWeek: day.dayWeek,
weekend: [0, 6].includes(day.dayWeek),
today: day.year === monthNow.year && day.dayYear === monthNow.dayYear,
between: isBetween(day),
selected: isSelected(day),
selectedIndex: selectedIndex(day),
selectedSame: selectedSame(day),
end: true,
amauiDate: day
});
}
}
// noTransition
refs.noTransition.current = monthSame;
// Update previous
if (refs.id.current !== `${month.year} ${month.month}`) {
refs.move.current = ((_c = refs.previous.current) === null || _c === void 0 ? void 0 : _c.milliseconds) > month.milliseconds ? 'next' : 'previous';
refs.id.current = `${month.year} ${month.month}`;
refs.previous.current = month;
refs.noTransition.current = false;
}
const weeks = (0, utils_1.arrayToParts)(days, 7);
const getCalendar = (status) => {
return ((0, jsx_runtime_1.jsx)(Surface, { children: ({ palette }) => ((0, jsx_runtime_1.jsx)(Line, Object.assign({ gap: 0.5, direction: 'column', align: 'unset', justify: 'unset', className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('CalendarMonth', theme) && [
'amaui-CalendarMonth-weeks'
],
classes.weeks,
classes[`weeks_size_${size}`],
status && [`weeks_${status}`],
!labels && classes.weeks_no_labels
]) }, { children: weeks.map((week, index) => (
// Week
(0, jsx_runtime_1.jsx)(Line, Object.assign({ gap: 0, direction: 'row', align: 'unset', justify: 'space-between', className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('CalendarMonth', theme) && [
'amaui-CalendarMonth-week'
],
classes.week
]) }, { children: week.map((day, index_) => {
const propsDay = {
onClick: () => onUpdate(day.amauiDate, day.start || day.end ? -1 : undefined),
disabled: ((!day.in && !outside) ||
!valid(day.amauiDate, 'day') ||
// not prior to 1970, we may potentially update this in the future
day.amauiDate.year < 1970)
};
return ((0, jsx_runtime_1.jsx)(Line, Object.assign({ direction: 'row', align: 'center', justify: 'center', onClick: (event) => {
const timeDate = (0, date_1.startOf)(day.amauiDate, 'hour');
onTimeClick === null || onTimeClick === void 0 ? void 0 : onTimeClick(timeDate, 'month', event);
}, className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('CalendarMonth', theme) && [
'amaui-CalendarMonth-day',
`amaui-CalendarMonth-day-${day.in ? 'in' : 'out'}`
],
classes.day,
classes[`day_size_${size}`],
classes[`day_${day.in ? 'in' : 'out'}`],
(!day.in && !outside) && classes.day_out_no,
!day.selectedSame && range && [
(day.dayWeek === 1 || (day.selected && day.selectedIndex === 0) || (day.start && !outside)) && classes.dayStart,
(day.dayWeek === 0 || (day.selected && day.selectedIndex === 1) || (day.end && !outside)) && classes.dayEnd,
((day.dayWeek === 1 || (day.selected && day.selectedIndex === 0) || (day.start && !outside)) && (day.dayWeek === 0 || (day.selected && day.selectedIndex === 1) || (day.end && !outside))) && classes.dayStartEnd,
(day.selected && day.selectedIndex === 0 && !day.selectedSame) && classes.dayStartSelected,
(day.selected && day.selectedIndex === 1 && !day.selectedSame) && classes.dayEndSelected
]
]), style: Object.assign(Object.assign({}, (range && !day.selected && !day.selectedSame && day.between ? {
background: theme.methods.palette.color.value(undefined, 60, true, palette)
} : undefined)), (range && day.selected && !day.selectedSame ? {
color: theme.methods.palette.color.value(undefined, 60, true, palette)
} : undefined)) }, { children: (0, utils_1.is)('function', renderDay) ?
renderDay(day.amauiDate, propsDay, day, outside) :
((0, jsx_runtime_1.jsx)(PaginationItem, Object.assign({ tonal: tonal, color: 'inherit', size: size, InteractionProps: {
background: false
}, TypeProps: {
version: size === 'large' ? 'b1' : size === 'regular' ? 'b2' : 'b3',
priority: !day.selected ? !day.weekend ? 'primary' : 'secondary' : undefined
}, "aria-label": (0, date_1.format)(day.amauiDate, 'DD-MM-YYYY') }, PaginationItemProps, { className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('CalendarMonth', theme) && [
'amaui-CalendarMonth-day-value',
day.in && 'amaui-CalendarMonth-day-in',
day.dayWeek && 'amaui-CalendarMonth-day-day-week',
day.weekend && 'amaui-CalendarMonth-day-weekend',
day.today && 'amaui-CalendarMonth-day-today',
day.between && 'amaui-CalendarMonth-day-between',
day.selected && 'amaui-CalendarMonth-day-selected',
day.start && 'amaui-CalendarMonth-day-start',
day.end && 'amaui-CalendarMonth-day-end'
],
PaginationItemProps === null || PaginationItemProps === void 0 ? void 0 : PaginationItemProps.className,
classes.dayValue
]), style: Object.assign(Object.assign(Object.assign({}, (day.today ? {
boxShadow: `inset 0px 0px 0px 1px ${palette[40]}`
} : undefined)), (day.selected ? {
color: theme.methods.palette.color.value(undefined, 90, true, palette),
backgroundColor: theme.methods.palette.color.value(undefined, 40, true, palette)
} : undefined)), PaginationItemProps === null || PaginationItemProps === void 0 ? void 0 : PaginationItemProps.style) }, propsDay, { children: day.value }))) }), index_));
}) }), index))) }))) }));
};
return ((0, jsx_runtime_1.jsxs)(Line, Object.assign({ ref: ref, gap: 0, direction: 'column', className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('CalendarMonth', theme) && [
'amaui-CalendarMonth-root',
`amaui-CalendarMonth-size-${size}`
],
className,
classes.root,
classes[`size_${size}`],
classes[`move_${refs.move.current}`],
!labels && classes.root_no_labels,
disabled && classes.disabled
]) }, (isMonthFrom && { 'data-month-from': true }), (isMonthTo && { 'data-month-to': true }), other, { children: [labels && ((0, jsx_runtime_1.jsx)(Line, Object.assign({ gap: 0, direction: 'row', align: 'center', justify: 'space-between', className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('CalendarMonth', theme) && [
'amaui-CalendarMonth-day-names'
],
classes.dayNames
]) }, { children: dayNames.map((day, index) => ((0, jsx_runtime_1.jsx)(Line, Object.assign({ direction: 'column', align: 'center', justify: 'center', className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('CalendarMonth', theme) && [
'amaui-CalendarMonth-day-name'
],
classes.dayName,
classes[`dayName_size_${size}`]
]) }, { children: (0, jsx_runtime_1.jsx)(Type, Object.assign({ version: size === 'large' ? 'b1' : size === 'regular' ? 'b2' : 'b3', align: 'center' }, DayNameProps, { children: renderDayNameMethod(day) })) }), index))) }))), noTransition && (getCalendar()), !noTransition && ((0, jsx_runtime_1.jsx)(Transitions, Object.assign({ id: refs.id.current, mode: 'in-out-follow', switch: true }, TransitionsProps, { children: (0, jsx_runtime_1.jsx)(Transition, Object.assign({ in: true }, TransitionProps, { children: getCalendar }), id) })))] })));
});
CalendarMonth.displayName = 'amaui-CalendarMonth';
exports.default = CalendarMonth;
;