@j3m-quantum/ui 1.10.0 → 1.11.1
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 +1620 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +245 -1
- package/dist/index.d.ts +245 -1
- package/dist/index.js +1591 -19
- package/dist/index.js.map +1 -1
- package/package.json +19 -10
package/dist/index.cjs
CHANGED
|
@@ -43,6 +43,15 @@ var ResizablePrimitive = require('react-resizable-panels');
|
|
|
43
43
|
var reactLeaflet = require('react-leaflet');
|
|
44
44
|
var reactTable = require('@tanstack/react-table');
|
|
45
45
|
var dateFns = require('date-fns');
|
|
46
|
+
var core = require('@dnd-kit/core');
|
|
47
|
+
var modifiers = require('@dnd-kit/modifiers');
|
|
48
|
+
var usehooks = require('@uidotdev/usehooks');
|
|
49
|
+
var jotai = require('jotai');
|
|
50
|
+
var throttle = require('lodash.throttle');
|
|
51
|
+
var sortable = require('@dnd-kit/sortable');
|
|
52
|
+
var utilities = require('@dnd-kit/utilities');
|
|
53
|
+
var reactDom = require('react-dom');
|
|
54
|
+
var tunnel = require('tunnel-rat');
|
|
46
55
|
|
|
47
56
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
48
57
|
|
|
@@ -93,6 +102,8 @@ var PopoverPrimitive__namespace = /*#__PURE__*/_interopNamespace(PopoverPrimitiv
|
|
|
93
102
|
var HoverCardPrimitive__namespace = /*#__PURE__*/_interopNamespace(HoverCardPrimitive);
|
|
94
103
|
var CollapsiblePrimitive__namespace = /*#__PURE__*/_interopNamespace(CollapsiblePrimitive);
|
|
95
104
|
var ResizablePrimitive__namespace = /*#__PURE__*/_interopNamespace(ResizablePrimitive);
|
|
105
|
+
var throttle__default = /*#__PURE__*/_interopDefault(throttle);
|
|
106
|
+
var tunnel__default = /*#__PURE__*/_interopDefault(tunnel);
|
|
96
107
|
|
|
97
108
|
// src/hooks/use-mobile.ts
|
|
98
109
|
var MOBILE_BREAKPOINT = 768;
|
|
@@ -6828,7 +6839,7 @@ function PlanningWeekCommentPopover({
|
|
|
6828
6839
|
onCommentClick(comment);
|
|
6829
6840
|
}
|
|
6830
6841
|
};
|
|
6831
|
-
const
|
|
6842
|
+
const formatDate3 = (date) => {
|
|
6832
6843
|
return new Intl.DateTimeFormat("en-US", {
|
|
6833
6844
|
month: "short",
|
|
6834
6845
|
day: "numeric",
|
|
@@ -6908,7 +6919,7 @@ function PlanningWeekCommentPopover({
|
|
|
6908
6919
|
] }),
|
|
6909
6920
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
6910
6921
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: comment.author }),
|
|
6911
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children:
|
|
6922
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: formatDate3(comment.createdAt) })
|
|
6912
6923
|
] }),
|
|
6913
6924
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground", children: comment.text })
|
|
6914
6925
|
]
|
|
@@ -7435,7 +7446,7 @@ function DeliveryCommentPopover({
|
|
|
7435
7446
|
setNewCommentText("");
|
|
7436
7447
|
}
|
|
7437
7448
|
};
|
|
7438
|
-
const
|
|
7449
|
+
const formatDate3 = (date) => {
|
|
7439
7450
|
return new Intl.DateTimeFormat("en-US", {
|
|
7440
7451
|
month: "short",
|
|
7441
7452
|
day: "numeric",
|
|
@@ -7481,7 +7492,7 @@ function DeliveryCommentPopover({
|
|
|
7481
7492
|
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent2, { className: "space-y-2 pt-2", children: comments.length > 0 ? comments.map((comment) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg bg-muted/50 p-3 space-y-2", children: [
|
|
7482
7493
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
7483
7494
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: comment.author }),
|
|
7484
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children:
|
|
7495
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: formatDate3(comment.createdAt) })
|
|
7485
7496
|
] }),
|
|
7486
7497
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground", children: comment.text })
|
|
7487
7498
|
] }, comment.id)) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground text-center py-2", children: "No comments yet" }) })
|
|
@@ -7575,7 +7586,7 @@ function ProductionCommentSection({
|
|
|
7575
7586
|
setNewComment("");
|
|
7576
7587
|
}
|
|
7577
7588
|
};
|
|
7578
|
-
const
|
|
7589
|
+
const formatDate3 = (date) => {
|
|
7579
7590
|
return new Intl.DateTimeFormat("en-US", {
|
|
7580
7591
|
month: "short",
|
|
7581
7592
|
day: "numeric",
|
|
@@ -7587,7 +7598,7 @@ function ProductionCommentSection({
|
|
|
7587
7598
|
comments.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: comments.map((comment) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg bg-muted/50 p-2.5 space-y-1", children: [
|
|
7588
7599
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
7589
7600
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: comment.author }),
|
|
7590
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children:
|
|
7601
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: formatDate3(comment.createdAt) })
|
|
7591
7602
|
] }),
|
|
7592
7603
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground", children: comment.text })
|
|
7593
7604
|
] }, comment.id)) }),
|
|
@@ -8531,7 +8542,7 @@ function CommentPopover({
|
|
|
8531
8542
|
setNewCommentText("");
|
|
8532
8543
|
}
|
|
8533
8544
|
};
|
|
8534
|
-
const
|
|
8545
|
+
const formatDate3 = (date) => {
|
|
8535
8546
|
return new Intl.DateTimeFormat("en-US", {
|
|
8536
8547
|
month: "short",
|
|
8537
8548
|
day: "numeric",
|
|
@@ -8599,7 +8610,7 @@ function CommentPopover({
|
|
|
8599
8610
|
),
|
|
8600
8611
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
8601
8612
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: comment.author }),
|
|
8602
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children:
|
|
8613
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: formatDate3(comment.createdAt) })
|
|
8603
8614
|
] }),
|
|
8604
8615
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground", children: comment.text })
|
|
8605
8616
|
]
|
|
@@ -9318,7 +9329,7 @@ function generateLoadingWeek(date) {
|
|
|
9318
9329
|
const today = /* @__PURE__ */ new Date();
|
|
9319
9330
|
today.setHours(0, 0, 0, 0);
|
|
9320
9331
|
const isCurrentWeek = monday <= today && today <= friday;
|
|
9321
|
-
const
|
|
9332
|
+
const formatDate3 = (d) => {
|
|
9322
9333
|
return d.toLocaleDateString("en-US", { month: "short", day: "numeric" });
|
|
9323
9334
|
};
|
|
9324
9335
|
return {
|
|
@@ -9326,7 +9337,7 @@ function generateLoadingWeek(date) {
|
|
|
9326
9337
|
label: `W${getLoadingISOWeek(monday).toString().padStart(2, "0")}`,
|
|
9327
9338
|
startDate: monday,
|
|
9328
9339
|
endDate: friday,
|
|
9329
|
-
dateRange: `${
|
|
9340
|
+
dateRange: `${formatDate3(monday)} - ${formatDate3(friday)}`,
|
|
9330
9341
|
isCurrentWeek
|
|
9331
9342
|
};
|
|
9332
9343
|
}
|
|
@@ -9985,7 +9996,7 @@ function CommentsSection({
|
|
|
9985
9996
|
}) {
|
|
9986
9997
|
const [viewCommentsOpen, setViewCommentsOpen] = React27__namespace.useState(true);
|
|
9987
9998
|
const [addDialogOpen, setAddDialogOpen] = React27__namespace.useState(false);
|
|
9988
|
-
const
|
|
9999
|
+
const formatDate3 = (date) => {
|
|
9989
10000
|
return new Intl.DateTimeFormat("en-US", {
|
|
9990
10001
|
month: "short",
|
|
9991
10002
|
day: "numeric",
|
|
@@ -10029,7 +10040,7 @@ function CommentsSection({
|
|
|
10029
10040
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: comment.author }),
|
|
10030
10041
|
comment.supplierName && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "outline", className: "text-[9px] px-1.5 py-0 h-4", children: comment.prefixName ? `${comment.supplierName} - ${comment.prefixName}` : comment.supplierName })
|
|
10031
10042
|
] }),
|
|
10032
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children:
|
|
10043
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: formatDate3(comment.createdAt) })
|
|
10033
10044
|
] }),
|
|
10034
10045
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: comment.text })
|
|
10035
10046
|
] }, comment.id)) })
|
|
@@ -11021,11 +11032,11 @@ function getVisibleHours(visibleHours, singleDayEvents) {
|
|
|
11021
11032
|
function getCalendarCells(selectedDate) {
|
|
11022
11033
|
const currentYear = selectedDate.getFullYear();
|
|
11023
11034
|
const currentMonth = selectedDate.getMonth();
|
|
11024
|
-
const
|
|
11035
|
+
const getDaysInMonth2 = (year, month) => new Date(year, month + 1, 0).getDate();
|
|
11025
11036
|
const getFirstDayOfMonth = (year, month) => new Date(year, month, 1).getDay();
|
|
11026
|
-
const daysInMonth =
|
|
11037
|
+
const daysInMonth = getDaysInMonth2(currentYear, currentMonth);
|
|
11027
11038
|
const firstDayOfMonth = getFirstDayOfMonth(currentYear, currentMonth);
|
|
11028
|
-
const daysInPrevMonth =
|
|
11039
|
+
const daysInPrevMonth = getDaysInMonth2(currentYear, currentMonth - 1);
|
|
11029
11040
|
const totalDays = firstDayOfMonth + daysInMonth;
|
|
11030
11041
|
const prevMonthCells = Array.from({ length: firstDayOfMonth }, (_, i) => ({
|
|
11031
11042
|
day: daysInPrevMonth - firstDayOfMonth + i + 1,
|
|
@@ -13746,6 +13757,1569 @@ function CalendarView({
|
|
|
13746
13757
|
return null;
|
|
13747
13758
|
}
|
|
13748
13759
|
}
|
|
13760
|
+
var draggingAtom = jotai.atom(false);
|
|
13761
|
+
var scrollXAtom = jotai.atom(0);
|
|
13762
|
+
var useGanttDragging = () => jotai.useAtom(draggingAtom);
|
|
13763
|
+
var useGanttScrollX = () => jotai.useAtom(scrollXAtom);
|
|
13764
|
+
var getDifferenceIn = (range) => {
|
|
13765
|
+
if (range === "weekly") {
|
|
13766
|
+
return dateFns.differenceInWeeks;
|
|
13767
|
+
}
|
|
13768
|
+
return dateFns.differenceInMonths;
|
|
13769
|
+
};
|
|
13770
|
+
var getInnerDifferenceIn = (range) => {
|
|
13771
|
+
if (range === "weekly") {
|
|
13772
|
+
return dateFns.differenceInDays;
|
|
13773
|
+
}
|
|
13774
|
+
return dateFns.differenceInDays;
|
|
13775
|
+
};
|
|
13776
|
+
var getStartOf = (range) => {
|
|
13777
|
+
if (range === "weekly") {
|
|
13778
|
+
return (date) => dateFns.startOfWeek(date, { weekStartsOn: 1 });
|
|
13779
|
+
}
|
|
13780
|
+
return dateFns.startOfMonth;
|
|
13781
|
+
};
|
|
13782
|
+
var getEndOf = (range) => {
|
|
13783
|
+
if (range === "weekly") {
|
|
13784
|
+
return (date) => dateFns.endOfWeek(date, { weekStartsOn: 1 });
|
|
13785
|
+
}
|
|
13786
|
+
return dateFns.endOfMonth;
|
|
13787
|
+
};
|
|
13788
|
+
var getAddRange = (range) => {
|
|
13789
|
+
if (range === "weekly") {
|
|
13790
|
+
return dateFns.addWeeks;
|
|
13791
|
+
}
|
|
13792
|
+
return dateFns.addMonths;
|
|
13793
|
+
};
|
|
13794
|
+
var getDateByMousePosition = (context, mouseX) => {
|
|
13795
|
+
const columnWidth = context.columnWidth * context.zoom / 100;
|
|
13796
|
+
const offset = Math.floor(mouseX / columnWidth);
|
|
13797
|
+
const addRange = getAddRange(context.range);
|
|
13798
|
+
if (context.range === "weekly") {
|
|
13799
|
+
const firstYear = context.timelineData[0].year;
|
|
13800
|
+
const weekStart = getWeekStartDate(firstYear, 1);
|
|
13801
|
+
const targetWeekStart = addRange(weekStart, offset);
|
|
13802
|
+
const pixelsPerDay2 = columnWidth / 7;
|
|
13803
|
+
const dayOffset2 = Math.floor(mouseX % columnWidth / pixelsPerDay2);
|
|
13804
|
+
return dateFns.addDays(targetWeekStart, dayOffset2);
|
|
13805
|
+
}
|
|
13806
|
+
const timelineStartDate = new Date(context.timelineData[0].year, 0, 1);
|
|
13807
|
+
const month = addRange(timelineStartDate, offset);
|
|
13808
|
+
const daysInMonth = dateFns.getDaysInMonth(month);
|
|
13809
|
+
const pixelsPerDay = Math.round(columnWidth / daysInMonth);
|
|
13810
|
+
const dayOffset = Math.floor(mouseX % columnWidth / pixelsPerDay);
|
|
13811
|
+
return dateFns.addDays(month, dayOffset);
|
|
13812
|
+
};
|
|
13813
|
+
var createInitialTimelineData = (today) => {
|
|
13814
|
+
const data = [];
|
|
13815
|
+
data.push(
|
|
13816
|
+
{ year: today.getFullYear() - 1, quarters: new Array(4).fill(null) },
|
|
13817
|
+
{ year: today.getFullYear(), quarters: new Array(4).fill(null) },
|
|
13818
|
+
{ year: today.getFullYear() + 1, quarters: new Array(4).fill(null) }
|
|
13819
|
+
);
|
|
13820
|
+
for (const yearObj of data) {
|
|
13821
|
+
yearObj.quarters = new Array(4).fill(null).map((_, quarterIndex) => ({
|
|
13822
|
+
months: new Array(3).fill(null).map((_2, monthIndex) => {
|
|
13823
|
+
const month = quarterIndex * 3 + monthIndex;
|
|
13824
|
+
return {
|
|
13825
|
+
days: dateFns.getDaysInMonth(new Date(yearObj.year, month, 1))
|
|
13826
|
+
};
|
|
13827
|
+
})
|
|
13828
|
+
}));
|
|
13829
|
+
}
|
|
13830
|
+
return data;
|
|
13831
|
+
};
|
|
13832
|
+
var getOffset = (date, timelineStartDate, context) => {
|
|
13833
|
+
const parsedColumnWidth = context.columnWidth * context.zoom / 100;
|
|
13834
|
+
const differenceIn = getDifferenceIn(context.range);
|
|
13835
|
+
const startOf = getStartOf(context.range);
|
|
13836
|
+
const fullColumns = differenceIn(startOf(date), startOf(timelineStartDate));
|
|
13837
|
+
if (context.range === "weekly") {
|
|
13838
|
+
const weekStart = startOf(date);
|
|
13839
|
+
const dayOfWeek = dateFns.differenceInDays(date, weekStart);
|
|
13840
|
+
const pixelsPerDay2 = parsedColumnWidth / 7;
|
|
13841
|
+
return fullColumns * parsedColumnWidth + dayOfWeek * pixelsPerDay2;
|
|
13842
|
+
}
|
|
13843
|
+
const partialColumns = date.getDate();
|
|
13844
|
+
const daysInMonth = dateFns.getDaysInMonth(date);
|
|
13845
|
+
const pixelsPerDay = parsedColumnWidth / daysInMonth;
|
|
13846
|
+
return fullColumns * parsedColumnWidth + partialColumns * pixelsPerDay;
|
|
13847
|
+
};
|
|
13848
|
+
var getWidth = (startAt, endAt, context) => {
|
|
13849
|
+
const parsedColumnWidth = context.columnWidth * context.zoom / 100;
|
|
13850
|
+
if (!endAt) {
|
|
13851
|
+
return parsedColumnWidth * 2;
|
|
13852
|
+
}
|
|
13853
|
+
const startOf = getStartOf(context.range);
|
|
13854
|
+
if (context.range === "weekly") {
|
|
13855
|
+
const pixelsPerDay = parsedColumnWidth / 7;
|
|
13856
|
+
const daysDiff = dateFns.differenceInDays(endAt, startAt);
|
|
13857
|
+
return Math.max(pixelsPerDay, daysDiff * pixelsPerDay);
|
|
13858
|
+
}
|
|
13859
|
+
const differenceIn = getDifferenceIn(context.range);
|
|
13860
|
+
const daysInStartMonth = dateFns.getDaysInMonth(startAt);
|
|
13861
|
+
const pixelsPerDayInStartMonth = parsedColumnWidth / daysInStartMonth;
|
|
13862
|
+
if (dateFns.isSameDay(startAt, endAt)) {
|
|
13863
|
+
return pixelsPerDayInStartMonth;
|
|
13864
|
+
}
|
|
13865
|
+
const innerDifferenceIn = getInnerDifferenceIn(context.range);
|
|
13866
|
+
if (dateFns.isSameDay(startOf(startAt), startOf(endAt))) {
|
|
13867
|
+
return innerDifferenceIn(endAt, startAt) * pixelsPerDayInStartMonth;
|
|
13868
|
+
}
|
|
13869
|
+
const startRangeOffset = daysInStartMonth - dateFns.getDate(startAt);
|
|
13870
|
+
const endRangeOffset = dateFns.getDate(endAt);
|
|
13871
|
+
const fullRangeOffset = differenceIn(startOf(endAt), startOf(startAt));
|
|
13872
|
+
const daysInEndMonth = dateFns.getDaysInMonth(endAt);
|
|
13873
|
+
const pixelsPerDayInEndMonth = parsedColumnWidth / daysInEndMonth;
|
|
13874
|
+
return (fullRangeOffset - 1) * parsedColumnWidth + startRangeOffset * pixelsPerDayInStartMonth + endRangeOffset * pixelsPerDayInEndMonth;
|
|
13875
|
+
};
|
|
13876
|
+
var calculateInnerOffset = (date, range, columnWidth) => {
|
|
13877
|
+
const startOf = getStartOf(range);
|
|
13878
|
+
const endOf = getEndOf(range);
|
|
13879
|
+
const startOfRange = startOf(date);
|
|
13880
|
+
const endOfRange = endOf(date);
|
|
13881
|
+
if (range === "weekly") {
|
|
13882
|
+
const dayOfWeek = dateFns.differenceInDays(date, startOfRange);
|
|
13883
|
+
return dayOfWeek / 7 * columnWidth;
|
|
13884
|
+
}
|
|
13885
|
+
const totalRangeDays = dateFns.differenceInDays(endOfRange, startOfRange);
|
|
13886
|
+
const dayOfMonth = date.getDate();
|
|
13887
|
+
return dayOfMonth / totalRangeDays * columnWidth;
|
|
13888
|
+
};
|
|
13889
|
+
var GanttContext = React27.createContext({
|
|
13890
|
+
zoom: 100,
|
|
13891
|
+
range: "monthly",
|
|
13892
|
+
columnWidth: 50,
|
|
13893
|
+
headerHeight: 60,
|
|
13894
|
+
sidebarWidth: 300,
|
|
13895
|
+
rowHeight: 36,
|
|
13896
|
+
onAddItem: void 0,
|
|
13897
|
+
placeholderLength: 2,
|
|
13898
|
+
timelineData: [],
|
|
13899
|
+
ref: null,
|
|
13900
|
+
scrollToFeature: void 0,
|
|
13901
|
+
expandedGroups: {},
|
|
13902
|
+
setGroupExpanded: () => {
|
|
13903
|
+
}
|
|
13904
|
+
});
|
|
13905
|
+
var GanttContentHeader = ({
|
|
13906
|
+
title,
|
|
13907
|
+
columns,
|
|
13908
|
+
renderHeaderItem
|
|
13909
|
+
}) => {
|
|
13910
|
+
const id = React27.useId();
|
|
13911
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
13912
|
+
"div",
|
|
13913
|
+
{
|
|
13914
|
+
className: "sticky top-0 z-20 grid w-full shrink-0 bg-background/95 backdrop-blur-sm",
|
|
13915
|
+
style: { height: "var(--gantt-header-height)" },
|
|
13916
|
+
children: [
|
|
13917
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13918
|
+
"div",
|
|
13919
|
+
{
|
|
13920
|
+
className: "sticky inline-flex whitespace-nowrap px-3 py-2 text-muted-foreground text-xs",
|
|
13921
|
+
style: {
|
|
13922
|
+
left: "var(--gantt-sidebar-width)"
|
|
13923
|
+
},
|
|
13924
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: title })
|
|
13925
|
+
}
|
|
13926
|
+
) }),
|
|
13927
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13928
|
+
"div",
|
|
13929
|
+
{
|
|
13930
|
+
className: "grid w-full",
|
|
13931
|
+
style: {
|
|
13932
|
+
gridTemplateColumns: `repeat(${columns}, var(--gantt-column-width))`
|
|
13933
|
+
},
|
|
13934
|
+
children: Array.from({ length: columns }).map((_, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
13935
|
+
"div",
|
|
13936
|
+
{
|
|
13937
|
+
className: "shrink-0 border-border/50 border-b py-1 text-center text-xs",
|
|
13938
|
+
children: renderHeaderItem(index)
|
|
13939
|
+
},
|
|
13940
|
+
`${id}-${index}`
|
|
13941
|
+
))
|
|
13942
|
+
}
|
|
13943
|
+
)
|
|
13944
|
+
]
|
|
13945
|
+
}
|
|
13946
|
+
);
|
|
13947
|
+
};
|
|
13948
|
+
var getWeeksInYear = (year) => {
|
|
13949
|
+
const dec28 = new Date(year, 11, 28);
|
|
13950
|
+
return dateFns.getISOWeek(dec28);
|
|
13951
|
+
};
|
|
13952
|
+
var getWeekStartDate = (year, weekNumber) => {
|
|
13953
|
+
const jan4 = new Date(year, 0, 4);
|
|
13954
|
+
const week1Start = dateFns.startOfWeek(jan4, { weekStartsOn: 1 });
|
|
13955
|
+
return dateFns.addWeeks(week1Start, weekNumber - 1);
|
|
13956
|
+
};
|
|
13957
|
+
var WeeklyHeader = () => {
|
|
13958
|
+
const gantt = React27.useContext(GanttContext);
|
|
13959
|
+
const weeklyData = React27.useMemo(() => {
|
|
13960
|
+
const result = [];
|
|
13961
|
+
for (const yearData of gantt.timelineData) {
|
|
13962
|
+
const year = yearData.year;
|
|
13963
|
+
const weeksInYear = getWeeksInYear(year);
|
|
13964
|
+
const weeks = [];
|
|
13965
|
+
for (let w = 1; w <= weeksInYear; w++) {
|
|
13966
|
+
weeks.push({
|
|
13967
|
+
weekNumber: w,
|
|
13968
|
+
startDate: getWeekStartDate(year, w)
|
|
13969
|
+
});
|
|
13970
|
+
}
|
|
13971
|
+
result.push({ year, weeks });
|
|
13972
|
+
}
|
|
13973
|
+
return result;
|
|
13974
|
+
}, [gantt.timelineData]);
|
|
13975
|
+
return weeklyData.map((yearData) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex flex-col", children: [
|
|
13976
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13977
|
+
GanttContentHeader,
|
|
13978
|
+
{
|
|
13979
|
+
columns: yearData.weeks.length,
|
|
13980
|
+
renderHeaderItem: (weekIndex) => {
|
|
13981
|
+
const week = yearData.weeks[weekIndex];
|
|
13982
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
|
|
13983
|
+
"W",
|
|
13984
|
+
week.weekNumber.toString().padStart(2, "0")
|
|
13985
|
+
] }) });
|
|
13986
|
+
},
|
|
13987
|
+
title: `${yearData.year}`
|
|
13988
|
+
}
|
|
13989
|
+
),
|
|
13990
|
+
/* @__PURE__ */ jsxRuntime.jsx(GanttColumns, { columns: yearData.weeks.length })
|
|
13991
|
+
] }, yearData.year));
|
|
13992
|
+
};
|
|
13993
|
+
var MonthlyHeader = () => {
|
|
13994
|
+
const gantt = React27.useContext(GanttContext);
|
|
13995
|
+
return gantt.timelineData.map((year) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex flex-col", children: [
|
|
13996
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13997
|
+
GanttContentHeader,
|
|
13998
|
+
{
|
|
13999
|
+
columns: year.quarters.flatMap((quarter) => quarter.months).length,
|
|
14000
|
+
renderHeaderItem: (item) => /* @__PURE__ */ jsxRuntime.jsx("p", { children: dateFns.format(new Date(year.year, item, 1), "MMM") }),
|
|
14001
|
+
title: `${year.year}`
|
|
14002
|
+
}
|
|
14003
|
+
),
|
|
14004
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14005
|
+
GanttColumns,
|
|
14006
|
+
{
|
|
14007
|
+
columns: year.quarters.flatMap((quarter) => quarter.months).length
|
|
14008
|
+
}
|
|
14009
|
+
)
|
|
14010
|
+
] }, year.year));
|
|
14011
|
+
};
|
|
14012
|
+
var QuarterlyHeader = () => {
|
|
14013
|
+
const gantt = React27.useContext(GanttContext);
|
|
14014
|
+
return gantt.timelineData.map(
|
|
14015
|
+
(year) => year.quarters.map((quarter, quarterIndex) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14016
|
+
"div",
|
|
14017
|
+
{
|
|
14018
|
+
className: "relative flex flex-col",
|
|
14019
|
+
children: [
|
|
14020
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14021
|
+
GanttContentHeader,
|
|
14022
|
+
{
|
|
14023
|
+
columns: quarter.months.length,
|
|
14024
|
+
renderHeaderItem: (item) => /* @__PURE__ */ jsxRuntime.jsx("p", { children: dateFns.format(new Date(year.year, quarterIndex * 3 + item, 1), "MMM") }),
|
|
14025
|
+
title: `Q${quarterIndex + 1} ${year.year}`
|
|
14026
|
+
}
|
|
14027
|
+
),
|
|
14028
|
+
/* @__PURE__ */ jsxRuntime.jsx(GanttColumns, { columns: quarter.months.length })
|
|
14029
|
+
]
|
|
14030
|
+
},
|
|
14031
|
+
`${year.year}-${quarterIndex}`
|
|
14032
|
+
))
|
|
14033
|
+
);
|
|
14034
|
+
};
|
|
14035
|
+
var headers = {
|
|
14036
|
+
weekly: WeeklyHeader,
|
|
14037
|
+
monthly: MonthlyHeader,
|
|
14038
|
+
quarterly: QuarterlyHeader
|
|
14039
|
+
};
|
|
14040
|
+
var GanttHeader = ({ className }) => {
|
|
14041
|
+
const gantt = React27.useContext(GanttContext);
|
|
14042
|
+
const Header2 = headers[gantt.range];
|
|
14043
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14044
|
+
"div",
|
|
14045
|
+
{
|
|
14046
|
+
className: cn(
|
|
14047
|
+
"-space-x-px flex h-full w-max divide-x-2 divide-border",
|
|
14048
|
+
className
|
|
14049
|
+
),
|
|
14050
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Header2, {})
|
|
14051
|
+
}
|
|
14052
|
+
);
|
|
14053
|
+
};
|
|
14054
|
+
var GanttSidebarItem = ({
|
|
14055
|
+
feature,
|
|
14056
|
+
onSelectItem,
|
|
14057
|
+
className
|
|
14058
|
+
}) => {
|
|
14059
|
+
const gantt = React27.useContext(GanttContext);
|
|
14060
|
+
const tempEndAt = feature.endAt && dateFns.isSameDay(feature.startAt, feature.endAt) ? dateFns.addDays(feature.endAt, 1) : feature.endAt;
|
|
14061
|
+
const duration = tempEndAt ? dateFns.formatDistance(feature.startAt, tempEndAt) : `${dateFns.formatDistance(feature.startAt, /* @__PURE__ */ new Date())} so far`;
|
|
14062
|
+
const handleClick = (event) => {
|
|
14063
|
+
if (event.target === event.currentTarget) {
|
|
14064
|
+
gantt.scrollToFeature?.(feature);
|
|
14065
|
+
onSelectItem?.(feature.id);
|
|
14066
|
+
}
|
|
14067
|
+
};
|
|
14068
|
+
const handleKeyDown = (event) => {
|
|
14069
|
+
if (event.key === "Enter") {
|
|
14070
|
+
gantt.scrollToFeature?.(feature);
|
|
14071
|
+
onSelectItem?.(feature.id);
|
|
14072
|
+
}
|
|
14073
|
+
};
|
|
14074
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14075
|
+
"div",
|
|
14076
|
+
{
|
|
14077
|
+
className: cn(
|
|
14078
|
+
"relative flex items-center gap-2.5 px-2.5 py-1.5 text-xs hover:bg-muted/50 border-b border-border/30",
|
|
14079
|
+
className
|
|
14080
|
+
),
|
|
14081
|
+
onClick: handleClick,
|
|
14082
|
+
onKeyDown: handleKeyDown,
|
|
14083
|
+
role: "button",
|
|
14084
|
+
style: {
|
|
14085
|
+
height: "var(--gantt-row-height)"
|
|
14086
|
+
},
|
|
14087
|
+
tabIndex: 0,
|
|
14088
|
+
children: [
|
|
14089
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14090
|
+
"div",
|
|
14091
|
+
{
|
|
14092
|
+
className: "pointer-events-none h-2 w-2 shrink-0 rounded-full",
|
|
14093
|
+
style: {
|
|
14094
|
+
backgroundColor: feature.status.color
|
|
14095
|
+
}
|
|
14096
|
+
}
|
|
14097
|
+
),
|
|
14098
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "pointer-events-none flex-1 truncate text-left font-medium", children: feature.name }),
|
|
14099
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "pointer-events-none text-muted-foreground text-[11px]", children: duration })
|
|
14100
|
+
]
|
|
14101
|
+
},
|
|
14102
|
+
feature.id
|
|
14103
|
+
);
|
|
14104
|
+
};
|
|
14105
|
+
var GanttSidebarHeader = ({
|
|
14106
|
+
title = "Tasks",
|
|
14107
|
+
durationLabel = "Duration"
|
|
14108
|
+
}) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14109
|
+
"div",
|
|
14110
|
+
{
|
|
14111
|
+
className: "sticky top-0 z-10 flex shrink-0 items-end justify-between gap-2.5 border-border/50 border-b bg-background/95 px-2.5 py-2 font-medium text-muted-foreground text-xs backdrop-blur-sm",
|
|
14112
|
+
style: { height: "var(--gantt-header-height)" },
|
|
14113
|
+
children: [
|
|
14114
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "flex-1 truncate text-left", children: title }),
|
|
14115
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "shrink-0", children: durationLabel })
|
|
14116
|
+
]
|
|
14117
|
+
}
|
|
14118
|
+
);
|
|
14119
|
+
function computeGroupRange(features) {
|
|
14120
|
+
if (features.length === 0) {
|
|
14121
|
+
return { start: null, end: null };
|
|
14122
|
+
}
|
|
14123
|
+
let minStart = features[0].startAt;
|
|
14124
|
+
let maxEnd = features[0].endAt;
|
|
14125
|
+
for (const feature of features) {
|
|
14126
|
+
if (feature.startAt < minStart) {
|
|
14127
|
+
minStart = feature.startAt;
|
|
14128
|
+
}
|
|
14129
|
+
if (feature.endAt > maxEnd) {
|
|
14130
|
+
maxEnd = feature.endAt;
|
|
14131
|
+
}
|
|
14132
|
+
}
|
|
14133
|
+
return { start: minStart, end: maxEnd };
|
|
14134
|
+
}
|
|
14135
|
+
var GanttGroupSummaryBar = React27.memo(({
|
|
14136
|
+
group,
|
|
14137
|
+
className
|
|
14138
|
+
}) => {
|
|
14139
|
+
const gantt = React27.useContext(GanttContext);
|
|
14140
|
+
const timelineStartDate = React27.useMemo(
|
|
14141
|
+
() => new Date(gantt.timelineData.at(0)?.year ?? 0, 0, 1),
|
|
14142
|
+
[gantt.timelineData]
|
|
14143
|
+
);
|
|
14144
|
+
const { start: groupStart, end: groupEnd } = React27.useMemo(
|
|
14145
|
+
() => computeGroupRange(group.features),
|
|
14146
|
+
[group.features]
|
|
14147
|
+
);
|
|
14148
|
+
const offset = React27.useMemo(() => {
|
|
14149
|
+
if (!groupStart) return 0;
|
|
14150
|
+
return Math.round(getOffset(groupStart, timelineStartDate, gantt));
|
|
14151
|
+
}, [groupStart, timelineStartDate, gantt]);
|
|
14152
|
+
const width = React27.useMemo(() => {
|
|
14153
|
+
if (!groupStart || !groupEnd) return 0;
|
|
14154
|
+
return Math.round(getWidth(groupStart, groupEnd, gantt));
|
|
14155
|
+
}, [groupStart, groupEnd, gantt]);
|
|
14156
|
+
if (!groupStart || !groupEnd || width === 0) {
|
|
14157
|
+
return null;
|
|
14158
|
+
}
|
|
14159
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14160
|
+
"div",
|
|
14161
|
+
{
|
|
14162
|
+
className: cn(
|
|
14163
|
+
"absolute pointer-events-none",
|
|
14164
|
+
className
|
|
14165
|
+
),
|
|
14166
|
+
style: {
|
|
14167
|
+
height: "calc(var(--gantt-row-height) - 12px)",
|
|
14168
|
+
top: "6px",
|
|
14169
|
+
width,
|
|
14170
|
+
left: offset
|
|
14171
|
+
},
|
|
14172
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14173
|
+
"div",
|
|
14174
|
+
{
|
|
14175
|
+
className: "h-full w-full rounded-sm border border-border/60 bg-muted/40 shadow-sm",
|
|
14176
|
+
style: {
|
|
14177
|
+
// Subtle gradient for depth
|
|
14178
|
+
background: "linear-gradient(180deg, hsl(var(--muted) / 0.5) 0%, hsl(var(--muted) / 0.3) 100%)"
|
|
14179
|
+
}
|
|
14180
|
+
}
|
|
14181
|
+
)
|
|
14182
|
+
}
|
|
14183
|
+
);
|
|
14184
|
+
});
|
|
14185
|
+
GanttGroupSummaryBar.displayName = "GanttGroupSummaryBar";
|
|
14186
|
+
var GanttCollapsibleSidebarGroup = ({
|
|
14187
|
+
group,
|
|
14188
|
+
children,
|
|
14189
|
+
className
|
|
14190
|
+
}) => {
|
|
14191
|
+
const gantt = React27.useContext(GanttContext);
|
|
14192
|
+
const isExpanded = gantt.expandedGroups[group.id] ?? true;
|
|
14193
|
+
const { start: groupStart, end: groupEnd } = React27.useMemo(
|
|
14194
|
+
() => computeGroupRange(group.features),
|
|
14195
|
+
[group.features]
|
|
14196
|
+
);
|
|
14197
|
+
const duration = React27.useMemo(() => {
|
|
14198
|
+
if (!groupStart || !groupEnd) return null;
|
|
14199
|
+
return dateFns.formatDistance(groupStart, groupEnd);
|
|
14200
|
+
}, [groupStart, groupEnd]);
|
|
14201
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14202
|
+
Collapsible,
|
|
14203
|
+
{
|
|
14204
|
+
open: isExpanded,
|
|
14205
|
+
onOpenChange: (open) => gantt.setGroupExpanded(group.id, open),
|
|
14206
|
+
className,
|
|
14207
|
+
children: [
|
|
14208
|
+
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14209
|
+
"button",
|
|
14210
|
+
{
|
|
14211
|
+
className: "flex w-full items-center gap-2 px-2.5 py-2 text-left font-medium text-xs hover:bg-muted/30 border-b border-border/50 bg-background",
|
|
14212
|
+
style: { height: "var(--gantt-row-height)" },
|
|
14213
|
+
type: "button",
|
|
14214
|
+
children: [
|
|
14215
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14216
|
+
lucideReact.ChevronRightIcon,
|
|
14217
|
+
{
|
|
14218
|
+
className: cn(
|
|
14219
|
+
"h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200",
|
|
14220
|
+
isExpanded && "rotate-90"
|
|
14221
|
+
)
|
|
14222
|
+
}
|
|
14223
|
+
),
|
|
14224
|
+
group.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-muted-foreground", children: group.icon }),
|
|
14225
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate", children: group.title }),
|
|
14226
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 rounded-full bg-muted px-2 py-0.5 text-[10px] text-muted-foreground", children: group.features.length }),
|
|
14227
|
+
duration && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-[10px] text-muted-foreground", children: duration })
|
|
14228
|
+
]
|
|
14229
|
+
}
|
|
14230
|
+
) }),
|
|
14231
|
+
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent2, { className: "[&[data-state]]:!opacity-100", children })
|
|
14232
|
+
]
|
|
14233
|
+
}
|
|
14234
|
+
);
|
|
14235
|
+
};
|
|
14236
|
+
var GanttCollapsibleTimelineGroup = ({
|
|
14237
|
+
group,
|
|
14238
|
+
children,
|
|
14239
|
+
className
|
|
14240
|
+
}) => {
|
|
14241
|
+
const gantt = React27.useContext(GanttContext);
|
|
14242
|
+
const isExpanded = gantt.expandedGroups[group.id] ?? true;
|
|
14243
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14244
|
+
Collapsible,
|
|
14245
|
+
{
|
|
14246
|
+
open: isExpanded,
|
|
14247
|
+
onOpenChange: (open) => gantt.setGroupExpanded(group.id, open),
|
|
14248
|
+
className,
|
|
14249
|
+
children: [
|
|
14250
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14251
|
+
"div",
|
|
14252
|
+
{
|
|
14253
|
+
className: "relative w-full border-b border-border/50",
|
|
14254
|
+
style: { height: "var(--gantt-row-height)" },
|
|
14255
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(GanttGroupSummaryBar, { group })
|
|
14256
|
+
}
|
|
14257
|
+
),
|
|
14258
|
+
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent2, { className: "[&[data-state]]:!opacity-100", children })
|
|
14259
|
+
]
|
|
14260
|
+
}
|
|
14261
|
+
);
|
|
14262
|
+
};
|
|
14263
|
+
var GanttSidebarGroup = ({
|
|
14264
|
+
children,
|
|
14265
|
+
name,
|
|
14266
|
+
className
|
|
14267
|
+
}) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
|
|
14268
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14269
|
+
"p",
|
|
14270
|
+
{
|
|
14271
|
+
className: "w-full truncate px-2.5 py-2 text-left font-medium text-muted-foreground text-xs border-b border-border/50 bg-background",
|
|
14272
|
+
style: { height: "var(--gantt-row-height)" },
|
|
14273
|
+
children: name
|
|
14274
|
+
}
|
|
14275
|
+
),
|
|
14276
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children })
|
|
14277
|
+
] });
|
|
14278
|
+
var GanttSidebar = ({
|
|
14279
|
+
children,
|
|
14280
|
+
className
|
|
14281
|
+
}) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14282
|
+
"div",
|
|
14283
|
+
{
|
|
14284
|
+
className: cn(
|
|
14285
|
+
"sticky left-0 z-30 h-max min-h-full border-border/50 border-r bg-background",
|
|
14286
|
+
className
|
|
14287
|
+
),
|
|
14288
|
+
style: { width: "var(--gantt-sidebar-width)" },
|
|
14289
|
+
"data-roadmap-ui": "gantt-sidebar",
|
|
14290
|
+
children: [
|
|
14291
|
+
/* @__PURE__ */ jsxRuntime.jsx(GanttSidebarHeader, {}),
|
|
14292
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children })
|
|
14293
|
+
]
|
|
14294
|
+
}
|
|
14295
|
+
);
|
|
14296
|
+
var GanttAddFeatureHelper = ({
|
|
14297
|
+
top,
|
|
14298
|
+
className
|
|
14299
|
+
}) => {
|
|
14300
|
+
const [scrollX] = useGanttScrollX();
|
|
14301
|
+
const gantt = React27.useContext(GanttContext);
|
|
14302
|
+
const [mousePosition, mouseRef] = usehooks.useMouse();
|
|
14303
|
+
const handleClick = () => {
|
|
14304
|
+
const ganttRect = gantt.ref?.current?.getBoundingClientRect();
|
|
14305
|
+
const x = mousePosition.x - (ganttRect?.left ?? 0) + scrollX - gantt.sidebarWidth;
|
|
14306
|
+
const currentDate = getDateByMousePosition(gantt, x);
|
|
14307
|
+
gantt.onAddItem?.(currentDate);
|
|
14308
|
+
};
|
|
14309
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14310
|
+
"div",
|
|
14311
|
+
{
|
|
14312
|
+
className: cn("absolute top-0 w-full px-0.5", className),
|
|
14313
|
+
ref: mouseRef,
|
|
14314
|
+
style: {
|
|
14315
|
+
marginTop: -gantt.rowHeight / 2,
|
|
14316
|
+
transform: `translateY(${top}px)`
|
|
14317
|
+
},
|
|
14318
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14319
|
+
"button",
|
|
14320
|
+
{
|
|
14321
|
+
className: "flex h-full w-full items-center justify-center rounded-sm border border-dashed p-2",
|
|
14322
|
+
onClick: handleClick,
|
|
14323
|
+
type: "button",
|
|
14324
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14325
|
+
lucideReact.PlusIcon,
|
|
14326
|
+
{
|
|
14327
|
+
className: "pointer-events-none select-none text-muted-foreground",
|
|
14328
|
+
size: 16
|
|
14329
|
+
}
|
|
14330
|
+
)
|
|
14331
|
+
}
|
|
14332
|
+
)
|
|
14333
|
+
}
|
|
14334
|
+
);
|
|
14335
|
+
};
|
|
14336
|
+
var GanttColumn = ({
|
|
14337
|
+
index,
|
|
14338
|
+
isColumnSecondary
|
|
14339
|
+
}) => {
|
|
14340
|
+
const gantt = React27.useContext(GanttContext);
|
|
14341
|
+
const [dragging] = useGanttDragging();
|
|
14342
|
+
const [mousePosition, mouseRef] = usehooks.useMouse();
|
|
14343
|
+
const [hovering, setHovering] = React27.useState(false);
|
|
14344
|
+
const [windowScroll] = usehooks.useWindowScroll();
|
|
14345
|
+
const handleMouseEnter = () => setHovering(true);
|
|
14346
|
+
const handleMouseLeave = () => setHovering(false);
|
|
14347
|
+
const top = usehooks.useThrottle(
|
|
14348
|
+
mousePosition.y - (mouseRef.current?.getBoundingClientRect().y ?? 0) - (windowScroll.y ?? 0),
|
|
14349
|
+
10
|
|
14350
|
+
);
|
|
14351
|
+
return (
|
|
14352
|
+
// biome-ignore lint/a11y/noStaticElementInteractions: "This is a clickable column"
|
|
14353
|
+
// biome-ignore lint/nursery/noNoninteractiveElementInteractions: "This is a clickable column"
|
|
14354
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14355
|
+
"div",
|
|
14356
|
+
{
|
|
14357
|
+
className: cn(
|
|
14358
|
+
"group relative h-full overflow-hidden",
|
|
14359
|
+
isColumnSecondary?.(index) ? "bg-muted/30" : ""
|
|
14360
|
+
),
|
|
14361
|
+
onMouseEnter: handleMouseEnter,
|
|
14362
|
+
onMouseLeave: handleMouseLeave,
|
|
14363
|
+
ref: mouseRef,
|
|
14364
|
+
children: !dragging && hovering && gantt.onAddItem ? /* @__PURE__ */ jsxRuntime.jsx(GanttAddFeatureHelper, { top }) : null
|
|
14365
|
+
}
|
|
14366
|
+
)
|
|
14367
|
+
);
|
|
14368
|
+
};
|
|
14369
|
+
var GanttColumns = ({
|
|
14370
|
+
columns,
|
|
14371
|
+
isColumnSecondary
|
|
14372
|
+
}) => {
|
|
14373
|
+
const id = React27.useId();
|
|
14374
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14375
|
+
"div",
|
|
14376
|
+
{
|
|
14377
|
+
className: "divide grid h-full w-full divide-x divide-border",
|
|
14378
|
+
style: {
|
|
14379
|
+
gridTemplateColumns: `repeat(${columns}, var(--gantt-column-width))`
|
|
14380
|
+
},
|
|
14381
|
+
children: Array.from({ length: columns }).map((_, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
14382
|
+
GanttColumn,
|
|
14383
|
+
{
|
|
14384
|
+
index,
|
|
14385
|
+
isColumnSecondary
|
|
14386
|
+
},
|
|
14387
|
+
`${id}-${index}`
|
|
14388
|
+
))
|
|
14389
|
+
}
|
|
14390
|
+
);
|
|
14391
|
+
};
|
|
14392
|
+
var GanttGridLines = React27.memo(({
|
|
14393
|
+
className
|
|
14394
|
+
}) => {
|
|
14395
|
+
const gantt = React27.useContext(GanttContext);
|
|
14396
|
+
const id = React27.useId();
|
|
14397
|
+
const { columns, monthBoundaryIndices } = React27.useMemo(() => {
|
|
14398
|
+
let totalColumns = 0;
|
|
14399
|
+
const monthIndices = [];
|
|
14400
|
+
if (gantt.range === "weekly") {
|
|
14401
|
+
let weekIndex = 0;
|
|
14402
|
+
for (const yearData of gantt.timelineData) {
|
|
14403
|
+
const weeksInYear = getWeeksInYear(yearData.year);
|
|
14404
|
+
let currentMonth = -1;
|
|
14405
|
+
for (let w = 1; w <= weeksInYear; w++) {
|
|
14406
|
+
const weekStart = getWeekStartDate(yearData.year, w);
|
|
14407
|
+
const monthOfWeek = weekStart.getMonth();
|
|
14408
|
+
if (monthOfWeek !== currentMonth) {
|
|
14409
|
+
monthIndices.push(weekIndex);
|
|
14410
|
+
currentMonth = monthOfWeek;
|
|
14411
|
+
}
|
|
14412
|
+
weekIndex++;
|
|
14413
|
+
}
|
|
14414
|
+
totalColumns += weeksInYear;
|
|
14415
|
+
}
|
|
14416
|
+
} else {
|
|
14417
|
+
for (const yearData of gantt.timelineData) {
|
|
14418
|
+
const monthsInYear = yearData.quarters.flatMap((q) => q.months).length;
|
|
14419
|
+
totalColumns += monthsInYear;
|
|
14420
|
+
}
|
|
14421
|
+
}
|
|
14422
|
+
return { columns: totalColumns, monthBoundaryIndices: monthIndices };
|
|
14423
|
+
}, [gantt.timelineData, gantt.range]);
|
|
14424
|
+
const columnWidth = gantt.columnWidth * gantt.zoom / 100;
|
|
14425
|
+
const totalWidth = columns * columnWidth;
|
|
14426
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14427
|
+
"div",
|
|
14428
|
+
{
|
|
14429
|
+
className: cn(
|
|
14430
|
+
"pointer-events-none absolute top-0 left-0 h-full",
|
|
14431
|
+
className
|
|
14432
|
+
),
|
|
14433
|
+
style: {
|
|
14434
|
+
marginTop: "var(--gantt-header-height)",
|
|
14435
|
+
width: totalWidth
|
|
14436
|
+
},
|
|
14437
|
+
children: Array.from({ length: columns + 1 }).map((_, index) => {
|
|
14438
|
+
const isMonthBoundary = gantt.range === "weekly" && monthBoundaryIndices.includes(index);
|
|
14439
|
+
const x = Math.round(index * columnWidth);
|
|
14440
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14441
|
+
"div",
|
|
14442
|
+
{
|
|
14443
|
+
className: "absolute top-0 bottom-0",
|
|
14444
|
+
style: {
|
|
14445
|
+
left: x,
|
|
14446
|
+
width: isMonthBoundary ? "2px" : "1px",
|
|
14447
|
+
backgroundColor: isMonthBoundary ? "hsl(var(--foreground) / 0.25)" : "hsl(var(--border) / 0.8)"
|
|
14448
|
+
}
|
|
14449
|
+
},
|
|
14450
|
+
`${id}-grid-${index}`
|
|
14451
|
+
);
|
|
14452
|
+
})
|
|
14453
|
+
}
|
|
14454
|
+
);
|
|
14455
|
+
});
|
|
14456
|
+
GanttGridLines.displayName = "GanttGridLines";
|
|
14457
|
+
var GanttCreateMarkerTrigger = ({
|
|
14458
|
+
onCreateMarker,
|
|
14459
|
+
className
|
|
14460
|
+
}) => {
|
|
14461
|
+
const gantt = React27.useContext(GanttContext);
|
|
14462
|
+
const [mousePosition, mouseRef] = usehooks.useMouse();
|
|
14463
|
+
const [windowScroll] = usehooks.useWindowScroll();
|
|
14464
|
+
const x = usehooks.useThrottle(
|
|
14465
|
+
mousePosition.x - (mouseRef.current?.getBoundingClientRect().x ?? 0) - (windowScroll.x ?? 0),
|
|
14466
|
+
10
|
|
14467
|
+
);
|
|
14468
|
+
const date = getDateByMousePosition(gantt, x);
|
|
14469
|
+
const handleClick = () => onCreateMarker(date);
|
|
14470
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14471
|
+
"div",
|
|
14472
|
+
{
|
|
14473
|
+
className: cn(
|
|
14474
|
+
"group pointer-events-none absolute top-0 left-0 h-full w-full select-none overflow-visible",
|
|
14475
|
+
className
|
|
14476
|
+
),
|
|
14477
|
+
ref: mouseRef,
|
|
14478
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14479
|
+
"div",
|
|
14480
|
+
{
|
|
14481
|
+
className: "-ml-2 pointer-events-auto sticky top-6 z-20 flex w-4 flex-col items-center justify-center gap-1 overflow-visible opacity-0 group-hover:opacity-100",
|
|
14482
|
+
style: { transform: `translateX(${x}px)` },
|
|
14483
|
+
children: [
|
|
14484
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14485
|
+
"button",
|
|
14486
|
+
{
|
|
14487
|
+
className: "z-50 inline-flex h-4 w-4 items-center justify-center rounded-full bg-card",
|
|
14488
|
+
onClick: handleClick,
|
|
14489
|
+
type: "button",
|
|
14490
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PlusIcon, { className: "text-muted-foreground", size: 12 })
|
|
14491
|
+
}
|
|
14492
|
+
),
|
|
14493
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "whitespace-nowrap rounded-sm border border-border/50 bg-background/95 px-2 py-1 text-foreground text-xs backdrop-blur-sm", children: dateFns.formatDate(date, "MMM dd, yyyy") })
|
|
14494
|
+
]
|
|
14495
|
+
}
|
|
14496
|
+
)
|
|
14497
|
+
}
|
|
14498
|
+
);
|
|
14499
|
+
};
|
|
14500
|
+
var GanttFeatureDragHelper = ({
|
|
14501
|
+
direction,
|
|
14502
|
+
featureId,
|
|
14503
|
+
date
|
|
14504
|
+
}) => {
|
|
14505
|
+
const [, setDragging] = useGanttDragging();
|
|
14506
|
+
const { attributes, listeners, setNodeRef } = core.useDraggable({
|
|
14507
|
+
id: `feature-drag-helper-${featureId}`
|
|
14508
|
+
});
|
|
14509
|
+
const isPressed = Boolean(attributes["aria-pressed"]);
|
|
14510
|
+
React27.useEffect(() => setDragging(isPressed), [isPressed, setDragging]);
|
|
14511
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14512
|
+
"div",
|
|
14513
|
+
{
|
|
14514
|
+
className: cn(
|
|
14515
|
+
"group -translate-y-1/2 !cursor-col-resize absolute top-1/2 z-[3] h-full w-6 rounded-sm outline-none",
|
|
14516
|
+
direction === "left" ? "-left-2.5" : "-right-2.5"
|
|
14517
|
+
),
|
|
14518
|
+
ref: setNodeRef,
|
|
14519
|
+
...attributes,
|
|
14520
|
+
...listeners,
|
|
14521
|
+
children: [
|
|
14522
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14523
|
+
"div",
|
|
14524
|
+
{
|
|
14525
|
+
className: cn(
|
|
14526
|
+
"-translate-y-1/2 absolute top-1/2 h-[80%] w-1 rounded-sm bg-muted-foreground opacity-0 transition-all",
|
|
14527
|
+
direction === "left" ? "left-2.5" : "right-2.5",
|
|
14528
|
+
direction === "left" ? "group-hover:left-0" : "group-hover:right-0",
|
|
14529
|
+
isPressed && (direction === "left" ? "left-0" : "right-0"),
|
|
14530
|
+
"group-hover:opacity-100",
|
|
14531
|
+
isPressed && "opacity-100"
|
|
14532
|
+
)
|
|
14533
|
+
}
|
|
14534
|
+
),
|
|
14535
|
+
date && /* @__PURE__ */ jsxRuntime.jsx(
|
|
14536
|
+
"div",
|
|
14537
|
+
{
|
|
14538
|
+
className: cn(
|
|
14539
|
+
"-translate-x-1/2 absolute top-10 hidden whitespace-nowrap rounded-sm border border-border/50 bg-background/95 px-2 py-1 text-foreground text-xs backdrop-blur-sm group-hover:block",
|
|
14540
|
+
isPressed && "block"
|
|
14541
|
+
),
|
|
14542
|
+
children: dateFns.format(date, "MMM dd, yyyy")
|
|
14543
|
+
}
|
|
14544
|
+
)
|
|
14545
|
+
]
|
|
14546
|
+
}
|
|
14547
|
+
);
|
|
14548
|
+
};
|
|
14549
|
+
var GanttFeatureItemCard = ({
|
|
14550
|
+
id,
|
|
14551
|
+
children
|
|
14552
|
+
}) => {
|
|
14553
|
+
const [, setDragging] = useGanttDragging();
|
|
14554
|
+
const { attributes, listeners, setNodeRef } = core.useDraggable({ id });
|
|
14555
|
+
const isPressed = Boolean(attributes["aria-pressed"]);
|
|
14556
|
+
React27.useEffect(() => setDragging(isPressed), [isPressed, setDragging]);
|
|
14557
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "h-full w-full rounded-sm border bg-background px-2 py-1.5 text-xs shadow-sm overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14558
|
+
"div",
|
|
14559
|
+
{
|
|
14560
|
+
className: cn(
|
|
14561
|
+
"flex h-full w-full items-center justify-between gap-2 text-left",
|
|
14562
|
+
isPressed && "cursor-grabbing"
|
|
14563
|
+
),
|
|
14564
|
+
...attributes,
|
|
14565
|
+
...listeners,
|
|
14566
|
+
ref: setNodeRef,
|
|
14567
|
+
children
|
|
14568
|
+
}
|
|
14569
|
+
) });
|
|
14570
|
+
};
|
|
14571
|
+
var GanttFeatureItem = ({
|
|
14572
|
+
onMove,
|
|
14573
|
+
contextMenuActions,
|
|
14574
|
+
onEdit,
|
|
14575
|
+
onDelete,
|
|
14576
|
+
onDuplicate,
|
|
14577
|
+
children,
|
|
14578
|
+
className,
|
|
14579
|
+
...feature
|
|
14580
|
+
}) => {
|
|
14581
|
+
const [scrollX] = useGanttScrollX();
|
|
14582
|
+
const gantt = React27.useContext(GanttContext);
|
|
14583
|
+
const timelineStartDate = React27.useMemo(
|
|
14584
|
+
() => new Date(gantt.timelineData.at(0)?.year ?? 0, 0, 1),
|
|
14585
|
+
[gantt.timelineData]
|
|
14586
|
+
);
|
|
14587
|
+
const [startAt, setStartAt] = React27.useState(feature.startAt);
|
|
14588
|
+
const [endAt, setEndAt] = React27.useState(feature.endAt);
|
|
14589
|
+
const width = React27.useMemo(
|
|
14590
|
+
() => Math.round(getWidth(startAt, endAt, gantt)),
|
|
14591
|
+
[startAt, endAt, gantt]
|
|
14592
|
+
);
|
|
14593
|
+
const offset = React27.useMemo(
|
|
14594
|
+
() => Math.round(getOffset(startAt, timelineStartDate, gantt)),
|
|
14595
|
+
[startAt, timelineStartDate, gantt]
|
|
14596
|
+
);
|
|
14597
|
+
const addRange = React27.useMemo(() => getAddRange(gantt.range), [gantt.range]);
|
|
14598
|
+
const [mousePosition] = usehooks.useMouse();
|
|
14599
|
+
const [previousMouseX, setPreviousMouseX] = React27.useState(0);
|
|
14600
|
+
const [previousStartAt, setPreviousStartAt] = React27.useState(startAt);
|
|
14601
|
+
const [previousEndAt, setPreviousEndAt] = React27.useState(endAt);
|
|
14602
|
+
const mouseSensor = core.useSensor(core.MouseSensor, {
|
|
14603
|
+
activationConstraint: {
|
|
14604
|
+
distance: 10
|
|
14605
|
+
}
|
|
14606
|
+
});
|
|
14607
|
+
const handleItemDragStart = React27.useCallback(() => {
|
|
14608
|
+
setPreviousMouseX(mousePosition.x);
|
|
14609
|
+
setPreviousStartAt(startAt);
|
|
14610
|
+
setPreviousEndAt(endAt);
|
|
14611
|
+
}, [mousePosition.x, startAt, endAt]);
|
|
14612
|
+
const handleItemDragMove = React27.useCallback(() => {
|
|
14613
|
+
const currentDate = getDateByMousePosition(gantt, mousePosition.x);
|
|
14614
|
+
const originalDate = getDateByMousePosition(gantt, previousMouseX);
|
|
14615
|
+
const delta = gantt.range === "weekly" ? dateFns.differenceInDays(currentDate, originalDate) : getInnerDifferenceIn(gantt.range)(currentDate, originalDate);
|
|
14616
|
+
const newStartDate = dateFns.addDays(previousStartAt, delta);
|
|
14617
|
+
const newEndDate = previousEndAt ? dateFns.addDays(previousEndAt, delta) : null;
|
|
14618
|
+
setStartAt(newStartDate);
|
|
14619
|
+
setEndAt(newEndDate);
|
|
14620
|
+
}, [gantt, mousePosition.x, previousMouseX, previousStartAt, previousEndAt]);
|
|
14621
|
+
const onDragEnd = React27.useCallback(
|
|
14622
|
+
() => onMove?.(feature.id, startAt, endAt),
|
|
14623
|
+
[onMove, feature.id, startAt, endAt]
|
|
14624
|
+
);
|
|
14625
|
+
const handleLeftDragMove = React27.useCallback(() => {
|
|
14626
|
+
const ganttRect = gantt.ref?.current?.getBoundingClientRect();
|
|
14627
|
+
const x = mousePosition.x - (ganttRect?.left ?? 0) + scrollX - gantt.sidebarWidth;
|
|
14628
|
+
const newStartAt = getDateByMousePosition(gantt, x);
|
|
14629
|
+
setStartAt(newStartAt);
|
|
14630
|
+
}, [gantt, mousePosition.x, scrollX]);
|
|
14631
|
+
const handleRightDragMove = React27.useCallback(() => {
|
|
14632
|
+
const ganttRect = gantt.ref?.current?.getBoundingClientRect();
|
|
14633
|
+
const x = mousePosition.x - (ganttRect?.left ?? 0) + scrollX - gantt.sidebarWidth;
|
|
14634
|
+
const newEndAt = getDateByMousePosition(gantt, x);
|
|
14635
|
+
setEndAt(newEndAt);
|
|
14636
|
+
}, [gantt, mousePosition.x, scrollX]);
|
|
14637
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14638
|
+
"div",
|
|
14639
|
+
{
|
|
14640
|
+
className: cn("relative flex w-max min-w-full", className),
|
|
14641
|
+
style: { height: "var(--gantt-row-height)" },
|
|
14642
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14643
|
+
"div",
|
|
14644
|
+
{
|
|
14645
|
+
className: "pointer-events-auto absolute",
|
|
14646
|
+
style: {
|
|
14647
|
+
height: "calc(var(--gantt-row-height) - 8px)",
|
|
14648
|
+
top: "4px",
|
|
14649
|
+
width,
|
|
14650
|
+
left: offset
|
|
14651
|
+
},
|
|
14652
|
+
children: [
|
|
14653
|
+
onMove && /* @__PURE__ */ jsxRuntime.jsx(
|
|
14654
|
+
core.DndContext,
|
|
14655
|
+
{
|
|
14656
|
+
modifiers: [modifiers.restrictToHorizontalAxis],
|
|
14657
|
+
onDragEnd,
|
|
14658
|
+
onDragMove: handleLeftDragMove,
|
|
14659
|
+
sensors: [mouseSensor],
|
|
14660
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14661
|
+
GanttFeatureDragHelper,
|
|
14662
|
+
{
|
|
14663
|
+
date: startAt,
|
|
14664
|
+
direction: "left",
|
|
14665
|
+
featureId: feature.id
|
|
14666
|
+
}
|
|
14667
|
+
)
|
|
14668
|
+
}
|
|
14669
|
+
),
|
|
14670
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ContextMenu, { children: [
|
|
14671
|
+
/* @__PURE__ */ jsxRuntime.jsx(ContextMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full w-full", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14672
|
+
core.DndContext,
|
|
14673
|
+
{
|
|
14674
|
+
modifiers: [modifiers.restrictToHorizontalAxis],
|
|
14675
|
+
onDragEnd,
|
|
14676
|
+
onDragMove: handleItemDragMove,
|
|
14677
|
+
onDragStart: handleItemDragStart,
|
|
14678
|
+
sensors: [mouseSensor],
|
|
14679
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(GanttFeatureItemCard, { id: feature.id, children: children ?? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "flex-1 truncate text-xs", children: feature.name }) })
|
|
14680
|
+
}
|
|
14681
|
+
) }) }),
|
|
14682
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ContextMenuContent, { children: [
|
|
14683
|
+
onEdit && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14684
|
+
ContextMenuItem,
|
|
14685
|
+
{
|
|
14686
|
+
className: "flex items-center gap-2",
|
|
14687
|
+
onClick: () => onEdit(feature),
|
|
14688
|
+
children: [
|
|
14689
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.PencilIcon, { size: 14 }),
|
|
14690
|
+
"Edit"
|
|
14691
|
+
]
|
|
14692
|
+
}
|
|
14693
|
+
),
|
|
14694
|
+
onDuplicate && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14695
|
+
ContextMenuItem,
|
|
14696
|
+
{
|
|
14697
|
+
className: "flex items-center gap-2",
|
|
14698
|
+
onClick: () => onDuplicate(feature),
|
|
14699
|
+
children: [
|
|
14700
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CopyIcon, { size: 14 }),
|
|
14701
|
+
"Duplicate"
|
|
14702
|
+
]
|
|
14703
|
+
}
|
|
14704
|
+
),
|
|
14705
|
+
contextMenuActions?.map((action, index) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14706
|
+
ContextMenuItem,
|
|
14707
|
+
{
|
|
14708
|
+
className: cn(
|
|
14709
|
+
"flex items-center gap-2",
|
|
14710
|
+
action.destructive && "text-destructive"
|
|
14711
|
+
),
|
|
14712
|
+
onClick: () => action.onClick(feature),
|
|
14713
|
+
disabled: action.disabled,
|
|
14714
|
+
children: [
|
|
14715
|
+
action.icon,
|
|
14716
|
+
action.label
|
|
14717
|
+
]
|
|
14718
|
+
},
|
|
14719
|
+
index
|
|
14720
|
+
)),
|
|
14721
|
+
onDelete && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14722
|
+
ContextMenuItem,
|
|
14723
|
+
{
|
|
14724
|
+
className: "flex items-center gap-2 text-destructive",
|
|
14725
|
+
onClick: () => onDelete(feature),
|
|
14726
|
+
children: [
|
|
14727
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrashIcon, { size: 14 }),
|
|
14728
|
+
"Delete"
|
|
14729
|
+
]
|
|
14730
|
+
}
|
|
14731
|
+
)
|
|
14732
|
+
] })
|
|
14733
|
+
] }),
|
|
14734
|
+
onMove && /* @__PURE__ */ jsxRuntime.jsx(
|
|
14735
|
+
core.DndContext,
|
|
14736
|
+
{
|
|
14737
|
+
modifiers: [modifiers.restrictToHorizontalAxis],
|
|
14738
|
+
onDragEnd,
|
|
14739
|
+
onDragMove: handleRightDragMove,
|
|
14740
|
+
sensors: [mouseSensor],
|
|
14741
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14742
|
+
GanttFeatureDragHelper,
|
|
14743
|
+
{
|
|
14744
|
+
date: endAt ?? addRange(startAt, 2),
|
|
14745
|
+
direction: "right",
|
|
14746
|
+
featureId: feature.id
|
|
14747
|
+
}
|
|
14748
|
+
)
|
|
14749
|
+
}
|
|
14750
|
+
)
|
|
14751
|
+
]
|
|
14752
|
+
}
|
|
14753
|
+
)
|
|
14754
|
+
}
|
|
14755
|
+
);
|
|
14756
|
+
};
|
|
14757
|
+
var GanttFeatureListGroup = ({
|
|
14758
|
+
children,
|
|
14759
|
+
className
|
|
14760
|
+
}) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
14761
|
+
"div",
|
|
14762
|
+
{
|
|
14763
|
+
className,
|
|
14764
|
+
style: { paddingTop: "var(--gantt-row-height)" },
|
|
14765
|
+
children
|
|
14766
|
+
}
|
|
14767
|
+
);
|
|
14768
|
+
var GanttFeatureRow = ({
|
|
14769
|
+
features,
|
|
14770
|
+
onMove,
|
|
14771
|
+
children,
|
|
14772
|
+
className
|
|
14773
|
+
}) => {
|
|
14774
|
+
const sortedFeatures = [...features].sort(
|
|
14775
|
+
(a, b) => a.startAt.getTime() - b.startAt.getTime()
|
|
14776
|
+
);
|
|
14777
|
+
const featureWithPositions = [];
|
|
14778
|
+
const subRowEndTimes = [];
|
|
14779
|
+
for (const feature of sortedFeatures) {
|
|
14780
|
+
let subRow = 0;
|
|
14781
|
+
while (subRow < subRowEndTimes.length && subRowEndTimes[subRow] > feature.startAt) {
|
|
14782
|
+
subRow++;
|
|
14783
|
+
}
|
|
14784
|
+
if (subRow === subRowEndTimes.length) {
|
|
14785
|
+
subRowEndTimes.push(feature.endAt);
|
|
14786
|
+
} else {
|
|
14787
|
+
subRowEndTimes[subRow] = feature.endAt;
|
|
14788
|
+
}
|
|
14789
|
+
featureWithPositions.push({ ...feature, subRow });
|
|
14790
|
+
}
|
|
14791
|
+
const maxSubRows = Math.max(1, subRowEndTimes.length);
|
|
14792
|
+
const subRowHeight = 36;
|
|
14793
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14794
|
+
"div",
|
|
14795
|
+
{
|
|
14796
|
+
className: cn("relative", className),
|
|
14797
|
+
style: {
|
|
14798
|
+
height: `${maxSubRows * subRowHeight}px`,
|
|
14799
|
+
minHeight: "var(--gantt-row-height)"
|
|
14800
|
+
},
|
|
14801
|
+
children: featureWithPositions.map((feature) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
14802
|
+
"div",
|
|
14803
|
+
{
|
|
14804
|
+
className: "absolute w-full",
|
|
14805
|
+
style: {
|
|
14806
|
+
top: `${feature.subRow * subRowHeight}px`,
|
|
14807
|
+
height: `${subRowHeight}px`
|
|
14808
|
+
},
|
|
14809
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(GanttFeatureItem, { ...feature, onMove, children: children ? children(feature) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "flex-1 truncate text-xs", children: feature.name }) })
|
|
14810
|
+
},
|
|
14811
|
+
feature.id
|
|
14812
|
+
))
|
|
14813
|
+
}
|
|
14814
|
+
);
|
|
14815
|
+
};
|
|
14816
|
+
var GanttFeatureList = ({
|
|
14817
|
+
className,
|
|
14818
|
+
children
|
|
14819
|
+
}) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
14820
|
+
"div",
|
|
14821
|
+
{
|
|
14822
|
+
className: cn("absolute top-0 left-0 h-max w-max min-w-full", className),
|
|
14823
|
+
style: { marginTop: "var(--gantt-header-height)" },
|
|
14824
|
+
children
|
|
14825
|
+
}
|
|
14826
|
+
);
|
|
14827
|
+
var GanttMarker = React27.memo(({ label, date, id, onRemove, className }) => {
|
|
14828
|
+
const gantt = React27.useContext(GanttContext);
|
|
14829
|
+
const differenceIn = React27.useMemo(
|
|
14830
|
+
() => getDifferenceIn(gantt.range),
|
|
14831
|
+
[gantt.range]
|
|
14832
|
+
);
|
|
14833
|
+
const timelineStartDate = React27.useMemo(
|
|
14834
|
+
() => new Date(gantt.timelineData.at(0)?.year ?? 0, 0, 1),
|
|
14835
|
+
[gantt.timelineData]
|
|
14836
|
+
);
|
|
14837
|
+
const offset = React27.useMemo(
|
|
14838
|
+
() => differenceIn(date, timelineStartDate),
|
|
14839
|
+
[differenceIn, date, timelineStartDate]
|
|
14840
|
+
);
|
|
14841
|
+
const innerOffset = React27.useMemo(
|
|
14842
|
+
() => calculateInnerOffset(
|
|
14843
|
+
date,
|
|
14844
|
+
gantt.range,
|
|
14845
|
+
gantt.columnWidth * gantt.zoom / 100
|
|
14846
|
+
),
|
|
14847
|
+
[date, gantt.range, gantt.columnWidth, gantt.zoom]
|
|
14848
|
+
);
|
|
14849
|
+
const handleRemove = React27.useCallback(() => onRemove?.(id), [onRemove, id]);
|
|
14850
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14851
|
+
"div",
|
|
14852
|
+
{
|
|
14853
|
+
className: "pointer-events-none absolute top-0 left-0 z-20 flex h-full select-none flex-col items-center justify-center overflow-visible",
|
|
14854
|
+
style: {
|
|
14855
|
+
width: 0,
|
|
14856
|
+
transform: `translateX(calc(var(--gantt-column-width) * ${offset} + ${Math.round(innerOffset)}px))`
|
|
14857
|
+
},
|
|
14858
|
+
children: [
|
|
14859
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ContextMenu, { children: [
|
|
14860
|
+
/* @__PURE__ */ jsxRuntime.jsx(ContextMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14861
|
+
"div",
|
|
14862
|
+
{
|
|
14863
|
+
className: cn(
|
|
14864
|
+
"group pointer-events-auto sticky top-0 flex select-auto flex-col flex-nowrap items-center justify-center whitespace-nowrap rounded-sm bg-card px-2 py-1 text-foreground text-xs shadow-sm",
|
|
14865
|
+
className
|
|
14866
|
+
),
|
|
14867
|
+
children: [
|
|
14868
|
+
label,
|
|
14869
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-h-[0] overflow-hidden opacity-80 transition-all group-hover:max-h-[2rem]", children: dateFns.formatDate(date, "MMM dd, yyyy") })
|
|
14870
|
+
]
|
|
14871
|
+
}
|
|
14872
|
+
) }),
|
|
14873
|
+
/* @__PURE__ */ jsxRuntime.jsx(ContextMenuContent, { children: onRemove ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14874
|
+
ContextMenuItem,
|
|
14875
|
+
{
|
|
14876
|
+
className: "flex items-center gap-2 text-destructive",
|
|
14877
|
+
onClick: handleRemove,
|
|
14878
|
+
children: [
|
|
14879
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrashIcon, { size: 16 }),
|
|
14880
|
+
"Remove marker"
|
|
14881
|
+
]
|
|
14882
|
+
}
|
|
14883
|
+
) : null })
|
|
14884
|
+
] }),
|
|
14885
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("h-full w-px bg-card", className) })
|
|
14886
|
+
]
|
|
14887
|
+
}
|
|
14888
|
+
);
|
|
14889
|
+
});
|
|
14890
|
+
GanttMarker.displayName = "GanttMarker";
|
|
14891
|
+
var GanttProvider = ({
|
|
14892
|
+
zoom = 100,
|
|
14893
|
+
range = "monthly",
|
|
14894
|
+
onAddItem,
|
|
14895
|
+
children,
|
|
14896
|
+
className,
|
|
14897
|
+
defaultExpandedGroups = {}
|
|
14898
|
+
}) => {
|
|
14899
|
+
const scrollRef = React27.useRef(null);
|
|
14900
|
+
const [timelineData, setTimelineData] = React27.useState(
|
|
14901
|
+
createInitialTimelineData(/* @__PURE__ */ new Date())
|
|
14902
|
+
);
|
|
14903
|
+
const [, setScrollX] = useGanttScrollX();
|
|
14904
|
+
const sidebarWidth = 280;
|
|
14905
|
+
const [expandedGroups, setExpandedGroups] = React27.useState(defaultExpandedGroups);
|
|
14906
|
+
const setGroupExpanded = React27.useCallback((groupId, expanded) => {
|
|
14907
|
+
setExpandedGroups((prev) => ({ ...prev, [groupId]: expanded }));
|
|
14908
|
+
}, []);
|
|
14909
|
+
const headerHeight = 60;
|
|
14910
|
+
const rowHeight = 36;
|
|
14911
|
+
let columnWidth = 50;
|
|
14912
|
+
if (range === "monthly") {
|
|
14913
|
+
columnWidth = 150;
|
|
14914
|
+
} else if (range === "quarterly") {
|
|
14915
|
+
columnWidth = 100;
|
|
14916
|
+
}
|
|
14917
|
+
const cssVariables = React27.useMemo(
|
|
14918
|
+
() => ({
|
|
14919
|
+
"--gantt-zoom": `${zoom}`,
|
|
14920
|
+
"--gantt-column-width": `${zoom / 100 * columnWidth}px`,
|
|
14921
|
+
"--gantt-header-height": `${headerHeight}px`,
|
|
14922
|
+
"--gantt-row-height": `${rowHeight}px`,
|
|
14923
|
+
"--gantt-sidebar-width": `${sidebarWidth}px`
|
|
14924
|
+
}),
|
|
14925
|
+
[zoom, columnWidth, sidebarWidth]
|
|
14926
|
+
);
|
|
14927
|
+
React27.useEffect(() => {
|
|
14928
|
+
if (scrollRef.current) {
|
|
14929
|
+
scrollRef.current.scrollLeft = scrollRef.current.scrollWidth / 2 - scrollRef.current.clientWidth / 2;
|
|
14930
|
+
setScrollX(scrollRef.current.scrollLeft);
|
|
14931
|
+
}
|
|
14932
|
+
}, [setScrollX]);
|
|
14933
|
+
const handleScroll = React27.useCallback(
|
|
14934
|
+
throttle__default.default(() => {
|
|
14935
|
+
const scrollElement = scrollRef.current;
|
|
14936
|
+
if (!scrollElement) {
|
|
14937
|
+
return;
|
|
14938
|
+
}
|
|
14939
|
+
const { scrollLeft, scrollWidth, clientWidth } = scrollElement;
|
|
14940
|
+
setScrollX(scrollLeft);
|
|
14941
|
+
if (scrollLeft === 0) {
|
|
14942
|
+
const firstYear = timelineData[0]?.year;
|
|
14943
|
+
if (!firstYear) {
|
|
14944
|
+
return;
|
|
14945
|
+
}
|
|
14946
|
+
const newTimelineData = [...timelineData];
|
|
14947
|
+
newTimelineData.unshift({
|
|
14948
|
+
year: firstYear - 1,
|
|
14949
|
+
quarters: new Array(4).fill(null).map((_, quarterIndex) => ({
|
|
14950
|
+
months: new Array(3).fill(null).map((_2, monthIndex) => {
|
|
14951
|
+
const month = quarterIndex * 3 + monthIndex;
|
|
14952
|
+
return {
|
|
14953
|
+
days: dateFns.getDaysInMonth(new Date(firstYear, month, 1))
|
|
14954
|
+
};
|
|
14955
|
+
})
|
|
14956
|
+
}))
|
|
14957
|
+
});
|
|
14958
|
+
setTimelineData(newTimelineData);
|
|
14959
|
+
scrollElement.scrollLeft = scrollElement.clientWidth;
|
|
14960
|
+
setScrollX(scrollElement.scrollLeft);
|
|
14961
|
+
} else if (scrollLeft + clientWidth >= scrollWidth) {
|
|
14962
|
+
const lastYear = timelineData.at(-1)?.year;
|
|
14963
|
+
if (!lastYear) {
|
|
14964
|
+
return;
|
|
14965
|
+
}
|
|
14966
|
+
const newTimelineData = [...timelineData];
|
|
14967
|
+
newTimelineData.push({
|
|
14968
|
+
year: lastYear + 1,
|
|
14969
|
+
quarters: new Array(4).fill(null).map((_, quarterIndex) => ({
|
|
14970
|
+
months: new Array(3).fill(null).map((_2, monthIndex) => {
|
|
14971
|
+
const month = quarterIndex * 3 + monthIndex;
|
|
14972
|
+
return {
|
|
14973
|
+
days: dateFns.getDaysInMonth(new Date(lastYear, month, 1))
|
|
14974
|
+
};
|
|
14975
|
+
})
|
|
14976
|
+
}))
|
|
14977
|
+
});
|
|
14978
|
+
setTimelineData(newTimelineData);
|
|
14979
|
+
scrollElement.scrollLeft = scrollElement.scrollWidth - scrollElement.clientWidth;
|
|
14980
|
+
setScrollX(scrollElement.scrollLeft);
|
|
14981
|
+
}
|
|
14982
|
+
}, 100),
|
|
14983
|
+
[]
|
|
14984
|
+
);
|
|
14985
|
+
React27.useEffect(() => {
|
|
14986
|
+
const scrollElement = scrollRef.current;
|
|
14987
|
+
if (scrollElement) {
|
|
14988
|
+
scrollElement.addEventListener("scroll", handleScroll);
|
|
14989
|
+
}
|
|
14990
|
+
return () => {
|
|
14991
|
+
if (scrollElement) {
|
|
14992
|
+
scrollElement.removeEventListener("scroll", handleScroll);
|
|
14993
|
+
}
|
|
14994
|
+
};
|
|
14995
|
+
}, [handleScroll]);
|
|
14996
|
+
const scrollToFeature = React27.useCallback(
|
|
14997
|
+
(feature) => {
|
|
14998
|
+
const scrollElement = scrollRef.current;
|
|
14999
|
+
if (!scrollElement) {
|
|
15000
|
+
return;
|
|
15001
|
+
}
|
|
15002
|
+
const timelineStartDate = new Date(timelineData[0].year, 0, 1);
|
|
15003
|
+
const offset = getOffset(feature.startAt, timelineStartDate, {
|
|
15004
|
+
zoom,
|
|
15005
|
+
range,
|
|
15006
|
+
columnWidth});
|
|
15007
|
+
const targetScrollLeft = Math.max(0, offset);
|
|
15008
|
+
scrollElement.scrollTo({
|
|
15009
|
+
left: targetScrollLeft,
|
|
15010
|
+
behavior: "smooth"
|
|
15011
|
+
});
|
|
15012
|
+
},
|
|
15013
|
+
[timelineData, zoom, range, columnWidth, sidebarWidth, onAddItem, expandedGroups, setGroupExpanded]
|
|
15014
|
+
);
|
|
15015
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15016
|
+
GanttContext.Provider,
|
|
15017
|
+
{
|
|
15018
|
+
value: {
|
|
15019
|
+
zoom,
|
|
15020
|
+
range,
|
|
15021
|
+
headerHeight,
|
|
15022
|
+
columnWidth,
|
|
15023
|
+
sidebarWidth,
|
|
15024
|
+
rowHeight,
|
|
15025
|
+
onAddItem,
|
|
15026
|
+
timelineData,
|
|
15027
|
+
placeholderLength: 2,
|
|
15028
|
+
ref: scrollRef,
|
|
15029
|
+
scrollToFeature,
|
|
15030
|
+
expandedGroups,
|
|
15031
|
+
setGroupExpanded
|
|
15032
|
+
},
|
|
15033
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15034
|
+
"div",
|
|
15035
|
+
{
|
|
15036
|
+
className: cn(
|
|
15037
|
+
"gantt relative isolate grid h-full w-full flex-none select-none rounded-sm border bg-background",
|
|
15038
|
+
range,
|
|
15039
|
+
className
|
|
15040
|
+
),
|
|
15041
|
+
style: {
|
|
15042
|
+
...cssVariables,
|
|
15043
|
+
gridTemplateColumns: "var(--gantt-sidebar-width) 1fr"
|
|
15044
|
+
},
|
|
15045
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15046
|
+
"div",
|
|
15047
|
+
{
|
|
15048
|
+
className: "col-span-2 grid overflow-auto",
|
|
15049
|
+
ref: scrollRef,
|
|
15050
|
+
style: {
|
|
15051
|
+
gridTemplateColumns: "var(--gantt-sidebar-width) 1fr"
|
|
15052
|
+
},
|
|
15053
|
+
children
|
|
15054
|
+
}
|
|
15055
|
+
)
|
|
15056
|
+
}
|
|
15057
|
+
)
|
|
15058
|
+
}
|
|
15059
|
+
);
|
|
15060
|
+
};
|
|
15061
|
+
var GanttTimeline = ({
|
|
15062
|
+
children,
|
|
15063
|
+
className
|
|
15064
|
+
}) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
15065
|
+
"div",
|
|
15066
|
+
{
|
|
15067
|
+
className: cn(
|
|
15068
|
+
"relative flex h-max min-h-full w-max flex-none",
|
|
15069
|
+
className
|
|
15070
|
+
),
|
|
15071
|
+
children
|
|
15072
|
+
}
|
|
15073
|
+
);
|
|
15074
|
+
var GanttToday = ({ className }) => {
|
|
15075
|
+
const label = "Today";
|
|
15076
|
+
const date = React27.useMemo(() => /* @__PURE__ */ new Date(), []);
|
|
15077
|
+
const gantt = React27.useContext(GanttContext);
|
|
15078
|
+
const differenceIn = React27.useMemo(
|
|
15079
|
+
() => getDifferenceIn(gantt.range),
|
|
15080
|
+
[gantt.range]
|
|
15081
|
+
);
|
|
15082
|
+
const timelineStartDate = React27.useMemo(
|
|
15083
|
+
() => new Date(gantt.timelineData.at(0)?.year ?? 0, 0, 1),
|
|
15084
|
+
[gantt.timelineData]
|
|
15085
|
+
);
|
|
15086
|
+
const offset = React27.useMemo(
|
|
15087
|
+
() => differenceIn(date, timelineStartDate),
|
|
15088
|
+
[differenceIn, date, timelineStartDate]
|
|
15089
|
+
);
|
|
15090
|
+
const innerOffset = React27.useMemo(
|
|
15091
|
+
() => Math.round(calculateInnerOffset(
|
|
15092
|
+
date,
|
|
15093
|
+
gantt.range,
|
|
15094
|
+
gantt.columnWidth * gantt.zoom / 100
|
|
15095
|
+
)),
|
|
15096
|
+
[date, gantt.range, gantt.columnWidth, gantt.zoom]
|
|
15097
|
+
);
|
|
15098
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15099
|
+
"div",
|
|
15100
|
+
{
|
|
15101
|
+
className: "pointer-events-none absolute top-0 left-0 z-20 flex h-full select-none flex-col items-center justify-center overflow-visible",
|
|
15102
|
+
style: {
|
|
15103
|
+
width: 0,
|
|
15104
|
+
transform: `translateX(calc(var(--gantt-column-width) * ${offset} + ${innerOffset}px))`
|
|
15105
|
+
},
|
|
15106
|
+
children: [
|
|
15107
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
15108
|
+
"div",
|
|
15109
|
+
{
|
|
15110
|
+
className: cn(
|
|
15111
|
+
"group pointer-events-auto sticky top-0 flex select-auto flex-col flex-nowrap items-center justify-center whitespace-nowrap rounded-sm bg-primary px-2 py-1 text-primary-foreground text-xs shadow-sm",
|
|
15112
|
+
className
|
|
15113
|
+
),
|
|
15114
|
+
children: [
|
|
15115
|
+
label,
|
|
15116
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-h-[0] overflow-hidden opacity-80 transition-all group-hover:max-h-[2rem]", children: dateFns.formatDate(date, "MMM dd, yyyy") })
|
|
15117
|
+
]
|
|
15118
|
+
}
|
|
15119
|
+
),
|
|
15120
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("h-full w-px bg-primary", className) })
|
|
15121
|
+
]
|
|
15122
|
+
}
|
|
15123
|
+
);
|
|
15124
|
+
};
|
|
15125
|
+
var t = tunnel__default.default();
|
|
15126
|
+
var KanbanContext = React27.createContext({
|
|
15127
|
+
columns: [],
|
|
15128
|
+
data: [],
|
|
15129
|
+
activeCardId: null
|
|
15130
|
+
});
|
|
15131
|
+
var KanbanBoard = ({ id, children, className }) => {
|
|
15132
|
+
const { isOver, setNodeRef } = core.useDroppable({
|
|
15133
|
+
id
|
|
15134
|
+
});
|
|
15135
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15136
|
+
"div",
|
|
15137
|
+
{
|
|
15138
|
+
className: cn(
|
|
15139
|
+
"flex size-full min-h-40 flex-col divide-y overflow-hidden rounded-md border bg-secondary text-xs shadow-sm ring-2 transition-all",
|
|
15140
|
+
isOver ? "ring-primary" : "ring-transparent",
|
|
15141
|
+
className
|
|
15142
|
+
),
|
|
15143
|
+
ref: setNodeRef,
|
|
15144
|
+
children
|
|
15145
|
+
}
|
|
15146
|
+
);
|
|
15147
|
+
};
|
|
15148
|
+
var KanbanCard = ({
|
|
15149
|
+
id,
|
|
15150
|
+
name,
|
|
15151
|
+
children,
|
|
15152
|
+
className
|
|
15153
|
+
}) => {
|
|
15154
|
+
const {
|
|
15155
|
+
attributes,
|
|
15156
|
+
listeners,
|
|
15157
|
+
setNodeRef,
|
|
15158
|
+
transition,
|
|
15159
|
+
transform,
|
|
15160
|
+
isDragging
|
|
15161
|
+
} = sortable.useSortable({
|
|
15162
|
+
id
|
|
15163
|
+
});
|
|
15164
|
+
const { activeCardId } = React27.useContext(KanbanContext);
|
|
15165
|
+
const style = {
|
|
15166
|
+
transition,
|
|
15167
|
+
transform: utilities.CSS.Transform.toString(transform)
|
|
15168
|
+
};
|
|
15169
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
15170
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style, ...listeners, ...attributes, ref: setNodeRef, className: "min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15171
|
+
Card,
|
|
15172
|
+
{
|
|
15173
|
+
className: cn(
|
|
15174
|
+
"cursor-grab gap-4 rounded-md p-2 shadow-sm overflow-hidden",
|
|
15175
|
+
isDragging && "pointer-events-none cursor-grabbing opacity-30",
|
|
15176
|
+
className
|
|
15177
|
+
),
|
|
15178
|
+
children: children ?? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "m-0 font-medium text-sm", children: name })
|
|
15179
|
+
}
|
|
15180
|
+
) }),
|
|
15181
|
+
activeCardId === id && /* @__PURE__ */ jsxRuntime.jsx(t.In, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15182
|
+
Card,
|
|
15183
|
+
{
|
|
15184
|
+
className: cn(
|
|
15185
|
+
"cursor-grab gap-4 rounded-md p-2 shadow-sm ring-2 ring-primary overflow-hidden",
|
|
15186
|
+
isDragging && "cursor-grabbing",
|
|
15187
|
+
className
|
|
15188
|
+
),
|
|
15189
|
+
children: children ?? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "m-0 font-medium text-sm", children: name })
|
|
15190
|
+
}
|
|
15191
|
+
) })
|
|
15192
|
+
] });
|
|
15193
|
+
};
|
|
15194
|
+
var KanbanCards = ({
|
|
15195
|
+
children,
|
|
15196
|
+
className,
|
|
15197
|
+
...props
|
|
15198
|
+
}) => {
|
|
15199
|
+
const { data } = React27.useContext(KanbanContext);
|
|
15200
|
+
const filteredData = data.filter((item) => item.column === props.id);
|
|
15201
|
+
const items = filteredData.map((item) => item.id);
|
|
15202
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ScrollArea, { className: "overflow-hidden", children: [
|
|
15203
|
+
/* @__PURE__ */ jsxRuntime.jsx(sortable.SortableContext, { items, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15204
|
+
"div",
|
|
15205
|
+
{
|
|
15206
|
+
className: cn("flex flex-grow flex-col gap-2 p-2", className),
|
|
15207
|
+
...props,
|
|
15208
|
+
children: filteredData.map(children)
|
|
15209
|
+
}
|
|
15210
|
+
) }),
|
|
15211
|
+
/* @__PURE__ */ jsxRuntime.jsx(ScrollBar, { orientation: "vertical" })
|
|
15212
|
+
] });
|
|
15213
|
+
};
|
|
15214
|
+
var KanbanHeader = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("m-0 p-2 font-semibold text-sm", className), ...props });
|
|
15215
|
+
var KanbanProvider = ({
|
|
15216
|
+
children,
|
|
15217
|
+
onDragStart,
|
|
15218
|
+
onDragEnd,
|
|
15219
|
+
onDragOver,
|
|
15220
|
+
className,
|
|
15221
|
+
columns,
|
|
15222
|
+
data,
|
|
15223
|
+
onDataChange,
|
|
15224
|
+
...props
|
|
15225
|
+
}) => {
|
|
15226
|
+
const [activeCardId, setActiveCardId] = React27.useState(null);
|
|
15227
|
+
const sensors = core.useSensors(
|
|
15228
|
+
core.useSensor(core.MouseSensor),
|
|
15229
|
+
core.useSensor(core.TouchSensor),
|
|
15230
|
+
core.useSensor(core.KeyboardSensor)
|
|
15231
|
+
);
|
|
15232
|
+
const handleDragStart = (event) => {
|
|
15233
|
+
const card = data.find((item) => item.id === event.active.id);
|
|
15234
|
+
if (card) {
|
|
15235
|
+
setActiveCardId(event.active.id);
|
|
15236
|
+
}
|
|
15237
|
+
onDragStart?.(event);
|
|
15238
|
+
};
|
|
15239
|
+
const handleDragOver = (event) => {
|
|
15240
|
+
const { active, over } = event;
|
|
15241
|
+
if (!over) {
|
|
15242
|
+
return;
|
|
15243
|
+
}
|
|
15244
|
+
const activeItem = data.find((item) => item.id === active.id);
|
|
15245
|
+
const overItem = data.find((item) => item.id === over.id);
|
|
15246
|
+
if (!activeItem) {
|
|
15247
|
+
return;
|
|
15248
|
+
}
|
|
15249
|
+
const activeColumn = activeItem.column;
|
|
15250
|
+
const overColumn = overItem?.column || columns.find((col) => col.id === over.id)?.id || columns[0]?.id;
|
|
15251
|
+
if (activeColumn !== overColumn) {
|
|
15252
|
+
let newData = [...data];
|
|
15253
|
+
const activeIndex = newData.findIndex((item) => item.id === active.id);
|
|
15254
|
+
const overIndex = newData.findIndex((item) => item.id === over.id);
|
|
15255
|
+
newData[activeIndex].column = overColumn;
|
|
15256
|
+
newData = sortable.arrayMove(newData, activeIndex, overIndex);
|
|
15257
|
+
onDataChange?.(newData);
|
|
15258
|
+
}
|
|
15259
|
+
onDragOver?.(event);
|
|
15260
|
+
};
|
|
15261
|
+
const handleDragEnd = (event) => {
|
|
15262
|
+
setActiveCardId(null);
|
|
15263
|
+
onDragEnd?.(event);
|
|
15264
|
+
const { active, over } = event;
|
|
15265
|
+
if (!over || active.id === over.id) {
|
|
15266
|
+
return;
|
|
15267
|
+
}
|
|
15268
|
+
let newData = [...data];
|
|
15269
|
+
const oldIndex = newData.findIndex((item) => item.id === active.id);
|
|
15270
|
+
const newIndex = newData.findIndex((item) => item.id === over.id);
|
|
15271
|
+
newData = sortable.arrayMove(newData, oldIndex, newIndex);
|
|
15272
|
+
onDataChange?.(newData);
|
|
15273
|
+
};
|
|
15274
|
+
const announcements = {
|
|
15275
|
+
onDragStart({ active }) {
|
|
15276
|
+
const { name, column } = data.find((item) => item.id === active.id) ?? {};
|
|
15277
|
+
return `Picked up the card "${name}" from the "${column}" column`;
|
|
15278
|
+
},
|
|
15279
|
+
onDragOver({ active, over }) {
|
|
15280
|
+
const { name } = data.find((item) => item.id === active.id) ?? {};
|
|
15281
|
+
const newColumn = columns.find((column) => column.id === over?.id)?.name;
|
|
15282
|
+
return `Dragged the card "${name}" over the "${newColumn}" column`;
|
|
15283
|
+
},
|
|
15284
|
+
onDragEnd({ active, over }) {
|
|
15285
|
+
const { name } = data.find((item) => item.id === active.id) ?? {};
|
|
15286
|
+
const newColumn = columns.find((column) => column.id === over?.id)?.name;
|
|
15287
|
+
return `Dropped the card "${name}" into the "${newColumn}" column`;
|
|
15288
|
+
},
|
|
15289
|
+
onDragCancel({ active }) {
|
|
15290
|
+
const { name } = data.find((item) => item.id === active.id) ?? {};
|
|
15291
|
+
return `Cancelled dragging the card "${name}"`;
|
|
15292
|
+
}
|
|
15293
|
+
};
|
|
15294
|
+
return /* @__PURE__ */ jsxRuntime.jsx(KanbanContext.Provider, { value: { columns, data, activeCardId }, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15295
|
+
core.DndContext,
|
|
15296
|
+
{
|
|
15297
|
+
accessibility: { announcements },
|
|
15298
|
+
collisionDetection: core.closestCenter,
|
|
15299
|
+
onDragEnd: handleDragEnd,
|
|
15300
|
+
onDragOver: handleDragOver,
|
|
15301
|
+
onDragStart: handleDragStart,
|
|
15302
|
+
sensors,
|
|
15303
|
+
...props,
|
|
15304
|
+
children: [
|
|
15305
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15306
|
+
"div",
|
|
15307
|
+
{
|
|
15308
|
+
className: cn(
|
|
15309
|
+
"grid size-full auto-cols-fr grid-flow-col gap-4",
|
|
15310
|
+
className
|
|
15311
|
+
),
|
|
15312
|
+
children: columns.map((column) => children(column))
|
|
15313
|
+
}
|
|
15314
|
+
),
|
|
15315
|
+
typeof window !== "undefined" && reactDom.createPortal(
|
|
15316
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.DragOverlay, { children: /* @__PURE__ */ jsxRuntime.jsx(t.Out, {}) }),
|
|
15317
|
+
document.body
|
|
15318
|
+
)
|
|
15319
|
+
]
|
|
15320
|
+
}
|
|
15321
|
+
) });
|
|
15322
|
+
};
|
|
13749
15323
|
|
|
13750
15324
|
Object.defineProperty(exports, "flexRender", {
|
|
13751
15325
|
enumerable: true,
|
|
@@ -13977,6 +15551,30 @@ exports.FormField = FormField;
|
|
|
13977
15551
|
exports.FormItem = FormItem;
|
|
13978
15552
|
exports.FormLabel = FormLabel;
|
|
13979
15553
|
exports.FormMessage = FormMessage;
|
|
15554
|
+
exports.GanttAddFeatureHelper = GanttAddFeatureHelper;
|
|
15555
|
+
exports.GanttCollapsibleSidebarGroup = GanttCollapsibleSidebarGroup;
|
|
15556
|
+
exports.GanttCollapsibleTimelineGroup = GanttCollapsibleTimelineGroup;
|
|
15557
|
+
exports.GanttColumn = GanttColumn;
|
|
15558
|
+
exports.GanttColumns = GanttColumns;
|
|
15559
|
+
exports.GanttContentHeader = GanttContentHeader;
|
|
15560
|
+
exports.GanttCreateMarkerTrigger = GanttCreateMarkerTrigger;
|
|
15561
|
+
exports.GanttFeatureDragHelper = GanttFeatureDragHelper;
|
|
15562
|
+
exports.GanttFeatureItem = GanttFeatureItem;
|
|
15563
|
+
exports.GanttFeatureItemCard = GanttFeatureItemCard;
|
|
15564
|
+
exports.GanttFeatureList = GanttFeatureList;
|
|
15565
|
+
exports.GanttFeatureListGroup = GanttFeatureListGroup;
|
|
15566
|
+
exports.GanttFeatureRow = GanttFeatureRow;
|
|
15567
|
+
exports.GanttGridLines = GanttGridLines;
|
|
15568
|
+
exports.GanttGroupSummaryBar = GanttGroupSummaryBar;
|
|
15569
|
+
exports.GanttHeader = GanttHeader;
|
|
15570
|
+
exports.GanttMarker = GanttMarker;
|
|
15571
|
+
exports.GanttProvider = GanttProvider;
|
|
15572
|
+
exports.GanttSidebar = GanttSidebar;
|
|
15573
|
+
exports.GanttSidebarGroup = GanttSidebarGroup;
|
|
15574
|
+
exports.GanttSidebarHeader = GanttSidebarHeader;
|
|
15575
|
+
exports.GanttSidebarItem = GanttSidebarItem;
|
|
15576
|
+
exports.GanttTimeline = GanttTimeline;
|
|
15577
|
+
exports.GanttToday = GanttToday;
|
|
13980
15578
|
exports.HoverCard = HoverCard;
|
|
13981
15579
|
exports.HoverCardContent = HoverCardContent;
|
|
13982
15580
|
exports.HoverCardTrigger = HoverCardTrigger;
|
|
@@ -13997,6 +15595,11 @@ exports.ItemHeader = ItemHeader;
|
|
|
13997
15595
|
exports.ItemMedia = ItemMedia;
|
|
13998
15596
|
exports.ItemSeparator = ItemSeparator;
|
|
13999
15597
|
exports.ItemTitle = ItemTitle;
|
|
15598
|
+
exports.KanbanBoard = KanbanBoard;
|
|
15599
|
+
exports.KanbanCard = KanbanCard;
|
|
15600
|
+
exports.KanbanCards = KanbanCards;
|
|
15601
|
+
exports.KanbanHeader = KanbanHeader;
|
|
15602
|
+
exports.KanbanProvider = KanbanProvider;
|
|
14000
15603
|
exports.Kbd = Kbd;
|
|
14001
15604
|
exports.KbdGroup = KbdGroup;
|
|
14002
15605
|
exports.Label = Label2;
|
|
@@ -14244,6 +15847,8 @@ exports.useEventCalendar = useEventCalendar;
|
|
|
14244
15847
|
exports.useEventsInRange = useEventsInRange;
|
|
14245
15848
|
exports.useFilteredEvents = useFilteredEvents;
|
|
14246
15849
|
exports.useFormField = useFormField;
|
|
15850
|
+
exports.useGanttDragging = useGanttDragging;
|
|
15851
|
+
exports.useGanttScrollX = useGanttScrollX;
|
|
14247
15852
|
exports.useIsMobile = useIsMobile;
|
|
14248
15853
|
exports.useSearchShortcut = useSearchShortcut;
|
|
14249
15854
|
exports.useSidebar = useSidebar;
|