@underverse-ui/underverse 1.0.3 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +264 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -2
- package/dist/index.d.ts +35 -2
- package/dist/index.js +264 -50
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -733,6 +733,8 @@ var defaultTranslations = {
|
|
|
733
733
|
month: "Month",
|
|
734
734
|
week: "Week",
|
|
735
735
|
day: "Day",
|
|
736
|
+
sprint: "Sprint",
|
|
737
|
+
sprints: "{n} sprints",
|
|
736
738
|
resourcesHeader: "Resources",
|
|
737
739
|
expandGroup: "Expand group",
|
|
738
740
|
collapseGroup: "Collapse group",
|
|
@@ -809,6 +811,8 @@ var defaultTranslations = {
|
|
|
809
811
|
month: "Th\xE1ng",
|
|
810
812
|
week: "Tu\u1EA7n",
|
|
811
813
|
day: "Ng\xE0y",
|
|
814
|
+
sprint: "Sprint",
|
|
815
|
+
sprints: "{n} sprint",
|
|
812
816
|
resourcesHeader: "T\xE0i nguy\xEAn",
|
|
813
817
|
expandGroup: "M\u1EDF nh\xF3m",
|
|
814
818
|
collapseGroup: "Thu g\u1ECDn nh\xF3m",
|
|
@@ -885,6 +889,8 @@ var defaultTranslations = {
|
|
|
885
889
|
month: "\uC6D4",
|
|
886
890
|
week: "\uC8FC",
|
|
887
891
|
day: "\uC77C",
|
|
892
|
+
sprint: "\uC2A4\uD504\uB9B0\uD2B8",
|
|
893
|
+
sprints: "{n} \uC2A4\uD504\uB9B0\uD2B8",
|
|
888
894
|
resourcesHeader: "\uB9AC\uC18C\uC2A4",
|
|
889
895
|
expandGroup: "\uADF8\uB8F9 \uD3BC\uCE58\uAE30",
|
|
890
896
|
collapseGroup: "\uADF8\uB8F9 \uC811\uAE30",
|
|
@@ -961,6 +967,8 @@ var defaultTranslations = {
|
|
|
961
967
|
month: "\u6708",
|
|
962
968
|
week: "\u9031",
|
|
963
969
|
day: "\u65E5",
|
|
970
|
+
sprint: "\u30B9\u30D7\u30EA\u30F3\u30C8",
|
|
971
|
+
sprints: "{n} \u30B9\u30D7\u30EA\u30F3\u30C8",
|
|
964
972
|
resourcesHeader: "\u30EA\u30BD\u30FC\u30B9",
|
|
965
973
|
expandGroup: "\u30B0\u30EB\u30FC\u30D7\u3092\u5C55\u958B",
|
|
966
974
|
collapseGroup: "\u30B0\u30EB\u30FC\u30D7\u3092\u6298\u308A\u305F\u305F\u3080",
|
|
@@ -8571,6 +8579,10 @@ function startOfZonedMonth(date, timeZone) {
|
|
|
8571
8579
|
const p = getZonedParts(date, timeZone);
|
|
8572
8580
|
return new Date(zonedTimeToUtcMs({ year: p.year, month: p.month, day: 1, hour: 0, minute: 0, second: 0 }, timeZone));
|
|
8573
8581
|
}
|
|
8582
|
+
function startOfZonedYear(date, timeZone) {
|
|
8583
|
+
const p = getZonedParts(date, timeZone);
|
|
8584
|
+
return new Date(zonedTimeToUtcMs({ year: p.year, month: 1, day: 1, hour: 0, minute: 0, second: 0 }, timeZone));
|
|
8585
|
+
}
|
|
8574
8586
|
function addZonedDays(date, days, timeZone) {
|
|
8575
8587
|
const p = getZonedParts(date, timeZone);
|
|
8576
8588
|
return new Date(zonedTimeToUtcMs({ ...p, day: p.day + days }, timeZone));
|
|
@@ -8583,6 +8595,9 @@ function addZonedMonths(date, months, timeZone) {
|
|
|
8583
8595
|
const clampedDay = Math.min(p.day, daysInTargetMonth);
|
|
8584
8596
|
return new Date(zonedTimeToUtcMs({ year: next.year, month: next.month, day: clampedDay, hour: p.hour, minute: p.minute, second: p.second }, timeZone));
|
|
8585
8597
|
}
|
|
8598
|
+
function addZonedYears(date, years, timeZone) {
|
|
8599
|
+
return addZonedMonths(date, years * 12, timeZone);
|
|
8600
|
+
}
|
|
8586
8601
|
function startOfZonedWeek(date, weekStartsOn, timeZone) {
|
|
8587
8602
|
const p = getZonedParts(date, timeZone);
|
|
8588
8603
|
const weekday = new Date(Date.UTC(p.year, p.month - 1, p.day)).getUTCDay();
|
|
@@ -8821,6 +8836,13 @@ function defaultSlotHeader(slotStart, view, locale, timeZone) {
|
|
|
8821
8836
|
if (view === "day") {
|
|
8822
8837
|
return getDtf(locale, timeZone, { hour: "2-digit", minute: "2-digit", hourCycle: "h23" }).format(slotStart);
|
|
8823
8838
|
}
|
|
8839
|
+
if (view === "sprint") {
|
|
8840
|
+
const { week } = getIsoWeekInfo(slotStart, timeZone);
|
|
8841
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "inline-flex flex-col items-center leading-tight", children: [
|
|
8842
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-[10px] font-medium uppercase tracking-wider text-muted-foreground/70", children: "S" }),
|
|
8843
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-sm font-semibold text-foreground", children: String(week).padStart(2, "0") })
|
|
8844
|
+
] });
|
|
8845
|
+
}
|
|
8824
8846
|
const weekday = getDtf(locale, timeZone, { weekday: "short" }).format(slotStart);
|
|
8825
8847
|
const day = getDtf(locale, timeZone, { day: "numeric" }).format(slotStart);
|
|
8826
8848
|
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "inline-flex flex-col items-center leading-tight", children: [
|
|
@@ -8881,7 +8903,10 @@ function getGroupResourceCounts(resources) {
|
|
|
8881
8903
|
function computeSlotStarts(args) {
|
|
8882
8904
|
const { view, date, timeZone, weekStartsOn, dayTimeStepMinutes, dayRangeMode, workHours } = args;
|
|
8883
8905
|
const baseDayStart = startOfZonedDay(date, timeZone);
|
|
8884
|
-
const start = view === "month" ? startOfZonedMonth(date, timeZone) : view === "week" ? startOfZonedWeek(date, weekStartsOn, timeZone) :
|
|
8906
|
+
const start = view === "month" ? startOfZonedMonth(date, timeZone) : view === "week" ? startOfZonedWeek(date, weekStartsOn, timeZone) : view === "sprint" ? (() => {
|
|
8907
|
+
const yearStart = startOfZonedYear(date, timeZone);
|
|
8908
|
+
return startOfZonedWeek(yearStart, weekStartsOn, timeZone);
|
|
8909
|
+
})() : baseDayStart;
|
|
8885
8910
|
if (view === "day") {
|
|
8886
8911
|
const step = Math.max(5, Math.min(240, Math.trunc(dayTimeStepMinutes)));
|
|
8887
8912
|
const stepMs = step * 6e4;
|
|
@@ -8898,6 +8923,21 @@ function computeSlotStarts(args) {
|
|
|
8898
8923
|
}
|
|
8899
8924
|
return { start: start2, end: end3, slotStarts: slotStarts2 };
|
|
8900
8925
|
}
|
|
8926
|
+
if (view === "sprint") {
|
|
8927
|
+
const yearStart = startOfZonedYear(date, timeZone);
|
|
8928
|
+
const nextYearStart = startOfZonedYear(addZonedMonths(yearStart, 12, timeZone), timeZone);
|
|
8929
|
+
const lastDayOfYear = addZonedDays(nextYearStart, -1, timeZone);
|
|
8930
|
+
const lastSlotStart = startOfZonedWeek(lastDayOfYear, weekStartsOn, timeZone);
|
|
8931
|
+
const end2 = addZonedDays(lastSlotStart, 7, timeZone);
|
|
8932
|
+
const slotStarts2 = [];
|
|
8933
|
+
let cur2 = start;
|
|
8934
|
+
let guard2 = 0;
|
|
8935
|
+
while (cur2.getTime() < end2.getTime() && guard2++ < 60) {
|
|
8936
|
+
slotStarts2.push(cur2);
|
|
8937
|
+
cur2 = addZonedDays(cur2, 7, timeZone);
|
|
8938
|
+
}
|
|
8939
|
+
return { start, end: end2, slotStarts: slotStarts2 };
|
|
8940
|
+
}
|
|
8901
8941
|
const end = view === "month" ? startOfZonedMonth(addZonedMonths(start, 1, timeZone), timeZone) : addZonedDays(start, 7, timeZone);
|
|
8902
8942
|
const slotStarts = [];
|
|
8903
8943
|
let cur = start;
|
|
@@ -8946,7 +8986,8 @@ var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
|
8946
8986
|
var VIEW_ICONS = {
|
|
8947
8987
|
month: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.CalendarRange, { className: "h-4 w-4" }),
|
|
8948
8988
|
week: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.CalendarDays, { className: "h-4 w-4" }),
|
|
8949
|
-
day: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Calendar, { className: "h-4 w-4" })
|
|
8989
|
+
day: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Calendar, { className: "h-4 w-4" }),
|
|
8990
|
+
sprint: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.CalendarDays, { className: "h-4 w-4" })
|
|
8950
8991
|
};
|
|
8951
8992
|
function CalendarTimelineHeader(props) {
|
|
8952
8993
|
const {
|
|
@@ -8957,6 +8998,8 @@ function CalendarTimelineHeader(props) {
|
|
|
8957
8998
|
newEventDisabled,
|
|
8958
8999
|
onNewEventClick,
|
|
8959
9000
|
activeView,
|
|
9001
|
+
availableViews,
|
|
9002
|
+
showResourceColumn,
|
|
8960
9003
|
sizeConfig,
|
|
8961
9004
|
navigate,
|
|
8962
9005
|
now,
|
|
@@ -8968,6 +9011,12 @@ function CalendarTimelineHeader(props) {
|
|
|
8968
9011
|
headerRef,
|
|
8969
9012
|
slotHeaderNodes
|
|
8970
9013
|
} = props;
|
|
9014
|
+
const resolvedAvailableViews = React28.useMemo(
|
|
9015
|
+
() => availableViews?.length ? availableViews : ["month", "week", "day", "sprint"],
|
|
9016
|
+
[availableViews]
|
|
9017
|
+
);
|
|
9018
|
+
const showViewSwitcher = resolvedAvailableViews.length > 1;
|
|
9019
|
+
const showLeftColumn = showResourceColumn ?? true;
|
|
8971
9020
|
const dt = useTranslations("DateTimePicker");
|
|
8972
9021
|
const locale = useLocale();
|
|
8973
9022
|
const [todayOpen, setTodayOpen] = React28.useState(false);
|
|
@@ -9026,7 +9075,7 @@ function CalendarTimelineHeader(props) {
|
|
|
9026
9075
|
onApplyDateTime(tempDate);
|
|
9027
9076
|
setTodayOpen(false);
|
|
9028
9077
|
}, [onApplyDateTime, tempDate]);
|
|
9029
|
-
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "sticky top-0 z-30 bg-linear-to-b from-
|
|
9078
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "sticky top-0 z-30 bg-linear-to-b from-card via-card to-card/95 border-b border-border/40 backdrop-blur-xl", children: [
|
|
9030
9079
|
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: cn("flex items-center justify-between gap-4", sizeConfig.headerPaddingClass), children: [
|
|
9031
9080
|
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-center gap-1.5 min-w-0", children: [
|
|
9032
9081
|
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-center bg-muted/40 rounded-full p-1 gap-0.5", children: [
|
|
@@ -9037,7 +9086,7 @@ function CalendarTimelineHeader(props) {
|
|
|
9037
9086
|
size: "icon",
|
|
9038
9087
|
onClick: () => navigate(-1),
|
|
9039
9088
|
"aria-label": labels.prev,
|
|
9040
|
-
className: cn(sizeConfig.controlButtonIconClass, "rounded-full hover:bg-
|
|
9089
|
+
className: cn(sizeConfig.controlButtonIconClass, "rounded-full hover:bg-card/80 transition-all duration-200"),
|
|
9041
9090
|
children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.ChevronLeft, { className: "h-4 w-4" })
|
|
9042
9091
|
}
|
|
9043
9092
|
),
|
|
@@ -9052,7 +9101,7 @@ function CalendarTimelineHeader(props) {
|
|
|
9052
9101
|
{
|
|
9053
9102
|
variant: "ghost",
|
|
9054
9103
|
size: "sm",
|
|
9055
|
-
className: cn(sizeConfig.controlButtonTextClass, "rounded-full hover:bg-
|
|
9104
|
+
className: cn(sizeConfig.controlButtonTextClass, "rounded-full hover:bg-card/80 font-medium transition-all duration-200"),
|
|
9056
9105
|
children: labels.today
|
|
9057
9106
|
}
|
|
9058
9107
|
),
|
|
@@ -9132,7 +9181,7 @@ function CalendarTimelineHeader(props) {
|
|
|
9132
9181
|
size: "icon",
|
|
9133
9182
|
onClick: () => navigate(1),
|
|
9134
9183
|
"aria-label": labels.next,
|
|
9135
|
-
className: cn(sizeConfig.controlButtonIconClass, "rounded-full hover:bg-
|
|
9184
|
+
className: cn(sizeConfig.controlButtonIconClass, "rounded-full hover:bg-card/80 transition-all duration-200"),
|
|
9136
9185
|
children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.ChevronRight, { className: "h-4 w-4" })
|
|
9137
9186
|
}
|
|
9138
9187
|
)
|
|
@@ -9152,7 +9201,7 @@ function CalendarTimelineHeader(props) {
|
|
|
9152
9201
|
children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "hidden sm:inline", children: newEventLabel })
|
|
9153
9202
|
}
|
|
9154
9203
|
) : null,
|
|
9155
|
-
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex items-center bg-muted/40 rounded-full p-1 gap-0.5", children:
|
|
9204
|
+
showViewSwitcher ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex items-center bg-muted/40 rounded-full p-1 gap-0.5", children: resolvedAvailableViews.map((v) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
9156
9205
|
Button_default,
|
|
9157
9206
|
{
|
|
9158
9207
|
variant: activeView === v ? "default" : "ghost",
|
|
@@ -9161,7 +9210,7 @@ function CalendarTimelineHeader(props) {
|
|
|
9161
9210
|
className: cn(
|
|
9162
9211
|
sizeConfig.controlButtonTextClass,
|
|
9163
9212
|
"rounded-full font-medium transition-all duration-200 gap-1.5",
|
|
9164
|
-
activeView === v ? "bg-primary text-primary-foreground shadow-sm shadow-primary/25" : "hover:bg-
|
|
9213
|
+
activeView === v ? "bg-primary text-primary-foreground shadow-sm shadow-primary/25" : "hover:bg-card/80 text-muted-foreground hover:text-foreground"
|
|
9165
9214
|
),
|
|
9166
9215
|
children: [
|
|
9167
9216
|
VIEW_ICONS[v],
|
|
@@ -9169,14 +9218,14 @@ function CalendarTimelineHeader(props) {
|
|
|
9169
9218
|
]
|
|
9170
9219
|
},
|
|
9171
9220
|
v
|
|
9172
|
-
)) })
|
|
9221
|
+
)) }) : null
|
|
9173
9222
|
] })
|
|
9174
9223
|
] }),
|
|
9175
9224
|
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex border-t border-border/20", children: [
|
|
9176
|
-
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
9225
|
+
showLeftColumn ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
9177
9226
|
"div",
|
|
9178
9227
|
{
|
|
9179
|
-
className: "shrink-0 border-r border-border/30 bg-
|
|
9228
|
+
className: "shrink-0 border-r border-border/30 bg-card/60 flex items-center justify-center relative group/uv-ct-top-left",
|
|
9180
9229
|
style: { width: effectiveResourceColumnWidth, minWidth: effectiveResourceColumnWidth },
|
|
9181
9230
|
children: [
|
|
9182
9231
|
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "text-xs font-medium text-muted-foreground/70 uppercase tracking-wider", children: resourcesHeaderLabel }),
|
|
@@ -9202,7 +9251,7 @@ function CalendarTimelineHeader(props) {
|
|
|
9202
9251
|
) : null
|
|
9203
9252
|
]
|
|
9204
9253
|
}
|
|
9205
|
-
),
|
|
9254
|
+
) : null,
|
|
9206
9255
|
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { ref: headerRef, className: "flex-1 min-w-0 overflow-x-auto overflow-y-hidden scrollbar-none", children: slotHeaderNodes })
|
|
9207
9256
|
] })
|
|
9208
9257
|
] });
|
|
@@ -9231,7 +9280,7 @@ function DefaultGroupRow(props) {
|
|
|
9231
9280
|
"span",
|
|
9232
9281
|
{
|
|
9233
9282
|
className: cn(
|
|
9234
|
-
"inline-flex items-center justify-center w-5 h-5 rounded-md bg-
|
|
9283
|
+
"inline-flex items-center justify-center w-5 h-5 rounded-md bg-card/60 transition-transform duration-200",
|
|
9235
9284
|
collapsed ? "" : "rotate-180"
|
|
9236
9285
|
),
|
|
9237
9286
|
children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react19.ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
@@ -9252,7 +9301,7 @@ function ResourceRowCell(props) {
|
|
|
9252
9301
|
"div",
|
|
9253
9302
|
{
|
|
9254
9303
|
className: cn(
|
|
9255
|
-
"h-full w-full flex items-center border-b border-border/30 bg-linear-to-r from-
|
|
9304
|
+
"h-full w-full flex items-center border-b border-border/30 bg-linear-to-r from-card to-card/95 relative",
|
|
9256
9305
|
sizeConfig.resourceRowClass,
|
|
9257
9306
|
"hover:from-muted/30 hover:to-muted/10 transition-all duration-200 group/uv-ct-row-header"
|
|
9258
9307
|
),
|
|
@@ -9312,7 +9361,7 @@ var CalendarTimelineGridOverlay = React29.memo(function CalendarTimelineGridOver
|
|
|
9312
9361
|
if (showToday && idx === todaySlotIdx) return null;
|
|
9313
9362
|
const left = slotLefts[idx] ?? 0;
|
|
9314
9363
|
const width = slotWidths[idx] ?? 0;
|
|
9315
|
-
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "absolute top-0 h-full bg-
|
|
9364
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "absolute top-0 h-full bg-muted/20", style: { left, width }, "aria-hidden": true }, `we_${idx}`);
|
|
9316
9365
|
}) : null,
|
|
9317
9366
|
showToday ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
9318
9367
|
"div",
|
|
@@ -9375,7 +9424,8 @@ function useTimelineSlots(args) {
|
|
|
9375
9424
|
dayRangeMode,
|
|
9376
9425
|
workHours,
|
|
9377
9426
|
resolvedNow,
|
|
9378
|
-
formatters
|
|
9427
|
+
formatters,
|
|
9428
|
+
dueDateSprint
|
|
9379
9429
|
} = args;
|
|
9380
9430
|
const { slots, range } = React31.useMemo(() => {
|
|
9381
9431
|
const { start, end, slotStarts: slotStarts2 } = computeSlotStarts({
|
|
@@ -9388,17 +9438,89 @@ function useTimelineSlots(args) {
|
|
|
9388
9438
|
workHours
|
|
9389
9439
|
});
|
|
9390
9440
|
const todayStart = startOfZonedDay(resolvedNow, resolvedTimeZone).getTime();
|
|
9391
|
-
const
|
|
9441
|
+
const nowMs = resolvedNow.getTime();
|
|
9442
|
+
const sprintDefs = (() => {
|
|
9443
|
+
if (activeView !== "sprint") return [];
|
|
9444
|
+
if (!dueDateSprint) return [];
|
|
9445
|
+
const out = [];
|
|
9446
|
+
for (const v of Object.values(dueDateSprint)) {
|
|
9447
|
+
const startInput = v.range_date?.start;
|
|
9448
|
+
const endInput = v.range_date?.end;
|
|
9449
|
+
if (startInput == null || endInput == null) continue;
|
|
9450
|
+
const startRaw = toDate2(startInput);
|
|
9451
|
+
const endRaw = toDate2(endInput);
|
|
9452
|
+
if (Number.isNaN(startRaw.getTime()) || Number.isNaN(endRaw.getTime())) continue;
|
|
9453
|
+
const startMs = startOfZonedDay(startRaw, resolvedTimeZone).getTime();
|
|
9454
|
+
const endMs = startOfZonedDay(endRaw, resolvedTimeZone).getTime();
|
|
9455
|
+
if (!Number.isFinite(startMs) || !Number.isFinite(endMs)) continue;
|
|
9456
|
+
if (endMs <= startMs) continue;
|
|
9457
|
+
out.push({ startMs, endMs, title: v.title });
|
|
9458
|
+
}
|
|
9459
|
+
out.sort((a, b) => a.startMs - b.startMs);
|
|
9460
|
+
return out;
|
|
9461
|
+
})();
|
|
9462
|
+
const sprintRangeText = (() => {
|
|
9463
|
+
if (activeView !== "sprint") return null;
|
|
9464
|
+
const df = getDtf(resolvedLocale, resolvedTimeZone, { month: "short", day: "numeric" });
|
|
9465
|
+
return (startMs, endMs) => {
|
|
9466
|
+
const a = df.format(new Date(startMs));
|
|
9467
|
+
const b = df.format(new Date(endMs - 1));
|
|
9468
|
+
return a === b ? a : `${a}\u2013${b}`;
|
|
9469
|
+
};
|
|
9470
|
+
})();
|
|
9471
|
+
const matchSprintDef = (slotStart, idx) => {
|
|
9472
|
+
if (activeView !== "sprint") return null;
|
|
9473
|
+
if (sprintDefs.length === 0) return null;
|
|
9474
|
+
const sMs = startOfZonedDay(slotStart, resolvedTimeZone).getTime();
|
|
9475
|
+
const byRange = sprintDefs.find((d) => sMs >= d.startMs && sMs < d.endMs) ?? null;
|
|
9476
|
+
return byRange ?? sprintDefs[idx] ?? null;
|
|
9477
|
+
};
|
|
9478
|
+
const slotItems = slotStarts2.map((s, idx) => ({
|
|
9392
9479
|
start: s,
|
|
9393
|
-
label: formatters?.slotHeader?.(s, { view: activeView, locale: resolvedLocale, timeZone: resolvedTimeZone }) ??
|
|
9394
|
-
|
|
9395
|
-
|
|
9480
|
+
label: formatters?.slotHeader?.(s, { view: activeView, locale: resolvedLocale, timeZone: resolvedTimeZone }) ?? (() => {
|
|
9481
|
+
if (activeView !== "sprint") return defaultSlotHeader(s, activeView, resolvedLocale, resolvedTimeZone);
|
|
9482
|
+
const match = matchSprintDef(s, idx);
|
|
9483
|
+
if (match && sprintRangeText) {
|
|
9484
|
+
const rangeText = sprintRangeText(match.startMs, match.endMs);
|
|
9485
|
+
return React31.createElement(
|
|
9486
|
+
"span",
|
|
9487
|
+
{ className: "inline-flex flex-col items-center leading-tight" },
|
|
9488
|
+
React31.createElement("span", { className: "text-[11px] font-semibold text-foreground truncate max-w-[8rem]" }, match.title),
|
|
9489
|
+
React31.createElement("span", { className: "text-[10px] font-medium text-muted-foreground/70" }, rangeText)
|
|
9490
|
+
);
|
|
9491
|
+
}
|
|
9492
|
+
return React31.createElement(
|
|
9493
|
+
"span",
|
|
9494
|
+
{ className: "inline-flex flex-col items-center leading-tight" },
|
|
9495
|
+
React31.createElement("span", { className: "text-[10px] font-medium uppercase tracking-wider text-muted-foreground/70" }, "S"),
|
|
9496
|
+
React31.createElement("span", { className: "text-sm font-semibold text-foreground" }, String(idx + 1).padStart(2, "0"))
|
|
9497
|
+
);
|
|
9498
|
+
})(),
|
|
9499
|
+
isToday: (() => {
|
|
9500
|
+
if (activeView !== "sprint") return startOfZonedDay(s, resolvedTimeZone).getTime() === todayStart;
|
|
9501
|
+
const match = matchSprintDef(s, idx);
|
|
9502
|
+
const sprintEndMs = match ? match.endMs : addZonedDays(s, 7, resolvedTimeZone).getTime();
|
|
9503
|
+
return nowMs >= s.getTime() && nowMs < sprintEndMs;
|
|
9504
|
+
})(),
|
|
9505
|
+
isWeekend: activeView === "day" || activeView === "sprint" ? false : (() => {
|
|
9396
9506
|
const wd = getZonedWeekday(s, resolvedTimeZone);
|
|
9397
9507
|
return wd === 0 || wd === 6;
|
|
9398
9508
|
})()
|
|
9399
9509
|
}));
|
|
9400
9510
|
return { slots: slotItems, range: { start, end } };
|
|
9401
|
-
}, [
|
|
9511
|
+
}, [
|
|
9512
|
+
activeView,
|
|
9513
|
+
activeDate,
|
|
9514
|
+
dayRangeMode,
|
|
9515
|
+
dayTimeStepMinutes,
|
|
9516
|
+
dueDateSprint,
|
|
9517
|
+
formatters,
|
|
9518
|
+
resolvedLocale,
|
|
9519
|
+
resolvedNow,
|
|
9520
|
+
resolvedTimeZone,
|
|
9521
|
+
weekStartsOn,
|
|
9522
|
+
workHours
|
|
9523
|
+
]);
|
|
9402
9524
|
const slotStarts = React31.useMemo(() => slots.map((s) => s.start), [slots]);
|
|
9403
9525
|
const todaySlotIdx = React31.useMemo(() => slots.findIndex((s) => s.isToday), [slots]);
|
|
9404
9526
|
const weekendSlotIdxs = React31.useMemo(() => {
|
|
@@ -9685,9 +9807,11 @@ function CalendarTimeline({
|
|
|
9685
9807
|
eventSheetOpen,
|
|
9686
9808
|
defaultEventSheetOpen,
|
|
9687
9809
|
onEventSheetOpenChange,
|
|
9810
|
+
onlyView,
|
|
9688
9811
|
view,
|
|
9689
9812
|
defaultView = "month",
|
|
9690
9813
|
onViewChange,
|
|
9814
|
+
dueDateSprint,
|
|
9691
9815
|
date,
|
|
9692
9816
|
defaultDate,
|
|
9693
9817
|
onDateChange,
|
|
@@ -9700,6 +9824,7 @@ function CalendarTimeline({
|
|
|
9700
9824
|
groupCollapsed,
|
|
9701
9825
|
defaultGroupCollapsed,
|
|
9702
9826
|
onGroupCollapsedChange,
|
|
9827
|
+
hideResourceColumn,
|
|
9703
9828
|
resourceColumnWidth,
|
|
9704
9829
|
defaultResourceColumnWidth,
|
|
9705
9830
|
onResourceColumnWidthChange,
|
|
@@ -9719,6 +9844,8 @@ function CalendarTimeline({
|
|
|
9719
9844
|
adaptiveSlotWidths,
|
|
9720
9845
|
dayEventStyle = "span",
|
|
9721
9846
|
dayEventMaxWidth,
|
|
9847
|
+
monthEventStyle = "span",
|
|
9848
|
+
monthEventMaxWidth,
|
|
9722
9849
|
dayTimeStepMinutes = 60,
|
|
9723
9850
|
enableEventTooltips = true,
|
|
9724
9851
|
dayHeaderMode = "full",
|
|
@@ -9772,6 +9899,7 @@ function CalendarTimeline({
|
|
|
9772
9899
|
},
|
|
9773
9900
|
[isControlledEventSheetOpen, onEventSheetOpenChange, setSelectedEventId]
|
|
9774
9901
|
);
|
|
9902
|
+
const showResourceColumn = !hideResourceColumn;
|
|
9775
9903
|
const sizeConfig = React32.useMemo(() => getSizeConfig(size), [size]);
|
|
9776
9904
|
const densityClass = sizeConfig.densityClass;
|
|
9777
9905
|
const eventHeight = sizeConfig.eventHeight;
|
|
@@ -9781,16 +9909,18 @@ function CalendarTimeline({
|
|
|
9781
9909
|
const cfg = enableLayoutResize;
|
|
9782
9910
|
if (!cfg) return false;
|
|
9783
9911
|
if (isViewOnly) return false;
|
|
9912
|
+
if (!showResourceColumn) return false;
|
|
9784
9913
|
if (cfg === true) return true;
|
|
9785
9914
|
return cfg.column !== false;
|
|
9786
|
-
}, [enableLayoutResize, isViewOnly]);
|
|
9915
|
+
}, [enableLayoutResize, isViewOnly, showResourceColumn]);
|
|
9787
9916
|
const canResizeRow = React32.useMemo(() => {
|
|
9788
9917
|
const cfg = enableLayoutResize;
|
|
9789
9918
|
if (!cfg) return false;
|
|
9790
9919
|
if (isViewOnly) return false;
|
|
9920
|
+
if (!showResourceColumn) return false;
|
|
9791
9921
|
if (cfg === true) return true;
|
|
9792
9922
|
return cfg.row !== false;
|
|
9793
|
-
}, [enableLayoutResize, isViewOnly]);
|
|
9923
|
+
}, [enableLayoutResize, isViewOnly, showResourceColumn]);
|
|
9794
9924
|
const isControlledResourceColumnWidth = resourceColumnWidth !== void 0;
|
|
9795
9925
|
const [internalResourceColumnWidth, setInternalResourceColumnWidth] = React32.useState(() => {
|
|
9796
9926
|
const init = defaultResourceColumnWidth ?? sizeConfig.resourceColumnWidth;
|
|
@@ -9801,7 +9931,7 @@ function CalendarTimeline({
|
|
|
9801
9931
|
if (defaultResourceColumnWidth == null) return;
|
|
9802
9932
|
setInternalResourceColumnWidth(defaultResourceColumnWidth);
|
|
9803
9933
|
}, [defaultResourceColumnWidth, isControlledResourceColumnWidth]);
|
|
9804
|
-
const effectiveResourceColumnWidth = isControlledResourceColumnWidth ? resourceColumnWidth : internalResourceColumnWidth;
|
|
9934
|
+
const effectiveResourceColumnWidth = showResourceColumn ? isControlledResourceColumnWidth ? resourceColumnWidth : internalResourceColumnWidth : 0;
|
|
9805
9935
|
const isControlledRowHeight = rowHeight !== void 0;
|
|
9806
9936
|
const [internalRowHeight, setInternalRowHeight] = React32.useState(() => defaultRowHeight ?? sizeConfig.rowHeight);
|
|
9807
9937
|
React32.useEffect(() => {
|
|
@@ -9810,14 +9940,29 @@ function CalendarTimeline({
|
|
|
9810
9940
|
setInternalRowHeight(defaultRowHeight);
|
|
9811
9941
|
}, [defaultRowHeight, isControlledRowHeight]);
|
|
9812
9942
|
const effectiveRowHeight = isControlledRowHeight ? rowHeight : internalRowHeight;
|
|
9813
|
-
const
|
|
9943
|
+
const baseSlotMinWidth = slotMinWidth ?? sizeConfig.slotMinWidth;
|
|
9814
9944
|
const colMin = minResourceColumnWidth ?? 160;
|
|
9815
9945
|
const colMax = maxResourceColumnWidth ?? 520;
|
|
9816
9946
|
const rowMin = minRowHeight ?? 36;
|
|
9817
9947
|
const rowMax = maxRowHeight ?? 120;
|
|
9948
|
+
const availableViews = React32.useMemo(
|
|
9949
|
+
() => onlyView ? [onlyView] : ["month", "week", "day", "sprint"],
|
|
9950
|
+
[onlyView]
|
|
9951
|
+
);
|
|
9818
9952
|
const isControlledView = view !== void 0;
|
|
9819
|
-
const [internalView, setInternalView] = React32.useState(defaultView);
|
|
9820
|
-
const activeView = isControlledView ? view : internalView;
|
|
9953
|
+
const [internalView, setInternalView] = React32.useState(() => onlyView ?? defaultView);
|
|
9954
|
+
const activeView = onlyView ? onlyView : isControlledView ? view : internalView;
|
|
9955
|
+
const effectiveSlotMinWidth = React32.useMemo(() => {
|
|
9956
|
+
if (slotMinWidth == null) {
|
|
9957
|
+
if (activeView === "month" && monthEventStyle === "compact") {
|
|
9958
|
+
return clamp4(Math.round(sizeConfig.slotMinWidth * 0.55), 32, sizeConfig.slotMinWidth);
|
|
9959
|
+
}
|
|
9960
|
+
if (activeView === "sprint") {
|
|
9961
|
+
return clamp4(Math.round(sizeConfig.slotMinWidth * 0.4), 18, 48);
|
|
9962
|
+
}
|
|
9963
|
+
}
|
|
9964
|
+
return baseSlotMinWidth;
|
|
9965
|
+
}, [activeView, baseSlotMinWidth, monthEventStyle, sizeConfig.slotMinWidth, slotMinWidth]);
|
|
9821
9966
|
const isControlledDate = date !== void 0;
|
|
9822
9967
|
const [internalDate, setInternalDate] = React32.useState(() => defaultDate ?? /* @__PURE__ */ new Date());
|
|
9823
9968
|
const activeDate = isControlledDate ? date : internalDate;
|
|
@@ -9830,6 +9975,7 @@ function CalendarTimeline({
|
|
|
9830
9975
|
month: labels?.month ?? t("month"),
|
|
9831
9976
|
week: labels?.week ?? t("week"),
|
|
9832
9977
|
day: labels?.day ?? t("day"),
|
|
9978
|
+
sprint: labels?.sprint ?? t("sprint"),
|
|
9833
9979
|
newEvent: labels?.newEvent ?? t("newEvent"),
|
|
9834
9980
|
createEventTitle: labels?.createEventTitle ?? t("createEventTitle"),
|
|
9835
9981
|
create: labels?.create ?? t("create"),
|
|
@@ -9846,10 +9992,11 @@ function CalendarTimeline({
|
|
|
9846
9992
|
);
|
|
9847
9993
|
const setView = React32.useCallback(
|
|
9848
9994
|
(next) => {
|
|
9995
|
+
if (onlyView) return;
|
|
9849
9996
|
if (!isControlledView) setInternalView(next);
|
|
9850
9997
|
onViewChange?.(next);
|
|
9851
9998
|
},
|
|
9852
|
-
[isControlledView, onViewChange]
|
|
9999
|
+
[isControlledView, onViewChange, onlyView]
|
|
9853
10000
|
);
|
|
9854
10001
|
const setDate = React32.useCallback(
|
|
9855
10002
|
(next) => {
|
|
@@ -9869,6 +10016,10 @@ function CalendarTimeline({
|
|
|
9869
10016
|
setDate(addZonedDays(base, dir * 7, resolvedTimeZone));
|
|
9870
10017
|
return;
|
|
9871
10018
|
}
|
|
10019
|
+
if (activeView === "sprint") {
|
|
10020
|
+
setDate(addZonedYears(base, dir, resolvedTimeZone));
|
|
10021
|
+
return;
|
|
10022
|
+
}
|
|
9872
10023
|
setDate(addZonedDays(base, dir, resolvedTimeZone));
|
|
9873
10024
|
},
|
|
9874
10025
|
[activeDate, activeView, resolvedTimeZone, setDate]
|
|
@@ -9894,7 +10045,8 @@ function CalendarTimeline({
|
|
|
9894
10045
|
dayRangeMode,
|
|
9895
10046
|
workHours,
|
|
9896
10047
|
resolvedNow,
|
|
9897
|
-
formatters
|
|
10048
|
+
formatters,
|
|
10049
|
+
dueDateSprint
|
|
9898
10050
|
});
|
|
9899
10051
|
React32.useEffect(() => {
|
|
9900
10052
|
onRangeChange?.(range);
|
|
@@ -9958,7 +10110,7 @@ function CalendarTimeline({
|
|
|
9958
10110
|
setEventSheetOpen(false);
|
|
9959
10111
|
}
|
|
9960
10112
|
}, [activeEventSheetOpen, activeSelectedEventId, effectiveEnableEventSheet, selectedEvent, setEventSheetOpen]);
|
|
9961
|
-
useHorizontalScrollSync({ bodyRef, headerRef, leftRef });
|
|
10113
|
+
useHorizontalScrollSync({ bodyRef, headerRef, leftRef: showResourceColumn ? leftRef : void 0 });
|
|
9962
10114
|
const virt = virtualization?.enabled;
|
|
9963
10115
|
const overscan = virtualization?.overscan ?? 8;
|
|
9964
10116
|
const isControlledRowHeights = rowHeights !== void 0;
|
|
@@ -10140,9 +10292,15 @@ function CalendarTimeline({
|
|
|
10140
10292
|
const rangeText = ya === yb ? `${a} \u2013 ${b}, ${ya}` : `${a}, ${ya} \u2013 ${b}, ${yb}`;
|
|
10141
10293
|
return `${l.week} ${week} \u2022 ${rangeText}`;
|
|
10142
10294
|
}
|
|
10295
|
+
if (activeView === "sprint") {
|
|
10296
|
+
const fmtYear = getDtf(resolvedLocale, resolvedTimeZone, { year: "numeric" });
|
|
10297
|
+
const yearText = fmtYear.format(activeDate);
|
|
10298
|
+
const count = Math.max(0, slots.length);
|
|
10299
|
+
return `${l.sprint} \u2022 ${yearText} \u2022 ${t("sprints", { n: count })}`;
|
|
10300
|
+
}
|
|
10143
10301
|
const fmt = getDtf(resolvedLocale, resolvedTimeZone, { weekday: "long", year: "numeric", month: "long", day: "numeric" });
|
|
10144
10302
|
return fmt.format(range.start);
|
|
10145
|
-
}, [activeDate, activeView, formatters, l.week, range.end, range.start, resolvedLocale, resolvedTimeZone]);
|
|
10303
|
+
}, [activeDate, activeView, formatters, l.sprint, l.week, range.end, range.start, resolvedLocale, resolvedTimeZone, slots.length, t]);
|
|
10146
10304
|
const createMode = interactions?.createMode ?? "drag";
|
|
10147
10305
|
const canCreate = !isViewOnly && (interactions?.creatable ?? false) && !!onCreateEvent;
|
|
10148
10306
|
const [createOpen, setCreateOpen] = React32.useState(false);
|
|
@@ -10157,11 +10315,54 @@ function CalendarTimeline({
|
|
|
10157
10315
|
disabled: r.disabled ?? false
|
|
10158
10316
|
}));
|
|
10159
10317
|
}, [resources]);
|
|
10160
|
-
const
|
|
10318
|
+
const formatCreateBoundaryLabel = React32.useMemo(() => {
|
|
10161
10319
|
const timeFmt = getDtf(resolvedLocale, resolvedTimeZone, { hour: "2-digit", minute: "2-digit", hourCycle: "h23" });
|
|
10162
10320
|
const dayFmt = getDtf(resolvedLocale, resolvedTimeZone, { weekday: "short", month: "short", day: "numeric" });
|
|
10163
|
-
|
|
10164
|
-
|
|
10321
|
+
const yearFmt = getDtf(resolvedLocale, resolvedTimeZone, { year: "numeric" });
|
|
10322
|
+
const sprintDefs = (() => {
|
|
10323
|
+
if (!dueDateSprint) return [];
|
|
10324
|
+
const out = [];
|
|
10325
|
+
for (const v of Object.values(dueDateSprint)) {
|
|
10326
|
+
const startInput = v.range_date?.start;
|
|
10327
|
+
const endInput = v.range_date?.end;
|
|
10328
|
+
if (startInput == null || endInput == null) continue;
|
|
10329
|
+
const startRaw = toDate2(startInput);
|
|
10330
|
+
const endRaw = toDate2(endInput);
|
|
10331
|
+
if (Number.isNaN(startRaw.getTime()) || Number.isNaN(endRaw.getTime())) continue;
|
|
10332
|
+
const startMs = startOfZonedDay(startRaw, resolvedTimeZone).getTime();
|
|
10333
|
+
const endMs = startOfZonedDay(endRaw, resolvedTimeZone).getTime();
|
|
10334
|
+
if (endMs <= startMs) continue;
|
|
10335
|
+
out.push({ startMs, endMs, title: v.title });
|
|
10336
|
+
}
|
|
10337
|
+
out.sort((a, b) => a.startMs - b.startMs);
|
|
10338
|
+
return out;
|
|
10339
|
+
})();
|
|
10340
|
+
const sprintTitleForStart = (slotStart, idx) => {
|
|
10341
|
+
if (activeView !== "sprint") return null;
|
|
10342
|
+
if (sprintDefs.length === 0) return null;
|
|
10343
|
+
const sMs = startOfZonedDay(slotStart, resolvedTimeZone).getTime();
|
|
10344
|
+
const match = sprintDefs.find((d) => sMs >= d.startMs && sMs < d.endMs) ?? sprintDefs[idx] ?? null;
|
|
10345
|
+
if (!match) return null;
|
|
10346
|
+
return typeof match.title === "string" || typeof match.title === "number" ? String(match.title) : null;
|
|
10347
|
+
};
|
|
10348
|
+
return (d, opts) => {
|
|
10349
|
+
if (activeView === "day") return timeFmt.format(d);
|
|
10350
|
+
if (activeView === "sprint") {
|
|
10351
|
+
const y = yearFmt.format(d);
|
|
10352
|
+
const idx = opts?.boundaryIdx;
|
|
10353
|
+
if (typeof idx === "number") {
|
|
10354
|
+
const slotStart = slotStarts[clamp4(idx, 0, Math.max(0, slotStarts.length - 1))] ?? d;
|
|
10355
|
+
const dynamicTitle = sprintTitleForStart(slotStart, idx);
|
|
10356
|
+
if (dynamicTitle) return `${dynamicTitle} \u2022 ${dayFmt.format(d)}, ${y}`;
|
|
10357
|
+
const sprintNumber = opts?.kind === "start" ? idx + 1 : Math.min(idx + 1, Math.max(1, slotStarts.length));
|
|
10358
|
+
const sprintText = `${l.sprint} ${String(sprintNumber).padStart(2, "0")}`;
|
|
10359
|
+
const dateText = dayFmt.format(d);
|
|
10360
|
+
return `${sprintText} \u2022 ${dateText}, ${y}`;
|
|
10361
|
+
}
|
|
10362
|
+
}
|
|
10363
|
+
return dayFmt.format(d);
|
|
10364
|
+
};
|
|
10365
|
+
}, [activeView, dueDateSprint, l.sprint, resolvedLocale, resolvedTimeZone, slotStarts, slotStarts.length]);
|
|
10165
10366
|
const openCreate = React32.useCallback(() => {
|
|
10166
10367
|
if (!canCreate) return;
|
|
10167
10368
|
if (activeEventSheetOpen) setEventSheetOpen(false);
|
|
@@ -10198,16 +10399,16 @@ function CalendarTimeline({
|
|
|
10198
10399
|
setCreateEndIdx((prev) => Math.min(slots.length, Math.max(prev, createStartIdx + 1)));
|
|
10199
10400
|
}, [createStartIdx, slots.length]);
|
|
10200
10401
|
const createStartOptions = React32.useMemo(() => {
|
|
10201
|
-
return slotStarts.map((d, idx) => ({ label:
|
|
10202
|
-
}, [
|
|
10402
|
+
return slotStarts.map((d, idx) => ({ label: formatCreateBoundaryLabel(d, { kind: "start", boundaryIdx: idx }), value: idx }));
|
|
10403
|
+
}, [formatCreateBoundaryLabel, slotStarts]);
|
|
10203
10404
|
const createEndOptions = React32.useMemo(() => {
|
|
10204
10405
|
const out = [];
|
|
10205
10406
|
for (let idx = createStartIdx + 1; idx <= slotStarts.length; idx++) {
|
|
10206
10407
|
const boundary = idx >= slotStarts.length ? range.end : slotStarts[idx];
|
|
10207
|
-
out.push({ label:
|
|
10408
|
+
out.push({ label: formatCreateBoundaryLabel(boundary, { kind: "end", boundaryIdx: idx }), value: idx });
|
|
10208
10409
|
}
|
|
10209
10410
|
return out;
|
|
10210
|
-
}, [createStartIdx, range.end,
|
|
10411
|
+
}, [createStartIdx, formatCreateBoundaryLabel, range.end, slotStarts]);
|
|
10211
10412
|
const commitCreate = React32.useCallback(() => {
|
|
10212
10413
|
if (!onCreateEvent) return;
|
|
10213
10414
|
if (!createResourceId) return;
|
|
@@ -10261,6 +10462,9 @@ function CalendarTimeline({
|
|
|
10261
10462
|
const stepMs = Math.trunc(Math.max(5, Math.min(240, Math.trunc(dayTimeStepMinutes))) * 6e4);
|
|
10262
10463
|
return { start, end: new Date(start.getTime() + stepMs) };
|
|
10263
10464
|
}
|
|
10465
|
+
if (activeView === "sprint") {
|
|
10466
|
+
return { start, end: addZonedDays(start, 7, resolvedTimeZone) };
|
|
10467
|
+
}
|
|
10264
10468
|
return { start, end: addZonedDays(start, 1, resolvedTimeZone) };
|
|
10265
10469
|
},
|
|
10266
10470
|
[activeView, dayTimeStepMinutes, resolvedTimeZone, slotStarts]
|
|
@@ -10543,7 +10747,7 @@ function CalendarTimeline({
|
|
|
10543
10747
|
className: cn(
|
|
10544
10748
|
sizeConfig.slotHeaderClass,
|
|
10545
10749
|
activeView !== "day" && s.isToday && "bg-primary/8 border-l-primary/40",
|
|
10546
|
-
activeView !== "day" && !s.isToday && s.isWeekend && "bg-
|
|
10750
|
+
activeView !== "day" && !s.isToday && s.isWeekend && "bg-muted/25"
|
|
10547
10751
|
),
|
|
10548
10752
|
dayHeaderMarks
|
|
10549
10753
|
},
|
|
@@ -10574,11 +10778,13 @@ function CalendarTimeline({
|
|
|
10574
10778
|
{
|
|
10575
10779
|
title,
|
|
10576
10780
|
resourcesHeaderLabel: t("resourcesHeader"),
|
|
10577
|
-
labels: { today: l.today, prev: l.prev, next: l.next, month: l.month, week: l.week, day: l.day },
|
|
10781
|
+
labels: { today: l.today, prev: l.prev, next: l.next, month: l.month, week: l.week, day: l.day, sprint: l.sprint },
|
|
10578
10782
|
newEventLabel: l.newEvent,
|
|
10579
10783
|
newEventDisabled: isViewOnly || !canCreate || resources.length === 0,
|
|
10580
10784
|
onNewEventClick: isViewOnly ? void 0 : openCreate,
|
|
10581
10785
|
activeView,
|
|
10786
|
+
availableViews,
|
|
10787
|
+
showResourceColumn,
|
|
10582
10788
|
sizeConfig,
|
|
10583
10789
|
navigate,
|
|
10584
10790
|
now: resolvedNow,
|
|
@@ -10607,8 +10813,9 @@ function CalendarTimeline({
|
|
|
10607
10813
|
"div",
|
|
10608
10814
|
{
|
|
10609
10815
|
className: cn(
|
|
10610
|
-
"
|
|
10611
|
-
"shadow-sm hover:shadow-md
|
|
10816
|
+
"rounded-2xl md:rounded-3xl overflow-hidden bg-card text-card-foreground backdrop-blur-sm",
|
|
10817
|
+
"border border-border shadow-sm md:hover:shadow-md",
|
|
10818
|
+
"transition-[transform,box-shadow,border-color,background-color] duration-300 ease-soft",
|
|
10612
10819
|
densityClass,
|
|
10613
10820
|
className
|
|
10614
10821
|
),
|
|
@@ -10616,7 +10823,7 @@ function CalendarTimeline({
|
|
|
10616
10823
|
children: [
|
|
10617
10824
|
Header,
|
|
10618
10825
|
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex min-h-0", children: [
|
|
10619
|
-
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
10826
|
+
showResourceColumn ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
10620
10827
|
"div",
|
|
10621
10828
|
{
|
|
10622
10829
|
ref: leftRef,
|
|
@@ -10645,7 +10852,7 @@ function CalendarTimeline({
|
|
|
10645
10852
|
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { style: { height: bottomSpacer } })
|
|
10646
10853
|
]
|
|
10647
10854
|
}
|
|
10648
|
-
),
|
|
10855
|
+
) : null,
|
|
10649
10856
|
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
10650
10857
|
"div",
|
|
10651
10858
|
{
|
|
@@ -10741,12 +10948,19 @@ function CalendarTimeline({
|
|
|
10741
10948
|
})();
|
|
10742
10949
|
const resource = resourceById.get(ev.resourceId);
|
|
10743
10950
|
const tooltipTitle = ev.title || ev.id;
|
|
10744
|
-
const shouldCompact = activeView === "day" && dayEventStyle === "compact";
|
|
10951
|
+
const shouldCompact = activeView === "day" && dayEventStyle === "compact" || activeView === "month" && monthEventStyle === "compact";
|
|
10745
10952
|
const eventInsetX = 2;
|
|
10746
10953
|
const leftInset = left + eventInsetX;
|
|
10747
10954
|
const widthInset = Math.max(1, width - eventInsetX * 2);
|
|
10748
|
-
const defaultMaxVisual =
|
|
10749
|
-
|
|
10955
|
+
const defaultMaxVisual = (() => {
|
|
10956
|
+
if (activeView === "month") return clamp4(Math.round(fixedSlotWidth * 2.5), 72, 360);
|
|
10957
|
+
return clamp4(Math.round(fixedSlotWidth * 1.2), 160, 360);
|
|
10958
|
+
})();
|
|
10959
|
+
const maxVisual = clamp4(
|
|
10960
|
+
Math.round(activeView === "month" ? monthEventMaxWidth ?? defaultMaxVisual : dayEventMaxWidth ?? defaultMaxVisual),
|
|
10961
|
+
48,
|
|
10962
|
+
1200
|
|
10963
|
+
);
|
|
10750
10964
|
const visualWidth = shouldCompact ? Math.min(widthInset, maxVisual) : widthInset;
|
|
10751
10965
|
const isClipped = shouldCompact && widthInset > visualWidth + 1;
|
|
10752
10966
|
const block = /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
@@ -10791,7 +11005,7 @@ function CalendarTimeline({
|
|
|
10791
11005
|
"transition-all duration-150 ease-out",
|
|
10792
11006
|
"backdrop-blur-sm",
|
|
10793
11007
|
ev.className,
|
|
10794
|
-
isPreview && "ring-2 ring-primary/50 ring-offset-1 ring-offset-
|
|
11008
|
+
isPreview && "ring-2 ring-primary/50 ring-offset-1 ring-offset-card scale-[1.02]"
|
|
10795
11009
|
),
|
|
10796
11010
|
style: {
|
|
10797
11011
|
width: visualWidth,
|
|
@@ -10803,7 +11017,7 @@ function CalendarTimeline({
|
|
|
10803
11017
|
},
|
|
10804
11018
|
children: [
|
|
10805
11019
|
node,
|
|
10806
|
-
isClipped ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "pointer-events-none absolute inset-y-0 right-0 w-10 bg-linear-to-l from-
|
|
11020
|
+
isClipped ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "pointer-events-none absolute inset-y-0 right-0 w-10 bg-linear-to-l from-card/50 to-transparent flex items-center justify-end pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "text-xs text-muted-foreground/80", children: "\u2026" }) }) : null
|
|
10807
11021
|
]
|
|
10808
11022
|
}
|
|
10809
11023
|
),
|
|
@@ -10859,7 +11073,7 @@ function CalendarTimeline({
|
|
|
10859
11073
|
className: cn(
|
|
10860
11074
|
"pointer-events-none absolute z-20",
|
|
10861
11075
|
"h-5 w-5 rounded-full",
|
|
10862
|
-
"bg-
|
|
11076
|
+
"bg-card/80 backdrop-blur-sm",
|
|
10863
11077
|
"border border-border/60 shadow-xs",
|
|
10864
11078
|
"flex items-center justify-center"
|
|
10865
11079
|
),
|