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.js
CHANGED
|
@@ -89,7 +89,6 @@ var import_react2 = __toESM(require("react"));
|
|
|
89
89
|
var import_ui_extensions2 = require("@hubspot/ui-extensions");
|
|
90
90
|
|
|
91
91
|
// src/common-components/svgDefaults.js
|
|
92
|
-
var HS_FONT_FAMILY = '"Lexend Deca", Helvetica, Arial, sans-serif';
|
|
93
92
|
var HS_TEXT_COLOR = "#33475b";
|
|
94
93
|
|
|
95
94
|
// src/common-components/icons.generated.js
|
|
@@ -344,7 +343,7 @@ var GENERATED_ICONS = {
|
|
|
344
343
|
"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"] }
|
|
345
344
|
};
|
|
346
345
|
|
|
347
|
-
// src/common-components/
|
|
346
|
+
// src/common-components/nativeIconNames.js
|
|
348
347
|
var NATIVE_ICON_NAMES = /* @__PURE__ */ new Set([
|
|
349
348
|
"add",
|
|
350
349
|
"appointment",
|
|
@@ -356,12 +355,12 @@ var NATIVE_ICON_NAMES = /* @__PURE__ */ new Set([
|
|
|
356
355
|
"block",
|
|
357
356
|
"book",
|
|
358
357
|
"bulb",
|
|
358
|
+
"callTranscript",
|
|
359
359
|
"calling",
|
|
360
360
|
"callingHangup",
|
|
361
361
|
"callingMade",
|
|
362
362
|
"callingMissed",
|
|
363
363
|
"callingVoicemail",
|
|
364
|
-
"callTranscript",
|
|
365
364
|
"campaigns",
|
|
366
365
|
"cap",
|
|
367
366
|
"checkCircle",
|
|
@@ -390,13 +389,13 @@ var NATIVE_ICON_NAMES = /* @__PURE__ */ new Set([
|
|
|
390
389
|
"enroll",
|
|
391
390
|
"exclamation",
|
|
392
391
|
"exclamationCircle",
|
|
393
|
-
"facebook",
|
|
394
392
|
"faceHappy",
|
|
395
393
|
"faceHappyFilled",
|
|
396
394
|
"faceNeutral",
|
|
397
395
|
"faceNeutralFilled",
|
|
398
396
|
"faceSad",
|
|
399
397
|
"faceSadFilled",
|
|
398
|
+
"facebook",
|
|
400
399
|
"favoriteHollow",
|
|
401
400
|
"file",
|
|
402
401
|
"filledXCircleIcon",
|
|
@@ -537,6 +536,8 @@ var NATIVE_ICON_NAMES = /* @__PURE__ */ new Set([
|
|
|
537
536
|
"zoomIn",
|
|
538
537
|
"zoomOut"
|
|
539
538
|
]);
|
|
539
|
+
|
|
540
|
+
// src/common-components/Icon.js
|
|
540
541
|
var NATIVE_COLORS = /* @__PURE__ */ new Set(["inherit", "alert", "warning", "success"]);
|
|
541
542
|
var NATIVE_SIZE_TOKENS = {
|
|
542
543
|
sm: "sm",
|
|
@@ -749,6 +750,7 @@ var CollectionFilterControl = ({
|
|
|
749
750
|
{ key: name, direction: "row", align: "center", gap: "xs" },
|
|
750
751
|
h2(import_ui_extensions3.DateInput, {
|
|
751
752
|
name: `${controlName}-from`,
|
|
753
|
+
label: filter.fromLabel ?? labels.dateFrom,
|
|
752
754
|
placeholder: filter.fromLabel ?? labels.dateFrom,
|
|
753
755
|
format: "medium",
|
|
754
756
|
value: rangeValue.from ?? null,
|
|
@@ -757,6 +759,7 @@ var CollectionFilterControl = ({
|
|
|
757
759
|
h2(Icon, { name: "right", size: "sm" }),
|
|
758
760
|
h2(import_ui_extensions3.DateInput, {
|
|
759
761
|
name: `${controlName}-to`,
|
|
762
|
+
label: filter.toLabel ?? labels.dateTo,
|
|
760
763
|
placeholder: filter.toLabel ?? labels.dateTo,
|
|
761
764
|
format: "medium",
|
|
762
765
|
value: rangeValue.to ?? null,
|
|
@@ -1211,21 +1214,6 @@ var formatTimeZoneLabel = (tz, atDate = /* @__PURE__ */ new Date()) => {
|
|
|
1211
1214
|
|
|
1212
1215
|
// src/calendar/svgChips.js
|
|
1213
1216
|
var toDataUri = (svg) => `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
|
1214
|
-
var escapeXml = (s) => String(s == null ? "" : s).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
1215
|
-
var truncateLabel = (value, max) => {
|
|
1216
|
-
const s = String(value == null ? "" : value);
|
|
1217
|
-
if (!max || s.length <= max) return s;
|
|
1218
|
-
return s.slice(0, Math.max(1, max - 1)).trimEnd() + "\u2026";
|
|
1219
|
-
};
|
|
1220
|
-
var CHIP_PALETTE = {
|
|
1221
|
-
default: { fill: "#7FD1DE", text: HS_TEXT_COLOR },
|
|
1222
|
-
info: { fill: "#00A4BD", text: "#FFFFFF" },
|
|
1223
|
-
success: { fill: "#00BDA5", text: "#FFFFFF" },
|
|
1224
|
-
warning: { fill: "#F5C26B", text: HS_TEXT_COLOR },
|
|
1225
|
-
error: { fill: "#F2545B", text: "#FFFFFF" },
|
|
1226
|
-
danger: { fill: "#F2545B", text: "#FFFFFF" }
|
|
1227
|
-
// StatusTag spells red "danger"; accept both
|
|
1228
|
-
};
|
|
1229
1217
|
var DOT_FILL = {
|
|
1230
1218
|
default: "#7C98B6",
|
|
1231
1219
|
info: "#00A4BD",
|
|
@@ -1240,31 +1228,177 @@ var makeDotDataUri = (variant = "default", size = 8) => {
|
|
|
1240
1228
|
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>`;
|
|
1241
1229
|
return { src: toDataUri(svg), width: size, height: size };
|
|
1242
1230
|
};
|
|
1243
|
-
var makeEventChipDataUri = (opts) => {
|
|
1244
|
-
const { label, width, height = 24, variant = "default" } = opts;
|
|
1245
|
-
const palette = CHIP_PALETTE[variant] || CHIP_PALETTE.default;
|
|
1246
|
-
const accentX = 5;
|
|
1247
|
-
const accentW = 3;
|
|
1248
|
-
const textX = accentX + accentW + 6;
|
|
1249
|
-
const rightPad = 8;
|
|
1250
|
-
const maxChars = Math.max(1, Math.floor((width - textX - rightPad) / 6));
|
|
1251
|
-
const text = truncateLabel(label, maxChars);
|
|
1252
|
-
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>`;
|
|
1253
|
-
return { src: toDataUri(svg), width, height };
|
|
1254
|
-
};
|
|
1255
|
-
var makeMoreDataUri = (opts) => {
|
|
1256
|
-
const { label, width, height = 24 } = opts;
|
|
1257
|
-
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>`;
|
|
1258
|
-
return { src: toDataUri(svg), width, height };
|
|
1259
|
-
};
|
|
1260
1231
|
var makeSpacerDataUri = (height = 24, width = 4) => {
|
|
1261
1232
|
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>`;
|
|
1262
1233
|
return { src: toDataUri(svg), width, height };
|
|
1263
1234
|
};
|
|
1264
1235
|
|
|
1236
|
+
// src/calendar/rescheduleUtils.js
|
|
1237
|
+
var shiftDate = (date, shift) => {
|
|
1238
|
+
const d = toDate(date);
|
|
1239
|
+
if (!d) return null;
|
|
1240
|
+
if (!shift || typeof shift !== "object") return new Date(d);
|
|
1241
|
+
const days = (shift.days || 0) + (shift.weeks || 0) * 7;
|
|
1242
|
+
let next = days ? addDays(d, days) : new Date(d);
|
|
1243
|
+
const ms = (shift.hours || 0) * 36e5 + (shift.minutes || 0) * 6e4;
|
|
1244
|
+
if (ms) next = new Date(next.getTime() + ms);
|
|
1245
|
+
return next;
|
|
1246
|
+
};
|
|
1247
|
+
var shiftEvent = (range, shift) => {
|
|
1248
|
+
const start = toDate(range && range.start);
|
|
1249
|
+
if (!start) return null;
|
|
1250
|
+
const end = toDate(range && range.end) || start;
|
|
1251
|
+
return { start: shiftDate(start, shift), end: shiftDate(end, shift) };
|
|
1252
|
+
};
|
|
1253
|
+
var calendarDayDelta = (a, b) => Math.round((startOfDay(b).getTime() - startOfDay(a).getTime()) / MS_PER_DAY);
|
|
1254
|
+
var msIntoDay = (d) => ((d.getHours() * 60 + d.getMinutes()) * 60 + d.getSeconds()) * 1e3 + d.getMilliseconds();
|
|
1255
|
+
var rescheduleToStart = (range, newStart) => {
|
|
1256
|
+
const start = toDate(range && range.start);
|
|
1257
|
+
const target = toDate(newStart);
|
|
1258
|
+
if (!start || !target) return null;
|
|
1259
|
+
const end = toDate(range && range.end) || start;
|
|
1260
|
+
const dayDelta = calendarDayDelta(start, target);
|
|
1261
|
+
const timeDelta = msIntoDay(target) - msIntoDay(start);
|
|
1262
|
+
const endOnDay = addDays(end, dayDelta);
|
|
1263
|
+
if (!timeDelta) return { start: target, end: endOnDay };
|
|
1264
|
+
return {
|
|
1265
|
+
start: target,
|
|
1266
|
+
end: new Date(
|
|
1267
|
+
endOnDay.getFullYear(),
|
|
1268
|
+
endOnDay.getMonth(),
|
|
1269
|
+
endOnDay.getDate(),
|
|
1270
|
+
0,
|
|
1271
|
+
0,
|
|
1272
|
+
0,
|
|
1273
|
+
msIntoDay(endOnDay) + timeDelta
|
|
1274
|
+
)
|
|
1275
|
+
};
|
|
1276
|
+
};
|
|
1277
|
+
var applyDatePick = (start, value) => {
|
|
1278
|
+
if (!isDateValueObject(value)) return null;
|
|
1279
|
+
const s = toDate(start);
|
|
1280
|
+
return new Date(
|
|
1281
|
+
value.year,
|
|
1282
|
+
value.month,
|
|
1283
|
+
value.date,
|
|
1284
|
+
s ? s.getHours() : 0,
|
|
1285
|
+
s ? s.getMinutes() : 0,
|
|
1286
|
+
s ? s.getSeconds() : 0,
|
|
1287
|
+
s ? s.getMilliseconds() : 0
|
|
1288
|
+
);
|
|
1289
|
+
};
|
|
1290
|
+
var DEFAULT_RESCHEDULE_PRESETS = [
|
|
1291
|
+
{ label: "+1 hour", shift: { hours: 1 } },
|
|
1292
|
+
{ label: "+1 day", shift: { days: 1 } },
|
|
1293
|
+
{ label: "Next week", shift: { weeks: 1 } }
|
|
1294
|
+
];
|
|
1295
|
+
var normalizeRescheduleOptions = (options) => {
|
|
1296
|
+
if (!options) return [];
|
|
1297
|
+
if (options === true) return DEFAULT_RESCHEDULE_PRESETS;
|
|
1298
|
+
if (!Array.isArray(options)) return [];
|
|
1299
|
+
const out = [];
|
|
1300
|
+
for (const opt of options) {
|
|
1301
|
+
if (typeof opt === "function") {
|
|
1302
|
+
out.push({ label: opt.label || opt.name || "Reschedule", getStart: opt });
|
|
1303
|
+
} else if (opt && typeof opt === "object" && opt.label != null) {
|
|
1304
|
+
if (typeof opt.shift === "function") {
|
|
1305
|
+
out.push({ label: opt.label, getStart: opt.shift });
|
|
1306
|
+
} else if (typeof opt.getStart === "function") {
|
|
1307
|
+
out.push({ label: opt.label, getStart: opt.getStart });
|
|
1308
|
+
} else if (opt.shift && typeof opt.shift === "object") {
|
|
1309
|
+
out.push({ label: opt.label, shift: opt.shift });
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
return out;
|
|
1314
|
+
};
|
|
1315
|
+
var resolveRescheduleTarget = (range, option, fnArg) => {
|
|
1316
|
+
if (!range || !toDate(range.start) || !option) return null;
|
|
1317
|
+
if (typeof option.getStart === "function") {
|
|
1318
|
+
const next = toDate(option.getStart(fnArg !== void 0 ? fnArg : range));
|
|
1319
|
+
return next ? rescheduleToStart(range, next) : null;
|
|
1320
|
+
}
|
|
1321
|
+
if (option.shift && typeof option.shift === "object") {
|
|
1322
|
+
return shiftEvent(range, option.shift);
|
|
1323
|
+
}
|
|
1324
|
+
return null;
|
|
1325
|
+
};
|
|
1326
|
+
|
|
1327
|
+
// src/calendar/resourceLanes.js
|
|
1328
|
+
var resolveResourceId = (record, spec) => {
|
|
1329
|
+
if (record == null || spec == null) return null;
|
|
1330
|
+
const value = typeof spec === "function" ? spec(record) : record[spec];
|
|
1331
|
+
if (value == null || value === "") return null;
|
|
1332
|
+
return value;
|
|
1333
|
+
};
|
|
1334
|
+
var buildResourceLanes = (events, options = {}) => {
|
|
1335
|
+
const {
|
|
1336
|
+
resources,
|
|
1337
|
+
resourceLabels,
|
|
1338
|
+
getId,
|
|
1339
|
+
showUnassignedLane = true,
|
|
1340
|
+
unassignedLabel = "Unassigned"
|
|
1341
|
+
} = options;
|
|
1342
|
+
const labelFor = (id) => {
|
|
1343
|
+
if (resourceLabels && resourceLabels[id] != null) return resourceLabels[id];
|
|
1344
|
+
return String(id);
|
|
1345
|
+
};
|
|
1346
|
+
const lanes = [];
|
|
1347
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
1348
|
+
const addLane = (id, label, declared) => {
|
|
1349
|
+
const key = String(id);
|
|
1350
|
+
if (byKey.has(key)) return byKey.get(key);
|
|
1351
|
+
const lane = { id, key, label, events: [], unassigned: false, declared };
|
|
1352
|
+
byKey.set(key, lane);
|
|
1353
|
+
lanes.push(lane);
|
|
1354
|
+
return lane;
|
|
1355
|
+
};
|
|
1356
|
+
(resources || []).forEach((resource) => {
|
|
1357
|
+
if (resource == null) return;
|
|
1358
|
+
if (typeof resource === "object") {
|
|
1359
|
+
addLane(resource.id, resource.label != null ? resource.label : labelFor(resource.id), true);
|
|
1360
|
+
} else {
|
|
1361
|
+
addLane(resource, labelFor(resource), true);
|
|
1362
|
+
}
|
|
1363
|
+
});
|
|
1364
|
+
const unassigned = {
|
|
1365
|
+
id: null,
|
|
1366
|
+
key: "__unassigned__",
|
|
1367
|
+
label: unassignedLabel,
|
|
1368
|
+
events: [],
|
|
1369
|
+
unassigned: true,
|
|
1370
|
+
declared: false
|
|
1371
|
+
};
|
|
1372
|
+
(events || []).forEach((event) => {
|
|
1373
|
+
const id = getId ? getId(event) : null;
|
|
1374
|
+
if (id == null || id === "") {
|
|
1375
|
+
unassigned.events.push(event);
|
|
1376
|
+
return;
|
|
1377
|
+
}
|
|
1378
|
+
const lane = byKey.get(String(id)) || addLane(id, labelFor(id), false);
|
|
1379
|
+
lane.events.push(event);
|
|
1380
|
+
});
|
|
1381
|
+
if (showUnassignedLane && unassigned.events.length > 0) lanes.push(unassigned);
|
|
1382
|
+
return lanes;
|
|
1383
|
+
};
|
|
1384
|
+
var eventsIntersectingRange = (events, rangeStart, rangeEnd) => {
|
|
1385
|
+
const rs = rangeStart.getTime();
|
|
1386
|
+
const re = rangeEnd.getTime();
|
|
1387
|
+
return (events || []).filter((event) => {
|
|
1388
|
+
if (!event || !event.start) return false;
|
|
1389
|
+
const es = event.start.getTime();
|
|
1390
|
+
const ee = (event.end || event.start).getTime();
|
|
1391
|
+
return es <= re && ee >= rs;
|
|
1392
|
+
});
|
|
1393
|
+
};
|
|
1394
|
+
var laneEventsForDay = (events, day) => eventsIntersectingRange(events, startOfDay(day), endOfDay(day)).sort(
|
|
1395
|
+
(a, b) => a.start.getTime() - b.start.getTime()
|
|
1396
|
+
);
|
|
1397
|
+
|
|
1265
1398
|
// src/calendar/Calendar.jsx
|
|
1266
1399
|
var DEFAULT_MAX_EVENTS_PER_DAY = 3;
|
|
1267
1400
|
var ALL_VIEWS = ["month", "week", "day", "agenda"];
|
|
1401
|
+
var ALL_VIEWS_WITH_RESOURCE = ["month", "week", "day", "resource", "agenda"];
|
|
1268
1402
|
var DEFAULT_DAY_START_HOUR = 8;
|
|
1269
1403
|
var DEFAULT_DAY_END_HOUR = 20;
|
|
1270
1404
|
var DEFAULT_TIME_ZONES = [
|
|
@@ -1300,7 +1434,8 @@ var VIEW_LABELS = {
|
|
|
1300
1434
|
month: "Month",
|
|
1301
1435
|
week: "Week",
|
|
1302
1436
|
day: "Day",
|
|
1303
|
-
agenda: "Agenda"
|
|
1437
|
+
agenda: "Agenda",
|
|
1438
|
+
resource: "Resource"
|
|
1304
1439
|
};
|
|
1305
1440
|
var DEFAULT_LABELS3 = {
|
|
1306
1441
|
today: "Today",
|
|
@@ -1317,7 +1452,11 @@ var DEFAULT_LABELS3 = {
|
|
|
1317
1452
|
errorMessage: "An error occurred while loading events.",
|
|
1318
1453
|
dayDetailTitle: (label) => label,
|
|
1319
1454
|
open: "Open",
|
|
1320
|
-
allDay: "All day"
|
|
1455
|
+
allDay: "All day",
|
|
1456
|
+
reschedule: "Reschedule",
|
|
1457
|
+
pickDate: "Pick date",
|
|
1458
|
+
unassigned: "Unassigned",
|
|
1459
|
+
resource: "Resource"
|
|
1321
1460
|
};
|
|
1322
1461
|
var DEFAULT_EVENT_FIELDS = {
|
|
1323
1462
|
id: "id",
|
|
@@ -1352,11 +1491,30 @@ var STATUS_VARIANT = {
|
|
|
1352
1491
|
error: "danger",
|
|
1353
1492
|
danger: "danger"
|
|
1354
1493
|
};
|
|
1494
|
+
var TAG_VARIANT = {
|
|
1495
|
+
default: "default",
|
|
1496
|
+
info: "info",
|
|
1497
|
+
success: "success",
|
|
1498
|
+
warning: "warning",
|
|
1499
|
+
error: "error",
|
|
1500
|
+
danger: "error"
|
|
1501
|
+
};
|
|
1502
|
+
var MONTH_EVENT_STYLES = /* @__PURE__ */ new Set(["statusTag", "tag"]);
|
|
1503
|
+
var monthLabelMaxChars = (style) => {
|
|
1504
|
+
const overhead = style === "tag" ? 34 : 46;
|
|
1505
|
+
return Math.max(6, Math.floor((MONTH_COL_WIDTH - overhead) / 6.6));
|
|
1506
|
+
};
|
|
1507
|
+
var truncateMonthLabel = (value, max) => {
|
|
1508
|
+
const s = String(value == null ? "" : value);
|
|
1509
|
+
if (!max || s.length <= max) return s;
|
|
1510
|
+
return s.slice(0, max).trimEnd();
|
|
1511
|
+
};
|
|
1355
1512
|
var MONTH_COL_WIDTH = 160;
|
|
1356
1513
|
var TIMEGRID_DAY_COL = 150;
|
|
1357
1514
|
var TIMEGRID_DAY_COL_SINGLE = 560;
|
|
1515
|
+
var RESOURCE_LABEL_COL_WIDTH = "min";
|
|
1358
1516
|
var HOUR_SLOT_HEIGHT = 64;
|
|
1359
|
-
var EventDetail = ({ event, labels }) => {
|
|
1517
|
+
var EventDetail = ({ event, labels, reschedule, idSuffix = "" }) => {
|
|
1360
1518
|
const { start, end, title, subtitle, href } = event;
|
|
1361
1519
|
let when = "";
|
|
1362
1520
|
if (start) {
|
|
@@ -1370,11 +1528,27 @@ var EventDetail = ({ event, labels }) => {
|
|
|
1370
1528
|
when = `${formatDayTitle(start)} \u2013 ${formatDayTitle(end)}`;
|
|
1371
1529
|
}
|
|
1372
1530
|
}
|
|
1373
|
-
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "column", gap: "xs" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { format: { fontWeight: "demibold" } }, title || "--"), when ? /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { variant: "microcopy" }, when) : null, subtitle ? /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text,
|
|
1531
|
+
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "column", gap: "xs" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { format: { fontWeight: "demibold" }, truncate: true }, title || "--"), when ? /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { variant: "microcopy", truncate: true }, when) : null, subtitle ? /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { truncate: true }, subtitle) : null, href ? /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Link, { href: href.url, external: href.external }, labels.open) : null, reschedule ? /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Divider, null), /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { variant: "microcopy", format: { fontWeight: "demibold" } }, labels.reschedule), reschedule.options.length > 0 ? /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "row", gap: "xs", wrap: "wrap" }, reschedule.options.map((option, i) => /* @__PURE__ */ import_react5.default.createElement(
|
|
1532
|
+
import_ui_extensions5.Button,
|
|
1533
|
+
{
|
|
1534
|
+
key: `${option.label}-${i}`,
|
|
1535
|
+
size: "xs",
|
|
1536
|
+
variant: "secondary",
|
|
1537
|
+
onClick: () => reschedule.onPreset(event, option)
|
|
1538
|
+
},
|
|
1539
|
+
option.label
|
|
1540
|
+
))) : null, /* @__PURE__ */ import_react5.default.createElement(
|
|
1541
|
+
import_ui_extensions5.DateInput,
|
|
1542
|
+
{
|
|
1543
|
+
name: `cal-resched-${event.key}${idSuffix}`,
|
|
1544
|
+
label: labels.pickDate,
|
|
1545
|
+
onChange: (value) => reschedule.onPick(event, value)
|
|
1546
|
+
}
|
|
1547
|
+
)) : null);
|
|
1374
1548
|
};
|
|
1375
|
-
var buildOverlay = (event, mode, renderEventDetail, labels, idSuffix = "") => {
|
|
1549
|
+
var buildOverlay = (event, mode, renderEventDetail, labels, idSuffix = "", reschedule = null) => {
|
|
1376
1550
|
if (mode === "none") return void 0;
|
|
1377
|
-
const body = renderEventDetail ? renderEventDetail(event) : /* @__PURE__ */ import_react5.default.createElement(EventDetail, { event, labels });
|
|
1551
|
+
const body = renderEventDetail ? renderEventDetail(event) : /* @__PURE__ */ import_react5.default.createElement(EventDetail, { event, labels, reschedule, idSuffix });
|
|
1378
1552
|
const id = `cal-evt-${event.key}${idSuffix}`;
|
|
1379
1553
|
if (mode === "modal") {
|
|
1380
1554
|
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Modal, { id, title: event.title || labels.open, width: "small" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.ModalBody, null, body));
|
|
@@ -1382,46 +1556,34 @@ var buildOverlay = (event, mode, renderEventDetail, labels, idSuffix = "") => {
|
|
|
1382
1556
|
if (mode === "panel") {
|
|
1383
1557
|
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Panel, { id, title: event.title || labels.open, width: "small", variant: "modal" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.PanelBody, null, body));
|
|
1384
1558
|
}
|
|
1385
|
-
return /* @__PURE__ */ import_react5.default.createElement(import_experimental.Popover, { id, placement: "bottom" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Tile, { compact: true }, body));
|
|
1559
|
+
return /* @__PURE__ */ import_react5.default.createElement(import_experimental.Popover, { id, placement: "bottom", variant: "longform" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Tile, { compact: true }, body));
|
|
1386
1560
|
};
|
|
1387
|
-
var AgendaEventRow = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels }) => {
|
|
1561
|
+
var AgendaEventRow = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels, reschedule }) => {
|
|
1388
1562
|
const variant = VALID_VARIANTS.has(event.color) ? event.color : "default";
|
|
1389
|
-
const overlay = buildOverlay(event, overlayMode, renderEventDetail, labels, day ? `-ag${day.getTime()}` : "");
|
|
1563
|
+
const overlay = buildOverlay(event, overlayMode, renderEventDetail, labels, day ? `-ag${day.getTime()}` : "", reschedule);
|
|
1390
1564
|
const handleClick = onEventClick ? () => onEventClick(event.raw, event) : void 0;
|
|
1391
1565
|
const timeLabel = isAllDayEvent(event) ? labels.allDay : formatTime(event.start);
|
|
1392
1566
|
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "row", align: "center", gap: "sm" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Box, { flex: 2 }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "row", align: "center" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { variant: "microcopy", format: { fontWeight: "demibold" } }, timeLabel))), /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Box, { flex: 11 }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "row", align: "center", gap: "xs" }, /* @__PURE__ */ import_react5.default.createElement(ColorDot, { variant }), /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { truncate: true }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Link, { overlay, onClick: handleClick }, event.title || "--")))), event.subtitle ? /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Box, { flex: 4 }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "row", align: "center" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { variant: "microcopy", truncate: true }, event.subtitle))) : null);
|
|
1393
1567
|
};
|
|
1394
|
-
var
|
|
1395
|
-
var
|
|
1396
|
-
var MonthChip = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels }) => {
|
|
1568
|
+
var MONTH_SLOT_HEIGHT = 24;
|
|
1569
|
+
var MonthChip = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels, monthEventStyle, monthEventMaxChars, reschedule, idScope = "" }) => {
|
|
1397
1570
|
const isStartDay = !day || !event.start || isSameDay(event.start, day);
|
|
1398
|
-
const overlay = buildOverlay(event, overlayMode, renderEventDetail, labels, day ? `-m${day.getTime()}` : "");
|
|
1571
|
+
const overlay = buildOverlay(event, overlayMode, renderEventDetail, labels, day ? `-m${idScope}${day.getTime()}` : "", reschedule);
|
|
1399
1572
|
const handleClick = onEventClick ? () => onEventClick(event.raw, event) : void 0;
|
|
1400
1573
|
const variant = VALID_VARIANTS.has(event.color) ? event.color : "default";
|
|
1401
1574
|
const startHasTime = event.start && (event.start.getHours() !== 0 || event.start.getMinutes() !== 0);
|
|
1402
1575
|
const time = isStartDay && startHasTime ? `${formatTime(event.start)} ` : "";
|
|
1403
1576
|
const prefix = isStartDay ? "" : "\u2192 ";
|
|
1404
|
-
const
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
});
|
|
1410
|
-
return /* @__PURE__ */ import_react5.default.createElement(
|
|
1411
|
-
import_ui_extensions5.Image,
|
|
1412
|
-
{
|
|
1413
|
-
src: chip.src,
|
|
1414
|
-
width: chip.width,
|
|
1415
|
-
height: chip.height,
|
|
1416
|
-
alt: event.title || "",
|
|
1417
|
-
overlay,
|
|
1418
|
-
onClick: handleClick
|
|
1419
|
-
}
|
|
1420
|
-
);
|
|
1577
|
+
const maxChars = monthEventMaxChars != null ? monthEventMaxChars : monthLabelMaxChars(monthEventStyle);
|
|
1578
|
+
const label = truncateMonthLabel(`${prefix}${time}${event.title || "--"}`, maxChars);
|
|
1579
|
+
if (monthEventStyle === "tag") {
|
|
1580
|
+
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Tag, { variant: TAG_VARIANT[variant] || "default", overlay, onClick: handleClick }, label);
|
|
1581
|
+
}
|
|
1582
|
+
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Link, { overlay, onClick: handleClick }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.StatusTag, { variant: STATUS_VARIANT[variant] || "default" }, label));
|
|
1421
1583
|
};
|
|
1422
|
-
var DayListItem = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels }) => {
|
|
1584
|
+
var DayListItem = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels, reschedule, idScope = "" }) => {
|
|
1423
1585
|
const handleClick = onEventClick ? () => onEventClick(event.raw, event) : void 0;
|
|
1424
|
-
const overlay = buildOverlay(event, overlayMode, renderEventDetail, labels, day ? `-more${day.getTime()}` : "-more");
|
|
1586
|
+
const overlay = buildOverlay(event, overlayMode, renderEventDetail, labels, day ? `-more${idScope}${day.getTime()}` : "-more", reschedule);
|
|
1425
1587
|
const href = event.href;
|
|
1426
1588
|
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Button, { variant: "transparent", size: "sm", href: href ? href.url : void 0, overlay, onClick: handleClick }, event.title || "--");
|
|
1427
1589
|
};
|
|
@@ -1486,6 +1648,40 @@ var Toolbar = ({
|
|
|
1486
1648
|
}
|
|
1487
1649
|
));
|
|
1488
1650
|
};
|
|
1651
|
+
var DayChipStack = ({ day, events, maxEventsPerDay, chipProps, labels, idScope = "" }) => {
|
|
1652
|
+
const slotSpacer = makeSpacerDataUri(MONTH_SLOT_HEIGHT, 1);
|
|
1653
|
+
const shown = events.slice(0, maxEventsPerDay);
|
|
1654
|
+
const hasOverflow = events.length > maxEventsPerDay;
|
|
1655
|
+
const heightSpacer = /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Image, { src: slotSpacer.src, width: slotSpacer.width, height: slotSpacer.height, alt: "" });
|
|
1656
|
+
const slotRow = (key, content) => /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { key, direction: "row", align: "center", gap: "flush" }, heightSpacer, content);
|
|
1657
|
+
const slots = [];
|
|
1658
|
+
for (let i = 0; i < maxEventsPerDay; i++) {
|
|
1659
|
+
if (i < shown.length) {
|
|
1660
|
+
slots.push(slotRow(shown[i].key, /* @__PURE__ */ import_react5.default.createElement(MonthChip, { event: shown[i], day, idScope, ...chipProps })));
|
|
1661
|
+
} else {
|
|
1662
|
+
slots.push(/* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Image, { key: `sp-${i}`, src: slotSpacer.src, width: slotSpacer.width, height: slotSpacer.height, alt: "" }));
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
if (hasOverflow) {
|
|
1666
|
+
slots.push(
|
|
1667
|
+
slotRow(
|
|
1668
|
+
"more",
|
|
1669
|
+
/* @__PURE__ */ import_react5.default.createElement(
|
|
1670
|
+
import_ui_extensions5.Link,
|
|
1671
|
+
{
|
|
1672
|
+
overlay: /* @__PURE__ */ import_react5.default.createElement(import_experimental.Popover, { id: `cal-day-${idScope}${day.getTime()}`, placement: "top", variant: "longform" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Tile, { compact: true }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "column", gap: "sm" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "row", justify: "center", align: "center", gap: "xs" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { format: { fontWeight: "bold" } }, String(events.length)), /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { format: { fontWeight: "demibold" } }, labels.onThisDate)), /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Divider, null), events.map((event, i) => /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, { key: event.key }, /* @__PURE__ */ import_react5.default.createElement(DayListItem, { event, day, idScope, ...chipProps }), i < events.length - 1 ? /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Divider, null) : null)))))
|
|
1673
|
+
},
|
|
1674
|
+
labels.more(events.length - maxEventsPerDay)
|
|
1675
|
+
)
|
|
1676
|
+
)
|
|
1677
|
+
);
|
|
1678
|
+
} else {
|
|
1679
|
+
slots.push(
|
|
1680
|
+
/* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Image, { key: "more-sp", src: slotSpacer.src, width: slotSpacer.width, height: slotSpacer.height, alt: "" })
|
|
1681
|
+
);
|
|
1682
|
+
}
|
|
1683
|
+
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "column", gap: "xs" }, slots);
|
|
1684
|
+
};
|
|
1489
1685
|
var MonthView = ({
|
|
1490
1686
|
refDate,
|
|
1491
1687
|
now,
|
|
@@ -1500,49 +1696,21 @@ var MonthView = ({
|
|
|
1500
1696
|
}) => {
|
|
1501
1697
|
const headers = weekdayLabels(weekStartsOn, hideWeekends, true);
|
|
1502
1698
|
const today = now || /* @__PURE__ */ new Date();
|
|
1503
|
-
const spacer24 = makeSpacerDataUri(MONTH_CHIP_HEIGHT, MONTH_COL_WIDTH);
|
|
1504
1699
|
const renderCell = (day) => {
|
|
1505
1700
|
const dayEvents = eventsForDay(day);
|
|
1506
1701
|
const inMonth = isSameMonth(day, refDate);
|
|
1507
1702
|
const isToday = isSameDay(day, today);
|
|
1508
1703
|
if (renderDayCell) return renderDayCell(day, dayEvents);
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
/* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Image, { key: `sp-${i}`, src: spacer24.src, width: spacer24.width, height: spacer24.height, alt: "" })
|
|
1518
|
-
);
|
|
1704
|
+
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.AutoGrid, { columnWidth: MONTH_COL_WIDTH, gap: "flush" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "column", gap: "xs" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "row", align: "center", gap: "xs" }, isToday ? /* @__PURE__ */ import_react5.default.createElement(ColorDot, { variant: "info" }) : null, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { variant: "microcopy", format: { fontWeight: inMonth ? "demibold" : "regular" } }, String(day.getDate()))), /* @__PURE__ */ import_react5.default.createElement(
|
|
1705
|
+
DayChipStack,
|
|
1706
|
+
{
|
|
1707
|
+
day,
|
|
1708
|
+
events: dayEvents,
|
|
1709
|
+
maxEventsPerDay,
|
|
1710
|
+
chipProps,
|
|
1711
|
+
labels
|
|
1519
1712
|
}
|
|
1520
|
-
|
|
1521
|
-
if (hasOverflow) {
|
|
1522
|
-
const more = makeMoreDataUri({
|
|
1523
|
-
label: labels.more(dayEvents.length - maxEventsPerDay),
|
|
1524
|
-
width: MONTH_COL_WIDTH,
|
|
1525
|
-
height: MONTH_CHIP_HEIGHT
|
|
1526
|
-
});
|
|
1527
|
-
slots.push(
|
|
1528
|
-
/* @__PURE__ */ import_react5.default.createElement(
|
|
1529
|
-
import_ui_extensions5.Image,
|
|
1530
|
-
{
|
|
1531
|
-
key: "more",
|
|
1532
|
-
src: more.src,
|
|
1533
|
-
width: more.width,
|
|
1534
|
-
height: more.height,
|
|
1535
|
-
alt: labels.more(dayEvents.length - maxEventsPerDay),
|
|
1536
|
-
overlay: /* @__PURE__ */ import_react5.default.createElement(import_experimental.Popover, { id: `cal-day-${day.getTime()}`, placement: "top", variant: "longform" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Tile, { compact: true }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "column", gap: "sm" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "row", align: "center", gap: "sm" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Heading, null, String(dayEvents.length)), /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { format: { fontWeight: "demibold" } }, labels.onThisDate)), /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Divider, null), dayEvents.map((event, i) => /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, { key: event.key }, /* @__PURE__ */ import_react5.default.createElement(DayListItem, { event, day, ...chipProps }), i < dayEvents.length - 1 ? /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Divider, null) : null)))))
|
|
1537
|
-
}
|
|
1538
|
-
)
|
|
1539
|
-
);
|
|
1540
|
-
} else {
|
|
1541
|
-
slots.push(
|
|
1542
|
-
/* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Image, { key: "more-sp", src: spacer24.src, width: spacer24.width, height: spacer24.height, alt: "" })
|
|
1543
|
-
);
|
|
1544
|
-
}
|
|
1545
|
-
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "column", gap: "xs" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "row", align: "center", gap: "xs" }, isToday ? /* @__PURE__ */ import_react5.default.createElement(ColorDot, { variant: "info" }) : null, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { variant: "microcopy", format: { fontWeight: inMonth ? "demibold" : "regular" } }, String(day.getDate()))), slots);
|
|
1713
|
+
)));
|
|
1546
1714
|
};
|
|
1547
1715
|
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Table, { bordered: true, flush: true }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.TableHead, null, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.TableRow, null, headers.map((h4) => /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.TableHeader, { key: h4, width: "min", align: "center" }, h4.toUpperCase())))), /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.TableBody, null, weeks.map((week, wi) => {
|
|
1548
1716
|
const days = hideWeekends ? week.filter((d) => d.getDay() !== 0 && d.getDay() !== 6) : week;
|
|
@@ -1564,6 +1732,33 @@ var AgendaView = ({ rangeStart, rangeEnd, eventsForDay, chipProps, labels, rende
|
|
|
1564
1732
|
}
|
|
1565
1733
|
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "column", gap: "lg" }, days.map(({ day, events }) => /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { key: day.getTime(), direction: "column", gap: "sm" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "row", justify: "between", align: "end" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { format: { fontWeight: "demibold" } }, formatDayTitle(day)), /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { variant: "microcopy" }, `${events.length} ${events.length === 1 ? "event" : "events"}`)), /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Divider, null), events.map((event) => /* @__PURE__ */ import_react5.default.createElement(AgendaEventRow, { key: event.key, event, day, ...chipProps })))));
|
|
1566
1734
|
};
|
|
1735
|
+
var ResourceView = ({ days, now, lanes, maxEventsPerDay, chipProps, labels, renderEmptyState }) => {
|
|
1736
|
+
const today = now || /* @__PURE__ */ new Date();
|
|
1737
|
+
if (!lanes || lanes.length === 0) {
|
|
1738
|
+
if (renderEmptyState) return renderEmptyState({});
|
|
1739
|
+
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.EmptyState, { title: labels.noEventsTitle }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, null, labels.noEventsMessage));
|
|
1740
|
+
}
|
|
1741
|
+
const rangeStart = startOfDay(days[0]);
|
|
1742
|
+
const rangeEnd = endOfDay(days[days.length - 1]);
|
|
1743
|
+
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Table, { bordered: true, flush: true }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.TableHead, null, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.TableRow, null, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.TableHeader, { width: RESOURCE_LABEL_COL_WIDTH }, String(labels.resource).toUpperCase()), days.map((day) => {
|
|
1744
|
+
const isToday = isSameDay(day, today);
|
|
1745
|
+
const label = `${formatWeekdayShort(day)} ${formatMonthShort(day)} ${day.getDate()}`;
|
|
1746
|
+
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.TableHeader, { key: day.getTime(), width: "min", align: "center" }, isToday ? `${label} \xB7 Today` : label);
|
|
1747
|
+
}))), /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.TableBody, null, lanes.map((lane, laneIndex) => {
|
|
1748
|
+
const visible = eventsIntersectingRange(lane.events, rangeStart, rangeEnd);
|
|
1749
|
+
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.TableRow, { key: lane.key }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.TableCell, { width: RESOURCE_LABEL_COL_WIDTH }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "column", gap: "flush" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { format: { fontWeight: "demibold" } }, lane.label), /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { variant: "microcopy" }, `${visible.length} ${visible.length === 1 ? "event" : "events"}`))), days.map((day) => /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.TableCell, { key: day.getTime(), width: "min" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.AutoGrid, { columnWidth: MONTH_COL_WIDTH, gap: "flush" }, /* @__PURE__ */ import_react5.default.createElement(
|
|
1750
|
+
DayChipStack,
|
|
1751
|
+
{
|
|
1752
|
+
day,
|
|
1753
|
+
events: laneEventsForDay(visible, day),
|
|
1754
|
+
maxEventsPerDay,
|
|
1755
|
+
chipProps,
|
|
1756
|
+
labels,
|
|
1757
|
+
idScope: `r${laneIndex}-`
|
|
1758
|
+
}
|
|
1759
|
+
)))));
|
|
1760
|
+
})));
|
|
1761
|
+
};
|
|
1567
1762
|
var formatTimedDuration = (start, end) => {
|
|
1568
1763
|
const mins = Math.max(0, Math.round(((end || start).getTime() - start.getTime()) / 6e4));
|
|
1569
1764
|
const h4 = Math.floor(mins / 60);
|
|
@@ -1585,6 +1780,7 @@ var TimeGridView = ({ days, now, hours, dayStartHour, dayEndHour, eventsForDay,
|
|
|
1585
1780
|
const today = now || /* @__PURE__ */ new Date();
|
|
1586
1781
|
const centerDays = days.length === 1;
|
|
1587
1782
|
const dayColWidth = days.length === 1 ? TIMEGRID_DAY_COL_SINGLE : TIMEGRID_DAY_COL;
|
|
1783
|
+
const weekTitleMaxChars = Math.max(6, Math.floor((TIMEGRID_DAY_COL - 46) / 6.6));
|
|
1588
1784
|
const todayInView = days.some((d) => isSameDay(d, today));
|
|
1589
1785
|
const nowHour = today.getHours();
|
|
1590
1786
|
const dayData = days.map((day) => {
|
|
@@ -1610,7 +1806,8 @@ var TimeGridView = ({ days, now, hours, dayStartHour, dayEndHour, eventsForDay,
|
|
|
1610
1806
|
chipProps.overlayMode,
|
|
1611
1807
|
chipProps.renderEventDetail,
|
|
1612
1808
|
chipProps.labels,
|
|
1613
|
-
`-tg${mode}${hour}-${dayMs}
|
|
1809
|
+
`-tg${mode}${hour}-${dayMs}`,
|
|
1810
|
+
chipProps.reschedule
|
|
1614
1811
|
);
|
|
1615
1812
|
const handleClick = chipProps.onEventClick ? () => chipProps.onEventClick(e.raw, e) : void 0;
|
|
1616
1813
|
const variant = VALID_VARIANTS.has(e.color) ? e.color : "default";
|
|
@@ -1629,10 +1826,10 @@ var TimeGridView = ({ days, now, hours, dayStartHour, dayEndHour, eventsForDay,
|
|
|
1629
1826
|
} else if (mode === "cont") {
|
|
1630
1827
|
sub = `\u2191 cont. through ${endLabel}`;
|
|
1631
1828
|
}
|
|
1632
|
-
|
|
1829
|
+
const titleLabel = centerDays ? e.title || "--" : truncateMonthLabel(e.title || "--", weekTitleMaxChars);
|
|
1830
|
+
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { key: `${e.key}-${mode}-${hour}`, direction: "column", gap: "flush" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Link, { overlay, onClick: handleClick }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.StatusTag, { variant: STATUS_VARIANT[variant] || "default" }, titleLabel)), sub ? /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { variant: "microcopy" }, sub) : null);
|
|
1633
1831
|
};
|
|
1634
|
-
const
|
|
1635
|
-
const dayCell = (key, content) => /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.TableCell, { key, width: centerDays ? "max" : "min", align: "left" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "column", gap: "xs" }, content, centerDays ? null : /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Image, { src: daySpacer.src, width: daySpacer.width, height: daySpacer.height, alt: "" })));
|
|
1832
|
+
const dayCell = (key, content) => /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.TableCell, { key, width: centerDays ? "max" : "min", align: "left" }, centerDays ? /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "column", gap: "xs" }, content) : /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.AutoGrid, { columnWidth: dayColWidth, gap: "flush" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "column", gap: "xs" }, content)));
|
|
1636
1833
|
const slotSpacer = makeSpacerDataUri(HOUR_SLOT_HEIGHT, 1);
|
|
1637
1834
|
const emptyCell = null;
|
|
1638
1835
|
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Table, { bordered: true, flush: true, density: "compact" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.TableHead, null, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.TableRow, null, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.TableHeader, { width: "min" }, "TIME"), dayData.map(({ day }) => {
|
|
@@ -1688,9 +1885,21 @@ var Calendar = (props) => {
|
|
|
1688
1885
|
weekStartsOn = 0,
|
|
1689
1886
|
hideWeekends = false,
|
|
1690
1887
|
maxEventsPerDay = DEFAULT_MAX_EVENTS_PER_DAY,
|
|
1888
|
+
// month-grid event token style: "statusTag" (dot + text, default) | "tag" (pill)
|
|
1889
|
+
monthEventStyle = "statusTag",
|
|
1890
|
+
// max characters for a month-cell label before "…" (default derived per style)
|
|
1891
|
+
monthEventMaxChars,
|
|
1691
1892
|
// time grid (week / day)
|
|
1692
1893
|
dayStartHour = DEFAULT_DAY_START_HOUR,
|
|
1693
1894
|
dayEndHour = DEFAULT_DAY_END_HOUR,
|
|
1895
|
+
// resource / lane view (rows = resources, columns = the focused week's days)
|
|
1896
|
+
resources,
|
|
1897
|
+
resourceField,
|
|
1898
|
+
resourceLabels,
|
|
1899
|
+
showUnassignedLane = true,
|
|
1900
|
+
// drag-free reschedule (presets + date picker in the event-detail overlay)
|
|
1901
|
+
rescheduleOptions,
|
|
1902
|
+
onEventReschedule,
|
|
1694
1903
|
// timezone
|
|
1695
1904
|
timeZone: controlledTimeZone,
|
|
1696
1905
|
defaultTimeZone,
|
|
@@ -1729,10 +1938,12 @@ var Calendar = (props) => {
|
|
|
1729
1938
|
const fields = (0, import_react5.useMemo)(() => ({ ...DEFAULT_EVENT_FIELDS, ...eventFields || {} }), [eventFields]);
|
|
1730
1939
|
const [internalView, setInternalView] = (0, import_react5.useState)(defaultView);
|
|
1731
1940
|
const view = controlledView != null ? controlledView : internalView;
|
|
1941
|
+
const resourceEnabled = resources && resources.length > 0 || resourceField != null;
|
|
1732
1942
|
const enabledViews = (0, import_react5.useMemo)(() => {
|
|
1733
|
-
const
|
|
1734
|
-
|
|
1735
|
-
|
|
1943
|
+
const all = resourceEnabled ? ALL_VIEWS_WITH_RESOURCE : ALL_VIEWS;
|
|
1944
|
+
const base = viewsProp && viewsProp.length > 0 ? viewsProp : all;
|
|
1945
|
+
return base.filter((v) => all.includes(v));
|
|
1946
|
+
}, [viewsProp, resourceEnabled]);
|
|
1736
1947
|
const setView = (0, import_react5.useCallback)(
|
|
1737
1948
|
(next) => {
|
|
1738
1949
|
if (controlledView == null) setInternalView(next);
|
|
@@ -1757,7 +1968,9 @@ var Calendar = (props) => {
|
|
|
1757
1968
|
const focusedDate = (controlledFocusedDate != null ? toDate(controlledFocusedDate) : internalDate) || startOfDay(nowWall);
|
|
1758
1969
|
const stepFor = (0, import_react5.useCallback)(
|
|
1759
1970
|
(dir) => {
|
|
1760
|
-
if (view === "week" || view === "agenda"
|
|
1971
|
+
if (view === "week" || view === "agenda" || view === "resource") {
|
|
1972
|
+
return addDays(focusedDate, dir * 7);
|
|
1973
|
+
}
|
|
1761
1974
|
if (view === "day") return addDays(focusedDate, dir);
|
|
1762
1975
|
return addMonths(focusedDate, dir);
|
|
1763
1976
|
},
|
|
@@ -1784,7 +1997,7 @@ var Calendar = (props) => {
|
|
|
1784
1997
|
rangeEnd: endOfDay(flat[flat.length - 1])
|
|
1785
1998
|
};
|
|
1786
1999
|
}
|
|
1787
|
-
if (view === "week") {
|
|
2000
|
+
if (view === "week" || view === "resource") {
|
|
1788
2001
|
const days = buildWeekDays(focusedDate, weekStartsOn, hideWeekends);
|
|
1789
2002
|
return {
|
|
1790
2003
|
weeks: null,
|
|
@@ -1857,14 +2070,18 @@ var Calendar = (props) => {
|
|
|
1857
2070
|
);
|
|
1858
2071
|
const normalized = (0, import_react5.useMemo)(
|
|
1859
2072
|
() => (events || []).map((raw, index) => {
|
|
1860
|
-
const
|
|
1861
|
-
const
|
|
2073
|
+
const sourceStart = toDate(resolveField(raw, fields.start));
|
|
2074
|
+
const sourceEnd = toDate(resolveField(raw, fields.end));
|
|
2075
|
+
const start = toWallClock(sourceStart, timeZone);
|
|
2076
|
+
const endRaw = toWallClock(sourceEnd, timeZone);
|
|
1862
2077
|
const id = resolveField(raw, fields.id);
|
|
1863
2078
|
return {
|
|
1864
2079
|
key: id != null ? String(id) : `evt-${index}`,
|
|
1865
2080
|
id,
|
|
1866
2081
|
start,
|
|
1867
2082
|
end: endRaw || start,
|
|
2083
|
+
sourceStart,
|
|
2084
|
+
sourceEnd: sourceEnd || sourceStart,
|
|
1868
2085
|
title: resolveField(raw, fields.title),
|
|
1869
2086
|
subtitle: resolveField(raw, fields.subtitle),
|
|
1870
2087
|
color: resolveField(raw, fields.color),
|
|
@@ -1901,13 +2118,60 @@ var Calendar = (props) => {
|
|
|
1901
2118
|
}, [rangeKey]);
|
|
1902
2119
|
const title = (0, import_react5.useMemo)(() => {
|
|
1903
2120
|
if (view === "day") return formatDayTitle(focusedDate);
|
|
1904
|
-
if (view === "week" || view === "agenda") {
|
|
1905
|
-
const days = buildWeekDays(focusedDate, weekStartsOn, view
|
|
2121
|
+
if (view === "week" || view === "agenda" || view === "resource") {
|
|
2122
|
+
const days = buildWeekDays(focusedDate, weekStartsOn, view !== "agenda" && hideWeekends);
|
|
1906
2123
|
return formatRangeTitle(days[0], days[days.length - 1]);
|
|
1907
2124
|
}
|
|
1908
2125
|
return formatMonthTitle(focusedDate);
|
|
1909
2126
|
}, [view, focusedDate, weekStartsOn, hideWeekends]);
|
|
1910
|
-
const
|
|
2127
|
+
const handleReschedulePreset = (0, import_react5.useCallback)(
|
|
2128
|
+
(event, option) => {
|
|
2129
|
+
const target = resolveRescheduleTarget(
|
|
2130
|
+
{ start: event.sourceStart, end: event.sourceEnd },
|
|
2131
|
+
option,
|
|
2132
|
+
event
|
|
2133
|
+
);
|
|
2134
|
+
if (target && onEventReschedule) onEventReschedule(event.raw, target, event);
|
|
2135
|
+
},
|
|
2136
|
+
[onEventReschedule]
|
|
2137
|
+
);
|
|
2138
|
+
const handleReschedulePick = (0, import_react5.useCallback)(
|
|
2139
|
+
(event, value) => {
|
|
2140
|
+
const newStart = applyDatePick(event.sourceStart, value);
|
|
2141
|
+
if (!newStart) return;
|
|
2142
|
+
const target = rescheduleToStart({ start: event.sourceStart, end: event.sourceEnd }, newStart);
|
|
2143
|
+
if (target && onEventReschedule) onEventReschedule(event.raw, target, event);
|
|
2144
|
+
},
|
|
2145
|
+
[onEventReschedule]
|
|
2146
|
+
);
|
|
2147
|
+
const reschedule = (0, import_react5.useMemo)(() => {
|
|
2148
|
+
if (!rescheduleOptions) return null;
|
|
2149
|
+
return {
|
|
2150
|
+
options: normalizeRescheduleOptions(rescheduleOptions),
|
|
2151
|
+
onPreset: handleReschedulePreset,
|
|
2152
|
+
onPick: handleReschedulePick
|
|
2153
|
+
};
|
|
2154
|
+
}, [rescheduleOptions, handleReschedulePreset, handleReschedulePick]);
|
|
2155
|
+
const safeMonthEventStyle = MONTH_EVENT_STYLES.has(monthEventStyle) ? monthEventStyle : "statusTag";
|
|
2156
|
+
const chipProps = {
|
|
2157
|
+
overlayMode,
|
|
2158
|
+
renderEventDetail,
|
|
2159
|
+
onEventClick,
|
|
2160
|
+
labels,
|
|
2161
|
+
monthEventStyle: safeMonthEventStyle,
|
|
2162
|
+
monthEventMaxChars,
|
|
2163
|
+
reschedule
|
|
2164
|
+
};
|
|
2165
|
+
const resourceLaneData = (0, import_react5.useMemo)(() => {
|
|
2166
|
+
if (view !== "resource") return null;
|
|
2167
|
+
return buildResourceLanes(queried, {
|
|
2168
|
+
resources,
|
|
2169
|
+
resourceLabels,
|
|
2170
|
+
getId: (e) => resolveResourceId(e.raw, resourceField),
|
|
2171
|
+
showUnassignedLane,
|
|
2172
|
+
unassignedLabel: labels.unassigned
|
|
2173
|
+
});
|
|
2174
|
+
}, [view, queried, resources, resourceLabels, resourceField, showUnassignedLane, labels]);
|
|
1911
2175
|
const timeZoneOptions = (0, import_react5.useMemo)(() => {
|
|
1912
2176
|
if (!showTimeZoneSelect) return null;
|
|
1913
2177
|
const base = (timeZoneOptionsProp && timeZoneOptionsProp.length ? timeZoneOptionsProp : DEFAULT_TIME_ZONES).map(
|
|
@@ -1968,6 +2232,19 @@ var Calendar = (props) => {
|
|
|
1968
2232
|
labels
|
|
1969
2233
|
}
|
|
1970
2234
|
);
|
|
2235
|
+
} else if (view === "resource") {
|
|
2236
|
+
body = /* @__PURE__ */ import_react5.default.createElement(
|
|
2237
|
+
ResourceView,
|
|
2238
|
+
{
|
|
2239
|
+
days: gridDays,
|
|
2240
|
+
now: nowWall,
|
|
2241
|
+
lanes: resourceLaneData,
|
|
2242
|
+
maxEventsPerDay,
|
|
2243
|
+
chipProps,
|
|
2244
|
+
labels,
|
|
2245
|
+
renderEmptyState
|
|
2246
|
+
}
|
|
2247
|
+
);
|
|
1971
2248
|
} else if (view === "week" || view === "day") {
|
|
1972
2249
|
body = /* @__PURE__ */ import_react5.default.createElement(
|
|
1973
2250
|
TimeGridView,
|
|
@@ -1997,6 +2274,7 @@ var Calendar = (props) => {
|
|
|
1997
2274
|
}
|
|
1998
2275
|
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { direction: "column", gap: "sm" }, toolbar, body);
|
|
1999
2276
|
};
|
|
2277
|
+
Calendar.displayName = "Calendar";
|
|
2000
2278
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2001
2279
|
0 && (module.exports = {
|
|
2002
2280
|
Calendar
|