@almadar/ui 6.26.0 → 6.27.0

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.
@@ -32193,6 +32193,247 @@ var init_WizardNavigation = __esm({
32193
32193
  WizardNavigation.displayName = "WizardNavigation";
32194
32194
  }
32195
32195
  });
32196
+ function parseDay(value) {
32197
+ if (value === void 0 || value === null || value === "") return null;
32198
+ const d = value instanceof Date ? new Date(value.getTime()) : new Date(value);
32199
+ if (Number.isNaN(d.getTime())) return null;
32200
+ d.setHours(0, 0, 0, 0);
32201
+ return d;
32202
+ }
32203
+ function Gantt({
32204
+ tasks = [],
32205
+ links = [],
32206
+ titleField = "title",
32207
+ startField = "start",
32208
+ endField = "end",
32209
+ durationField,
32210
+ statusField = "status",
32211
+ groupField = "",
32212
+ rangeStart,
32213
+ rangeEnd,
32214
+ showToday = true,
32215
+ dayWidth = 28,
32216
+ barClickEvent,
32217
+ className,
32218
+ isLoading = false,
32219
+ error = null
32220
+ }) {
32221
+ const { t } = useTranslate();
32222
+ const placed = useMemo(() => {
32223
+ const rows = Array.isArray(tasks) ? tasks : tasks ? [tasks] : [];
32224
+ const out = [];
32225
+ rows.forEach((row, idx) => {
32226
+ const start = parseDay(getNestedValue(row, startField));
32227
+ if (!start) return;
32228
+ let end = parseDay(getNestedValue(row, endField));
32229
+ if (!end && durationField) {
32230
+ const days2 = Number(getNestedValue(row, durationField));
32231
+ if (Number.isFinite(days2) && days2 > 0) {
32232
+ end = new Date(start.getTime() + days2 * DAY_MS);
32233
+ }
32234
+ }
32235
+ if (!end || end.getTime() < start.getTime()) end = new Date(start.getTime() + DAY_MS);
32236
+ out.push({
32237
+ row,
32238
+ id: String(row.id ?? idx),
32239
+ label: String(getNestedValue(row, titleField) ?? ""),
32240
+ status: String(getNestedValue(row, statusField) ?? "").toLowerCase(),
32241
+ group: groupField ? String(getNestedValue(row, groupField) ?? "") : "",
32242
+ start,
32243
+ end
32244
+ });
32245
+ });
32246
+ return out;
32247
+ }, [tasks, titleField, startField, endField, durationField, statusField, groupField]);
32248
+ const [axisStart, axisEnd] = useMemo(() => {
32249
+ const lo = parseDay(rangeStart) ?? (placed.length ? new Date(Math.min(...placed.map((p) => p.start.getTime())) - 2 * DAY_MS) : new Date((/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0)));
32250
+ const hi = parseDay(rangeEnd) ?? (placed.length ? new Date(Math.max(...placed.map((p) => p.end.getTime())) + 2 * DAY_MS) : new Date(lo.getTime() + 30 * DAY_MS));
32251
+ return hi.getTime() > lo.getTime() ? [lo, hi] : [lo, new Date(lo.getTime() + DAY_MS)];
32252
+ }, [rangeStart, rangeEnd, placed]);
32253
+ const totalDays = Math.round((axisEnd.getTime() - axisStart.getTime()) / DAY_MS);
32254
+ const chartWidth = totalDays * dayWidth;
32255
+ const dayOffset = (d) => (d.getTime() - axisStart.getTime()) / DAY_MS * dayWidth;
32256
+ const displayItems = useMemo(() => {
32257
+ if (!groupField) return placed.map((task) => ({ kind: "task", task }));
32258
+ const items = [];
32259
+ const seen = /* @__PURE__ */ new Set();
32260
+ for (const task of placed) {
32261
+ if (!seen.has(task.group)) {
32262
+ seen.add(task.group);
32263
+ items.push({ kind: "group", label: task.group || "\u2014" });
32264
+ }
32265
+ items.push({ kind: "task", task });
32266
+ }
32267
+ return items;
32268
+ }, [placed, groupField]);
32269
+ const barGeometry = useMemo(() => {
32270
+ const offset = (d) => (d.getTime() - axisStart.getTime()) / DAY_MS * dayWidth;
32271
+ const map = /* @__PURE__ */ new Map();
32272
+ displayItems.forEach((item, idx) => {
32273
+ if (item.kind !== "task") return;
32274
+ const x0 = offset(item.task.start);
32275
+ const x1 = Math.max(offset(item.task.end), x0 + dayWidth / 2);
32276
+ map.set(item.task.id, { x0, x1, y: HEADER_HEIGHT + idx * ROW_HEIGHT + ROW_HEIGHT / 2 });
32277
+ });
32278
+ return map;
32279
+ }, [displayItems, axisStart, dayWidth]);
32280
+ const days = useMemo(() => {
32281
+ const out = [];
32282
+ for (let i = 0; i < totalDays; i++) out.push(new Date(axisStart.getTime() + i * DAY_MS));
32283
+ return out;
32284
+ }, [axisStart, totalDays]);
32285
+ const todayOffset = useMemo(() => {
32286
+ const today = parseDay(/* @__PURE__ */ new Date());
32287
+ if (!today || today < axisStart || today > axisEnd) return null;
32288
+ return (today.getTime() - axisStart.getTime()) / DAY_MS * dayWidth;
32289
+ }, [axisStart, axisEnd, dayWidth]);
32290
+ if (isLoading) {
32291
+ return /* @__PURE__ */ jsx(LoadingState, { message: t("common.loading"), className });
32292
+ }
32293
+ if (error) {
32294
+ return /* @__PURE__ */ jsx(Box, { className: cn("p-4", className), children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "error", children: error.message }) });
32295
+ }
32296
+ if (placed.length === 0) {
32297
+ return /* @__PURE__ */ jsx(
32298
+ EmptyState,
32299
+ {
32300
+ title: t("empty.noData"),
32301
+ className
32302
+ }
32303
+ );
32304
+ }
32305
+ return /* @__PURE__ */ jsx(
32306
+ Box,
32307
+ {
32308
+ className: cn("w-full overflow-auto rounded-md border border-border bg-card", className),
32309
+ children: /* @__PURE__ */ jsxs(Box, { className: "relative", style: { width: LABEL_WIDTH + chartWidth, minWidth: "100%" }, children: [
32310
+ /* @__PURE__ */ jsxs(HStack, { gap: "none", className: "sticky top-0 z-20 bg-card border-b border-border", style: { height: HEADER_HEIGHT }, children: [
32311
+ /* @__PURE__ */ jsx(Box, { className: "sticky left-0 z-10 shrink-0 bg-card border-r border-border", style: { width: LABEL_WIDTH, height: HEADER_HEIGHT } }),
32312
+ /* @__PURE__ */ jsx(Box, { className: "relative", style: { width: chartWidth, height: HEADER_HEIGHT }, children: days.map((day, i) => /* @__PURE__ */ jsx(
32313
+ Box,
32314
+ {
32315
+ className: cn(
32316
+ "absolute top-0 bottom-0 border-l border-border/50 flex items-end justify-center pb-1",
32317
+ day.getDay() === 0 || day.getDay() === 6 ? "bg-muted/40" : void 0
32318
+ ),
32319
+ style: { left: i * dayWidth, width: dayWidth },
32320
+ children: dayWidth >= 20 && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: day.getDate() })
32321
+ },
32322
+ i
32323
+ )) })
32324
+ ] }),
32325
+ /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "relative", children: [
32326
+ displayItems.map(
32327
+ (item, idx) => item.kind === "group" ? /* @__PURE__ */ jsxs(
32328
+ HStack,
32329
+ {
32330
+ gap: "none",
32331
+ className: "border-b border-border bg-muted/30",
32332
+ style: { height: ROW_HEIGHT },
32333
+ children: [
32334
+ /* @__PURE__ */ jsx(Box, { className: "sticky left-0 z-10 shrink-0 bg-muted/30 px-3 flex items-center border-r border-border", style: { width: LABEL_WIDTH, height: ROW_HEIGHT }, children: /* @__PURE__ */ jsx(Typography, { variant: "caption", weight: "semibold", children: item.label }) }),
32335
+ /* @__PURE__ */ jsx(Box, { style: { width: chartWidth, height: ROW_HEIGHT } })
32336
+ ]
32337
+ },
32338
+ `g-${idx}`
32339
+ ) : /* @__PURE__ */ jsxs(
32340
+ HStack,
32341
+ {
32342
+ gap: "none",
32343
+ className: "border-b border-border/50",
32344
+ style: { height: ROW_HEIGHT },
32345
+ children: [
32346
+ /* @__PURE__ */ jsx(Box, { className: "sticky left-0 z-10 shrink-0 bg-card px-3 flex items-center border-r border-border", style: { width: LABEL_WIDTH, height: ROW_HEIGHT }, children: /* @__PURE__ */ jsx(Typography, { variant: "small", className: "truncate", children: item.task.label }) }),
32347
+ /* @__PURE__ */ jsx(Box, { className: "relative", style: { width: chartWidth, height: ROW_HEIGHT }, children: /* @__PURE__ */ jsx(
32348
+ Box,
32349
+ {
32350
+ className: cn(
32351
+ "absolute top-1/2 -translate-y-1/2 h-4 rounded-sm transition-colors",
32352
+ STATUS_BAR[item.task.status] ?? "bg-primary/80 hover:bg-primary",
32353
+ barClickEvent ? "cursor-pointer" : void 0
32354
+ ),
32355
+ style: {
32356
+ left: dayOffset(item.task.start),
32357
+ width: Math.max(dayOffset(item.task.end) - dayOffset(item.task.start), dayWidth / 2)
32358
+ },
32359
+ action: barClickEvent,
32360
+ actionPayload: { id: item.task.id }
32361
+ }
32362
+ ) })
32363
+ ]
32364
+ },
32365
+ item.task.id
32366
+ )
32367
+ ),
32368
+ links.length > 0 && /* @__PURE__ */ jsxs(
32369
+ "svg",
32370
+ {
32371
+ className: "absolute pointer-events-none",
32372
+ style: { left: LABEL_WIDTH, top: 0 },
32373
+ width: chartWidth,
32374
+ height: HEADER_HEIGHT + displayItems.length * ROW_HEIGHT,
32375
+ children: [
32376
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("marker", { id: "gantt-arrow", markerWidth: "8", markerHeight: "8", refX: "7", refY: "4", orient: "auto", children: /* @__PURE__ */ jsx("path", { d: "M0,0 L8,4 L0,8 z", fill: "var(--muted-foreground, currentColor)" }) }) }),
32377
+ links.map((link, i) => {
32378
+ const from = barGeometry.get(link.from);
32379
+ const to = barGeometry.get(link.to);
32380
+ if (!from || !to) return null;
32381
+ const midX = from.x1 + Math.max(8, (to.x0 - from.x1) / 2);
32382
+ return /* @__PURE__ */ jsx(
32383
+ "path",
32384
+ {
32385
+ d: `M ${from.x1} ${from.y} L ${midX} ${from.y} L ${midX} ${to.y} L ${to.x0} ${to.y}`,
32386
+ fill: "none",
32387
+ stroke: "var(--muted-foreground, currentColor)",
32388
+ strokeWidth: 1.5,
32389
+ markerEnd: "url(#gantt-arrow)"
32390
+ },
32391
+ i
32392
+ );
32393
+ })
32394
+ ]
32395
+ }
32396
+ ),
32397
+ showToday && todayOffset !== null && /* @__PURE__ */ jsx(
32398
+ Box,
32399
+ {
32400
+ className: "absolute top-0 bottom-0 w-0.5 bg-error/70 pointer-events-none",
32401
+ style: { left: LABEL_WIDTH + todayOffset }
32402
+ }
32403
+ )
32404
+ ] })
32405
+ ] })
32406
+ }
32407
+ );
32408
+ }
32409
+ var DAY_MS, ROW_HEIGHT, HEADER_HEIGHT, LABEL_WIDTH, STATUS_BAR;
32410
+ var init_Gantt = __esm({
32411
+ "components/core/molecules/Gantt.tsx"() {
32412
+ "use client";
32413
+ init_cn();
32414
+ init_getNestedValue();
32415
+ init_Box();
32416
+ init_Stack();
32417
+ init_Typography();
32418
+ init_LoadingState();
32419
+ init_EmptyState();
32420
+ DAY_MS = 24 * 60 * 60 * 1e3;
32421
+ ROW_HEIGHT = 36;
32422
+ HEADER_HEIGHT = 44;
32423
+ LABEL_WIDTH = 192;
32424
+ STATUS_BAR = {
32425
+ complete: "bg-success/80 hover:bg-success",
32426
+ done: "bg-success/80 hover:bg-success",
32427
+ active: "bg-primary/80 hover:bg-primary",
32428
+ "in-progress": "bg-primary/80 hover:bg-primary",
32429
+ blocked: "bg-error/80 hover:bg-error",
32430
+ error: "bg-error/80 hover:bg-error",
32431
+ "at-risk": "bg-warning/80 hover:bg-warning",
32432
+ pending: "bg-muted-foreground/50 hover:bg-muted-foreground/70"
32433
+ };
32434
+ Gantt.displayName = "Gantt";
32435
+ }
32436
+ });
32196
32437
  var RepeatableFormSection;
