analytica-frontend-lib
Version:
Repositório público dos componentes utilizados nas plataformas da Analytica Ensino
535 lines (532 loc) • 20.7 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/components/Calendar/Calendar.tsx
var Calendar_exports = {};
__export(Calendar_exports, {
WEEK_DAYS: () => WEEK_DAYS,
default: () => Calendar_default
});
module.exports = __toCommonJS(Calendar_exports);
var import_react = require("react");
// src/utils/utils.ts
var import_clsx = require("clsx");
var import_tailwind_merge = require("tailwind-merge");
function cn(...inputs) {
return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
}
// src/components/Calendar/Calendar.tsx
var import_jsx_runtime = require("react/jsx-runtime");
var WEEK_DAYS = ["SEG", "TER", "QUA", "QUI", "SEX", "S\xC1B", "DOM"];
var WEEK_DAYS_SHORT = ["S", "T", "Q", "Q", "S", "S", "D"];
var MONTH_NAMES = [
"Janeiro",
"Fevereiro",
"Mar\xE7o",
"Abril",
"Maio",
"Junho",
"Julho",
"Agosto",
"Setembro",
"Outubro",
"Novembro",
"Dezembro"
];
var MonthYearPicker = ({
monthPickerRef,
availableYears,
currentDate,
onYearChange,
onMonthChange
}) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
"div",
{
ref: monthPickerRef,
className: "absolute top-full left-0 z-50 mt-1 bg-white rounded-lg shadow-lg border border-border-200 p-4 min-w-[280px]",
children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mb-4", children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "text-sm font-medium text-text-700 mb-2", children: "Selecionar Ano" }),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-4 gap-1 max-h-32 overflow-y-auto", children: availableYears.map((year) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"button",
{
onClick: () => onYearChange(year),
className: `
px-2 py-1 text-xs rounded text-center hover:bg-background-100 transition-colors
${year === currentDate.getFullYear() ? "bg-primary-800 text-text font-medium hover:text-text-950" : "text-text-700"}
`,
children: year
},
year
)) })
] }),
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "text-sm font-medium text-text-700 mb-2", children: "Selecionar M\xEAs" }),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-3 gap-1", children: MONTH_NAMES.map((month, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"button",
{
onClick: () => onMonthChange(index, currentDate.getFullYear()),
className: `
px-2 py-2 text-xs rounded text-center hover:bg-background-100 transition-colors
${index === currentDate.getMonth() ? "bg-primary-800 text-text font-medium hover:text-text-950" : "text-text-700"}
`,
children: month.substring(0, 3)
},
month
)) })
] })
]
}
);
var getDayStyles = (day, variant, showActivities) => {
let dayStyle = "";
let textStyle = "";
if (variant === "selection" && day.isSelected) {
dayStyle = "bg-primary-800";
textStyle = "text-text";
} else if (day.isToday) {
textStyle = "text-primary-800";
} else if (variant === "navigation" && showActivities && day.activities?.length) {
const primaryActivity = day.activities[0];
if (primaryActivity.status === "near-deadline") {
dayStyle = "bg-warning-background border-2 border-warning-400";
textStyle = "text-text-950";
} else if (primaryActivity.status === "in-deadline") {
dayStyle = "bg-success-background border-2 border-success-300";
textStyle = "text-text-950";
} else if (primaryActivity.status === "overdue") {
dayStyle = "bg-error-background border-2 border-error-300";
textStyle = "text-text-950";
} else {
dayStyle = "border-2 border-blue-500";
textStyle = "text-blue-500";
}
} else {
textStyle = "text-text-950 hover:bg-background-100";
}
return { dayStyle, textStyle };
};
var Calendar = ({
variant = "selection",
selectedDate,
onDateSelect,
onMonthChange,
activities = {},
showActivities = true,
className = ""
}) => {
const [currentDate, setCurrentDate] = (0, import_react.useState)(selectedDate || /* @__PURE__ */ new Date());
const [isMonthPickerOpen, setIsMonthPickerOpen] = (0, import_react.useState)(false);
const monthPickerRef = (0, import_react.useRef)(null);
const monthPickerContainerRef = (0, import_react.useRef)(null);
(0, import_react.useEffect)(() => {
const handleClickOutside = (event) => {
if (monthPickerContainerRef.current && !monthPickerContainerRef.current.contains(event.target)) {
setIsMonthPickerOpen(false);
}
};
if (isMonthPickerOpen) {
document.addEventListener("mousedown", handleClickOutside);
}
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [isMonthPickerOpen]);
const today = /* @__PURE__ */ new Date();
const availableYears = (0, import_react.useMemo)(() => {
const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
const years = [];
for (let year = currentYear - 10; year <= currentYear + 10; year++) {
years.push(year);
}
return years;
}, []);
const calendarData = (0, import_react.useMemo)(() => {
const year = currentDate.getFullYear();
const month = currentDate.getMonth();
const firstDay = new Date(year, month, 1);
const startDate = new Date(firstDay);
const firstDayOfWeek = (firstDay.getDay() + 6) % 7;
startDate.setDate(startDate.getDate() - firstDayOfWeek);
const days = [];
const currentCalendarDate = new Date(startDate);
for (let i = 0; i < 42; i++) {
const dateKey = currentCalendarDate.toISOString().split("T")[0];
const dayActivities = activities[dateKey] || [];
days.push({
date: new Date(currentCalendarDate),
isCurrentMonth: currentCalendarDate.getMonth() === month,
isToday: currentCalendarDate.getFullYear() === today.getFullYear() && currentCalendarDate.getMonth() === today.getMonth() && currentCalendarDate.getDate() === today.getDate(),
isSelected: selectedDate ? currentCalendarDate.getFullYear() === selectedDate.getFullYear() && currentCalendarDate.getMonth() === selectedDate.getMonth() && currentCalendarDate.getDate() === selectedDate.getDate() : false,
activities: dayActivities
});
currentCalendarDate.setDate(currentCalendarDate.getDate() + 1);
}
return days;
}, [currentDate, selectedDate, activities]);
const goToPreviousMonth = () => {
const newDate = new Date(currentDate);
newDate.setMonth(newDate.getMonth() - 1);
setCurrentDate(newDate);
onMonthChange?.(newDate);
};
const goToNextMonth = () => {
const newDate = new Date(currentDate);
newDate.setMonth(newDate.getMonth() + 1);
setCurrentDate(newDate);
onMonthChange?.(newDate);
};
const goToMonth = (month, year) => {
const newDate = new Date(year, month, 1);
setCurrentDate(newDate);
setIsMonthPickerOpen(false);
onMonthChange?.(newDate);
};
const handleYearChange = (year) => {
const newDate = new Date(year, currentDate.getMonth(), 1);
setCurrentDate(newDate);
};
const toggleMonthPicker = (event) => {
event.stopPropagation();
setIsMonthPickerOpen(!isMonthPickerOpen);
};
const handleDateSelect = (day) => {
onDateSelect?.(day.date);
};
if (variant === "navigation") {
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: cn("bg-background rounded-xl pt-6", className), children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-between mb-4 px-6", children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative", ref: monthPickerContainerRef, children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
"button",
{
onClick: toggleMonthPicker,
className: "flex items-center group gap-1 rounded transition-colors cursor-pointer",
children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "text-sm font-medium text-text-600 group-hover:text-primary-950", children: [
MONTH_NAMES[currentDate.getMonth()],
" ",
currentDate.getFullYear()
] }),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"svg",
{
className: `w-4 h-4 text-primary-950 transition-transform ${isMonthPickerOpen ? "rotate-180" : ""}`,
fill: "none",
stroke: "currentColor",
viewBox: "0 0 24 24",
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"path",
{
strokeLinecap: "round",
strokeLinejoin: "round",
strokeWidth: 2,
d: "M19 9l-7 7-7-7"
}
)
}
)
]
}
),
isMonthPickerOpen && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
MonthYearPicker,
{
monthPickerRef,
availableYears,
currentDate,
onYearChange: handleYearChange,
onMonthChange: goToMonth
}
)
] }),
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-10", children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"button",
{
onClick: goToPreviousMonth,
className: "p-1 rounded hover:bg-background-100 transition-colors",
"aria-label": "M\xEAs anterior",
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"svg",
{
className: "w-6 h-6 text-primary-950",
fill: "none",
stroke: "currentColor",
viewBox: "0 0 24 24",
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"path",
{
strokeLinecap: "round",
strokeLinejoin: "round",
strokeWidth: 2,
d: "M15 19l-7-7 7-7"
}
)
}
)
}
),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"button",
{
onClick: goToNextMonth,
className: "p-1 rounded hover:bg-background-100 transition-colors",
"aria-label": "Pr\xF3ximo m\xEAs",
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"svg",
{
className: "w-6 h-6 text-primary-950",
fill: "none",
stroke: "currentColor",
viewBox: "0 0 24 24",
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"path",
{
strokeLinecap: "round",
strokeLinejoin: "round",
strokeWidth: 2,
d: "M9 5l7 7-7 7"
}
)
}
)
}
)
] })
] }),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-7 gap-1 mb-2 px-3", children: WEEK_DAYS_SHORT.map((day, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"div",
{
className: "h-9 flex items-center justify-center text-xs font-normal text-text-600",
children: day
},
`${day}-${index}`
)) }),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-7 gap-1 px-3", children: calendarData.map((day) => {
if (!day.isCurrentMonth) {
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"div",
{
className: "flex items-center justify-center",
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-9 h-9" })
},
day.date.getTime()
);
}
const { dayStyle, textStyle } = getDayStyles(
day,
variant,
showActivities
);
let spanClass = "";
if (day.isSelected && day.isToday) {
spanClass = "h-6 w-6 rounded-full bg-primary-800 text-text";
} else if (day.isSelected) {
spanClass = "h-6 w-6 rounded-full bg-primary-950 text-text";
}
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"div",
{
className: "flex items-center justify-center",
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"button",
{
className: `
w-9 h-9
flex items-center justify-center
text-md font-normal
cursor-pointer
rounded-full
${dayStyle}
${textStyle}
`,
onClick: () => handleDateSelect(day),
"aria-label": `${day.date.getDate()} de ${MONTH_NAMES[day.date.getMonth()]}`,
"aria-current": day.isToday ? "date" : void 0,
tabIndex: 0,
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: spanClass, children: day.date.getDate() })
}
)
},
day.date.getTime()
);
}) })
] });
}
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: cn("bg-background rounded-xl p-4", className), children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-between mb-3.5", children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative", ref: monthPickerContainerRef, children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
"button",
{
onClick: toggleMonthPicker,
className: "flex items-center gap-2 hover:bg-background-100 rounded px-2 py-1 transition-colors",
children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h2", { className: "text-lg font-semibold text-text-950", children: [
MONTH_NAMES[currentDate.getMonth()],
" ",
currentDate.getFullYear()
] }),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"svg",
{
className: `w-4 h-4 text-text-400 transition-transform ${isMonthPickerOpen ? "rotate-180" : ""}`,
fill: "none",
stroke: "currentColor",
viewBox: "0 0 24 24",
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"path",
{
strokeLinecap: "round",
strokeLinejoin: "round",
strokeWidth: 2,
d: "M19 9l-7 7-7-7"
}
)
}
)
]
}
),
isMonthPickerOpen && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
MonthYearPicker,
{
monthPickerRef,
availableYears,
currentDate,
onYearChange: handleYearChange,
onMonthChange: goToMonth
}
)
] }),
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-1", children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"button",
{
onClick: goToPreviousMonth,
className: "p-1 rounded-md hover:bg-background-100 transition-colors",
"aria-label": "M\xEAs anterior",
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"svg",
{
className: "w-6 h-6 text-primary-950",
fill: "none",
stroke: "currentColor",
viewBox: "0 0 24 24",
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"path",
{
strokeLinecap: "round",
strokeLinejoin: "round",
strokeWidth: 2,
d: "M15 19l-7-7 7-7"
}
)
}
)
}
),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"button",
{
onClick: goToNextMonth,
className: "p-1 rounded-md hover:bg-background-100 transition-colors",
"aria-label": "Pr\xF3ximo m\xEAs",
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"svg",
{
className: "w-6 h-6 text-primary-950",
fill: "none",
stroke: "currentColor",
viewBox: "0 0 24 24",
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"path",
{
strokeLinecap: "round",
strokeLinejoin: "round",
strokeWidth: 2,
d: "M9 5l7 7-7 7"
}
)
}
)
}
)
] })
] }),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-7 mb-2", children: WEEK_DAYS.map((day) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"div",
{
className: "h-4 flex items-center justify-center text-xs font-semibold text-text-500",
children: day
},
day
)) }),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-7", children: calendarData.map((day) => {
if (!day.isCurrentMonth) {
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"div",
{
className: "flex items-center justify-center",
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-10 h-10" })
},
day.date.getTime()
);
}
const { dayStyle, textStyle } = getDayStyles(
day,
variant,
showActivities
);
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"div",
{
className: "flex items-center justify-center",
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"button",
{
className: `
w-9 h-9
flex items-center justify-center
text-lg font-normal
cursor-pointer
rounded-full
focus:outline-none focus:ring-2 focus:ring-primary-600 focus:ring-offset-1
${dayStyle}
${textStyle}
`,
onClick: () => handleDateSelect(day),
"aria-label": `${day.date.getDate()} de ${MONTH_NAMES[day.date.getMonth()]}`,
"aria-current": day.isToday ? "date" : void 0,
tabIndex: 0,
children: day.date.getDate()
}
)
},
day.date.getTime()
);
}) })
] });
};
var Calendar_default = Calendar;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
WEEK_DAYS
});
//# sourceMappingURL=index.js.map