hs-uix 2.1.0 → 2.2.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.
- package/README.md +3 -1
- package/common-components.d.ts +319 -68
- package/dist/calendar.js +397 -119
- package/dist/calendar.mjs +399 -119
- package/dist/common-components.js +3546 -88
- package/dist/common-components.mjs +3530 -84
- package/dist/datatable.js +108 -18
- package/dist/datatable.mjs +108 -18
- package/dist/experimental.js +2876 -0
- package/dist/experimental.mjs +2883 -0
- package/dist/feed.js +267 -38
- package/dist/feed.mjs +260 -37
- package/dist/filter.js +1379 -0
- package/dist/filter.mjs +1334 -0
- package/dist/form.js +222 -26
- package/dist/form.mjs +227 -27
- package/dist/index.js +3255 -353
- package/dist/index.mjs +3199 -344
- package/dist/kanban.js +282 -62
- package/dist/kanban.mjs +273 -61
- package/dist/safe.js +9207 -0
- package/dist/safe.mjs +9298 -0
- package/dist/utils.js +491 -75
- package/dist/utils.mjs +491 -75
- package/experimental.d.ts +1 -0
- package/filter.d.ts +1 -0
- package/index.d.ts +45 -3
- package/package.json +19 -1
- package/safe.d.ts +1 -0
- package/src/calendar/README.md +76 -5
- package/src/calendar/index.d.ts +108 -1
- package/src/common-components/README.md +140 -1
- package/src/datatable/README.md +0 -2
- package/src/experimental/README.md +126 -0
- package/src/experimental/index.d.ts +346 -0
- package/src/feed/README.md +69 -0
- package/src/feed/index.d.ts +103 -0
- package/src/filter/README.md +148 -0
- package/src/filter/index.d.ts +221 -0
- package/src/form/README.md +132 -4
- package/src/form/index.d.ts +82 -1
- package/src/kanban/README.md +119 -6
- package/src/kanban/index.d.ts +153 -2
- package/src/safe/README.md +108 -0
- package/src/safe/index.d.ts +158 -0
- package/src/utils/README.md +39 -0
- package/src/wizard/README.md +158 -0
- package/src/wizard/index.d.ts +138 -0
- package/utils.d.ts +17 -0
package/dist/calendar.mjs
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
import React5, { useCallback, useEffect, useMemo, useState as useState2 } from "react";
|
|
3
3
|
import {
|
|
4
4
|
Alert,
|
|
5
|
+
AutoGrid,
|
|
5
6
|
Box as Box2,
|
|
6
7
|
Button as Button3,
|
|
8
|
+
DateInput as DateInput2,
|
|
7
9
|
Divider,
|
|
8
10
|
EmptyState,
|
|
9
11
|
Flex as Flex4,
|
|
@@ -91,7 +93,6 @@ import React2 from "react";
|
|
|
91
93
|
import { Image, Icon as HsIcon, Link } from "@hubspot/ui-extensions";
|
|
92
94
|
|
|
93
95
|
// src/common-components/svgDefaults.js
|
|
94
|
-
var HS_FONT_FAMILY = '"Lexend Deca", Helvetica, Arial, sans-serif';
|
|
95
96
|
var HS_TEXT_COLOR = "#33475b";
|
|
96
97
|
|
|
97
98
|
// src/common-components/icons.generated.js
|
|
@@ -346,7 +347,7 @@ var GENERATED_ICONS = {
|
|
|
346
347
|
"ZoomOut": { "viewBox": "0 0 32 32", "paths": ["M14.42 26.75c2.85 0 5.47-.97 7.56-2.6l-.03.02 5.28 5.34a1.619 1.619 0 0 0 2.76-1.15c0-.45-.18-.85-.47-1.14l-5.33-5.33c1.59-2.06 2.55-4.68 2.55-7.52C26.74 7.54 21.2 2 14.37 2S2 7.55 2 14.38s5.54 12.37 12.37 12.37h.05m0-21.55c5.06 0 9.16 4.1 9.16 9.16s-4.1 9.16-9.16 9.16-9.16-4.1-9.16-9.16c.01-5.05 4.11-9.14 9.16-9.15Zm-4.31 10.78h8.62c.89 0 1.62-.72 1.62-1.62s-.72-1.62-1.62-1.62h-8.62c-.89 0-1.62.72-1.62 1.62s.72 1.62 1.62 1.62"] }
|
|
347
348
|
};
|
|
348
349
|
|
|
349
|
-
// src/common-components/
|
|
350
|
+
// src/common-components/nativeIconNames.js
|
|
350
351
|
var NATIVE_ICON_NAMES = /* @__PURE__ */ new Set([
|
|
351
352
|
"add",
|
|
352
353
|
"appointment",
|
|
@@ -358,12 +359,12 @@ var NATIVE_ICON_NAMES = /* @__PURE__ */ new Set([
|
|
|
358
359
|
"block",
|
|
359
360
|
"book",
|
|
360
361
|
"bulb",
|
|
362
|
+
"callTranscript",
|
|
361
363
|
"calling",
|
|
362
364
|
"callingHangup",
|
|
363
365
|
"callingMade",
|
|
364
366
|
"callingMissed",
|
|
365
367
|
"callingVoicemail",
|
|
366
|
-
"callTranscript",
|
|
367
368
|
"campaigns",
|
|
368
369
|
"cap",
|
|
369
370
|
"checkCircle",
|
|
@@ -392,13 +393,13 @@ var NATIVE_ICON_NAMES = /* @__PURE__ */ new Set([
|
|
|
392
393
|
"enroll",
|
|
393
394
|
"exclamation",
|
|
394
395
|
"exclamationCircle",
|
|
395
|
-
"facebook",
|
|
396
396
|
"faceHappy",
|
|
397
397
|
"faceHappyFilled",
|
|
398
398
|
"faceNeutral",
|
|
399
399
|
"faceNeutralFilled",
|
|
400
400
|
"faceSad",
|
|
401
401
|
"faceSadFilled",
|
|
402
|
+
"facebook",
|
|
402
403
|
"favoriteHollow",
|
|
403
404
|
"file",
|
|
404
405
|
"filledXCircleIcon",
|
|
@@ -539,6 +540,8 @@ var NATIVE_ICON_NAMES = /* @__PURE__ */ new Set([
|
|
|
539
540
|
"zoomIn",
|
|
540
541
|
"zoomOut"
|
|
541
542
|
]);
|
|
543
|
+
|
|
544
|
+
// src/common-components/Icon.js
|
|
542
545
|
var NATIVE_COLORS = /* @__PURE__ */ new Set(["inherit", "alert", "warning", "success"]);
|
|
543
546
|
var NATIVE_SIZE_TOKENS = {
|
|
544
547
|
sm: "sm",
|
|
@@ -751,6 +754,7 @@ var CollectionFilterControl = ({
|
|
|
751
754
|
{ key: name, direction: "row", align: "center", gap: "xs" },
|
|
752
755
|
h2(DateInput, {
|
|
753
756
|
name: `${controlName}-from`,
|
|
757
|
+
label: filter.fromLabel ?? labels.dateFrom,
|
|
754
758
|
placeholder: filter.fromLabel ?? labels.dateFrom,
|
|
755
759
|
format: "medium",
|
|
756
760
|
value: rangeValue.from ?? null,
|
|
@@ -759,6 +763,7 @@ var CollectionFilterControl = ({
|
|
|
759
763
|
h2(Icon, { name: "right", size: "sm" }),
|
|
760
764
|
h2(DateInput, {
|
|
761
765
|
name: `${controlName}-to`,
|
|
766
|
+
label: filter.toLabel ?? labels.dateTo,
|
|
762
767
|
placeholder: filter.toLabel ?? labels.dateTo,
|
|
763
768
|
format: "medium",
|
|
764
769
|
value: rangeValue.to ?? null,
|
|
@@ -1213,21 +1218,6 @@ var formatTimeZoneLabel = (tz, atDate = /* @__PURE__ */ new Date()) => {
|
|
|
1213
1218
|
|
|
1214
1219
|
// src/calendar/svgChips.js
|
|
1215
1220
|
var toDataUri = (svg) => `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
|
1216
|
-
var escapeXml = (s) => String(s == null ? "" : s).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
1217
|
-
var truncateLabel = (value, max) => {
|
|
1218
|
-
const s = String(value == null ? "" : value);
|
|
1219
|
-
if (!max || s.length <= max) return s;
|
|
1220
|
-
return s.slice(0, Math.max(1, max - 1)).trimEnd() + "\u2026";
|
|
1221
|
-
};
|
|
1222
|
-
var CHIP_PALETTE = {
|
|
1223
|
-
default: { fill: "#7FD1DE", text: HS_TEXT_COLOR },
|
|
1224
|
-
info: { fill: "#00A4BD", text: "#FFFFFF" },
|
|
1225
|
-
success: { fill: "#00BDA5", text: "#FFFFFF" },
|
|
1226
|
-
warning: { fill: "#F5C26B", text: HS_TEXT_COLOR },
|
|
1227
|
-
error: { fill: "#F2545B", text: "#FFFFFF" },
|
|
1228
|
-
danger: { fill: "#F2545B", text: "#FFFFFF" }
|
|
1229
|
-
// StatusTag spells red "danger"; accept both
|
|
1230
|
-
};
|
|
1231
1221
|
var DOT_FILL = {
|
|
1232
1222
|
default: "#7C98B6",
|
|
1233
1223
|
info: "#00A4BD",
|
|
@@ -1242,31 +1232,177 @@ var makeDotDataUri = (variant = "default", size = 8) => {
|
|
|
1242
1232
|
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 ${size} ${size}"><circle cx="${r}" cy="${r}" r="${r}" fill="${fill}" /></svg>`;
|
|
1243
1233
|
return { src: toDataUri(svg), width: size, height: size };
|
|
1244
1234
|
};
|
|
1245
|
-
var makeEventChipDataUri = (opts) => {
|
|
1246
|
-
const { label, width, height = 24, variant = "default" } = opts;
|
|
1247
|
-
const palette = CHIP_PALETTE[variant] || CHIP_PALETTE.default;
|
|
1248
|
-
const accentX = 5;
|
|
1249
|
-
const accentW = 3;
|
|
1250
|
-
const textX = accentX + accentW + 6;
|
|
1251
|
-
const rightPad = 8;
|
|
1252
|
-
const maxChars = Math.max(1, Math.floor((width - textX - rightPad) / 6));
|
|
1253
|
-
const text = truncateLabel(label, maxChars);
|
|
1254
|
-
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}"><rect x="0.5" y="0.5" width="${width - 1}" height="${height - 1}" rx="4" ry="4" fill="#FFFFFF" stroke="#CBD6E2" stroke-width="1" /><rect x="${accentX}" y="5" width="${accentW}" height="${height - 10}" rx="1.5" ry="1.5" fill="${palette.fill}" /><text x="${textX}" y="${height / 2}" font-family='${HS_FONT_FAMILY}' font-size="12" font-weight="500" fill="${HS_TEXT_COLOR}" text-anchor="start" dominant-baseline="central">${escapeXml(text)}</text></svg>`;
|
|
1255
|
-
return { src: toDataUri(svg), width, height };
|
|
1256
|
-
};
|
|
1257
|
-
var makeMoreDataUri = (opts) => {
|
|
1258
|
-
const { label, width, height = 24 } = opts;
|
|
1259
|
-
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}"><text x="3" y="${height / 2}" font-family='${HS_FONT_FAMILY}' font-size="13" font-weight="700" fill="#0091AE" text-anchor="start" dominant-baseline="central">${escapeXml(label)}</text></svg>`;
|
|
1260
|
-
return { src: toDataUri(svg), width, height };
|
|
1261
|
-
};
|
|
1262
1235
|
var makeSpacerDataUri = (height = 24, width = 4) => {
|
|
1263
1236
|
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}"><rect x="0" y="0" width="${width}" height="${height}" fill="#FFFFFF" fill-opacity="0" /></svg>`;
|
|
1264
1237
|
return { src: toDataUri(svg), width, height };
|
|
1265
1238
|
};
|
|
1266
1239
|
|
|
1240
|
+
// src/calendar/rescheduleUtils.js
|
|
1241
|
+
var shiftDate = (date, shift) => {
|
|
1242
|
+
const d = toDate(date);
|
|
1243
|
+
if (!d) return null;
|
|
1244
|
+
if (!shift || typeof shift !== "object") return new Date(d);
|
|
1245
|
+
const days = (shift.days || 0) + (shift.weeks || 0) * 7;
|
|
1246
|
+
let next = days ? addDays(d, days) : new Date(d);
|
|
1247
|
+
const ms = (shift.hours || 0) * 36e5 + (shift.minutes || 0) * 6e4;
|
|
1248
|
+
if (ms) next = new Date(next.getTime() + ms);
|
|
1249
|
+
return next;
|
|
1250
|
+
};
|
|
1251
|
+
var shiftEvent = (range, shift) => {
|
|
1252
|
+
const start = toDate(range && range.start);
|
|
1253
|
+
if (!start) return null;
|
|
1254
|
+
const end = toDate(range && range.end) || start;
|
|
1255
|
+
return { start: shiftDate(start, shift), end: shiftDate(end, shift) };
|
|
1256
|
+
};
|
|
1257
|
+
var calendarDayDelta = (a, b) => Math.round((startOfDay(b).getTime() - startOfDay(a).getTime()) / MS_PER_DAY);
|
|
1258
|
+
var msIntoDay = (d) => ((d.getHours() * 60 + d.getMinutes()) * 60 + d.getSeconds()) * 1e3 + d.getMilliseconds();
|
|
1259
|
+
var rescheduleToStart = (range, newStart) => {
|
|
1260
|
+
const start = toDate(range && range.start);
|
|
1261
|
+
const target = toDate(newStart);
|
|
1262
|
+
if (!start || !target) return null;
|
|
1263
|
+
const end = toDate(range && range.end) || start;
|
|
1264
|
+
const dayDelta = calendarDayDelta(start, target);
|
|
1265
|
+
const timeDelta = msIntoDay(target) - msIntoDay(start);
|
|
1266
|
+
const endOnDay = addDays(end, dayDelta);
|
|
1267
|
+
if (!timeDelta) return { start: target, end: endOnDay };
|
|
1268
|
+
return {
|
|
1269
|
+
start: target,
|
|
1270
|
+
end: new Date(
|
|
1271
|
+
endOnDay.getFullYear(),
|
|
1272
|
+
endOnDay.getMonth(),
|
|
1273
|
+
endOnDay.getDate(),
|
|
1274
|
+
0,
|
|
1275
|
+
0,
|
|
1276
|
+
0,
|
|
1277
|
+
msIntoDay(endOnDay) + timeDelta
|
|
1278
|
+
)
|
|
1279
|
+
};
|
|
1280
|
+
};
|
|
1281
|
+
var applyDatePick = (start, value) => {
|
|
1282
|
+
if (!isDateValueObject(value)) return null;
|
|
1283
|
+
const s = toDate(start);
|
|
1284
|
+
return new Date(
|
|
1285
|
+
value.year,
|
|
1286
|
+
value.month,
|
|
1287
|
+
value.date,
|
|
1288
|
+
s ? s.getHours() : 0,
|
|
1289
|
+
s ? s.getMinutes() : 0,
|
|
1290
|
+
s ? s.getSeconds() : 0,
|
|
1291
|
+
s ? s.getMilliseconds() : 0
|
|
1292
|
+
);
|
|
1293
|
+
};
|
|
1294
|
+
var DEFAULT_RESCHEDULE_PRESETS = [
|
|
1295
|
+
{ label: "+1 hour", shift: { hours: 1 } },
|
|
1296
|
+
{ label: "+1 day", shift: { days: 1 } },
|
|
1297
|
+
{ label: "Next week", shift: { weeks: 1 } }
|
|
1298
|
+
];
|
|
1299
|
+
var normalizeRescheduleOptions = (options) => {
|
|
1300
|
+
if (!options) return [];
|
|
1301
|
+
if (options === true) return DEFAULT_RESCHEDULE_PRESETS;
|
|
1302
|
+
if (!Array.isArray(options)) return [];
|
|
1303
|
+
const out = [];
|
|
1304
|
+
for (const opt of options) {
|
|
1305
|
+
if (typeof opt === "function") {
|
|
1306
|
+
out.push({ label: opt.label || opt.name || "Reschedule", getStart: opt });
|
|
1307
|
+
} else if (opt && typeof opt === "object" && opt.label != null) {
|
|
1308
|
+
if (typeof opt.shift === "function") {
|
|
1309
|
+
out.push({ label: opt.label, getStart: opt.shift });
|
|
1310
|
+
} else if (typeof opt.getStart === "function") {
|
|
1311
|
+
out.push({ label: opt.label, getStart: opt.getStart });
|
|
1312
|
+
} else if (opt.shift && typeof opt.shift === "object") {
|
|
1313
|
+
out.push({ label: opt.label, shift: opt.shift });
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
return out;
|
|
1318
|
+
};
|
|
1319
|
+
var resolveRescheduleTarget = (range, option, fnArg) => {
|
|
1320
|
+
if (!range || !toDate(range.start) || !option) return null;
|
|
1321
|
+
if (typeof option.getStart === "function") {
|
|
1322
|
+
const next = toDate(option.getStart(fnArg !== void 0 ? fnArg : range));
|
|
1323
|
+
return next ? rescheduleToStart(range, next) : null;
|
|
1324
|
+
}
|
|
1325
|
+
if (option.shift && typeof option.shift === "object") {
|
|
1326
|
+
return shiftEvent(range, option.shift);
|
|
1327
|
+
}
|
|
1328
|
+
return null;
|
|
1329
|
+
};
|
|
1330
|
+
|
|
1331
|
+
// src/calendar/resourceLanes.js
|
|
1332
|
+
var resolveResourceId = (record, spec) => {
|
|
1333
|
+
if (record == null || spec == null) return null;
|
|
1334
|
+
const value = typeof spec === "function" ? spec(record) : record[spec];
|
|
1335
|
+
if (value == null || value === "") return null;
|
|
1336
|
+
return value;
|
|
1337
|
+
};
|
|
1338
|
+
var buildResourceLanes = (events, options = {}) => {
|
|
1339
|
+
const {
|
|
1340
|
+
resources,
|
|
1341
|
+
resourceLabels,
|
|
1342
|
+
getId,
|
|
1343
|
+
showUnassignedLane = true,
|
|
1344
|
+
unassignedLabel = "Unassigned"
|
|
1345
|
+
} = options;
|
|
1346
|
+
const labelFor = (id) => {
|
|
1347
|
+
if (resourceLabels && resourceLabels[id] != null) return resourceLabels[id];
|
|
1348
|
+
return String(id);
|
|
1349
|
+
};
|
|
1350
|
+
const lanes = [];
|
|
1351
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
1352
|
+
const addLane = (id, label, declared) => {
|
|
1353
|
+
const key = String(id);
|
|
1354
|
+
if (byKey.has(key)) return byKey.get(key);
|
|
1355
|
+
const lane = { id, key, label, events: [], unassigned: false, declared };
|
|
1356
|
+
byKey.set(key, lane);
|
|
1357
|
+
lanes.push(lane);
|
|
1358
|
+
return lane;
|
|
1359
|
+
};
|
|
1360
|
+
(resources || []).forEach((resource) => {
|
|
1361
|
+
if (resource == null) return;
|
|
1362
|
+
if (typeof resource === "object") {
|
|
1363
|
+
addLane(resource.id, resource.label != null ? resource.label : labelFor(resource.id), true);
|
|
1364
|
+
} else {
|
|
1365
|
+
addLane(resource, labelFor(resource), true);
|
|
1366
|
+
}
|
|
1367
|
+
});
|
|
1368
|
+
const unassigned = {
|
|
1369
|
+
id: null,
|
|
1370
|
+
key: "__unassigned__",
|
|
1371
|
+
label: unassignedLabel,
|
|
1372
|
+
events: [],
|
|
1373
|
+
unassigned: true,
|
|
1374
|
+
declared: false
|
|
1375
|
+
};
|
|
1376
|
+
(events || []).forEach((event) => {
|
|
1377
|
+
const id = getId ? getId(event) : null;
|
|
1378
|
+
if (id == null || id === "") {
|
|
1379
|
+
unassigned.events.push(event);
|
|
1380
|
+
return;
|
|
1381
|
+
}
|
|
1382
|
+
const lane = byKey.get(String(id)) || addLane(id, labelFor(id), false);
|
|
1383
|
+
lane.events.push(event);
|
|
1384
|
+
});
|
|
1385
|
+
if (showUnassignedLane && unassigned.events.length > 0) lanes.push(unassigned);
|
|
1386
|
+
return lanes;
|
|
1387
|
+
};
|
|
1388
|
+
var eventsIntersectingRange = (events, rangeStart, rangeEnd) => {
|
|
1389
|
+
const rs = rangeStart.getTime();
|
|
1390
|
+
const re = rangeEnd.getTime();
|
|
1391
|
+
return (events || []).filter((event) => {
|
|
1392
|
+
if (!event || !event.start) return false;
|
|
1393
|
+
const es = event.start.getTime();
|
|
1394
|
+
const ee = (event.end || event.start).getTime();
|
|
1395
|
+
return es <= re && ee >= rs;
|
|
1396
|
+
});
|
|
1397
|
+
};
|
|
1398
|
+
var laneEventsForDay = (events, day) => eventsIntersectingRange(events, startOfDay(day), endOfDay(day)).sort(
|
|
1399
|
+
(a, b) => a.start.getTime() - b.start.getTime()
|
|
1400
|
+
);
|
|
1401
|
+
|
|
1267
1402
|
// src/calendar/Calendar.jsx
|
|
1268
1403
|
var DEFAULT_MAX_EVENTS_PER_DAY = 3;
|
|
1269
1404
|
var ALL_VIEWS = ["month", "week", "day", "agenda"];
|
|
1405
|
+
var ALL_VIEWS_WITH_RESOURCE = ["month", "week", "day", "resource", "agenda"];
|
|
1270
1406
|
var DEFAULT_DAY_START_HOUR = 8;
|
|
1271
1407
|
var DEFAULT_DAY_END_HOUR = 20;
|
|
1272
1408
|
var DEFAULT_TIME_ZONES = [
|
|
@@ -1302,7 +1438,8 @@ var VIEW_LABELS = {
|
|
|
1302
1438
|
month: "Month",
|
|
1303
1439
|
week: "Week",
|
|
1304
1440
|
day: "Day",
|
|
1305
|
-
agenda: "Agenda"
|
|
1441
|
+
agenda: "Agenda",
|
|
1442
|
+
resource: "Resource"
|
|
1306
1443
|
};
|
|
1307
1444
|
var DEFAULT_LABELS3 = {
|
|
1308
1445
|
today: "Today",
|
|
@@ -1319,7 +1456,11 @@ var DEFAULT_LABELS3 = {
|
|
|
1319
1456
|
errorMessage: "An error occurred while loading events.",
|
|
1320
1457
|
dayDetailTitle: (label) => label,
|
|
1321
1458
|
open: "Open",
|
|
1322
|
-
allDay: "All day"
|
|
1459
|
+
allDay: "All day",
|
|
1460
|
+
reschedule: "Reschedule",
|
|
1461
|
+
pickDate: "Pick date",
|
|
1462
|
+
unassigned: "Unassigned",
|
|
1463
|
+
resource: "Resource"
|
|
1323
1464
|
};
|
|
1324
1465
|
var DEFAULT_EVENT_FIELDS = {
|
|
1325
1466
|
id: "id",
|
|
@@ -1354,11 +1495,30 @@ var STATUS_VARIANT = {
|
|
|
1354
1495
|
error: "danger",
|
|
1355
1496
|
danger: "danger"
|
|
1356
1497
|
};
|
|
1498
|
+
var TAG_VARIANT = {
|
|
1499
|
+
default: "default",
|
|
1500
|
+
info: "info",
|
|
1501
|
+
success: "success",
|
|
1502
|
+
warning: "warning",
|
|
1503
|
+
error: "error",
|
|
1504
|
+
danger: "error"
|
|
1505
|
+
};
|
|
1506
|
+
var MONTH_EVENT_STYLES = /* @__PURE__ */ new Set(["statusTag", "tag"]);
|
|
1507
|
+
var monthLabelMaxChars = (style) => {
|
|
1508
|
+
const overhead = style === "tag" ? 34 : 46;
|
|
1509
|
+
return Math.max(6, Math.floor((MONTH_COL_WIDTH - overhead) / 6.6));
|
|
1510
|
+
};
|
|
1511
|
+
var truncateMonthLabel = (value, max) => {
|
|
1512
|
+
const s = String(value == null ? "" : value);
|
|
1513
|
+
if (!max || s.length <= max) return s;
|
|
1514
|
+
return s.slice(0, max).trimEnd();
|
|
1515
|
+
};
|
|
1357
1516
|
var MONTH_COL_WIDTH = 160;
|
|
1358
1517
|
var TIMEGRID_DAY_COL = 150;
|
|
1359
1518
|
var TIMEGRID_DAY_COL_SINGLE = 560;
|
|
1519
|
+
var RESOURCE_LABEL_COL_WIDTH = "min";
|
|
1360
1520
|
var HOUR_SLOT_HEIGHT = 64;
|
|
1361
|
-
var EventDetail = ({ event, labels }) => {
|
|
1521
|
+
var EventDetail = ({ event, labels, reschedule, idSuffix = "" }) => {
|
|
1362
1522
|
const { start, end, title, subtitle, href } = event;
|
|
1363
1523
|
let when = "";
|
|
1364
1524
|
if (start) {
|
|
@@ -1372,11 +1532,27 @@ var EventDetail = ({ event, labels }) => {
|
|
|
1372
1532
|
when = `${formatDayTitle(start)} \u2013 ${formatDayTitle(end)}`;
|
|
1373
1533
|
}
|
|
1374
1534
|
}
|
|
1375
|
-
return /* @__PURE__ */ React5.createElement(Flex4, { direction: "column", gap: "xs" }, /* @__PURE__ */ React5.createElement(Text, { format: { fontWeight: "demibold" } }, title || "--"), when ? /* @__PURE__ */ React5.createElement(Text, { variant: "microcopy" }, when) : null, subtitle ? /* @__PURE__ */ React5.createElement(Text,
|
|
1535
|
+
return /* @__PURE__ */ React5.createElement(Flex4, { direction: "column", gap: "xs" }, /* @__PURE__ */ React5.createElement(Text, { format: { fontWeight: "demibold" }, truncate: true }, title || "--"), when ? /* @__PURE__ */ React5.createElement(Text, { variant: "microcopy", truncate: true }, when) : null, subtitle ? /* @__PURE__ */ React5.createElement(Text, { truncate: true }, subtitle) : null, href ? /* @__PURE__ */ React5.createElement(Link2, { href: href.url, external: href.external }, labels.open) : null, reschedule ? /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement(Divider, null), /* @__PURE__ */ React5.createElement(Text, { variant: "microcopy", format: { fontWeight: "demibold" } }, labels.reschedule), reschedule.options.length > 0 ? /* @__PURE__ */ React5.createElement(Flex4, { direction: "row", gap: "xs", wrap: "wrap" }, reschedule.options.map((option, i) => /* @__PURE__ */ React5.createElement(
|
|
1536
|
+
Button3,
|
|
1537
|
+
{
|
|
1538
|
+
key: `${option.label}-${i}`,
|
|
1539
|
+
size: "xs",
|
|
1540
|
+
variant: "secondary",
|
|
1541
|
+
onClick: () => reschedule.onPreset(event, option)
|
|
1542
|
+
},
|
|
1543
|
+
option.label
|
|
1544
|
+
))) : null, /* @__PURE__ */ React5.createElement(
|
|
1545
|
+
DateInput2,
|
|
1546
|
+
{
|
|
1547
|
+
name: `cal-resched-${event.key}${idSuffix}`,
|
|
1548
|
+
label: labels.pickDate,
|
|
1549
|
+
onChange: (value) => reschedule.onPick(event, value)
|
|
1550
|
+
}
|
|
1551
|
+
)) : null);
|
|
1376
1552
|
};
|
|
1377
|
-
var buildOverlay = (event, mode, renderEventDetail, labels, idSuffix = "") => {
|
|
1553
|
+
var buildOverlay = (event, mode, renderEventDetail, labels, idSuffix = "", reschedule = null) => {
|
|
1378
1554
|
if (mode === "none") return void 0;
|
|
1379
|
-
const body = renderEventDetail ? renderEventDetail(event) : /* @__PURE__ */ React5.createElement(EventDetail, { event, labels });
|
|
1555
|
+
const body = renderEventDetail ? renderEventDetail(event) : /* @__PURE__ */ React5.createElement(EventDetail, { event, labels, reschedule, idSuffix });
|
|
1380
1556
|
const id = `cal-evt-${event.key}${idSuffix}`;
|
|
1381
1557
|
if (mode === "modal") {
|
|
1382
1558
|
return /* @__PURE__ */ React5.createElement(Modal, { id, title: event.title || labels.open, width: "small" }, /* @__PURE__ */ React5.createElement(ModalBody, null, body));
|
|
@@ -1384,46 +1560,34 @@ var buildOverlay = (event, mode, renderEventDetail, labels, idSuffix = "") => {
|
|
|
1384
1560
|
if (mode === "panel") {
|
|
1385
1561
|
return /* @__PURE__ */ React5.createElement(Panel, { id, title: event.title || labels.open, width: "small", variant: "modal" }, /* @__PURE__ */ React5.createElement(PanelBody, null, body));
|
|
1386
1562
|
}
|
|
1387
|
-
return /* @__PURE__ */ React5.createElement(Popover, { id, placement: "bottom" }, /* @__PURE__ */ React5.createElement(Tile, { compact: true }, body));
|
|
1563
|
+
return /* @__PURE__ */ React5.createElement(Popover, { id, placement: "bottom", variant: "longform" }, /* @__PURE__ */ React5.createElement(Tile, { compact: true }, body));
|
|
1388
1564
|
};
|
|
1389
|
-
var AgendaEventRow = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels }) => {
|
|
1565
|
+
var AgendaEventRow = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels, reschedule }) => {
|
|
1390
1566
|
const variant = VALID_VARIANTS.has(event.color) ? event.color : "default";
|
|
1391
|
-
const overlay = buildOverlay(event, overlayMode, renderEventDetail, labels, day ? `-ag${day.getTime()}` : "");
|
|
1567
|
+
const overlay = buildOverlay(event, overlayMode, renderEventDetail, labels, day ? `-ag${day.getTime()}` : "", reschedule);
|
|
1392
1568
|
const handleClick = onEventClick ? () => onEventClick(event.raw, event) : void 0;
|
|
1393
1569
|
const timeLabel = isAllDayEvent(event) ? labels.allDay : formatTime(event.start);
|
|
1394
1570
|
return /* @__PURE__ */ React5.createElement(Flex4, { direction: "row", align: "center", gap: "sm" }, /* @__PURE__ */ React5.createElement(Box2, { flex: 2 }, /* @__PURE__ */ React5.createElement(Flex4, { direction: "row", align: "center" }, /* @__PURE__ */ React5.createElement(Text, { variant: "microcopy", format: { fontWeight: "demibold" } }, timeLabel))), /* @__PURE__ */ React5.createElement(Box2, { flex: 11 }, /* @__PURE__ */ React5.createElement(Flex4, { direction: "row", align: "center", gap: "xs" }, /* @__PURE__ */ React5.createElement(ColorDot, { variant }), /* @__PURE__ */ React5.createElement(Text, { truncate: true }, /* @__PURE__ */ React5.createElement(Link2, { overlay, onClick: handleClick }, event.title || "--")))), event.subtitle ? /* @__PURE__ */ React5.createElement(Box2, { flex: 4 }, /* @__PURE__ */ React5.createElement(Flex4, { direction: "row", align: "center" }, /* @__PURE__ */ React5.createElement(Text, { variant: "microcopy", truncate: true }, event.subtitle))) : null);
|
|
1395
1571
|
};
|
|
1396
|
-
var
|
|
1397
|
-
var
|
|
1398
|
-
var MonthChip = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels }) => {
|
|
1572
|
+
var MONTH_SLOT_HEIGHT = 24;
|
|
1573
|
+
var MonthChip = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels, monthEventStyle, monthEventMaxChars, reschedule, idScope = "" }) => {
|
|
1399
1574
|
const isStartDay = !day || !event.start || isSameDay(event.start, day);
|
|
1400
|
-
const overlay = buildOverlay(event, overlayMode, renderEventDetail, labels, day ? `-m${day.getTime()}` : "");
|
|
1575
|
+
const overlay = buildOverlay(event, overlayMode, renderEventDetail, labels, day ? `-m${idScope}${day.getTime()}` : "", reschedule);
|
|
1401
1576
|
const handleClick = onEventClick ? () => onEventClick(event.raw, event) : void 0;
|
|
1402
1577
|
const variant = VALID_VARIANTS.has(event.color) ? event.color : "default";
|
|
1403
1578
|
const startHasTime = event.start && (event.start.getHours() !== 0 || event.start.getMinutes() !== 0);
|
|
1404
1579
|
const time = isStartDay && startHasTime ? `${formatTime(event.start)} ` : "";
|
|
1405
1580
|
const prefix = isStartDay ? "" : "\u2192 ";
|
|
1406
|
-
const
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
});
|
|
1412
|
-
return /* @__PURE__ */ React5.createElement(
|
|
1413
|
-
Image2,
|
|
1414
|
-
{
|
|
1415
|
-
src: chip.src,
|
|
1416
|
-
width: chip.width,
|
|
1417
|
-
height: chip.height,
|
|
1418
|
-
alt: event.title || "",
|
|
1419
|
-
overlay,
|
|
1420
|
-
onClick: handleClick
|
|
1421
|
-
}
|
|
1422
|
-
);
|
|
1581
|
+
const maxChars = monthEventMaxChars != null ? monthEventMaxChars : monthLabelMaxChars(monthEventStyle);
|
|
1582
|
+
const label = truncateMonthLabel(`${prefix}${time}${event.title || "--"}`, maxChars);
|
|
1583
|
+
if (monthEventStyle === "tag") {
|
|
1584
|
+
return /* @__PURE__ */ React5.createElement(Tag2, { variant: TAG_VARIANT[variant] || "default", overlay, onClick: handleClick }, label);
|
|
1585
|
+
}
|
|
1586
|
+
return /* @__PURE__ */ React5.createElement(Link2, { overlay, onClick: handleClick }, /* @__PURE__ */ React5.createElement(StatusTag, { variant: STATUS_VARIANT[variant] || "default" }, label));
|
|
1423
1587
|
};
|
|
1424
|
-
var DayListItem = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels }) => {
|
|
1588
|
+
var DayListItem = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels, reschedule, idScope = "" }) => {
|
|
1425
1589
|
const handleClick = onEventClick ? () => onEventClick(event.raw, event) : void 0;
|
|
1426
|
-
const overlay = buildOverlay(event, overlayMode, renderEventDetail, labels, day ? `-more${day.getTime()}` : "-more");
|
|
1590
|
+
const overlay = buildOverlay(event, overlayMode, renderEventDetail, labels, day ? `-more${idScope}${day.getTime()}` : "-more", reschedule);
|
|
1427
1591
|
const href = event.href;
|
|
1428
1592
|
return /* @__PURE__ */ React5.createElement(Button3, { variant: "transparent", size: "sm", href: href ? href.url : void 0, overlay, onClick: handleClick }, event.title || "--");
|
|
1429
1593
|
};
|
|
@@ -1488,6 +1652,40 @@ var Toolbar = ({
|
|
|
1488
1652
|
}
|
|
1489
1653
|
));
|
|
1490
1654
|
};
|
|
1655
|
+
var DayChipStack = ({ day, events, maxEventsPerDay, chipProps, labels, idScope = "" }) => {
|
|
1656
|
+
const slotSpacer = makeSpacerDataUri(MONTH_SLOT_HEIGHT, 1);
|
|
1657
|
+
const shown = events.slice(0, maxEventsPerDay);
|
|
1658
|
+
const hasOverflow = events.length > maxEventsPerDay;
|
|
1659
|
+
const heightSpacer = /* @__PURE__ */ React5.createElement(Image2, { src: slotSpacer.src, width: slotSpacer.width, height: slotSpacer.height, alt: "" });
|
|
1660
|
+
const slotRow = (key, content) => /* @__PURE__ */ React5.createElement(Flex4, { key, direction: "row", align: "center", gap: "flush" }, heightSpacer, content);
|
|
1661
|
+
const slots = [];
|
|
1662
|
+
for (let i = 0; i < maxEventsPerDay; i++) {
|
|
1663
|
+
if (i < shown.length) {
|
|
1664
|
+
slots.push(slotRow(shown[i].key, /* @__PURE__ */ React5.createElement(MonthChip, { event: shown[i], day, idScope, ...chipProps })));
|
|
1665
|
+
} else {
|
|
1666
|
+
slots.push(/* @__PURE__ */ React5.createElement(Image2, { key: `sp-${i}`, src: slotSpacer.src, width: slotSpacer.width, height: slotSpacer.height, alt: "" }));
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
if (hasOverflow) {
|
|
1670
|
+
slots.push(
|
|
1671
|
+
slotRow(
|
|
1672
|
+
"more",
|
|
1673
|
+
/* @__PURE__ */ React5.createElement(
|
|
1674
|
+
Link2,
|
|
1675
|
+
{
|
|
1676
|
+
overlay: /* @__PURE__ */ React5.createElement(Popover, { id: `cal-day-${idScope}${day.getTime()}`, placement: "top", variant: "longform" }, /* @__PURE__ */ React5.createElement(Tile, { compact: true }, /* @__PURE__ */ React5.createElement(Flex4, { direction: "column", gap: "sm" }, /* @__PURE__ */ React5.createElement(Flex4, { direction: "row", justify: "center", align: "center", gap: "xs" }, /* @__PURE__ */ React5.createElement(Text, { format: { fontWeight: "bold" } }, String(events.length)), /* @__PURE__ */ React5.createElement(Text, { format: { fontWeight: "demibold" } }, labels.onThisDate)), /* @__PURE__ */ React5.createElement(Divider, null), events.map((event, i) => /* @__PURE__ */ React5.createElement(React5.Fragment, { key: event.key }, /* @__PURE__ */ React5.createElement(DayListItem, { event, day, idScope, ...chipProps }), i < events.length - 1 ? /* @__PURE__ */ React5.createElement(Divider, null) : null)))))
|
|
1677
|
+
},
|
|
1678
|
+
labels.more(events.length - maxEventsPerDay)
|
|
1679
|
+
)
|
|
1680
|
+
)
|
|
1681
|
+
);
|
|
1682
|
+
} else {
|
|
1683
|
+
slots.push(
|
|
1684
|
+
/* @__PURE__ */ React5.createElement(Image2, { key: "more-sp", src: slotSpacer.src, width: slotSpacer.width, height: slotSpacer.height, alt: "" })
|
|
1685
|
+
);
|
|
1686
|
+
}
|
|
1687
|
+
return /* @__PURE__ */ React5.createElement(Flex4, { direction: "column", gap: "xs" }, slots);
|
|
1688
|
+
};
|
|
1491
1689
|
var MonthView = ({
|
|
1492
1690
|
refDate,
|
|
1493
1691
|
now,
|
|
@@ -1502,49 +1700,21 @@ var MonthView = ({
|
|
|
1502
1700
|
}) => {
|
|
1503
1701
|
const headers = weekdayLabels(weekStartsOn, hideWeekends, true);
|
|
1504
1702
|
const today = now || /* @__PURE__ */ new Date();
|
|
1505
|
-
const spacer24 = makeSpacerDataUri(MONTH_CHIP_HEIGHT, MONTH_COL_WIDTH);
|
|
1506
1703
|
const renderCell = (day) => {
|
|
1507
1704
|
const dayEvents = eventsForDay(day);
|
|
1508
1705
|
const inMonth = isSameMonth(day, refDate);
|
|
1509
1706
|
const isToday = isSameDay(day, today);
|
|
1510
1707
|
if (renderDayCell) return renderDayCell(day, dayEvents);
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
/* @__PURE__ */ React5.createElement(Image2, { key: `sp-${i}`, src: spacer24.src, width: spacer24.width, height: spacer24.height, alt: "" })
|
|
1520
|
-
);
|
|
1708
|
+
return /* @__PURE__ */ React5.createElement(AutoGrid, { columnWidth: MONTH_COL_WIDTH, gap: "flush" }, /* @__PURE__ */ React5.createElement(Flex4, { direction: "column", gap: "xs" }, /* @__PURE__ */ React5.createElement(Flex4, { direction: "row", align: "center", gap: "xs" }, isToday ? /* @__PURE__ */ React5.createElement(ColorDot, { variant: "info" }) : null, /* @__PURE__ */ React5.createElement(Text, { variant: "microcopy", format: { fontWeight: inMonth ? "demibold" : "regular" } }, String(day.getDate()))), /* @__PURE__ */ React5.createElement(
|
|
1709
|
+
DayChipStack,
|
|
1710
|
+
{
|
|
1711
|
+
day,
|
|
1712
|
+
events: dayEvents,
|
|
1713
|
+
maxEventsPerDay,
|
|
1714
|
+
chipProps,
|
|
1715
|
+
labels
|
|
1521
1716
|
}
|
|
1522
|
-
|
|
1523
|
-
if (hasOverflow) {
|
|
1524
|
-
const more = makeMoreDataUri({
|
|
1525
|
-
label: labels.more(dayEvents.length - maxEventsPerDay),
|
|
1526
|
-
width: MONTH_COL_WIDTH,
|
|
1527
|
-
height: MONTH_CHIP_HEIGHT
|
|
1528
|
-
});
|
|
1529
|
-
slots.push(
|
|
1530
|
-
/* @__PURE__ */ React5.createElement(
|
|
1531
|
-
Image2,
|
|
1532
|
-
{
|
|
1533
|
-
key: "more",
|
|
1534
|
-
src: more.src,
|
|
1535
|
-
width: more.width,
|
|
1536
|
-
height: more.height,
|
|
1537
|
-
alt: labels.more(dayEvents.length - maxEventsPerDay),
|
|
1538
|
-
overlay: /* @__PURE__ */ React5.createElement(Popover, { id: `cal-day-${day.getTime()}`, placement: "top", variant: "longform" }, /* @__PURE__ */ React5.createElement(Tile, { compact: true }, /* @__PURE__ */ React5.createElement(Flex4, { direction: "column", gap: "sm" }, /* @__PURE__ */ React5.createElement(Flex4, { direction: "row", align: "center", gap: "sm" }, /* @__PURE__ */ React5.createElement(Heading, null, String(dayEvents.length)), /* @__PURE__ */ React5.createElement(Text, { format: { fontWeight: "demibold" } }, labels.onThisDate)), /* @__PURE__ */ React5.createElement(Divider, null), dayEvents.map((event, i) => /* @__PURE__ */ React5.createElement(React5.Fragment, { key: event.key }, /* @__PURE__ */ React5.createElement(DayListItem, { event, day, ...chipProps }), i < dayEvents.length - 1 ? /* @__PURE__ */ React5.createElement(Divider, null) : null)))))
|
|
1539
|
-
}
|
|
1540
|
-
)
|
|
1541
|
-
);
|
|
1542
|
-
} else {
|
|
1543
|
-
slots.push(
|
|
1544
|
-
/* @__PURE__ */ React5.createElement(Image2, { key: "more-sp", src: spacer24.src, width: spacer24.width, height: spacer24.height, alt: "" })
|
|
1545
|
-
);
|
|
1546
|
-
}
|
|
1547
|
-
return /* @__PURE__ */ React5.createElement(Flex4, { direction: "column", gap: "xs" }, /* @__PURE__ */ React5.createElement(Flex4, { direction: "row", align: "center", gap: "xs" }, isToday ? /* @__PURE__ */ React5.createElement(ColorDot, { variant: "info" }) : null, /* @__PURE__ */ React5.createElement(Text, { variant: "microcopy", format: { fontWeight: inMonth ? "demibold" : "regular" } }, String(day.getDate()))), slots);
|
|
1717
|
+
)));
|
|
1548
1718
|
};
|
|
1549
1719
|
return /* @__PURE__ */ React5.createElement(Table, { bordered: true, flush: true }, /* @__PURE__ */ React5.createElement(TableHead, null, /* @__PURE__ */ React5.createElement(TableRow, null, headers.map((h4) => /* @__PURE__ */ React5.createElement(TableHeader, { key: h4, width: "min", align: "center" }, h4.toUpperCase())))), /* @__PURE__ */ React5.createElement(TableBody, null, weeks.map((week, wi) => {
|
|
1550
1720
|
const days = hideWeekends ? week.filter((d) => d.getDay() !== 0 && d.getDay() !== 6) : week;
|
|
@@ -1566,6 +1736,33 @@ var AgendaView = ({ rangeStart, rangeEnd, eventsForDay, chipProps, labels, rende
|
|
|
1566
1736
|
}
|
|
1567
1737
|
return /* @__PURE__ */ React5.createElement(Flex4, { direction: "column", gap: "lg" }, days.map(({ day, events }) => /* @__PURE__ */ React5.createElement(Flex4, { key: day.getTime(), direction: "column", gap: "sm" }, /* @__PURE__ */ React5.createElement(Flex4, { direction: "row", justify: "between", align: "end" }, /* @__PURE__ */ React5.createElement(Text, { format: { fontWeight: "demibold" } }, formatDayTitle(day)), /* @__PURE__ */ React5.createElement(Text, { variant: "microcopy" }, `${events.length} ${events.length === 1 ? "event" : "events"}`)), /* @__PURE__ */ React5.createElement(Divider, null), events.map((event) => /* @__PURE__ */ React5.createElement(AgendaEventRow, { key: event.key, event, day, ...chipProps })))));
|
|
1568
1738
|
};
|
|
1739
|
+
var ResourceView = ({ days, now, lanes, maxEventsPerDay, chipProps, labels, renderEmptyState }) => {
|
|
1740
|
+
const today = now || /* @__PURE__ */ new Date();
|
|
1741
|
+
if (!lanes || lanes.length === 0) {
|
|
1742
|
+
if (renderEmptyState) return renderEmptyState({});
|
|
1743
|
+
return /* @__PURE__ */ React5.createElement(EmptyState, { title: labels.noEventsTitle }, /* @__PURE__ */ React5.createElement(Text, null, labels.noEventsMessage));
|
|
1744
|
+
}
|
|
1745
|
+
const rangeStart = startOfDay(days[0]);
|
|
1746
|
+
const rangeEnd = endOfDay(days[days.length - 1]);
|
|
1747
|
+
return /* @__PURE__ */ React5.createElement(Table, { bordered: true, flush: true }, /* @__PURE__ */ React5.createElement(TableHead, null, /* @__PURE__ */ React5.createElement(TableRow, null, /* @__PURE__ */ React5.createElement(TableHeader, { width: RESOURCE_LABEL_COL_WIDTH }, String(labels.resource).toUpperCase()), days.map((day) => {
|
|
1748
|
+
const isToday = isSameDay(day, today);
|
|
1749
|
+
const label = `${formatWeekdayShort(day)} ${formatMonthShort(day)} ${day.getDate()}`;
|
|
1750
|
+
return /* @__PURE__ */ React5.createElement(TableHeader, { key: day.getTime(), width: "min", align: "center" }, isToday ? `${label} \xB7 Today` : label);
|
|
1751
|
+
}))), /* @__PURE__ */ React5.createElement(TableBody, null, lanes.map((lane, laneIndex) => {
|
|
1752
|
+
const visible = eventsIntersectingRange(lane.events, rangeStart, rangeEnd);
|
|
1753
|
+
return /* @__PURE__ */ React5.createElement(TableRow, { key: lane.key }, /* @__PURE__ */ React5.createElement(TableCell, { width: RESOURCE_LABEL_COL_WIDTH }, /* @__PURE__ */ React5.createElement(Flex4, { direction: "column", gap: "flush" }, /* @__PURE__ */ React5.createElement(Text, { format: { fontWeight: "demibold" } }, lane.label), /* @__PURE__ */ React5.createElement(Text, { variant: "microcopy" }, `${visible.length} ${visible.length === 1 ? "event" : "events"}`))), days.map((day) => /* @__PURE__ */ React5.createElement(TableCell, { key: day.getTime(), width: "min" }, /* @__PURE__ */ React5.createElement(AutoGrid, { columnWidth: MONTH_COL_WIDTH, gap: "flush" }, /* @__PURE__ */ React5.createElement(
|
|
1754
|
+
DayChipStack,
|
|
1755
|
+
{
|
|
1756
|
+
day,
|
|
1757
|
+
events: laneEventsForDay(visible, day),
|
|
1758
|
+
maxEventsPerDay,
|
|
1759
|
+
chipProps,
|
|
1760
|
+
labels,
|
|
1761
|
+
idScope: `r${laneIndex}-`
|
|
1762
|
+
}
|
|
1763
|
+
)))));
|
|
1764
|
+
})));
|
|
1765
|
+
};
|
|
1569
1766
|
var formatTimedDuration = (start, end) => {
|
|
1570
1767
|
const mins = Math.max(0, Math.round(((end || start).getTime() - start.getTime()) / 6e4));
|
|
1571
1768
|
const h4 = Math.floor(mins / 60);
|
|
@@ -1587,6 +1784,7 @@ var TimeGridView = ({ days, now, hours, dayStartHour, dayEndHour, eventsForDay,
|
|
|
1587
1784
|
const today = now || /* @__PURE__ */ new Date();
|
|
1588
1785
|
const centerDays = days.length === 1;
|
|
1589
1786
|
const dayColWidth = days.length === 1 ? TIMEGRID_DAY_COL_SINGLE : TIMEGRID_DAY_COL;
|
|
1787
|
+
const weekTitleMaxChars = Math.max(6, Math.floor((TIMEGRID_DAY_COL - 46) / 6.6));
|
|
1590
1788
|
const todayInView = days.some((d) => isSameDay(d, today));
|
|
1591
1789
|
const nowHour = today.getHours();
|
|
1592
1790
|
const dayData = days.map((day) => {
|
|
@@ -1612,7 +1810,8 @@ var TimeGridView = ({ days, now, hours, dayStartHour, dayEndHour, eventsForDay,
|
|
|
1612
1810
|
chipProps.overlayMode,
|
|
1613
1811
|
chipProps.renderEventDetail,
|
|
1614
1812
|
chipProps.labels,
|
|
1615
|
-
`-tg${mode}${hour}-${dayMs}
|
|
1813
|
+
`-tg${mode}${hour}-${dayMs}`,
|
|
1814
|
+
chipProps.reschedule
|
|
1616
1815
|
);
|
|
1617
1816
|
const handleClick = chipProps.onEventClick ? () => chipProps.onEventClick(e.raw, e) : void 0;
|
|
1618
1817
|
const variant = VALID_VARIANTS.has(e.color) ? e.color : "default";
|
|
@@ -1631,10 +1830,10 @@ var TimeGridView = ({ days, now, hours, dayStartHour, dayEndHour, eventsForDay,
|
|
|
1631
1830
|
} else if (mode === "cont") {
|
|
1632
1831
|
sub = `\u2191 cont. through ${endLabel}`;
|
|
1633
1832
|
}
|
|
1634
|
-
|
|
1833
|
+
const titleLabel = centerDays ? e.title || "--" : truncateMonthLabel(e.title || "--", weekTitleMaxChars);
|
|
1834
|
+
return /* @__PURE__ */ React5.createElement(Flex4, { key: `${e.key}-${mode}-${hour}`, direction: "column", gap: "flush" }, /* @__PURE__ */ React5.createElement(Link2, { overlay, onClick: handleClick }, /* @__PURE__ */ React5.createElement(StatusTag, { variant: STATUS_VARIANT[variant] || "default" }, titleLabel)), sub ? /* @__PURE__ */ React5.createElement(Text, { variant: "microcopy" }, sub) : null);
|
|
1635
1835
|
};
|
|
1636
|
-
const
|
|
1637
|
-
const dayCell = (key, content) => /* @__PURE__ */ React5.createElement(TableCell, { key, width: centerDays ? "max" : "min", align: "left" }, /* @__PURE__ */ React5.createElement(Flex4, { direction: "column", gap: "xs" }, content, centerDays ? null : /* @__PURE__ */ React5.createElement(Image2, { src: daySpacer.src, width: daySpacer.width, height: daySpacer.height, alt: "" })));
|
|
1836
|
+
const dayCell = (key, content) => /* @__PURE__ */ React5.createElement(TableCell, { key, width: centerDays ? "max" : "min", align: "left" }, centerDays ? /* @__PURE__ */ React5.createElement(Flex4, { direction: "column", gap: "xs" }, content) : /* @__PURE__ */ React5.createElement(AutoGrid, { columnWidth: dayColWidth, gap: "flush" }, /* @__PURE__ */ React5.createElement(Flex4, { direction: "column", gap: "xs" }, content)));
|
|
1638
1837
|
const slotSpacer = makeSpacerDataUri(HOUR_SLOT_HEIGHT, 1);
|
|
1639
1838
|
const emptyCell = null;
|
|
1640
1839
|
return /* @__PURE__ */ React5.createElement(Table, { bordered: true, flush: true, density: "compact" }, /* @__PURE__ */ React5.createElement(TableHead, null, /* @__PURE__ */ React5.createElement(TableRow, null, /* @__PURE__ */ React5.createElement(TableHeader, { width: "min" }, "TIME"), dayData.map(({ day }) => {
|
|
@@ -1690,9 +1889,21 @@ var Calendar = (props) => {
|
|
|
1690
1889
|
weekStartsOn = 0,
|
|
1691
1890
|
hideWeekends = false,
|
|
1692
1891
|
maxEventsPerDay = DEFAULT_MAX_EVENTS_PER_DAY,
|
|
1892
|
+
// month-grid event token style: "statusTag" (dot + text, default) | "tag" (pill)
|
|
1893
|
+
monthEventStyle = "statusTag",
|
|
1894
|
+
// max characters for a month-cell label before "…" (default derived per style)
|
|
1895
|
+
monthEventMaxChars,
|
|
1693
1896
|
// time grid (week / day)
|
|
1694
1897
|
dayStartHour = DEFAULT_DAY_START_HOUR,
|
|
1695
1898
|
dayEndHour = DEFAULT_DAY_END_HOUR,
|
|
1899
|
+
// resource / lane view (rows = resources, columns = the focused week's days)
|
|
1900
|
+
resources,
|
|
1901
|
+
resourceField,
|
|
1902
|
+
resourceLabels,
|
|
1903
|
+
showUnassignedLane = true,
|
|
1904
|
+
// drag-free reschedule (presets + date picker in the event-detail overlay)
|
|
1905
|
+
rescheduleOptions,
|
|
1906
|
+
onEventReschedule,
|
|
1696
1907
|
// timezone
|
|
1697
1908
|
timeZone: controlledTimeZone,
|
|
1698
1909
|
defaultTimeZone,
|
|
@@ -1731,10 +1942,12 @@ var Calendar = (props) => {
|
|
|
1731
1942
|
const fields = useMemo(() => ({ ...DEFAULT_EVENT_FIELDS, ...eventFields || {} }), [eventFields]);
|
|
1732
1943
|
const [internalView, setInternalView] = useState2(defaultView);
|
|
1733
1944
|
const view = controlledView != null ? controlledView : internalView;
|
|
1945
|
+
const resourceEnabled = resources && resources.length > 0 || resourceField != null;
|
|
1734
1946
|
const enabledViews = useMemo(() => {
|
|
1735
|
-
const
|
|
1736
|
-
|
|
1737
|
-
|
|
1947
|
+
const all = resourceEnabled ? ALL_VIEWS_WITH_RESOURCE : ALL_VIEWS;
|
|
1948
|
+
const base = viewsProp && viewsProp.length > 0 ? viewsProp : all;
|
|
1949
|
+
return base.filter((v) => all.includes(v));
|
|
1950
|
+
}, [viewsProp, resourceEnabled]);
|
|
1738
1951
|
const setView = useCallback(
|
|
1739
1952
|
(next) => {
|
|
1740
1953
|
if (controlledView == null) setInternalView(next);
|
|
@@ -1759,7 +1972,9 @@ var Calendar = (props) => {
|
|
|
1759
1972
|
const focusedDate = (controlledFocusedDate != null ? toDate(controlledFocusedDate) : internalDate) || startOfDay(nowWall);
|
|
1760
1973
|
const stepFor = useCallback(
|
|
1761
1974
|
(dir) => {
|
|
1762
|
-
if (view === "week" || view === "agenda"
|
|
1975
|
+
if (view === "week" || view === "agenda" || view === "resource") {
|
|
1976
|
+
return addDays(focusedDate, dir * 7);
|
|
1977
|
+
}
|
|
1763
1978
|
if (view === "day") return addDays(focusedDate, dir);
|
|
1764
1979
|
return addMonths(focusedDate, dir);
|
|
1765
1980
|
},
|
|
@@ -1786,7 +2001,7 @@ var Calendar = (props) => {
|
|
|
1786
2001
|
rangeEnd: endOfDay(flat[flat.length - 1])
|
|
1787
2002
|
};
|
|
1788
2003
|
}
|
|
1789
|
-
if (view === "week") {
|
|
2004
|
+
if (view === "week" || view === "resource") {
|
|
1790
2005
|
const days = buildWeekDays(focusedDate, weekStartsOn, hideWeekends);
|
|
1791
2006
|
return {
|
|
1792
2007
|
weeks: null,
|
|
@@ -1859,14 +2074,18 @@ var Calendar = (props) => {
|
|
|
1859
2074
|
);
|
|
1860
2075
|
const normalized = useMemo(
|
|
1861
2076
|
() => (events || []).map((raw, index) => {
|
|
1862
|
-
const
|
|
1863
|
-
const
|
|
2077
|
+
const sourceStart = toDate(resolveField(raw, fields.start));
|
|
2078
|
+
const sourceEnd = toDate(resolveField(raw, fields.end));
|
|
2079
|
+
const start = toWallClock(sourceStart, timeZone);
|
|
2080
|
+
const endRaw = toWallClock(sourceEnd, timeZone);
|
|
1864
2081
|
const id = resolveField(raw, fields.id);
|
|
1865
2082
|
return {
|
|
1866
2083
|
key: id != null ? String(id) : `evt-${index}`,
|
|
1867
2084
|
id,
|
|
1868
2085
|
start,
|
|
1869
2086
|
end: endRaw || start,
|
|
2087
|
+
sourceStart,
|
|
2088
|
+
sourceEnd: sourceEnd || sourceStart,
|
|
1870
2089
|
title: resolveField(raw, fields.title),
|
|
1871
2090
|
subtitle: resolveField(raw, fields.subtitle),
|
|
1872
2091
|
color: resolveField(raw, fields.color),
|
|
@@ -1903,13 +2122,60 @@ var Calendar = (props) => {
|
|
|
1903
2122
|
}, [rangeKey]);
|
|
1904
2123
|
const title = useMemo(() => {
|
|
1905
2124
|
if (view === "day") return formatDayTitle(focusedDate);
|
|
1906
|
-
if (view === "week" || view === "agenda") {
|
|
1907
|
-
const days = buildWeekDays(focusedDate, weekStartsOn, view
|
|
2125
|
+
if (view === "week" || view === "agenda" || view === "resource") {
|
|
2126
|
+
const days = buildWeekDays(focusedDate, weekStartsOn, view !== "agenda" && hideWeekends);
|
|
1908
2127
|
return formatRangeTitle(days[0], days[days.length - 1]);
|
|
1909
2128
|
}
|
|
1910
2129
|
return formatMonthTitle(focusedDate);
|
|
1911
2130
|
}, [view, focusedDate, weekStartsOn, hideWeekends]);
|
|
1912
|
-
const
|
|
2131
|
+
const handleReschedulePreset = useCallback(
|
|
2132
|
+
(event, option) => {
|
|
2133
|
+
const target = resolveRescheduleTarget(
|
|
2134
|
+
{ start: event.sourceStart, end: event.sourceEnd },
|
|
2135
|
+
option,
|
|
2136
|
+
event
|
|
2137
|
+
);
|
|
2138
|
+
if (target && onEventReschedule) onEventReschedule(event.raw, target, event);
|
|
2139
|
+
},
|
|
2140
|
+
[onEventReschedule]
|
|
2141
|
+
);
|
|
2142
|
+
const handleReschedulePick = useCallback(
|
|
2143
|
+
(event, value) => {
|
|
2144
|
+
const newStart = applyDatePick(event.sourceStart, value);
|
|
2145
|
+
if (!newStart) return;
|
|
2146
|
+
const target = rescheduleToStart({ start: event.sourceStart, end: event.sourceEnd }, newStart);
|
|
2147
|
+
if (target && onEventReschedule) onEventReschedule(event.raw, target, event);
|
|
2148
|
+
},
|
|
2149
|
+
[onEventReschedule]
|
|
2150
|
+
);
|
|
2151
|
+
const reschedule = useMemo(() => {
|
|
2152
|
+
if (!rescheduleOptions) return null;
|
|
2153
|
+
return {
|
|
2154
|
+
options: normalizeRescheduleOptions(rescheduleOptions),
|
|
2155
|
+
onPreset: handleReschedulePreset,
|
|
2156
|
+
onPick: handleReschedulePick
|
|
2157
|
+
};
|
|
2158
|
+
}, [rescheduleOptions, handleReschedulePreset, handleReschedulePick]);
|
|
2159
|
+
const safeMonthEventStyle = MONTH_EVENT_STYLES.has(monthEventStyle) ? monthEventStyle : "statusTag";
|
|
2160
|
+
const chipProps = {
|
|
2161
|
+
overlayMode,
|
|
2162
|
+
renderEventDetail,
|
|
2163
|
+
onEventClick,
|
|
2164
|
+
labels,
|
|
2165
|
+
monthEventStyle: safeMonthEventStyle,
|
|
2166
|
+
monthEventMaxChars,
|
|
2167
|
+
reschedule
|
|
2168
|
+
};
|
|
2169
|
+
const resourceLaneData = useMemo(() => {
|
|
2170
|
+
if (view !== "resource") return null;
|
|
2171
|
+
return buildResourceLanes(queried, {
|
|
2172
|
+
resources,
|
|
2173
|
+
resourceLabels,
|
|
2174
|
+
getId: (e) => resolveResourceId(e.raw, resourceField),
|
|
2175
|
+
showUnassignedLane,
|
|
2176
|
+
unassignedLabel: labels.unassigned
|
|
2177
|
+
});
|
|
2178
|
+
}, [view, queried, resources, resourceLabels, resourceField, showUnassignedLane, labels]);
|
|
1913
2179
|
const timeZoneOptions = useMemo(() => {
|
|
1914
2180
|
if (!showTimeZoneSelect) return null;
|
|
1915
2181
|
const base = (timeZoneOptionsProp && timeZoneOptionsProp.length ? timeZoneOptionsProp : DEFAULT_TIME_ZONES).map(
|
|
@@ -1970,6 +2236,19 @@ var Calendar = (props) => {
|
|
|
1970
2236
|
labels
|
|
1971
2237
|
}
|
|
1972
2238
|
);
|
|
2239
|
+
} else if (view === "resource") {
|
|
2240
|
+
body = /* @__PURE__ */ React5.createElement(
|
|
2241
|
+
ResourceView,
|
|
2242
|
+
{
|
|
2243
|
+
days: gridDays,
|
|
2244
|
+
now: nowWall,
|
|
2245
|
+
lanes: resourceLaneData,
|
|
2246
|
+
maxEventsPerDay,
|
|
2247
|
+
chipProps,
|
|
2248
|
+
labels,
|
|
2249
|
+
renderEmptyState
|
|
2250
|
+
}
|
|
2251
|
+
);
|
|
1973
2252
|
} else if (view === "week" || view === "day") {
|
|
1974
2253
|
body = /* @__PURE__ */ React5.createElement(
|
|
1975
2254
|
TimeGridView,
|
|
@@ -1999,6 +2278,7 @@ var Calendar = (props) => {
|
|
|
1999
2278
|
}
|
|
2000
2279
|
return /* @__PURE__ */ React5.createElement(Flex4, { direction: "column", gap: "sm" }, toolbar, body);
|
|
2001
2280
|
};
|
|
2281
|
+
Calendar.displayName = "Calendar";
|
|
2002
2282
|
export {
|
|
2003
2283
|
Calendar
|
|
2004
2284
|
};
|