32197
32438
  var init_RepeatableFormSection = __esm({
32198
32439
  "components/core/molecules/RepeatableFormSection.tsx"() {
@@ -51740,6 +51981,7 @@ var init_component_registry_generated = __esm({
51740
51981
  init_GameIcon();
51741
51982
  init_GameMenu();
51742
51983
  init_GameShell();
51984
+ init_Gantt();
51743
51985
  init_GenericAppTemplate();
51744
51986
  init_GeometricPattern();
51745
51987
  init_GradientDivider();
@@ -52019,6 +52261,7 @@ var init_component_registry_generated = __esm({
52019
52261
  "GameIcon": GameIcon,
52020
52262
  "GameMenu": GameMenu,
52021
52263
  "GameShell": GameShell,
52264
+ "Gantt": Gantt,
52022
52265
  "GenericAppTemplate": GenericAppTemplate,
52023
52266
  "GeometricPattern": GeometricPattern,
52024
52267
  "GradientDivider": GradientDivider,
@@ -32045,6 +32045,247 @@ var init_WizardNavigation = __esm({
32045
32045
  WizardNavigation.displayName = "WizardNavigation";
32046
32046
  }
32047
32047
  });
32048
+ function parseDay(value) {
32049
+ if (value === void 0 || value === null || value === "") return null;
32050
+ const d = value instanceof Date ? new Date(value.getTime()) : new Date(value);
32051
+ if (Number.isNaN(d.getTime())) return null;
32052
+ d.setHours(0, 0, 0, 0);
32053
+ return d;
32054
+ }
32055
+ function Gantt({
32056
+ tasks = [],
32057
+ links = [],
32058
+ titleField = "title",
32059
+ startField = "start",
32060
+ endField = "end",
32061
+ durationField,
32062
+ statusField = "status",
32063
+ groupField = "",
32064
+ rangeStart,
32065
+ rangeEnd,
32066
+ showToday = true,
32067
+ dayWidth = 28,
32068
+ barClickEvent,
32069
+ className,
32070
+ isLoading = false,
32071
+ error = null
32072
+ }) {
32073
+ const { t } = hooks.useTranslate();
32074
+ const placed = React87.useMemo(() => {
32075
+ const rows = Array.isArray(tasks) ? tasks : tasks ? [tasks] : [];
32076
+ const out = [];
32077
+ rows.forEach((row, idx) => {
32078
+ const start = parseDay(core.getNestedValue(row, startField));
32079
+ if (!start) return;
32080
+ let end = parseDay(core.getNestedValue(row, endField));
32081
+ if (!end && durationField) {
32082
+ const days2 = Number(core.getNestedValue(row, durationField));
32083
+ if (Number.isFinite(days2) && days2 > 0) {
32084
+ end = new Date(start.getTime() + days2 * DAY_MS);
32085
+ }
32086
+ }
32087
+ if (!end || end.getTime() < start.getTime()) end = new Date(start.getTime() + DAY_MS);
32088
+ out.push({
32089
+ row,
32090
+ id: String(row.id ?? idx),
32091
+ label: String(core.getNestedValue(row, titleField) ?? ""),
32092
+ status: String(core.getNestedValue(row, statusField) ?? "").toLowerCase(),
32093
+ group: groupField ? String(core.getNestedValue(row, groupField) ?? "") : "",
32094
+ start,
32095
+ end
32096
+ });
32097
+ });
32098
+ return out;
32099
+ }, [tasks, titleField, startField, endField, durationField, statusField, groupField]);
32100
+ const [axisStart, axisEnd] = React87.useMemo(() => {
32101
+ const lo = parseDay(rangeStart) ?? (placed.length ? new Date(Math.min(...placed.map((p) => p.start.getTime())) - 2 * DAY_MS) : new Date((/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0)));
32102
+ const hi = parseDay(rangeEnd) ?? (placed.length ? new Date(Math.max(...placed.map((p) => p.end.getTime())) + 2 * DAY_MS) : new Date(lo.getTime() + 30 * DAY_MS));
32103
+ return hi.getTime() > lo.getTime() ? [lo, hi] : [lo, new Date(lo.getTime() + DAY_MS)];
32104
+ }, [rangeStart, rangeEnd, placed]);
32105
+ const totalDays = Math.round((axisEnd.getTime() - axisStart.getTime()) / DAY_MS);
32106
+ const chartWidth = totalDays * dayWidth;
32107
+ const dayOffset = (d) => (d.getTime() - axisStart.getTime()) / DAY_MS * dayWidth;
32108
+ const displayItems = React87.useMemo(() => {
32109
+ if (!groupField) return placed.map((task) => ({ kind: "task", task }));
32110
+ const items = [];
32111
+ const seen = /* @__PURE__ */ new Set();
32112
+ for (const task of placed) {
32113
+ if (!seen.has(task.group)) {
32114
+ seen.add(task.group);
32115
+ items.push({ kind: "group", label: task.group || "\u2014" });
32116
+ }
32117
+ items.push({ kind: "task", task });
32118
+ }
32119
+ return items;
32120
+ }, [placed, groupField]);
32121
+ const barGeometry = React87.useMemo(() => {
32122
+ const offset = (d) => (d.getTime() - axisStart.getTime()) / DAY_MS * dayWidth;
32123
+ const map = /* @__PURE__ */ new Map();
32124
+ displayItems.forEach((item, idx) => {
32125
+ if (item.kind !== "task") return;
32126
+ const x0 = offset(item.task.start);
32127
+ const x1 = Math.max(offset(item.task.end), x0 + dayWidth / 2);
32128
+ map.set(item.task.id, { x0, x1, y: HEADER_HEIGHT + idx * ROW_HEIGHT + ROW_HEIGHT / 2 });
32129
+ });
32130
+ return map;
32131
+ }, [displayItems, axisStart, dayWidth]);
32132
+ const days = React87.useMemo(() => {
32133
+ const out = [];
32134
+ for (let i = 0; i < totalDays; i++) out.push(new Date(axisStart.getTime() + i * DAY_MS));
32135
+ return out;
32136
+ }, [axisStart, totalDays]);
32137
+ const todayOffset = React87.useMemo(() => {
32138
+ const today = parseDay(/* @__PURE__ */ new Date());
32139
+ if (!today || today < axisStart || today > axisEnd) return null;
32140
+ return (today.getTime() - axisStart.getTime()) / DAY_MS * dayWidth;
32141
+ }, [axisStart, axisEnd, dayWidth]);
32142
+ if (isLoading) {
32143
+ return /* @__PURE__ */ jsxRuntime.jsx(LoadingState, { message: t("common.loading"), className });
32144
+ }
32145
+ if (error) {
32146
+ return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("p-4", className), children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "error", children: error.message }) });
32147
+ }
32148
+ if (placed.length === 0) {
32149
+ return /* @__PURE__ */ jsxRuntime.jsx(
32150
+ EmptyState,
32151
+ {
32152
+ title: t("empty.noData"),
32153
+ className
32154
+ }
32155
+ );
32156
+ }
32157
+ return /* @__PURE__ */ jsxRuntime.jsx(
32158
+ Box,
32159
+ {
32160
+ className: cn("w-full overflow-auto rounded-md border border-border bg-card", className),
32161
+ children: /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "relative", style: { width: LABEL_WIDTH + chartWidth, minWidth: "100%" }, children: [
32162
+ /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "none", className: "sticky top-0 z-20 bg-card border-b border-border", style: { height: HEADER_HEIGHT }, children: [
32163
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "sticky left-0 z-10 shrink-0 bg-card border-r border-border", style: { width: LABEL_WIDTH, height: HEADER_HEIGHT } }),
32164
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "relative", style: { width: chartWidth, height: HEADER_HEIGHT }, children: days.map((day, i) => /* @__PURE__ */ jsxRuntime.jsx(
32165
+ Box,
32166
+ {
32167
+ className: cn(
32168
+ "absolute top-0 bottom-0 border-l border-border/50 flex items-end justify-center pb-1",
32169
+ day.getDay() === 0 || day.getDay() === 6 ? "bg-muted/40" : void 0
32170
+ ),
32171
+ style: { left: i * dayWidth, width: dayWidth },
32172
+ children: dayWidth >= 20 && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: day.getDate() })
32173
+ },
32174
+ i
32175
+ )) })
32176
+ ] }),
32177
+ /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", className: "relative", children: [
32178
+ displayItems.map(
32179
+ (item, idx) => item.kind === "group" ? /* @__PURE__ */ jsxRuntime.jsxs(
32180
+ HStack,
32181
+ {
32182
+ gap: "none",
32183
+ className: "border-b border-border bg-muted/30",
32184
+ style: { height: ROW_HEIGHT },
32185
+ children: [
32186
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "sticky left-0 z-10 shrink-0 bg-muted/30 px-3 flex items-center border-r border-border", style: { width: LABEL_WIDTH, height: ROW_HEIGHT }, children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", weight: "semibold", children: item.label }) }),
32187
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { style: { width: chartWidth, height: ROW_HEIGHT } })
32188
+ ]
32189
+ },
32190
+ `g-${idx}`
32191
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
32192
+ HStack,
32193
+ {
32194
+ gap: "none",
32195
+ className: "border-b border-border/50",
32196
+ style: { height: ROW_HEIGHT },
32197
+ children: [
32198
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "sticky left-0 z-10 shrink-0 bg-card px-3 flex items-center border-r border-border", style: { width: LABEL_WIDTH, height: ROW_HEIGHT }, children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", className: "truncate", children: item.task.label }) }),
32199
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "relative", style: { width: chartWidth, height: ROW_HEIGHT }, children: /* @__PURE__ */ jsxRuntime.jsx(
32200
+ Box,
32201
+ {
32202
+ className: cn(
32203
+ "absolute top-1/2 -translate-y-1/2 h-4 rounded-sm transition-colors",
32204
+ STATUS_BAR[item.task.status] ?? "bg-primary/80 hover:bg-primary",
32205
+ barClickEvent ? "cursor-pointer" : void 0
32206
+ ),
32207
+ style: {
32208
+ left: dayOffset(item.task.start),
32209
+ width: Math.max(dayOffset(item.task.end) - dayOffset(item.task.start), dayWidth / 2)
32210
+ },
32211
+ action: barClickEvent,
32212
+ actionPayload: { id: item.task.id }
32213
+ }
32214
+ ) })
32215
+ ]
32216
+ },
32217
+ item.task.id
32218
+ )
32219
+ ),
32220
+ links.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
32221
+ "svg",
32222
+ {
32223
+ className: "absolute pointer-events-none",
32224
+ style: { left: LABEL_WIDTH, top: 0 },
32225
+ width: chartWidth,
32226
+ height: HEADER_HEIGHT + displayItems.length * ROW_HEIGHT,
32227
+ children: [
32228
+ /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx("marker", { id: "gantt-arrow", markerWidth: "8", markerHeight: "8", refX: "7", refY: "4", orient: "auto", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M0,0 L8,4 L0,8 z", fill: "var(--muted-foreground, currentColor)" }) }) }),
32229
+ links.map((link, i) => {
32230
+ const from = barGeometry.get(link.from);
32231
+ const to = barGeometry.get(link.to);
32232
+ if (!from || !to) return null;
32233
+ const midX = from.x1 + Math.max(8, (to.x0 - from.x1) / 2);
32234
+ return /* @__PURE__ */ jsxRuntime.jsx(
32235
+ "path",
32236
+ {
32237
+ d: `M ${from.x1} ${from.y} L ${midX} ${from.y} L ${midX} ${to.y} L ${to.x0} ${to.y}`,
32238
+ fill: "none",
32239
+ stroke: "var(--muted-foreground, currentColor)",
32240
+ strokeWidth: 1.5,
32241
+ markerEnd: "url(#gantt-arrow)"
32242
+ },
32243
+ i
32244
+ );
32245
+ })
32246
+ ]
32247
+ }
32248
+ ),
32249
+ showToday && todayOffset !== null && /* @__PURE__ */ jsxRuntime.jsx(
32250
+ Box,
32251
+ {
32252
+ className: "absolute top-0 bottom-0 w-0.5 bg-error/70 pointer-events-none",
32253
+ style: { left: LABEL_WIDTH + todayOffset }
32254
+ }
32255
+ )
32256
+ ] })
32257
+ ] })
32258
+ }
32259
+ );
32260
+ }
32261
+ var DAY_MS, ROW_HEIGHT, HEADER_HEIGHT, LABEL_WIDTH, STATUS_BAR;
32262
+ var init_Gantt = __esm({
32263
+ "components/core/molecules/Gantt.tsx"() {
32264
+ "use client";
32265
+ init_cn();
32266
+ init_getNestedValue();
32267
+ init_Box();
32268
+ init_Stack();
32269
+ init_Typography();
32270
+ init_LoadingState();
32271
+ init_EmptyState();
32272
+ DAY_MS = 24 * 60 * 60 * 1e3;
32273
+ ROW_HEIGHT = 36;
32274
+ HEADER_HEIGHT = 44;
32275
+ LABEL_WIDTH = 192;
32276
+ STATUS_BAR = {
32277
+ complete: "bg-success/80 hover:bg-success",
32278
+ done: "bg-success/80 hover:bg-success",
32279
+ active: "bg-primary/80 hover:bg-primary",
32280
+ "in-progress": "bg-primary/80 hover:bg-primary",
32281
+ blocked: "bg-error/80 hover:bg-error",
32282
+ error: "bg-error/80 hover:bg-error",
32283
+ "at-risk": "bg-warning/80 hover:bg-warning",
32284
+ pending: "bg-muted-foreground/50 hover:bg-muted-foreground/70"
32285
+ };
32286
+ Gantt.displayName = "Gantt";
32287
+ }
32288
+ });
32048
32289
  var RepeatableFormSection;
32049
32290
  var init_RepeatableFormSection = __esm({
32050
32291
  "components/core/molecules/RepeatableFormSection.tsx"() {
@@ -51473,6 +51714,7 @@ var init_component_registry_generated = __esm({
51473
51714
  init_GameIcon();
51474
51715
  init_GameMenu();
51475
51716
  init_GameShell();
51717
+ init_Gantt();
51476
51718
  init_GenericAppTemplate();
51477
51719
  init_GeometricPattern();
51478
51720
  init_GradientDivider();
@@ -51752,6 +51994,7 @@ var init_component_registry_generated = __esm({
51752
51994
  "GameIcon": GameIcon,
51753
51995
  "GameMenu": GameMenu,
51754
51996
  "GameShell": GameShell,
51997
+ "Gantt": Gantt,
51755
51998
  "GenericAppTemplate": GenericAppTemplate,
51756
51999
  "GeometricPattern": GeometricPattern,
51757
52000
  "GradientDivider": GradientDivider,